1#define_import_path bevy_pbr::utils 3#import bevy_pbr::rgb9e5 4#import bevy_render::maths::{PI, PI_2, orthonormalize} 15fn rand_u(state: ptr<function, u32>) -> u32 { 16 *state = *state * 747796405u + 2891336453u; 17 let word = ((*state >> ((*state >> 28u) + 4u)) ^ *state) * 277803737u; 18 return (word >> 22u) ^ word; 22fn rand_f(state: ptr<function, u32>) -> f32 { 23 *state = *state * 747796405u + 2891336453u; 24 let word = ((*state >> ((*state >> 28u) + 4u)) ^ *state) * 277803737u; 25 return f32((word >> 22u) ^ word) * bitcast<f32>(0x2f800004u); 29fn rand_vec2f(state: ptr<function, u32>) -> vec2<f32> { 30 return vec2(rand_f(state), rand_f(state)); 34fn rand_range_u(n: u32, state: ptr<function, u32>) -> u32 { 35 return rand_u(state) % n; 42fn coords_to_viewport_uv(position: vec2<f32>, viewport: vec4<f32>) -> vec2<f32> { 43 return (position - viewport.xy) / viewport.zw; 49fn octahedral_encode(v: vec3<f32>) -> vec2<f32> { 50 var n = v / (abs(v.x) + abs(v.y) + abs(v.z)); 51 let octahedral_wrap = (1.0 - abs(n.yx)) * select(vec2(-1.0), vec2(1.0), n.xy > vec2f(0.0)); 52 let n_xy = select(octahedral_wrap, n.xy, n.z >= 0.0); 53 return n_xy * 0.5 + 0.5; 57fn octahedral_decode(v: vec2<f32>) -> vec3<f32> { 58 let f = v * 2.0 - 1.0; 59 return octahedral_decode_signed(f); 63fn octahedral_decode_signed(v: vec2<f32>) -> vec3<f32> { 64 var n = vec3(v.xy, 1.0 - abs(v.x) - abs(v.y)); 65 let t = saturate(-n.z); 66 let w = select(vec2(t), vec2(-t), n.xy >= vec2(0.0)); 67 n = vec3(n.xy + w, n.z); 72fn interleaved_gradient_noise(pixel_coordinates: vec2<f32>, frame: u32) -> f32 { 73 let xy = pixel_coordinates + 5.588238 * f32(frame % 64u); 74 return fract(52.9829189 * fract(0.06711056 * xy.x + 0.00583715 * xy.y)); 78fn hammersley_2d(i: u32, n: u32) -> vec2f { 79 let inv_n = 1.0 / f32(n); 80 let vdc = f32(reverseBits(i)) * 2.3283064365386963e-10; 81 return vec2f(f32(i) * inv_n, vdc); 88const SPIRAL_OFFSET_0_ = vec2<f32>(-0.7071, 0.7071); 89const SPIRAL_OFFSET_1_ = vec2<f32>(-0.0000, -0.8750); 90const SPIRAL_OFFSET_2_ = vec2<f32>( 0.5303, 0.5303); 91const SPIRAL_OFFSET_3_ = vec2<f32>(-0.6250, -0.0000); 92const SPIRAL_OFFSET_4_ = vec2<f32>( 0.3536, -0.3536); 93const SPIRAL_OFFSET_5_ = vec2<f32>(-0.0000, 0.3750); 94const SPIRAL_OFFSET_6_ = vec2<f32>(-0.1768, -0.1768); 95const SPIRAL_OFFSET_7_ = vec2<f32>( 0.1250, 0.0000); 98fn sample_cosine_hemisphere(normal: vec3<f32>, rng: ptr<function, u32>) -> vec3<f32> { 99 let cos_theta = 1.0 - 2.0 * rand_f(rng); 100 let phi = PI_2 * rand_f(rng); 101 let sin_theta = sqrt(max(1.0 - cos_theta * cos_theta, 0.0)); 102 let x = normal.x + sin_theta * cos(phi); 103 let y = normal.y + sin_theta * sin(phi); 104 let z = normal.z + cos_theta; 105 return vec3(x, y, z); 108fn sample_uniform_hemisphere(normal: vec3<f32>, rng: ptr<function, u32>) -> vec3<f32> { 109 let cos_theta = rand_f(rng); 110 let phi = PI_2 * rand_f(rng); 111 let sin_theta = sqrt(max(1.0 - cos_theta * cos_theta, 0.0)); 112 let x = sin_theta * cos(phi); 113 let y = sin_theta * sin(phi); 115 return orthonormalize(normal) * vec3(x, y, z); 118fn uniform_hemisphere_inverse_pdf() -> f32 { 123fn sample_disk(disk_radius: f32, rng: ptr<function, u32>) -> vec2<f32> { 124 let ab = 2.0 * rand_vec2f(rng) - 1.0; 127 if (b == 0.0) { b = 1.0; } 133 phi = (PI / 4.0) * (b / a); 136 phi = (PI / 2.0) - (PI / 4.0) * (a / b); 139 let x = r * cos(phi); 140 let y = r * sin(phi); 145fn sample_cube_dir(uv: vec2f, face: u32) -> vec3f { 147 let uvc = 2.0 * uv - 1.0; 152 case 0u: { dir = vec3f( 1.0, -uvc.y, -uvc.x); } 153 case 1u: { dir = vec3f(-1.0, -uvc.y, uvc.x); } 154 case 2u: { dir = vec3f( uvc.x, 1.0, uvc.y); } 155 case 3u: { dir = vec3f( uvc.x, -1.0, -uvc.y); } 156 case 4u: { dir = vec3f( uvc.x, -uvc.y, 1.0); } 157 case 5u: { dir = vec3f(-uvc.x, -uvc.y, -1.0); } 158 default: { dir = vec3f(0.0); } 160 return normalize(dir); 168fn dir_to_cube_uv(dir: vec3f) -> CubeUV { 169 let abs_dir = abs(dir); 171 var uv: vec2f = vec2f(0.0); 174 if (abs_dir.x >= abs_dir.y && abs_dir.x >= abs_dir.z) { 178 uv = vec2f(-dir.z, -dir.y) / dir.x; 181 uv = vec2f(dir.z, -dir.y) / abs_dir.x; 183 } else if (abs_dir.y >= abs_dir.x && abs_dir.y >= abs_dir.z) { 187 uv = vec2f(dir.x, dir.z) / dir.y; 190 uv = vec2f(dir.x, -dir.z) / abs_dir.y; 196 uv = vec2f(dir.x, -dir.y) / dir.z; 199 uv = vec2f(-dir.x, -dir.y) / abs_dir.z; 204 return CubeUV(uv * 0.5 + 0.5, face);