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 direction = normal + vec3(sin_theta * cos(phi), sin_theta * sin(phi), cos_theta); 103 let len_sq = dot(direction, direction); 104 if len_sq < 1e-8 { return normal; } 105 return direction * inverseSqrt(len_sq); 109fn sample_uniform_hemisphere(normal: vec3<f32>, rng: ptr<function, u32>) -> vec3<f32> { 110 let cos_theta = rand_f(rng); 111 let phi = PI_2 * rand_f(rng); 112 let sin_theta = sqrt(max(1.0 - cos_theta * cos_theta, 0.0)); 113 let x = sin_theta * cos(phi); 114 let y = sin_theta * sin(phi); 116 return orthonormalize(normal) * vec3(x, y, z); 119fn uniform_hemisphere_inverse_pdf() -> f32 { 124fn sample_disk(disk_radius: f32, rng: ptr<function, u32>) -> vec2<f32> { 125 let ab = 2.0 * rand_vec2f(rng) - 1.0; 128 if (b == 0.0) { b = 1.0; } 134 phi = (PI / 4.0) * (b / a); 137 phi = (PI / 2.0) - (PI / 4.0) * (a / b); 140 let x = r * cos(phi); 141 let y = r * sin(phi); 146fn sample_cube_dir(uv: vec2f, face: u32) -> vec3f { 148 let uvc = 2.0 * uv - 1.0; 153 case 0u: { dir = vec3f( 1.0, -uvc.y, -uvc.x); } 154 case 1u: { dir = vec3f(-1.0, -uvc.y, uvc.x); } 155 case 2u: { dir = vec3f( uvc.x, 1.0, uvc.y); } 156 case 3u: { dir = vec3f( uvc.x, -1.0, -uvc.y); } 157 case 4u: { dir = vec3f( uvc.x, -uvc.y, 1.0); } 158 case 5u: { dir = vec3f(-uvc.x, -uvc.y, -1.0); } 159 default: { dir = vec3f(0.0); } 161 return normalize(dir); 169fn dir_to_cube_uv(dir: vec3f) -> CubeUV { 170 let abs_dir = abs(dir); 172 var uv: vec2f = vec2f(0.0); 175 if (abs_dir.x >= abs_dir.y && abs_dir.x >= abs_dir.z) { 179 uv = vec2f(-dir.z, -dir.y) / dir.x; 182 uv = vec2f(dir.z, -dir.y) / abs_dir.x; 184 } else if (abs_dir.y >= abs_dir.x && abs_dir.y >= abs_dir.z) { 188 uv = vec2f(dir.x, dir.z) / dir.y; 191 uv = vec2f(dir.x, -dir.z) / abs_dir.y; 197 uv = vec2f(dir.x, -dir.y) / dir.z; 200 uv = vec2f(-dir.x, -dir.y) / abs_dir.z; 205 return CubeUV(uv * 0.5 + 0.5, face); 210fn porter_duff_over(bg: vec4<f32>, fg: vec4<f32>) -> vec4<f32> { 211 return vec4<f32>(mix(bg.rgb * bg.a, fg.rgb, fg.a), bg.a + fg.a * (1.0 - bg.a));