Class GlobalIllumination
- All Implemented Interfaces:
GiLightProvider
Generations: the scene is lit pass by pass, each walking all snapshot entries near-to-far from the camera, with a global barrier between passes:
- Stage 1 (generation 0) — uniform centroid direct: every entry gets one centroid evaluation against every tracked lamp. Plain polygons and mesh-block triangles record it as their final-resolution direct state; lightmapped triangles display it immediately through the per-triangle GI shade stamped on the triangle (no texel work — the painters multiply texels by the triplet until the first real composite lands). The whole scene shows per-polygon direct light with shadows within the first seconds.
- Generation 1 — per-texel direct: every lightmap texel casts a shadow ray toward every light; the outcome is cached in the texel's visibility bytes. Direct light is always derived from the cached visibility, never stored separately.
- Generation k >= 2 — one more bounce: every texel casts
e3d.gi.samplescosine-weighted bounce rays and averages them (a plain running mean — within a generation the sampled field is frozen by the barrier, so the samples are independent and no EMA is needed). Generation 2 gathers the hit point's direct light; generation k >= 3 gathers the hit surface's generation-(k-1) delta only, so each generation adds exactly one more light bounce to the solution.
Termination: the bake stops when a generation's mean delta
falls below e3d.gi.deltaThreshold (later generations only
shrink — the 1/pi diffuse gain keeps the loop gain below one) or when
e3d.gi.generations generations have run (default 6 = direct +
up to 5 bounce generations). The uncaptured series tail is the price
of the hard stop; raise the knob for bright interiors.
Storage lifetime: per-texel arrays (indirect total, two
delta buffers, visibility) are allocated lazily when the bake reaches
a lightmap and freed for the whole scene when the bake
completes — a finished lightmap keeps only its final composite
texture. Plain polygons keep their handful of per-polygon floats
(render threads read them every frame through GiLightProvider).
A scene or light change rebuilds the snapshot and restarts the bake
from stage 1; the old textures stay on screen until the new
direct pass lands (a lightmap that has already shown traced lighting
keeps it — no uniform preview on rebake).
Two sampling resolutions:
- Lightmapped triangles (
LightmappedShape, e.g. the wrapped polygons of a lightmapping-enabledLightmappedCompositeShape): per-texel sampling. Shadows and gradients live INSIDE the polygon surface; the painted texture is the premultiplied composite (baseColor x ambient+direct+indirect), regenerated on GI threads every 500 ms during the bake and swapped in double-buffered — painters never see a half-updated texture. - Plain solid polygons: per-polygon sampling; the result
feeds the flat-shading path through
GiLightProvider(shadow tests + indirect add). Polygons stay single-colored. - Mesh blocks (
TriangleMeshBlock, lean flat-array game geometry): per-triangle sampling like plain polygons. Light totals (direct + indirect) are written straight into the block'sgiLightarray at each generation barrier; the paint path multiplies texels by them.
Render-side cost: zero ray casting. Lightmapped triangles paint from their current composite texture; the flat-shading path only reads cached per-polygon values. Frame rate is unaffected by GI quality.
Limitations: diffuse light only; polygon vertices are used in composite-local space, so scenes combining composites with non-identity transforms are traced incorrectly.
Radius gating (e3d.giStage2Radius/ giStage3Radius/
giStage4Radius in ~/.config/aukio/config.yaml, or the
corresponding -De3d.gi.stage*Radius properties): in huge
streaming worlds the full-scene stages would never reach the camera
area, so each stage past 1 can be limited to a distance bubble around
the camera. Entries beyond the stage-2 radius keep their stage-1
direct stamp; lightmapped triangles beyond the stage-3 radius keep
the stage-2 display and never allocate texels; lightmaps beyond the
stage-4 radius are never refined to full density. Eligibility is
re-evaluated from the LIVE camera position at every generation
barrier, so the bubble follows the camera; entries that become
eligible after the bake converged get a local catch-up (one bounce
against the frozen converged field). Stage 1 stays global on purpose:
bounce rays read the hit surface's stage-1 visibility bits
everywhere. Mesh-block triangles additionally gain per-texel
lightmaps inside the stage-3 bubble (they are the only geometry kind
in streaming game worlds); their composites carry the block's photo
texture resampled into lightmap space, and finished composites are
kept in a geometry-keyed LightmapCache so a cell that streams
out and back in restores its lightmaps instantly. A stage-3 radius of
0 disables mesh-block lightmapping entirely (the historical
behavior).
Usage:
GlobalIllumination gi = viewPanel.enableGlobalIllumination(); // 2 threads
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionstatic final classStatus snapshot for the developer-tools GI row (also handy in logs). -
Constructor Summary
ConstructorsConstructorDescriptionGlobalIllumination(ShapeCollection shapes, LightingManager lightingManager, int threadCount) Creates the GI system.GlobalIllumination(ShapeCollection shapes, LightingManager lightingManager, int threadCount, Supplier<Point3D> cameraPosition) Creates the GI system. -
Method Summary
Modifier and TypeMethodDescriptionvoidaddIndirectLight(SolidPolygon polygon, Color baseColor, Color result) Adds the polygon's indirect (bounced light) contribution to an already computed direct-lighting color, in place.Reads a consistent-enough status snapshot for display; safe to call from any thread (UI polls it a few times a second).intReturns the number of traceable entries (triangles) in the current scene snapshot.booleanReturns whether the bake has completed: all generations traced (or the delta threshold reached) and the per-texel arrays freed.booleanisLightVisible(SolidPolygon polygon, LightSource light) Tells whether a light source currently has an unobstructed path to the polygon.booleanReturns whether the GI worker threads are running.static doublelightmapUnitsPerTexel(double base) Units-per-texel that lightmap construction should use while the pipeline starts coarse (stage 3): the configured value scaled bySTAGE3_TEXEL_FACTOR.voidsetMeshUnitsPerTexelOverride(Double unitsPerTexel) Overrides the mesh-block lightmap texel density for THIS GI system (EngineConfig giMeshUnitsPerTexel untouched).voidsetRadiusOverrides(Double stage2, Double stage3, Double stage4) Overrides the radius-gating config values for THIS GI system only (EngineConfig giStage2/3/4Radius untouched).voidstart()Registers the GI provider and starts the worker threads.voidstop()Stops the worker threads and unregisters the provider.
-
Constructor Details
-
GlobalIllumination
Creates the GI system. Callstart()to begin tracing. Distance ordering is disabled (uniform order).- Parameters:
shapes- the scene to tracelightingManager- the lights to samplethreadCount- dedicated worker threads (2 is a good default)
-
GlobalIllumination
public GlobalIllumination(ShapeCollection shapes, LightingManager lightingManager, int threadCount, Supplier<Point3D> cameraPosition) Creates the GI system. Callstart()to begin tracing.- Parameters:
shapes- the scene to tracelightingManager- the lights to samplethreadCount- dedicated worker threads (2 is a good default)cameraPosition- supplies the camera position for the near-to-far bake order; null disables distance ordering (uniform order)
-
-
Method Details
-
lightmapUnitsPerTexel
public static double lightmapUnitsPerTexel(double base) Units-per-texel that lightmap construction should use while the pipeline starts coarse (stage 3): the configured value scaled bySTAGE3_TEXEL_FACTOR. Callers pass the fine value when constructing at final resolution (fine phase, or late entrants after the bake). Read atLightmappedTriangleconstruction time — changing it takes effect on the next render-list rebuild.- Parameters:
base- the composite's configured units per texel- Returns:
- the effective units per texel for new lightmaps
-
getStatus
Reads a consistent-enough status snapshot for display; safe to call from any thread (UI polls it a few times a second).- Returns:
- the current GI status
-
setRadiusOverrides
Overrides the radius-gating config values for THIS GI system only (EngineConfig giStage2/3/4Radius untouched). Needed when one JVM hosts scenes of wildly different scales (the demo launcher: an FO4 cell at 1 unit = 1.43 cm vs a 48 000-unit procedural district) — a global -D/config.yaml value cannot fit both. Pass null to keep the configured value for a stage.Call BEFORE
start()(or via the ViewPanel enable-overload that applies it pre-start) so the first eligibility evaluation already uses the overrides. -
setMeshUnitsPerTexelOverride
Overrides the mesh-block lightmap texel density for THIS GI system (EngineConfig giMeshUnitsPerTexel untouched). Call beforestart(); seesetRadiusOverrides(Double, Double, Double). -
start
public void start()Registers the GI provider and starts the worker threads. -
stop
public void stop()Stops the worker threads and unregisters the provider. -
isRunning
-
isConverged
public boolean isConverged()Returns whether the bake has completed: all generations traced (or the delta threshold reached) and the per-texel arrays freed. The workers then idle at a low cadence, watching for scene changes.- Returns:
truewhen baked
-
getWorkItemCount
public int getWorkItemCount()Returns the number of traceable entries (triangles) in the current scene snapshot. 0 when no snapshot has been built yet.- Returns:
- the entry count
-
isLightVisible
Description copied from interface:GiLightProviderTells whether a light source currently has an unobstructed path to the polygon. Until the provider has computed the answer, it should returntrue(light visible): shadows then fade in gradually instead of popping out.- Specified by:
isLightVisiblein interfaceGiLightProvider- Parameters:
polygon- the shaded polygonlight- the light source being evaluated- Returns:
- true if the light reaches the polygon
-
addIndirectLight
Description copied from interface:GiLightProviderAdds the polygon's indirect (bounced light) contribution to an already computed direct-lighting color, in place.- Specified by:
addIndirectLightin interfaceGiLightProvider- Parameters:
polygon- the shaded polygonbaseColor- the polygon's unlit color (for albedo scaling)result- the direct-lighted color to augment (modified in place)
-