1import constants::WORLD_CACHE_SIZE; 2import bevy_pbr::render::utils::{rand_f, rand_vec2f}; 3import bevy_render::maths::orthonormalize; 4import package::realtime::bindings::{ 12const WORLD_CACHE_CELL_LIFETIME: u32 = 10u; 14const WORLD_CACHE_MAX_SEARCH_STEPS: u32 = 3u; 17const WORLD_CACHE_EMPTY_CELL: u32 = 0u; 19@if(!WORLD_CACHE_NON_ATOMIC_LIFE_BUFFER) 20fn query_world_cache(world_position_in: vec3<f32>, world_normal: vec3<f32>, view_position: vec3<f32>, ray_t: f32, cell_lifetime: u32, rng: ptr<function, u32>) -> vec3<f32> { 21 var world_position = world_position_in; 22 var cell_size = get_cell_size(world_position, view_position, ray_t, rng); 24@if(!NO_JITTER_WORLD_CACHE) { 27 let TBN = orthonormalize(world_normal); 28 let offset = (rand_vec2f(rng) * 2.0 - 1.0) * cell_size * 0.5; 29 world_position += offset.x * TBN[0] + offset.y * TBN[1]; 30 cell_size = get_cell_size(world_position, view_position, ray_t, rng); 33 let world_position_quantized = bitcast<vec3<u32>>(quantize_position(world_position, cell_size)); 34 let world_normal_quantized = bitcast<vec3<u32>>(quantize_normal(world_normal)); 35 var key = compute_key(world_position_quantized, world_normal_quantized); 36 let checksum = compute_checksum(world_position_quantized, world_normal_quantized); 38 for (var i = 0u; i < WORLD_CACHE_MAX_SEARCH_STEPS; i++) { 39 let cas = atomicCompareExchangeWeak(&world_cache.checksums[key], WORLD_CACHE_EMPTY_CELL, checksum); 40 let existing_checksum = cas.old_value; 43 if existing_checksum == checksum || existing_checksum == WORLD_CACHE_EMPTY_CELL { 44 @if(!WORLD_CACHE_QUERY_ATOMIC_MAX_LIFETIME) 45 atomicStore(&world_cache.life[key], cell_lifetime); 47 atomicMax(&world_cache.life[key], cell_lifetime); 50 if existing_checksum == checksum { 52 return world_cache.radiance[key].rgb; 53 } else if existing_checksum == WORLD_CACHE_EMPTY_CELL && cas.exchanged { 55 world_cache.geometry_data[key].world_position = world_position; 56 world_cache.geometry_data[key].world_normal = world_normal; 67fn get_cell_size(world_position: vec3<f32>, view_position: vec3<f32>, ray_t: f32, rng: ptr<function, u32>) -> f32 { 68 let camera_distance = distance(view_position, world_position) / constants.world_cache_position_lod_scale; 69 let lod_f = log2(1.0 + camera_distance); 70 let lod_fract = fract(lod_f); 71 let lod = floor(lod_f) + select(0.0, 1.0, rand_f(rng) < lod_fract * lod_fract * lod_fract); 72 return constants.world_cache_position_base_cell_size * exp2(lod); 75fn quantize_position(world_position: vec3<f32>, quantization_factor: f32) -> vec3<f32> { 76 return floor(world_position / quantization_factor + 0.0001); 79fn quantize_normal(world_normal: vec3<f32>) -> vec3<f32> { 80 return floor(world_normal + 0.0001); 83fn compute_key(world_position: vec3<u32>, world_normal: vec3<u32>) -> u32 { 84 var key = pcg_hash(world_position.x); 85 key = pcg_hash(key + world_position.y); 86 key = pcg_hash(key + world_position.z); 87 key = pcg_hash(key + world_normal.x); 88 key = pcg_hash(key + world_normal.y); 89 key = pcg_hash(key + world_normal.z); 93fn compute_checksum(world_position: vec3<u32>, world_normal: vec3<u32>) -> u32 { 94 var key = iqint_hash(world_position.x); 95 key = iqint_hash(key + world_position.y); 96 key = iqint_hash(key + world_position.z); 97 key = iqint_hash(key + world_normal.x); 98 key = iqint_hash(key + world_normal.y); 99 key = iqint_hash(key + world_normal.z); 103fn pcg_hash(input: u32) -> u32 { 104 let state = input * 747796405u + 2891336453u; 105 let word = ((state >> ((state >> 28u) + 4u)) ^ state) * 277803737u; 106 return (word >> 22u) ^ word; 109fn iqint_hash(input: u32) -> u32 { 110 let n = (input << 13u) ^ input; 111 return n * (n * n * 15731u + 789221u) + 1376312589u; 114fn wrap_key(key: u32) -> u32 { 115 return key & (u32(WORLD_CACHE_SIZE) - 1u);