Support Warning
WebGPU is currently only supported on Chrome starting with version 113, and only on desktop. If they don't work on
your configuration, you can check the WebGL2 examples
here.
extended_material.rs:
use bevy::{
color::palettes::basic::RED,
pbr::{ExtendedMaterial, MaterialExtension, OpaqueRendererMethod},
prelude::*,
render::render_resource::*,
};
fn main() {
App::new()
.add_plugins(DefaultPlugins)
.add_plugins(MaterialPlugin::<
ExtendedMaterial<StandardMaterial, MyExtension>,
>::default())
.add_systems(Startup, setup)
.add_systems(Update, rotate_things)
.run();
}
fn setup(
mut commands: Commands,
mut meshes: ResMut<Assets<Mesh>>,
mut materials: ResMut<Assets<ExtendedMaterial<StandardMaterial, MyExtension>>>,
) {
commands.spawn(MaterialMeshBundle {
mesh: meshes.add(Sphere::new(1.0)),
transform: Transform::from_xyz(0.0, 0.5, 0.0),
material: materials.add(ExtendedMaterial {
base: StandardMaterial {
base_color: RED.into(),
opaque_render_method: OpaqueRendererMethod::Auto,
..Default::default()
},
extension: MyExtension { quantize_steps: 3 },
}),
..default()
});
commands.spawn((
DirectionalLightBundle {
transform: Transform::from_xyz(1.0, 1.0, 1.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
},
Rotate,
));
commands.spawn(Camera3dBundle {
transform: Transform::from_xyz(-2.0, 2.5, 5.0).looking_at(Vec3::ZERO, Vec3::Y),
..default()
});
}
#[derive(Component)]
struct Rotate;
fn rotate_things(mut q: Query<&mut Transform, With<Rotate>>, time: Res<Time>) {
for mut t in &mut q {
t.rotate_y(time.delta_seconds());
}
}
#[derive(Asset, AsBindGroup, Reflect, Debug, Clone)]
struct MyExtension {
#[uniform(100)]
quantize_steps: u32,
}
impl MaterialExtension for MyExtension {
fn fragment_shader() -> ShaderRef {
"shaders/extended_material.wgsl".into()
}
fn deferred_fragment_shader() -> ShaderRef {
"shaders/extended_material.wgsl".into()
}
}
shaders/extended_material.wgsl:
#import bevy_pbr::{
pbr_fragment::pbr_input_from_standard_material,
pbr_functions::alpha_discard,
}
#ifdef PREPASS_PIPELINE
#import bevy_pbr::{
prepass_io::{VertexOutput, FragmentOutput},
pbr_deferred_functions::deferred_output,
}
#else
#import bevy_pbr::{
forward_io::{VertexOutput, FragmentOutput},
pbr_functions::{apply_pbr_lighting, main_pass_post_lighting_processing},
}
#endif
struct MyExtendedMaterial {
quantize_steps: u32,
}
@group(2) @binding(100)
var<uniform> my_extended_material: MyExtendedMaterial;
@fragment
fn fragment(
in: VertexOutput,
@builtin(front_facing) is_front: bool,
) -> FragmentOutput {
var pbr_input = pbr_input_from_standard_material(in, is_front);
pbr_input.material.base_color.b = pbr_input.material.base_color.r;
pbr_input.material.base_color = alpha_discard(pbr_input.material, pbr_input.material.base_color);
#ifdef PREPASS_PIPELINE
let out = deferred_output(in, pbr_input);
#else
var out: FragmentOutput;
out.color = apply_pbr_lighting(pbr_input);
out.color = vec4<f32>(vec4<u32>(out.color * f32(my_extended_material.quantize_steps))) / f32(my_extended_material.quantize_steps);
out.color = main_pass_post_lighting_processing(pbr_input, out.color);
out.color = out.color * 2.0;
#endif
return out;
}