Skip to content

Commit

Permalink
fix: translate diffuse irradiance convolution shader (#141)
Browse files Browse the repository at this point in the history
* rewrite diffuse irradiance convolution shader in Rust

* remove WGSL version of diffuse irradiance convolution fragment shader
  • Loading branch information
schell authored Nov 26, 2024
1 parent 6126e62 commit 092c64c
Show file tree
Hide file tree
Showing 11 changed files with 266 additions and 188 deletions.
Binary file not shown.
Original file line number Diff line number Diff line change
@@ -0,0 +1,153 @@
var<private> global: vec4<f32>;
var<private> global_1: vec3<f32>;
@group(0) @binding(2)
var global_2: sampler;
@group(0) @binding(1)
var global_3: texture_cube<f32>;

fn function() {
var phi_273_: vec3<f32>;
var phi_308_: vec3<f32>;
var phi_343_: vec3<f32>;
var phi_138_: vec3<f32>;
var phi_141_: f32;
var phi_143_: f32;
var phi_153_: vec3<f32>;
var phi_156_: f32;
var phi_158_: f32;
var phi_378_: vec3<f32>;
var phi_154_: vec3<f32>;
var phi_157_: f32;
var phi_159_: f32;
var phi_139_: vec3<f32>;
var phi_142_: f32;
var phi_144_: f32;
var local: f32;
var local_1: vec3<f32>;
var local_2: vec3<f32>;
var local_3: vec3<f32>;
var local_4: vec3<f32>;
var local_5: f32;

let _e14 = global_1;
let _e21 = sqrt(fma(_e14.z, _e14.z, fma(_e14.x, _e14.x, (_e14.y * _e14.y))));
if (_e21 == 0f) {
phi_273_ = vec3<f32>(0f, 0f, 0f);
} else {
phi_273_ = (_e14 * (1f / _e21));
}
let _e26 = phi_273_;
let _e28 = (_e26.y * -1f);
let _e31 = -(_e26.x);
let _e35 = sqrt(fma(_e26.z, _e26.z, (_e31 * _e31)));
if (_e35 == 0f) {
phi_308_ = vec3<f32>(0f, 0f, 0f);
} else {
phi_308_ = (vec3<f32>(_e26.z, 0f, _e31) * (1f / _e35));
}
let _e40 = phi_308_;
let _e45 = fma(_e28, _e40.z, -((_e40.y * _e26.z)));
let _e49 = fma(_e26.z, _e40.x, -((_e40.z * _e26.x)));
let _e52 = fma(_e26.x, _e40.y, -((_e40.x * _e28)));
let _e57 = sqrt(fma(_e52, _e52, fma(_e45, _e45, (_e49 * _e49))));
if (_e57 == 0f) {
phi_343_ = vec3<f32>(0f, 0f, 0f);
} else {
phi_343_ = (vec3<f32>(_e45, _e49, _e52) * (1f / _e57));
}
let _e62 = phi_343_;
phi_138_ = vec3<f32>(0f, 0f, 0f);
phi_141_ = 0f;
phi_143_ = 0f;
loop {
let _e64 = phi_138_;
let _e66 = phi_141_;
let _e68 = phi_143_;
local = _e68;
local_1 = _e64;
local_2 = _e64;
local_3 = _e64;
let _e69 = (_e66 < 6.2831855f);
if _e69 {
phi_153_ = _e64;
phi_156_ = 0f;
phi_158_ = _e68;
loop {
let _e71 = phi_153_;
let _e73 = phi_156_;
let _e75 = phi_158_;
local_4 = _e71;
local_5 = _e75;
let _e76 = (_e73 < 1.5707964f);
if _e76 {
let _e77 = sin(_e73);
let _e79 = (_e77 * cos(_e66));
let _e81 = (_e77 * sin(_e66));
let _e82 = cos(_e73);
let _e92 = fma(_e82, _e26.x, fma(_e79, _e40.x, (_e81 * _e62.x)));
let _e93 = fma(_e82, _e28, fma(_e79, _e40.y, (_e81 * _e62.y)));
let _e94 = fma(_e82, _e26.z, fma(_e79, _e40.z, (_e81 * _e62.z)));
let _e99 = sqrt(fma(_e94, _e94, fma(_e92, _e92, (_e93 * _e93))));
if (_e99 == 0f) {
phi_378_ = vec3<f32>(0f, 0f, 0f);
} else {
phi_378_ = (vec3<f32>(_e92, _e93, _e94) * (1f / _e99));
}
let _e104 = phi_378_;
let _e105 = textureSample(global_3, global_2, _e104);
phi_154_ = vec3<f32>(fma((_e105.x * _e82), _e77, _e71.x), fma((_e105.y * _e82), _e77, _e71.y), fma((_e105.z * _e82), _e77, _e71.z));
phi_157_ = (_e73 + 0.025f);
phi_159_ = (_e75 + 1f);
} else {
phi_154_ = vec3<f32>();
phi_157_ = f32();
phi_159_ = f32();
}
let _e122 = phi_154_;
let _e124 = phi_157_;
let _e126 = phi_159_;
continue;
continuing {
phi_153_ = _e122;
phi_156_ = _e124;
phi_158_ = _e126;
break if !(_e76);
}
}
let _e167 = local_4;
phi_139_ = _e167;
phi_142_ = (_e66 + 0.025f);
let _e171 = local_5;
phi_144_ = _e171;
} else {
phi_139_ = vec3<f32>();
phi_142_ = f32();
phi_144_ = f32();
}
let _e130 = phi_139_;
let _e132 = phi_142_;
let _e134 = phi_144_;
continue;
continuing {
phi_138_ = _e130;
phi_141_ = _e132;
phi_143_ = _e134;
break if !(_e69);
}
}
let _e137 = local;
let _e138 = (3.1415927f / _e137);
let _e140 = local_1;
let _e144 = local_2;
let _e148 = local_3;
global = vec4<f32>((_e140.x * _e138), (_e144.y * _e138), (_e148.z * _e138), 1f);
return;
}

@fragment
fn ibldiffuse_irradiancedi_convolution_fragment(@location(0) param: vec3<f32>) -> @location(0) vec4<f32> {
global_1 = param;
function();
let _e3 = global;
return _e3;
}
5 changes: 5 additions & 0 deletions crates/renderling/shaders/manifest.json
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,11 @@
"entry_point": "debug::debug_overlay_vertex",
"wgsl_entry_point": "debugdebug_overlay_vertex"
},
{
"source_path": "shaders/ibl-diffuse_irradiance-di_convolution_fragment.spv",
"entry_point": "ibl::diffuse_irradiance::di_convolution_fragment",
"wgsl_entry_point": "ibldiffuse_irradiancedi_convolution_fragment"
},
{
"source_path": "shaders/skybox-skybox_cubemap_fragment.spv",
"entry_point": "skybox::skybox_cubemap_fragment",
Expand Down
Binary file modified crates/renderling/shaders/skybox-skybox_cubemap_fragment.spv
Binary file not shown.
175 changes: 54 additions & 121 deletions crates/renderling/src/ibl/diffuse_irradiance.rs
Original file line number Diff line number Diff line change
@@ -1,127 +1,60 @@
//! Pipeline and bindings for for diffuse irradiance convolution shaders.
//! Diffuse irradiance convolution.
pub fn diffuse_irradiance_convolution_bindgroup_layout(
device: &wgpu::Device,
) -> wgpu::BindGroupLayout {
device.create_bind_group_layout(&wgpu::BindGroupLayoutDescriptor {
label: Some("convolution bindgroup"),
entries: &[
wgpu::BindGroupLayoutEntry {
binding: 0,
visibility: wgpu::ShaderStages::VERTEX,
ty: wgpu::BindingType::Buffer {
ty: wgpu::BufferBindingType::Storage { read_only: true },
has_dynamic_offset: false,
min_binding_size: None,
},
count: None,
},
wgpu::BindGroupLayoutEntry {
binding: 1,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Texture {
sample_type: wgpu::TextureSampleType::Float { filterable: true },
view_dimension: wgpu::TextureViewDimension::Cube,
multisampled: false,
},
count: None,
},
wgpu::BindGroupLayoutEntry {
binding: 2,
visibility: wgpu::ShaderStages::FRAGMENT,
ty: wgpu::BindingType::Sampler(wgpu::SamplerBindingType::Filtering),
count: None,
},
],
})
}
use glam::{Vec3, Vec4, Vec4Swizzles};
#[cfg(target_arch = "spirv")]
use spirv_std::num_traits::Float;
use spirv_std::{image::Cubemap, spirv, Sampler};

pub fn diffuse_irradiance_convolution_bindgroup(
device: &wgpu::Device,
label: Option<&str>,
buffer: &wgpu::Buffer,
// The texture to sample the environment from
texture: &crate::texture::Texture,
) -> wgpu::BindGroup {
device.create_bind_group(&wgpu::BindGroupDescriptor {
label,
layout: &diffuse_irradiance_convolution_bindgroup_layout(device),
entries: &[
wgpu::BindGroupEntry {
binding: 0,
resource: wgpu::BindingResource::Buffer(buffer.as_entire_buffer_binding()),
},
wgpu::BindGroupEntry {
binding: 1,
resource: wgpu::BindingResource::TextureView(&texture.view),
},
wgpu::BindGroupEntry {
binding: 2,
resource: wgpu::BindingResource::Sampler(&texture.sampler),
},
],
})
}
use crate::math::IsVector;

#[cfg(not(target_arch = "spirv"))]
mod cpu;
#[cfg(not(target_arch = "spirv"))]
pub use cpu::*;

pub struct DiffuseIrradianceConvolutionRenderPipeline(pub wgpu::RenderPipeline);
/// Diffuse irradiance convolution.
#[spirv(fragment)]
pub fn di_convolution_fragment(
#[spirv(descriptor_set = 0, binding = 1)] environment_texture: &Cubemap,
#[spirv(descriptor_set = 0, binding = 2)] environment_sampler: &Sampler,
local_pos: Vec3,
frag_color: &mut Vec4,
) {
let normal = {
let mut n = local_pos.alt_norm_or_zero();
n.y *= -1.0;
n
};
let mut irradiance = Vec3::ZERO;
let right = Vec3::Y.cross(normal).alt_norm_or_zero();
let up = normal.cross(right).alt_norm_or_zero();

impl DiffuseIrradianceConvolutionRenderPipeline {
/// Create the rendering pipeline that performs a convolution.
pub fn new(device: &wgpu::Device, format: wgpu::TextureFormat) -> Self {
log::trace!("creating convolution render pipeline with format '{format:?}'");
let vertex_linkage = crate::linkage::skybox_cubemap_vertex::linkage(device);
let fragment_shader = device.create_shader_module(wgpu::include_wgsl!(
// TODO: rewrite this shader in Rust after atomics are added to naga spv
"../wgsl/diffuse_irradiance_convolution.wgsl"
));
log::trace!(" done.");
let bg_layout = diffuse_irradiance_convolution_bindgroup_layout(device);
let pp_layout = device.create_pipeline_layout(&wgpu::PipelineLayoutDescriptor {
label: Some("convolution pipeline layout"),
bind_group_layouts: &[&bg_layout],
push_constant_ranges: &[],
});
// TODO: merge irradiance pipeline with cubemap
let pipeline = DiffuseIrradianceConvolutionRenderPipeline(device.create_render_pipeline(
&wgpu::RenderPipelineDescriptor {
label: Some("convolution pipeline"),
layout: Some(&pp_layout),
vertex: wgpu::VertexState {
module: &vertex_linkage.module,
entry_point: Some(vertex_linkage.entry_point),
buffers: &[],
compilation_options: Default::default(),
},
primitive: wgpu::PrimitiveState {
topology: wgpu::PrimitiveTopology::TriangleList,
strip_index_format: None,
front_face: wgpu::FrontFace::Ccw,
cull_mode: None,
unclipped_depth: false,
polygon_mode: wgpu::PolygonMode::Fill,
conservative: false,
},
depth_stencil: None,
multisample: wgpu::MultisampleState {
mask: !0,
alpha_to_coverage_enabled: false,
count: 1,
},
fragment: Some(wgpu::FragmentState {
module: &fragment_shader,
entry_point: Some("fragment_convolve_diffuse_irradiance"),
targets: &[Some(wgpu::ColorTargetState {
format,
blend: Some(wgpu::BlendState::ALPHA_BLENDING),
write_mask: wgpu::ColorWrites::ALL,
})],
compilation_options: Default::default(),
}),
multiview: None,
cache: None,
},
));
log::trace!(" completed pipeline creation");
pipeline
let sample_delta = 0.025;
let mut nr_samples = 0.0;
let mut phi = 0.0f32;
while phi < 2.0 * core::f32::consts::PI {
let mut theta = 0.0f32;
while theta < core::f32::consts::FRAC_PI_2 {
// spherical to cartisian tangent coords
let tangent_sample = Vec3::new(
theta.sin() * phi.cos(),
theta.sin() * phi.sin(),
theta.cos(),
);
// tangent to world coords
let sample_vec =
(tangent_sample.x * right + tangent_sample.y * up + tangent_sample.z * normal)
.alt_norm_or_zero();
let sample = environment_texture.sample(*environment_sampler, sample_vec)
* theta.cos()
* theta.sin();
irradiance += sample.xyz();
nr_samples += 1.0;

theta += sample_delta;
}
phi += sample_delta
}

*frag_color = (irradiance * (core::f32::consts::PI / nr_samples)).extend(1.0);
}
Loading

0 comments on commit 092c64c

Please sign in to comment.