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