You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add a system that changes one of the materials when space is pressed
Expand modified 2d shader_defs.rs
//! A shader that uses "shaders defs", which selectively toggle parts of a shader.use bevy::{
prelude::*,
reflect::TypePath,
render::{
mesh::MeshVertexBufferLayoutRef,
render_resource::{AsBindGroup,RenderPipelineDescriptor,ShaderRef,SpecializedMeshPipelineError,},},
sprite::{Material2d,Material2dKey,Material2dPlugin},};/// This example uses a shader source file from the assets subdirectoryconstSHADER_ASSET_PATH:&str = "shaders/shader_defs.wgsl";#[derive(Component)]structControllable;fnmain(){App::new().add_plugins((DefaultPlugins,Material2dPlugin::<CustomMaterial>::default(),)).add_systems(Startup, setup).add_systems(Update, control).run();}/// set up a simple 2d scenefnsetup(mutcommands:Commands,mutmeshes:ResMut<Assets<Mesh>>,mutmaterials:ResMut<Assets<CustomMaterial>>,){// blue cube
commands.spawn((Mesh2d(meshes.add(Rectangle::default())),MeshMaterial2d(materials.add(CustomMaterial{color:LinearRgba::BLUE,is_red:false,})),Transform::from_xyz(-100.0,50.,0.0).with_scale(Vec2::splat(100.).extend(1.)),Controllable,));// red cube (with green color overridden by the IS_RED "shader def")
commands.spawn((Mesh2d(meshes.add(Rectangle::default())),MeshMaterial2d(materials.add(CustomMaterial{color:LinearRgba::GREEN,is_red:true,})),Transform::from_xyz(100.0,50.,0.0).with_scale(Vec2::splat(100.).extend(1.)),));// camera
commands.spawn(Camera2d::default());}fncontrol(handles:Query<&MeshMaterial2d<CustomMaterial>,With<Controllable>>,mutmaterials:ResMut<Assets<CustomMaterial>>,input:Res<ButtonInput<KeyCode>>,){if !input.just_pressed(KeyCode::Space){return;}for handle in&handles {letSome(mat) = materials.get_mut(handle)else{continue;};
mat.is_red = !mat.is_red;}}implMaterial2dforCustomMaterial{fnfragment_shader() -> ShaderRef{SHADER_ASSET_PATH.into()}fnspecialize(descriptor:&mutRenderPipelineDescriptor,_layout:&MeshVertexBufferLayoutRef,key:Material2dKey<Self>,) -> Result<(),SpecializedMeshPipelineError>{if key.bind_group_data.is_red{let fragment = descriptor.fragment.as_mut().unwrap();
fragment.shader_defs.push("IS_RED".into());}Ok(())}}// This is the struct that will be passed to your shader#[derive(Asset,TypePath,AsBindGroup,Debug,Clone)]#[bind_group_data(CustomMaterialKey)]structCustomMaterial{#[uniform(0)]color:LinearRgba,is_red:bool,}// This key is used to identify a specific permutation of this material pipeline.// In this case, we specialize on whether or not to configure the "IS_RED" shader def.// Specialization keys should be kept as small / cheap to hash as possible,// as they will be used to look up the pipeline for each drawn entity with this material type.#[derive(Eq,PartialEq,Hash,Clone)]structCustomMaterialKey{is_red:bool,}implFrom<&CustomMaterial>forCustomMaterialKey{fnfrom(material:&CustomMaterial) -> Self{Self{is_red: material.is_red,}}}
cargo run --example shader_defs
What went wrong
Left square should toggle between blue and red.
Instead, the square only changes on the first press. After that, it stays red.
Additional information
@hukasu may be investigating a related but different bug. Credit to them for the discovery.
After doing some light archaeology, It seems to me like 2d is missing the following:
But there appears to be more to the story, because adding those results in some errors I don't understand.
This does work in 3d.
Expand 3d NON-repro
//! A shader that uses "shaders defs", which selectively toggle parts of a shader.use bevy::{
pbr::{MaterialPipeline,MaterialPipelineKey},
prelude::*,
reflect::TypePath,
render::{
mesh::MeshVertexBufferLayoutRef,
render_resource::{AsBindGroup,RenderPipelineDescriptor,ShaderRef,SpecializedMeshPipelineError,},},};/// This example uses a shader source file from the assets subdirectoryconstSHADER_ASSET_PATH:&str = "shaders/shader_defs.wgsl";#[derive(Component)]structControllable;fnmain(){App::new().add_plugins((DefaultPlugins,MaterialPlugin::<CustomMaterial>::default())).add_systems(Startup, setup).add_systems(Update, control).run();}/// set up a simple 3D scenefnsetup(mutcommands:Commands,mutmeshes:ResMut<Assets<Mesh>>,mutmaterials:ResMut<Assets<CustomMaterial>>,){// blue cube
commands.spawn((Mesh3d(meshes.add(Cuboid::default())),MeshMaterial3d(materials.add(CustomMaterial{color:LinearRgba::BLUE,is_red:false,})),Transform::from_xyz(-1.0,0.5,0.0),Controllable,));// red cube (with green color overridden by the IS_RED "shader def")
commands.spawn((Mesh3d(meshes.add(Cuboid::default())),MeshMaterial3d(materials.add(CustomMaterial{color:LinearRgba::GREEN,is_red:true,})),Transform::from_xyz(1.0,0.5,0.0),));// camera
commands.spawn((Camera3d::default(),Transform::from_xyz(-2.0,2.5,5.0).looking_at(Vec3::ZERO,Vec3::Y),));}fncontrol(handles:Query<&MeshMaterial3d<CustomMaterial>,With<Controllable>>,mutmaterials:ResMut<Assets<CustomMaterial>>,input:Res<ButtonInput<KeyCode>>,){if !input.just_pressed(KeyCode::Space){return;}for handle in&handles {letSome(mat) = materials.get_mut(handle)else{continue;};
mat.is_red = !mat.is_red;}}implMaterialforCustomMaterial{fnfragment_shader() -> ShaderRef{SHADER_ASSET_PATH.into()}fnspecialize(_pipeline:&MaterialPipeline<Self>,descriptor:&mutRenderPipelineDescriptor,_layout:&MeshVertexBufferLayoutRef,key:MaterialPipelineKey<Self>,) -> Result<(),SpecializedMeshPipelineError>{if key.bind_group_data.is_red{let fragment = descriptor.fragment.as_mut().unwrap();
fragment.shader_defs.push("IS_RED".into());}Ok(())}}// This is the struct that will be passed to your shader#[derive(Asset,TypePath,AsBindGroup,Debug,Clone)]#[bind_group_data(CustomMaterialKey)]structCustomMaterial{#[uniform(0)]color:LinearRgba,is_red:bool,}// This key is used to identify a specific permutation of this material pipeline.// In this case, we specialize on whether or not to configure the "IS_RED" shader def.// Specialization keys should be kept as small / cheap to hash as possible,// as they will be used to look up the pipeline for each drawn entity with this material type.#[derive(Eq,PartialEq,Hash,Clone)]structCustomMaterialKey{is_red:bool,}implFrom<&CustomMaterial>forCustomMaterialKey{fnfrom(material:&CustomMaterial) -> Self{Self{is_red: material.is_red,}}}
The text was updated successfully, but these errors were encountered:
# Objective
- #17787 removed sweeping of binned render phases from 2D by accident
due to them not using the `BinnedRenderPhasePlugin`.
- Fixes#17885
## Solution
- Schedule `sweep_old_entities` in `QueueSweep` like
`BinnedRenderPhasePlugin` does, but for 2D where that plugin is not
used.
## Testing
Tested with the modified `shader_defs` example in #17885 .
Bevy version
main, bisected to #17787
Relevant system information
SystemInfo { os: "macOS 15.3 Sequoia", kernel: "24.3.0", cpu: "Apple M4 Max", core_count: "16", memory: "64.0 GiB" }
AdapterInfo { name: "Apple M4 Max", vendor: 0, device: 0, device_type: IntegratedGpu, driver: "", driver_info: "", backend: Metal }
What you did
Modified the
shader_defs
example:Expand modified 2d
shader_defs.rs
cargo run --example shader_defs
What went wrong
Left square should toggle between blue and red.
Instead, the square only changes on the first press. After that, it stays red.
Additional information
Expand 3d NON-repro
The text was updated successfully, but these errors were encountered: