# fog_casters.ludic — under a fog wall, a layer's cards cast shadows only from where they can be seen. # The impostor shadow list is every instance on the map; past the wall that is a vertex bill for # nothing, so the casters inside the wall (and a shadow's throw past it) go into a list of their own. const FOG_CAST_THROW: float = 30.0 # the longest shadow a tree throws back toward the camera const FOG_CAST_STEP: float = 4.0 # the camera moves this far before the list is rebuilt # the buffer and count the card shadows draw from: the whole list, or the wall's share of it function fog_casters(render3d_st: mut Render3dState, l: Layer) -> int { let w = render3d_st.r3d_fog_wall 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 (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 let far2 = far * far let src = l.inst let dst = l.scratch var n = 0 let total = Math.min(l.n_sh, l.count) for i in 0 .. total { let o = i * INST_FLOATS let ex = src[o] - l.fog_x let ez = src[o + 2] - l.fog_z if ex * ex + ez * ez > far2 { continue } let q = n * INST_FLOATS for k in 0 .. INST_FLOATS { dst[q + k] = src[o + k] } 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 or l.fog_all { return l.n_sh } return l.fog_n }