docs/bevy/examples/shader/shader_material_bindless.rs 2.5 K · 88 lines · raw · history

1 //! A material that uses bindless textures.
2
3 use bevy::prelude::*;
4 use bevy::render::render_resource::{AsBindGroup, ShaderType};
5 use bevy::shader::ShaderRef;
6
7 const SHADER_ASSET_PATH: &str = "shaders/bindless_material.wesl";
8
9 // `#[bindless(limit(4))]` indicates that we want Bevy to group materials into
10 // bind groups of at most 4 materials each.
11 // Note that we use the structure-level `#[uniform]` attribute to supply
12 // ordinary data to the shader.
13 #[derive(Asset, TypePath, AsBindGroup, Debug, Clone)]
14 #[uniform(0, BindlessMaterialUniform, binding_array(10))]
15 #[bindless(limit(4))]
16 struct BindlessMaterial {
17 color: LinearRgba,
18 // This will be exposed to the shader as a binding array of 4 textures and a
19 // binding array of 4 samplers.
20 #[texture(1)]
21 #[sampler(2)]
22 color_texture: Option<Handle<Image>>,
23 }
24
25 // This buffer will be presented to the shader as `@binding(10)`.
26 #[derive(ShaderType)]
27 struct BindlessMaterialUniform {
28 color: LinearRgba,
29 }
30
31 impl<'a> From<&'a BindlessMaterial> for BindlessMaterialUniform {
32 fn from(material: &'a BindlessMaterial) -> Self {
33 BindlessMaterialUniform {
34 color: material.color,
35 }
36 }
37 }
38
39 // The entry point.
40 fn main() {
41 App::new()
42 .add_plugins((
43 DefaultPlugins,
44 MaterialPlugin::<BindlessMaterial>::default(),
45 ))
46 .add_systems(Startup, setup)
47 .run();
48 }
49
50 // Creates a simple scene.
51 fn setup(
52 mut commands: Commands,
53 mut meshes: ResMut<Assets<Mesh>>,
54 mut materials: ResMut<Assets<BindlessMaterial>>,
55 asset_server: Res<AssetServer>,
56 ) {
57 // Add a cube with a blue tinted texture.
58 commands.spawn((
59 Mesh3d(meshes.add(Cuboid::default())),
60 MeshMaterial3d(materials.add(BindlessMaterial {
61 color: LinearRgba::BLUE,
62 color_texture: Some(asset_server.load("branding/bevy_logo_dark.png")),
63 })),
64 Transform::from_xyz(-2.0, 0.5, 0.0),
65 ));
66
67 // Add a cylinder with a red tinted texture.
68 commands.spawn((
69 Mesh3d(meshes.add(Cylinder::default())),
70 MeshMaterial3d(materials.add(BindlessMaterial {
71 color: LinearRgba::RED,
72 color_texture: Some(asset_server.load("branding/bevy_logo_light.png")),
73 })),
74 Transform::from_xyz(2.0, 0.5, 0.0),
75 ));
76
77 // Add a camera.
78 commands.spawn((
79 Camera3d::default(),
80 Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
81 ));
82 }
83
84 impl Material for BindlessMaterial {
85 fn fragment_shader() -> ShaderRef {
86 SHADER_ASSET_PATH.into()
87 }
88 }