renderling/pbr/ibl/
shader.rs1use glam::{Vec3, Vec4, Vec4Swizzles};
3#[cfg(gpu)]
4use spirv_std::num_traits::Float;
5use spirv_std::{image::Cubemap, spirv, Sampler};
6
7use crate::math::IsVector;
8
9#[spirv(fragment)]
11pub fn di_convolution_fragment(
12 #[spirv(descriptor_set = 0, binding = 1)] environment_texture: &Cubemap,
13 #[spirv(descriptor_set = 0, binding = 2)] environment_sampler: &Sampler,
14 local_pos: Vec3,
15 frag_color: &mut Vec4,
16) {
17 let normal = {
18 let mut n = local_pos.alt_norm_or_zero();
19 n.y *= -1.0;
20 n
21 };
22 let mut irradiance = Vec3::ZERO;
23 let right = Vec3::Y.cross(normal).alt_norm_or_zero();
24 let up = normal.cross(right).alt_norm_or_zero();
25
26 let sample_delta = 0.025;
27 let mut nr_samples = 0.0;
28 let mut phi = 0.0f32;
29 while phi < 2.0 * core::f32::consts::PI {
30 let mut theta = 0.0f32;
31 while theta < core::f32::consts::FRAC_PI_2 {
32 let tangent_sample = Vec3::new(
34 theta.sin() * phi.cos(),
35 theta.sin() * phi.sin(),
36 theta.cos(),
37 );
38 let sample_vec =
40 (tangent_sample.x * right + tangent_sample.y * up + tangent_sample.z * normal)
41 .alt_norm_or_zero();
42 let sample = environment_texture.sample(*environment_sampler, sample_vec)
43 * theta.cos()
44 * theta.sin();
45 irradiance += sample.xyz();
46 nr_samples += 1.0;
47
48 theta += sample_delta;
49 }
50 phi += sample_delta
51 }
52
53 *frag_color = (irradiance * (core::f32::consts::PI / nr_samples)).extend(1.0);
54}