Class Lightmap
What you trace is what you see: the composite texture the painter samples IS the lightmap, at native texel resolution. Shadow-edge smoothness comes from tracing at finer resolution (smaller unitsPerTexel), never from upsampling.
Bake state: the GI system bakes lighting in strict global generations (1 = direct, k = k-th bounce generation). While baking, each lightmap carries three per-texel float field sets:
indirectR/indirectG/indirectB— the accumulated indirect total (sum of all completed generations), the value the composite texture displays.deltaPrevR/deltaPrevG/deltaPrevB— the last completed generation's delta: the gather source for the generation currently being traced (strict ordering: generation k reads only generation k-1 output). Read-only between generation barriers.deltaCurR/deltaCurG/deltaCurB— the in-progress generation's accumulator: a running mean over the samples cast so far this generation, composited as a live preview.
All texel arrays are allocated lazily when the bake reaches the lightmap (lightmapped scenes that never enable GI pay only the two composite textures) and are freed when the global bake completes — after that, the composite texture is final and the only remaining per-texel state. A scene or light change starts a new bake and re-allocates them.
Threading: texel state arrays are written by the single GI worker
that owns the entry and read by whoever holds the snapshot (other
workers' bounce rays, the compositor); element-wise racy access is
benign for progressive refinement. Texture buffer swaps are
volatile/atomic via TexturedTriangle.setTexture(Texture).
-
Field Summary
FieldsModifier and TypeFieldDescriptiondoubleParametric u of the apex vertex in the bounding-rect frame.booleanTrue once the bake has finished and the texel arrays are freed.final ColorUnlit surface color of the triangle.final double[]Frame-space (u, v) of each CONSTRUCTOR vertex (a, b, c order), 0..1: one is (0,0), one is (1,0), one is (apexU, 1).final double[]float[]float[]float[]In-progress generation accumulator: a running mean over the samples cast so far this generation.float[]float[]float[]Last completed generation's indirect delta, pre-albedo light units: the gather source for the generation currently being traced.booleanTrue once this lightmap has traced its per-texel direct light (enginedirectPass) or had a fully-baked composite restored from the lightmap cache.final doublefinal doublefinal doublefinal doublefinal doublefinal doubleintRadius-gating mask of the owning triangle, mirroringTriangleBvh.Entry.eligibleStages(set at every generation barrier from the live camera position).booleanTrue once a real composite (traced lighting) has been swapped in.doubleUnits-per-texel of the FINAL (stage-4) resolution: the raw configured value, before the stage-3 coarsening factor.intCompleted generations: 0 = none, 1 = direct, k = k generations done.intfloat[]float[]float[]Accumulated indirect irradiance total, pre-albedo light units: the sum of all completed bounce generations, displayed by the composite texture.static final doubleIrradiance the composite texture starts at (light units, display scale 0..255): the default 255 shows every lightmapped triangle in its true base color from frame one ("unlit, as-is"), then each lightmap flips to its traced lighting when the bake reaches it.intbyte[]Per-texel per-light visibility, written in generation 1: texelCount * lightCount bytes, indexedtexel * lightCount + lampIndex.final doubleUnit surface normal.final doubleUnit surface normal.final doubleUnit surface normal.final doublefinal doublefinal doubleThe triangle currently displaying this lightmap (for texture swaps).int[]Valid (inside-the-triangle) texel indices, for generation sampling.static final byteVisibility value: shadow ray was blocked.static final byteVisibility value: not yet computed.static final byteVisibility value: shadow ray reached the light.int -
Constructor Summary
Constructors -
Method Summary
Modifier and TypeMethodDescriptionThe texture GI should write the next composite into.intbaseColorAt(int texel) Base color of one texel for compositing: the photo-texture sample whenbaseTexelsexists (mesh-block lightmaps), the flatbaseColorotherwise.intbaseColorAtUv(double u, double v) Base color at a parametric (u, v), sampled at the base array's OWN dimensions.voidensureArrays(int lights) Allocates the per-texel bake state (indirect total, both delta buffers, visibility) and re-arms the bake progression.voidFrees all per-texel bake state at the end of the global bake.booleanisValidTexel(int i, int j) /** Inside-triangle test in texture space for smoothing/neighborhood queries — the same regionvalidTexelswas built from (bounding-rect frame: NOT the whole texture, NOT the old half-square).booleanTrue when this lightmap still runs at a coarser resolution thanfineUnitsPerTexelimplies (i.e.voidrefine()Stage 4: reallocates this lightmap atfineUnitsPerTexelafter the coarse bake converged.voidrestoreComposite(int[] pixels) Cache restore: replaces both composite buffers with the given baked pixels (dimensions must match — the cache checks before calling) and marks the lightmap baked.doublerollover()Generation barrier rollover: folds the finished generation's delta into the accumulated total, then makes it the new gather source (delta buffers swapped, the fresh one zeroed).voidsetBaseTextureMapping(Texture texture, double[] uv) Switches this lightmap to photo-texture compositing (mesh-block triangles): samples the base texture into per-texel base colors at the current resolution.The texture the triangle should show right now.voidFlips the buffers after the back texture has been regenerated.inttexelAt(double px, double py, double pz) Texel index nearest to a world point on the triangle plane.voidtexelWorldPosition(int texel, double[] out) World position of a texel center.voiduvAt(double px, double py, double pz, double[] out) Parametric (u, v) of a world-space point on this lightmap's quad.doubleUV perimeter of this lightmap in primary-texture pixels — the mipmap metric's texture side for triangles painted from this lightmap (UVs (0,0), (width,0), (0,height)).
-
Field Details
-
VISIBILITY_UNKNOWN
public static final byte VISIBILITY_UNKNOWNVisibility value: not yet computed.- See Also:
-
VISIBILITY_VISIBLE
public static final byte VISIBILITY_VISIBLEVisibility value: shadow ray reached the light.- See Also:
-
VISIBILITY_OCCLUDED
public static final byte VISIBILITY_OCCLUDEDVisibility value: shadow ray was blocked.- See Also:
-
INITIAL_IRRADIANCE
public static final double INITIAL_IRRADIANCEIrradiance the composite texture starts at (light units, display scale 0..255): the default 255 shows every lightmapped triangle in its true base color from frame one ("unlit, as-is"), then each lightmap flips to its traced lighting when the bake reaches it. Lower values make un-baked surfaces visibly dimmer placeholders.-De3d.gi.initialIrradiance. -
width
public int width -
height
public int height -
baseColor
Unlit surface color of the triangle. -
originX
public final double originX -
originY
public final double originY -
originZ
public final double originZ -
edge1X
public final double edge1X -
edge1Y
public final double edge1Y -
edge1Z
public final double edge1Z -
edge2X
public final double edge2X -
edge2Y
public final double edge2Y -
edge2Z
public final double edge2Z -
normalX
public final double normalXUnit surface normal. -
normalY
public final double normalYUnit surface normal. -
normalZ
public final double normalZUnit surface normal. -
validTexels
public int[] validTexelsValid (inside-the-triangle) texel indices, for generation sampling. -
cornerU
public final double[] cornerUFrame-space (u, v) of each CONSTRUCTOR vertex (a, b, c order), 0..1: one is (0,0), one is (1,0), one is (apexU, 1). Painters pin per-vertex UVs to (cornerU[k]*width, cornerV[k]*height). -
cornerV
public final double[] cornerV -
apexU
public double apexUParametric u of the apex vertex in the bounding-rect frame. -
fineUnitsPerTexel
public double fineUnitsPerTexelUnits-per-texel of the FINAL (stage-4) resolution: the raw configured value, before the stage-3 coarsening factor.LightmappedTriangleoverwrites this after construction with the composite's configured value; defaults to the construction value (no coarsening ->refine()is a no-op). -
indirectR
public volatile float[] indirectRAccumulated indirect irradiance total, pre-albedo light units: the sum of all completed bounce generations, displayed by the composite texture. Null before the bake reaches this lightmap and after the bake completes. -
indirectG
public volatile float[] indirectG -
indirectB
public volatile float[] indirectB -
deltaPrevR
public volatile float[] deltaPrevRLast completed generation's indirect delta, pre-albedo light units: the gather source for the generation currently being traced. Null outside an active bake. -
deltaPrevG
public volatile float[] deltaPrevG -
deltaPrevB
public volatile float[] deltaPrevB -
deltaCurR
public volatile float[] deltaCurRIn-progress generation accumulator: a running mean over the samples cast so far this generation. Written only by the worker that owns the entry; rolled into the total and swapped intodeltaPrevRat the generation barrier. Null outside an active bake. -
deltaCurG
public volatile float[] deltaCurG -
deltaCurB
public volatile float[] deltaCurB -
lightVisibility
public byte[] lightVisibilityPer-texel per-light visibility, written in generation 1: texelCount * lightCount bytes, indexedtexel * lightCount + lampIndex. Direct light is always derived from these bytes (by the compositor and by generation-2 bounce rays), never stored separately. Null outside an active bake. -
lightCount
public int lightCount -
generation
public volatile int generationCompleted generations: 0 = none, 1 = direct, k = k generations done. -
baked
public volatile boolean bakedTrue once the bake has finished and the texel arrays are freed. -
directBaked
public volatile boolean directBakedTrue once this lightmap has traced its per-texel direct light (enginedirectPass) or had a fully-baked composite restored from the lightmap cache. False for lightmaps that only ever received the stage-1 uniform shade (outside the stage-3 radius for the whole bake): the catch-up watcher uses it to give them their direct + bounce when the radius bubble reaches them, and the cache refuses to store their shade-only composites. -
eligibleStages
public volatile int eligibleStagesRadius-gating mask of the owning triangle, mirroringTriangleBvh.Entry.eligibleStages(set at every generation barrier from the live camera position). Read at the coarse→fine transition (bit 2 = stage-4 eligible) and in termination accounting (current-phase bit). -
everComposited
public volatile boolean everCompositedTrue once a real composite (traced lighting) has been swapped in. Until then the texture still holds the initial base-color fill, and the stage-1 uniform preview may stamp the owner's per-triangle GI shade on top of it. Sticky across rebakes: a lightmap that has shown traced lighting keeps its old composite until the new direct pass lands — no uniform preview on rebake. -
owner
The triangle currently displaying this lightmap (for texture swaps).
-
-
Constructor Details
-
Lightmap
public Lightmap(Point3D a, Point3D b, Point3D c, Color baseColor, double unitsPerTexel, double normalX, double normalY, double normalZ) Creates a lightmap for a triangle.- Parameters:
a- first vertex (UV 0,0)b- second vertex (UV 1,0)c- third vertex (UV 0,1)baseColor- unlit surface colorunitsPerTexel- world units per lightmap texel (resolution knob)normalX- unit normal xnormalY- unit normal ynormalZ- unit normal z
-
-
Method Details
-
uvPerimeter
public double uvPerimeter()UV perimeter of this lightmap in primary-texture pixels — the mipmap metric's texture side for triangles painted from this lightmap (UVs (0,0), (width,0), (0,height)).- Returns:
- width + height + hypot(width, height)
-
baseColorAt
public int baseColorAt(int texel) Base color of one texel for compositing: the photo-texture sample whenbaseTexelsexists (mesh-block lightmaps), the flatbaseColorotherwise.- Parameters:
texel- texel index (j * width + i)- Returns:
- ARGB base color
-
baseColorAtUv
public int baseColorAtUv(double u, double v) Base color at a parametric (u, v), sampled at the base array's OWN dimensions. Race-safe against a concurrentrefine(): the (pixels, width, height) triple is swapped atomically, so the sample is always in bounds — possibly at the pre-refine resolution, which carries the same photo content.- Parameters:
u- parametric u, 0..1v- parametric v, 0..1- Returns:
- ARGB base color
-
setBaseTextureMapping
Switches this lightmap to photo-texture compositing (mesh-block triangles): samples the base texture into per-texel base colors at the current resolution. Bilinear with wrap-aware fetch, over ALL texels — the mirrored (u+v > 1) half maps to the mirrored triangle region and is filled by the compositor's neighbor fill, so it must carry plausible colors too.- Parameters:
texture- the block triangle's base textureuv- 6 UV doubles (u0,v0,u1,v1,u2,v2), primary-texture pixels
-
restoreComposite
public void restoreComposite(int[] pixels) Cache restore: replaces both composite buffers with the given baked pixels (dimensions must match — the cache checks before calling) and marks the lightmap baked. No texel arrays are allocated; the lightmap is display-complete without any bake.- Parameters:
pixels- ARGB composite, width * height ints
-
isValidTexel
public boolean isValidTexel(int i, int j) /** Inside-triangle test in texture space for smoothing/neighborhood queries — the same regionvalidTexelswas built from (bounding-rect frame: NOT the whole texture, NOT the old half-square). -
refine
public void refine()Stage 4: reallocates this lightmap atfineUnitsPerTexelafter the coarse bake converged. The shown composite is upscaled into the new buffers (the display does not regress at the transition itself), then the texel arrays drop to null and the fine bake rebuilds them from direct. Visibility is dropped: generation 1 re-traces shadow rays at the final resolution. No-op when the coarse and fine resolutions coincide (tiny lightmaps at the 4-texel floor).The coarse field seeds the DISPLAY only, never the solver: the fine Neumann chain rebuilds every bounce path at fine resolution, and carrying the coarse total into the accumulated indirect would count the whole series twice (measured: floor probes at 44.0 instead of the correct 27.7).
-
needsRefine
public boolean needsRefine()True when this lightmap still runs at a coarser resolution thanfineUnitsPerTexelimplies (i.e.refine()would reallocate). Used by the GI catch-up watcher: a coarse-baked lightmap whose triangle enters the stage-4 radius gets refined and re-baked at the final density.- Returns:
- true when a refine would change the dimensions
-
texelWorldPosition
public void texelWorldPosition(int texel, double[] out) World position of a texel center.- Parameters:
texel- texel index (j * width + i)out- receives x, y, z
-
texelAt
public int texelAt(double px, double py, double pz) Texel index nearest to a world point on the triangle plane.- Parameters:
px- world xpy- world ypz- world z- Returns:
- texel index, clamped into the texture
-
uvAt
public void uvAt(double px, double py, double pz, double[] out) Parametric (u, v) of a world-space point on this lightmap's quad. Resolution-independent: callers sampling a texture whose size can change under them (GI catch-up reading a composite while another workerrefine()s this lightmap) scale (u, v) by the texture's own dimensions and stay in bounds. Values may fall slightly outside 0..1 for edge hits; callers clamp after scaling.- Parameters:
px- world xpy- world ypz- world zout- receives {u, v}
-
ensureArrays
public void ensureArrays(int lights) Allocates the per-texel bake state (indirect total, both delta buffers, visibility) and re-arms the bake progression. Idempotent; called from GI threads when the bake reaches this lightmap, and again when a scene change restarts the bake after the arrays were freed. A bake restart over previously used arrays also zeroes the accumulated totals so the old solution cannot leak into the new one (the delta buffers need no clearing: generation 2 reads only visibility, and deltaPrev is rewritten by the generation-2 rollover before generation 3 reads it).- Parameters:
lights- number of lights in the snapshot
-
freeArrays
public void freeArrays()Frees all per-texel bake state at the end of the global bake. The double-buffered composite textures stay — from here on they are the only per-texel state, and the displayed one is final. -
rollover
public double rollover()Generation barrier rollover: folds the finished generation's delta into the accumulated total, then makes it the new gather source (delta buffers swapped, the fresh one zeroed). Called by the GI system only, with no sampling in flight.- Returns:
- the generation's absolute per-texel delta summed over the valid texels (light units), the termination signal
-
shownTexture
The texture the triangle should show right now.- Returns:
- the front composite texture
-
backTexture
The texture GI should write the next composite into.- Returns:
- the back composite texture
-
swapBuffers
public void swapBuffers()Flips the buffers after the back texture has been regenerated.
-