array_texture/
array_texture.rs

1//! This example illustrates how to create a texture for use with a `texture_2d_array<f32>` shader
2//! uniform variable.
3
4use bevy::{
5    prelude::*, reflect::TypePath, render::render_resource::AsBindGroup, shader::ShaderRef,
6};
7
8/// This example uses a shader source file from the assets subdirectory
9const SHADER_ASSET_PATH: &str = "shaders/array_texture.wgsl";
10
11fn main() {
12    App::new()
13        .add_plugins((
14            DefaultPlugins,
15            MaterialPlugin::<ArrayTextureMaterial>::default(),
16        ))
17        .add_systems(Startup, setup)
18        .add_systems(Update, create_array_texture)
19        .run();
20}
21
22#[derive(Resource)]
23struct LoadingTexture {
24    is_loaded: bool,
25    handle: Handle<Image>,
26}
27
28fn setup(mut commands: Commands, asset_server: Res<AssetServer>) {
29    // Start loading the texture.
30    commands.insert_resource(LoadingTexture {
31        is_loaded: false,
32        handle: asset_server.load("textures/array_texture.png"),
33    });
34
35    // light
36    commands.spawn((
37        DirectionalLight::default(),
38        Transform::from_xyz(3.0, 2.0, 1.0).looking_at(Vec3::ZERO, Vec3::Y),
39    ));
40
41    // camera
42    commands.spawn((
43        Camera3d::default(),
44        Transform::from_xyz(5.0, 5.0, 5.0).looking_at(Vec3::new(1.5, 0.0, 0.0), Vec3::Y),
45    ));
46}
47
48fn create_array_texture(
49    mut commands: Commands,
50    asset_server: Res<AssetServer>,
51    mut loading_texture: ResMut<LoadingTexture>,
52    mut images: ResMut<Assets<Image>>,
53    mut meshes: ResMut<Assets<Mesh>>,
54    mut materials: ResMut<Assets<ArrayTextureMaterial>>,
55) {
56    if loading_texture.is_loaded
57        || !asset_server
58            .load_state(loading_texture.handle.id())
59            .is_loaded()
60    {
61        return;
62    }
63    loading_texture.is_loaded = true;
64    let image = images.get_mut(&loading_texture.handle).unwrap();
65
66    // Create a new array texture asset from the loaded texture.
67    let array_layers = 4;
68    image.reinterpret_stacked_2d_as_array(array_layers);
69
70    // Spawn some cubes using the array texture
71    let mesh_handle = meshes.add(Cuboid::default());
72    let material_handle = materials.add(ArrayTextureMaterial {
73        array_texture: loading_texture.handle.clone(),
74    });
75    for x in -5..=5 {
76        commands.spawn((
77            Mesh3d(mesh_handle.clone()),
78            MeshMaterial3d(material_handle.clone()),
79            Transform::from_xyz(x as f32 + 0.5, 0.0, 0.0),
80        ));
81    }
82}
83
84#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)]
85struct ArrayTextureMaterial {
86    #[texture(0, dimension = "2d_array")]
87    #[sampler(1)]
88    array_texture: Handle<Image>,
89}
90
91impl Material for ArrayTextureMaterial {
92    fn fragment_shader() -> ShaderRef {
93        SHADER_ASSET_PATH.into()
94    }
95}