Class Lightmap

java.lang.Object
eu.svjatoslav.aukio.e3d.renderer.raster.gi.Lightmap

public class Lightmap extends Object
Per-triangle lightmap: a small generated texture whose texels map onto the triangle surface. The grid is an ORTHOGONAL frame on the triangle's plane, not the triangle's own edge frame (that sheared texels into diamonds on acute triangles — bugreport-20261005-192002): the longest edge is the u-axis, the v-axis is the in-plane perpendicular, and the texture covers the triangle's bounding rectangle in that frame. The triangle's UVs (texture pixel units) are (0,0), (width,0), (apexU*width, height); texels outside the triangle are filled from valid neighbors to keep mipmaps and edge sampling clean. Texels are square in world space on every triangle, and the bounding rect is exactly 2x the triangle's area — the same overhead class as the old half-empty edge-frame texture.

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

    Fields
    Modifier and Type
    Field
    Description
    double
    Parametric u of the apex vertex in the bounding-rect frame.
    boolean
    True once the bake has finished and the texel arrays are freed.
    final Color
    Unlit 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.
    boolean
    True once this lightmap has traced its per-texel direct light (engine directPass) or had a fully-baked composite restored from the lightmap cache.
    final double
     
    final double
     
    final double
     
    final double
     
    final double
     
    final double
     
    int
    Radius-gating mask of the owning triangle, mirroring TriangleBvh.Entry.eligibleStages (set at every generation barrier from the live camera position).
    boolean
    True once a real composite (traced lighting) has been swapped in.
    double
    Units-per-texel of the FINAL (stage-4) resolution: the raw configured value, before the stage-3 coarsening factor.
    int
    Completed generations: 0 = none, 1 = direct, k = k generations done.
    int
     
    float[]
     
    float[]
     
    float[]
    Accumulated indirect irradiance total, pre-albedo light units: the sum of all completed bounce generations, displayed by the composite texture.
    static final double
    Irradiance 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.
    int
     
    byte[]
    Per-texel per-light visibility, written in generation 1: texelCount * lightCount bytes, indexed texel * lightCount + lampIndex.
    final double
    Unit surface normal.
    final double
    Unit surface normal.
    final double
    Unit surface normal.
    final double
     
    final double
     
    final double
     
    The triangle currently displaying this lightmap (for texture swaps).
    int[]
    Valid (inside-the-triangle) texel indices, for generation sampling.
    static final byte
    Visibility value: shadow ray was blocked.
    static final byte
    Visibility value: not yet computed.
    static final byte
    Visibility value: shadow ray reached the light.
    int
     
  • Constructor Summary

    Constructors
    Constructor
    Description
    Lightmap(Point3D a, Point3D b, Point3D c, Color baseColor, double unitsPerTexel, double normalX, double normalY, double normalZ)
    Creates a lightmap for a triangle.
  • Method Summary

    Modifier and Type
    Method
    Description
    The texture GI should write the next composite into.
    int
    baseColorAt(int texel)
    Base color of one texel for compositing: the photo-texture sample when baseTexels exists (mesh-block lightmaps), the flat baseColor otherwise.
    int
    baseColorAtUv(double u, double v)
    Base color at a parametric (u, v), sampled at the base array's OWN dimensions.
    void
    ensureArrays(int lights)
    Allocates the per-texel bake state (indirect total, both delta buffers, visibility) and re-arms the bake progression.
    void
    Frees all per-texel bake state at the end of the global bake.
    boolean
    isValidTexel(int i, int j)
    /** Inside-triangle test in texture space for smoothing/neighborhood queries — the same region validTexels was built from (bounding-rect frame: NOT the whole texture, NOT the old half-square).
    boolean
    True when this lightmap still runs at a coarser resolution than fineUnitsPerTexel implies (i.e.
    void
    Stage 4: reallocates this lightmap at fineUnitsPerTexel after the coarse bake converged.
    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.
    double
    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).
    void
    setBaseTextureMapping(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.
    void
    Flips the buffers after the back texture has been regenerated.
    int
    texelAt(double px, double py, double pz)
    Texel index nearest to a world point on the triangle plane.
    void
    texelWorldPosition(int texel, double[] out)
    World position of a texel center.
    void
    uvAt(double px, double py, double pz, double[] out)
    Parametric (u, v) of a world-space point on this lightmap's quad.
    double
    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)).

    Methods inherited from class Object

    clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
  • Field Details

    • VISIBILITY_UNKNOWN

      public static final byte VISIBILITY_UNKNOWN
      Visibility value: not yet computed.
      See Also:
    • VISIBILITY_VISIBLE

      public static final byte VISIBILITY_VISIBLE
      Visibility value: shadow ray reached the light.
      See Also:
    • VISIBILITY_OCCLUDED

      public static final byte VISIBILITY_OCCLUDED
      Visibility value: shadow ray was blocked.
      See Also:
    • INITIAL_IRRADIANCE

      public static final double INITIAL_IRRADIANCE
      Irradiance 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

      public final Color 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 normalX
      Unit surface normal.
    • normalY

      public final double normalY
      Unit surface normal.
    • normalZ

      public final double normalZ
      Unit surface normal.
    • validTexels

      public int[] validTexels
      Valid (inside-the-triangle) texel indices, for generation sampling.
    • cornerU

      public final double[] cornerU
      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). Painters pin per-vertex UVs to (cornerU[k]*width, cornerV[k]*height).
    • cornerV

      public final double[] cornerV
    • apexU

      public double apexU
      Parametric u of the apex vertex in the bounding-rect frame.
    • fineUnitsPerTexel

      public double fineUnitsPerTexel
      Units-per-texel of the FINAL (stage-4) resolution: the raw configured value, before the stage-3 coarsening factor. LightmappedTriangle overwrites 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[] indirectR
      Accumulated 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[] deltaPrevR
      Last 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[] deltaCurR
      In-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 into deltaPrevR at the generation barrier. Null outside an active bake.
    • deltaCurG

      public volatile float[] deltaCurG
    • deltaCurB

      public volatile float[] deltaCurB
    • lightVisibility

      public byte[] lightVisibility
      Per-texel per-light visibility, written in generation 1: texelCount * lightCount bytes, indexed texel * 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 generation
      Completed generations: 0 = none, 1 = direct, k = k generations done.
    • baked

      public volatile boolean baked
      True once the bake has finished and the texel arrays are freed.
    • directBaked

      public volatile boolean directBaked
      True once this lightmap has traced its per-texel direct light (engine directPass) 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 eligibleStages
      Radius-gating mask of the owning triangle, mirroring TriangleBvh.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 everComposited
      True 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

      public volatile LightmappedTriangle 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 color
      unitsPerTexel - world units per lightmap texel (resolution knob)
      normalX - unit normal x
      normalY - unit normal y
      normalZ - 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 when baseTexels exists (mesh-block lightmaps), the flat baseColor otherwise.
      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 concurrent refine(): 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..1
      v - parametric v, 0..1
      Returns:
      ARGB base color
    • setBaseTextureMapping

      public void setBaseTextureMapping(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. 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 texture
      uv - 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 region validTexels was built from (bounding-rect frame: NOT the whole texture, NOT the old half-square).
    • refine

      public void refine()
      Stage 4: reallocates this lightmap at fineUnitsPerTexel after 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 than fineUnitsPerTexel implies (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 x
      py - world y
      pz - 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 worker refine()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 x
      py - world y
      pz - world z
      out - 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

      public Texture shownTexture()
      The texture the triangle should show right now.
      Returns:
      the front composite texture
    • backTexture

      public 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.