shader_defs/
shader_defs.rs1use bevy::{
4 mesh::MeshVertexBufferLayoutRef,
5 pbr::{MaterialPipeline, MaterialPipelineKey},
6 prelude::*,
7 reflect::TypePath,
8 render::render_resource::{
9 AsBindGroup, RenderPipelineDescriptor, SpecializedMeshPipelineError,
10 },
11 shader::ShaderRef,
12};
13
14const SHADER_ASSET_PATH: &str = "shaders/shader_defs.wgsl";
16
17fn main() {
18 App::new()
19 .add_plugins((DefaultPlugins, MaterialPlugin::<CustomMaterial>::default()))
20 .add_systems(Startup, setup)
21 .run();
22}
23
24fn setup(
26 mut commands: Commands,
27 mut meshes: ResMut<Assets<Mesh>>,
28 mut materials: ResMut<Assets<CustomMaterial>>,
29) {
30 commands.spawn((
32 Mesh3d(meshes.add(Cuboid::default())),
33 MeshMaterial3d(materials.add(CustomMaterial {
34 color: LinearRgba::BLUE,
35 is_red: false,
36 })),
37 Transform::from_xyz(-1.0, 0.5, 0.0),
38 ));
39
40 commands.spawn((
42 Mesh3d(meshes.add(Cuboid::default())),
43 MeshMaterial3d(materials.add(CustomMaterial {
44 color: LinearRgba::GREEN,
45 is_red: true,
46 })),
47 Transform::from_xyz(1.0, 0.5, 0.0),
48 ));
49
50 commands.spawn((
52 Camera3d::default(),
53 Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
54 ));
55}
56
57impl Material for CustomMaterial {
58 fn fragment_shader() -> ShaderRef {
59 SHADER_ASSET_PATH.into()
60 }
61
62 fn specialize(
63 _pipeline: &MaterialPipeline,
64 descriptor: &mut RenderPipelineDescriptor,
65 _layout: &MeshVertexBufferLayoutRef,
66 key: MaterialPipelineKey<Self>,
67 ) -> Result<(), SpecializedMeshPipelineError> {
68 if key.bind_group_data.is_red {
69 let fragment = descriptor.fragment.as_mut().unwrap();
70 fragment.shader_defs.push("IS_RED".into());
71 }
72 Ok(())
73 }
74}
75
76#[derive(Asset, TypePath, AsBindGroup, Debug, Clone)]
78#[bind_group_data(CustomMaterialKey)]
79struct CustomMaterial {
80 #[uniform(0)]
81 color: LinearRgba,
82 is_red: bool,
83}
84
85#[repr(C)]
90#[derive(Eq, PartialEq, Hash, Copy, Clone)]
91struct CustomMaterialKey {
92 is_red: bool,
93}
94
95impl From<&CustomMaterial> for CustomMaterialKey {
96 fn from(material: &CustomMaterial) -> Self {
97 Self {
98 is_red: material.is_red,
99 }
100 }
101}