From 5f3ed207fad68c4ce4e399592f8abc3262469f63 Mon Sep 17 00:00:00 2001 From: "Elijah C. Voigt" Date: Mon, 6 May 2024 20:05:04 -0700 Subject: [PATCH] Shdaow example + fixed shadows Turns out one of the two things I fucked with caused the shadows to be borked! What are the odds! (very high) --- assets/shaders/extended_material.wgsl | 61 +++++++++++++++++ examples/shadow.rs | 95 ++++++++++++++++++++++++++- src/display3d.rs | 8 ++- 3 files changed, 160 insertions(+), 4 deletions(-) create mode 100644 assets/shaders/extended_material.wgsl diff --git a/assets/shaders/extended_material.wgsl b/assets/shaders/extended_material.wgsl new file mode 100644 index 0000000..59edaf6 --- /dev/null +++ b/assets/shaders/extended_material.wgsl @@ -0,0 +1,61 @@ +// Source: https://github.com/bevyengine/bevy/blob/4f9f987099224ca41aab91a582b80fca8eb969f8/assets/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 my_extended_material: MyExtendedMaterial; + +@fragment +fn fragment( + in: VertexOutput, + @builtin(front_facing) is_front: bool, +) -> FragmentOutput { + // generate a PbrInput struct from the StandardMaterial bindings + var pbr_input = pbr_input_from_standard_material(in, is_front); + + // we can optionally modify the input before lighting and alpha_discard is applied + pbr_input.material.base_color.b = pbr_input.material.base_color.r; + + // alpha discard + pbr_input.material.base_color = alpha_discard(pbr_input.material, pbr_input.material.base_color); + +#ifdef PREPASS_PIPELINE + // in deferred mode we can't modify anything after that, as lighting is run in a separate fullscreen shader. + let out = deferred_output(in, pbr_input); +#else + var out: FragmentOutput; + // apply lighting + out.color = apply_pbr_lighting(pbr_input); + + // we can optionally modify the lit color before post-processing is applied + out.color = vec4(vec4(out.color * f32(my_extended_material.quantize_steps))) / f32(my_extended_material.quantize_steps); + + // apply in-shader post processing (fog, alpha-premultiply, and also tonemapping, debanding if the camera is non-hdr) + // note this does not include fullscreen postprocessing effects like bloom. + out.color = main_pass_post_lighting_processing(pbr_input, out.color); + + // we can optionally modify the final result here + out.color = out.color * 2.0; +#endif + + return out; +} \ No newline at end of file diff --git a/examples/shadow.rs b/examples/shadow.rs index a35302f..9d14d95 100644 --- a/examples/shadow.rs +++ b/examples/shadow.rs @@ -1,18 +1,42 @@ -use bevy::prelude::*; +use bevy::{pbr::{ExtendedMaterial, MaterialExtension}, prelude::*, render::render_resource::{AsBindGroup, ShaderRef}}; + fn main() { App::new() .add_plugins(DefaultPlugins) + .add_plugins(MaterialPlugin::::default()) + .insert_resource(Speed(0.3)) .add_systems(Startup, init) .add_systems(Update, add_shadows) + .add_systems(Update, process_material) + .add_systems(Update, rotate_monkey) .run(); } -fn init(server: Res, mut commands: Commands) { +fn init( + server: Res, + mut meshes: ResMut>, + mut monkey_materials: ResMut>, + mut commands: Commands +) { commands.spawn(SceneBundle { scene: server.load("models/shadow-example.gltf#Scene0"), ..default() }); + + commands.spawn(MaterialMeshBundle { + mesh: meshes.add(Sphere::new(1.0)), + transform: Transform::from_xyz(0.0, 0.5, 0.0), + material: monkey_materials.add(ExtendedMaterial { + base: StandardMaterial { + base_color: Color::RED.into(), + alpha_mode: AlphaMode::Mask(1.0), + ..Default::default() + }, + extension: MonkeyMaterialExtension { percentage: 0.5 }, + }), + ..default() + }); } fn add_shadows( @@ -20,6 +44,7 @@ fn add_shadows( mut commands: Commands, ) { lights.iter_mut().for_each(|(e, mut l)| { + info!("Fixing up shadows"); l.shadows_enabled = true; let config: bevy::pbr::CascadeShadowConfig = @@ -27,3 +52,69 @@ fn add_shadows( commands.entity(e).insert(config); }); } + +type MonkeyMaterial = ExtendedMaterial; + +#[derive(Asset, AsBindGroup, Reflect, Debug, Clone)] +struct MonkeyMaterialExtension { + #[uniform(100)] + percentage: f32, +} + +impl MaterialExtension for MonkeyMaterialExtension { + fn fragment_shader() -> ShaderRef { + "shaders/dissolve.wgsl".into() + } + + fn deferred_fragment_shader() -> ShaderRef { + "shaders/dissolve.wgsl".into() + } +} + +fn process_material( + query: Query<(Entity, &Handle, &Name), Added>>, + base_materials: Res>, + mut monkey_materials: ResMut>, + mut commands: Commands, +) { + query.iter().for_each(|(e, h, n)| { + info!("Extended Materials"); + let mut base = base_materials.get(h).unwrap().clone(); + + base.alpha_mode = AlphaMode::Mask(1.0); + // base.base_color = base.base_color.clone().with_a(0.0); + + let extension = MonkeyMaterialExtension { percentage: 0.5 }; + + let monkey_material = monkey_materials.add( + ExtendedMaterial { + base, extension + } + ); + commands + .entity(e) + .remove::>() + .insert(monkey_material); + }) +} + +#[derive(Resource)] +struct Speed(f32); + +fn rotate_monkey( + mut query: Query<(&mut Transform, &Name)>, + time: Res