Builds the instanced-quad base geometry used by PointMaterial and
PointPickingMaterial, plus the texture-backed per-point storage
(depth-sorting Phase 4 points migration). Each point is rendered as an
axis-aligned quad with 4 corner vertices; the vertex shader expands the
quad into a screen-space sprite of the per-instance size (replacing
gl_PointSize, which r184's GLSLNodeBuilder hardcodes to 1.0 for
THREE.Points).
Per-point data lives in an RGBA32F point texture (3 texels/point —
see ./element-texture-layout for the layout authority) sampled by the
vertex shader via texelFetch. The only per-instance data is the
double-buffered ordering pair aSortedIndex / aSortedIndexB (Uint32),
which maps the draw slot to a storage slot so draw order can be
permuted without rewriting point data. The per-texel
layout is FIXED regardless of which optional fields the dataset has
(pool geometries are reused across nodes, so the layout never varies):
texel
rgba
0
center.xyz, radius
1
color.rgb, sharpness
2
scalar (0.0 when no scalars), alpha, 0, 0
texel2.x is the colormap scalar and texel2.y the per-point opacity
alpha (the RGBA color column when the dataset carries one — volumetric
Phase 3 — else the 1.0 opaque identity); BOTH are written
UNCONDITIONALLY — pool textures are reused, so leaving them
unspecified would let a previous tenant's values leak through. 0.0 is
the no-scalar identity and 1.0 (opaque) the per-element-opacity
identity. texel2.zw stay unspecified (stale on reused pool textures;
never read).
Texture lifetime = geometry lifetime: attachPointStorage registers a
dispose listener on the geometry, so every dispose site (pool
evictors, pool.dispose(), the non-pool dispose+recreate commit) frees
the texture with the geometry — no site-by-site bookkeeping.
All source arrays consumed by the texel writer are ALREADY-WIDENED
Float32 — dtype normalization (Uint8/255, Uint16/65535, Float16 copy)
happens at the call sites (gpu-buffer-pool/points-adapter.ts,
node-factory/create-points-node.ts) with the exact same
widenToFloat32 calls and fallback fills as the interleaved era, so
the floats landing in texels are bit-identical to what the old
per-attribute path uploaded.
Mirrors gsplat-geometry.ts (which pioneered this migration) so the
geometry types share one storage model; the geometry-agnostic helpers
live in ./element-storage.
Point Geometry Creation for Luxar
Builds the instanced-quad base geometry used by
PointMaterialandPointPickingMaterial, plus the texture-backed per-point storage (depth-sorting Phase 4 points migration). Each point is rendered as an axis-aligned quad with 4 corner vertices; the vertex shader expands the quad into a screen-space sprite of the per-instance size (replacinggl_PointSize, which r184'sGLSLNodeBuilderhardcodes to1.0forTHREE.Points).Per-point data lives in an RGBA32F point texture (3 texels/point — see
./element-texture-layoutfor the layout authority) sampled by the vertex shader viatexelFetch. The only per-instance data is the double-buffered ordering pairaSortedIndex/aSortedIndexB(Uint32), which maps the draw slot to a storage slot so draw order can be permuted without rewriting point data. The per-texel layout is FIXED regardless of which optional fields the dataset has (pool geometries are reused across nodes, so the layout never varies):texel2.x is the colormap scalar and texel2.y the per-point opacity alpha (the RGBA color column when the dataset carries one — volumetric Phase 3 — else the 1.0 opaque identity); BOTH are written UNCONDITIONALLY — pool textures are reused, so leaving them unspecified would let a previous tenant's values leak through. 0.0 is the no-scalar identity and 1.0 (opaque) the per-element-opacity identity. texel2.zw stay unspecified (stale on reused pool textures; never read).
Texture lifetime = geometry lifetime:
attachPointStorageregisters adisposelistener on the geometry, so every dispose site (pool evictors,pool.dispose(), the non-pool dispose+recreate commit) frees the texture with the geometry — no site-by-site bookkeeping.All source arrays consumed by the texel writer are ALREADY-WIDENED Float32 — dtype normalization (Uint8/255, Uint16/65535, Float16 copy) happens at the call sites (
gpu-buffer-pool/points-adapter.ts,node-factory/create-points-node.ts) with the exact samewidenToFloat32calls and fallback fills as the interleaved era, so the floats landing in texels are bit-identical to what the old per-attribute path uploaded.Mirrors
gsplat-geometry.ts(which pioneered this migration) so the geometry types share one storage model; the geometry-agnostic helpers live in./element-storage.