1import package::render::rgb9e5; 2import bevy_render::maths::{PI, PI_2, orthonormalize}; 13fn rand_u(state: ptr<function, u32>) -> u32 { 14 *state = *state * 747796405u + 2891336453u; 15 let word = ((*state >> ((*state >> 28u) + 4u)) ^ *state) * 277803737u; 16 return (word >> 22u) ^ word; 20fn rand_f(state: ptr<function, u32>) -> f32 { 21 *state = *state * 747796405u + 2891336453u; 22 let word = ((*state >> ((*state >> 28u) + 4u)) ^ *state) * 277803737u; 23 return f32((word >> 22u) ^ word) * bitcast<f32>(0x2f800004u); 27fn rand_vec2f(state: ptr<function, u32>) -> vec2<f32> { 28 return vec2(rand_f(state), rand_f(state)); 32fn rand_range_u(n: u32, state: ptr<function, u32>) -> u32 { 33 return rand_u(state) % n; 40fn coords_to_viewport_uv(position: vec2<f32>, viewport: vec4<f32>) -> vec2<f32> { 41 return (position - viewport.xy) / viewport.zw; 45fn interleaved_gradient_noise(pixel_coordinates: vec2<f32>, frame: u32) -> f32 { 46 let xy = pixel_coordinates + 5.588238 * f32(frame % 64u); 47 return fract(52.9829189 * fract(0.06711056 * xy.x + 0.00583715 * xy.y)); 51fn hammersley_2d(i: u32, n: u32) -> vec2f { 52 let inv_n = 1.0 / f32(n); 53 let vdc = f32(reverseBits(i)) * 2.3283064365386963e-10; 54 return vec2f(f32(i) * inv_n, vdc); 61const SPIRAL_OFFSET_0_ = vec2<f32>(-0.7071, 0.7071); 62const SPIRAL_OFFSET_1_ = vec2<f32>(-0.0000, -0.8750); 63const SPIRAL_OFFSET_2_ = vec2<f32>( 0.5303, 0.5303); 64const SPIRAL_OFFSET_3_ = vec2<f32>(-0.6250, -0.0000); 65const SPIRAL_OFFSET_4_ = vec2<f32>( 0.3536, -0.3536); 66const SPIRAL_OFFSET_5_ = vec2<f32>(-0.0000, 0.3750); 67const SPIRAL_OFFSET_6_ = vec2<f32>(-0.1768, -0.1768); 68const SPIRAL_OFFSET_7_ = vec2<f32>( 0.1250, 0.0000); 71fn sample_cosine_hemisphere(normal: vec3<f32>, rng: ptr<function, u32>) -> vec3<f32> { 72 let cos_theta = 1.0 - 2.0 * rand_f(rng); 73 let phi = PI_2 * rand_f(rng); 74 let sin_theta = sqrt(max(1.0 - cos_theta * cos_theta, 0.0)); 75 let direction = normal + vec3(sin_theta * cos(phi), sin_theta * sin(phi), cos_theta); 76 let len_sq = dot(direction, direction); 77 if len_sq < 1e-8 { return normal; } 78 return direction * inverseSqrt(len_sq); 82fn sample_uniform_hemisphere(normal: vec3<f32>, rng: ptr<function, u32>) -> vec3<f32> { 83 let cos_theta = rand_f(rng); 84 let phi = PI_2 * rand_f(rng); 85 let sin_theta = sqrt(max(1.0 - cos_theta * cos_theta, 0.0)); 86 let x = sin_theta * cos(phi); 87 let y = sin_theta * sin(phi); 89 return orthonormalize(normal) * vec3(x, y, z); 92fn uniform_hemisphere_inverse_pdf() -> f32 { 97fn sample_disk(disk_radius: f32, rng: ptr<function, u32>) -> vec2<f32> { 98 let ab = 2.0 * rand_vec2f(rng) - 1.0; 101 if (b == 0.0) { b = 1.0; } 107 phi = (PI / 4.0) * (b / a); 110 phi = (PI / 2.0) - (PI / 4.0) * (a / b); 113 let x = r * cos(phi); 114 let y = r * sin(phi); 119fn sample_cube_dir(uv: vec2f, face: u32) -> vec3f { 121 let uvc = 2.0 * uv - 1.0; 126 case 0u: { dir = vec3f( 1.0, -uvc.y, -uvc.x); } 127 case 1u: { dir = vec3f(-1.0, -uvc.y, uvc.x); } 128 case 2u: { dir = vec3f( uvc.x, 1.0, uvc.y); } 129 case 3u: { dir = vec3f( uvc.x, -1.0, -uvc.y); } 130 case 4u: { dir = vec3f( uvc.x, -uvc.y, 1.0); } 131 case 5u: { dir = vec3f(-uvc.x, -uvc.y, -1.0); } 132 default: { dir = vec3f(0.0); } 134 return normalize(dir); 142fn dir_to_cube_uv(dir: vec3f) -> CubeUV { 143 let abs_dir = abs(dir); 145 var uv: vec2f = vec2f(0.0); 148 if (abs_dir.x >= abs_dir.y && abs_dir.x >= abs_dir.z) { 152 uv = vec2f(-dir.z, -dir.y) / dir.x; 155 uv = vec2f(dir.z, -dir.y) / abs_dir.x; 157 } else if (abs_dir.y >= abs_dir.x && abs_dir.y >= abs_dir.z) { 161 uv = vec2f(dir.x, dir.z) / dir.y; 164 uv = vec2f(dir.x, -dir.z) / abs_dir.y; 170 uv = vec2f(dir.x, -dir.y) / dir.z; 173 uv = vec2f(-dir.x, -dir.y) / abs_dir.z; 178 return CubeUV(uv * 0.5 + 0.5, face); 183fn porter_duff_over(bg: vec4<f32>, fg: vec4<f32>) -> vec4<f32> { 184 return vec4<f32>(mix(bg.rgb * bg.a, fg.rgb, fg.a), bg.a + fg.a * (1.0 - bg.a));