example-runner-ash: use NumPad +/- to control sky-shader's "sun intensity" through a specialization constant.

This commit is contained in:
Eduard-Mihai Burtescu 2023-07-20 21:39:41 +03:00 committed by Eduard-Mihai Burtescu
parent af2a9ee445
commit 4c6cf0d737
3 changed files with 49 additions and 6 deletions

View File

@ -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, _ => *control_flow = ControlFlow::Wait,
}, },
WindowEvent::Resized(_) => { WindowEvent::Resized(_) => {
@ -657,6 +670,9 @@ pub struct RenderCtx {
pub rendering_paused: bool, pub rendering_paused: bool,
pub recompiling_shaders: bool, pub recompiling_shaders: bool,
pub start: std::time::Instant, 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 { impl RenderCtx {
@ -702,6 +718,8 @@ impl RenderCtx {
rendering_paused: false, rendering_paused: false,
recompiling_shaders: false, recompiling_shaders: false,
start: std::time::Instant::now(), 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) { 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(); self.cleanup_pipelines();
let pipeline_layout = self.create_pipeline_layout(); let pipeline_layout = self.create_pipeline_layout();
let viewport = vk::PipelineViewportStateCreateInfo::builder() let viewport = vk::PipelineViewportStateCreateInfo::builder()
@ -754,6 +784,7 @@ impl RenderCtx {
module: *frag_module, module: *frag_module,
p_name: (*frag_name).as_ptr(), p_name: (*frag_name).as_ptr(),
stage: vk::ShaderStageFlags::FRAGMENT, stage: vk::ShaderStageFlags::FRAGMENT,
p_specialization_info: &*specialization_info,
..Default::default() ..Default::default()
}, },
])) ]))

View File

@ -141,7 +141,7 @@ fn main() {
* vec2(WIDTH as f32, HEIGHT as f32); * vec2(WIDTH as f32, HEIGHT as f32);
// evaluate the fragment shader for the specific pixel // 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) color_u32_from_vec4(color)
}) })

View File

@ -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 up = vec3(0.0, 1.0, 0.0);
let sunfade = 1.0 - (1.0 - saturate(sun_position.y / 450000.0).exp()); let sunfade = 1.0 - (1.0 - saturate(sun_position.y / 450000.0).exp());
let rayleigh_coefficient = RAYLEIGH - (1.0 * (1.0 - sunfade)); 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_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 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( let mut lin = pow(
sun_e * ((beta_r_theta + beta_m_theta) / (beta_r + beta_m)) * (Vec3::splat(1.0) - fex), sun_e * ((beta_r_theta + beta_m_theta) / (beta_r + beta_m)) * (Vec3::splat(1.0) - fex),
1.5, 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() (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)) let mut uv = (frag_coord - 0.5 * vec2(constants.width as f32, constants.height as f32))
/ constants.height as f32; / constants.height as f32;
uv.y = -uv.y; 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); let dir = get_ray_dir(uv, eye_pos, sun_pos);
// evaluate Preetham sky model // evaluate Preetham sky model
let color = sky(dir, sun_pos); let color = sky(dir, sun_pos, sun_intensity_extra_spec_const_factor);
// Tonemapping // Tonemapping
let color = color.max(Vec3::splat(0.0)).min(Vec3::splat(1024.0)); 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(frag_coord)] in_frag_coord: Vec4,
#[spirv(push_constant)] constants: &ShaderConstants, #[spirv(push_constant)] constants: &ShaderConstants,
output: &mut Vec4, 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); 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)] #[spirv(vertex)]