Skip to main content

Module dda

Module dda 

Source
Expand description

Per-pixel 3D-DDA + brickmap CPU renderer (Substage DDA).

This is the clean-room replacement for the voxlap-derived column-coherent opticast pipeline (opticast + grouscan + scan_loops). Every pixel casts one independent ray, so none of the column/row-coherence stitching artifacts of the 2.5D voxlap renderer can occur (silhouette notch, floor hairlines, axis-aligned mip beams, cross-chunk virtual-column complexity). See PORTING-DDA.md for the full stage plan.

Stage status — DDA.6 (per-grid distance mip) + DDA.7 (tile parallelism). Each pixel casts one ray over the grid’s full voxel box (GridView::voxel_bounds, spanning every chunk in XY and Z) via a 3D-DDA (Amanatides–Woo). A uniform render mip (chosen per grid by LOD distance, clamped by effective_mip to a level every chunk has built) coarsens the cell size to 2^mip mip-0 voxels and samples mip-mip data — the ray stays in mip-0 units so depth and fog are exact. [BrickMaps] (one occupancy map per populated chunk, at the render mip) are built once per frame and shared immutably; a [Sampler] resolves each cell to its chunk (GridView::chunk_at_xyz) and brick-gates the GridView::surface_color_mip slab walk, caching the current chunk so air costs an O(1) bit test. render_dda_parallel splits the frame into disjoint rayon bands — bit-identical to sequential since pixels are independent. Hits are shaded by baked brightness ([shade]) + DdaEnv::side_shades face tint, fogged toward DdaEnv::fog_color ([apply_fog]); misses sample the DdaEnv::sky panorama ([sample_sky]) or keep the solid pre-fill.

Buffer conventions match the rest of the engine so this backend is colour is packed 0x80RRGGBB; depth is perpendicular distance from the camera with smaller = closer (so the scene compositor’s min-z merge works directly on the z-buffer this writes).

Structs§

BrickCache
Persistent, cross-frame brick occupancy cache (Substage DDA.7 perf). Keyed by (chunk x, y, z, mip) with the chunk’s edit version; an entry is reused until its chunk’s version changes, so a static / streamed-once world pays zero brick-build cost after the first frame (the per-frame rebuild was the dominant DDA cost).
DdaEnv
Per-frame environment for DDA shading (Substage DDA.5): a textured sky panorama, distance fog, and per-face side shading.
RasterSink
PixelSink over a borrowed (framebuffer, zbuffer) pair.

Traits§

PixelSink
Per-pixel output target for the DDA renderer.

Functions§

effective_mip
Clamp a requested render mip to one every populated chunk actually has built — so the uniform-mip traversal never under-samples a chunk that lacks the requested level (which would punch holes). 0 short- circuits (always available).
pixel_ray
World-space ray for screen pixel (px, py) under opticast’s pinhole: origin is the camera position, direction is (px - hx)·right + (py - hy)·down + hz·forward.
render_dda
Render one grid into sink with per-pixel 3D-DDA.
render_dda_parallel
Tile-parallel render_dda writing straight into (fb, zb).
render_sky_fill
Fill the panorama Sky into every background pixel — one whose z-buffer entry is still +∞ (no grid/terrain hit). The per-grid DDA only samples the sky inside each grid’s screen rect (and only its sky-owning grid); pixels outside any grid — most of a sprite/effect-only view, or the margins around a small world grid — would otherwise keep the caller’s flat clear colour. This paints the real panorama there while leaving terrain (finite z) and composited translucent pixels untouched. The z-buffer is not modified. cam/settings are the same per-frame projection the renderer used.