From 4c6cf0d737b7e14bed5c0f704b3a89fdcde52922 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Thu, 20 Jul 2023 21:39:41 +0300 Subject: [PATCH] example-runner-ash: use NumPad +/- to control `sky-shader`'s "sun intensity" through a specialization constant. --- examples/runners/ash/src/main.rs | 31 ++++++++++++++++++++++++++ examples/runners/cpu/src/main.rs | 2 +- examples/shaders/sky-shader/src/lib.rs | 22 +++++++++++++----- 3 files changed, 49 insertions(+), 6 deletions(-) diff --git a/examples/runners/ash/src/main.rs b/examples/runners/ash/src/main.rs index 9ff4430b60..03c2e1111a 100644 --- a/examples/runners/ash/src/main.rs +++ b/examples/runners/ash/src/main.rs @@ -187,6 +187,19 @@ pub fn main() { }); } } + Some(key @ (VirtualKeyCode::NumpadAdd | VirtualKeyCode::NumpadSubtract)) => { + let factor = + &mut ctx.sky_fs_spec_id_0x5007_sun_intensity_extra_spec_const_factor; + *factor = if key == VirtualKeyCode::NumpadAdd { + factor.saturating_add(1) + } else { + factor.saturating_sub(1) + }; + + // HACK(eddyb) to see any changes, re-specializing the + // shader module is needed (e.g. during pipeline rebuild). + ctx.rebuild_pipelines(vk::PipelineCache::null()); + } _ => *control_flow = ControlFlow::Wait, }, WindowEvent::Resized(_) => { @@ -657,6 +670,9 @@ pub struct RenderCtx { pub rendering_paused: bool, pub recompiling_shaders: bool, pub start: std::time::Instant, + + // NOTE(eddyb) this acts like an integration test for specialization constants. + pub sky_fs_spec_id_0x5007_sun_intensity_extra_spec_const_factor: u32, } impl RenderCtx { @@ -702,6 +718,8 @@ impl RenderCtx { rendering_paused: false, recompiling_shaders: false, start: std::time::Instant::now(), + + sky_fs_spec_id_0x5007_sun_intensity_extra_spec_const_factor: 100, } } @@ -723,6 +741,18 @@ impl RenderCtx { } pub fn rebuild_pipelines(&mut self, pipeline_cache: vk::PipelineCache) { + // NOTE(eddyb) this acts like an integration test for specialization constants. + let spec_const_entries = [vk::SpecializationMapEntry::builder() + .constant_id(0x5007) + .offset(0) + .size(4) + .build()]; + let spec_const_data = + u32::to_le_bytes(self.sky_fs_spec_id_0x5007_sun_intensity_extra_spec_const_factor); + let specialization_info = vk::SpecializationInfo::builder() + .map_entries(&spec_const_entries) + .data(&spec_const_data); + self.cleanup_pipelines(); let pipeline_layout = self.create_pipeline_layout(); let viewport = vk::PipelineViewportStateCreateInfo::builder() @@ -754,6 +784,7 @@ impl RenderCtx { module: *frag_module, p_name: (*frag_name).as_ptr(), stage: vk::ShaderStageFlags::FRAGMENT, + p_specialization_info: &*specialization_info, ..Default::default() }, ])) diff --git a/examples/runners/cpu/src/main.rs b/examples/runners/cpu/src/main.rs index 7fccbc6975..30c12a9420 100644 --- a/examples/runners/cpu/src/main.rs +++ b/examples/runners/cpu/src/main.rs @@ -141,7 +141,7 @@ fn main() { * vec2(WIDTH as f32, HEIGHT as f32); // evaluate the fragment shader for the specific pixel - let color = shader_module::fs(&push_constants, frag_coord); + let color = shader_module::fs(&push_constants, frag_coord, 1); color_u32_from_vec4(color) }) diff --git a/examples/shaders/sky-shader/src/lib.rs b/examples/shaders/sky-shader/src/lib.rs index 4bebaf38f3..5096df0dd9 100644 --- a/examples/shaders/sky-shader/src/lib.rs +++ b/examples/shaders/sky-shader/src/lib.rs @@ -71,7 +71,7 @@ fn sun_intensity(zenith_angle_cos: f32) -> f32 { ) } -fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 { +fn sky(dir: Vec3, sun_position: Vec3, sun_intensity_extra_spec_const_factor: u32) -> Vec3 { let up = vec3(0.0, 1.0, 0.0); let sunfade = 1.0 - (1.0 - saturate(sun_position.y / 450000.0).exp()); let rayleigh_coefficient = RAYLEIGH - (1.0 * (1.0 - sunfade)); @@ -96,7 +96,12 @@ fn sky(dir: Vec3, sun_position: Vec3) -> Vec3 { let beta_r_theta = beta_r * rayleigh_phase(cos_theta * 0.5 + 0.5); let beta_m_theta = beta_m * henyey_greenstein_phase(cos_theta, MIE_DIRECTIONAL_G); - let sun_e = sun_intensity(sun_direction.dot(up)); + let sun_e = sun_intensity(sun_direction.dot(up)) + + // HACK(eddyb) this acts like an integration test for specialization constants, + // but the correct value is only obtained when this is a noop (multiplies by `1`). + * (sun_intensity_extra_spec_const_factor as f32 / 100.0); + let mut lin = pow( sun_e * ((beta_r_theta + beta_m_theta) / (beta_r + beta_m)) * (Vec3::splat(1.0) - fex), 1.5, @@ -130,7 +135,11 @@ fn get_ray_dir(uv: Vec2, pos: Vec3, look_at_pos: Vec3) -> Vec3 { (forward + uv.x * right + uv.y * up).normalize() } -pub fn fs(constants: &ShaderConstants, frag_coord: Vec2) -> Vec4 { +pub fn fs( + constants: &ShaderConstants, + frag_coord: Vec2, + sun_intensity_extra_spec_const_factor: u32, +) -> Vec4 { let mut uv = (frag_coord - 0.5 * vec2(constants.width as f32, constants.height as f32)) / constants.height as f32; uv.y = -uv.y; @@ -141,7 +150,7 @@ pub fn fs(constants: &ShaderConstants, frag_coord: Vec2) -> Vec4 { let dir = get_ray_dir(uv, eye_pos, sun_pos); // evaluate Preetham sky model - let color = sky(dir, sun_pos); + let color = sky(dir, sun_pos, sun_intensity_extra_spec_const_factor); // Tonemapping let color = color.max(Vec3::splat(0.0)).min(Vec3::splat(1024.0)); @@ -154,9 +163,12 @@ pub fn main_fs( #[spirv(frag_coord)] in_frag_coord: Vec4, #[spirv(push_constant)] constants: &ShaderConstants, output: &mut Vec4, + + // NOTE(eddyb) this acts like an integration test for specialization constants. + #[spirv(spec_constant(id = 0x5007, default = 100))] sun_intensity_extra_spec_const_factor: u32, ) { let frag_coord = vec2(in_frag_coord.x, in_frag_coord.y); - *output = fs(constants, frag_coord); + *output = fs(constants, frag_coord, sun_intensity_extra_spec_const_factor); } #[spirv(vertex)]