Ticket 014 V6 — bake the world-space radiance cache. One dispatch covers all `WSRC_GRID_RES³` probes × 64 octel texels. Cheap: per-texel work is one shadow-cascade lookup + analytic sun/sky math, roughly matching a single card-lighting pixel. Runs at most once per `WSRC_REBAKE_THRESHOLD × extent` of camera travel — same amortisation pattern as the clipmap.
(
&mut self,
encoder: &mut wgpu::CommandEncoder,
)
| 7033 | /// Runs at most once per `WSRC_REBAKE_THRESHOLD × extent` of |
| 7034 | /// camera travel — same amortisation pattern as the clipmap. |
| 7035 | fn bake_wsrc( |
| 7036 | &mut self, |
| 7037 | encoder: &mut wgpu::CommandEncoder, |
| 7038 | ) { |
| 7039 | // V13 — bake only cascades that are marked not-built. Each |
| 7040 | // cascade snaps to its own cell grid (cell = extent / 16) |
| 7041 | // and writes into its own 16-slice block of the shared |
| 7042 | // atlas. |
| 7043 | if self.wsrc_built.iter().all(|b| *b) { |
| 7044 | return; |
| 7045 | } |
| 7046 | |
| 7047 | // V14 — pick the HW ray-traced bake when the adapter has |
| 7048 | // ray-query AND the TLAS is ready. The SW path stays the |
| 7049 | // fallback for non-RT adapters and for the early frames |
| 7050 | // before BLAS / TLAS have been built. |
| 7051 | let use_hw = self.hw_rt_enabled |
| 7052 | && self.wsrc_bake_hw_pipeline.is_some() |
| 7053 | && self.tlas.is_some() |
| 7054 | && self.tlas_instance_data_buffer.is_some(); |
| 7055 | |
| 7056 | // Resolve a single set of lighting params — they're the same |
| 7057 | // across all cascades in one frame. Per-cascade differences |
| 7058 | // come from the origin + extent passed through the uniform. |
| 7059 | let ld = self.lighting_uniforms.light_dir; |
| 7060 | let inv_len = 1.0 / (ld[0]*ld[0] + ld[1]*ld[1] + ld[2]*ld[2]).sqrt().max(1e-4); |
| 7061 | let sun_dir_ws = [-ld[0]*inv_len, -ld[1]*inv_len, -ld[2]*inv_len, ld[3]]; |
| 7062 | let lc = self.lighting_uniforms.light_color; |
| 7063 | let sun_intensity = ld[3].max(0.0); |
| 7064 | let sun_color = [ |
| 7065 | lc[0] * sun_intensity, |
| 7066 | lc[1] * sun_intensity, |
| 7067 | lc[2] * sun_intensity, |
| 7068 | 0.0, |
| 7069 | ]; |
| 7070 | let amb = self.lighting_uniforms.ambient; |
| 7071 | let sky_intensity = amb[3].max(0.0); |
| 7072 | let sky_color = [ |
| 7073 | amb[0] * sky_intensity, |
| 7074 | amb[1] * sky_intensity, |
| 7075 | amb[2] * sky_intensity, |
| 7076 | 0.0, |
| 7077 | ]; |
| 7078 | |
| 7079 | let shadows_enabled = self.shadow_map.enabled; |
| 7080 | let shadow_vps: [[[f32; 4]; 4]; 3] = if shadows_enabled { |
| 7081 | self.shadow_map.light_vps |
| 7082 | } else { |
| 7083 | [IDENTITY_MAT4; 3] |
| 7084 | }; |
| 7085 | let shadow_splits = if shadows_enabled { |
| 7086 | let s = self.shadow_map.cascade_splits; |
| 7087 | [s[0], s[1], s[2], 0.0] |
| 7088 | } else { |
| 7089 | [f32::INFINITY, f32::INFINITY, f32::INFINITY, 0.0] |
| 7090 | }; |
| 7091 | |
| 7092 | // Lazy-build whichever bind group the selected path needs. |
no test coverage detected