feat(e3d): GI for mesh blocks, frustum far-plane and subpixel cull fixes
authorSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Mon, 28 Sep 2026 20:53:42 +0000 (23:53 +0300)
committerSvjatoslav Agejenko <svjatoslav@svjatoslav.eu>
Mon, 28 Sep 2026 20:53:42 +0000 (23:53 +0300)
commit27deab957f9071f2139957cc00c9c6a7c61382b4
tree3a7676b8b6832a43ad92ee27ee6bebb37444e05d
parent9ca140487324ef91a0bf02bb64ea2e40f4195ab5
feat(e3d): GI for mesh blocks, frustum far-plane and subpixel cull fixes

Global illumination now traces lean TriangleMeshBlock geometry:
each block triangle is a TriangleBvh.Entry with no backing polygon
(the entry carries the block and triangle index), sampled
per-triangle like plain polygons. Phase A writes direct light with
shadow bits and phase B adds the bounce estimate straight into the
block's new per-triangle giLight array (allocated at 255 = full
texture, so enabling GI shows no dark age); MeshTriangle.paint
copies the triplet before the span loop and the span writers
multiply sampled texels by it — per-triangle baked shading at a
branch per pixel. Albedo for bounce rays comes from each texture's
cached average color. Blocks skip the texel/lightmap phase
entirely.

Because streaming worlds bump the render-list version per loaded
cell, snapshot rebuilds are single-flighted (one worker builds, the
rest keep sampling the old snapshot) and rate-limited
(-De3d.gi.minRebuildMs=, default 1000 ms) so bursts coalesce
instead of rebuilding a multi-million-triangle BVH back-to-back.

Raise the frustum far plane from 10000 to 1e9 units
(-De3d.cull.far=): the short plane wrongly culled distant cell/LOD
composites whose whole bounds lay beyond it, punching holes into
mid-distance terrain while streaming (bugreport-20260928-005318;
FO4 LOD blocks span 100k+ units). Add -De3d.cull.frustum=false to
disable composite culling and -De3d.cull.frustumTrace=true to log
culled composites' bounds.

Include paint margins in the subpixel cull span: single-vertex
shapes (Billboard/GlowingPoint) have a zero raw span and their
entire visible area IS the margin, so the raw-span test culled them
regardless of glow size — billboards rendered invisible.

Document the mesh-block GI path, the far-plane rationale, and the
new tuning properties in the Global illumination and Frustum
culling pages and AGENTS.org.
12 files changed:
AGENTS.org
Documentation/Frustum culling/index.org
Documentation/Global illumination/index.org
src/main/java/eu/svjatoslav/aukio/e3d/renderer/raster/Frustum.java
src/main/java/eu/svjatoslav/aukio/e3d/renderer/raster/ShapeCollection.java
src/main/java/eu/svjatoslav/aukio/e3d/renderer/raster/gi/GlobalIllumination.java
src/main/java/eu/svjatoslav/aukio/e3d/renderer/raster/gi/TriangleBvh.java
src/main/java/eu/svjatoslav/aukio/e3d/renderer/raster/shapes/AbstractCoordinateShape.java
src/main/java/eu/svjatoslav/aukio/e3d/renderer/raster/shapes/basic/texturedpolygon/MeshTriangle.java
src/main/java/eu/svjatoslav/aukio/e3d/renderer/raster/shapes/basic/texturedpolygon/TexturedTriangle.java
src/main/java/eu/svjatoslav/aukio/e3d/renderer/raster/shapes/basic/texturedpolygon/TriangleMeshBlock.java
src/main/java/eu/svjatoslav/aukio/e3d/renderer/raster/shapes/composite/base/AbstractCompositeShape.java