render3d: under a fog wall the volumetric air is marched only to it, SSGI stops where it is solid, and card casters that fill the wall stop rebuilding

The volumetric pass marched 800 m in a fixed number of steps whatever the wall: it now stops at the
wall with steps in proportion (at least 8) - 0.57 -> 0.33 ms at 30 m by the pass timers. SSGI skipped
only past 900 m; it now also skips past 0.85 of a wall, where the fog is solid (u_ao_far). applyFog
samples the fog's colour only where its weight is above zero. A card layer whose casters inside the
wall are 80% or more of it (a kilometre's wall) casts from its static list and is not refiltered and
re-uploaded every 4 m of camera motion. Fog off: the frame unchanged (0 pixels over 8).

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Orkun ÇAKILKAYA 2026-09-29 17:00:27 +03:00
parent 5b3cfac48e
commit 329439cf61
32 changed files with 36 additions and 14 deletions

View file

@ -11,7 +11,10 @@ function fog_casters(render3d_st: mut Render3dState, l: Layer) -> int {
if w <= 0.0 { return l.sh_buf }
let dx = render3d_st.cam_pos[0] - l.fog_x
let dz = render3d_st.cam_pos[2] - l.fog_z
if l.fog_wall == w and l.fog_src == l.n_sh and dx * dx + dz * dz < FOG_CAST_STEP * FOG_CAST_STEP { return l.fog_buf }
if l.fog_wall == w and l.fog_src == l.n_sh and (l.fog_all or dx * dx + dz * dz < FOG_CAST_STEP * FOG_CAST_STEP) {
if l.fog_all { return l.sh_buf }
return l.fog_buf
}
l.fog_wall = w; l.fog_src = l.n_sh
l.fog_x = render3d_st.cam_pos[0]; l.fog_z = render3d_st.cam_pos[2]
let far = w + R3D_FOG_MARGIN + FOG_CAST_THROW + FOG_CAST_STEP
@ -30,11 +33,15 @@ function fog_casters(render3d_st: mut Render3dState, l: Layer) -> int {
n += 1
}
l.fog_n = n
# a wall that keeps nearly the whole layer (a kilometre): the static list, and no rebuild as the camera
# moves - copying and uploading 60k cards every 4 m bought nothing there
l.fog_all = n * 5 >= total * 4
if l.fog_all { return l.sh_buf }
if n > 0 { gpu_buffer_upload(render3d_st, l.fog_buf, n * INST_FLOATS * 4, data_of(dst), GPU_DYNAMIC) }
return l.fog_buf
}
function fog_casters_n(render3d_st: Render3dState, l: Layer) -> int {
if render3d_st.r3d_fog_wall <= 0.0 { return l.n_sh }
if render3d_st.r3d_fog_wall <= 0.0 or l.fog_all { return l.n_sh }
return l.fog_n
}