three-virtual-geometry 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +14 -0
- package/dist/core/import/fromObject3D.d.ts +3 -3
- package/dist/core/io/cache.d.ts +1 -1
- package/dist/core/io/serialize.d.ts +1 -1
- package/dist/core/runtime/GeometryPool.d.ts +2 -2
- package/dist/core/runtime/OcclusionCulling.d.ts +1 -1
- package/dist/core/runtime/VirtualGeometry.d.ts +6 -6
- package/dist/core/runtime/VirtualMesh.d.ts +4 -4
- package/dist/core/runtime/cut.d.ts +1 -1
- package/dist/index.d.ts +20 -20
- package/dist/index.js.map +1 -1
- package/dist/source.d.ts +1 -1
- package/dist/three-virtual-geometry.all.min.js +1 -1
- package/dist/three-virtual-geometry.min.js +2 -2
- package/dist/three-virtual-geometry.min.js.map +2 -2
- package/package.json +5 -3
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":["mortonOrder","minNode","maxNode","VirtualMeshClass","THREE","MAX_MESHLET_TRIANGLES","MAX_MESHLET_VERTICES","ERROR_INFINITY","FAST_PATH_MARGIN","VG_DEBUG_MODES","partitionMeshlets","count","meshlets","groupSize","i","edgeOwners","e","owners","adjacency","a","b","j","order","mortonOrder$1","m","assigned","groups","seed","group","frontier","addNeighbours","n","shared","best","bestScore","bestDist","score","d","dist2","result","pending","minSize","dx","dy","dz","min","max","p","points","k","extent","codes","q","part1By2","x","buildVoxelProxy","indices","o","positions","cell","resolution","origin","nx","ny","nz","sy","sz","total","occupied","colorSum","colors","colorCount","voxelUv","uvs","sampleU","sampleV","mark","y","z","g","t","c","longest","dist","steps","u","v","w","ta","tb","tc","closed","erode","dilate","field","blurAxis","ISO","cellsX","cellsY","cellsZ","cellVertex","outPositions","outNormals","outColors","outUvs","corner","base","inside","px","py","pz","crossings","bit","f0","f1","s","gx","gy","gz","len","r","outIndices","cellIndex","quad","ux","uy","uz","vx","vy","vz","cx","cy","cz","nx_","ny_","nz_","here","proxyColors","fillMissing","proxyUvs","src","axis","morph","stride","size","out","prev","next","grow","line","lines","l","start","values","pass","missing","sum","hits","DEFAULTS","TAIL_START_TRIANGLES","VOXEL_RESOLUTIONS","yieldToBrowser","buildVirtualMesh","opts","options","t0","MeshoptClusterizer","MeshoptSimplifier","normals","weld","voxelLevels","flags","all","proxyCache","leafs","splitIntoMeshlets","current","lastTriangles","countTriangles","lodLevels","estimatedTotal","level","groupIdx","merged","concatIndices","local","compact","target","simplified","simplifyError","lodSphere","enclosingSphere","childError","shapeError","extentShrink","error","child","globalIndices","outputs","triangles","simplifyTail","pack","appendVertices","first","uv","voxelProxy","roots","levels","tailFlags","nodes","keepLimit","sloppy","relativeError","parentError","voxel","proxy","proxyTarget","proxyError","voxelError","used","pick","node","built","vertexOffset","triangleOffset","vertexCount","triangleCount","vertices","localTriangles","meshletIndices","cullSphere","boundingSphere","meshlet","findBoundaryEdges","unsorted","meshletCount","acc","meshletBounds","meshletInfo","indexOf","replacementStart","replacementIndices","meshletVertices","meshletTriangles","firstIndex","stats","tri","whole","levelCount","levelRanges","levelErrors","levelGuardErrors","lodBoundsSphere","cullBoundsSphere","box","before","after","shrink","localOf","toGlobalAll","localIndices","toGlobal","localPositions","edgeTableKeys","edgeTableCounts","edgeOrder","edgeCount","mask","inserted","key","edgeKey","h","offset","r2","spheres","centers","radii","radius","VG_FORMAT_VERSION","MAGIC","PREFIX_BYTES","TYPED_ARRAYS","FIELD_HINTS","VirtualMeshFormatError","message","encodeVirtualMesh","compress","MeshoptEncoder","record","data","keys","fields","blobs","name","value","type","array","blob","entry","indicesMatchMeshlets","encodeField","bytesOf","align4","headerJson","headerBytes","jsonReplacer","headerPadded","payloadStart","f","view","checksum","decodeVirtualMesh","bytes","input","version","headerLength","header","jsonReviver","payload","arrays","rank","MeshoptDecoder","fail","inflate","decodeField","loadVirtualMesh","source","response","init","raw","hint","rawCandidate","candidates","encodeMeshletTriangles","strides","useDeflate","canDeflate","toDeflate","deflate","sameBytes","slots","covered","packed","codec","decoded","rotations","rebuildIndices","Ctor","requireArray","forField","decodeMeshletTriangles","codecLength","rotationsStart","length","words","stream","VG_BUILD_VERSION","DB_NAME","DATA_STORE","META_STORE","MAX_CACHE_BYTES","OPEN_TIMEOUT_MS","buildVirtualMeshCached","buildOptions","cache","hasIndexedDb","virtualMeshCacheKey","db","openDb","readEntry","touchEntry","clearVirtualMeshCache","tx","resolve","versions","customKey","subtle","names","describe","parts","optionEntries","text","digests","combined","hash","dbPromise","timer","done","request","writeEntry","evict","store","meta","deleteEntry","keysRequest","valuesRequest","entries","keep","selectCut","B","selected","projectedError","distance","own","parent","threshold","verifyCutCoverage","list","isCovered","holes","lodDistanceBounds","R","instanceMeshletRange","dMin","dMax","lo","hi","minOwn","maxParent","ownPossible","parentPossible","instanceGuaranteedRange","margin","possibleMeshlets","guaranteedMeshlets","maxOwn","minParent","ownSure","parentSure","end","vgUv","varyingProperty","getUV","vgTexture","texture","map","TWO_CHANNEL_FORMATS","vgNormalMap","sample","xy","vec3","sqrt","float","scale","transformNormalToView","q0","positionView","q1","st0","st1","N","normalView","q1perp","q0perp","T","det","mat3","negateOnBackSide","bindVirtualGeometryTextures","material","isTexture","color","vec4","materialColor","materialReference","bumpMap","context","minNode$1","maxNode$1","vgWorldNormal","vgMeshletVarying","vgLodVarying","vgInstanceVarying","vgTintVarying","LOCAL_VERTEX_BITS","LOCAL_VERTEX_MASK","MAX_DISPATCH","CULL_GROUP","MESHLET_GROUP","EXPAND_GROUP","MAX_LEVELS","MESH_STRIDE","INSTANCE_STRIDE","CELL_STRIDE","DRAW_DISTANCE_FADE","NO_DRAW_DISTANCE","CUT_COUNTERS","C_SELECTED","C_DRAWN","C_SURVIVED","C_WORK","C_REQUESTED","PER_MESH_COUNTERS","GrowBuffer","make","itemSize","maxItems","capacity","needed","f32","u32","GeometryPool","uniform","maxBytes","limit","bytesPerItem","add","instanceCount","slot","matrices","cellCount","at","buffer","gpuToInput","old","shift","levelsStart","grownSize","table","vd","asFloat","encodeOctNormal","va","packUvs","info","mv","set","index","gpuIndex","cells","maxRadius","instanceSphere","backend","renderer","ctx","cap","maxDrawn","instanceCapacity","cellCapacity","cameraIndexCapacity","shadowIndexCapacity","storageOf","storage","vertexData","vertexAttrs","bounds","meshTable","instances","cellListAttribute","workListAttribute","drawListAttribute","dispatchAttr","instanceArgsAttribute","meshletArgsAttributes","expandArgsAttributes","counters","drawArgs","cameraIndex","shadowIndex","cellList","cellListRead","workList","drawList","drawListRead","instanceArgs","meshletArgs","expandArgs","counter","cut","meshCount","uint","meshStart","cutCapacity","indexBuffers","shadowThreshold","thresholds","minPixelsGlobal","occlusion","instanceColumn","instanceId","modelOf","mat4","meshRecord","viewCenter","model","sphere","pixels","select","frustumDistance","minDistance","plane","dot","center","swept","occludedSphere","worldCenter","occlusionOn","dispatchArgs","resetNode","Fn","instanceIndex","If","rest","cellNode","levers","minPixels","gap","atomicAdd","uvec4","cellArgsNode","atomicLoad","levelCache","workgroupArray","selectLevels","last","l0","l1","levelFirst","possible","pixelsAtMax","pixelsAtMin","sure","cullCenter","cullBounds","cullRadius","fastPath","meshletId","item","tag","occlusionFlag","instanceNode","workgroupId","numWorkgroups","valid","levelBase","Loop","localId","workgroupBarrier","objectSphere","lodBounds","shadowOn","maxDrawDistance","noFrustum","inCamera","inShadow","viewDistance","tooSmall","tooFar","bool","lodCenter","meshletPass","work","boundsBase","visible","errors","ownError","prefixPass","requested","room","args","atomicStore","drawn","expandPass","drawSlot","regionStart","firstTriangle","vertexIndex","localVertex","vertexId","tintAndSlot","meshSlot","uvPacking","packedVertex","attrs","localPosition","bitcast","columns","originDistance","fade","worldPosition","worldNormal","normalize","decodeOctNormal","normalLocal","unpackRgba8","unpackUnorm2x16","sx","sr","c0","c1","c2","bits","pu","pv","spreadBits10","mortonOrder","radixOrder","counts","pristineMaterials","claimMaterial","pristine","placeholderGeometry","geometry","VirtualMesh","randomColor","debugColor","cameraViewMatrix","faceDirection","shadowCamera","autoUpdateHook","pool","matrix","CONVERSIONS","FLAGS","conversionOf","flag","canConvertToNodeMaterial","toNodeMaterial","conversion","Classic","Node","defines","POSITION_TOLERANCE","ATTRIBUTE_TOLERANCE","fromBufferGeometry","position","normal","vertexOf","byPosition","gather","smoothNormals","channels","full","attribute","width","quantize","multiplier","tolerance","firstVertex","firstCorner","welded","additive","HASH_PRIMES","same","mergeSources","indexCount","mesh","defaultBuilder","converted","incompatibility","mat","collectVirtualGeometryGroups","meshes","skipped","instanceMatrix","world","object","reason","filter","materials","drawnRanges","instanced","isVisible","rangeCount","materialIndex","vertexColors","tinted","matrixList","colorList","drawStart","drawEnd","ranges","multiMaterial","VirtualGeometryImport","collected","emptied","root","virtualMeshesFromObject3D","build","sources","sourceKey","createdGroups","failed","convertMaterial","meshOptions","flipNormalY","HEADER_SIZE","LEVEL_COUNT_SLOT","WORKGROUP","NO_NODES","mean","minNode","maxNode","OcclusionCulling","maxSize","projection","near","dim","levelCapacity","depth","nearDepth","farDepth","xLo","xHi","yLo","yHi","minX","maxX","minY","maxY","minZ","behind","hzb","W","H","zero","x0","clamp","floor","x1","y0","y1","levelF","ceil","log2","exp2","levelW","levelH","sampleAt","fx","ty","fy","hzbMax","dt","now","phase","supported","camera","any","occluder","previous","depthTexture","lw","lh","copyNode","idx","dstW","dstH","dstOffset","ivec2","int","srcOffset","srcW","srcH","row0","row1","CUT_INPUT_COUNT","ZERO","capacityStep","use","VirtualGeometry","scene","ortho","fromScene","hook","call","cssHeight","projScale","constant","sweep","occlusionWanted","dispatched","hzbNodes","cur","pixelRatio","ratio","back"],"sources":["../src/core/constants.ts","../src/core/preprocess/partition.ts","../src/core/preprocess/voxelProxy.ts","../src/core/preprocess/buildVirtualMesh.ts","../src/core/io/serialize.ts","../src/core/io/cache.ts","../src/core/runtime/cut.ts","../src/core/runtime/vgMaterial.ts","../src/core/runtime/GeometryPool.ts","../src/core/runtime/VirtualMesh.ts","../src/core/import/toNodeMaterial.ts","../src/source.ts","../src/core/import/fromObject3D.ts","../src/core/runtime/OcclusionCulling.ts","../src/core/runtime/VirtualGeometry.ts"],"sourcesContent":["/** Max triangles per meshlet. The renderer always issues `MAX_MESHLET_TRIANGLES * 3` vertices per drawn meshlet. */\nexport const MAX_MESHLET_TRIANGLES = 128;\n\n/** Max unique vertices per meshlet (meshoptimizer allows up to 256). */\nexport const MAX_MESHLET_VERTICES = 128;\n\n/** Stand-in for `Infinity` on the GPU: the parent error of root meshlets. */\nexport const ERROR_INFINITY = 1e30;\n\n/**\n * Instances whose LOD range is at most this many meshlets, and where every meshlet is guaranteed to be\n * selected, emit their meshlets directly from the instance pass (no meshlet pass for them).\n */\nexport const FAST_PATH_MAX_MESHLETS = 4;\n\n/**\n * Relative margin the fast path keeps from the LOD threshold, so float rounding between the bound and the\n * per-meshlet test can never make the fast path select a meshlet the full test would reject.\n */\nexport const FAST_PATH_MARGIN = 1e-3;\n\n/** Floats per meshlet in `VirtualMeshData.meshletBounds` (4 x vec4). */\nexport const MESHLET_BOUNDS_STRIDE = 16;\n\n/** Uints per meshlet in `VirtualMeshData.meshletInfo` (1 x uvec4). */\nexport const MESHLET_INFO_STRIDE = 4;\n\n\n\n/** Debug views for `VirtualGeometry.debugMode`. */\nexport const VG_DEBUG_MODES = {\n shaded: 0,\n meshlets: 1,\n lodLevel: 2,\n instances: 3,\n} as const;\n","/**\n * Groups meshlets into clusters of ~`groupSize` that share as many boundary\n * edges as possible. This stands in for METIS (the graph partitioner nanite-webgpu uses):\n * a greedy region-growing pass over the meshlet adjacency graph, seeded in\n * Morton order so groups stay spatially compact. Meshlets without enough\n * neighbours (e.g. disconnected leaves or grass blades) are then merged with\n * spatially close leftovers so they can still be simplified together.\n */\n\nexport interface PartitionInput {\n /** Boundary edge keys (position-welded vertex ids, see `edgeKey`). */\n boundaryEdges: number[];\n center: [number, number, number];\n}\n\nexport function partitionMeshlets(meshlets: PartitionInput[], groupSize: number): number[][] {\n const count = meshlets.length;\n if (count <= groupSize) return [meshlets.map((_, i) => i)];\n\n // edge -> meshlets touching it\n const edgeOwners = new Map<number, number[]>();\n for (let i = 0; i < count; i++) {\n for (const e of meshlets[i].boundaryEdges) {\n const owners = edgeOwners.get(e);\n if (owners) {\n if (owners[owners.length - 1] !== i) owners.push(i);\n } else edgeOwners.set(e, [i]);\n }\n }\n\n // meshlet -> (neighbour -> shared edge count)\n const adjacency: Map<number, number>[] = Array.from({ length: count }, () => new Map());\n for (const owners of edgeOwners.values()) {\n for (let a = 0; a < owners.length; a++) {\n for (let b = a + 1; b < owners.length; b++) {\n const i = owners[a];\n const j = owners[b];\n adjacency[i].set(j, (adjacency[i].get(j) || 0) + 1);\n adjacency[j].set(i, (adjacency[j].get(i) || 0) + 1);\n }\n }\n }\n\n const order = mortonOrder(meshlets.map((m) => m.center));\n const assigned = new Uint8Array(count);\n const groups: number[][] = [];\n\n for (const seed of order) {\n if (assigned[seed]) continue;\n const group = [seed];\n assigned[seed] = 1;\n\n // frontier: candidate -> total shared edges with the group\n const frontier = new Map<number, number>();\n const addNeighbours = (m: number) => {\n for (const [n, shared] of adjacency[m]) {\n if (!assigned[n]) frontier.set(n, (frontier.get(n) || 0) + shared);\n }\n };\n addNeighbours(seed);\n\n while (group.length < groupSize && frontier.size > 0) {\n let best = -1;\n let bestScore = -1;\n let bestDist = Infinity;\n for (const [n, score] of frontier) {\n if (assigned[n]) continue;\n const d = dist2(meshlets[n].center, meshlets[seed].center);\n if (score > bestScore || (score === bestScore && d < bestDist)) {\n best = n;\n bestScore = score;\n bestDist = d;\n }\n }\n if (best < 0) break;\n frontier.delete(best);\n assigned[best] = 1;\n group.push(best);\n addNeighbours(best);\n }\n groups.push(group);\n }\n\n // Merge undersized groups with spatially close undersized groups.\n // `groups` is already in Morton order of their seeds.\n const result: number[][] = [];\n let pending: number[] = [];\n const minSize = Math.max(2, Math.floor(groupSize / 2));\n for (const group of groups) {\n if (group.length >= minSize) {\n result.push(group);\n continue;\n }\n if (pending.length + group.length > groupSize) {\n result.push(pending);\n pending = [];\n }\n pending.push(...group);\n }\n if (pending.length > 0) result.push(pending);\n return result;\n}\n\nfunction dist2(a: [number, number, number], b: [number, number, number]) {\n const dx = a[0] - b[0];\n const dy = a[1] - b[1];\n const dz = a[2] - b[2];\n return dx * dx + dy * dy + dz * dz;\n}\n\n/** Indices sorted along a 30-bit Morton curve of the given points. */\nexport function mortonOrder(points: [number, number, number][]): number[] {\n const min = [Infinity, Infinity, Infinity];\n const max = [-Infinity, -Infinity, -Infinity];\n for (const p of points) {\n for (let k = 0; k < 3; k++) {\n min[k] = Math.min(min[k], p[k]);\n max[k] = Math.max(max[k], p[k]);\n }\n }\n const extent = Math.max(max[0] - min[0], max[1] - min[1], max[2] - min[2]) || 1;\n const codes = points.map((p) => {\n const q = (k: number) => Math.min(1023, Math.max(0, Math.floor(((p[k] - min[k]) / extent) * 1023)));\n return part1By2(q(0)) | (part1By2(q(1)) << 1) | (part1By2(q(2)) << 2);\n });\n return points.map((_, i) => i).sort((a, b) => codes[a] - codes[b]);\n}\n\nfunction part1By2(x: number) {\n x &= 0x3ff;\n x = (x | (x << 16)) & 0x030000ff;\n x = (x | (x << 8)) & 0x0300f00f;\n x = (x | (x << 4)) & 0x030c30c3;\n x = (x | (x << 2)) & 0x09249249;\n return x;\n}\n","/**\n * Voxel proxies for coarse LODs, for foliage and other aggregate geometry.\n *\n * Triangle simplification breaks down on aggregate geometry such as a tree crown made of hundreds of\n * separate leaf clumps: below a few hundred triangles it can only delete or collapse whole clumps, so\n * the silhouette shrinks and the LOD error jumps. A voxel proxy keeps the volume instead: the mesh is\n * voxelized, gaps between clumps are closed, and a smooth closed surface is extracted (surface nets).\n * That surface is one connected shape, which simplifies gracefully to a handful of triangles.\n *\n * Every proxy vertex lies within about one cell of the original surface, and closing fills gaps of at most\n * two cells, so `VOXEL_ERROR_CELLS * cellSize` bounds how far the proxy deviates from the original.\n */\n\n/** Deviation of a proxy from the source mesh, in cells (surface offset plus closed gaps). */\nexport const VOXEL_ERROR_CELLS = 2;\n\nexport interface VoxelProxy {\n positions: Float32Array;\n normals: Float32Array;\n colors: Float32Array | null;\n /** UV of a representative source sample near each vertex (null when the source has no UVs). */\n uvs: Float32Array | null;\n indices: Uint32Array;\n cellSize: number;\n}\n\n/**\n * Voxelizes the triangles `indices` of a mesh with `resolution` cells along its longest side and returns\n * a closed, smooth surface around the occupied volume (null if the mesh is empty).\n * With `uvs`, each proxy vertex takes the UV of the first source sample in its cell's voxels, so textured\n * geometry keeps plausible colors at a distance (UVs cannot be averaged across islands).\n */\nexport function buildVoxelProxy(\n positions: Float32Array,\n colors: Float32Array | null | undefined,\n indices: Uint32Array,\n resolution: number,\n uvs?: Float32Array | null\n): VoxelProxy | null {\n if (indices.length === 0) return null;\n const min = [Infinity, Infinity, Infinity];\n const max = [-Infinity, -Infinity, -Infinity];\n for (let i = 0; i < indices.length; i++) {\n const o = indices[i] * 3;\n for (let k = 0; k < 3; k++) {\n min[k] = Math.min(min[k], positions[o + k]);\n max[k] = Math.max(max[k], positions[o + k]);\n }\n }\n const extent = Math.max(max[0] - min[0], max[1] - min[1], max[2] - min[2]);\n if (!(extent > 0)) return null;\n const cell = extent / resolution;\n // Samples sit at cell centers; 3 cells of padding keep the closed surface away from the grid border.\n const PAD = 3;\n const n = [0, 1, 2].map((k) => Math.ceil((max[k] - min[k]) / cell) + 1 + PAD * 2);\n const origin = [0, 1, 2].map((k) => min[k] - PAD * cell);\n const [nx, ny, nz] = n;\n const sx = 1;\n const sy = nx;\n const sz = nx * ny;\n const total = nx * ny * nz;\n\n // ---- 1. occupancy (+ color) by sampling every triangle at half-cell spacing ----\n const occupied = new Uint8Array(total);\n const colorSum = colors ? new Float32Array(total * 3) : null;\n const colorCount = colors ? new Uint32Array(total) : null;\n // First UV sampled in each voxel (NaN: none yet).\n const voxelUv = uvs ? new Float32Array(total * 2).fill(NaN) : null;\n let sampleU = 0;\n let sampleV = 0;\n const mark = (x: number, y: number, z: number, r: number, g: number, b: number) => {\n const i = Math.floor((x - origin[0]) / cell) * sx + Math.floor((y - origin[1]) / cell) * sy + Math.floor((z - origin[2]) / cell) * sz;\n occupied[i] = 1;\n if (voxelUv && Number.isNaN(voxelUv[i * 2])) {\n voxelUv[i * 2] = sampleU;\n voxelUv[i * 2 + 1] = sampleV;\n }\n if (colorSum) {\n colorSum[i * 3] += r;\n colorSum[i * 3 + 1] += g;\n colorSum[i * 3 + 2] += b;\n colorCount![i]++;\n }\n };\n for (let t = 0; t < indices.length; t += 3) {\n const a = indices[t] * 3;\n const b = indices[t + 1] * 3;\n const c = indices[t + 2] * 3;\n const longest = Math.max(dist(positions, a, b), dist(positions, b, c), dist(positions, c, a));\n const steps = Math.max(1, Math.ceil(longest / (cell * 0.5)));\n for (let i = 0; i <= steps; i++) {\n for (let j = 0; j <= steps - i; j++) {\n const u = i / steps;\n const v = j / steps;\n const w = 1 - u - v;\n const x = positions[a] * w + positions[b] * u + positions[c] * v;\n const y = positions[a + 1] * w + positions[b + 1] * u + positions[c + 1] * v;\n const z = positions[a + 2] * w + positions[b + 2] * u + positions[c + 2] * v;\n if (uvs) {\n const ta = indices[t] * 2;\n const tb = indices[t + 1] * 2;\n const tc = indices[t + 2] * 2;\n sampleU = uvs[ta] * w + uvs[tb] * u + uvs[tc] * v;\n sampleV = uvs[ta + 1] * w + uvs[tb + 1] * u + uvs[tc + 1] * v;\n }\n if (colors) {\n mark(\n x,\n y,\n z,\n colors[a] * w + colors[b] * u + colors[c] * v,\n colors[a + 1] * w + colors[b + 1] * u + colors[c + 1] * v,\n colors[a + 2] * w + colors[b + 2] * u + colors[c + 2] * v\n );\n } else mark(x, y, z, 0, 0, 0);\n }\n }\n }\n\n // ---- 2. morphological closing (dilate, then erode) fuses clumps into one volume ----\n const closed = erode(dilate(occupied, n), n);\n\n // ---- 3. smooth field: 3x3x3 box blur of the occupancy, iso level 0.5 ----\n const field = new Float32Array(total);\n for (let i = 0; i < total; i++) field[i] = closed[i];\n blurAxis(field, n, sx, nx);\n blurAxis(field, n, sy, ny);\n blurAxis(field, n, sz, nz);\n const ISO = 0.5;\n\n // ---- 4. surface nets: one vertex per cell crossing the iso surface, one quad per crossing edge ----\n const cellsX = nx - 1;\n const cellsY = ny - 1;\n const cellsZ = nz - 1;\n const cellVertex = new Int32Array(cellsX * cellsY * cellsZ).fill(-1);\n const outPositions: number[] = [];\n const outNormals: number[] = [];\n const outColors: number[] = [];\n const outUvs: number[] = [];\n const corner = new Float32Array(8);\n for (let z = 0; z < cellsZ; z++) {\n for (let y = 0; y < cellsY; y++) {\n for (let x = 0; x < cellsX; x++) {\n const base = x * sx + y * sy + z * sz;\n let inside = 0;\n for (let c = 0; c < 8; c++) {\n corner[c] = field[base + (c & 1) * sx + ((c >> 1) & 1) * sy + ((c >> 2) & 1) * sz];\n if (corner[c] >= ISO) inside++;\n }\n if (inside === 0 || inside === 8) continue;\n // Vertex: mean of the iso crossings on the cell's 12 edges.\n let px = 0;\n let py = 0;\n let pz = 0;\n let crossings = 0;\n for (let c = 0; c < 8; c++) {\n for (const bit of [1, 2, 4]) {\n if (c & bit) continue;\n const d = c | bit;\n const f0 = corner[c];\n const f1 = corner[d];\n if (f0 >= ISO === f1 >= ISO) continue;\n const s = (ISO - f0) / (f1 - f0);\n px += (c & 1) + (bit === 1 ? s : 0);\n py += ((c >> 1) & 1) + (bit === 2 ? s : 0);\n pz += ((c >> 2) & 1) + (bit === 4 ? s : 0);\n crossings++;\n }\n }\n cellVertex[x + y * cellsX + z * cellsX * cellsY] = outPositions.length / 3;\n // Sample (i, j, k) sits at origin + (i + 0.5) * cell.\n outPositions.push(origin[0] + (x + 0.5 + px / crossings) * cell, origin[1] + (y + 0.5 + py / crossings) * cell, origin[2] + (z + 0.5 + pz / crossings) * cell);\n // Normal: the field decreases outward, so the outward normal is minus its gradient.\n const gx = corner[1] + corner[3] + corner[5] + corner[7] - corner[0] - corner[2] - corner[4] - corner[6];\n const gy = corner[2] + corner[3] + corner[6] + corner[7] - corner[0] - corner[1] - corner[4] - corner[5];\n const gz = corner[4] + corner[5] + corner[6] + corner[7] - corner[0] - corner[1] - corner[2] - corner[3];\n const len = Math.hypot(gx, gy, gz) || 1;\n outNormals.push(-gx / len, -gy / len, -gz / len);\n if (colorSum) {\n let r = 0;\n let g = 0;\n let b = 0;\n let count = 0;\n for (let c = 0; c < 8; c++) {\n const i = base + (c & 1) * sx + ((c >> 1) & 1) * sy + ((c >> 2) & 1) * sz;\n if (!colorCount![i]) continue;\n r += colorSum[i * 3];\n g += colorSum[i * 3 + 1];\n b += colorSum[i * 3 + 2];\n count += colorCount![i];\n }\n if (count) outColors.push(r / count, g / count, b / count);\n else outColors.push(NaN, NaN, NaN); // filled in below from neighbours\n }\n if (voxelUv) {\n let u = NaN;\n let v = NaN;\n for (let c = 0; c < 8 && Number.isNaN(u); c++) {\n const i = base + (c & 1) * sx + ((c >> 1) & 1) * sy + ((c >> 2) & 1) * sz;\n u = voxelUv[i * 2];\n v = voxelUv[i * 2 + 1];\n }\n outUvs.push(u, v); // NaN: filled in below from neighbours\n }\n }\n }\n }\n\n const outIndices: number[] = [];\n const cellIndex = (x: number, y: number, z: number) => cellVertex[x + y * cellsX + z * cellsX * cellsY];\n const quad = (a: number, b: number, c: number, d: number, nx_: number, ny_: number, nz_: number) => {\n // Orient so the face normal agrees with the outward direction of the crossing edge.\n const ux = outPositions[c * 3] - outPositions[a * 3];\n const uy = outPositions[c * 3 + 1] - outPositions[a * 3 + 1];\n const uz = outPositions[c * 3 + 2] - outPositions[a * 3 + 2];\n const vx = outPositions[d * 3] - outPositions[b * 3];\n const vy = outPositions[d * 3 + 1] - outPositions[b * 3 + 1];\n const vz = outPositions[d * 3 + 2] - outPositions[b * 3 + 2];\n const cx = uy * vz - uz * vy;\n const cy = uz * vx - ux * vz;\n const cz = ux * vy - uy * vx;\n if (cx * nx_ + cy * ny_ + cz * nz_ >= 0) outIndices.push(a, b, c, a, c, d);\n else outIndices.push(a, c, b, a, d, c);\n };\n for (let z = 1; z < nz - 1; z++) {\n for (let y = 1; y < ny - 1; y++) {\n for (let x = 1; x < nx - 1; x++) {\n const i = x * sx + y * sy + z * sz;\n const here = field[i] >= ISO;\n // Edge to +x: the four cells around it share x and span y-1..y, z-1..z.\n if (here !== field[i + sx] >= ISO) {\n const s = here ? 1 : -1;\n quad(cellIndex(x, y - 1, z - 1), cellIndex(x, y, z - 1), cellIndex(x, y, z), cellIndex(x, y - 1, z), s, 0, 0);\n }\n if (here !== field[i + sy] >= ISO) {\n const s = here ? 1 : -1;\n quad(cellIndex(x - 1, y, z - 1), cellIndex(x, y, z - 1), cellIndex(x, y, z), cellIndex(x - 1, y, z), 0, s, 0);\n }\n if (here !== field[i + sz] >= ISO) {\n const s = here ? 1 : -1;\n quad(cellIndex(x - 1, y - 1, z), cellIndex(x, y - 1, z), cellIndex(x, y, z), cellIndex(x - 1, y, z), 0, 0, s);\n }\n }\n }\n }\n if (outIndices.length === 0) return null;\n\n let proxyColors: Float32Array | null = null;\n if (colorSum) {\n proxyColors = Float32Array.from(outColors);\n // Vertices of cells with no colored sample (volume added by closing) take the mean of their triangles' others.\n fillMissing(proxyColors, outIndices, 3);\n }\n let proxyUvs: Float32Array | null = null;\n if (voxelUv) {\n proxyUvs = Float32Array.from(outUvs);\n fillMissing(proxyUvs, outIndices, 2);\n }\n return {\n positions: Float32Array.from(outPositions),\n normals: Float32Array.from(outNormals),\n colors: proxyColors,\n uvs: proxyUvs,\n indices: Uint32Array.from(outIndices),\n cellSize: cell,\n };\n}\n\nfunction dist(p: Float32Array, a: number, b: number) {\n return Math.hypot(p[a] - p[b], p[a + 1] - p[b + 1], p[a + 2] - p[b + 2]);\n}\n\n/** 3x3x3 max (26-neighbourhood), separable per axis. */\nfunction dilate(src: Uint8Array, n: number[]) {\n let a = src;\n for (let axis = 0; axis < 3; axis++) a = morph(a, n, axis, 1);\n return a;\n}\n\n/** 3x3x3 min, separable per axis. */\nfunction erode(src: Uint8Array, n: number[]) {\n let a = src;\n for (let axis = 0; axis < 3; axis++) a = morph(a, n, axis, 0);\n return a;\n}\n\nfunction morph(src: Uint8Array, n: number[], axis: number, grow: number) {\n const [nx, ny, nz] = n;\n const stride = axis === 0 ? 1 : axis === 1 ? nx : nx * ny;\n const size = n[axis];\n const out = new Uint8Array(src.length);\n for (let z = 0; z < nz; z++) {\n for (let y = 0; y < ny; y++) {\n for (let x = 0; x < nx; x++) {\n const i = x + y * nx + z * nx * ny;\n const c = axis === 0 ? x : axis === 1 ? y : z;\n const prev = c > 0 ? src[i - stride] : 0;\n const next = c < size - 1 ? src[i + stride] : 0;\n out[i] = grow ? src[i] | prev | next : src[i] & prev & next;\n }\n }\n }\n return out;\n}\n\n/** In-place 3-tap box blur along one axis (borders treated as empty). */\nfunction blurAxis(field: Float32Array, n: number[], stride: number, size: number) {\n const [nx, ny, nz] = n;\n const line = new Float32Array(size);\n const lines = (nx * ny * nz) / size;\n // Walk every line along this axis: its first sample index enumerates the other two axes.\n for (let l = 0; l < lines; l++) {\n let start: number;\n if (stride === 1) start = l * nx;\n else if (stride === nx) start = (l % nx) + Math.floor(l / nx) * nx * ny;\n else start = l;\n for (let k = 0; k < size; k++) line[k] = field[start + k * stride];\n for (let k = 0; k < size; k++) {\n const a = k > 0 ? line[k - 1] : 0;\n const b = k < size - 1 ? line[k + 1] : 0;\n field[start + k * stride] = (a + line[k] + b) / 3;\n }\n }\n}\n\n/** Fills NaN entries (`size` floats per vertex) with the mean of their triangles' known neighbours. */\nfunction fillMissing(values: Float32Array, indices: number[], size: number) {\n const count = values.length / size;\n for (let pass = 0; pass < 8; pass++) {\n let missing = 0;\n const sum = new Float32Array(count * size);\n const hits = new Uint32Array(count);\n for (let t = 0; t < indices.length; t += 3) {\n for (let k = 0; k < 3; k++) {\n const v = indices[t + k];\n if (!Number.isNaN(values[v * size])) continue;\n for (let m = 1; m < 3; m++) {\n const u = indices[t + ((k + m) % 3)];\n if (Number.isNaN(values[u * size])) continue;\n for (let c = 0; c < size; c++) sum[v * size + c] += values[u * size + c];\n hits[v]++;\n }\n }\n }\n for (let v = 0; v < count; v++) {\n if (!Number.isNaN(values[v * size])) continue;\n if (hits[v]) {\n for (let c = 0; c < size; c++) values[v * size + c] = sum[v * size + c] / hits[v];\n } else missing++;\n }\n if (!missing) return;\n }\n for (let i = 0; i < values.length; i++) if (Number.isNaN(values[i])) values[i] = 0.5;\n}\n","/**\n * Builds the virtual-geometry meshlet LOD DAG for a single mesh.\n *\n * Ported from nanite-webgpu (MIT, Marcin Matuszczyk) `src/meshPreprocessing`,\n * using the npm `meshoptimizer` build instead of custom WASM, a JS partitioner\n * instead of METIS, and meshoptimizer clusterlod-style monotonic LOD bounds.\n *\n * Per level: partition meshlets into groups -> merge each group -> simplify to\n * ~50% with locked group borders -> split back into meshlets. All meshlets index\n * the same (original) vertex buffer, so normals/UVs survive simplification.\n */\nimport { MeshoptClusterizer, MeshoptSimplifier, type SimplifierFlags } from 'meshoptimizer';\nimport {\n ERROR_INFINITY,\n MAX_MESHLET_TRIANGLES,\n MAX_MESHLET_VERTICES,\n MESHLET_BOUNDS_STRIDE,\n MESHLET_INFO_STRIDE,\n} from '../constants';\nimport { partitionMeshlets } from './partition';\nimport { buildVoxelProxy, VOXEL_ERROR_CELLS, type VoxelProxy } from './voxelProxy';\n\nexport interface VirtualMeshSource {\n /** xyz per vertex */\n positions: Float32Array;\n /** xyz per vertex */\n normals: Float32Array;\n /** Optional rgb per vertex, multiplied with the material color. */\n colors?: Float32Array;\n /** Optional uv per vertex (texture coordinates). Vertices on a UV seam must be separate vertices. */\n uvs?: Float32Array;\n indices: Uint32Array;\n}\n\nexport interface VirtualMeshBuildOptions {\n /** Meshlets per group before simplification. */\n groupSize?: number;\n maxLodLevels?: number;\n /** A group that keeps more than this fraction of its triangles stops refining (its meshlets become roots). */\n maxGroupKeepRatio?: number;\n /** Fraction of a group's triangles kept by its simplification (the per-level reduction factor). */\n simplifyRatio?: number;\n /** Stop when a whole level removed less than this fraction of triangles. */\n minLevelReduction?: number;\n /** Remove small disconnected components while simplifying (good for foliage). */\n prune?: boolean;\n /**\n * Keep simplifying below a single meshlet once the remaining roots form the whole mesh, so distant\n * instances can draw a handful of triangles (or nothing, with `prune`) instead of a full meshlet.\n */\n tailSimplify?: boolean;\n /** Stop the tail at this many triangles. */\n minRootTriangles?: number;\n /**\n * Let coarse LODs switch to voxel proxies when those are more accurate than simplified triangles\n * (foliage and other aggregate geometry; solid meshes keep their triangles). Default true.\n */\n voxelLods?: boolean;\n onProgress?: (fraction: number) => void | Promise<void>;\n}\n\nexport interface VirtualMeshData {\n positions: Float32Array;\n normals: Float32Array;\n colors: Float32Array | null;\n /** uv per vertex, or null when the source had none. */\n uvs: Float32Array | null;\n /** Concatenated meshlet triangle lists, indexing `positions`. */\n indices: Uint32Array;\n meshletCount: number;\n /**\n * 4 x vec4 per meshlet:\n * [0] LOD sphere (center, radius) - shared by all meshlets created from the same group\n * [1] parent LOD sphere (center, radius)\n * [2] (error, parentError, 0, 0) - object-space; parentError = ERROR_INFINITY for roots\n * [3] culling sphere (center, radius) - the meshlet's own geometry\n */\n meshletBounds: Float32Array;\n /**\n * uvec4 per meshlet: (triangleCount, firstIndex, lodLevel, vertexOffset).\n * `firstIndex / 3` is also the meshlet's first entry in `meshletTriangles`.\n */\n meshletInfo: Uint32Array;\n /** Global vertex ids, per meshlet, in meshlet-local order (`vertexOffset` indexes this). */\n meshletVertices: Uint32Array;\n /** One packed triangle per entry: three meshlet-local vertex ids in bits 0-7, 8-15, 16-23. */\n meshletTriangles: Uint32Array;\n /** Meshlets are sorted by LOD level. Per level: [firstMeshlet, meshletCount]. */\n levelRanges: Uint32Array;\n /** Per level: [smallest own error, largest parent error] in object space (parent may be ERROR_INFINITY). */\n levelErrors: Float32Array;\n /**\n * Per level: [largest own error, smallest parent error] in object space. Used by the fast path: if every\n * meshlet of a level passes the LOD test at the nearest distance (largest own error) and at the farthest\n * (smallest parent error), the level needs no per-meshlet test.\n */\n levelGuardErrors: Float32Array;\n /** Sphere enclosing every LOD and parent sphere: bounds the distances the LOD test can see. */\n lodBoundsSphere: [number, number, number, number];\n /** Sphere enclosing every meshlet's culling sphere (all LODs): if an instance sphere is inside the frustum, so are they. */\n cullBoundsSphere: [number, number, number, number];\n /**\n * DAG links, CSR form: meshlet i is replaced by coarser meshlets\n * `replacementIndices[replacementStart[i] .. replacementStart[i + 1]]`. Empty for coarsest meshlets.\n */\n replacementStart: Uint32Array;\n replacementIndices: Uint32Array;\n /** Whole-object bounding sphere (center xyz, radius). */\n boundingSphere: [number, number, number, number];\n stats: {\n leafTriangles: number;\n leafMeshlets: number;\n rootTriangles: number;\n rootMeshlets: number;\n lodLevels: number;\n /** Coarse levels built from voxel proxies (see voxelProxy.ts). */\n voxelLevels: number;\n buildMs: number;\n };\n}\n\ntype Sphere = [number, number, number, number];\n\ninterface WipMeshlet {\n indices: Uint32Array;\n lodLevel: number;\n lodSphere: Sphere;\n error: number;\n parentSphere: Sphere;\n parentError: number;\n cullSphere: Sphere;\n boundaryEdges: number[];\n center: [number, number, number];\n /** Coarser meshlets that replaced this one (the outputs of the group it was merged into). */\n replacements: WipMeshlet[];\n /** Global vertex ids of this meshlet's unique vertices (meshlet-local order). */\n vertices: Uint32Array;\n /** Per triangle corner: index into `vertices` (0..MAX_MESHLET_VERTICES-1). */\n localTriangles: Uint8Array;\n}\n\nconst DEFAULTS = {\n groupSize: 12,\n maxLodLevels: 24,\n maxGroupKeepRatio: 0.9,\n simplifyRatio: 0.5,\n minLevelReduction: 0.03,\n prune: false,\n tailSimplify: true,\n minRootTriangles: 4,\n voxelLods: true,\n};\n\n/** The tail (whole-object simplification, where voxel proxies can take over) starts at this many triangles. */\nconst TAIL_START_TRIANGLES = 1024;\n/** Voxel proxy resolutions tried for each tail step (cells along the longest side). */\nconst VOXEL_RESOLUTIONS = [64, 32, 16, 8, 4];\n\nconst yieldToBrowser = () => new Promise<void>((r) => setTimeout(r, 0));\n\nexport async function buildVirtualMesh(src: VirtualMeshSource, options: VirtualMeshBuildOptions = {}): Promise<VirtualMeshData> {\n const opts = { ...DEFAULTS, ...options };\n const t0 = performance.now();\n await MeshoptClusterizer.ready;\n await MeshoptSimplifier.ready;\n\n // Vertex buffers grow when voxel proxies add their own vertices (appendVertices).\n let positions = src.positions;\n let normals = src.normals;\n let colors = src.colors ?? null;\n let uvs = src.uvs ?? null;\n // Vertices sharing a position (UV/normal seams) are the same vertex topologically.\n let weld = MeshoptSimplifier.generatePositionRemap(positions, 3);\n let voxelLevels = 0;\n const flags: SimplifierFlags[] = ['LockBorder', 'ErrorAbsolute'];\n if (opts.prune) flags.push('Prune');\n\n const all: WipMeshlet[] = [];\n const proxyCache = new Map<number, VoxelProxy | null>();\n const leafs = splitIntoMeshlets(src.indices, 0, null, 0);\n let current = leafs;\n let lastTriangles = countTriangles(current);\n let lodLevels = 1;\n const estimatedTotal = Math.max(1, leafs.length * 2);\n\n for (let level = 1; level <= opts.maxLodLevels && current.length > 1; level++) {\n // Small enough to treat as one piece: the tail takes over (and may switch to voxel proxies).\n if (opts.tailSimplify && lastTriangles <= TAIL_START_TRIANGLES) break;\n const groups = partitionMeshlets(current, opts.groupSize);\n const next: WipMeshlet[] = [];\n\n for (const groupIdx of groups) {\n const group = groupIdx.map((i) => current[i]);\n const merged = concatIndices(group);\n const local = compact(merged, positions);\n const target = Math.max(3, Math.floor((merged.length * opts.simplifyRatio) / 3) * 3);\n const [simplified, simplifyError] = MeshoptSimplifier.simplify(local.indices, local.positions, 3, target, 1e10, flags);\n\n if (simplified.length > merged.length * opts.maxGroupKeepRatio) {\n continue; // cannot reduce this group any further: its meshlets stay roots\n }\n\n // Monotonic LOD bounds: the group sphere encloses every child LOD sphere,\n // and the group error is never smaller than any child error.\n const lodSphere = enclosingSphere(group.map((m) => m.lodSphere));\n const childError = Math.max(...group.map((m) => m.error));\n // meshopt's error is vertex displacement; it misses silhouette loss (pruned parts, collapsed sheets).\n const shapeError = Math.max(simplifyError, extentShrink(local.indices, simplified, local.positions));\n const error = childError + Math.max(shapeError, 1e-7);\n for (const child of group) {\n child.parentSphere = lodSphere;\n child.parentError = error;\n }\n\n const globalIndices = new Uint32Array(simplified.length);\n for (let i = 0; i < simplified.length; i++) globalIndices[i] = local.toGlobal[simplified[i]];\n if (globalIndices.length > 0) {\n const outputs = splitIntoMeshlets(globalIndices, level, lodSphere, error);\n next.push(...outputs);\n for (const child of group) child.replacements = outputs;\n }\n }\n\n await opts.onProgress?.(Math.min(0.99, all.length / estimatedTotal));\n await yieldToBrowser();\n\n if (next.length === 0) break;\n lodLevels = level + 1;\n current = next;\n\n const triangles = countTriangles(current);\n if (triangles > lastTriangles * (1 - opts.minLevelReduction)) break;\n lastTriangles = triangles;\n }\n\n // Every root, not only the last level: groups that could not be reduced (e.g. UV-seam fans at a sphere's\n // poles) leave roots on earlier levels, and together the roots still cover the whole mesh.\n if (opts.tailSimplify) lodLevels = simplifyTail(all.filter((m) => m.parentError >= ERROR_INFINITY), lodLevels);\n\n await opts.onProgress?.(1);\n return pack({ positions, normals, colors: colors ?? undefined, uvs: uvs ?? undefined, indices: src.indices }, all, lodLevels, voxelLevels, performance.now() - t0);\n\n /** Adds vertices to the shared buffers and returns the index of the first one. */\n function appendVertices(p: Float32Array, n: Float32Array, c: Float32Array | null, uv: Float32Array | null) {\n const first = positions.length / 3;\n const count = p.length / 3;\n const grow = (a: Float32Array, b: Float32Array) => {\n const out = new Float32Array(a.length + b.length);\n out.set(a);\n out.set(b, a.length);\n return out;\n };\n positions = grow(positions, p);\n normals = grow(normals, n);\n if (colors) colors = grow(colors, c ?? new Float32Array(count * 3).fill(1));\n if (uvs) uvs = grow(uvs, uv ?? new Float32Array(count * 2));\n const w = new Uint32Array(weld.length + count);\n w.set(weld);\n for (let i = 0; i < count; i++) w[weld.length + i] = first + i;\n weld = w;\n return first;\n }\n\n /** Voxel proxies of the full-detail mesh, built on first use per resolution. */\n function voxelProxy(resolution: number): VoxelProxy | null {\n if (!proxyCache.has(resolution)) proxyCache.set(resolution, buildVoxelProxy(src.positions, src.colors, src.indices, resolution, src.uvs));\n return proxyCache.get(resolution)!;\n }\n\n /**\n * Below one meshlet: merge all remaining roots and keep halving. Borders can be unlocked because\n * the roots cover the whole mesh, so no other meshlet shares them.\n */\n function simplifyTail(roots: WipMeshlet[], levels: number): number {\n if (roots.length === 0) return levels;\n\n const tailFlags: SimplifierFlags[] = ['ErrorAbsolute'];\n if (opts.prune) tailFlags.push('Prune');\n let nodes = roots;\n let level = levels;\n for (; level < levels + opts.maxLodLevels; level++) {\n const merged = concatIndices(nodes);\n if (merged.length / 3 <= opts.minRootTriangles) break;\n const local = compact(merged, positions);\n const target = Math.max(3, Math.floor(merged.length / 2 / 3) * 3);\n const keepLimit = merged.length * opts.maxGroupKeepRatio;\n const childError = Math.max(...nodes.map((m) => m.error));\n\n // Candidate 1: simplify the current triangles (errors accumulate level over level).\n let [result, error] = MeshoptSimplifier.simplify(local.indices, local.positions, 3, target, 1e10, tailFlags);\n if (result.length > keepLimit) {\n // Topology blocks regular collapses (e.g. many disconnected parts): try sloppy simplification.\n const [sloppy, relativeError] = MeshoptSimplifier.simplifySloppy(local.indices, local.positions, 3, null, target, 1);\n if (sloppy.length < result.length) {\n result = sloppy;\n error = relativeError * MeshoptSimplifier.getScale(local.positions, 3);\n }\n }\n let globalIndices: Uint32Array | null = null;\n let parentError = Infinity;\n if (result.length <= keepLimit) {\n parentError = childError + Math.max(Math.max(error, extentShrink(local.indices, result, local.positions)), 1e-7);\n globalIndices = new Uint32Array(result.length);\n for (let i = 0; i < result.length; i++) globalIndices[i] = local.toGlobal[result[i]];\n }\n\n // Candidate 2: a simplified voxel proxy of the full-detail mesh. Its error is measured against the\n // original directly, so it does not accumulate. It wins when triangles can only shrink the shape.\n let voxel: { proxy: VoxelProxy; indices: Uint32Array } | null = null;\n if (opts.voxelLods) {\n for (const resolution of VOXEL_RESOLUTIONS) {\n const proxy = voxelProxy(resolution);\n if (!proxy) continue;\n const proxyTarget = Math.min(target, proxy.indices.length);\n const [simplified, proxyError] = MeshoptSimplifier.simplify(proxy.indices, proxy.positions, 3, proxyTarget, 1e10, ['ErrorAbsolute']);\n if (simplified.length === 0 || simplified.length > keepLimit) continue;\n const voxelError = Math.max(childError * (1 + 1e-5) + 1e-7, VOXEL_ERROR_CELLS * proxy.cellSize + proxyError);\n if (voxelError < parentError) {\n parentError = voxelError;\n voxel = { proxy, indices: simplified };\n }\n }\n }\n if (!Number.isFinite(parentError)) break;\n if (voxel) {\n // Copy the proxy vertices this level uses into the shared vertex buffers.\n const used = compact(voxel.indices, voxel.proxy.positions);\n const pick = (src: Float32Array, size = 3) => {\n const out = new Float32Array(used.toGlobal.length * size);\n used.toGlobal.forEach((v, i) => out.set(src.subarray(v * size, v * size + size), i * size));\n return out;\n };\n const { proxy } = voxel;\n const first = appendVertices(used.positions, pick(proxy.normals), proxy.colors ? pick(proxy.colors) : null, proxy.uvs ? pick(proxy.uvs, 2) : null);\n globalIndices = used.indices.map((i) => i + first);\n voxelLevels++;\n }\n\n const lodSphere = enclosingSphere(nodes.map((m) => m.lodSphere));\n for (const node of nodes) {\n node.parentSphere = lodSphere;\n node.parentError = parentError;\n }\n if (globalIndices!.length === 0) return level + 1; // pruned away entirely beyond this distance\n\n const outputs = splitIntoMeshlets(globalIndices!, level, lodSphere, parentError);\n for (const node of nodes) node.replacements = outputs;\n nodes = outputs;\n }\n return level;\n }\n\n ////////////////\n\n function splitIntoMeshlets(indices: Uint32Array, lodLevel: number, lodSphere: Sphere | null, error: number): WipMeshlet[] {\n const local = compact(indices, positions);\n const built = MeshoptClusterizer.buildMeshlets(local.indices, local.positions, 3, MAX_MESHLET_VERTICES, MAX_MESHLET_TRIANGLES, 0);\n const result: WipMeshlet[] = [];\n\n for (let m = 0; m < built.meshletCount; m++) {\n const vertexOffset = built.meshlets[m * 4 + 0];\n const triangleOffset = built.meshlets[m * 4 + 1];\n const vertexCount = built.meshlets[m * 4 + 2];\n const triangleCount = built.meshlets[m * 4 + 3];\n const vertices = new Uint32Array(vertexCount);\n for (let v = 0; v < vertexCount; v++) vertices[v] = local.toGlobal[built.vertices[vertexOffset + v]];\n const localTriangles = built.triangles.slice(triangleOffset, triangleOffset + triangleCount * 3);\n const meshletIndices = new Uint32Array(triangleCount * 3);\n for (let i = 0; i < triangleCount * 3; i++) meshletIndices[i] = vertices[localTriangles[i]];\n\n const cullSphere = boundingSphere(meshletIndices, positions);\n const meshlet: WipMeshlet = {\n indices: meshletIndices,\n lodLevel,\n lodSphere: lodSphere ?? cullSphere,\n error,\n parentSphere: [0, 0, 0, 0],\n parentError: ERROR_INFINITY,\n cullSphere,\n boundaryEdges: findBoundaryEdges(meshletIndices, weld),\n center: [cullSphere[0], cullSphere[1], cullSphere[2]],\n replacements: [],\n vertices,\n localTriangles,\n };\n result.push(meshlet);\n all.push(meshlet);\n }\n return result;\n }\n}\n\nfunction pack(src: VirtualMeshSource, unsorted: WipMeshlet[], lodLevels: number, voxelLevels: number, buildMs: number): VirtualMeshData {\n // Sorted by LOD level so every level is a contiguous range (used for per-instance level ranges).\n const all = [...unsorted].sort((a, b) => a.lodLevel - b.lodLevel);\n const meshletCount = all.length;\n const indices = new Uint32Array(all.reduce((acc, m) => acc + m.indices.length, 0));\n const meshletBounds = new Float32Array(meshletCount * MESHLET_BOUNDS_STRIDE);\n const meshletInfo = new Uint32Array(meshletCount * MESHLET_INFO_STRIDE);\n const indexOf = new Map<WipMeshlet, number>();\n all.forEach((m, i) => indexOf.set(m, i));\n const replacementStart = new Uint32Array(meshletCount + 1);\n const replacementIndices: number[] = [];\n all.forEach((m, i) => {\n replacementStart[i] = replacementIndices.length;\n for (const r of m.replacements) replacementIndices.push(indexOf.get(r)!);\n });\n replacementStart[meshletCount] = replacementIndices.length;\n\n const meshletVertices = new Uint32Array(all.reduce((acc, m) => acc + m.vertices.length, 0));\n const meshletTriangles = new Uint32Array(indices.length / 3);\n let firstIndex = 0;\n let vertexOffset = 0;\n const stats = { leafTriangles: 0, leafMeshlets: 0, rootTriangles: 0, rootMeshlets: 0, lodLevels, voxelLevels, buildMs };\n all.forEach((m, i) => {\n indices.set(m.indices, firstIndex);\n meshletVertices.set(m.vertices, vertexOffset);\n const t = m.localTriangles;\n for (let k = 0, tri = firstIndex / 3; k < t.length; k += 3, tri++) {\n meshletTriangles[tri] = t[k] | (t[k + 1] << 8) | (t[k + 2] << 16);\n }\n const b = i * MESHLET_BOUNDS_STRIDE;\n meshletBounds.set(m.lodSphere, b);\n meshletBounds.set(m.parentSphere, b + 4);\n meshletBounds[b + 8] = m.error;\n meshletBounds[b + 9] = m.parentError;\n meshletBounds.set(m.cullSphere, b + 12);\n\n const triangleCount = m.indices.length / 3;\n const o = i * MESHLET_INFO_STRIDE;\n meshletInfo[o + 0] = triangleCount;\n meshletInfo[o + 1] = firstIndex;\n meshletInfo[o + 2] = m.lodLevel;\n meshletInfo[o + 3] = vertexOffset;\n firstIndex += m.indices.length;\n vertexOffset += m.vertices.length;\n\n if (m.lodLevel === 0) {\n stats.leafTriangles += triangleCount;\n stats.leafMeshlets += 1;\n }\n if (m.parentError >= ERROR_INFINITY) {\n stats.rootTriangles += triangleCount;\n stats.rootMeshlets += 1;\n }\n });\n\n const whole = enclosingSphere(all.filter((m) => m.lodLevel === 0).map((m) => m.cullSphere));\n\n // Per level: [start, count] and [smallest own error, largest parent error] (object space).\n const levelCount = all.length ? all[all.length - 1].lodLevel + 1 : 0;\n const levelRanges = new Uint32Array(levelCount * 2);\n const levelErrors = new Float32Array(levelCount * 2);\n const levelGuardErrors = new Float32Array(levelCount * 2);\n for (let l = 0; l < levelCount; l++) {\n levelErrors[l * 2] = Infinity;\n levelErrors[l * 2 + 1] = 0;\n levelGuardErrors[l * 2] = 0;\n levelGuardErrors[l * 2 + 1] = Infinity;\n }\n all.forEach((m, i) => {\n const l = m.lodLevel;\n if (levelRanges[l * 2 + 1] === 0) levelRanges[l * 2] = i;\n levelRanges[l * 2 + 1]++;\n levelErrors[l * 2] = Math.min(levelErrors[l * 2], m.error);\n levelErrors[l * 2 + 1] = Math.max(levelErrors[l * 2 + 1], m.parentError);\n levelGuardErrors[l * 2] = Math.max(levelGuardErrors[l * 2], m.error);\n levelGuardErrors[l * 2 + 1] = Math.min(levelGuardErrors[l * 2 + 1], m.parentError);\n });\n // Encloses every sphere the LOD test can look at, so per-instance distance bounds stay conservative.\n const lodBoundsSphere = enclosingSphere([\n ...all.map((m) => m.lodSphere),\n ...all.filter((m) => m.parentError < ERROR_INFINITY).map((m) => m.parentSphere),\n ]);\n const cullBoundsSphere = enclosingSphere(all.map((m) => m.cullSphere));\n return {\n positions: src.positions,\n normals: src.normals,\n colors: src.colors ?? null,\n uvs: src.uvs ?? null,\n indices,\n meshletCount,\n meshletBounds,\n meshletInfo,\n replacementStart,\n replacementIndices: Uint32Array.from(replacementIndices),\n meshletVertices,\n meshletTriangles,\n levelRanges,\n levelErrors,\n levelGuardErrors,\n lodBoundsSphere,\n cullBoundsSphere,\n boundingSphere: whole,\n stats,\n };\n}\n\n/**\n * How far the simplified mesh's bounding box retreats from the original's, per side (max over the 6\n * sides). An empty result counts as losing the whole extent. Used as a floor for the LOD error so a\n * version that lost its silhouette is only drawn once that loss is below the pixel threshold.\n */\nexport function extentShrink(before: Uint32Array, after: Uint32Array, positions: Float32Array): number {\n const box = (indices: Uint32Array) => {\n const min = [Infinity, Infinity, Infinity];\n const max = [-Infinity, -Infinity, -Infinity];\n for (let i = 0; i < indices.length; i++) {\n const o = indices[i] * 3;\n for (let k = 0; k < 3; k++) {\n const v = positions[o + k];\n if (v < min[k]) min[k] = v;\n if (v > max[k]) max[k] = v;\n }\n }\n return { min, max };\n };\n const a = box(before);\n if (after.length === 0) return Math.max(a.max[0] - a.min[0], a.max[1] - a.min[1], a.max[2] - a.min[2]) / 2;\n const b = box(after);\n let shrink = 0;\n for (let k = 0; k < 3; k++) shrink = Math.max(shrink, b.min[k] - a.min[k], a.max[k] - b.max[k]);\n return shrink;\n}\n\n/**\n * Vertex id -> local id scratch for compact(), all -1 between calls. A typed-array lookup instead of a Map:\n * compact() runs several times per group, so this is one of the hottest loops of the build.\n */\nlet localOf = new Int32Array(0);\n\n/** Re-index a triangle subset into a compact local vertex buffer so meshopt only touches what it needs. */\nfunction compact(indices: Uint32Array, positions: Float32Array) {\n const vertexCount = positions.length / 3;\n if (localOf.length < vertexCount) localOf = new Int32Array(vertexCount).fill(-1);\n const toGlobalAll = new Uint32Array(indices.length);\n const localIndices = new Uint32Array(indices.length);\n let count = 0;\n for (let i = 0; i < indices.length; i++) {\n const g = indices[i];\n let l = localOf[g];\n if (l < 0) {\n l = count++;\n localOf[g] = l;\n toGlobalAll[l] = g;\n }\n localIndices[i] = l;\n }\n const toGlobal = toGlobalAll.subarray(0, count);\n const localPositions = new Float32Array(count * 3);\n for (let i = 0; i < count; i++) {\n const g = toGlobal[i];\n localOf[g] = -1;\n localPositions[i * 3 + 0] = positions[g * 3 + 0];\n localPositions[i * 3 + 1] = positions[g * 3 + 1];\n localPositions[i * 3 + 2] = positions[g * 3 + 2];\n }\n return { indices: localIndices, positions: localPositions, toGlobal };\n}\n\n/** Open-addressing scratch for findBoundaryEdges(): edge keys, use counts and insertion order. */\nlet edgeTableKeys = new Float64Array(1024);\nlet edgeTableCounts = new Uint8Array(1024);\nlet edgeOrder = new Int32Array(512);\n\n/** Edges used by exactly one triangle, keyed by position-welded vertex ids (in first-seen order). */\nfunction findBoundaryEdges(indices: Uint32Array, weld: Uint32Array): number[] {\n const edgeCount = indices.length;\n let size = edgeTableKeys.length;\n if (size < edgeCount * 2) {\n while (size < edgeCount * 2) size <<= 1;\n edgeTableKeys = new Float64Array(size);\n edgeTableCounts = new Uint8Array(size);\n edgeOrder = new Int32Array(size / 2);\n }\n const mask = size - 1;\n let inserted = 0;\n for (let t = 0; t < indices.length; t += 3) {\n for (let k = 0; k < 3; k++) {\n const a = weld[indices[t + k]];\n const b = weld[indices[t + ((k + 1) % 3)]];\n const key = edgeKey(a, b);\n let h = (Math.imul(a < b ? a : b, 0x9e3779b1) ^ Math.imul(a < b ? b : a, 0x85ebca6b)) & mask;\n while (edgeTableCounts[h] !== 0 && edgeTableKeys[h] !== key) h = (h + 1) & mask;\n if (edgeTableCounts[h] === 0) {\n edgeTableKeys[h] = key;\n edgeOrder[inserted++] = h;\n }\n if (edgeTableCounts[h] < 255) edgeTableCounts[h]++;\n }\n }\n const result: number[] = [];\n for (let i = 0; i < inserted; i++) {\n const h = edgeOrder[i];\n if (edgeTableCounts[h] === 1) result.push(edgeTableKeys[h]);\n edgeTableCounts[h] = 0;\n }\n return result;\n}\n\n/** Order-independent edge id. Safe while vertex ids stay below 2^26. */\nexport const edgeKey = (a: number, b: number) => (a < b ? a * 67108864 + b : b * 67108864 + a);\n\nfunction concatIndices(meshlets: WipMeshlet[]) {\n const result = new Uint32Array(meshlets.reduce((acc, m) => acc + m.indices.length, 0));\n let offset = 0;\n for (const m of meshlets) {\n result.set(m.indices, offset);\n offset += m.indices.length;\n }\n return result;\n}\n\nconst countTriangles = (meshlets: WipMeshlet[]) => meshlets.reduce((acc, m) => acc + m.indices.length / 3, 0);\n\nfunction boundingSphere(indices: Uint32Array, positions: Float32Array): Sphere {\n const min = [Infinity, Infinity, Infinity];\n const max = [-Infinity, -Infinity, -Infinity];\n for (let i = 0; i < indices.length; i++) {\n const o = indices[i] * 3;\n for (let k = 0; k < 3; k++) {\n const v = positions[o + k];\n if (v < min[k]) min[k] = v;\n if (v > max[k]) max[k] = v;\n }\n }\n const cx = (min[0] + max[0]) / 2;\n const cy = (min[1] + max[1]) / 2;\n const cz = (min[2] + max[2]) / 2;\n let r2 = 0;\n for (let i = 0; i < indices.length; i++) {\n const o = indices[i] * 3;\n const dx = positions[o] - cx;\n const dy = positions[o + 1] - cy;\n const dz = positions[o + 2] - cz;\n r2 = Math.max(r2, dx * dx + dy * dy + dz * dz);\n }\n return [cx, cy, cz, Math.sqrt(r2)];\n}\n\n/** Sphere enclosing all given spheres (meshoptimizer's computeSphereBounds), padded for float error. */\nfunction enclosingSphere(spheres: Sphere[]): Sphere {\n if (spheres.length === 1) return [...spheres[0]] as Sphere;\n const centers = new Float32Array(spheres.length * 3);\n const radii = new Float32Array(spheres.length);\n spheres.forEach((s, i) => {\n centers.set([s[0], s[1], s[2]], i * 3);\n radii[i] = s[3];\n });\n const b = MeshoptClusterizer.computeSphereBounds(centers, 3, radii, 1);\n let radius = b.radius;\n // guarantee containment regardless of the approximation used\n for (const s of spheres) {\n const d = Math.hypot(s[0] - b.centerX, s[1] - b.centerY, s[2] - b.centerZ) + s[3];\n radius = Math.max(radius, d);\n }\n return [b.centerX, b.centerY, b.centerZ, radius * 1.0001];\n}\n","/**\n * Binary container for `VirtualMeshData` (`.vgeo`, \"virtual geometry\").\n *\n * Layout (little-endian):\n * 0 magic 'VGEO'\n * 4 u32 format version\n * 8 u32 header byte length (UTF-8 JSON, then space-padded to 4 bytes)\n * 12 u32 checksum of everything after this 16-byte prefix\n * 16 JSON header\n * .. payload: one 4-byte aligned blob per typed-array field\n *\n * The header lists every typed-array field (name, array type, length, encoding, payload offset and size)\n * and carries every other field as JSON, so fields added to `VirtualMeshData` later are stored without\n * format changes. Compression is lossless: meshoptimizer's vertex and index codecs, optionally followed by\n * deflate, whichever is smallest per field. `indices` is not stored: it is rebuilt from the meshlet arrays.\n */\nimport { MeshoptDecoder, MeshoptEncoder } from 'meshoptimizer';\nimport { MESHLET_INFO_STRIDE } from '../constants';\nimport type { VirtualMeshData } from '../preprocess/buildVirtualMesh';\n\n/** Bumped whenever the container layout or an encoding changes; older readers reject newer files. */\nexport const VG_FORMAT_VERSION = 1;\n\nconst MAGIC = 0x4f454756; // 'VGEO' read as a little-endian u32\nconst PREFIX_BYTES = 16;\n\nexport interface VirtualMeshEncodeOptions {\n /** Store `indices` instead of rebuilding it from the meshlet arrays on decode. Default false. */\n keepIndices?: boolean;\n /** Lossless compression with meshoptimizer's codecs. Default true; false stores every array uncompressed. */\n compress?: boolean;\n /**\n * Also deflate fields where that makes them smaller (about 30% smaller files, about 2x slower decoding).\n * Default true; ignored where `CompressionStream` is unavailable. The IndexedDB cache turns it off.\n */\n deflate?: boolean;\n}\n\ntype Encoding = 'raw' | 'meshopt-vertex' | 'meshlet-triangles' | 'meshlet-indices';\n\ninterface FieldEntry {\n name: string;\n type: TypedArrayName;\n length: number;\n encoding: Encoding;\n /** Bytes per element group for 'meshopt-vertex'. */\n stride?: number;\n /** The encoded blob is additionally deflate-compressed. */\n deflate?: boolean;\n /** Payload-relative byte offset and size of the blob. */\n offset: number;\n byteLength: number;\n}\n\ninterface Header {\n generator: string;\n /** Every top-level key of the original object, in order. */\n keys: string[];\n fields: FieldEntry[];\n values: Record<string, unknown>;\n}\n\ntype AnyTypedArray =\n | Int8Array\n | Uint8Array\n | Uint8ClampedArray\n | Int16Array\n | Uint16Array\n | Int32Array\n | Uint32Array\n | Float32Array\n | Float64Array;\n\nconst TYPED_ARRAYS = {\n Int8Array,\n Uint8Array,\n Uint8ClampedArray,\n Int16Array,\n Uint16Array,\n Int32Array,\n Uint32Array,\n Float32Array,\n Float64Array,\n};\ntype TypedArrayName = keyof typeof TYPED_ARRAYS;\n\n/**\n * Per-field encoder hints, from measurements on the demo assets. `strides`: element groups (bytes) to try with\n * the vertex codec (unknown fields use their element size, at least 4). `deflateRaw`: also try deflate on the\n * uncompressed array (meshletBounds repeats whole spheres, which deflate finds and the vertex codec does not).\n */\nconst FIELD_HINTS: Record<string, { strides?: number[]; deflateRaw?: boolean }> = {\n positions: { strides: [12] },\n normals: { strides: [12] },\n colors: { strides: [12] },\n uvs: { strides: [8] },\n tangents: { strides: [16] },\n meshletBounds: { strides: [64], deflateRaw: true },\n meshletInfo: { strides: [16] },\n};\n\nexport class VirtualMeshFormatError extends Error {\n constructor(message: string) {\n super(`three-virtual-geometry: ${message}`);\n this.name = 'VirtualMeshFormatError';\n }\n}\n\nexport async function encodeVirtualMesh(data: VirtualMeshData, options: VirtualMeshEncodeOptions = {}): Promise<Uint8Array> {\n const compress = options.compress ?? true;\n if (compress) await MeshoptEncoder.ready;\n const record = data as unknown as Record<string, unknown>;\n const keys = Object.keys(record).filter((k) => record[k] !== undefined && typeof record[k] !== 'function');\n const fields: FieldEntry[] = [];\n const blobs: Uint8Array[] = [];\n const values: Record<string, unknown> = {};\n let offset = 0;\n\n for (const name of keys) {\n const value = record[name];\n if (!ArrayBuffer.isView(value)) {\n values[name] = value;\n continue;\n }\n const type = value.constructor.name as TypedArrayName;\n if (!(type in TYPED_ARRAYS)) throw new VirtualMeshFormatError(`cannot serialize field \"${name}\" of type ${type}`);\n const array = value as AnyTypedArray;\n let blob: Uint8Array;\n let entry: Omit<FieldEntry, 'offset' | 'byteLength'>;\n if (name === 'indices' && !options.keepIndices && indicesMatchMeshlets(data)) {\n entry = { name, type, length: array.length, encoding: 'meshlet-indices' };\n blob = new Uint8Array(0);\n } else if (compress) {\n ({ entry, blob } = await encodeField(name, type, array, data, options.deflate ?? true));\n } else {\n entry = { name, type, length: array.length, encoding: 'raw' };\n blob = bytesOf(array);\n }\n fields.push({ ...entry, offset, byteLength: blob.length });\n blobs.push(blob);\n offset += align4(blob.length);\n }\n\n const headerJson: Header = { generator: 'three-virtual-geometry', keys, fields, values };\n const headerBytes = new TextEncoder().encode(JSON.stringify(headerJson, jsonReplacer));\n const headerPadded = align4(headerBytes.length);\n const out = new Uint8Array(PREFIX_BYTES + headerPadded + offset);\n out.set(headerBytes, PREFIX_BYTES);\n out.fill(0x20, PREFIX_BYTES + headerBytes.length, PREFIX_BYTES + headerPadded);\n const payloadStart = PREFIX_BYTES + headerPadded;\n fields.forEach((f, i) => out.set(blobs[i], payloadStart + f.offset));\n const view = new DataView(out.buffer);\n view.setUint32(0, MAGIC, true);\n view.setUint32(4, VG_FORMAT_VERSION, true);\n view.setUint32(8, headerBytes.length, true);\n view.setUint32(12, checksum(out, PREFIX_BYTES), true);\n return out;\n}\n\nexport async function decodeVirtualMesh(input: ArrayBuffer | ArrayBufferView): Promise<VirtualMeshData> {\n let bytes = ArrayBuffer.isView(input) ? new Uint8Array(input.buffer, input.byteOffset, input.byteLength) : new Uint8Array(input);\n if (bytes.byteOffset % 4 !== 0) bytes = bytes.slice(); // checksum and payload views need 4-byte alignment\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n if (bytes.length < PREFIX_BYTES || view.getUint32(0, true) !== MAGIC) {\n throw new VirtualMeshFormatError('not a three-virtual-geometry geometry file (bad magic bytes)');\n }\n const version = view.getUint32(4, true);\n if (version !== VG_FORMAT_VERSION) {\n throw new VirtualMeshFormatError(`unsupported geometry format version ${version} (this build reads version ${VG_FORMAT_VERSION}); re-bake the file`);\n }\n const headerLength = view.getUint32(8, true);\n const payloadStart = PREFIX_BYTES + align4(headerLength);\n if (payloadStart > bytes.length || bytes.length % 4 !== 0) throw new VirtualMeshFormatError('geometry file is truncated');\n // Header and field bounds are checked before the checksum so truncation gets its own message.\n\n let header: Header;\n try {\n header = JSON.parse(new TextDecoder().decode(bytes.subarray(PREFIX_BYTES, PREFIX_BYTES + headerLength)), jsonReviver);\n } catch {\n throw new VirtualMeshFormatError('geometry file is corrupt or truncated (unreadable header)');\n }\n if (!header || !Array.isArray(header.fields) || !Array.isArray(header.keys) || typeof header.values !== 'object') {\n throw new VirtualMeshFormatError('geometry file is corrupt (malformed header)');\n }\n\n const payload = bytes.subarray(payloadStart);\n const arrays: Record<string, AnyTypedArray> = {};\n // Derived encodings read other fields, so they go last.\n const order = [...header.fields].sort((a, b) => rank(a.encoding) - rank(b.encoding));\n if (order.some((f) => f.encoding !== 'raw')) await MeshoptDecoder.ready;\n for (const field of order) {\n const Ctor = TYPED_ARRAYS[field.type];\n if (!Ctor || !Number.isInteger(field.length) || field.length < 0) throw new VirtualMeshFormatError(`geometry file is corrupt (field \"${field.name}\")`);\n if (field.offset % 4 !== 0 || field.offset + field.byteLength > payload.length) {\n throw new VirtualMeshFormatError(`geometry file is truncated (field \"${field.name}\")`);\n }\n }\n if (checksum(bytes, PREFIX_BYTES) !== view.getUint32(12, true)) throw new VirtualMeshFormatError('geometry file is corrupt (checksum mismatch)');\n const fail = (field: FieldEntry, e: unknown) =>\n e instanceof VirtualMeshFormatError ? e : new VirtualMeshFormatError(`geometry file is corrupt (field \"${field.name}\": ${(e as Error).message})`);\n // Inflate every deflated field at once (runs concurrently where the platform allows), then decode in order.\n const blobs = await Promise.all(\n order.map((f) => {\n const blob = payload.subarray(f.offset, f.offset + f.byteLength);\n return f.deflate ? inflate(blob).catch((e) => Promise.reject(fail(f, e))) : blob;\n })\n );\n for (let i = 0; i < order.length; i++) {\n try {\n arrays[order[i].name] = await decodeField({ ...order[i], deflate: false }, blobs[i], arrays);\n } catch (e) {\n throw fail(order[i], e);\n }\n }\n\n const result: Record<string, unknown> = {};\n for (const key of header.keys) result[key] = key in arrays ? arrays[key] : header.values[key];\n return result as unknown as VirtualMeshData;\n}\n\n/** Fetches and decodes a baked `.vgeo` file, or decodes bytes that are already in memory. */\nexport async function loadVirtualMesh(source: string | URL | ArrayBuffer | ArrayBufferView, init?: RequestInit): Promise<VirtualMeshData> {\n if (typeof source !== 'string' && !(source instanceof URL)) return decodeVirtualMesh(source);\n const response = await fetch(source, init);\n if (!response.ok) throw new Error(`three-virtual-geometry: failed to load ${source} (HTTP ${response.status})`);\n return decodeVirtualMesh(await response.arrayBuffer());\n}\n\n// ------------------------------------------------------------------ encoding\n\nasync function encodeField(name: string, type: TypedArrayName, array: AnyTypedArray, data: VirtualMeshData, useDeflate: boolean) {\n const raw = bytesOf(array);\n const base = { name, type, length: array.length };\n const hint = FIELD_HINTS[name] ?? {};\n const rawCandidate = { entry: { ...base, encoding: 'raw' as Encoding }, blob: raw };\n const candidates: { entry: Omit<FieldEntry, 'offset' | 'byteLength'>; blob: Uint8Array }[] = [rawCandidate];\n\n // Always much smaller than the vertex codec on meshlet triangles, so that one is only a fallback there.\n const triangles = name === 'meshletTriangles' && array instanceof Uint32Array ? encodeMeshletTriangles(array, data.meshletInfo) : null;\n if (triangles) candidates.push({ entry: { ...base, encoding: 'meshlet-triangles' }, blob: triangles });\n else if (raw.length % 4 === 0 && raw.length > 0) {\n const strides = (hint.strides ?? [Math.max(4, array.BYTES_PER_ELEMENT)]).filter((s) => s % 4 === 0 && s <= 256 && raw.length % s === 0);\n for (const stride of strides) {\n const blob = MeshoptEncoder.encodeVertexBufferLevel(raw, raw.length / stride, stride, 2, 1);\n candidates.push({ entry: { ...base, encoding: 'meshopt-vertex', stride }, blob });\n }\n }\n candidates.sort((a, b) => a.blob.length - b.blob.length);\n if (useDeflate && canDeflate() && raw.length >= 64) {\n // Deflate is slow to run on everything: try it on the best codec output (and on the raw data if hinted).\n const toDeflate = hint.deflateRaw && candidates[0] !== rawCandidate ? [candidates[0], rawCandidate] : [candidates[0]];\n for (const c of toDeflate) candidates.push({ entry: { ...c.entry, deflate: true }, blob: await deflate(c.blob) });\n candidates.sort((a, b) => a.blob.length - b.blob.length);\n }\n\n for (const c of candidates) {\n // The chosen encoding is decoded once and compared, so a stored file always round-trips exactly.\n const decoded = await decodeField({ ...c.entry, offset: 0, byteLength: c.blob.length }, c.blob, { meshletInfo: data.meshletInfo });\n if (sameBytes(bytesOf(decoded), raw)) return c;\n }\n return rawCandidate;\n}\n\n/**\n * Meshlet triangles as one index buffer over meshlet-vertex slots (vertexOffset + local id). Meshlet-local\n * ids are in first-use order, so that buffer is ideal input for the index codec. The codec may rotate the\n * corners of a triangle, so each triangle's rotation is stored too (2 bits) to keep the exact corner order.\n * Layout: u32 codec byte length, codec bytes (padded to 4), packed rotations.\n */\nfunction encodeMeshletTriangles(triangles: Uint32Array, meshletInfo: Uint32Array | undefined): Uint8Array | null {\n if (!(meshletInfo instanceof Uint32Array)) return null;\n const slots = new Uint32Array(triangles.length * 3);\n const covered = new Uint8Array(triangles.length);\n for (let m = 0; m < meshletInfo.length; m += MESHLET_INFO_STRIDE) {\n const count = meshletInfo[m];\n const first = meshletInfo[m + 1] / 3;\n const vertexOffset = meshletInfo[m + 3];\n if (first + count > triangles.length) return null;\n for (let t = first; t < first + count; t++) {\n const packed = triangles[t];\n if (covered[t] || packed >>> 24 !== 0) return null;\n covered[t] = 1;\n slots[t * 3] = vertexOffset + (packed & 255);\n slots[t * 3 + 1] = vertexOffset + ((packed >> 8) & 255);\n slots[t * 3 + 2] = vertexOffset + ((packed >> 16) & 255);\n }\n }\n if (!covered.every((c) => c === 1)) return null;\n\n const codec = MeshoptEncoder.encodeIndexBuffer(bytesOf(slots), slots.length, 4);\n const decoded = new Uint32Array(slots.length);\n MeshoptDecoder.decodeIndexBuffer(bytesOf(decoded), slots.length, 4, codec);\n const rotations = new Uint8Array(Math.ceil(triangles.length / 4));\n for (let t = 0; t < triangles.length; t++) {\n const a = slots[t * 3], b = slots[t * 3 + 1], c = slots[t * 3 + 2];\n const x = decoded[t * 3], y = decoded[t * 3 + 1], z = decoded[t * 3 + 2];\n let r: number;\n if (a === x && b === y && c === z) r = 0;\n else if (a === y && b === z && c === x) r = 1;\n else if (a === z && b === x && c === y) r = 2;\n else return null;\n rotations[t >> 2] |= r << ((t & 3) * 2);\n }\n const out = new Uint8Array(4 + align4(codec.length) + rotations.length);\n new DataView(out.buffer).setUint32(0, codec.length, true);\n out.set(codec, 4);\n out.set(rotations, 4 + align4(codec.length));\n return out;\n}\n\n/** True if `indices` is exactly what decoding rebuilds from meshletInfo / meshletVertices / meshletTriangles. */\nfunction indicesMatchMeshlets(data: VirtualMeshData): boolean {\n const { indices, meshletInfo, meshletVertices, meshletTriangles } = data;\n if (!(indices instanceof Uint32Array && meshletInfo instanceof Uint32Array && meshletVertices instanceof Uint32Array && meshletTriangles instanceof Uint32Array)) {\n return false;\n }\n try {\n return sameBytes(bytesOf(rebuildIndices(indices.length, meshletInfo, meshletVertices, meshletTriangles)), bytesOf(indices));\n } catch {\n return false;\n }\n}\n\n// ------------------------------------------------------------------ decoding\n\nconst rank = (e: Encoding) => (e === 'meshlet-triangles' ? 1 : e === 'meshlet-indices' ? 2 : 0);\n\nasync function decodeField(field: FieldEntry, blob: Uint8Array, arrays: Record<string, AnyTypedArray>): Promise<AnyTypedArray> {\n const Ctor = TYPED_ARRAYS[field.type];\n const out = new Ctor(field.length);\n const target = bytesOf(out);\n const src = field.deflate ? await inflate(blob) : blob;\n switch (field.encoding) {\n case 'raw':\n if (src.length !== target.length) throw new VirtualMeshFormatError(`geometry file is corrupt (field \"${field.name}\" has the wrong size)`);\n target.set(src);\n break;\n case 'meshopt-vertex': {\n const stride = field.stride ?? 0;\n if (stride <= 0 || stride % 4 !== 0 || target.length % stride !== 0) throw new VirtualMeshFormatError(`geometry file is corrupt (field \"${field.name}\" stride)`);\n MeshoptDecoder.decodeVertexBuffer(target, target.length / stride, stride, src);\n break;\n }\n case 'meshlet-triangles':\n decodeMeshletTriangles(out as Uint32Array, src, requireArray(arrays, 'meshletInfo', field.name));\n break;\n case 'meshlet-indices':\n out.set(\n rebuildIndices(\n field.length,\n requireArray(arrays, 'meshletInfo', field.name),\n requireArray(arrays, 'meshletVertices', field.name),\n requireArray(arrays, 'meshletTriangles', field.name)\n )\n );\n break;\n default:\n throw new VirtualMeshFormatError(`unknown encoding \"${field.encoding}\" for field \"${field.name}\"`);\n }\n return out;\n}\n\nfunction requireArray(arrays: Record<string, AnyTypedArray>, name: string, forField: string): Uint32Array {\n const a = arrays[name];\n if (!(a instanceof Uint32Array)) throw new VirtualMeshFormatError(`geometry file is corrupt (\"${forField}\" needs \"${name}\")`);\n return a;\n}\n\nfunction decodeMeshletTriangles(out: Uint32Array, blob: Uint8Array, meshletInfo: Uint32Array) {\n const codecLength = new DataView(blob.buffer, blob.byteOffset, blob.byteLength).getUint32(0, true);\n const rotationsStart = 4 + align4(codecLength);\n if (rotationsStart + Math.ceil(out.length / 4) > blob.length) throw new Error('truncated triangle data');\n const slots = new Uint32Array(out.length * 3);\n MeshoptDecoder.decodeIndexBuffer(bytesOf(slots), slots.length, 4, blob.subarray(4, 4 + codecLength));\n const rotations = blob.subarray(rotationsStart);\n for (let m = 0; m < meshletInfo.length; m += MESHLET_INFO_STRIDE) {\n const count = meshletInfo[m];\n const first = meshletInfo[m + 1] / 3;\n const vertexOffset = meshletInfo[m + 3];\n if (first + count > out.length) throw new Error('meshlet range out of bounds');\n for (let t = first; t < first + count; t++) {\n const r = (rotations[t >> 2] >> ((t & 3) * 2)) & 3;\n const x = slots[t * 3] - vertexOffset, y = slots[t * 3 + 1] - vertexOffset, z = slots[t * 3 + 2] - vertexOffset;\n const [a, b, c] = r === 0 ? [x, y, z] : r === 1 ? [y, z, x] : [z, x, y];\n if ((a | b | c) >>> 8 !== 0) throw new Error('meshlet-local vertex id out of range');\n out[t] = a | (b << 8) | (c << 16);\n }\n }\n}\n\n/** `indices[firstIndex + 3t + k]` = global vertex of corner k of the meshlet's triangle t. */\nfunction rebuildIndices(length: number, meshletInfo: Uint32Array, meshletVertices: Uint32Array, meshletTriangles: Uint32Array): Uint32Array {\n const indices = new Uint32Array(length);\n for (let m = 0; m < meshletInfo.length; m += MESHLET_INFO_STRIDE) {\n const count = meshletInfo[m];\n const first = meshletInfo[m + 1];\n const vertexOffset = meshletInfo[m + 3];\n if (first + count * 3 > length || first / 3 + count > meshletTriangles.length) throw new VirtualMeshFormatError('geometry file is corrupt (meshlet range out of bounds)');\n for (let t = 0; t < count; t++) {\n const packed = meshletTriangles[first / 3 + t];\n for (let k = 0; k < 3; k++) {\n const v = vertexOffset + ((packed >> (8 * k)) & 255);\n if (v >= meshletVertices.length) throw new VirtualMeshFormatError('geometry file is corrupt (meshlet vertex out of bounds)');\n indices[first + t * 3 + k] = meshletVertices[v];\n }\n }\n }\n return indices;\n}\n\n// ------------------------------------------------------------------ helpers\n\nconst align4 = (n: number) => (n + 3) & ~3;\n\nfunction bytesOf(a: ArrayBufferView): Uint8Array {\n return new Uint8Array(a.buffer, a.byteOffset, a.byteLength);\n}\n\nfunction sameBytes(a: Uint8Array, b: Uint8Array) {\n if (a.length !== b.length) return false;\n if (a.byteOffset % 4 === 0 && b.byteOffset % 4 === 0 && a.length % 4 === 0) {\n const x = new Uint32Array(a.buffer, a.byteOffset, a.length / 4);\n const y = new Uint32Array(b.buffer, b.byteOffset, b.length / 4);\n for (let i = 0; i < x.length; i++) if (x[i] !== y[i]) return false;\n return true;\n }\n for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;\n return true;\n}\n\n/** 32-bit multiplicative hash over the u32 words from `start` (catches truncation and bit rot, not tampering). */\nfunction checksum(bytes: Uint8Array, start: number): number {\n const words = new Uint32Array(bytes.buffer, bytes.byteOffset + start, (bytes.length - start) >> 2);\n let h = 0x811c9dc5 ^ words.length;\n for (let i = 0; i < words.length; i++) {\n h = Math.imul(h ^ words[i], 0x01000193);\n h ^= h >>> 15;\n }\n return h >>> 0;\n}\n\nconst canDeflate = () => typeof CompressionStream !== 'undefined' && typeof DecompressionStream !== 'undefined';\n\nasync function deflate(bytes: Uint8Array): Promise<Uint8Array> {\n const stream = new Blob([bytes as Uint8Array<ArrayBuffer>]).stream().pipeThrough(new CompressionStream('deflate-raw'));\n return new Uint8Array(await new Response(stream).arrayBuffer());\n}\n\nasync function inflate(bytes: Uint8Array): Promise<Uint8Array> {\n if (typeof DecompressionStream === 'undefined') throw new VirtualMeshFormatError('this environment cannot decompress the geometry file (no DecompressionStream)');\n const stream = new Blob([bytes as Uint8Array<ArrayBuffer>]).stream().pipeThrough(new DecompressionStream('deflate-raw'));\n return new Uint8Array(await new Response(stream).arrayBuffer());\n}\n\n/** JSON has no Infinity/NaN; error fields use them (e.g. root parent errors). */\nfunction jsonReplacer(key: string, value: unknown) {\n if (typeof value === 'number' && !Number.isFinite(value)) return { $number: String(value) };\n if (ArrayBuffer.isView(value)) throw new VirtualMeshFormatError(`typed array nested inside field \"${key}\" cannot be serialized; store it as a top-level field`);\n return value;\n}\n\nfunction jsonReviver(_key: string, value: unknown) {\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n const keys = Object.keys(value);\n if (keys.length === 1 && keys[0] === '$number') return Number((value as { $number: string }).$number);\n }\n return value;\n}\n","/**\n * `buildVirtualMeshCached`: `buildVirtualMesh` behind a persistent IndexedDB cache, keyed by a SHA-256 of the\n * source arrays and build options. The first load builds and stores the encoded result; later loads decode\n * it. Any cache problem (no IndexedDB, private mode, quota, corrupt entry) falls back to building.\n */\nimport { buildVirtualMesh, type VirtualMeshBuildOptions, type VirtualMeshData, type VirtualMeshSource } from '../preprocess/buildVirtualMesh';\nimport { decodeVirtualMesh, encodeVirtualMesh, VG_FORMAT_VERSION } from './serialize';\n\n/**\n * Part of every cache key. Bump it whenever `buildVirtualMesh` produces different output for the same input\n * (algorithm or default changes), so stale cached builds are never returned.\n */\nexport const VG_BUILD_VERSION = 3;\n\nexport interface VirtualGeometryCacheOptions {\n /**\n * Fixed cache key instead of a content hash (skips hashing the source). You must change it whenever the\n * source mesh or build options change.\n */\n key?: string;\n /** 'indexeddb' (default) or false to always build. */\n store?: 'indexeddb' | false;\n}\n\nexport interface VirtualGeometryCachedBuildOptions extends VirtualMeshBuildOptions {\n cache?: VirtualGeometryCacheOptions;\n}\n\nconst DB_NAME = 'three-virtual-geometry-cache';\nconst DATA_STORE = 'meshes';\nconst META_STORE = 'meta';\n/** Least recently used entries are evicted above this total size. */\nconst MAX_CACHE_BYTES = 512 * 1024 * 1024;\nconst OPEN_TIMEOUT_MS = 3000;\n\ninterface MetaEntry {\n size: number;\n lastUsed: number;\n}\n\n/**\n * Same as `buildVirtualMesh`, plus a persistent cache. On a hit the build is skipped, `onProgress(1)` is still\n * called, and `stats.buildMs` reports the time this call took (hashing, lookup and decoding).\n */\nexport async function buildVirtualMeshCached(source: VirtualMeshSource, options: VirtualGeometryCachedBuildOptions = {}): Promise<VirtualMeshData> {\n const { cache, ...buildOptions } = options;\n if (cache?.store === false || !hasIndexedDb()) return buildVirtualMesh(source, buildOptions);\n\n const t0 = performance.now();\n const key = await virtualMeshCacheKey(source, buildOptions, cache?.key).catch(() => null);\n const db = key ? await openDb() : null;\n if (!db || !key) return buildVirtualMesh(source, buildOptions);\n\n const bytes = await readEntry(db, key);\n if (bytes) {\n try {\n const data = await decodeVirtualMesh(bytes);\n if (data.stats) data.stats.buildMs = performance.now() - t0;\n touchEntry(db, key);\n await buildOptions.onProgress?.(1);\n return data;\n } catch {\n deleteEntry(db, key); // unreadable (e.g. written by another format version): rebuild below\n }\n }\n\n const data = await buildVirtualMesh(source, buildOptions);\n try {\n // No deflate: the cache optimizes for decode speed (deflate saves ~30% space but doubles decode time).\n const encoded = await encodeVirtualMesh(data, { deflate: false });\n void writeEntry(db, key, encoded); // not awaited: the build result is ready, storing happens in the background\n } catch {\n // never fail a build because of the cache\n }\n return data;\n}\n\n/** Deletes every cached build. Resolves even if IndexedDB is unavailable. */\nexport async function clearVirtualMeshCache(): Promise<void> {\n if (!hasIndexedDb()) return;\n const db = await openDb();\n if (!db) return;\n await new Promise<void>((resolve) => {\n try {\n const tx = db.transaction([DATA_STORE, META_STORE], 'readwrite');\n tx.objectStore(DATA_STORE).clear();\n tx.objectStore(META_STORE).clear();\n tx.oncomplete = tx.onerror = tx.onabort = () => resolve();\n } catch {\n resolve();\n }\n });\n}\n\n// ------------------------------------------------------------------ key\n\n/** SHA-256 over every source field (typed arrays by content), the build options and the format versions. */\nexport async function virtualMeshCacheKey(source: VirtualMeshSource, options: VirtualMeshBuildOptions = {}, customKey?: string): Promise<string> {\n const versions = `v${VG_BUILD_VERSION}.${VG_FORMAT_VERSION}`;\n if (customKey !== undefined) return `${versions}:key:${customKey}`;\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) throw new Error('crypto.subtle unavailable');\n\n const record = source as unknown as Record<string, unknown>;\n const names = Object.keys(record)\n .filter((k) => record[k] !== undefined && record[k] !== null)\n .sort();\n const describe: unknown[] = [];\n const parts: Promise<ArrayBuffer>[] = [];\n for (const name of names) {\n const value = record[name];\n if (ArrayBuffer.isView(value)) {\n describe.push([name, value.constructor.name, value.byteLength]);\n // Hashed per array, then combined: avoids concatenating hundreds of MB into one buffer.\n parts.push(subtle.digest('SHA-256', value as ArrayBufferView<ArrayBuffer>));\n } else {\n describe.push([name, value]);\n }\n }\n const optionEntries = Object.entries(options)\n .filter(([, v]) => v !== undefined && typeof v !== 'function')\n .sort(([a], [b]) => (a < b ? -1 : 1));\n const text = new TextEncoder().encode(JSON.stringify({ versions, source: describe, options: optionEntries }));\n const digests = await Promise.all(parts);\n const combined = new Uint8Array(text.length + digests.length * 32);\n combined.set(text);\n digests.forEach((d, i) => combined.set(new Uint8Array(d), text.length + i * 32));\n const hash = new Uint8Array(await subtle.digest('SHA-256', combined));\n return `${versions}:sha256:${Array.from(hash, (b) => b.toString(16).padStart(2, '0')).join('')}`;\n}\n\n// ------------------------------------------------------------------ IndexedDB\n\nfunction hasIndexedDb() {\n try {\n return typeof indexedDB !== 'undefined' && indexedDB !== null;\n } catch {\n return false; // some sandboxed iframes throw on access\n }\n}\n\nlet dbPromise: Promise<IDBDatabase | null> | null = null;\n\n/** Resolves to null instead of rejecting: no database just means no cache. */\nfunction openDb(): Promise<IDBDatabase | null> {\n dbPromise ??= new Promise<IDBDatabase | null>((resolve) => {\n const timer = setTimeout(() => resolve(null), OPEN_TIMEOUT_MS);\n const done = (db: IDBDatabase | null) => {\n clearTimeout(timer);\n resolve(db);\n };\n try {\n const request = indexedDB.open(DB_NAME, 1);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(DATA_STORE)) db.createObjectStore(DATA_STORE);\n if (!db.objectStoreNames.contains(META_STORE)) db.createObjectStore(META_STORE);\n };\n request.onsuccess = () => {\n const db = request.result;\n // Another tab deleting or upgrading the database: let it, and stop caching in this one.\n db.onversionchange = () => {\n db.close();\n dbPromise = Promise.resolve(null);\n };\n done(db);\n };\n request.onerror = request.onblocked = () => done(null);\n } catch {\n done(null);\n }\n });\n return dbPromise;\n}\n\nfunction readEntry(db: IDBDatabase, key: string): Promise<Uint8Array | null> {\n return new Promise((resolve) => {\n try {\n const request = db.transaction(DATA_STORE, 'readonly').objectStore(DATA_STORE).get(key);\n request.onsuccess = () => {\n const value = request.result;\n resolve(value instanceof ArrayBuffer ? new Uint8Array(value) : value instanceof Uint8Array ? value : null);\n };\n request.onerror = () => resolve(null);\n } catch {\n resolve(null);\n }\n });\n}\n\nfunction writeEntry(db: IDBDatabase, key: string, bytes: Uint8Array): Promise<void> {\n return new Promise<void>((resolve) => {\n try {\n const tx = db.transaction([DATA_STORE, META_STORE], 'readwrite');\n tx.objectStore(DATA_STORE).put(bytes.buffer.byteLength === bytes.length ? bytes.buffer : bytes.slice().buffer, key);\n tx.objectStore(META_STORE).put({ size: bytes.length, lastUsed: Date.now() } satisfies MetaEntry, key);\n tx.oncomplete = () => resolve();\n tx.onerror = tx.onabort = () => resolve(); // e.g. QuotaExceededError\n } catch {\n resolve();\n }\n }).then(() => evict(db, key));\n}\n\nfunction touchEntry(db: IDBDatabase, key: string) {\n try {\n const tx = db.transaction(META_STORE, 'readwrite');\n const store = tx.objectStore(META_STORE);\n const request = store.get(key);\n request.onsuccess = () => {\n const meta = request.result as MetaEntry | undefined;\n if (meta) store.put({ ...meta, lastUsed: Date.now() }, key);\n };\n } catch {\n // only affects eviction order\n }\n}\n\nfunction deleteEntry(db: IDBDatabase, key: string) {\n try {\n const tx = db.transaction([DATA_STORE, META_STORE], 'readwrite');\n tx.objectStore(DATA_STORE).delete(key);\n tx.objectStore(META_STORE).delete(key);\n } catch {\n // a stale entry costs disk space only\n }\n}\n\n/** Drops least recently used entries (never `keep`) while the cache is over MAX_CACHE_BYTES. */\nfunction evict(db: IDBDatabase, keep: string): Promise<void> {\n return new Promise<void>((resolve) => {\n try {\n const tx = db.transaction([DATA_STORE, META_STORE], 'readwrite');\n const meta = tx.objectStore(META_STORE);\n const keysRequest = meta.getAllKeys();\n const valuesRequest = meta.getAll();\n valuesRequest.onsuccess = () => {\n const keys = keysRequest.result as string[];\n const entries = (valuesRequest.result as MetaEntry[]).map((m, i) => ({ key: keys[i], ...m }));\n let total = entries.reduce((acc, e) => acc + e.size, 0);\n entries.sort((a, b) => a.lastUsed - b.lastUsed);\n for (const e of entries) {\n if (total <= MAX_CACHE_BYTES) break;\n if (e.key === keep) continue;\n tx.objectStore(DATA_STORE).delete(e.key);\n meta.delete(e.key);\n total -= e.size;\n }\n };\n tx.oncomplete = tx.onerror = tx.onabort = () => resolve();\n } catch {\n resolve();\n }\n });\n}\n","import { ERROR_INFINITY, FAST_PATH_MARGIN, FAST_PATH_MAX_MESHLETS, MESHLET_BOUNDS_STRIDE } from '../constants';\nimport type { VirtualMeshData } from '../preprocess/buildVirtualMesh';\n\n/** Camera parameters the LOD test needs. Same values the GPU pass uses. */\nexport interface CutView {\n /** Column-major world-to-view matrix (camera.matrixWorldInverse.elements). */\n viewMatrix: ArrayLike<number>;\n /** projection[1][1] * viewportHeight / 2: converts view-space error to pixels. */\n projScale: number;\n near: number;\n /**\n * Uniform scale of the instance, applied to the sphere radii and errors as the GPU does. `viewMatrix`\n * must then include the instance's scale in its centers too (view * model). Default 1.\n */\n scale?: number;\n}\n\n/**\n * CPU reference for the GPU LOD selection (no frustum culling, identity model matrix).\n * A meshlet is in the cut when its own projected error is within `threshold` pixels and its\n * parent's projected error is not. Returns one flag per meshlet.\n *\n * Use it to test the DAG (see `verifyCutCoverage`) or to pick LODs on the CPU, e.g. for physics or AI.\n */\nexport function selectCut(data: VirtualMeshData, view: CutView, threshold: number): Uint8Array {\n const v = view.viewMatrix;\n const B = data.meshletBounds;\n const selected = new Uint8Array(data.meshletCount);\n\n const s = view.scale ?? 1;\n const projectedError = (cx: number, cy: number, cz: number, r: number, error: number) => {\n if (error >= ERROR_INFINITY * 0.5) return Infinity;\n const x = v[0] * cx + v[4] * cy + v[8] * cz + v[12];\n const y = v[1] * cx + v[5] * cy + v[9] * cz + v[13];\n const z = v[2] * cx + v[6] * cy + v[10] * cz + v[14];\n const distance = Math.max(Math.hypot(x, y, z) - r * s, view.near);\n return (error * s * view.projScale) / distance;\n };\n\n for (let i = 0; i < data.meshletCount; i++) {\n const b = i * MESHLET_BOUNDS_STRIDE;\n const own = projectedError(B[b], B[b + 1], B[b + 2], B[b + 3], B[b + 8]);\n const parent = projectedError(B[b + 4], B[b + 5], B[b + 6], B[b + 7], B[b + 9]);\n selected[i] = own <= threshold && parent > threshold ? 1 : 0;\n }\n return selected;\n}\n\n/**\n * Checks that a cut has no holes: every leaf meshlet (LOD 0) is covered by a selected meshlet on its\n * path to the coarsest level (itself or one of its replacements, recursively).\n * Returns the indices of uncovered leaves (empty array = valid cut).\n */\nexport function verifyCutCoverage(data: VirtualMeshData, selected: Uint8Array): number[] {\n const covered = new Int8Array(data.meshletCount).fill(-1); // -1 unknown, 0 no, 1 yes\n const { replacementStart: start, replacementIndices: list } = data;\n\n const isCovered = (i: number): boolean => {\n if (covered[i] !== -1) return covered[i] === 1;\n let result = selected[i] === 1;\n for (let k = start[i]; !result && k < start[i + 1]; k++) result = isCovered(list[k]);\n covered[i] = result ? 1 : 0;\n return result;\n };\n\n const holes: number[] = [];\n for (let i = 0; i < data.meshletCount; i++) {\n if (data.meshletInfo[i * 4 + 2] === 0 && !isCovered(i)) holes.push(i);\n }\n return holes;\n}\n\n/** Distance from the camera to the instance's LOD sphere, and the band [dMin, dMax] every LOD test distance falls in. */\nfunction lodDistanceBounds(data: VirtualMeshData, view: CutView): [number, number] {\n const v = view.viewMatrix;\n const [cx, cy, cz, r] = data.lodBoundsSphere;\n const x = v[0] * cx + v[4] * cy + v[8] * cz + v[12];\n const y = v[1] * cx + v[5] * cy + v[9] * cz + v[13];\n const z = v[2] * cx + v[6] * cy + v[10] * cz + v[14];\n const d = Math.hypot(x, y, z);\n const R = r * (view.scale ?? 1);\n return [Math.max(d - R, view.near), Math.max(d + R, view.near)];\n}\n\n/**\n * CPU reference for the GPU instance pass: the contiguous range of meshlets (sorted by LOD level)\n * that can possibly pass the LOD test for an instance, from distance bounds alone.\n *\n * Every LOD and parent sphere lies inside `lodBoundsSphere`, so the distance to any of them is within\n * [D - R, D + R]. A level can contribute only if its smallest own error could be within the threshold\n * at the farthest distance and its largest parent error could exceed it at the nearest.\n * Returns [start, end) or [0, 0] when nothing can be selected.\n */\nexport function instanceMeshletRange(data: VirtualMeshData, view: CutView, threshold: number): [number, number] {\n const [dMin, dMax] = lodDistanceBounds(data, view);\n\n const k = (view.scale ?? 1) * view.projScale;\n let lo = -1;\n let hi = -1;\n const levels = data.levelRanges.length / 2;\n for (let l = 0; l < levels; l++) {\n const minOwn = data.levelErrors[l * 2];\n const maxParent = data.levelErrors[l * 2 + 1];\n const ownPossible = (minOwn * k) / dMax <= threshold;\n const parentPossible = maxParent >= ERROR_INFINITY * 0.5 || (maxParent * k) / dMin > threshold;\n if (ownPossible && parentPossible) {\n if (lo < 0) lo = l;\n hi = l;\n }\n }\n if (lo < 0) return [0, 0];\n return [data.levelRanges[lo * 2], data.levelRanges[hi * 2] + data.levelRanges[hi * 2 + 1]];\n}\n\n/**\n * CPU reference for the GPU fast path of the instance pass. Returns the range [start, end) when every\n * meshlet in it is guaranteed to be selected by the LOD test, for any distance the instance can have, and\n * the range is at most FAST_PATH_MAX_MESHLETS long. Otherwise returns null (use the per-meshlet pass).\n *\n * Guarantee per level, over the distance band [dMin, dMax] of `instanceMeshletRange`:\n * - largest own error projects to <= threshold at dMin (its closest possible distance), and\n * - smallest parent error projects to > threshold at dMax (its farthest possible distance).\n * A small relative margin keeps float rounding on the GPU from flipping a borderline meshlet.\n * The caller must also check that the instance is fully inside the frustum (see `cullBoundsSphere`).\n */\nexport function instanceGuaranteedRange(data: VirtualMeshData, view: CutView, threshold: number): [number, number] | null {\n const [dMin, dMax] = lodDistanceBounds(data, view);\n const margin = FAST_PATH_MARGIN;\n const k = (view.scale ?? 1) * view.projScale;\n\n let lo = -1;\n let hi = -1;\n let possibleMeshlets = 0;\n let guaranteedMeshlets = 0;\n const levels = data.levelRanges.length / 2;\n for (let l = 0; l < levels; l++) {\n const minOwn = data.levelErrors[l * 2];\n const maxParent = data.levelErrors[l * 2 + 1];\n const ownPossible = (minOwn * k) / dMax <= threshold;\n const parentPossible = maxParent >= ERROR_INFINITY * 0.5 || (maxParent * k) / dMin > threshold;\n if (!ownPossible || !parentPossible) continue;\n if (lo < 0) lo = l;\n hi = l;\n const size = data.levelRanges[l * 2 + 1];\n possibleMeshlets += size;\n\n const maxOwn = data.levelGuardErrors[l * 2];\n const minParent = data.levelGuardErrors[l * 2 + 1];\n const ownSure = (maxOwn * k) / dMin <= threshold * (1 - margin);\n const parentSure = minParent >= ERROR_INFINITY * 0.5 || (minParent * k) / dMax > threshold * (1 + margin);\n if (ownSure && parentSure) guaranteedMeshlets += size;\n }\n if (lo < 0) return null;\n const start = data.levelRanges[lo * 2];\n const end = data.levelRanges[hi * 2] + data.levelRanges[hi * 2 + 1];\n // Possible levels must be contiguous (no impossible level inside the range) and all guaranteed.\n if (possibleMeshlets !== end - start || guaranteedMeshlets !== possibleMeshlets) return null;\n if (possibleMeshlets > FAST_PATH_MAX_MESHLETS) return null;\n return [start, end];\n}\n","/**\n * Texture coordinates for materials on a VirtualMesh.\n *\n * A VirtualMesh pulls its vertices from storage buffers, so its placeholder geometry has no `uv` attribute and\n * three's default texture lookups (`uv()`) would read nothing. The vertex stage writes the pulled UV into the\n * `vgUv` varying, and `bindVirtualGeometryTextures` points the material's textures at it.\n */\nimport * as THREE from 'three/webgpu';\nimport {\n bumpMap,\n context,\n float,\n mat3,\n materialColor,\n materialReference,\n negateOnBackSide,\n normalView,\n positionView,\n sqrt,\n texture,\n transformNormalToView,\n varyingProperty,\n vec3,\n vec4,\n} from 'three/tsl';\n\ntype Node = any; // eslint-disable-line @typescript-eslint/no-explicit-any\n\n/** Interpolated texture coordinates of the current fragment (vec2), for custom material nodes. */\nexport const vgUv = varyingProperty('vec2', 'vVgUv');\n\n/** Plain 2D textures sample `vgUv`; cube, 3D and environment lookups keep their own coordinates. */\nfunction getUV(node: Node): Node {\n if (node?.isTextureNode !== true || node.isCubeTextureNode || node.isTexture3DNode) return undefined;\n return vgUv;\n}\n\n/** Texture lookup at `vgUv`, with the texture's offset/repeat/rotation applied like three's own maps. */\nexport function vgTexture(map: THREE.Texture): Node {\n return (texture(map, vgUv) as Node).setUpdateMatrix(true);\n}\n\nconst TWO_CHANNEL_FORMATS: number[] = [THREE.RGFormat, THREE.RED_GREEN_RGTC2_Format, THREE.RG11_EAC_Format];\n\n/**\n * Normal map without precomputed tangents: the tangent frame comes from screen-space derivatives of the view\n * position and `vgUv` (same construction as three's derivative tangents, http://www.thetenthplanet.de/archives/1180).\n */\nexport function vgNormalMap(map: THREE.Texture, scale: Node, type: THREE.NormalMapTypes = THREE.TangentSpaceNormalMap): Node {\n const sample: Node = vgTexture(map);\n let n: Node = sample.xyz.mul(2).sub(1);\n if (TWO_CHANNEL_FORMATS.includes(map.format)) {\n const xy = sample.xy.mul(2).sub(1);\n n = vec3(xy, sqrt(float(1).sub(xy.dot(xy)).max(0)));\n }\n n = vec3(n.xy.mul(scale), n.z);\n // Object space is the VirtualMesh's space (world space): correct for instances without rotation.\n if (type === THREE.ObjectSpaceNormalMap) return transformNormalToView(n);\n\n const q0: Node = (positionView as Node).dFdx();\n const q1: Node = (positionView as Node).dFdy();\n const st0: Node = (vgUv as Node).dFdx();\n const st1: Node = (vgUv as Node).dFdy();\n const N: Node = normalView;\n const q1perp = q1.cross(N);\n const q0perp = N.cross(q0);\n const T = q1perp.mul(st0.x).add(q0perp.mul(st1.x));\n const B = q1perp.mul(st0.y).add(q0perp.mul(st1.y));\n const det = T.dot(T).max(B.dot(B));\n const s = det.equal(0).select(0, det.inverseSqrt());\n return (mat3(negateOnBackSide(T.mul(s)), negateOnBackSide(B.mul(s)), N) as Node).mul(n).normalize();\n}\n\n/**\n * Makes a material's textures sample `vgUv`. Called by VirtualMesh on the material it takes over.\n *\n * - `map` and `alphaMap` move into `colorNode` (and are cleared on the material): the shadow pass reads\n * `colorNode.a` for alpha-tested shadows, but would sample the material's `map` with the missing `uv()`.\n * - Normal, bump and clearcoat normal maps become explicit normal nodes, because three builds normals in a\n * context that ignores custom UVs.\n * - Every other texture lookup without explicit coordinates (roughness, metalness, emissive, AO, light,\n * clearcoat, sheen, transmission maps, textures in your own nodes, ...) gets `vgUv` through\n * `material.contextNode`. A `getUV` in your own `contextNode` takes precedence.\n *\n * Nodes the material already has are kept: only properties three would otherwise read implicitly are rewired.\n */\nexport function bindVirtualGeometryTextures(material: THREE.NodeMaterial) {\n const m = material as Node;\n if (!m.colorNode && (isTexture(m.map) || isTexture(m.alphaMap))) {\n // With `map` cleared below, materialColor is just the color uniform (live, like three's).\n let color: Node = vec4(materialColor as Node, 1);\n if (isTexture(m.map)) {\n const sample = vgTexture(m.map);\n color = vec4((materialColor as Node).mul(sample.rgb), sample.a);\n }\n if (isTexture(m.alphaMap)) color = vec4(color.rgb, color.a.mul(vgTexture(m.alphaMap).g));\n m.colorNode = color;\n m.map = null;\n m.alphaMap = null;\n }\n if (!m.normalNode) {\n if (isTexture(m.normalMap)) m.normalNode = vgNormalMap(m.normalMap, materialReference('normalScale', 'vec2'), m.normalMapType);\n else if (isTexture(m.bumpMap)) m.normalNode = bumpMap(vgTexture(m.bumpMap).r, materialReference('bumpScale', 'float'));\n }\n if (!m.clearcoatNormalNode && isTexture(m.clearcoatNormalMap)) {\n m.clearcoatNormalNode = vgNormalMap(m.clearcoatNormalMap, materialReference('clearcoatNormalScale', 'vec2'));\n }\n m.contextNode = m.contextNode ? context(m.contextNode, { getUV }) : context({ getUV });\n material.needsUpdate = true;\n}\n\nconst isTexture = (t: unknown): t is THREE.Texture => (t as THREE.Texture | null)?.isTexture === true;\n","/**\n * Shared GPU buffers and compute passes for many VirtualMeshes.\n *\n * Every mesh's vertices, meshlets, level table and instances are appended to one set of storage buffers, and one\n * fixed set of compute passes selects the cut for all of them. CPU cost, shader count and pipeline compilation\n * therefore do not grow with the number of unique meshes: a level with hundreds of different props costs the\n * same 12 dispatches per frame as a scene with one. Each mesh still gets its own indexed indirect draw (its own\n * material), into a region of the pool's shared index buffer laid out each frame by a prefix sum.\n *\n * Per frame (all on the GPU):\n * 0. reset - clears the counters.\n * 1. cells - one thread per cell (CELL_SIZE instances of one mesh, Morton-ordered): frustum, sub-pixel and\n * draw-distance tests on the cell's bounding sphere. Visible cells are appended to a list.\n * 2. instance - one workgroup per visible cell: per-instance tests, occlusion, then the LOD level range per\n * cut (camera and shadow). Instances whose few meshlets are all certain to pass emit them\n * directly (fast path); the others go to a work list.\n * 3. meshlet - one workgroup per work item: per-meshlet frustum/occlusion culling and the LOD test\n * `parentError > t && error <= t`. Selected meshlets get a draw slot and a range inside their\n * mesh's region of the index buffer.\n * 4. prefix - one thread: lays the meshes' regions out one after another and writes each mesh's draw args.\n * 5. expand - one workgroup per drawn meshlet: writes 3 indices per triangle. An index encodes\n * `drawSlot * 128 + meshletLocalVertex`; the material's positionNode decodes it and pulls the\n * vertex from storage buffers, so any three.js NodeMaterial works unchanged.\n *\n * A pool is bounded by WebGPU's storage-buffer binding size; VirtualGeometry opens another pool when one is full.\n * Buffers grow by reallocation (the nodes are rebuilt, and the pipelines recompiled in the background).\n *\n * Based on nanite-webgpu (MIT, Marcin Matuszczyk): cullMeshletsPass + rasterizeHwPass.\n */\nimport * as THREE from 'three/webgpu';\nimport {\n Fn,\n If,\n Loop,\n Return,\n atomicAdd,\n atomicLoad,\n atomicStore,\n bitcast,\n bool,\n dot,\n float,\n instanceIndex,\n length,\n localId,\n mat4,\n max,\n min,\n normalLocal,\n normalize,\n numWorkgroups,\n select,\n storage,\n uint,\n uniform,\n unpackUnorm2x16,\n uvec4,\n varyingProperty,\n vec3,\n vec4,\n vertexIndex,\n workgroupArray,\n workgroupBarrier,\n workgroupId,\n} from 'three/tsl';\nimport { ERROR_INFINITY, FAST_PATH_MARGIN, FAST_PATH_MAX_MESHLETS, MAX_MESHLET_VERTICES, MESHLET_BOUNDS_STRIDE, MESHLET_INFO_STRIDE } from '../constants';\nimport type { VirtualMeshData } from '../preprocess/buildVirtualMesh';\nimport type { VirtualGeometry } from './VirtualGeometry';\nimport { vgUv } from './vgMaterial';\n\nconst minNode = min as (a: unknown, b: unknown) => any; // eslint-disable-line @typescript-eslint/no-explicit-any\nconst maxNode = max as (a: unknown, b: unknown) => any; // eslint-disable-line @typescript-eslint/no-explicit-any\ntype Node = any; // TSL node typings are too strict for the graph code below; runtime is verified in the browser\n\n/** World-space normal of the current vertex, usable in material color/roughness nodes. */\nexport const vgWorldNormal = varyingProperty('vec3', 'vVgWorldNormal');\nexport const vgMeshletVarying = varyingProperty('float', 'vVgMeshlet');\nexport const vgLodVarying = varyingProperty('float', 'vVgLod');\nexport const vgInstanceVarying = varyingProperty('float', 'vVgInstance');\nexport const vgTintVarying = varyingProperty('vec3', 'vVgTint');\n\n/** Bits of an index used for the meshlet-local vertex; the rest is the draw slot. */\nexport const LOCAL_VERTEX_BITS = Math.ceil(Math.log2(MAX_MESHLET_VERTICES));\nconst LOCAL_VERTEX_MASK = (1 << LOCAL_VERTEX_BITS) - 1;\nconst MAX_DISPATCH = 65535;\n/** Instances per cell. A cell is a contiguous range of one mesh's Morton-sorted instances. */\nexport const CELL_SIZE = 128;\nconst CULL_GROUP = 64;\nconst MESHLET_GROUP = 64;\nconst EXPAND_GROUP = 64;\n/** Level-table entries cached in workgroup memory by the instance pass (2 vec4 per level). */\nconst MAX_LEVELS = 48;\n/** vec4s per mesh record in the mesh table. */\nconst MESH_STRIDE = 6;\n/** vec4s per instance: 4 matrix columns, then (tint rgb, mesh slot). */\nconst INSTANCE_STRIDE = 5;\n/** vec4s per cell: bounding sphere, then (max instance radius, mesh slot, first instance, instance count). */\nconst CELL_STRIDE = 2;\n/** Fraction of `maxDrawDistance` over which instances shrink to nothing before they are culled. */\nexport const DRAW_DISTANCE_FADE = 0.15;\n/** Stand-in for an infinite draw distance on the GPU. */\nexport const NO_DRAW_DISTANCE = 1e30;\n/** Global counters: [0] visible cells, [1] occluded instances, then CUT_COUNTERS per cut. */\nconst CUT_COUNTERS = 5;\nconst C_SELECTED = 0;\nconst C_DRAWN = 1;\nconst C_SURVIVED = 2;\nconst C_WORK = 3;\nconst C_REQUESTED = 4;\nconst PER_MESH_COUNTERS = 2 + 2 * CUT_COUNTERS;\n\nexport interface PoolCapacity {\n /** Max meshlets drawn per frame, per cut. */\n meshlets: number;\n /** Max triangles drawn per frame by the camera cut (its index buffer). */\n triangles: number;\n /** Max triangles drawn per frame into shadow maps. */\n shadowTriangles: number;\n}\n\n/** CPU-side record of one mesh's place in the pool. */\nexport interface PoolEntry {\n slot: number;\n data: VirtualMeshData;\n vertexBase: number;\n meshletBase: number;\n meshletVertexBase: number;\n triangleBase: number;\n levelBase: number;\n levelCount: number;\n instanceBase: number;\n instanceCount: number;\n cellBase: number;\n cellCount: number;\n uvScale: [number, number];\n uvOffset: [number, number];\n}\n\n/** Growable typed array with a GPU attribute; growth replaces the attribute (the pool then rebuilds its nodes). */\nclass GrowBuffer<T extends Float32Array | Uint32Array> {\n array: T;\n attribute: THREE.StorageBufferAttribute;\n used = 0;\n constructor(\n private readonly make: (n: number) => T,\n readonly itemSize: number,\n capacity: number,\n /** Largest capacity (items) whose binding stays under the pool's byte limit. */\n private readonly maxItems = Infinity\n ) {\n this.array = make(Math.max(1, capacity) * itemSize);\n this.attribute = new THREE.StorageBufferAttribute(this.array, itemSize);\n }\n get capacity() {\n return this.array.length / this.itemSize;\n }\n /** Reserves `count` items; returns the first, or -1 when the buffer must grow first. */\n reserve(count: number) {\n if (this.used + count > this.capacity) return -1;\n const first = this.used;\n this.used += count;\n return first;\n }\n /** Reallocates to hold at least `needed` items (keeps the contents). */\n grow(needed: number) {\n // Grow ahead (fewer rebuilds), but never past the binding limit: the pool checked that `needed` fits.\n const next = this.make(Math.min(Math.max(needed, Math.ceil(this.capacity * 1.6)), Math.max(needed, this.maxItems)) * this.itemSize);\n next.set(this.array);\n this.array = next;\n this.attribute = new THREE.StorageBufferAttribute(this.array, this.itemSize);\n }\n /** Marks items [first, first + count) for upload. */\n touch(first: number, count: number) {\n if (count <= 0) return;\n this.attribute.addUpdateRange(first * this.itemSize, count * this.itemSize);\n this.attribute.needsUpdate = true;\n }\n}\n\nconst f32 = (n: number) => new Float32Array(n);\nconst u32 = (n: number) => new Uint32Array(n);\n\nexport class GeometryPool {\n readonly entries: (PoolEntry | null)[] = [];\n /** Highest used mesh slot + 1 (the prefix pass loops over this many). */\n readonly meshSlots = uniform(0, 'uint');\n readonly cellCount = uniform(0, 'uint');\n readonly maxBytes: number;\n readonly capacity: PoolCapacity;\n\n // geometry\n readonly vertexData: GrowBuffer<Uint32Array>; // uvec4: position float bits xyz + octahedral normal\n readonly vertexAttrs: GrowBuffer<Uint32Array>; // uvec2: rgba8 color + uv (2 x unorm16 over the mesh's uv bounds)\n readonly meshletBounds: GrowBuffer<Float32Array>; // 4 x vec4 per meshlet\n readonly meshletInfo: GrowBuffer<Uint32Array>; // uvec4: triangleCount, firstIndex, lodLevel, vertexOffset (pool-global)\n readonly meshletVertices: GrowBuffer<Uint32Array>; // pool-global vertex ids\n readonly meshletTriangles: GrowBuffer<Uint32Array>; // 3 x u8 local ids\n // scene\n readonly meshTable: GrowBuffer<Float32Array>; // MESH_STRIDE vec4 per slot, then the level tables (2 vec4 per level)\n readonly instances: GrowBuffer<Float32Array>; // INSTANCE_STRIDE vec4 per instance\n readonly cells: GrowBuffer<Float32Array>; // CELL_STRIDE vec4 per cell\n private meshSlotCapacity: number;\n private levelUsed = 0;\n\n // per frame (rebuilt with the nodes)\n private countersAttribute!: THREE.StorageBufferAttribute;\n drawArgsAttribute!: THREE.IndirectStorageBufferAttribute;\n cameraIndex!: THREE.StorageBufferAttribute;\n shadowIndex!: THREE.StorageBufferAttribute;\n computeNodes: THREE.ComputeNode[] = [];\n positionNode: Node = null;\n /** Bumped on every rebuild: meshes re-point their geometry and material when it changes. */\n version = 0;\n private needsRebuild = true;\n private indexBuffersReady = false;\n pipelineState: 'none' | 'compiling' | 'ready' = 'none';\n /** The cut needs recomputing (camera moved, instances or settings changed). */\n dirty = true;\n /** True once a cut was computed (its camera index buffer can then serve as occluders). */\n hasCut = false;\n\n constructor(\n private readonly context: VirtualGeometry,\n capacity: PoolCapacity,\n maxBytes: number\n ) {\n this.capacity = capacity;\n this.maxBytes = maxBytes;\n this.meshSlotCapacity = 64;\n const limit = (bytesPerItem: number) => Math.floor(maxBytes / bytesPerItem);\n this.vertexData = new GrowBuffer(u32, 4, 1 << 16, limit(16));\n this.vertexAttrs = new GrowBuffer(u32, 2, 1 << 16, limit(8));\n this.meshletBounds = new GrowBuffer(f32, 16, 1 << 12, limit(64));\n this.meshletInfo = new GrowBuffer(u32, 4, 1 << 12, limit(16));\n this.meshletVertices = new GrowBuffer(u32, 1, 1 << 18, limit(4));\n this.meshletTriangles = new GrowBuffer(u32, 1, 1 << 18, limit(4));\n this.meshTable = new GrowBuffer(f32, 4, this.meshSlotCapacity * MESH_STRIDE + 1024, limit(16));\n this.meshTable.used = this.meshSlotCapacity * MESH_STRIDE;\n // In vec4s: whole instances only, and the work list (2 x 16 bytes per instance) stays smaller.\n this.instances = new GrowBuffer(f32, 4, 1 << 12, limit(16 * INSTANCE_STRIDE) * INSTANCE_STRIDE);\n this.cells = new GrowBuffer(f32, 4, 1 << 8, limit(16));\n }\n\n /** Bytes the geometry of `data` takes in this pool (the largest single binding is what must fit). */\n static bytesOf(data: VirtualMeshData) {\n return Math.max((data.positions.length / 3) * 16, data.meshletVertices.length * 4, data.meshletTriangles.length * 4, data.meshletCount * 64);\n }\n\n /** True when `data` (and `instanceCount` instances) still fit under the binding-size limit. */\n fits(data: VirtualMeshData, instanceCount: number) {\n const after = (used: number, add: number, bytesPerItem: number) => (used + add) * bytesPerItem <= this.maxBytes;\n return (\n after(this.vertexData.used, data.positions.length / 3, 16) &&\n after(this.meshletBounds.used, data.meshletCount, 64) &&\n after(this.meshletVertices.used, data.meshletVertices.length, 4) &&\n after(this.meshletTriangles.used, data.meshletTriangles.length, 4) &&\n after(this.instances.used, instanceCount * INSTANCE_STRIDE, 16)\n );\n }\n\n // ------------------------------------------------------------------ meshes\n\n /** Appends a mesh's geometry and instances. Returns its entry (`slot` is its index in the mesh table). */\n add(data: VirtualMeshData, matrices: Float32Array, colors: Float32Array | undefined, gpuToInput: Uint32Array): PoolEntry {\n let slot = this.entries.indexOf(null);\n if (slot === -1) slot = this.entries.length;\n if (slot >= this.meshSlotCapacity) this.growMeshSlots(slot + 1);\n\n const vertexCount = data.positions.length / 3;\n const levelCount = data.levelRanges.length / 2;\n const instanceCount = matrices.length / 16;\n const cellCount = Math.ceil(instanceCount / CELL_SIZE);\n const at = <T extends Float32Array | Uint32Array>(buffer: GrowBuffer<T>, count: number) => {\n let first = buffer.reserve(count);\n if (first === -1) {\n buffer.grow(buffer.used + count);\n this.needsRebuild = true;\n first = buffer.reserve(count);\n }\n return first;\n };\n const entry: PoolEntry = {\n slot,\n data,\n vertexBase: at(this.vertexData, vertexCount),\n meshletBase: at(this.meshletBounds, data.meshletCount),\n meshletVertexBase: at(this.meshletVertices, data.meshletVertices.length),\n triangleBase: at(this.meshletTriangles, data.meshletTriangles.length),\n levelBase: 0,\n levelCount,\n instanceBase: at(this.instances, instanceCount * INSTANCE_STRIDE) / INSTANCE_STRIDE,\n instanceCount,\n cellBase: at(this.cells, cellCount * CELL_STRIDE) / CELL_STRIDE,\n cellCount,\n uvScale: [1, 1],\n uvOffset: [0, 0],\n };\n at(this.meshletInfo, data.meshletCount);\n at(this.vertexAttrs, vertexCount);\n // Level table entries live after the mesh records.\n entry.levelBase = this.meshSlotCapacity * MESH_STRIDE + this.levelUsed;\n if (entry.levelBase + levelCount * 2 > this.meshTable.capacity) {\n this.meshTable.grow(entry.levelBase + levelCount * 2);\n this.needsRebuild = true;\n }\n this.levelUsed += levelCount * 2;\n this.meshTable.used = Math.max(this.meshTable.used, entry.levelBase + levelCount * 2);\n\n this.entries[slot] = entry;\n this.writeGeometry(entry);\n this.writeInstances(entry, matrices, colors, gpuToInput);\n this.writeMeshRecord(entry, { maxDrawDistance: NO_DRAW_DISTANCE, minPixelRadius: 0, enabled: 1, shadow: 1, occlusion: 0 });\n this.meshSlots.value = Math.max(this.meshSlots.value, slot + 1);\n this.cellCount.value = this.cells.used / CELL_STRIDE;\n this.dirty = true;\n return entry;\n }\n\n /** Frees a mesh's slot (its buffer ranges are reclaimed when the pool is next repacked). */\n remove(entry: PoolEntry) {\n this.writeFlags(entry, { enabled: 0 });\n this.entries[entry.slot] = null;\n // Its cells stay in the cell buffer but point at a disabled slot, so they are rejected at once.\n this.dirty = true;\n }\n\n private growMeshSlots(needed: number) {\n // The level tables start after the mesh records: move them up.\n const old = this.meshSlotCapacity;\n const next = Math.max(needed, old * 2);\n const shift = (next - old) * MESH_STRIDE;\n const levelsStart = old * MESH_STRIDE;\n const grownSize = this.meshTable.used + shift;\n if (grownSize > this.meshTable.capacity) this.meshTable.grow(grownSize);\n const table = this.meshTable.array;\n table.copyWithin((levelsStart + shift) * 4, levelsStart * 4, this.meshTable.used * 4);\n table.fill(0, levelsStart * 4, (levelsStart + shift) * 4);\n this.meshTable.used += shift;\n this.meshSlotCapacity = next;\n for (const entry of this.entries) {\n if (!entry) continue;\n entry.levelBase += shift;\n table[(entry.slot * MESH_STRIDE + 3) * 4 + 3] = entry.levelBase;\n }\n this.needsRebuild = true;\n }\n\n private writeGeometry(e: PoolEntry) {\n const d = e.data;\n const vertexCount = d.positions.length / 3;\n // Vertices: position bits + octahedral normal.\n const vd = this.vertexData.array;\n const asFloat = new Float32Array(vd.buffer, vd.byteOffset, vd.length);\n for (let i = 0; i < vertexCount; i++) {\n const o = (e.vertexBase + i) * 4;\n asFloat[o] = d.positions[i * 3];\n asFloat[o + 1] = d.positions[i * 3 + 1];\n asFloat[o + 2] = d.positions[i * 3 + 2];\n vd[o + 3] = encodeOctNormal(d.normals[i * 3], d.normals[i * 3 + 1], d.normals[i * 3 + 2]);\n }\n this.vertexData.touch(e.vertexBase, vertexCount);\n // Per-vertex color (white without colors) and uv (quantized over the mesh's uv bounds).\n const va = this.vertexAttrs.array;\n const uv = d.uvs ? packUvs(d.uvs) : null;\n if (uv) {\n e.uvScale = uv.scale;\n e.uvOffset = uv.offset;\n }\n const q = (x: number) => Math.round(Math.max(0, Math.min(1, x)) * 255);\n for (let i = 0; i < vertexCount; i++) {\n const o = (e.vertexBase + i) * 2;\n va[o] = d.colors ? (q(d.colors[i * 3]) | (q(d.colors[i * 3 + 1]) << 8) | (q(d.colors[i * 3 + 2]) << 16) | (255 << 24)) >>> 0 : 0xffffffff;\n va[o + 1] = uv ? uv.packed[i] : 0;\n }\n this.vertexAttrs.touch(e.vertexBase, vertexCount);\n // Meshlets, rebased to pool-global vertex / index ranges.\n this.meshletBounds.array.set(d.meshletBounds, e.meshletBase * 16);\n this.meshletBounds.touch(e.meshletBase, d.meshletCount);\n const info = this.meshletInfo.array;\n for (let m = 0; m < d.meshletCount; m++) {\n const o = (e.meshletBase + m) * 4;\n const s = m * MESHLET_INFO_STRIDE;\n info[o] = d.meshletInfo[s];\n info[o + 1] = d.meshletInfo[s + 1] + e.triangleBase * 3;\n info[o + 2] = d.meshletInfo[s + 2];\n info[o + 3] = d.meshletInfo[s + 3] + e.meshletVertexBase;\n }\n this.meshletInfo.touch(e.meshletBase, d.meshletCount);\n const mv = this.meshletVertices.array;\n for (let i = 0; i < d.meshletVertices.length; i++) mv[e.meshletVertexBase + i] = d.meshletVertices[i] + e.vertexBase;\n this.meshletVertices.touch(e.meshletVertexBase, d.meshletVertices.length);\n this.meshletTriangles.array.set(d.meshletTriangles, e.triangleBase);\n this.meshletTriangles.touch(e.triangleBase, d.meshletTriangles.length);\n // Level table: (first meshlet, count, smallest own error, largest parent error), (largest own, smallest parent).\n const t = this.meshTable.array;\n for (let l = 0; l < e.levelCount; l++) {\n const o = (e.levelBase + l * 2) * 4;\n t[o] = d.levelRanges[l * 2] + e.meshletBase;\n t[o + 1] = d.levelRanges[l * 2 + 1];\n t[o + 2] = d.levelErrors[l * 2];\n t[o + 3] = d.levelErrors[l * 2 + 1];\n t[o + 4] = d.levelGuardErrors[l * 2];\n t[o + 5] = d.levelGuardErrors[l * 2 + 1];\n t[o + 6] = 0;\n t[o + 7] = 0;\n }\n this.meshTable.touch(e.levelBase, e.levelCount * 2);\n }\n\n /** Writes a mesh record: bounding spheres, levers, level table location, uv packing, flags. */\n writeMeshRecord(e: PoolEntry, o: { maxDrawDistance: number; minPixelRadius: number; enabled: number; shadow: number; occlusion: number }) {\n const t = this.meshTable.array;\n const base = e.slot * MESH_STRIDE * 4;\n t.set(e.data.boundingSphere, base);\n t.set(e.data.lodBoundsSphere, base + 4);\n t.set(e.data.cullBoundsSphere, base + 8);\n t.set([o.maxDrawDistance, o.minPixelRadius, e.levelCount, e.levelBase], base + 12);\n t.set([e.uvScale[0], e.uvScale[1], e.uvOffset[0], e.uvOffset[1]], base + 16);\n t.set([o.enabled, o.shadow, o.occlusion, 0], base + 20);\n this.meshTable.touch(e.slot * MESH_STRIDE, MESH_STRIDE);\n this.dirty = true;\n }\n\n /** Updates some of a mesh's per-frame levers (only what changed is uploaded). */\n writeFlags(e: PoolEntry, o: { maxDrawDistance?: number; minPixelRadius?: number; enabled?: number; shadow?: number; occlusion?: number }) {\n const t = this.meshTable.array;\n const base = e.slot * MESH_STRIDE * 4;\n const set = (index: number, value: number | undefined) => {\n if (value === undefined || t[base + index] === value) return;\n t[base + index] = value;\n this.meshTable.touch(e.slot * MESH_STRIDE + (index >> 2), 1);\n this.dirty = true;\n };\n set(12, o.maxDrawDistance);\n set(13, o.minPixelRadius);\n set(20, o.enabled);\n set(21, o.shadow);\n set(22, o.occlusion);\n }\n\n readFlag(e: PoolEntry, index: 'maxDrawDistance' | 'minPixelRadius' | 'enabled' | 'shadow' | 'occlusion') {\n const offsets = { maxDrawDistance: 12, minPixelRadius: 13, enabled: 20, shadow: 21, occlusion: 22 };\n return this.meshTable.array[e.slot * MESH_STRIDE * 4 + offsets[index]];\n }\n\n private writeInstances(e: PoolEntry, matrices: Float32Array, colors: Float32Array | undefined, gpuToInput: Uint32Array) {\n const a = this.instances.array;\n for (let g = 0; g < e.instanceCount; g++) {\n const src = gpuToInput[g];\n const o = (e.instanceBase + g) * INSTANCE_STRIDE * 4;\n a.set(matrices.subarray(src * 16, src * 16 + 16), o);\n if (colors) a.set(colors.subarray(src * 4, src * 4 + 3), o + 16);\n else a.fill(1, o + 16, o + 19);\n a[o + 19] = e.slot;\n }\n this.instances.touch(e.instanceBase * INSTANCE_STRIDE, e.instanceCount * INSTANCE_STRIDE);\n for (let c = 0; c < e.cellCount; c++) this.computeCell(e, c);\n this.cells.touch(e.cellBase * CELL_STRIDE, e.cellCount * CELL_STRIDE);\n }\n\n /** Writes one instance matrix (GPU order index within the mesh). Call `commitInstances` afterwards. */\n setMatrix(e: PoolEntry, gpuIndex: number, matrix: THREE.Matrix4) {\n matrix.toArray(this.instances.array, (e.instanceBase + gpuIndex) * INSTANCE_STRIDE * 4);\n }\n\n /** Uploads changed instances and refreshes the bounds of the given cells. */\n commitInstances(e: PoolEntry, cells: Iterable<number>) {\n this.instances.touch(e.instanceBase * INSTANCE_STRIDE, e.instanceCount * INSTANCE_STRIDE);\n for (const c of cells) {\n this.computeCell(e, c);\n this.cells.touch((e.cellBase + c) * CELL_STRIDE, CELL_STRIDE);\n }\n this.dirty = true;\n }\n\n /**\n * Bounding sphere of one cell's instances: the AABB of their world-space object spheres gives the center, and\n * the radius reaches every instance sphere. Both radii are inflated a little so float32 rounding on the GPU can\n * never make the cell test stricter than the per-instance test.\n */\n private computeCell(e: PoolEntry, cell: number) {\n const m = this.instances.array;\n const first = cell * CELL_SIZE;\n const end = Math.min(first + CELL_SIZE, e.instanceCount);\n const s = new Float64Array(4);\n const lo = [Infinity, Infinity, Infinity];\n const hi = [-Infinity, -Infinity, -Infinity];\n let maxRadius = 0;\n for (let g = first; g < end; g++) {\n instanceSphere(m, (e.instanceBase + g) * INSTANCE_STRIDE * 4, e.data.boundingSphere, s);\n for (let a = 0; a < 3; a++) {\n lo[a] = Math.min(lo[a], s[a] - s[3]);\n hi[a] = Math.max(hi[a], s[a] + s[3]);\n }\n maxRadius = Math.max(maxRadius, s[3]);\n }\n const cx = (lo[0] + hi[0]) / 2;\n const cy = (lo[1] + hi[1]) / 2;\n const cz = (lo[2] + hi[2]) / 2;\n let radius = 0;\n for (let g = first; g < end; g++) {\n instanceSphere(m, (e.instanceBase + g) * INSTANCE_STRIDE * 4, e.data.boundingSphere, s);\n radius = Math.max(radius, Math.hypot(s[0] - cx, s[1] - cy, s[2] - cz) + s[3]);\n }\n const o = (e.cellBase + cell) * CELL_STRIDE * 4;\n this.cells.array.set([cx, cy, cz, radius * (1 + 1e-4) + 1e-3, maxRadius * (1 + 1e-4) + 1e-4, e.slot, e.instanceBase + first, end - first], o);\n }\n\n // ------------------------------------------------------------------ GPU\n\n /**\n * Index buffers are written by compute and read by draws. three.js picks GPU buffer usage from the first use,\n * so create them as index buffers (INDEX | STORAGE) before any compute. Also rebuilds the nodes after growth.\n */\n prepare(renderer: THREE.WebGPURenderer) {\n this.ensureBuilt();\n if (this.indexBuffersReady) return;\n const backend = renderer.backend as unknown as { createIndexAttribute(a: unknown): void };\n backend.createIndexAttribute(this.cameraIndex);\n backend.createIndexAttribute(this.shadowIndex);\n this.indexBuffersReady = true;\n }\n\n /** Builds the nodes if the pool's buffers grew since the last build (or it was never built). */\n ensureBuilt() {\n if (this.needsRebuild) this.build();\n }\n\n /** Recreates the per-frame buffers and every node (after the pool's buffers grew). */\n build() {\n this.needsRebuild = false;\n this.indexBuffersReady = false;\n this.pipelineState = 'none';\n this.hasCut = false;\n this.version++;\n for (const node of this.computeNodes) node.dispose();\n\n const ctx = this.context;\n const cap = this.capacity;\n const slots = this.meshSlotCapacity;\n const maxDrawn = cap.meshlets;\n const instanceCapacity = Math.floor(this.instances.capacity / INSTANCE_STRIDE);\n const cellCapacity = Math.floor(this.cells.capacity / CELL_STRIDE);\n const cameraIndexCapacity = cap.triangles * 3;\n const shadowIndexCapacity = cap.shadowTriangles * 3;\n\n // Attribute objects of the growable buffers (replaced when they grew).\n const storageOf = (buffer: GrowBuffer<Float32Array | Uint32Array>, type: string): Node => (storage as Node)(buffer.attribute, type, buffer.capacity);\n const vertexData: Node = storageOf(this.vertexData, 'uvec4').toReadOnly();\n const vertexAttrs: Node = storageOf(this.vertexAttrs, 'uvec2').toReadOnly();\n const bounds: Node = storageOf(this.meshletBounds, 'vec4').toReadOnly();\n const info: Node = storageOf(this.meshletInfo, 'uvec4').toReadOnly();\n const meshletVertices: Node = storageOf(this.meshletVertices, 'uint').toReadOnly();\n const meshletTriangles: Node = storageOf(this.meshletTriangles, 'uint').toReadOnly();\n const meshTable: Node = storageOf(this.meshTable, 'vec4').toReadOnly();\n const instances: Node = storageOf(this.instances, 'vec4').toReadOnly();\n const cells: Node = storageOf(this.cells, 'vec4').toReadOnly();\n\n // Per-frame buffers.\n // counters: PER_MESH_COUNTERS globals, then per cut and mesh slot (requested indices, region start).\n this.countersAttribute = new THREE.StorageBufferAttribute(new Uint32Array(PER_MESH_COUNTERS + 2 * slots * 2), 1);\n // drawIndexedIndirect args per cut and mesh slot: indexCount, instanceCount, firstIndex, baseVertex, firstInstance.\n this.drawArgsAttribute = new THREE.IndirectStorageBufferAttribute(new Uint32Array(2 * slots * 5), 1);\n this.cameraIndex = new THREE.StorageBufferAttribute(new Uint32Array(cameraIndexCapacity), 1);\n this.shadowIndex = new THREE.StorageBufferAttribute(new Uint32Array(shadowIndexCapacity), 1);\n const cellListAttribute = new THREE.StorageBufferAttribute(new Uint32Array(cellCapacity * 4), 4);\n // (instance, first meshlet, end meshlet, mesh slot | occlusion << 31) per cut.\n const workListAttribute = new THREE.StorageBufferAttribute(new Uint32Array(instanceCapacity * 2 * 4), 4);\n // (instance, meshlet, first index within the mesh's region, triangle count); slots are absolute over both cuts.\n const drawListAttribute = new THREE.StorageBufferAttribute(new Uint32Array(maxDrawn * 2 * 4), 4);\n const dispatchAttr = () => new THREE.IndirectStorageBufferAttribute(new Uint32Array(3), 3);\n const instanceArgsAttribute = dispatchAttr();\n const meshletArgsAttributes = [dispatchAttr(), dispatchAttr()];\n const expandArgsAttributes = [dispatchAttr(), dispatchAttr()];\n\n const counters: Node = storage(this.countersAttribute, 'uint', this.countersAttribute.count).toAtomic();\n const drawArgs: Node = storage(this.drawArgsAttribute, 'uint', this.drawArgsAttribute.count);\n const cameraIndex: Node = storage(this.cameraIndex, 'uint', cameraIndexCapacity);\n const shadowIndex: Node = storage(this.shadowIndex, 'uint', shadowIndexCapacity);\n const cellList: Node = storage(cellListAttribute, 'uvec4', cellCapacity);\n const cellListRead: Node = storage(cellListAttribute, 'uvec4', cellCapacity).toReadOnly();\n const workList: Node = storage(workListAttribute, 'uvec4', instanceCapacity * 2);\n const drawList: Node = storage(drawListAttribute, 'uvec4', maxDrawn * 2);\n const drawListRead: Node = storage(drawListAttribute, 'uvec4', maxDrawn * 2).toReadOnly();\n const instanceArgs: Node = storage(instanceArgsAttribute, 'uint', 3);\n const meshletArgs = meshletArgsAttributes.map((a) => storage(a, 'uint', 3) as Node);\n const expandArgs = expandArgsAttributes.map((a) => storage(a, 'uint', 3) as Node);\n\n const counter = (cut: number, i: number) => counters.element(2 + cut * CUT_COUNTERS + i);\n const meshCount = (cut: number, slot: Node) => counters.element(uint(PER_MESH_COUNTERS + cut * slots * 2).add(slot.mul(2)));\n const meshStart = (cut: number, slot: Node) => counters.element(uint(PER_MESH_COUNTERS + cut * slots * 2 + 1).add(slot.mul(2)));\n const cutCapacity = [cameraIndexCapacity, shadowIndexCapacity];\n const indexBuffers = [cameraIndex, shadowIndex];\n\n const shadowThreshold: Node = ctx.errorThreshold.mul(ctx.shadowErrorScale);\n const thresholds = [ctx.errorThreshold as Node, shadowThreshold];\n const minPixelsGlobal: Node = ctx.minPixelRadius;\n const occlusion = ctx.occlusion;\n\n const instanceColumn = (instanceId: Node, k: number) => instances.element(instanceId.mul(INSTANCE_STRIDE).add(k));\n const modelOf = (instanceId: Node) => {\n const c = [0, 1, 2, 3].map((k) => instanceColumn(instanceId, k).toVar());\n const model = mat4(c[0], c[1], c[2], c[3]).toVar();\n const scale = max(length(c[0].xyz), max(length(c[1].xyz), length(c[2].xyz))).toVar();\n return { model, scale, columns: c };\n };\n const meshRecord = (slot: Node, k: number) => meshTable.element(slot.mul(MESH_STRIDE).add(k));\n\n const projectedError = (model: Node, scale: Node, sphere: Node, error: Node) => {\n const viewCenter: Node = (ctx.viewMatrix as Node).mul(model.mul(vec4(sphere.xyz, 1)));\n const distance = max(length(viewCenter.xyz).sub(sphere.w.mul(scale)), ctx.near) as Node;\n const pixels = error.mul(scale).div(distance).mul(ctx.projScale);\n return select(error.greaterThanEqual(ERROR_INFINITY * 0.5), float(ERROR_INFINITY), pixels);\n };\n\n /**\n * Signed distance of a sphere to the camera frustum (negative radius-or-more = fully outside). With `swept`,\n * the sphere is swept along shadowSweep (the light direction): a caster outside the view can still throw a\n * shadow into it, so it is kept if ANY point of that segment is inside the plane: d(center) + max(0, dot(n, sweep)).\n */\n const frustumDistance = (center: Node, swept: Node | boolean) => {\n let minDistance: Node = float(1e30);\n for (const plane of ctx.frustumPlanes) {\n let d: Node = dot(plane.xyz, center).add(plane.w);\n if (swept !== false) d = d.add(max(dot(plane.xyz, ctx.shadowSweep), 0).mul(swept === true ? 1 : select(swept, float(1), float(0))));\n minDistance = min(minDistance, d);\n }\n return minDistance;\n };\n\n /** Hidden behind the occluders; the sphere grows by the error threshold (occluders are LOD-simplified). */\n const occludedSphere = (occlusionOn: Node, worldCenter: Node, radius: Node) => {\n const viewCenter: Node = (ctx.viewMatrix as Node).mul(vec4(worldCenter, 1)).xyz.toVar();\n const margin = viewCenter.z.abs().mul(ctx.errorThreshold).div(ctx.projScale);\n return occlusionOn.and((occlusion.activeNode as Node).equal(1)).and(occlusion.occluded(viewCenter, radius.add(margin)));\n };\n\n const dispatchArgs = (target: Node, count: Node) => {\n target.element(0).assign(minNode(count, uint(MAX_DISPATCH)));\n target.element(1).assign(count.add(MAX_DISPATCH - 1).div(MAX_DISPATCH));\n target.element(2).assign(uint(1));\n };\n\n // ---------- 0. reset ----------\n const resetNode = Fn(() => {\n const i = instanceIndex;\n If(i.lessThan(uint(PER_MESH_COUNTERS)), () => {\n atomicStore(counters.element(i), uint(0));\n });\n If(i.lessThan(this.meshSlots.mul(4)), () => {\n // count and start of slot i>>1 for both cuts\n const cut = i.div(this.meshSlots.mul(2));\n const rest = i.mod(this.meshSlots.mul(2));\n atomicStore(counters.element(uint(PER_MESH_COUNTERS).add(cut.mul(slots * 2)).add(rest)), uint(0));\n });\n })().compute(Math.max(PER_MESH_COUNTERS, slots * 4), [64]);\n\n // ---------- 1. cells ----------\n const cellNode = Fn(() => {\n If(instanceIndex.greaterThanEqual(this.cellCount), () => {\n Return();\n });\n const cell = instanceIndex.toVar();\n const sphere = cells.element(cell.mul(CELL_STRIDE)).toVar();\n const record = cells.element(cell.mul(CELL_STRIDE).add(1)).toVar();\n const slot = uint(record.y).toVar();\n const flags = meshRecord(slot, 5).toVar();\n If(flags.x.equal(0), () => {\n Return(); // removed or invisible mesh\n });\n const center = sphere.xyz.toVar();\n const radius = sphere.w.toVar();\n If(ctx.frustumCulling.equal(1).and(frustumDistance(center, flags.y.greaterThan(0.5)).lessThan(radius.negate())), () => {\n Return();\n });\n const levers = meshRecord(slot, 3).toVar();\n const minPixels = max(minPixelsGlobal, levers.y);\n // Every instance lies within `radius` of the cell center, so its view distance is at least\n // viewDistance - radius, and its radius is at most maxRadius.\n const maxRadius = record.x;\n const viewDistance = length((ctx.viewMatrix as Node).mul(vec4(center, 1)).xyz).toVar();\n const gap = viewDistance.sub(radius).toVar();\n If(gap.greaterThan(maxRadius).and(maxRadius.mul(ctx.projScale).div(max(gap, 1e-6)).lessThan(minPixels)), () => {\n Return();\n });\n If(gap.greaterThan(levers.x), () => {\n Return(); // beyond the draw distance\n });\n const at = (atomicAdd(counters.element(0), uint(1)) as Node).toVar();\n cellList.element(at).assign(uvec4(slot, uint(record.z), uint(record.w), cell));\n })().compute(cellCapacity, [CULL_GROUP]);\n\n const cellArgsNode = Fn(() => {\n dispatchArgs(instanceArgs, (atomicLoad(counters.element(0)) as Node).toVar());\n })().compute(1);\n\n // ---------- 2. instances ----------\n // The mesh's level table is cached in workgroup memory: every instance of a cell belongs to one mesh.\n const levelCache: Node = workgroupArray('vec4', MAX_LEVELS * 2);\n\n /** Emits the level range of one instance for one cut, then its fast path or its work-list entry. */\n const selectLevels = (\n cut: number,\n slot: Node,\n levelCount: Node,\n occlusionFlag: Node,\n cullBounds: Node,\n instanceId: Node,\n model: Node,\n scale: Node,\n pixelsAtMin: Node,\n pixelsAtMax: Node\n ) => {\n const threshold = thresholds[cut];\n const first = uint(0xffffffff).toVar();\n const last = uint(0).toVar();\n const possibleMeshlets = uint(0).toVar();\n const guaranteedMeshlets = uint(0).toVar();\n Loop({ start: uint(0), end: levelCount, type: 'uint', condition: '<' }, ({ i }: { i: Node }) => {\n const l0 = levelCache.element(i.mul(2)).toVar(); // first meshlet, count, smallest own error, largest parent error\n const l1 = levelCache.element(i.mul(2).add(1)).toVar(); // largest own error, smallest parent error\n const levelFirst = uint(l0.x).toVar();\n const size = uint(l0.y).toVar();\n const possible = l0.z\n .mul(pixelsAtMax)\n .lessThanEqual(threshold)\n .and(l0.w.greaterThanEqual(ERROR_INFINITY * 0.5).or(l0.w.mul(pixelsAtMin).greaterThan(threshold)));\n // Every meshlet of the level passes for any distance in [min, max]: largest own error at the nearest\n // distance, smallest parent error at the farthest. Relative margin keeps float rounding on our side.\n const sure = l1.x\n .mul(pixelsAtMin)\n .lessThanEqual(threshold.mul(1 - FAST_PATH_MARGIN))\n .and(l1.y.greaterThanEqual(ERROR_INFINITY * 0.5).or(l1.y.mul(pixelsAtMax).greaterThan(threshold.mul(1 + FAST_PATH_MARGIN))));\n If(possible, () => {\n first.assign(minNode(first, levelFirst));\n last.assign(maxNode(last, levelFirst.add(size)));\n possibleMeshlets.addAssign(size);\n If(sure, () => {\n guaranteedMeshlets.addAssign(size);\n });\n });\n });\n\n const cullCenter = model.mul(vec4(cullBounds.xyz, 1)).xyz.toVar();\n const cullRadius = cullBounds.w.mul(scale).toVar();\n // Possible levels must be contiguous, all guaranteed, few, and every meshlet inside the frustum.\n const fastPath = possibleMeshlets\n .greaterThan(uint(0))\n .and(possibleMeshlets.equal(last.sub(first)))\n .and(guaranteedMeshlets.equal(possibleMeshlets))\n .and(possibleMeshlets.lessThanEqual(uint(FAST_PATH_MAX_MESHLETS)))\n .and(ctx.frustumCulling.equal(0).or(frustumDistance(cullCenter, cut === 1).greaterThanEqual(cullRadius)))\n .toVar();\n\n If(last.greaterThan(first), () => {\n atomicAdd(counter(cut, C_SURVIVED), uint(1));\n If(fastPath, () => {\n const base = (atomicAdd(counter(cut, C_SELECTED), possibleMeshlets) as Node).toVar();\n for (let k = 0; k < FAST_PATH_MAX_MESHLETS; k++) {\n If(uint(k).lessThan(possibleMeshlets).and(base.add(k).lessThan(uint(maxDrawn))), () => {\n const meshletId = first.add(k).toVar();\n const triangleCount = info.element(meshletId).x.toVar();\n const firstIndex = (atomicAdd(meshCount(cut, slot), triangleCount.mul(3)) as Node).toVar();\n drawList.element(base.add(k + cut * maxDrawn)).assign(uvec4(instanceId, meshletId, firstIndex, triangleCount));\n });\n }\n }).Else(() => {\n const item = (atomicAdd(counter(cut, C_WORK), uint(1)) as Node).toVar();\n const tag = slot.bitOr(select(occlusionFlag, uint(0x80000000), uint(0)));\n workList.element(item.add(cut * instanceCapacity)).assign(uvec4(instanceId, first, last, tag));\n });\n });\n };\n\n const instanceNode = Fn(() => {\n // No early return before the barrier (WGSL needs uniform control flow there): workgroups past the\n // visible-cell count (the dispatch is rounded up) load no levels and process no instances.\n const cellIndex = workgroupId.x.add(workgroupId.y.mul(numWorkgroups.x)).toVar();\n const valid = cellIndex.lessThan(atomicLoad(counters.element(0)) as Node).toVar();\n const cell = cellListRead.element(minNode(cellIndex, uint(cellCapacity - 1))).toVar(); // (mesh slot, first instance, count, cell)\n const slot = cell.x;\n const levers = meshRecord(slot, 3).toVar(); // draw distance, min pixel radius, level count, level base\n const levelCount = select(valid, minNode(uint(levers.z), uint(MAX_LEVELS)), uint(0)).toVar();\n const levelBase = uint(levers.w).toVar();\n Loop({ start: localId.x, end: levelCount.mul(2), type: 'uint', condition: '<', update: CULL_GROUP }, ({ i }: { i: Node }) => {\n levelCache.element(i).assign(meshTable.element(levelBase.add(i)));\n });\n workgroupBarrier();\n If(valid.not(), () => {\n Return();\n });\n\n const objectSphere = meshRecord(slot, 0).toVar();\n const lodBounds = meshRecord(slot, 1).toVar();\n const cullBounds = meshRecord(slot, 2).toVar();\n const flags = meshRecord(slot, 5).toVar(); // enabled, shadow, occlusion\n const shadowOn = flags.y.greaterThan(0.5);\n const occlusionOn = flags.z.greaterThan(0.5);\n const minPixels = max(minPixelsGlobal, levers.y).toVar();\n const maxDrawDistance = levers.x.toVar();\n const end = cell.y.add(cell.z);\n Loop({ start: cell.y.add(localId.x), end, type: 'uint', condition: '<', update: CULL_GROUP }, ({ i }: { i: Node }) => {\n const instanceId = i.toVar();\n const { model, scale } = modelOf(instanceId);\n const center = model.mul(vec4(objectSphere.xyz, 1)).xyz.toVar();\n const radius = objectSphere.w.mul(scale).toVar();\n const noFrustum = ctx.frustumCulling.equal(0);\n const inCamera = noFrustum.or(frustumDistance(center, false).greaterThanEqual(radius.negate())).toVar();\n const inShadow = shadowOn.and(noFrustum.or(frustumDistance(center, true).greaterThanEqual(radius.negate()))).toVar();\n // Sub-pixel instances and instances beyond the draw distance: both cuts.\n const viewDistance = length((ctx.viewMatrix as Node).mul(vec4(center, 1)).xyz).toVar();\n const tooSmall = viewDistance.greaterThan(radius).and(radius.mul(ctx.projScale).div(viewDistance).lessThan(minPixels));\n const tooFar = viewDistance.sub(radius).greaterThan(maxDrawDistance);\n const keep = inCamera.or(inShadow).and(tooSmall.not()).and(tooFar.not());\n If(keep, () => {\n If(inCamera.and(occludedSphere(occlusionOn, center, radius)), () => {\n inCamera.assign(bool(false));\n atomicAdd(counters.element(1), uint(1));\n });\n const lodCenter: Node = (ctx.viewMatrix as Node).mul(model.mul(vec4(lodBounds.xyz, 1)));\n const d = length(lodCenter.xyz).toVar();\n const r = lodBounds.w.mul(scale);\n const pixelsAtMin = scale.mul(ctx.projScale).div(max(d.sub(r), ctx.near)).toVar();\n const pixelsAtMax = scale.mul(ctx.projScale).div(max(d.add(r), ctx.near)).toVar();\n If(inCamera, () => {\n selectLevels(0, slot, levelCount, occlusionOn, cullBounds, instanceId, model, scale, pixelsAtMin, pixelsAtMax);\n });\n If(inShadow, () => {\n selectLevels(1, slot, levelCount, bool(false), cullBounds, instanceId, model, scale, pixelsAtMin, pixelsAtMax);\n });\n });\n });\n })().compute(instanceArgsAttribute as unknown as number, [CULL_GROUP]);\n\n // ---------- 3. meshlets ----------\n const meshletPass = (cut: number) => {\n const argsNode = Fn(() => {\n dispatchArgs(meshletArgs[cut], (atomicLoad(counter(cut, C_WORK)) as Node).toVar());\n })().compute(1);\n const passNode = Fn(() => {\n const item = workgroupId.x.add(workgroupId.y.mul(numWorkgroups.x)).toVar();\n If(item.greaterThanEqual(atomicLoad(counter(cut, C_WORK)) as Node), () => {\n Return();\n });\n const work = workList.element(item.add(cut * instanceCapacity)).toVar();\n const instanceId = work.x;\n const slot = work.w.bitAnd(0x7fffffff).toVar();\n const occlusionOn = work.w.shiftRight(31).equal(1);\n const { model, scale } = modelOf(instanceId);\n Loop({ start: work.y.add(localId.x), end: work.z, type: 'uint', condition: '<', update: MESHLET_GROUP }, ({ i }: { i: Node }) => {\n const meshletId = i;\n const boundsBase = meshletId.mul(MESHLET_BOUNDS_STRIDE / 4).toVar();\n const cullSphere = bounds.element(boundsBase.add(3));\n const center = model.mul(vec4(cullSphere.xyz, 1)).xyz;\n let visible: Node = ctx.frustumCulling.equal(0).or(frustumDistance(center, cut === 1).greaterThanEqual(cullSphere.w.mul(scale).negate()));\n if (cut === 0) visible = visible.and(occludedSphere(occlusionOn, center, cullSphere.w.mul(scale)).not());\n // LOD selection: draw this meshlet iff its own error is small enough but its parent's is not.\n const errors = bounds.element(boundsBase.add(2));\n const ownError = projectedError(model, scale, bounds.element(boundsBase), errors.x);\n const parentError = projectedError(model, scale, bounds.element(boundsBase.add(1)), errors.y);\n If(visible.and(ownError.lessThanEqual(thresholds[cut])).and(parentError.greaterThan(thresholds[cut])), () => {\n const at = (atomicAdd(counter(cut, C_SELECTED), uint(1)) as Node).toVar();\n If(at.lessThan(uint(maxDrawn)), () => {\n const triangleCount = info.element(meshletId).x.toVar();\n const firstIndex = (atomicAdd(meshCount(cut, slot), triangleCount.mul(3)) as Node).toVar();\n drawList.element(at.add(cut * maxDrawn)).assign(uvec4(instanceId, meshletId, firstIndex, triangleCount));\n });\n });\n });\n })().compute(meshletArgsAttributes[cut] as unknown as number, [MESHLET_GROUP]);\n return [argsNode, passNode];\n };\n\n // ---------- 4. prefix: lay the meshes' regions out, write draw args and the expand dispatch ----------\n const prefixPass = (cut: number) =>\n Fn(() => {\n const start = uint(0).toVar();\n const capacity = uint(cutCapacity[cut]);\n Loop({ start: uint(0), end: this.meshSlots, type: 'uint', condition: '<' }, ({ i }: { i: Node }) => {\n const requested = (atomicLoad(meshCount(cut, i)) as Node).toVar();\n atomicStore(meshStart(cut, i), start);\n const room = select(start.lessThan(capacity), capacity.sub(start), uint(0));\n const args = uint(cut * slots * 5).add(i.mul(5)).toVar();\n drawArgs.element(args).assign(minNode(requested, room));\n drawArgs.element(args.add(1)).assign(uint(1));\n drawArgs.element(args.add(2)).assign(start);\n drawArgs.element(args.add(3)).assign(uint(0));\n drawArgs.element(args.add(4)).assign(uint(0));\n start.addAssign(requested);\n });\n atomicStore(counter(cut, C_REQUESTED), start);\n const drawn = minNode(atomicLoad(counter(cut, C_SELECTED)) as Node, uint(maxDrawn)).toVar();\n atomicStore(counter(cut, C_DRAWN), drawn);\n dispatchArgs(expandArgs[cut], drawn);\n })().compute(1);\n\n // ---------- 5. expand ----------\n const expandPass = (cut: number) =>\n Fn(() => {\n const at = workgroupId.x.add(workgroupId.y.mul(numWorkgroups.x)).toVar();\n If(at.greaterThanEqual(atomicLoad(counter(cut, C_DRAWN)) as Node), () => {\n Return();\n });\n const drawSlot = at.add(cut * maxDrawn).toVar();\n const entry = drawListRead.element(drawSlot).toVar();\n const slot = uint(instanceColumn(entry.x, 4).w).toVar();\n const regionStart = (atomicLoad(meshStart(cut, slot)) as Node).toVar();\n const firstTriangle = info.element(entry.y).y.div(3).toVar();\n const base = drawSlot.shiftLeft(LOCAL_VERTEX_BITS).toVar();\n const buffer = indexBuffers[cut];\n Loop({ start: localId.x, end: entry.w, type: 'uint', condition: '<', update: EXPAND_GROUP }, ({ i }: { i: Node }) => {\n const index = regionStart.add(entry.z).add(i.mul(3)).toVar();\n If(index.add(2).lessThan(uint(cutCapacity[cut])), () => {\n const packed = meshletTriangles.element(firstTriangle.add(i)).toVar();\n buffer.element(index).assign(base.bitOr(packed.bitAnd(255)));\n buffer.element(index.add(1)).assign(base.bitOr(packed.shiftRight(8).bitAnd(255)));\n buffer.element(index.add(2)).assign(base.bitOr(packed.shiftRight(16).bitAnd(255)));\n });\n });\n })().compute(expandArgsAttributes[cut] as unknown as number, [EXPAND_GROUP]);\n\n this.computeNodes = [\n resetNode,\n cellNode,\n cellArgsNode,\n instanceNode,\n ...meshletPass(0),\n ...meshletPass(1),\n prefixPass(0),\n prefixPass(1),\n expandPass(0),\n expandPass(1),\n ];\n\n // ---------- vertex pulling (shared by every mesh of the pool, both cuts) ----------\n this.positionNode = Fn(() => {\n const slot = vertexIndex.shiftRight(LOCAL_VERTEX_BITS);\n const localVertex = vertexIndex.bitAnd(LOCAL_VERTEX_MASK);\n const entry = drawListRead.element(slot).toVar();\n const instanceId = entry.x;\n const meshletId = entry.y;\n const meshletInfo = info.element(meshletId).toVar();\n const vertexId: Node = meshletVertices.element(meshletInfo.w.add(localVertex)).toVar();\n\n const { model, columns } = modelOf(instanceId);\n const tintAndSlot = instanceColumn(instanceId, 4).toVar();\n const meshSlot = uint(tintAndSlot.w).toVar();\n const levers = meshRecord(meshSlot, 3);\n const uvPacking = meshRecord(meshSlot, 4).toVar();\n const packedVertex = vertexData.element(vertexId).toVar();\n const attrs = vertexAttrs.element(vertexId).toVar();\n const localPosition: Node = bitcast(packedVertex.xyz, 'vec3');\n // Draw-distance fade: shrink toward the instance origin over the last DRAW_DISTANCE_FADE of the distance.\n // Distance from the main camera (context.viewMatrix), also in the shadow pass, so shadows fade with it.\n const maxDrawDistance = levers.x;\n const origin = columns[3].xyz;\n const originDistance = length((ctx.viewMatrix as Node).mul(vec4(origin, 1)).xyz);\n const fade = maxDrawDistance.sub(originDistance).div(maxDrawDistance.mul(DRAW_DISTANCE_FADE)).clamp(0, 1);\n const worldPosition = origin.add(model.mul(vec4(localPosition, 0)).xyz.mul(fade));\n const worldNormal = normalize(model.mul(vec4(decodeOctNormal(packedVertex.w), 0)).xyz);\n normalLocal.assign(worldNormal);\n vgWorldNormal.assign(worldNormal);\n\n vgMeshletVarying.assign(float(meshletId));\n vgLodVarying.assign(float(meshletInfo.z));\n vgInstanceVarying.assign(float(instanceId));\n vgTintVarying.assign(tintAndSlot.xyz.mul(unpackRgba8(attrs.x).xyz));\n vgUv.assign((unpackUnorm2x16(attrs.y) as Node).mul(uvPacking.xy).add(uvPacking.zw));\n return worldPosition;\n })();\n }\n\n /** Stats of the last computed cut, from a readback of the counters buffer. */\n async readCounters(renderer: THREE.WebGPURenderer) {\n const words = new Uint32Array(await renderer.getArrayBufferAsync(this.countersAttribute));\n const slots = this.meshSlotCapacity;\n const cut = (c: number) => ({\n selected: words[2 + c * CUT_COUNTERS + C_SELECTED],\n drawn: words[2 + c * CUT_COUNTERS + C_DRAWN],\n survived: words[2 + c * CUT_COUNTERS + C_SURVIVED],\n requestedTriangles: words[2 + c * CUT_COUNTERS + C_REQUESTED] / 3,\n });\n const perMesh = (c: number, slot: number) => words[PER_MESH_COUNTERS + (c * slots + slot) * 2] / 3;\n return { camera: cut(0), shadow: cut(1), occluded: words[1], perMesh };\n }\n\n /** Byte offset of a mesh's draw args for a cut (0: camera, 1: shadow) in `drawArgsAttribute`. */\n drawArgsOffset(cut: number, slot: number) {\n return (cut * this.meshSlotCapacity + slot) * 20;\n }\n\n dispose() {\n for (const node of this.computeNodes) node.dispose();\n this.computeNodes = [];\n }\n}\n\n/**\n * World-space bounding sphere of the instance whose column-major matrix starts at `base`, computed the same way\n * the instance pass does: center = model * sphere center, radius = sphere radius * max column length.\n */\nexport function instanceSphere(m: ArrayLike<number>, base: number, sphere: number[], out: Float64Array) {\n const [sx, sy, sz, sr] = sphere;\n out[0] = m[base] * sx + m[base + 4] * sy + m[base + 8] * sz + m[base + 12];\n out[1] = m[base + 1] * sx + m[base + 5] * sy + m[base + 9] * sz + m[base + 13];\n out[2] = m[base + 2] * sx + m[base + 6] * sy + m[base + 10] * sz + m[base + 14];\n const c0 = Math.hypot(m[base], m[base + 1], m[base + 2]);\n const c1 = Math.hypot(m[base + 4], m[base + 5], m[base + 6]);\n const c2 = Math.hypot(m[base + 8], m[base + 9], m[base + 10]);\n out[3] = sr * Math.max(c0, c1, c2);\n}\n\n/** Octahedral normal (two snorm16 in one u32) -> unit vector. */\nfunction decodeOctNormal(packed: Node): Node {\n const bits: Node = bitcast(packed, 'int');\n const u = float(bits.shiftLeft(16).shiftRight(16)).div(32767);\n const v = float(bits.shiftRight(16)).div(32767);\n const z = float(1).sub(u.abs()).sub(v.abs());\n const t = maxNode(z.negate(), 0);\n const x = u.add(select(u.greaterThanEqual(0), t.negate(), t));\n const y = v.add(select(v.greaterThanEqual(0), t.negate(), t));\n return normalize(vec3(x, y, z));\n}\n\nfunction unpackRgba8(packed: Node): Node {\n return vec4(float(packed.bitAnd(255)), float(packed.shiftRight(8).bitAnd(255)), float(packed.shiftRight(16).bitAnd(255)), float(packed.shiftRight(24))).div(255);\n}\n\nexport function encodeOctNormal(nx: number, ny: number, nz: number): number {\n const l1 = Math.abs(nx) + Math.abs(ny) + Math.abs(nz) || 1;\n let u = nx / l1;\n let v = ny / l1;\n if (nz < 0) {\n const pu = (1 - Math.abs(v)) * (u >= 0 ? 1 : -1);\n const pv = (1 - Math.abs(u)) * (v >= 0 ? 1 : -1);\n u = pu;\n v = pv;\n }\n const su = Math.round(Math.max(-1, Math.min(1, u)) * 32767) & 0xffff;\n const sv = Math.round(Math.max(-1, Math.min(1, v)) * 32767) & 0xffff;\n return (su | (sv << 16)) >>> 0;\n}\n\n/** xyz as float bits + octahedral-encoded normal, 4 x u32 per vertex. */\nexport function packVertices(positions: Float32Array, normals: Float32Array): Uint32Array {\n const count = positions.length / 3;\n const out = new Uint32Array(count * 4);\n const asFloat = new Float32Array(out.buffer);\n for (let i = 0; i < count; i++) {\n asFloat[i * 4 + 0] = positions[i * 3 + 0];\n asFloat[i * 4 + 1] = positions[i * 3 + 1];\n asFloat[i * 4 + 2] = positions[i * 3 + 2];\n out[i * 4 + 3] = encodeOctNormal(normals[i * 3], normals[i * 3 + 1], normals[i * 3 + 2]);\n }\n return out;\n}\n\n/**\n * uv per vertex as two unorm16 in one u32, quantized over the bounds of all UVs (also tiling UVs outside 0..1).\n * Decode: unpackUnorm2x16(packed) * scale + offset. One step is 1/65535 of the range: well below a texel of a 4K\n * texture for 0..1 UVs.\n */\nexport function packUvs(uvs: Float32Array): { packed: Uint32Array; scale: [number, number]; offset: [number, number] } {\n const count = uvs.length / 2;\n const lo = [Infinity, Infinity];\n const hi = [-Infinity, -Infinity];\n for (let i = 0; i < uvs.length; i++) {\n const k = i & 1;\n if (uvs[i] < lo[k]) lo[k] = uvs[i];\n if (uvs[i] > hi[k]) hi[k] = uvs[i];\n }\n if (count === 0) lo[0] = lo[1] = hi[0] = hi[1] = 0;\n const scale: [number, number] = [hi[0] - lo[0] || 1, hi[1] - lo[1] || 1];\n const packed = new Uint32Array(count);\n const q = (v: number, k: number) => Math.round(Math.max(0, Math.min(1, (v - lo[k]) / scale[k])) * 65535);\n for (let i = 0; i < count; i++) packed[i] = (q(uvs[i * 2], 0) | (q(uvs[i * 2 + 1], 1) << 16)) >>> 0;\n return { packed, scale, offset: [lo[0], lo[1]] };\n}\n\n/** Spread the low 10 bits of v so that two zero bits sit between consecutive ones. */\nfunction spreadBits10(v: number): number {\n v &= 0x3ff;\n v = (v | (v << 16)) & 0x030000ff;\n v = (v | (v << 8)) & 0x0300f00f;\n v = (v | (v << 4)) & 0x030c30c3;\n v = (v | (v << 2)) & 0x09249249;\n return v;\n}\n\n/**\n * Instance indices sorted along a 30-bit Morton curve over the instance centers, so that consecutive slots are\n * spatially close and a fixed-size run of slots forms a compact cell.\n */\nexport function mortonOrder(matrices: Float32Array, sphere: number[]): Uint32Array {\n const n = matrices.length / 16;\n const s = new Float64Array(4);\n const centers = new Float64Array(n * 3);\n const lo = [Infinity, Infinity, Infinity];\n const hi = [-Infinity, -Infinity, -Infinity];\n for (let i = 0; i < n; i++) {\n instanceSphere(matrices, i * 16, sphere, s);\n for (let a = 0; a < 3; a++) {\n centers[i * 3 + a] = s[a];\n lo[a] = Math.min(lo[a], s[a]);\n hi[a] = Math.max(hi[a], s[a]);\n }\n }\n const extent = Math.max(hi[0] - lo[0], hi[1] - lo[1], hi[2] - lo[2], 1e-9);\n const codes = new Uint32Array(n);\n for (let i = 0; i < n; i++) {\n const q = (a: number) => Math.min(1023, Math.max(0, Math.floor(((centers[i * 3 + a] - lo[a]) / extent) * 1024)));\n codes[i] = (spreadBits10(q(0)) | (spreadBits10(q(1)) << 1) | (spreadBits10(q(2)) << 2)) >>> 0;\n }\n return radixOrder(codes);\n}\n\n/**\n * Indices sorted by 30-bit key: LSD radix sort, two passes of 15 bits. O(n), and stable, so equal keys keep index\n * order (same result as a stable comparison sort). Millions of instances sort in tens of milliseconds.\n */\nfunction radixOrder(keys: Uint32Array): Uint32Array {\n const n = keys.length;\n let order = Uint32Array.from({ length: n }, (_, i) => i);\n let next = new Uint32Array(n);\n const counts = new Uint32Array(1 << 15);\n for (const shift of [0, 15]) {\n counts.fill(0);\n for (let i = 0; i < n; i++) counts[(keys[i] >>> shift) & 0x7fff]++;\n let sum = 0;\n for (let b = 0; b < counts.length; b++) {\n const c = counts[b];\n counts[b] = sum;\n sum += c;\n }\n for (let i = 0; i < n; i++) {\n const index = order[i];\n next[counts[(keys[index] >>> shift) & 0x7fff]++] = index;\n }\n [order, next] = [next, order];\n }\n return order;\n}\n","/**\n * A renderable set of instances of one preprocessed mesh (a three.js Mesh, so it goes into any scene).\n *\n * The geometry and instances live in a GeometryPool shared with other meshes; the pool's compute passes select\n * the cut for all of its meshes at once (see GeometryPool). This object holds the material and two geometries,\n * the camera cut and the shadow cut, which draw this mesh's region of the pool's index buffers.\n */\nimport * as THREE from 'three/webgpu';\nimport { cameraViewMatrix, faceDirection, hash, materialColor, normalize, select, vec3, vec4 } from 'three/tsl';\nimport { VG_DEBUG_MODES } from '../constants';\nimport type { VirtualMeshData } from '../preprocess/buildVirtualMesh';\nimport type { VirtualGeometry } from './VirtualGeometry';\nimport {\n CELL_SIZE,\n NO_DRAW_DISTANCE,\n mortonOrder,\n vgInstanceVarying,\n vgLodVarying,\n vgMeshletVarying,\n vgTintVarying,\n vgWorldNormal,\n type GeometryPool,\n type PoolEntry,\n} from './GeometryPool';\nimport { bindVirtualGeometryTextures } from './vgMaterial';\n\nexport { vgWorldNormal, encodeOctNormal, packVertices, packUvs } from './GeometryPool';\n\nexport interface VirtualMeshInstances {\n /** 16 floats (column-major Matrix4) per instance. */\n matrices: Float32Array;\n /** Optional rgba tint per instance (multiplied with the material color). */\n colors?: Float32Array;\n}\n\nexport interface VirtualMeshOptions {\n /**\n * Cull distance in world units: instances farther than this are not drawn (and cost almost nothing, since\n * whole cells are rejected at once). They shrink to nothing over the last 15% of the distance, so there is\n * no visible pop. Default: Infinity. Can be changed later via `mesh.maxDrawDistance`.\n */\n maxDrawDistance?: number;\n /**\n * Hide instances whose bounding sphere is smaller than this many pixels (radius) on screen. Combined with\n * `VirtualGeometry.minPixelRadius` (the larger one wins). Default: 0. Also settable via `mesh.minPixelRadius`.\n */\n minPixelRadius?: number;\n /** @deprecated Draw capacity is shared per pool now: see `VirtualGeometryOptions`. Ignored. */\n maxDrawnMeshlets?: number;\n /** @deprecated Draw capacity is shared per pool now: see `VirtualGeometryOptions`. Ignored. */\n maxDrawnTriangles?: number;\n}\n\ntype Node = any; // TSL node typings are too strict for the graph code below; runtime is verified in the browser\n\n/**\n * Untouched copy of every material a VirtualMesh has taken over. A mesh rewires its material's nodes, so two\n * meshes cannot share one material object: the second one gets a clone of the original instead, as if the caller\n * had passed separate materials.\n */\nconst pristineMaterials = new WeakMap<THREE.NodeMaterial, THREE.NodeMaterial>();\n\nfunction claimMaterial(material: THREE.NodeMaterial): THREE.NodeMaterial {\n const pristine = pristineMaterials.get(material);\n if (pristine) return pristine.clone();\n pristineMaterials.set(material, material.clone());\n return material;\n}\n\nfunction placeholderGeometry() {\n const geometry = new THREE.BufferGeometry();\n // Placeholder attributes; real vertex data is pulled from storage buffers in the vertex shader.\n geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(3), 3));\n geometry.setAttribute('normal', new THREE.BufferAttribute(new Float32Array(3), 3));\n return geometry;\n}\n\nexport class VirtualMesh extends THREE.Mesh<THREE.BufferGeometry, THREE.NodeMaterial> {\n readonly isVirtualMesh = true;\n readonly data: VirtualMeshData;\n readonly instanceCount: number;\n readonly fullDetailTriangles: number;\n /** The pool holding this mesh's geometry and instances, and its record there. Set by `VirtualGeometry`. */\n pool!: GeometryPool;\n entry!: PoolEntry;\n /** Geometries drawing this mesh's region of the pool's camera and shadow index buffers. */\n readonly cameraGeometry = placeholderGeometry();\n readonly shadowGeometry = placeholderGeometry();\n /** `context.frameCount` of the last shadow-map render of this mesh. */\n lastShadowFrame = 0;\n /**\n * Lever: draw this mesh into the occlusion depth pass, so it can hide other geometry. Default: solid\n * materials (opaque, single-sided, no alpha test). Foliage is mostly holes, so it only gets tested.\n */\n occluder: boolean;\n /** Lever: let occlusion culling remove hidden instances and meshlets of this mesh. */\n occlusionCulling = true;\n /** GPU instance slot of each caller instance (inverse of the Morton order). */\n readonly gpuIndexOf: Uint32Array;\n /** Morton order: caller instance of each GPU slot. */\n readonly gpuToInput: Uint32Array;\n private readonly dirtyCells = new Set<number>();\n private drawingShadow = false;\n private poolVersion = -1;\n private readonly context: VirtualGeometry;\n\n /** Cull distance in world units (Infinity: never). See `VirtualMeshOptions.maxDrawDistance`. */\n get maxDrawDistance() {\n const d = this.pool.readFlag(this.entry, 'maxDrawDistance');\n return d >= NO_DRAW_DISTANCE ? Infinity : d;\n }\n set maxDrawDistance(distance: number) {\n this.pool.writeFlags(this.entry, { maxDrawDistance: Number.isFinite(distance) ? Math.max(0, distance) : NO_DRAW_DISTANCE });\n }\n\n /** Per-mesh minimum on-screen radius in pixels. See `VirtualMeshOptions.minPixelRadius`. */\n get minPixelRadius() {\n return this.pool.readFlag(this.entry, 'minPixelRadius');\n }\n set minPixelRadius(pixels: number) {\n this.pool.writeFlags(this.entry, { minPixelRadius: Math.max(0, pixels) });\n }\n\n /** The pool's per-frame draw capacity (shared by every mesh of the pool). */\n get capacity() {\n return { meshlets: this.pool.capacity.meshlets, triangles: this.pool.capacity.triangles };\n }\n\n constructor(context: VirtualGeometry, data: VirtualMeshData, material: THREE.NodeMaterial, instances: VirtualMeshInstances, options: VirtualMeshOptions = {}) {\n material = claimMaterial(material);\n const geometry = placeholderGeometry();\n super(geometry, material);\n this.context = context;\n this.data = data;\n this.frustumCulled = false; // culling happens on the GPU\n this.instanceCount = instances.matrices.length / 16;\n this.fullDetailTriangles = data.stats.leafTriangles * this.instanceCount;\n this.occluder = material.side !== THREE.DoubleSide && !material.transparent && material.alphaTest === 0 && !material.alphaHash;\n\n // The pool stores the instances in Morton order, so each cell is a contiguous range of slots.\n this.gpuToInput = mortonOrder(instances.matrices, data.boundingSphere);\n this.gpuIndexOf = new Uint32Array(this.instanceCount);\n for (let g = 0; g < this.instanceCount; g++) this.gpuIndexOf[this.gpuToInput[g]] = g;\n context.register(this, instances);\n if (options.maxDrawDistance !== undefined) this.maxDrawDistance = options.maxDrawDistance;\n if (options.minPixelRadius !== undefined) this.minPixelRadius = options.minPixelRadius;\n\n // Material: textures sample the pulled UVs, per-instance tint, debug views. The position node comes from\n // the pool (set in syncPool, again whenever the pool rebuilds its buffers).\n bindVirtualGeometryTextures(material);\n const base = vec4(material.colorNode ?? (materialColor as Node)).toVar() as Node;\n const randomColor = (seed: Node) => vec3(hash(seed), hash(seed.add(17.17)), hash(seed.add(43.43)));\n const debugColor = select(\n context.debugMode.equal(VG_DEBUG_MODES.meshlets),\n randomColor(vgMeshletVarying.add(vgInstanceVarying.mul(0.618))),\n select(context.debugMode.equal(VG_DEBUG_MODES.lodLevel), randomColor(vgLodVarying.add(3)), randomColor(vgInstanceVarying))\n );\n // Alpha passes through, so alpha-tested and transparent materials (and their shadows) keep working.\n material.colorNode = vec4(select(context.debugMode.equal(VG_DEBUG_MODES.shaded), base.xyz.mul(vgTintVarying), debugColor), base.w);\n // Two-sided foliage: back faces must light with the outward normal (normalNode is in view space).\n if (material.side === THREE.DoubleSide && !material.normalNode) {\n material.normalNode = normalize((cameraViewMatrix as Node).mul(vec4(vgWorldNormal, 0)).xyz.mul(faceDirection as Node));\n }\n this.syncPool();\n this.geometry = this.cameraGeometry;\n geometry.dispose();\n\n // The shadow pass calls onBeforeShadow and then onBeforeRender for each caster; the camera pass only\n // onBeforeRender. Each pass keeps its own render object and picks up `geometry` at draw time, so swapping\n // it here makes the shadow pass draw the shadow cut and the camera pass the camera cut.\n this.onBeforeShadow = (_renderer: unknown, _object: unknown, _camera: unknown, shadowCamera: THREE.Camera) => {\n this.lastShadowFrame = context.frameCount;\n context.noteShadowCamera(shadowCamera);\n this.drawingShadow = true;\n this.geometry = this.shadowGeometry;\n };\n // context.register() installed the auto-update hook as onBeforeRender: keep calling it after the swap.\n const autoUpdateHook = this.onBeforeRender;\n this.onBeforeRender = (...args: Parameters<THREE.Object3D['onBeforeRender']>) => {\n if (this.drawingShadow) this.drawingShadow = false;\n else this.geometry = this.cameraGeometry;\n autoUpdateHook.apply(this, args);\n };\n }\n\n /** Points the geometries and the material at the pool's current buffers and nodes (after a pool rebuild). */\n syncPool() {\n const pool = this.pool;\n if (this.poolVersion === pool.version || !pool.positionNode) return;\n this.poolVersion = pool.version;\n this.cameraGeometry.setIndex(pool.cameraIndex as unknown as THREE.BufferAttribute);\n this.cameraGeometry.setIndirect(pool.drawArgsAttribute, pool.drawArgsOffset(0, this.entry.slot));\n this.shadowGeometry.setIndex(pool.shadowIndex as unknown as THREE.BufferAttribute);\n this.shadowGeometry.setIndirect(pool.drawArgsAttribute, pool.drawArgsOffset(1, this.entry.slot));\n this.material.positionNode = pool.positionNode;\n this.material.needsUpdate = true;\n }\n\n /** Force the next `VirtualGeometry.update` to recompute the cut. */\n markCutDirty() {\n this.pool.dirty = true;\n }\n\n /** Update one instance transform. Call `commitInstances()` after a batch of changes. */\n setMatrixAt(index: number, matrix: THREE.Matrix4) {\n const slot = this.gpuIndexOf[index];\n this.pool.setMatrix(this.entry, slot, matrix);\n this.dirtyCells.add(Math.floor(slot / CELL_SIZE));\n }\n\n commitInstances() {\n this.pool.commitInstances(this.entry, this.dirtyCells);\n this.dirtyCells.clear();\n }\n\n /**\n * Stop rendering this mesh and drop it from its context. The GPU buffers are released when the\n * renderer frees them; call this before removing the object from the scene for good.\n */\n dispose(context?: VirtualGeometry) {\n this.visible = false;\n (context ?? this.context).unregister(this);\n this.removeFromParent();\n }\n\n /** Triangles drawn for this mesh by the last computed cut (camera and shadow), from one readback. */\n async readStats(renderer: THREE.WebGPURenderer) {\n const c = await this.pool.readCounters(renderer);\n return { drawnTriangles: c.perMesh(0, this.entry.slot), shadowTriangles: c.perMesh(1, this.entry.slot) };\n }\n}\n","import * as THREE from 'three/webgpu';\n\ntype MaterialClass = new () => THREE.Material;\n\n/** Classic mesh material type -> [classic class (whose copy() knows every property), node material class]. */\nconst CONVERSIONS: Record<string, [MaterialClass, new () => THREE.NodeMaterial]> = {\n MeshPhysicalMaterial: [THREE.MeshPhysicalMaterial, THREE.MeshPhysicalNodeMaterial],\n MeshStandardMaterial: [THREE.MeshStandardMaterial, THREE.MeshStandardNodeMaterial],\n MeshPhongMaterial: [THREE.MeshPhongMaterial, THREE.MeshPhongNodeMaterial],\n MeshLambertMaterial: [THREE.MeshLambertMaterial, THREE.MeshLambertNodeMaterial],\n MeshBasicMaterial: [THREE.MeshBasicMaterial, THREE.MeshBasicNodeMaterial],\n MeshToonMaterial: [THREE.MeshToonMaterial, THREE.MeshToonNodeMaterial],\n MeshMatcapMaterial: [THREE.MeshMatcapMaterial, THREE.MeshMatcapNodeMaterial],\n MeshNormalMaterial: [THREE.MeshNormalMaterial, THREE.MeshNormalNodeMaterial],\n};\n\n/** Subclasses keep their parent's flags: check the most derived first. */\nconst FLAGS: [string, string][] = [\n ['isMeshPhysicalMaterial', 'MeshPhysicalMaterial'],\n ['isMeshStandardMaterial', 'MeshStandardMaterial'],\n ['isMeshPhongMaterial', 'MeshPhongMaterial'],\n ['isMeshLambertMaterial', 'MeshLambertMaterial'],\n ['isMeshBasicMaterial', 'MeshBasicMaterial'],\n ['isMeshToonMaterial', 'MeshToonMaterial'],\n ['isMeshMatcapMaterial', 'MeshMatcapMaterial'],\n ['isMeshNormalMaterial', 'MeshNormalMaterial'],\n];\n\nfunction conversionOf(material: THREE.Material) {\n const flags = material as unknown as Record<string, unknown>;\n const type = CONVERSIONS[material.type] ? material.type : FLAGS.find(([flag]) => flags[flag] === true)?.[1];\n return type ? CONVERSIONS[type] : null;\n}\n\n/** True when `toNodeMaterial` can convert the material (node materials, and the classic mesh materials). */\nexport function canConvertToNodeMaterial(material: THREE.Material): boolean {\n return (material as THREE.NodeMaterial).isNodeMaterial === true || conversionOf(material) !== null;\n}\n\n/**\n * The node-material equivalent of a classic mesh material: MeshStandardMaterial -> MeshStandardNodeMaterial,\n * and likewise for Physical, Phong, Lambert, Basic, Toon, Matcap and Normal. Every property is copied (colors,\n * maps and their texture objects, transparency, alphaTest, side, blending, userData, ...). Node materials are\n * returned as they are; materials without a node equivalent (ShaderMaterial, ...) return null.\n */\nexport function toNodeMaterial(material: THREE.Material): THREE.NodeMaterial | null {\n if ((material as THREE.NodeMaterial).isNodeMaterial) return material as THREE.NodeMaterial;\n const conversion = conversionOf(material);\n if (!conversion) return null;\n const [Classic, Node] = conversion;\n const result = new Node();\n const defines = (result as unknown as { defines?: unknown }).defines;\n // The classic copy() lists every property of its material type; the node material has the same ones.\n (Classic.prototype.copy as (this: THREE.Material, source: THREE.Material) => THREE.Material).call(result, material);\n (result as unknown as { defines?: unknown }).defines = defines;\n return result;\n}\n","import * as THREE from 'three/webgpu';\nimport type { VirtualMeshSource } from './core/preprocess/buildVirtualMesh';\n\ntype Attribute = THREE.BufferAttribute | THREE.InterleavedBufferAttribute;\n\nexport interface FromGeometryOptions {\n /**\n * Keep the `uv` attribute. Vertices are then welded by position and UV, so UV seams stay separate vertices\n * (the simplifier treats them as seams, not borders). Default: true when the geometry has a `uv` attribute.\n */\n uvs?: boolean;\n /** Keep the `color` attribute as per-vertex colors (multiplied with the material color). Default: false. */\n colors?: boolean;\n /**\n * 'compute' (default): smooth normals over the position-welded mesh, ignoring the `normal` attribute.\n * 'keep': use the geometry's normals; vertices with different normals stay separate, so hard edges stay hard.\n */\n normals?: 'compute' | 'keep';\n /** Only this range of the index buffer (or of the vertices, for non-indexed geometry), e.g. one of `geometry.groups`. */\n range?: { start: number; count: number };\n}\n\n/** Weld tolerance per channel: positions and UVs need to match almost exactly, normals and colors a little less. */\nconst POSITION_TOLERANCE = 1e-6;\nconst ATTRIBUTE_TOLERANCE = 1e-4;\n\n/**\n * Weld vertices and produce a `VirtualMeshSource`. By default vertices are welded by position (and UV when the\n * geometry has UVs) and get smooth normals, so meshlets share edges. See `FromGeometryOptions`.\n */\nexport function fromBufferGeometry(geometry: THREE.BufferGeometry, options: FromGeometryOptions = {}): VirtualMeshSource {\n const position = geometry.attributes.position as Attribute;\n const uv = (options.uvs ?? true) ? (geometry.attributes.uv as Attribute | undefined) : undefined;\n const color = options.colors ? (geometry.attributes.color as Attribute | undefined) : undefined;\n const normal = options.normals === 'keep' ? (geometry.attributes.normal as Attribute | undefined) : undefined;\n const index = geometry.index;\n const total = index ? index.count : position.count;\n const start = Math.max(0, Math.min(total, options.range?.start ?? 0));\n const count = Math.floor((Math.min(total, start + (options.range?.count ?? total)) - start) / 3) * 3;\n const vertexOf = (corner: number) => (index ? index.getX(start + corner) : start + corner);\n\n // Position-only weld: the topology smooth normals are computed on (and the whole result when nothing else is kept).\n const byPosition = weld(count, vertexOf, [{ attribute: position, size: 3, tolerance: POSITION_TOLERANCE }]);\n const positions = gather(byPosition.firstVertex, position, 3);\n let smoothNormals: Float32Array | null = null;\n if (!normal) {\n const g = new THREE.BufferGeometry();\n g.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n g.setIndex(new THREE.BufferAttribute(byPosition.indices, 1));\n g.computeVertexNormals();\n smoothNormals = g.attributes.normal.array as Float32Array;\n }\n if (!uv && !color && !normal) return { positions, normals: smoothNormals!, indices: byPosition.indices };\n\n // Full weld: vertices that differ in any kept attribute stay separate (seams).\n const channels = [{ attribute: position, size: 3, tolerance: POSITION_TOLERANCE }];\n if (uv) channels.push({ attribute: uv, size: 2, tolerance: POSITION_TOLERANCE });\n if (normal) channels.push({ attribute: normal, size: 3, tolerance: ATTRIBUTE_TOLERANCE });\n if (color) channels.push({ attribute: color, size: 3, tolerance: ATTRIBUTE_TOLERANCE });\n const full = weld(count, vertexOf, channels);\n const result: VirtualMeshSource = { positions: gather(full.firstVertex, position, 3), normals: new Float32Array(0), indices: full.indices };\n if (normal) {\n result.normals = gather(full.firstVertex, normal, 3);\n for (let i = 0; i < result.normals.length; i += 3) {\n const l = Math.hypot(result.normals[i], result.normals[i + 1], result.normals[i + 2]) || 1;\n result.normals[i] /= l;\n result.normals[i + 1] /= l;\n result.normals[i + 2] /= l;\n }\n } else {\n // Every seam copy of a vertex gets the smooth normal of its position.\n result.normals = new Float32Array(full.firstVertex.length * 3);\n for (let w = 0; w < full.firstVertex.length; w++) {\n const p = byPosition.indices[full.firstCorner[w]];\n result.normals.set(smoothNormals!.subarray(p * 3, p * 3 + 3), w * 3);\n }\n }\n if (uv) result.uvs = gather(full.firstVertex, uv, 2);\n if (color) result.colors = gather(full.firstVertex, color, 3);\n return result;\n}\n\nfunction gather(vertices: Uint32Array, attribute: Attribute, size: number): Float32Array {\n const out = new Float32Array(vertices.length * size);\n for (let i = 0; i < vertices.length; i++) {\n for (let k = 0; k < size; k++) out[i * size + k] = attribute.getComponent(vertices[i], k);\n }\n return out;\n}\n\n/**\n * Same result as three's `mergeVertices` on the given channels (same quantization, vertices in first-use\n * order), but with an open-addressing hash table on the quantized values instead of string keys: about 10x\n * faster on million-triangle meshes. Returns, per welded vertex, the source vertex and corner that created it.\n */\nfunction weld(\n count: number,\n vertexOf: (corner: number) => number,\n channels: { attribute: Attribute; size: number; tolerance: number }[]\n) {\n const width = channels.reduce((a, c) => a + c.size, 0);\n const quantize = channels.map(({ tolerance }) => {\n const multiplier = Math.pow(10, Math.log10(1 / tolerance));\n return { multiplier, additive: tolerance * 0.5 * multiplier };\n });\n let size = 1;\n while (size < count * 2) size <<= 1;\n const mask = size - 1;\n const table = new Int32Array(size).fill(-1); // slot -> welded vertex\n const keys = new Float64Array(count * width); // quantized values per welded vertex (exact integers)\n const key = new Float64Array(width);\n const firstVertex = new Uint32Array(count);\n const firstCorner = new Uint32Array(count);\n const indices = new Uint32Array(count);\n let welded = 0;\n for (let i = 0; i < count; i++) {\n const v = vertexOf(i);\n let h = 0;\n let o = 0;\n for (let c = 0; c < channels.length; c++) {\n const { attribute, size: n } = channels[c];\n const { multiplier, additive } = quantize[c];\n for (let k = 0; k < n; k++, o++) {\n key[o] = Math.trunc(attribute.getComponent(v, k) * multiplier + additive);\n h = (h ^ Math.imul(key[o] | 0, HASH_PRIMES[o % HASH_PRIMES.length])) | 0;\n }\n }\n h &= mask;\n for (;;) {\n const w = table[h];\n if (w < 0) {\n table[h] = welded;\n keys.set(key, welded * width);\n firstVertex[welded] = v;\n firstCorner[welded] = i;\n indices[i] = welded++;\n break;\n }\n let same = true;\n for (let k = 0; k < width && same; k++) same = keys[w * width + k] === key[k];\n if (same) {\n indices[i] = w;\n break;\n }\n h = (h + 1) & mask;\n }\n }\n return { indices, firstVertex: firstVertex.slice(0, welded), firstCorner: firstCorner.slice(0, welded) };\n}\n\nconst HASH_PRIMES = [73856093, 19349663, 83492791, 2654435761, 2246822519, 3266489917, 668265263, 374761393, 1181783497, 3735928559, 2028178513];\n\n/**\n * Concatenate several already-welded meshes into one source mesh with per-vertex colors.\n * Each part uses its own `colors` if present, otherwise the given flat `color`.\n */\nexport function mergeSources(parts: { mesh: VirtualMeshSource; color?: THREE.ColorRepresentation }[]): VirtualMeshSource {\n const vertexCount = parts.reduce((a, p) => a + p.mesh.positions.length / 3, 0);\n const indexCount = parts.reduce((a, p) => a + p.mesh.indices.length, 0);\n const positions = new Float32Array(vertexCount * 3);\n const normals = new Float32Array(vertexCount * 3);\n const colors = new Float32Array(vertexCount * 3);\n const uvs = parts.some((p) => p.mesh.uvs) ? new Float32Array(vertexCount * 2) : null;\n const indices = new Uint32Array(indexCount);\n const c = new THREE.Color();\n let v = 0;\n let i = 0;\n for (const { mesh, color = 0xffffff } of parts) {\n const n = mesh.positions.length / 3;\n positions.set(mesh.positions, v * 3);\n normals.set(mesh.normals, v * 3);\n if (uvs && mesh.uvs) uvs.set(mesh.uvs, v * 2);\n if (mesh.colors) colors.set(mesh.colors, v * 3);\n else {\n c.set(color);\n for (let k = 0; k < n; k++) colors.set([c.r, c.g, c.b], (v + k) * 3);\n }\n for (let k = 0; k < mesh.indices.length; k++) indices[i + k] = mesh.indices[k] + v;\n v += n;\n i += mesh.indices.length;\n }\n return uvs ? { positions, normals, colors, uvs, indices } : { positions, normals, colors, indices };\n}\n","/**\n * One-call scene import: every static mesh of an Object3D (e.g. a loaded glTF scene) becomes VirtualGeometry geometry.\n *\n * Meshes are grouped by (geometry, geometry group, material, render flags), so repeated geometry becomes one\n * VirtualMesh with one instance per occurrence (InstancedMesh instances included). Each unique geometry range\n * is built once. Skinned and morphing meshes, points, lines and sprites are left alone and keep rendering.\n */\nimport * as THREE from 'three/webgpu';\nimport { buildVirtualMeshCached } from '../io/cache';\nimport { buildVirtualMesh, type VirtualMeshBuildOptions, type VirtualMeshData, type VirtualMeshSource } from '../preprocess/buildVirtualMesh';\nimport { fromBufferGeometry } from '../../source';\nimport type { VirtualGeometry } from '../runtime/VirtualGeometry';\nimport type { VirtualMesh, VirtualMeshOptions } from '../runtime/VirtualMesh';\nimport { canConvertToNodeMaterial, toNodeMaterial } from './toNodeMaterial';\n\n/** Builds one DAG. Same signature as `buildVirtualMesh`, so a caching builder drops in here or via `options.builder`. */\nexport type VirtualGeometryBuilder = (source: VirtualMeshSource, options?: VirtualMeshBuildOptions) => Promise<VirtualMeshData>;\n// Cached in IndexedDB: importing the same model again (e.g. the next page load) skips the build.\nconst defaultBuilder: VirtualGeometryBuilder = buildVirtualMeshCached;\n\nexport interface VirtualGeometryImportOptions {\n /** DAG build options for every geometry (`onProgress` is driven by the import; use `onProgress` below). */\n build?: Omit<VirtualMeshBuildOptions, 'onProgress'>;\n /** Options for each created VirtualMesh (e.g. `maxDrawDistance`), or a function returning them per group. */\n mesh?: VirtualMeshOptions | ((group: VirtualGeometryImportGroup) => VirtualMeshOptions | undefined);\n /** Return false to leave a mesh as it is (it keeps rendering normally). Called for every compatible mesh. */\n filter?: (mesh: THREE.Mesh) => boolean;\n /**\n * true (default): the VirtualMeshes are added to `object` and the converted meshes stop rendering (their\n * leaf meshes are taken out of the graph, meshes with children stay with their layers cleared; `dispose()`\n * restores both). false: nothing in the scene changes; add `result.object` yourself.\n */\n replace?: boolean;\n /** Overall progress in 0..1 while building. May be async (awaited), e.g. to let the page repaint. */\n onProgress?: (fraction: number) => void | Promise<void>;\n /** Converts a source material. Default: node materials are cloned, classic mesh materials go through `toNodeMaterial`. */\n material?: (material: THREE.Material, group: VirtualGeometryImportGroup) => THREE.NodeMaterial | null;\n /** DAG builder (default `buildVirtualMesh`), e.g. a cached one with the same signature. */\n builder?: VirtualGeometryBuilder;\n}\n\n/** Meshes that share geometry, geometry range, material and render flags: one VirtualMesh. */\nexport interface VirtualGeometryImportGroup {\n geometry: THREE.BufferGeometry;\n /** Index range (vertex range for non-indexed geometry) this group draws: one entry of `geometry.groups`, clipped to the draw range. */\n range: { start: number; count: number };\n material: THREE.Material;\n /** Column-major world matrix per instance (16 floats each), in the order of `instances`. */\n matrices: Float32Array;\n /** rgba per instance, from `InstancedMesh.instanceColor` (null when no source has instance colors). */\n colors: Float32Array | null;\n /** Source of each instance: the mesh, and the instance index for an InstancedMesh (else -1). */\n instances: { object: THREE.Mesh; index: number }[];\n /** Per-vertex colors are used (`material.vertexColors` and a `color` attribute), like three would. */\n vertexColors: boolean;\n castShadow: boolean;\n receiveShadow: boolean;\n /** False when the mesh or one of its ancestors is hidden. */\n visible: boolean;\n renderOrder: number;\n layers: number;\n /** From the first source mesh. */\n name: string;\n userData: Record<string, unknown>;\n}\n\nconst converted = new WeakSet<THREE.Object3D>();\n\n/** Why a mesh is left alone, or null when it can be converted. */\nexport function incompatibility(mesh: THREE.Object3D): string | null {\n const m = mesh as THREE.Mesh & { isSkinnedMesh?: boolean; isBatchedMesh?: boolean; isVirtualMesh?: boolean };\n if (!m.isMesh) return 'not a mesh';\n if (m.isVirtualMesh) return 'already a VirtualMesh';\n if (m.isSkinnedMesh) return 'skinned';\n if (m.isBatchedMesh) return 'batched';\n const geometry = m.geometry;\n if (!geometry?.attributes?.position || (geometry as THREE.InstancedBufferGeometry).isInstancedBufferGeometry) return 'unsupported geometry';\n const morph = geometry.morphAttributes;\n if ((morph.position?.length ?? 0) > 0 || (morph.normal?.length ?? 0) > 0 || (m.morphTargetInfluences?.length ?? 0) > 0) return 'morph targets';\n const materials = Array.isArray(m.material) ? m.material : [m.material];\n if (materials.some((mat) => !mat || !canConvertToNodeMaterial(mat))) return 'material without a node equivalent';\n return null;\n}\n\n/**\n * Collects the convertible meshes under `root` into instance groups (pure CPU work, no GPU, testable in Node).\n * World matrices are read after updating them, so the result matches what three would render now.\n */\nexport function collectVirtualGeometryGroups(root: THREE.Object3D, filter?: (mesh: THREE.Mesh) => boolean) {\n root.updateWorldMatrix(true, true);\n const groups = new Map<string, VirtualGeometryImportGroup & { matrixList: number[]; colorList: number[] | null }>();\n const meshes: THREE.Mesh[] = [];\n const skipped: { object: THREE.Object3D; reason: string }[] = [];\n const instanceMatrix = new THREE.Matrix4();\n const world = new THREE.Matrix4();\n const color = new THREE.Color();\n\n root.traverse((object) => {\n if (!(object as THREE.Mesh).isMesh || converted.has(object)) return;\n const mesh = object as THREE.Mesh;\n const reason = incompatibility(mesh) ?? (filter && !filter(mesh) ? 'filtered out' : null);\n if (reason) {\n skipped.push({ object: mesh, reason });\n return;\n }\n const geometry = mesh.geometry;\n const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];\n const drawn = drawnRanges(geometry, Array.isArray(mesh.material));\n if (drawn.length === 0) return;\n meshes.push(mesh);\n const instanced = (mesh as THREE.InstancedMesh).isInstancedMesh ? (mesh as THREE.InstancedMesh) : null;\n const count = instanced ? instanced.count : 1;\n const visible = isVisible(mesh);\n\n for (const { start, count: rangeCount, materialIndex } of drawn) {\n const material = materials[materialIndex];\n if (!material) continue;\n const vertexColors = material.vertexColors === true && geometry.attributes.color !== undefined;\n const key = [geometry.id, start, rangeCount, material.uuid, mesh.castShadow, mesh.receiveShadow, visible, mesh.renderOrder, mesh.layers.mask].join(':');\n let group = groups.get(key);\n if (!group) {\n group = {\n geometry,\n range: { start, count: rangeCount },\n material,\n matrices: new Float32Array(0),\n colors: null,\n instances: [],\n vertexColors,\n castShadow: mesh.castShadow,\n receiveShadow: mesh.receiveShadow,\n visible,\n renderOrder: mesh.renderOrder,\n layers: mesh.layers.mask,\n name: mesh.name,\n userData: { ...mesh.userData },\n matrixList: [],\n colorList: null,\n };\n groups.set(key, group);\n }\n for (let i = 0; i < count; i++) {\n if (instanced) {\n instanced.getMatrixAt(i, instanceMatrix);\n world.multiplyMatrices(mesh.matrixWorld, instanceMatrix);\n } else world.copy(mesh.matrixWorld);\n group.matrixList.push(...world.elements);\n const tinted = !!instanced?.instanceColor;\n if (tinted) instanced!.getColorAt(i, color);\n if (tinted && !group.colorList) group.colorList = new Array(group.instances.length * 4).fill(1);\n if (group.colorList) {\n if (tinted) group.colorList.push(color.r, color.g, color.b, 1);\n else group.colorList.push(1, 1, 1, 1);\n }\n group.instances.push({ object: mesh, index: instanced ? i : -1 });\n }\n }\n });\n\n const result: VirtualGeometryImportGroup[] = [];\n for (const { matrixList, colorList, ...group } of groups.values()) {\n group.matrices = Float32Array.from(matrixList);\n group.colors = colorList ? Float32Array.from(colorList) : null;\n result.push(group);\n }\n return { groups: result, meshes, skipped };\n}\n\n/** The (start, count, materialIndex) ranges three draws for this geometry, clipped to its draw range. */\nfunction drawnRanges(geometry: THREE.BufferGeometry, multiMaterial: boolean) {\n const total = geometry.index ? geometry.index.count : geometry.attributes.position.count;\n const drawStart = Math.max(0, geometry.drawRange.start);\n const drawEnd = Math.min(total, drawStart + geometry.drawRange.count);\n const ranges = multiMaterial ? geometry.groups : [{ start: 0, count: total, materialIndex: 0 }];\n const out: { start: number; count: number; materialIndex: number }[] = [];\n for (const g of ranges) {\n const start = Math.max(g.start, drawStart);\n const end = Math.min(g.start + g.count, drawEnd);\n if (end - start >= 3) out.push({ start, count: end - start, materialIndex: g.materialIndex ?? 0 });\n }\n return out;\n}\n\nfunction isVisible(object: THREE.Object3D) {\n for (let o: THREE.Object3D | null = object; o; o = o.parent) if (!o.visible) return false;\n return true;\n}\n\n/** Result of `VirtualGeometry.add()`: the created meshes, and how to undo the import. */\nexport class VirtualGeometryImport {\n /** Holds every created VirtualMesh. Added to the imported object unless `replace: false`. */\n readonly object = new THREE.Group();\n /** One VirtualMesh per entry of `groups`. */\n readonly meshes: VirtualMesh[] = [];\n groups: VirtualGeometryImportGroup[];\n /** Meshes that were left alone, and why. */\n readonly skipped: { object: THREE.Object3D; reason: string }[];\n readonly stats = { sourceMeshes: 0, instances: 0, uniqueGeometries: 0, buildMs: 0 };\n private readonly hidden = new Map<THREE.Object3D, number>();\n /** Converted leaf meshes taken out of the graph, with their former parent (restored by `dispose`). */\n private readonly detached = new Map<THREE.Object3D, THREE.Object3D>();\n\n constructor(\n private readonly context: VirtualGeometry,\n collected: ReturnType<typeof collectVirtualGeometryGroups>\n ) {\n this.object.name = 'VirtualGeometryImport';\n this.groups = collected.groups;\n this.skipped = collected.skipped;\n this.stats.sourceMeshes = collected.meshes.length;\n this.stats.instances = collected.groups.reduce((a, g) => a + g.instances.length, 0);\n }\n\n /** @internal Stops the given source meshes from rendering (restored by `dispose`). */\n hide(meshes: THREE.Mesh[], root: THREE.Object3D) {\n const emptied = new Set<THREE.Object3D>();\n for (const mesh of meshes) {\n converted.add(mesh);\n // Leaf meshes leave the graph: three.js would still traverse them every frame (matrix updates and\n // render-list projection), which costs more CPU than the rendering itself in scenes with thousands of\n // props. Meshes with children (lights, skinned parts, ...) stay, with their layers cleared.\n if (mesh.children.length === 0 && mesh.parent) {\n this.detached.set(mesh, mesh.parent);\n emptied.add(mesh.parent);\n mesh.parent.remove(mesh);\n continue;\n }\n if (!this.hidden.has(mesh)) this.hidden.set(mesh, mesh.layers.mask);\n mesh.layers.disableAll();\n }\n // Plain groups left empty (e.g. one root node per prop) go too, walking up, but never `root` itself.\n for (let node of emptied) {\n while (node !== root && node.children.length === 0 && node.parent && (node.type === 'Group' || node.type === 'Object3D')) {\n const parent: THREE.Object3D = node.parent;\n this.detached.set(node, parent);\n parent.remove(node);\n node = parent;\n }\n }\n }\n\n /** World matrix of a source object, also when it (or its ancestors) were taken out of the graph. */\n private worldMatrixOf(object: THREE.Object3D): THREE.Matrix4 {\n const parent = this.detached.get(object);\n if (!parent) {\n object.updateWorldMatrix(true, false);\n return object.matrixWorld;\n }\n object.updateMatrix();\n return object.matrixWorld.multiplyMatrices(this.worldMatrixOf(parent), object.matrix);\n }\n\n /**\n * Re-reads every source mesh's current world matrix into the instances (call after moving the imported\n * object or animating its nodes). Instances are baked in world space at import time otherwise.\n */\n syncTransforms() {\n const m = new THREE.Matrix4();\n const instanceMatrix = new THREE.Matrix4();\n const roots = new Set<THREE.Object3D>();\n this.groups.forEach((group, g) => {\n const mesh = this.meshes[g];\n group.instances.forEach(({ object, index }, i) => {\n if (!roots.has(object)) {\n this.worldMatrixOf(object);\n roots.add(object);\n }\n if (index >= 0) {\n (object as THREE.InstancedMesh).getMatrixAt(index, instanceMatrix);\n m.multiplyMatrices(object.matrixWorld, instanceMatrix);\n } else m.copy(object.matrixWorld);\n mesh.setMatrixAt(i, m);\n });\n mesh.commitInstances();\n });\n }\n\n /** Removes the VirtualMeshes and lets the source meshes render again. */\n dispose() {\n for (const mesh of this.meshes) {\n mesh.dispose(this.context);\n mesh.material.dispose();\n mesh.geometry.dispose();\n }\n this.meshes.length = 0;\n for (const [mesh, mask] of this.hidden) {\n mesh.layers.mask = mask;\n converted.delete(mesh);\n }\n this.hidden.clear();\n for (const [mesh, parent] of this.detached) {\n parent.add(mesh);\n converted.delete(mesh);\n }\n this.detached.clear();\n this.object.removeFromParent();\n }\n}\n\n/**\n * Converts every compatible mesh under `object` to VirtualGeometry geometry. See `VirtualGeometry.add`.\n */\nexport async function virtualMeshesFromObject3D(context: VirtualGeometry, object: THREE.Object3D, options: VirtualGeometryImportOptions = {}): Promise<VirtualGeometryImport> {\n const t0 = performance.now();\n const build = options.builder ?? defaultBuilder;\n const collected = collectVirtualGeometryGroups(object, options.filter);\n const result = new VirtualGeometryImport(context, collected);\n\n // One build per geometry range (and vertex color use): groups that differ only in material or flags share it.\n const sources = new Map<string, { group: VirtualGeometryImportGroup; triangles: number; data?: VirtualMeshData }>();\n const sourceKey = (g: VirtualGeometryImportGroup) => `${g.geometry.id}:${g.range.start}:${g.range.count}:${g.vertexColors}`;\n for (const group of result.groups) {\n const key = sourceKey(group);\n if (!sources.has(key)) sources.set(key, { group, triangles: group.range.count / 3 });\n }\n result.stats.uniqueGeometries = sources.size;\n const total = [...sources.values()].reduce((a, s) => a + s.triangles, 0) || 1;\n let done = 0;\n for (const source of sources.values()) {\n const { geometry, range, vertexColors } = source.group;\n const mesh = fromBufferGeometry(geometry, {\n range,\n colors: vertexColors,\n normals: geometry.attributes.normal ? 'keep' : 'compute',\n });\n source.data = await build(mesh, {\n ...options.build,\n onProgress: (f) => options.onProgress?.((done + f * source.triangles) / total),\n });\n done += source.triangles;\n }\n\n const materials = new Map<string, THREE.NodeMaterial | null>();\n const createdGroups: VirtualGeometryImportGroup[] = [];\n const failed = new Set<THREE.Object3D>();\n for (const group of result.groups) {\n const material = convertMaterial(group, options, materials);\n if (!material) {\n for (const { object: source } of group.instances) failed.add(source);\n continue;\n }\n const meshOptions = typeof options.mesh === 'function' ? options.mesh(group) : options.mesh;\n const mesh = context.createMesh(sources.get(sourceKey(group))!.data!, material, { matrices: group.matrices, colors: group.colors ?? undefined }, meshOptions);\n // Vertices are pulled in world space: the mesh itself must stay at identity wherever it is attached.\n mesh.matrixAutoUpdate = false;\n mesh.matrixWorldAutoUpdate = false;\n mesh.name = group.name;\n mesh.userData = { ...group.userData };\n mesh.castShadow = group.castShadow;\n mesh.receiveShadow = group.receiveShadow;\n mesh.visible = group.visible;\n mesh.renderOrder = group.renderOrder;\n mesh.layers.mask = group.layers;\n result.meshes.push(mesh);\n createdGroups.push(group);\n result.object.add(mesh);\n }\n result.groups = createdGroups;\n\n if (options.replace ?? true) {\n // A mesh with any part that could not be converted keeps rendering (its converted parts are drawn twice).\n result.hide(collected.meshes.filter((m) => !failed.has(m)), object);\n object.add(result.object);\n }\n await options.onProgress?.(1);\n result.stats.buildMs = performance.now() - t0;\n return result;\n}\n\n/**\n * Node material for a group. Node materials are cloned so the source mesh keeps its own (VirtualMesh rewires the\n * material it gets). glTF normal maps authored against tangents need the derivative-tangent sign (normalScale.y\n * flipped), which GLTFLoader only applies when the geometry has no tangents.\n */\nfunction convertMaterial(group: VirtualGeometryImportGroup, options: VirtualGeometryImportOptions, cache: Map<string, THREE.NodeMaterial | null>) {\n const source = group.material as THREE.MeshStandardMaterial;\n const flipNormalY = !!(source.normalMap && group.geometry.attributes.tangent && source.normalMap.flipY === false);\n const key = `${source.uuid}:${flipNormalY}`;\n if (cache.has(key)) return cache.get(key)!;\n let material: THREE.NodeMaterial | null;\n if (options.material) material = options.material(source, group);\n else {\n material = toNodeMaterial(source);\n if (material === (source as THREE.Material)) material = (source as unknown as THREE.NodeMaterial).clone();\n }\n if (material && flipNormalY) {\n const scale = (material as unknown as { normalScale?: THREE.Vector2 }).normalScale;\n if (scale) (material as unknown as { normalScale: THREE.Vector2 }).normalScale = scale.clone().setY(-scale.y);\n }\n cache.set(key, material);\n return material;\n}\n","/**\n * Occlusion culling against a hierarchical depth buffer (HZB), on by default.\n *\n * Per frame, before the cut is computed:\n * 1. occluder pass - the occluder meshes' previous-frame camera cuts (their index buffers still hold them)\n * are drawn depth-only with the CURRENT camera into a small depth target. That geometry was visible last\n * frame, so it is a subset of the real occluders.\n * 2. HZB build - mip 0 is that depth (copied into a storage buffer), each further mip is the MAX of its\n * 2x2 children: a texel only hides what lies behind all of its occluders.\n * 3. cull - an instance or meshlet sphere is dropped from the camera cut when its projected box, read at\n * the mip where it covers at most 2x2 texels, is entirely behind the max depth there.\n *\n * Why it is safe: removing occluders can only push the depth buffer back, so anything hidden by the subset\n * is hidden by the full scene. Stale or missing occluders cost efficiency, never correctness. The occluders\n * are LOD-simplified (they may bulge up to the error threshold in front of the true surface), so the tested\n * sphere is grown by that error first.\n *\n * Only meshes flagged `occluder` are drawn in step 1 (by default: opaque, single-sided, no alpha test, i.e.\n * solid geometry such as terrain, rocks, buildings; foliage is mostly holes). Every mesh is tested, unless\n * its `occlusionCulling` is off. Shadow cuts are never occlusion culled: a caster hidden from the camera can\n * still shadow something visible.\n *\n * Storage: the whole HZB (a header with each mip's offset and size, then all mips) is one storage buffer,\n * sized for `maxSize`, so nothing is reallocated on resize.\n */\nimport * as THREE from 'three/webgpu';\nimport { Fn, If, Return, ceil, clamp, exp2, float, floor, instanceIndex, int, ivec2, log2, max, min, select, storage, texture, uint, uniform, vec3, vec4 } from 'three/tsl';\nimport type { VirtualMesh } from './VirtualMesh';\n\n/** Upper bound on mip levels (maxSize up to 32768). */\nconst MAX_LEVELS = 16;\n/** Header at the start of the HZB buffer: per level [offset, width, height, 0], then the level count. */\nconst HEADER_SIZE = MAX_LEVELS * 4 + 4;\nconst LEVEL_COUNT_SLOT = MAX_LEVELS * 4;\nconst WORKGROUP = 64;\nconst NO_NODES: THREE.ComputeNode[] = [];\n\n/** Mean frame time: with pipelined or batched submission, single frame times vary; the mean is the throughput. */\nconst mean = (values: number[]) => values.reduce((a, b) => a + b, 0) / values.length;\n\nconst minNode = min as (a: unknown, b: unknown) => any; // eslint-disable-line @typescript-eslint/no-explicit-any\nconst maxNode = max as (a: unknown, b: unknown) => any; // eslint-disable-line @typescript-eslint/no-explicit-any\ntype Node = any; // TSL node typings are too strict for the graph code below; runtime is verified in the browser\n\nexport class OcclusionCulling {\n /** Lever: set false to turn occlusion culling off (no occluder pass, no HZB, nothing culled by it). */\n enabled = true;\n /**\n * Lever: decide by measurement. Whether occlusion pays off depends on the scene and the GPU: the occluder\n * pass has a fixed cost, which wins in cities and interiors and loses in open landscapes. With `auto`,\n * frame times are compared with occlusion off and on (`autoProbeFrames` each), the faster setting is kept\n * for `autoHoldFrames`, then measured again. Within 3% (e.g. both capped by vsync) it stays off.\n * Set false to keep it on whenever `enabled`.\n */\n auto = true;\n autoProbeFrames = 40;\n autoHoldFrames = 900;\n /** The auto setting currently in use (true: occlusion on). */\n autoChoice = false;\n // Starts in 'hold' (off) and probes after a 120-frame warm-up: the first frames compile pipelines.\n private phase: 'probeOff' | 'probeOn' | 'hold' = 'hold';\n private phaseFrames = this.autoHoldFrames - 120;\n private samples: number[] = [];\n private offMean = 0;\n private lastTick = 0;\n /** Depth resolution relative to the drawing buffer. Lower is cheaper and culls a little less. */\n resolutionScale = 0.5;\n /** Largest HZB dimension in texels (memory ~1.33 * maxSize^2 * 4 bytes). */\n readonly maxSize: number;\n /** True when this frame's HZB holds at least one occluder (the cull kernels test against it only then). */\n active = false;\n /** 1 while this frame's HZB is valid; the cull kernels only occlusion-cull then. */\n readonly activeNode = uniform(0, 'uint');\n\n private readonly depthScene = new THREE.Scene();\n private readonly proxies = new Map<VirtualMesh, THREE.Mesh>();\n private readonly projection: Node;\n private readonly near: Node;\n private readonly levelCapacity: number;\n private readonly levelOffsets: number[] = [];\n private readonly hzbAttribute: THREE.StorageBufferAttribute;\n private readonly hzbWrite: Node;\n private readonly hzbRead: Node;\n /** Copy + reduce kernels for the current depth size, dispatched with this frame's cut (one submission). */\n private buildNodes: THREE.ComputeNode[] = [];\n private renderTarget: THREE.RenderTarget | null = null;\n private width = 0;\n private height = 0;\n private levels = 0;\n private readonly bufferSize = new THREE.Vector2();\n\n constructor(projection: Node, near: Node, maxSize = 1024) {\n this.maxSize = Math.max(1, Math.min(1 << (MAX_LEVELS - 1), maxSize));\n this.projection = projection;\n this.near = near;\n\n let dim = this.maxSize;\n let total = HEADER_SIZE;\n let levelCapacity = 0;\n for (;;) {\n this.levelOffsets.push(total);\n total += dim * dim;\n levelCapacity++;\n if (dim === 1) break;\n dim = Math.ceil(dim / 2);\n }\n this.levelCapacity = levelCapacity;\n this.hzbAttribute = new THREE.StorageBufferAttribute(new Float32Array(total), 1);\n this.hzbWrite = storage(this.hzbAttribute, 'float', total);\n // Separate node: toReadOnly() changes the node it is called on.\n this.hzbRead = storage(this.hzbAttribute, 'float', total).toReadOnly();\n\n }\n\n /**\n * True only when a sphere (view-space center, radius) is certainly hidden. Any doubt (touching the near\n * plane, outside the screen) keeps it.\n */\n occluded(viewCenter: Node, radius: Node): Node {\n // Closed-form bounds of the sphere's view-space box (perspective camera, looking down -z): over the box,\n // x / depth is extreme at its corners, so each axis needs only the near and far depth. Same result as\n // projecting the 8 corners, at a fraction of the cost.\n const p: Node = this.projection;\n const depth = viewCenter.z.negate();\n const nearDepth = depth.sub(radius).toVar();\n const farDepth = depth.add(radius);\n const xLo = viewCenter.x.sub(radius);\n const xHi = viewCenter.x.add(radius);\n const yLo = viewCenter.y.sub(radius);\n const yHi = viewCenter.y.add(radius);\n // ndc.x = P00 * x / depth - P02 (P02, P12 are zero unless the frustum is off-center); P00, P11 > 0.\n const sx = p.element(0).x;\n const sy = p.element(1).y;\n const minX = minNode(xLo.div(nearDepth), xLo.div(farDepth)).mul(sx).sub(p.element(2).x);\n const maxX = maxNode(xHi.div(nearDepth), xHi.div(farDepth)).mul(sx).sub(p.element(2).x);\n const minY = minNode(yLo.div(nearDepth), yLo.div(farDepth)).mul(sy).sub(p.element(2).y);\n const maxY = maxNode(yHi.div(nearDepth), yHi.div(farDepth)).mul(sy).sub(p.element(2).y);\n // Depth of the nearest point: ndc.z = -P22 + P23 / depth.\n const minZ = p.element(3).z.div(nearDepth).sub(p.element(2).z);\n const behind = nearDepth.lessThanEqual(this.near);\n\n // Footprint in mip-0 texels. Row 0 is the top of the screen (WebGPU texture origin).\n const hzb = this.hzbRead;\n const W = hzb.element(1);\n const H = hzb.element(2);\n const zero = float(0);\n const x0 = clamp(floor(minX.mul(0.5).add(0.5).mul(W)), zero, W.sub(1));\n const x1 = clamp(floor(maxX.mul(0.5).add(0.5).mul(W)), zero, W.sub(1));\n const y0 = clamp(floor(float(0.5).sub(maxY.mul(0.5)).mul(H)), zero, H.sub(1));\n const y1 = clamp(floor(float(0.5).sub(minY.mul(0.5)).mul(H)), zero, H.sub(1));\n\n // The mip whose texels are at least as big as the footprint: then it spans at most 2x2 of them.\n const extent = maxNode(x1.sub(x0), y1.sub(y0)).add(1);\n const levelF = minNode(ceil(log2(extent)), hzb.element(LEVEL_COUNT_SLOT).sub(1));\n const entry = uint(levelF).mul(4);\n const scale = exp2(levelF);\n const offset = hzb.element(entry);\n const levelW = hzb.element(entry.add(1));\n const levelH = hzb.element(entry.add(2));\n const sampleAt = (fx: Node, fy: Node): Node => {\n const tx = clamp(floor(fx.div(scale)), zero, levelW.sub(1));\n const ty = clamp(floor(fy.div(scale)), zero, levelH.sub(1));\n return hzb.element(uint(offset.add(ty.mul(levelW)).add(tx)));\n };\n const hzbMax = maxNode(maxNode(sampleAt(x0, y0), sampleAt(x1, y0)), maxNode(sampleAt(x0, y1), sampleAt(x1, y1)));\n\n // Hidden when the nearest point of the box is behind every occluder in its on-screen footprint (parts\n // off screen are not visible anyway).\n return behind.not().and(minZ.lessThan(1)).and(minZ.greaterThan(hzbMax.add(1e-6)));\n }\n\n /** Called once per frame by the context: feeds the auto A/B measurement (see `auto`). */\n tick(now: number) {\n const dt = this.lastTick ? now - this.lastTick : 0;\n this.lastTick = now;\n if (!this.auto || !this.enabled) return;\n this.phaseFrames++;\n // Skip the first frames after a switch (pipelines, stale cuts), and stalls (tab switches, loading).\n if (this.phase !== 'hold' && this.phaseFrames > 5 && dt > 0 && dt < 250) this.samples.push(dt);\n if (this.phase === 'probeOff' && this.samples.length >= this.autoProbeFrames) {\n this.offMean = mean(this.samples);\n this.next('probeOn');\n } else if (this.phase === 'probeOn' && this.samples.length >= this.autoProbeFrames) {\n this.autoChoice = mean(this.samples) < this.offMean * 0.97;\n this.next('hold');\n } else if (this.phase === 'hold' && this.phaseFrames >= this.autoHoldFrames) {\n this.next('probeOff');\n }\n }\n\n private next(phase: 'probeOff' | 'probeOn' | 'hold') {\n this.phase = phase;\n this.phaseFrames = 0;\n this.samples = [];\n }\n\n private autoWanted() {\n return this.phase === 'probeOn' || (this.phase === 'hold' && this.autoChoice);\n }\n\n /** Depth-only proxy of a mesh's camera cut, created on first use and kept in sync with its pool. */\n private proxyOf(mesh: VirtualMesh) {\n let proxy = this.proxies.get(mesh);\n if (!proxy) {\n proxy = new THREE.Mesh(mesh.cameraGeometry, new THREE.MeshBasicNodeMaterial({ colorWrite: false }));\n proxy.frustumCulled = false;\n this.depthScene.add(proxy);\n this.proxies.set(mesh, proxy);\n }\n const material = proxy.material as THREE.MeshBasicNodeMaterial;\n if (material.positionNode !== mesh.pool.positionNode) {\n material.positionNode = mesh.pool.positionNode; // same vertex pulling as the shaded mesh\n material.needsUpdate = true;\n }\n return proxy;\n }\n\n unregisterMesh(mesh: VirtualMesh) {\n const proxy = this.proxies.get(mesh);\n if (!proxy) return;\n this.proxies.delete(mesh);\n proxy.removeFromParent();\n (proxy.material as THREE.Material).dispose();\n }\n\n /**\n * Whether occlusion culling runs this frame (enabled, a supported camera and depth mode, and the auto tuner\n * wants it). Meshes get their per-mesh flag from this before the cut is computed.\n */\n wantsFrame(renderer: THREE.WebGPURenderer, camera: THREE.Camera, _frame: number) {\n const r = renderer as unknown as { reversedDepthBuffer?: boolean; logarithmicDepthBuffer?: boolean };\n // The test assumes a perspective camera and standard [0, 1] depth.\n const supported = (camera as THREE.PerspectiveCamera).isPerspectiveCamera && !r.reversedDepthBuffer && !r.logarithmicDepthBuffer;\n return this.enabled && supported && (!this.auto || this.autoWanted());\n }\n\n /**\n * Renders the occluders' last camera cuts into the depth target and returns the compute kernels that turn\n * it into the HZB; run them before the cut (the caller prepends them to the same compute submission).\n * Sets `activeNode`, which the cull kernels check: without occluders this frame, nothing is occlusion culled.\n */\n beginFrame(renderer: THREE.WebGPURenderer, camera: THREE.Camera, meshes: readonly VirtualMesh[]): THREE.ComputeNode[] {\n let any = false;\n for (const mesh of meshes) {\n const occluder = mesh.visible && mesh.occluder && mesh.pool.hasCut && !!mesh.pool.positionNode;\n if (!occluder && !this.proxies.has(mesh)) continue;\n const proxy = this.proxyOf(mesh);\n proxy.visible = occluder;\n any = any || occluder;\n }\n this.active = any;\n this.activeNode.value = any ? 1 : 0;\n if (!any) return NO_NODES;\n\n renderer.getDrawingBufferSize(this.bufferSize);\n const s = Math.min(this.resolutionScale, this.maxSize / Math.max(this.bufferSize.x, this.bufferSize.y));\n const w = Math.max(1, Math.round(this.bufferSize.x * s));\n const h = Math.max(1, Math.round(this.bufferSize.y * s));\n if (w !== this.width || h !== this.height) this.resize(w, h);\n\n // The depth scene has no lights, so this renders no shadow maps.\n const previous = renderer.getRenderTarget();\n renderer.setRenderTarget(this.renderTarget);\n renderer.render(this.depthScene, camera);\n renderer.setRenderTarget(previous);\n return this.buildNodes;\n }\n\n private resize(w: number, h: number) {\n const old = this.buildNodes;\n this.renderTarget?.dispose();\n const depthTexture = new THREE.DepthTexture(w, h);\n depthTexture.type = THREE.FloatType;\n this.renderTarget = new THREE.RenderTarget(w, h, { depthBuffer: true, depthTexture });\n this.width = w;\n this.height = h;\n\n const header = this.hzbAttribute.array as Float32Array;\n header.fill(0, 0, HEADER_SIZE);\n let lw = w;\n let lh = h;\n let levels = 0;\n for (let i = 0; i < this.levelCapacity; i++) {\n header[i * 4] = this.levelOffsets[i];\n header[i * 4 + 1] = lw;\n header[i * 4 + 2] = lh;\n levels++;\n if (lw === 1 && lh === 1) break;\n lw = Math.max(1, Math.ceil(lw / 2));\n lh = Math.max(1, Math.ceil(lh / 2));\n }\n this.levels = levels;\n header[LEVEL_COUNT_SLOT] = levels;\n this.hzbAttribute.needsUpdate = true;\n\n // Mip 0: depth texture -> the first region of the HZB buffer.\n const depth = texture(depthTexture);\n const hzb = this.hzbWrite;\n const copyNode = Fn(() => {\n const idx = instanceIndex;\n const dstW = uint(hzb.element(1));\n const dstH = uint(hzb.element(2));\n If(idx.greaterThanEqual(dstW.mul(dstH)), () => {\n Return();\n });\n const x = idx.mod(dstW);\n const y = idx.div(dstW);\n // Through a var: an inline uint() of a storage element is dropped by the WGSL builder (f32 + u32).\n const dstOffset = uint(hzb.element(0)).toVar();\n hzb.element(dstOffset.add(idx)).assign(depth.load(ivec2(int(x), int(y))));\n })().compute(w * h, [WORKGROUP]);\n this.buildNodes = [copyNode];\n\n // Mip i = max of the 2x2 texels of mip i-1 (disjoint regions of the same read-write binding).\n lw = w;\n lh = h;\n for (let i = 1; i < levels; i++) {\n lw = Math.max(1, Math.ceil(lw / 2));\n lh = Math.max(1, Math.ceil(lh / 2));\n this.buildNodes.push(\n Fn(() => {\n const idx = instanceIndex;\n const dstOffset = uint(hzb.element(i * 4)).toVar();\n const dstW = uint(hzb.element(i * 4 + 1));\n const dstH = uint(hzb.element(i * 4 + 2));\n If(idx.greaterThanEqual(dstW.mul(dstH)), () => {\n Return();\n });\n const x = idx.mod(dstW);\n const y = idx.div(dstW);\n const srcOffset = uint(hzb.element((i - 1) * 4)).toVar();\n const srcW = uint(hzb.element((i - 1) * 4 + 1));\n const srcH = uint(hzb.element((i - 1) * 4 + 2));\n const x0 = x.mul(2);\n const y0 = y.mul(2);\n const x1 = minNode(x0.add(1), srcW.sub(1));\n const y1 = minNode(y0.add(1), srcH.sub(1));\n const row0 = srcOffset.add(y0.mul(srcW));\n const row1 = srcOffset.add(y1.mul(srcW));\n const v = maxNode(maxNode(hzb.element(row0.add(x0)), hzb.element(row0.add(x1))), maxNode(hzb.element(row1.add(x0)), hzb.element(row1.add(x1))));\n hzb.element(dstOffset.add(idx)).assign(v);\n })().compute(lw * lh, [WORKGROUP])\n );\n }\n for (const node of old) node.dispose();\n }\n\n dispose() {\n this.renderTarget?.dispose();\n this.renderTarget = null;\n for (const mesh of [...this.proxies.keys()]) this.unregisterMesh(mesh);\n }\n}\n","import * as THREE from 'three/webgpu';\nimport { uniform } from 'three/tsl';\nimport type { VirtualMesh, VirtualMeshInstances, VirtualMeshOptions } from './VirtualMesh';\nimport { OcclusionCulling } from './OcclusionCulling';\nimport { VirtualMesh as VirtualMeshClass } from './VirtualMesh';\nimport type { VirtualMeshData } from '../preprocess/buildVirtualMesh';\nimport { GeometryPool, NO_DRAW_DISTANCE, type PoolCapacity } from './GeometryPool';\nimport { virtualMeshesFromObject3D, type VirtualGeometryImport, type VirtualGeometryImportOptions } from '../import/fromObject3D';\n\nexport { VG_DEBUG_MODES } from '../constants';\n\n/** Length of the camera + settings vector compared by `VirtualGeometry.cutInputsChanged`. */\nconst CUT_INPUT_COUNT = 16 + 16 + 12;\n\nexport interface VirtualGeometryStats {\n drawnMeshlets: number;\n drawnTriangles: number;\n /** Triangles if every instance were drawn at full detail (no LOD, no culling). */\n fullDetailTriangles: number;\n instances: number;\n /** Instances that survived instance culling (frustum, sub-pixel). */\n visibleInstances: number;\n /** Triangles the LOD cut asked for. Above drawnTriangles means some mesh ran out of index buffer. */\n requestedTriangles: number;\n /** True when a mesh dropped meshlets for lack of capacity (visible as flicker). */\n overflow: boolean;\n /** Fullest draw buffer of any mesh, as a fraction of its capacity (above 1: overflow). */\n capacityUse: number;\n /** Instances hidden from the camera by occlusion culling. */\n occludedInstances: number;\n /** Triangles drawn into shadow maps (the coarser shadow cut). */\n shadowTriangles: number;\n}\n\n/**\n * Per-frame state shared by every `VirtualMesh`: camera uniforms used by the\n * GPU culling/LOD-selection kernels, plus global settings.\n */\nconst ZERO = new THREE.Vector3();\n\n/**\n * Threshold that brings a too-full draw buffer back to ~85%: triangles scale with about 1/threshold^2, so\n * one step lands near the target even from a large overflow (at most 2x per step, at least 4%).\n */\nfunction capacityStep(threshold: number, use: number) {\n return Math.min(64, threshold * Math.min(2, Math.max(1.04, Math.sqrt(use / 0.85))));\n}\n\nexport interface VirtualGeometryOptions {\n /** Max triangles drawn per frame per pool (camera). Default 10M (120 MB of indices, under the 128 MB binding limit). */\n maxTriangles?: number;\n /** Max triangles drawn into shadow maps per frame per pool. Default 4M. */\n maxShadowTriangles?: number;\n /** Max meshlets drawn per frame per pool. Default 1M. */\n maxMeshlets?: number;\n /**\n * Largest storage-buffer binding a pool may use, in bytes. A pool that would exceed it is closed and a new one\n * opened. Default 120 MB (WebGPU guarantees 128 MB; raise it if you request a higher device limit).\n */\n maxPoolBytes?: number;\n}\n\nexport class VirtualGeometry {\n readonly viewMatrix = uniform(new THREE.Matrix4());\n readonly projectionMatrix = uniform(new THREE.Matrix4());\n /** `projection[1][1] * viewportHeight / 2`: converts view-space error to pixels. */\n readonly projScale = uniform(1);\n readonly near = uniform(0.1);\n /** Max projected error, in pixels, a meshlet may have to be drawn. */\n readonly errorThreshold = uniform(1);\n\n /**\n * Lever: target number of drawn triangles per frame. When > 0, the error threshold is adjusted (slowly, see\n * adaptThreshold) to keep the drawn triangle count near this budget. Off by default: a fixed threshold gives\n * the steadiest image, because LODs then only switch with distance, never all at once.\n */\n triangleBudget = 0;\n /** Bounds for the automatically adjusted error threshold, in pixels. */\n thresholdRange: [number, number] = [0.5, 3];\n /** Latest GPU readback, updated every `statsInterval` frames while a budget or HUD is active. */\n lastStats: VirtualGeometryStats | null = null;\n statsInterval = 10;\n /** Frames updated so far. */\n frameCount = 0;\n /** The user's threshold while the capacity guard holds a coarser one (no budget), else null. */\n private guardBase: number | null = null;\n /** Consecutive stats readbacks with the drawn triangles outside the budget's deadband. */\n private outOfBand = 0;\n private guardWritten = NaN;\n private statsPending = false;\n readonly frustumCulling = uniform(1, 'uint');\n readonly debugMode = uniform(0, 'uint');\n /**\n * Instances whose bounding sphere projects to a smaller radius than this (pixels) are skipped. 0 disables.\n * The sphere is never smaller than the object, so at 0.7 nothing wider than ~1.4 px on screen is dropped.\n */\n readonly minPixelRadius = uniform(0.7);\n readonly frustumPlanes = Array.from({ length: 6 }, () => uniform(new THREE.Vector4()));\n /**\n * Direction * length that light travels (e.g. sun direction * 300). When non-zero, frustum culling\n * keeps meshlets whose shadow, swept along this vector, can reach the view frustum, so shadow\n * casters just outside the view still cast shadows. Zero disables it.\n */\n readonly shadowSweep = uniform(new THREE.Vector3());\n /**\n * Set `shadowSweep` automatically from the shadow cameras of the lights that render the meshes (direction\n * of an orthographic shadow camera, length = its larger extent). Turn off to set `shadowSweep` yourself.\n */\n autoShadowSweep = true;\n /**\n * Shadow maps use a coarser cut: the error threshold times this. Shadows are soft and seen from the camera\n * at a distance, so this saves most of the shadow-pass triangles with no visible change. 1 = camera detail.\n */\n readonly shadowErrorScale = uniform(3);\n private readonly detectedSweep = new THREE.Vector3();\n private detectedSweepFrame = -Infinity;\n\n /**\n * Occlusion culling (on by default): geometry hidden behind solid meshes is not drawn. Levers:\n * `occlusion.enabled`, `occlusion.resolutionScale`, and per mesh `occluder` / `occlusionCulling`.\n */\n readonly occlusion = new OcclusionCulling(this.projectionMatrix, this.near);\n\n /** Skip LOD selection/culling and keep drawing the last selection (for inspecting the cut). */\n freeze = false;\n /**\n * Run `update()` automatically before every render of a scene that contains this context's meshes, with the\n * camera that render uses (default true). Shadow-map renders reuse the cut of the camera being rendered.\n * Calling `update()` yourself still works: a render right after it with the same camera does not repeat it.\n */\n autoUpdate = true;\n /**\n * Measure the error threshold in CSS pixels (default) instead of device pixels. On a 2x display,\n * device pixels would request ~4x the triangles for detail nobody can see.\n */\n errorInCssPixels = true;\n\n readonly meshes: VirtualMesh[] = [];\n /** Shared buffers and compute passes; meshes go into the first pool with room (see GeometryPool). */\n readonly pools: GeometryPool[] = [];\n private readonly capacity: PoolCapacity;\n private readonly maxPoolBytes: number;\n\n constructor(options: VirtualGeometryOptions = {}) {\n this.capacity = {\n triangles: options.maxTriangles ?? 10_000_000,\n shadowTriangles: options.maxShadowTriangles ?? 4_000_000,\n meshlets: Math.min(options.maxMeshlets ?? 1 << 20, 1 << 24),\n };\n this.maxPoolBytes = options.maxPoolBytes ?? 120 * 1024 * 1024;\n }\n\n private readonly frustum = new THREE.Frustum();\n private readonly projScreen = new THREE.Matrix4();\n private readonly size = new THREE.Vector2();\n /** Compute nodes dispatched this frame (reused to avoid per-frame allocation). */\n private readonly computeList: THREE.ComputeNode[] = [];\n private readonly dispatchedPools: GeometryPool[] = [];\n /** Frames where `update` ran no compute pass because nothing the cut depends on changed. */\n skippedFrames = 0;\n /** Inputs of the cut as of the last frame that changed them (NaN until the first frame). */\n private readonly cutInputs = new Float64Array(CUT_INPUT_COUNT).fill(NaN);\n private readonly cutInputsScratch = new Float64Array(CUT_INPUT_COUNT);\n /** Scenes whose onBeforeRender runs the auto update (installed the first time one of our meshes renders in them). */\n private readonly sceneHooks = new WeakMap<THREE.Object3D, THREE.Object3D['onBeforeRender']>();\n /** `renderer.info.render.calls` and camera of the last automatic and the last manual update. */\n private autoCall = -1;\n private autoCamera: THREE.Camera | null = null;\n private manualCall = -1;\n private manualCamera: THREE.Camera | null = null;\n private updatingAuto = false;\n\n /**\n * Converts every static mesh under `object` (e.g. `gltf.scene`) to VirtualGeometry geometry, in place: meshes sharing\n * geometry and material become one VirtualMesh with many instances, materials are converted to node materials\n * with their textures, and the originals stop rendering. Skinned/morphing meshes, points and lines are left\n * alone. Returns the created meshes and a `dispose()` that restores the originals. See `VirtualGeometryImportOptions`.\n */\n add(object: THREE.Object3D, options?: VirtualGeometryImportOptions): Promise<VirtualGeometryImport> {\n return virtualMeshesFromObject3D(this, object, options);\n }\n\n /** Create a renderable mesh from a built DAG. Add the result to any three.js scene. */\n createMesh(data: VirtualMeshData, material: THREE.NodeMaterial, instances: VirtualMeshInstances, options?: VirtualMeshOptions): VirtualMesh {\n return new VirtualMeshClass(this, data, material, instances, options);\n }\n\n /**\n * Lever: compile a pool's compute pipelines in the background before its first dispatch (default), so adding\n * meshes never freezes the page; they appear once ready. False: compile on first use (a hitch).\n */\n asyncCompile = true;\n\n private compilePool(renderer: THREE.WebGPURenderer, pool: GeometryPool) {\n pool.pipelineState = 'compiling';\n const version = pool.version;\n const done = () => {\n if (pool.version !== version) return; // rebuilt meanwhile: compiles again\n pool.pipelineState = 'ready';\n pool.dirty = true;\n };\n renderer.compileComputeAsync(pool.computeNodes).then(done, done);\n }\n\n /** Builds pools whose buffers grew and points their meshes at the new buffers. */\n private preparePools(renderer: THREE.WebGPURenderer) {\n for (const pool of this.pools) pool.prepare(renderer);\n // A pool may also have been rebuilt while meshes were being added: syncPool is a version check.\n for (const mesh of this.meshes) mesh.syncPool();\n }\n\n /**\n * Optional, for loading screens: compiles every pipeline the scene needs (compute and render), so the first\n * frames neither freeze nor show meshes popping in. Call after adding the meshes, before the first render.\n */\n async compileAsync(renderer: THREE.WebGPURenderer, scene: THREE.Object3D, camera: THREE.Camera) {\n this.preparePools(renderer);\n const pending = this.pools.filter((p) => p.pipelineState !== 'ready');\n for (const pool of pending) pool.pipelineState = 'compiling';\n await Promise.all(pending.map((p) => renderer.compileComputeAsync(p.computeNodes).catch(() => undefined)));\n for (const pool of pending) {\n pool.pipelineState = 'ready';\n pool.dirty = true;\n }\n await renderer.compileAsync(scene, camera);\n }\n\n /** Called by meshes from onBeforeShadow: remembers the light direction for `autoShadowSweep`. */\n noteShadowCamera(shadowCamera: THREE.Camera) {\n if (this.detectedSweepFrame === this.frameCount) return;\n const ortho = shadowCamera as THREE.OrthographicCamera;\n if (!ortho.isOrthographicCamera) return; // spot/point lights: no single direction to sweep along\n const extent = Math.max(ortho.top - ortho.bottom, ortho.right - ortho.left) / ortho.zoom;\n shadowCamera.getWorldDirection(this.detectedSweep).multiplyScalar(extent);\n this.detectedSweepFrame = this.frameCount;\n }\n\n /** Puts the mesh's geometry and instances into the first pool with room (a new pool when none has). */\n register(mesh: VirtualMesh, instances: VirtualMeshInstances) {\n const instanceCount = instances.matrices.length / 16;\n if (GeometryPool.bytesOf(mesh.data) > this.maxPoolBytes) {\n throw new Error(`VirtualGeometry: a single mesh needs more than maxPoolBytes (${this.maxPoolBytes} bytes) of GPU buffer`);\n }\n let pool = this.pools.find((p) => p.fits(mesh.data, instanceCount));\n if (!pool) {\n pool = new GeometryPool(this, this.capacity, this.maxPoolBytes);\n this.pools.push(pool);\n }\n mesh.pool = pool;\n mesh.entry = pool.add(mesh.data, instances.matrices, instances.colors, mesh.gpuToInput);\n pool.ensureBuilt(); // nodes are only rebuilt when the pool's buffers grew\n this.meshes.push(mesh);\n mesh.onBeforeRender = (renderer, scene, camera) => this.autoUpdateFor(renderer as unknown as THREE.WebGPURenderer, scene, camera, false);\n }\n\n /**\n * Auto update, from a VirtualMesh's onBeforeRender. The first time, this also hooks the scene's onBeforeRender,\n * which runs before the render pass starts (so shadow maps rendered inside the pass already see the new cut);\n * later frames update from there. A compute submitted from inside a pass still runs before that pass on the\n * GPU, because the pass is submitted when it ends.\n */\n private autoUpdateFor(renderer: THREE.WebGPURenderer, scene: THREE.Object3D, camera: THREE.Camera, fromScene: boolean) {\n if (!this.autoUpdate || this.meshes.length === 0) return;\n // Shadow maps draw the cut of the camera being rendered (see shadowSweep), never their own.\n if ((scene as THREE.Scene).overrideMaterial && (scene as THREE.Scene & { overrideMaterial: { isShadowPassMaterial?: boolean } }).overrideMaterial.isShadowPassMaterial) return;\n if (!fromScene && (scene as THREE.Scene).isScene) {\n // The scene hook already ran for this render; (re)install it if missing, e.g. replaced by user code.\n if (scene.onBeforeRender === this.sceneHooks.get(scene)) return;\n const previous = scene.onBeforeRender;\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const context = this;\n const hook: THREE.Object3D['onBeforeRender'] = function (this: THREE.Object3D, r, s, c, ...rest) {\n context.autoUpdateFor(r as unknown as THREE.WebGPURenderer, s, c, true);\n previous.call(this, r, s, c, ...rest);\n };\n scene.onBeforeRender = hook;\n this.sceneHooks.set(scene, hook);\n }\n // Once per render call, and not for the render right after a manual update() with the same camera.\n const call = renderer.info.render.calls;\n if (camera === this.autoCamera && call === this.autoCall) return;\n if (camera === this.manualCamera && call === this.manualCall + 1) return;\n this.autoCall = call;\n this.autoCamera = camera;\n this.updatingAuto = true;\n try {\n this.update(renderer, camera as THREE.PerspectiveCamera);\n } finally {\n this.updatingAuto = false;\n }\n }\n\n unregister(mesh: VirtualMesh) {\n const i = this.meshes.indexOf(mesh);\n if (i === -1) return;\n this.meshes.splice(i, 1);\n mesh.pool.remove(mesh.entry);\n this.occlusion.unregisterMesh(mesh);\n }\n\n /** Dispose every mesh created by this context. */\n dispose() {\n for (const mesh of [...this.meshes]) mesh.dispose(this);\n for (const pool of this.pools) pool.dispose();\n this.pools.length = 0;\n this.occlusion.dispose();\n }\n\n /**\n * Runs LOD selection + culling on the GPU for `camera`. With `autoUpdate` (default) the renderer calls this\n * for you before each render; call it yourself before `renderer.render` when `autoUpdate` is false.\n * When the camera, the settings and every mesh's instances are unchanged, the compute passes are\n * skipped and the previous cut (index buffer + draw args) is drawn again.\n */\n update(renderer: THREE.WebGPURenderer, camera: THREE.PerspectiveCamera) {\n if (!this.updatingAuto) {\n this.manualCall = renderer.info.render.calls;\n this.manualCamera = camera;\n }\n if (this.freeze) return;\n this.occlusion.tick(performance.now());\n\n camera.updateMatrixWorld();\n this.viewMatrix.value.copy(camera.matrixWorldInverse);\n if (!this.projectionMatrix.value.equals(camera.projectionMatrix)) this.projectionMatrix.value.copy(camera.projectionMatrix);\n renderer.getDrawingBufferSize(this.size);\n // Errors are measured in CSS pixels, so a threshold means the same thing at any devicePixelRatio.\n const cssHeight = this.size.y / (this.errorInCssPixels ? renderer.getPixelRatio() : 1);\n // Only write uniforms that changed: a static camera then costs no uniform updates at all.\n const projScale = camera.projectionMatrix.elements[5] * cssHeight * 0.5;\n if (this.projScale.value !== projScale) this.projScale.value = projScale;\n if (this.near.value !== camera.near) this.near.value = camera.near;\n\n this.projScreen.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);\n this.frustum.setFromProjectionMatrix(this.projScreen, THREE.WebGPUCoordinateSystem);\n for (let i = 0; i < 6; i++) {\n const { normal, constant } = this.frustum.planes[i];\n const p = this.frustumPlanes[i].value;\n if (p.x !== normal.x || p.y !== normal.y || p.z !== normal.z || p.w !== constant) {\n p.set(normal.x, normal.y, normal.z, constant);\n }\n }\n\n if (this.autoShadowSweep) {\n const sweep = this.frameCount - this.detectedSweepFrame <= 2 ? this.detectedSweep : ZERO;\n if (!this.shadowSweep.value.equals(sweep)) this.shadowSweep.value.copy(sweep);\n }\n // Per-mesh flags in the pools' mesh tables: visibility, shadows (only for meshes a shadow-casting light\n // rendered recently, reported from onBeforeShadow; a newly lit mesh starts casting one frame later) and\n // occlusion. writeFlags only uploads (and dirties the pool) when a value changes.\n const occlusionWanted = this.occlusion.wantsFrame(renderer, camera, this.frameCount);\n for (const mesh of this.meshes) {\n mesh.pool.writeFlags(mesh.entry, {\n enabled: mesh.visible ? 1 : 0,\n shadow: mesh.castShadow && this.frameCount - mesh.lastShadowFrame <= 2 ? 1 : 0,\n occlusion: occlusionWanted && mesh.occlusionCulling ? 1 : 0,\n });\n }\n\n // Anything the cut depends on changed: every pool needs a new cut.\n if (this.cutInputsChanged(camera, renderer.getPixelRatio())) {\n for (const pool of this.pools) pool.dirty = true;\n }\n\n this.preparePools(renderer);\n const nodes = this.computeList;\n nodes.length = 0;\n const dispatched = this.dispatchedPools;\n dispatched.length = 0;\n for (const pool of this.pools) {\n if (!pool.dirty || pool.entries.length === 0) continue;\n if (pool.pipelineState !== 'ready') {\n if (this.asyncCompile) {\n // Compile in the background: the pool's meshes show up a few frames later instead of a freeze.\n if (pool.pipelineState === 'none') this.compilePool(renderer, pool);\n continue;\n }\n pool.pipelineState = 'ready';\n }\n for (const node of pool.computeNodes) nodes.push(node);\n dispatched.push(pool);\n }\n if (nodes.length > 0) {\n // Depth of last frame's solid geometry from this frame's camera: what this frame's cut is tested against.\n const hzbNodes = occlusionWanted ? this.occlusion.beginFrame(renderer, camera, this.meshes) : [];\n if (hzbNodes.length) nodes.unshift(...hzbNodes);\n renderer.compute(nodes);\n for (const pool of dispatched) {\n pool.dirty = false;\n pool.hasCut = true;\n }\n } else {\n this.skippedFrames++;\n }\n\n this.frameCount++;\n // One small readback every statsInterval frames feeds the budget controller, the capacity guard (always\n // on: an overflow would flicker) and the occlusion auto pause.\n if (this.meshes.length > 0 && !this.statsPending && this.frameCount % this.statsInterval === 0) {\n this.statsPending = true;\n this.readStats(renderer)\n .then((s) => {\n this.lastStats = s;\n this.adaptThreshold(s);\n })\n .finally(() => (this.statsPending = false));\n }\n }\n\n\n /**\n * True when anything the GPU cut reads from the context differs from the last frame that was computed\n * (and records the new values). Exact comparison on purpose: an unmoved camera recomputes the same\n * matrices bit for bit, while any real change, including a budget-controller step, differs.\n */\n private cutInputsChanged(camera: THREE.PerspectiveCamera, pixelRatio: number): boolean {\n const cur = this.cutInputsScratch;\n let i = 0;\n for (let k = 0; k < 16; k++) cur[i++] = camera.matrixWorldInverse.elements[k];\n for (let k = 0; k < 16; k++) cur[i++] = camera.projectionMatrix.elements[k];\n cur[i++] = camera.near;\n cur[i++] = this.size.x;\n cur[i++] = this.size.y;\n cur[i++] = pixelRatio;\n cur[i++] = this.errorInCssPixels ? 1 : 0;\n cur[i++] = this.errorThreshold.value;\n cur[i++] = this.minPixelRadius.value;\n cur[i++] = this.frustumCulling.value;\n cur[i++] = this.debugMode.value;\n const sweep = this.shadowSweep.value;\n cur[i++] = sweep.x;\n cur[i++] = sweep.y;\n cur[i++] = sweep.z;\n\n for (let k = 0; k < CUT_INPUT_COUNT; k++) {\n if (cur[k] !== this.cutInputs[k]) {\n this.cutInputs.set(cur);\n return true;\n }\n }\n return false;\n }\n\n /**\n * Slow multiplicative controller. Drawn triangles grow roughly with 1/threshold^2. Every change of the\n * threshold re-picks LODs across the whole screen, so it moves rarely (deadband) and in small steps.\n *\n * Draw capacity is a hard constraint: an overflowing mesh drops meshlets in a different order every frame,\n * which flickers. So the controller coarsens *before* a buffer is full, never refines into one, and may go\n * above `thresholdRange[1]` only for capacity, coming back down as soon as there is room.\n */\n private adaptThreshold(stats: VirtualGeometryStats) {\n const t = this.errorThreshold.value;\n const use = stats.capacityUse;\n if (this.triangleBudget <= 0) {\n this.guardCapacity(stats, t);\n return;\n }\n this.guardBase = null;\n const [lo, hi] = this.thresholdRange;\n if (stats.overflow || use > 0.9) {\n this.errorThreshold.value = capacityStep(t, use);\n return;\n }\n if (stats.drawnTriangles <= 0) return;\n const ratio = stats.drawnTriangles / this.triangleBudget;\n // Every change re-picks LODs across the whole screen at once, which is far more visible than the\n // distance-driven switches of a fixed threshold. So: a wide deadband, and only after the count stayed out of\n // it for several readbacks in a row (moving through a scene makes it swing briefly all the time).\n if (Math.abs(ratio - 1) < 0.2) {\n this.outOfBand = 0;\n return;\n }\n if (++this.outOfBand < 3) return;\n let next = t * Math.min(1.03, Math.max(0.97, Math.sqrt(ratio)));\n // Back inside the range: gradually from above (capacity pushed it there), clamped otherwise.\n next = t > hi ? Math.max(hi, Math.min(next, t * 0.97)) : Math.min(hi, Math.max(lo, next));\n // Refining multiplies the drawn triangles by about (t / next)^2: never step into a full buffer.\n if (next < t && use * (t / next) ** 2 > 0.85) return;\n this.errorThreshold.value = next;\n }\n\n /**\n * Without a budget the threshold is the user's, except that draw capacity stays a hard limit: coarsen\n * temporarily before a buffer fills up, and return to the user's value once there is room again.\n */\n private guardCapacity(stats: VirtualGeometryStats, t: number) {\n // Changed since the guard last wrote it (by the user, or the budget was just switched off): new target.\n if (t !== this.guardWritten) this.guardBase = null;\n let next = t;\n if (stats.overflow || stats.capacityUse > 0.9) {\n this.guardBase ??= t;\n next = capacityStep(t, stats.capacityUse);\n } else if (this.guardBase !== null && t > this.guardBase) {\n const back = Math.max(this.guardBase, t * 0.97);\n if (stats.capacityUse * (t / back) ** 2 <= 0.85) next = back;\n if (next === this.guardBase) this.guardBase = null;\n }\n if (next !== t) this.errorThreshold.value = next;\n this.guardWritten = this.errorThreshold.value;\n }\n\n /** GPU -> CPU readback of the last culling result. Async; never call every frame. One small readback per pool. */\n async readStats(renderer: THREE.WebGPURenderer): Promise<VirtualGeometryStats> {\n const result: VirtualGeometryStats = {\n drawnMeshlets: 0,\n drawnTriangles: 0,\n fullDetailTriangles: 0,\n instances: 0,\n visibleInstances: 0,\n requestedTriangles: 0,\n overflow: false,\n capacityUse: 0,\n occludedInstances: 0,\n shadowTriangles: 0,\n };\n for (const mesh of this.meshes) {\n if (!mesh.visible) continue;\n result.fullDetailTriangles += mesh.fullDetailTriangles;\n result.instances += mesh.instanceCount;\n }\n for (const pool of this.pools) {\n if (!pool.hasCut) continue;\n const c = await pool.readCounters(renderer);\n const cap = pool.capacity;\n result.drawnMeshlets += c.camera.drawn;\n result.drawnTriangles += Math.min(c.camera.requestedTriangles, cap.triangles);\n result.requestedTriangles += c.camera.requestedTriangles;\n result.visibleInstances += c.camera.survived;\n result.occludedInstances += c.occluded;\n result.shadowTriangles += Math.min(c.shadow.requestedTriangles, cap.shadowTriangles);\n if (c.camera.selected > cap.meshlets || c.camera.requestedTriangles > cap.triangles) result.overflow = true;\n if (c.shadow.selected > cap.meshlets || c.shadow.requestedTriangles > cap.shadowTriangles) result.overflow = true;\n result.capacityUse = Math.max(\n result.capacityUse,\n c.camera.requestedTriangles / cap.triangles,\n c.camera.selected / cap.meshlets,\n c.shadow.requestedTriangles / cap.shadowTriangles,\n c.shadow.selected / cap.meshlets\n );\n }\n return result;\n }\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","names":["mortonOrder","minNode","maxNode","VirtualMeshClass","THREE","MAX_MESHLET_TRIANGLES","MAX_MESHLET_VERTICES","ERROR_INFINITY","FAST_PATH_MARGIN","VG_DEBUG_MODES","partitionMeshlets","count","meshlets","groupSize","i","edgeOwners","e","owners","adjacency","a","b","j","order","mortonOrder$1","m","assigned","groups","seed","group","frontier","addNeighbours","n","shared","best","bestScore","bestDist","score","d","dist2","result","pending","minSize","dx","dy","dz","min","max","p","points","k","extent","codes","q","part1By2","x","buildVoxelProxy","indices","o","positions","cell","resolution","origin","nx","ny","nz","sy","sz","total","occupied","colorSum","colors","colorCount","voxelUv","uvs","sampleU","sampleV","mark","y","z","g","t","c","longest","dist","steps","u","v","w","ta","tb","tc","closed","erode","dilate","field","blurAxis","ISO","cellsX","cellsY","cellsZ","cellVertex","outPositions","outNormals","outColors","outUvs","corner","base","inside","px","py","pz","crossings","bit","f0","f1","s","gx","gy","gz","len","r","outIndices","cellIndex","quad","ux","uy","uz","vx","vy","vz","cx","cy","cz","nx_","ny_","nz_","here","proxyColors","fillMissing","proxyUvs","src","axis","morph","stride","size","out","prev","next","grow","line","lines","l","start","values","pass","missing","sum","hits","DEFAULTS","TAIL_START_TRIANGLES","VOXEL_RESOLUTIONS","yieldToBrowser","buildVirtualMesh","opts","options","t0","MeshoptClusterizer","MeshoptSimplifier","normals","weld","voxelLevels","flags","all","proxyCache","leafs","splitIntoMeshlets","current","lastTriangles","countTriangles","lodLevels","estimatedTotal","level","groupIdx","merged","concatIndices","local","compact","target","simplified","simplifyError","lodSphere","enclosingSphere","childError","shapeError","extentShrink","error","child","globalIndices","outputs","triangles","simplifyTail","pack","appendVertices","first","uv","voxelProxy","roots","levels","tailFlags","nodes","keepLimit","sloppy","relativeError","parentError","voxel","proxy","proxyTarget","proxyError","voxelError","used","pick","node","built","vertexOffset","triangleOffset","vertexCount","triangleCount","vertices","localTriangles","meshletIndices","cullSphere","boundingSphere","meshlet","findBoundaryEdges","unsorted","meshletCount","acc","meshletBounds","meshletInfo","indexOf","replacementStart","replacementIndices","meshletVertices","meshletTriangles","firstIndex","stats","tri","whole","levelCount","levelRanges","levelErrors","levelGuardErrors","lodBoundsSphere","cullBoundsSphere","box","before","after","shrink","localOf","toGlobalAll","localIndices","toGlobal","localPositions","edgeTableKeys","edgeTableCounts","edgeOrder","edgeCount","mask","inserted","key","edgeKey","h","offset","r2","spheres","centers","radii","radius","VG_FORMAT_VERSION","MAGIC","PREFIX_BYTES","TYPED_ARRAYS","FIELD_HINTS","VirtualMeshFormatError","message","encodeVirtualMesh","compress","MeshoptEncoder","record","data","keys","fields","blobs","name","value","type","array","blob","entry","indicesMatchMeshlets","encodeField","bytesOf","align4","headerJson","headerBytes","jsonReplacer","headerPadded","payloadStart","f","view","checksum","decodeVirtualMesh","bytes","input","version","headerLength","header","jsonReviver","payload","arrays","rank","MeshoptDecoder","fail","inflate","decodeField","loadVirtualMesh","source","response","init","raw","hint","rawCandidate","candidates","encodeMeshletTriangles","strides","useDeflate","canDeflate","toDeflate","deflate","sameBytes","slots","covered","packed","codec","decoded","rotations","rebuildIndices","Ctor","requireArray","forField","decodeMeshletTriangles","codecLength","rotationsStart","length","words","stream","VG_BUILD_VERSION","DB_NAME","DATA_STORE","META_STORE","MAX_CACHE_BYTES","OPEN_TIMEOUT_MS","buildVirtualMeshCached","buildOptions","cache","hasIndexedDb","virtualMeshCacheKey","db","openDb","readEntry","touchEntry","clearVirtualMeshCache","tx","resolve","versions","customKey","subtle","names","describe","parts","optionEntries","text","digests","combined","hash","dbPromise","timer","done","request","writeEntry","evict","store","meta","deleteEntry","keysRequest","valuesRequest","entries","keep","selectCut","B","selected","projectedError","distance","own","parent","threshold","verifyCutCoverage","list","isCovered","holes","lodDistanceBounds","R","instanceMeshletRange","dMin","dMax","lo","hi","minOwn","maxParent","ownPossible","parentPossible","instanceGuaranteedRange","margin","possibleMeshlets","guaranteedMeshlets","maxOwn","minParent","ownSure","parentSure","end","vgUv","varyingProperty","getUV","vgTexture","texture","map","TWO_CHANNEL_FORMATS","vgNormalMap","sample","xy","vec3","sqrt","float","scale","transformNormalToView","q0","positionView","q1","st0","st1","N","normalView","q1perp","q0perp","T","det","mat3","negateOnBackSide","bindVirtualGeometryTextures","material","isTexture","color","vec4","materialColor","materialReference","bumpMap","context","minNode$1","maxNode$1","vgWorldNormal","vgMeshletVarying","vgLodVarying","vgInstanceVarying","vgTintVarying","LOCAL_VERTEX_BITS","LOCAL_VERTEX_MASK","MAX_DISPATCH","CULL_GROUP","MESHLET_GROUP","EXPAND_GROUP","MAX_LEVELS","MESH_STRIDE","INSTANCE_STRIDE","CELL_STRIDE","DRAW_DISTANCE_FADE","NO_DRAW_DISTANCE","CUT_COUNTERS","C_SELECTED","C_DRAWN","C_SURVIVED","C_WORK","C_REQUESTED","PER_MESH_COUNTERS","GrowBuffer","make","itemSize","maxItems","capacity","needed","f32","u32","GeometryPool","uniform","maxBytes","limit","bytesPerItem","add","instanceCount","slot","matrices","cellCount","at","buffer","gpuToInput","old","shift","levelsStart","grownSize","table","vd","asFloat","encodeOctNormal","va","packUvs","info","mv","set","index","gpuIndex","cells","maxRadius","instanceSphere","backend","renderer","ctx","cap","maxDrawn","instanceCapacity","cellCapacity","cameraIndexCapacity","shadowIndexCapacity","storageOf","storage","vertexData","vertexAttrs","bounds","meshTable","instances","cellListAttribute","workListAttribute","drawListAttribute","dispatchAttr","instanceArgsAttribute","meshletArgsAttributes","expandArgsAttributes","counters","drawArgs","cameraIndex","shadowIndex","cellList","cellListRead","workList","drawList","drawListRead","instanceArgs","meshletArgs","expandArgs","counter","cut","meshCount","uint","meshStart","cutCapacity","indexBuffers","shadowThreshold","thresholds","minPixelsGlobal","occlusion","instanceColumn","instanceId","modelOf","mat4","meshRecord","viewCenter","model","sphere","pixels","select","frustumDistance","minDistance","plane","dot","center","swept","occludedSphere","worldCenter","occlusionOn","dispatchArgs","resetNode","Fn","instanceIndex","If","rest","cellNode","levers","minPixels","gap","atomicAdd","uvec4","cellArgsNode","atomicLoad","levelCache","workgroupArray","selectLevels","last","l0","l1","levelFirst","possible","pixelsAtMax","pixelsAtMin","sure","cullCenter","cullBounds","cullRadius","fastPath","meshletId","item","tag","occlusionFlag","instanceNode","workgroupId","numWorkgroups","valid","levelBase","Loop","localId","workgroupBarrier","objectSphere","lodBounds","shadowOn","maxDrawDistance","noFrustum","inCamera","inShadow","viewDistance","tooSmall","tooFar","bool","lodCenter","meshletPass","work","boundsBase","visible","errors","ownError","prefixPass","requested","room","args","atomicStore","drawn","expandPass","drawSlot","regionStart","firstTriangle","vertexIndex","localVertex","vertexId","tintAndSlot","meshSlot","uvPacking","packedVertex","attrs","localPosition","bitcast","columns","originDistance","fade","worldPosition","worldNormal","normalize","decodeOctNormal","normalLocal","unpackRgba8","unpackUnorm2x16","sx","sr","c0","c1","c2","bits","pu","pv","spreadBits10","mortonOrder","radixOrder","counts","pristineMaterials","claimMaterial","pristine","placeholderGeometry","geometry","VirtualMesh","randomColor","debugColor","cameraViewMatrix","faceDirection","shadowCamera","autoUpdateHook","pool","matrix","CONVERSIONS","FLAGS","conversionOf","flag","canConvertToNodeMaterial","toNodeMaterial","conversion","Classic","Node","defines","POSITION_TOLERANCE","ATTRIBUTE_TOLERANCE","fromBufferGeometry","position","normal","vertexOf","byPosition","gather","smoothNormals","channels","full","attribute","width","quantize","multiplier","tolerance","firstVertex","firstCorner","welded","additive","HASH_PRIMES","same","mergeSources","indexCount","mesh","defaultBuilder","converted","incompatibility","mat","collectVirtualGeometryGroups","meshes","skipped","instanceMatrix","world","object","reason","filter","materials","drawnRanges","instanced","isVisible","rangeCount","materialIndex","vertexColors","tinted","matrixList","colorList","drawStart","drawEnd","ranges","multiMaterial","VirtualGeometryImport","collected","emptied","root","virtualMeshesFromObject3D","build","sources","sourceKey","createdGroups","failed","convertMaterial","meshOptions","flipNormalY","HEADER_SIZE","LEVEL_COUNT_SLOT","WORKGROUP","NO_NODES","mean","minNode","maxNode","OcclusionCulling","maxSize","projection","near","dim","levelCapacity","depth","nearDepth","farDepth","xLo","xHi","yLo","yHi","minX","maxX","minY","maxY","minZ","behind","hzb","W","H","zero","x0","clamp","floor","x1","y0","y1","levelF","ceil","log2","exp2","levelW","levelH","sampleAt","fx","ty","fy","hzbMax","dt","now","phase","supported","camera","any","occluder","previous","depthTexture","lw","lh","copyNode","idx","dstW","dstH","dstOffset","ivec2","int","srcOffset","srcW","srcH","row0","row1","CUT_INPUT_COUNT","ZERO","capacityStep","use","VirtualGeometry","scene","ortho","fromScene","hook","call","cssHeight","projScale","constant","sweep","occlusionWanted","dispatched","hzbNodes","cur","pixelRatio","ratio","back"],"sources":["../src/core/constants.ts","../src/core/preprocess/partition.ts","../src/core/preprocess/voxelProxy.ts","../src/core/preprocess/buildVirtualMesh.ts","../src/core/io/serialize.ts","../src/core/io/cache.ts","../src/core/runtime/cut.ts","../src/core/runtime/vgMaterial.ts","../src/core/runtime/GeometryPool.ts","../src/core/runtime/VirtualMesh.ts","../src/core/import/toNodeMaterial.ts","../src/source.ts","../src/core/import/fromObject3D.ts","../src/core/runtime/OcclusionCulling.ts","../src/core/runtime/VirtualGeometry.ts"],"sourcesContent":["/** Max triangles per meshlet. The renderer always issues `MAX_MESHLET_TRIANGLES * 3` vertices per drawn meshlet. */\nexport const MAX_MESHLET_TRIANGLES = 128;\n\n/** Max unique vertices per meshlet (meshoptimizer allows up to 256). */\nexport const MAX_MESHLET_VERTICES = 128;\n\n/** Stand-in for `Infinity` on the GPU: the parent error of root meshlets. */\nexport const ERROR_INFINITY = 1e30;\n\n/**\n * Instances whose LOD range is at most this many meshlets, and where every meshlet is guaranteed to be\n * selected, emit their meshlets directly from the instance pass (no meshlet pass for them).\n */\nexport const FAST_PATH_MAX_MESHLETS = 4;\n\n/**\n * Relative margin the fast path keeps from the LOD threshold, so float rounding between the bound and the\n * per-meshlet test can never make the fast path select a meshlet the full test would reject.\n */\nexport const FAST_PATH_MARGIN = 1e-3;\n\n/** Floats per meshlet in `VirtualMeshData.meshletBounds` (4 x vec4). */\nexport const MESHLET_BOUNDS_STRIDE = 16;\n\n/** Uints per meshlet in `VirtualMeshData.meshletInfo` (1 x uvec4). */\nexport const MESHLET_INFO_STRIDE = 4;\n\n\n\n/** Debug views for `VirtualGeometry.debugMode`. */\nexport const VG_DEBUG_MODES = {\n shaded: 0,\n meshlets: 1,\n lodLevel: 2,\n instances: 3,\n} as const;\n","/**\n * Groups meshlets into clusters of ~`groupSize` that share as many boundary\n * edges as possible. This stands in for METIS (the graph partitioner nanite-webgpu uses):\n * a greedy region-growing pass over the meshlet adjacency graph, seeded in\n * Morton order so groups stay spatially compact. Meshlets without enough\n * neighbours (e.g. disconnected leaves or grass blades) are then merged with\n * spatially close leftovers so they can still be simplified together.\n */\n\nexport interface PartitionInput {\n /** Boundary edge keys (position-welded vertex ids, see `edgeKey`). */\n boundaryEdges: number[];\n center: [number, number, number];\n}\n\nexport function partitionMeshlets(meshlets: PartitionInput[], groupSize: number): number[][] {\n const count = meshlets.length;\n if (count <= groupSize) return [meshlets.map((_, i) => i)];\n\n // edge -> meshlets touching it\n const edgeOwners = new Map<number, number[]>();\n for (let i = 0; i < count; i++) {\n for (const e of meshlets[i].boundaryEdges) {\n const owners = edgeOwners.get(e);\n if (owners) {\n if (owners[owners.length - 1] !== i) owners.push(i);\n } else edgeOwners.set(e, [i]);\n }\n }\n\n // meshlet -> (neighbour -> shared edge count)\n const adjacency: Map<number, number>[] = Array.from({ length: count }, () => new Map());\n for (const owners of edgeOwners.values()) {\n for (let a = 0; a < owners.length; a++) {\n for (let b = a + 1; b < owners.length; b++) {\n const i = owners[a];\n const j = owners[b];\n adjacency[i].set(j, (adjacency[i].get(j) || 0) + 1);\n adjacency[j].set(i, (adjacency[j].get(i) || 0) + 1);\n }\n }\n }\n\n const order = mortonOrder(meshlets.map((m) => m.center));\n const assigned = new Uint8Array(count);\n const groups: number[][] = [];\n\n for (const seed of order) {\n if (assigned[seed]) continue;\n const group = [seed];\n assigned[seed] = 1;\n\n // frontier: candidate -> total shared edges with the group\n const frontier = new Map<number, number>();\n const addNeighbours = (m: number) => {\n for (const [n, shared] of adjacency[m]) {\n if (!assigned[n]) frontier.set(n, (frontier.get(n) || 0) + shared);\n }\n };\n addNeighbours(seed);\n\n while (group.length < groupSize && frontier.size > 0) {\n let best = -1;\n let bestScore = -1;\n let bestDist = Infinity;\n for (const [n, score] of frontier) {\n if (assigned[n]) continue;\n const d = dist2(meshlets[n].center, meshlets[seed].center);\n if (score > bestScore || (score === bestScore && d < bestDist)) {\n best = n;\n bestScore = score;\n bestDist = d;\n }\n }\n if (best < 0) break;\n frontier.delete(best);\n assigned[best] = 1;\n group.push(best);\n addNeighbours(best);\n }\n groups.push(group);\n }\n\n // Merge undersized groups with spatially close undersized groups.\n // `groups` is already in Morton order of their seeds.\n const result: number[][] = [];\n let pending: number[] = [];\n const minSize = Math.max(2, Math.floor(groupSize / 2));\n for (const group of groups) {\n if (group.length >= minSize) {\n result.push(group);\n continue;\n }\n if (pending.length + group.length > groupSize) {\n result.push(pending);\n pending = [];\n }\n pending.push(...group);\n }\n if (pending.length > 0) result.push(pending);\n return result;\n}\n\nfunction dist2(a: [number, number, number], b: [number, number, number]) {\n const dx = a[0] - b[0];\n const dy = a[1] - b[1];\n const dz = a[2] - b[2];\n return dx * dx + dy * dy + dz * dz;\n}\n\n/** Indices sorted along a 30-bit Morton curve of the given points. */\nexport function mortonOrder(points: [number, number, number][]): number[] {\n const min = [Infinity, Infinity, Infinity];\n const max = [-Infinity, -Infinity, -Infinity];\n for (const p of points) {\n for (let k = 0; k < 3; k++) {\n min[k] = Math.min(min[k], p[k]);\n max[k] = Math.max(max[k], p[k]);\n }\n }\n const extent = Math.max(max[0] - min[0], max[1] - min[1], max[2] - min[2]) || 1;\n const codes = points.map((p) => {\n const q = (k: number) => Math.min(1023, Math.max(0, Math.floor(((p[k] - min[k]) / extent) * 1023)));\n return part1By2(q(0)) | (part1By2(q(1)) << 1) | (part1By2(q(2)) << 2);\n });\n return points.map((_, i) => i).sort((a, b) => codes[a] - codes[b]);\n}\n\nfunction part1By2(x: number) {\n x &= 0x3ff;\n x = (x | (x << 16)) & 0x030000ff;\n x = (x | (x << 8)) & 0x0300f00f;\n x = (x | (x << 4)) & 0x030c30c3;\n x = (x | (x << 2)) & 0x09249249;\n return x;\n}\n","/**\n * Voxel proxies for coarse LODs, for foliage and other aggregate geometry.\n *\n * Triangle simplification breaks down on aggregate geometry such as a tree crown made of hundreds of\n * separate leaf clumps: below a few hundred triangles it can only delete or collapse whole clumps, so\n * the silhouette shrinks and the LOD error jumps. A voxel proxy keeps the volume instead: the mesh is\n * voxelized, gaps between clumps are closed, and a smooth closed surface is extracted (surface nets).\n * That surface is one connected shape, which simplifies gracefully to a handful of triangles.\n *\n * Every proxy vertex lies within about one cell of the original surface, and closing fills gaps of at most\n * two cells, so `VOXEL_ERROR_CELLS * cellSize` bounds how far the proxy deviates from the original.\n */\n\n/** Deviation of a proxy from the source mesh, in cells (surface offset plus closed gaps). */\nexport const VOXEL_ERROR_CELLS = 2;\n\nexport interface VoxelProxy {\n positions: Float32Array;\n normals: Float32Array;\n colors: Float32Array | null;\n /** UV of a representative source sample near each vertex (null when the source has no UVs). */\n uvs: Float32Array | null;\n indices: Uint32Array;\n cellSize: number;\n}\n\n/**\n * Voxelizes the triangles `indices` of a mesh with `resolution` cells along its longest side and returns\n * a closed, smooth surface around the occupied volume (null if the mesh is empty).\n * With `uvs`, each proxy vertex takes the UV of the first source sample in its cell's voxels, so textured\n * geometry keeps plausible colors at a distance (UVs cannot be averaged across islands).\n */\nexport function buildVoxelProxy(\n positions: Float32Array,\n colors: Float32Array | null | undefined,\n indices: Uint32Array,\n resolution: number,\n uvs?: Float32Array | null\n): VoxelProxy | null {\n if (indices.length === 0) return null;\n const min = [Infinity, Infinity, Infinity];\n const max = [-Infinity, -Infinity, -Infinity];\n for (let i = 0; i < indices.length; i++) {\n const o = indices[i] * 3;\n for (let k = 0; k < 3; k++) {\n min[k] = Math.min(min[k], positions[o + k]);\n max[k] = Math.max(max[k], positions[o + k]);\n }\n }\n const extent = Math.max(max[0] - min[0], max[1] - min[1], max[2] - min[2]);\n if (!(extent > 0)) return null;\n const cell = extent / resolution;\n // Samples sit at cell centers; 3 cells of padding keep the closed surface away from the grid border.\n const PAD = 3;\n const n = [0, 1, 2].map((k) => Math.ceil((max[k] - min[k]) / cell) + 1 + PAD * 2);\n const origin = [0, 1, 2].map((k) => min[k] - PAD * cell);\n const [nx, ny, nz] = n;\n const sx = 1;\n const sy = nx;\n const sz = nx * ny;\n const total = nx * ny * nz;\n\n // ---- 1. occupancy (+ color) by sampling every triangle at half-cell spacing ----\n const occupied = new Uint8Array(total);\n const colorSum = colors ? new Float32Array(total * 3) : null;\n const colorCount = colors ? new Uint32Array(total) : null;\n // First UV sampled in each voxel (NaN: none yet).\n const voxelUv = uvs ? new Float32Array(total * 2).fill(NaN) : null;\n let sampleU = 0;\n let sampleV = 0;\n const mark = (x: number, y: number, z: number, r: number, g: number, b: number) => {\n const i = Math.floor((x - origin[0]) / cell) * sx + Math.floor((y - origin[1]) / cell) * sy + Math.floor((z - origin[2]) / cell) * sz;\n occupied[i] = 1;\n if (voxelUv && Number.isNaN(voxelUv[i * 2])) {\n voxelUv[i * 2] = sampleU;\n voxelUv[i * 2 + 1] = sampleV;\n }\n if (colorSum) {\n colorSum[i * 3] += r;\n colorSum[i * 3 + 1] += g;\n colorSum[i * 3 + 2] += b;\n colorCount![i]++;\n }\n };\n for (let t = 0; t < indices.length; t += 3) {\n const a = indices[t] * 3;\n const b = indices[t + 1] * 3;\n const c = indices[t + 2] * 3;\n const longest = Math.max(dist(positions, a, b), dist(positions, b, c), dist(positions, c, a));\n const steps = Math.max(1, Math.ceil(longest / (cell * 0.5)));\n for (let i = 0; i <= steps; i++) {\n for (let j = 0; j <= steps - i; j++) {\n const u = i / steps;\n const v = j / steps;\n const w = 1 - u - v;\n const x = positions[a] * w + positions[b] * u + positions[c] * v;\n const y = positions[a + 1] * w + positions[b + 1] * u + positions[c + 1] * v;\n const z = positions[a + 2] * w + positions[b + 2] * u + positions[c + 2] * v;\n if (uvs) {\n const ta = indices[t] * 2;\n const tb = indices[t + 1] * 2;\n const tc = indices[t + 2] * 2;\n sampleU = uvs[ta] * w + uvs[tb] * u + uvs[tc] * v;\n sampleV = uvs[ta + 1] * w + uvs[tb + 1] * u + uvs[tc + 1] * v;\n }\n if (colors) {\n mark(\n x,\n y,\n z,\n colors[a] * w + colors[b] * u + colors[c] * v,\n colors[a + 1] * w + colors[b + 1] * u + colors[c + 1] * v,\n colors[a + 2] * w + colors[b + 2] * u + colors[c + 2] * v\n );\n } else mark(x, y, z, 0, 0, 0);\n }\n }\n }\n\n // ---- 2. morphological closing (dilate, then erode) fuses clumps into one volume ----\n const closed = erode(dilate(occupied, n), n);\n\n // ---- 3. smooth field: 3x3x3 box blur of the occupancy, iso level 0.5 ----\n const field = new Float32Array(total);\n for (let i = 0; i < total; i++) field[i] = closed[i];\n blurAxis(field, n, sx, nx);\n blurAxis(field, n, sy, ny);\n blurAxis(field, n, sz, nz);\n const ISO = 0.5;\n\n // ---- 4. surface nets: one vertex per cell crossing the iso surface, one quad per crossing edge ----\n const cellsX = nx - 1;\n const cellsY = ny - 1;\n const cellsZ = nz - 1;\n const cellVertex = new Int32Array(cellsX * cellsY * cellsZ).fill(-1);\n const outPositions: number[] = [];\n const outNormals: number[] = [];\n const outColors: number[] = [];\n const outUvs: number[] = [];\n const corner = new Float32Array(8);\n for (let z = 0; z < cellsZ; z++) {\n for (let y = 0; y < cellsY; y++) {\n for (let x = 0; x < cellsX; x++) {\n const base = x * sx + y * sy + z * sz;\n let inside = 0;\n for (let c = 0; c < 8; c++) {\n corner[c] = field[base + (c & 1) * sx + ((c >> 1) & 1) * sy + ((c >> 2) & 1) * sz];\n if (corner[c] >= ISO) inside++;\n }\n if (inside === 0 || inside === 8) continue;\n // Vertex: mean of the iso crossings on the cell's 12 edges.\n let px = 0;\n let py = 0;\n let pz = 0;\n let crossings = 0;\n for (let c = 0; c < 8; c++) {\n for (const bit of [1, 2, 4]) {\n if (c & bit) continue;\n const d = c | bit;\n const f0 = corner[c];\n const f1 = corner[d];\n if (f0 >= ISO === f1 >= ISO) continue;\n const s = (ISO - f0) / (f1 - f0);\n px += (c & 1) + (bit === 1 ? s : 0);\n py += ((c >> 1) & 1) + (bit === 2 ? s : 0);\n pz += ((c >> 2) & 1) + (bit === 4 ? s : 0);\n crossings++;\n }\n }\n cellVertex[x + y * cellsX + z * cellsX * cellsY] = outPositions.length / 3;\n // Sample (i, j, k) sits at origin + (i + 0.5) * cell.\n outPositions.push(origin[0] + (x + 0.5 + px / crossings) * cell, origin[1] + (y + 0.5 + py / crossings) * cell, origin[2] + (z + 0.5 + pz / crossings) * cell);\n // Normal: the field decreases outward, so the outward normal is minus its gradient.\n const gx = corner[1] + corner[3] + corner[5] + corner[7] - corner[0] - corner[2] - corner[4] - corner[6];\n const gy = corner[2] + corner[3] + corner[6] + corner[7] - corner[0] - corner[1] - corner[4] - corner[5];\n const gz = corner[4] + corner[5] + corner[6] + corner[7] - corner[0] - corner[1] - corner[2] - corner[3];\n const len = Math.hypot(gx, gy, gz) || 1;\n outNormals.push(-gx / len, -gy / len, -gz / len);\n if (colorSum) {\n let r = 0;\n let g = 0;\n let b = 0;\n let count = 0;\n for (let c = 0; c < 8; c++) {\n const i = base + (c & 1) * sx + ((c >> 1) & 1) * sy + ((c >> 2) & 1) * sz;\n if (!colorCount![i]) continue;\n r += colorSum[i * 3];\n g += colorSum[i * 3 + 1];\n b += colorSum[i * 3 + 2];\n count += colorCount![i];\n }\n if (count) outColors.push(r / count, g / count, b / count);\n else outColors.push(NaN, NaN, NaN); // filled in below from neighbours\n }\n if (voxelUv) {\n let u = NaN;\n let v = NaN;\n for (let c = 0; c < 8 && Number.isNaN(u); c++) {\n const i = base + (c & 1) * sx + ((c >> 1) & 1) * sy + ((c >> 2) & 1) * sz;\n u = voxelUv[i * 2];\n v = voxelUv[i * 2 + 1];\n }\n outUvs.push(u, v); // NaN: filled in below from neighbours\n }\n }\n }\n }\n\n const outIndices: number[] = [];\n const cellIndex = (x: number, y: number, z: number) => cellVertex[x + y * cellsX + z * cellsX * cellsY];\n const quad = (a: number, b: number, c: number, d: number, nx_: number, ny_: number, nz_: number) => {\n // Orient so the face normal agrees with the outward direction of the crossing edge.\n const ux = outPositions[c * 3] - outPositions[a * 3];\n const uy = outPositions[c * 3 + 1] - outPositions[a * 3 + 1];\n const uz = outPositions[c * 3 + 2] - outPositions[a * 3 + 2];\n const vx = outPositions[d * 3] - outPositions[b * 3];\n const vy = outPositions[d * 3 + 1] - outPositions[b * 3 + 1];\n const vz = outPositions[d * 3 + 2] - outPositions[b * 3 + 2];\n const cx = uy * vz - uz * vy;\n const cy = uz * vx - ux * vz;\n const cz = ux * vy - uy * vx;\n if (cx * nx_ + cy * ny_ + cz * nz_ >= 0) outIndices.push(a, b, c, a, c, d);\n else outIndices.push(a, c, b, a, d, c);\n };\n for (let z = 1; z < nz - 1; z++) {\n for (let y = 1; y < ny - 1; y++) {\n for (let x = 1; x < nx - 1; x++) {\n const i = x * sx + y * sy + z * sz;\n const here = field[i] >= ISO;\n // Edge to +x: the four cells around it share x and span y-1..y, z-1..z.\n if (here !== field[i + sx] >= ISO) {\n const s = here ? 1 : -1;\n quad(cellIndex(x, y - 1, z - 1), cellIndex(x, y, z - 1), cellIndex(x, y, z), cellIndex(x, y - 1, z), s, 0, 0);\n }\n if (here !== field[i + sy] >= ISO) {\n const s = here ? 1 : -1;\n quad(cellIndex(x - 1, y, z - 1), cellIndex(x, y, z - 1), cellIndex(x, y, z), cellIndex(x - 1, y, z), 0, s, 0);\n }\n if (here !== field[i + sz] >= ISO) {\n const s = here ? 1 : -1;\n quad(cellIndex(x - 1, y - 1, z), cellIndex(x, y - 1, z), cellIndex(x, y, z), cellIndex(x - 1, y, z), 0, 0, s);\n }\n }\n }\n }\n if (outIndices.length === 0) return null;\n\n let proxyColors: Float32Array | null = null;\n if (colorSum) {\n proxyColors = Float32Array.from(outColors);\n // Vertices of cells with no colored sample (volume added by closing) take the mean of their triangles' others.\n fillMissing(proxyColors, outIndices, 3);\n }\n let proxyUvs: Float32Array | null = null;\n if (voxelUv) {\n proxyUvs = Float32Array.from(outUvs);\n fillMissing(proxyUvs, outIndices, 2);\n }\n return {\n positions: Float32Array.from(outPositions),\n normals: Float32Array.from(outNormals),\n colors: proxyColors,\n uvs: proxyUvs,\n indices: Uint32Array.from(outIndices),\n cellSize: cell,\n };\n}\n\nfunction dist(p: Float32Array, a: number, b: number) {\n return Math.hypot(p[a] - p[b], p[a + 1] - p[b + 1], p[a + 2] - p[b + 2]);\n}\n\n/** 3x3x3 max (26-neighbourhood), separable per axis. */\nfunction dilate(src: Uint8Array, n: number[]) {\n let a = src;\n for (let axis = 0; axis < 3; axis++) a = morph(a, n, axis, 1);\n return a;\n}\n\n/** 3x3x3 min, separable per axis. */\nfunction erode(src: Uint8Array, n: number[]) {\n let a = src;\n for (let axis = 0; axis < 3; axis++) a = morph(a, n, axis, 0);\n return a;\n}\n\nfunction morph(src: Uint8Array, n: number[], axis: number, grow: number) {\n const [nx, ny, nz] = n;\n const stride = axis === 0 ? 1 : axis === 1 ? nx : nx * ny;\n const size = n[axis];\n const out = new Uint8Array(src.length);\n for (let z = 0; z < nz; z++) {\n for (let y = 0; y < ny; y++) {\n for (let x = 0; x < nx; x++) {\n const i = x + y * nx + z * nx * ny;\n const c = axis === 0 ? x : axis === 1 ? y : z;\n const prev = c > 0 ? src[i - stride] : 0;\n const next = c < size - 1 ? src[i + stride] : 0;\n out[i] = grow ? src[i] | prev | next : src[i] & prev & next;\n }\n }\n }\n return out;\n}\n\n/** In-place 3-tap box blur along one axis (borders treated as empty). */\nfunction blurAxis(field: Float32Array, n: number[], stride: number, size: number) {\n const [nx, ny, nz] = n;\n const line = new Float32Array(size);\n const lines = (nx * ny * nz) / size;\n // Walk every line along this axis: its first sample index enumerates the other two axes.\n for (let l = 0; l < lines; l++) {\n let start: number;\n if (stride === 1) start = l * nx;\n else if (stride === nx) start = (l % nx) + Math.floor(l / nx) * nx * ny;\n else start = l;\n for (let k = 0; k < size; k++) line[k] = field[start + k * stride];\n for (let k = 0; k < size; k++) {\n const a = k > 0 ? line[k - 1] : 0;\n const b = k < size - 1 ? line[k + 1] : 0;\n field[start + k * stride] = (a + line[k] + b) / 3;\n }\n }\n}\n\n/** Fills NaN entries (`size` floats per vertex) with the mean of their triangles' known neighbours. */\nfunction fillMissing(values: Float32Array, indices: number[], size: number) {\n const count = values.length / size;\n for (let pass = 0; pass < 8; pass++) {\n let missing = 0;\n const sum = new Float32Array(count * size);\n const hits = new Uint32Array(count);\n for (let t = 0; t < indices.length; t += 3) {\n for (let k = 0; k < 3; k++) {\n const v = indices[t + k];\n if (!Number.isNaN(values[v * size])) continue;\n for (let m = 1; m < 3; m++) {\n const u = indices[t + ((k + m) % 3)];\n if (Number.isNaN(values[u * size])) continue;\n for (let c = 0; c < size; c++) sum[v * size + c] += values[u * size + c];\n hits[v]++;\n }\n }\n }\n for (let v = 0; v < count; v++) {\n if (!Number.isNaN(values[v * size])) continue;\n if (hits[v]) {\n for (let c = 0; c < size; c++) values[v * size + c] = sum[v * size + c] / hits[v];\n } else missing++;\n }\n if (!missing) return;\n }\n for (let i = 0; i < values.length; i++) if (Number.isNaN(values[i])) values[i] = 0.5;\n}\n","/**\n * Builds the virtual-geometry meshlet LOD DAG for a single mesh.\n *\n * Ported from nanite-webgpu (MIT, Marcin Matuszczyk) `src/meshPreprocessing`,\n * using the npm `meshoptimizer` build instead of custom WASM, a JS partitioner\n * instead of METIS, and meshoptimizer clusterlod-style monotonic LOD bounds.\n *\n * Per level: partition meshlets into groups -> merge each group -> simplify to\n * ~50% with locked group borders -> split back into meshlets. All meshlets index\n * the same (original) vertex buffer, so normals/UVs survive simplification.\n */\nimport { MeshoptClusterizer, MeshoptSimplifier, type SimplifierFlags } from 'meshoptimizer';\nimport {\n ERROR_INFINITY,\n MAX_MESHLET_TRIANGLES,\n MAX_MESHLET_VERTICES,\n MESHLET_BOUNDS_STRIDE,\n MESHLET_INFO_STRIDE,\n} from '../constants.js';\nimport { partitionMeshlets } from './partition.js';\nimport { buildVoxelProxy, VOXEL_ERROR_CELLS, type VoxelProxy } from './voxelProxy.js';\n\nexport interface VirtualMeshSource {\n /** xyz per vertex */\n positions: Float32Array;\n /** xyz per vertex */\n normals: Float32Array;\n /** Optional rgb per vertex, multiplied with the material color. */\n colors?: Float32Array;\n /** Optional uv per vertex (texture coordinates). Vertices on a UV seam must be separate vertices. */\n uvs?: Float32Array;\n indices: Uint32Array;\n}\n\nexport interface VirtualMeshBuildOptions {\n /** Meshlets per group before simplification. */\n groupSize?: number;\n maxLodLevels?: number;\n /** A group that keeps more than this fraction of its triangles stops refining (its meshlets become roots). */\n maxGroupKeepRatio?: number;\n /** Fraction of a group's triangles kept by its simplification (the per-level reduction factor). */\n simplifyRatio?: number;\n /** Stop when a whole level removed less than this fraction of triangles. */\n minLevelReduction?: number;\n /** Remove small disconnected components while simplifying (good for foliage). */\n prune?: boolean;\n /**\n * Keep simplifying below a single meshlet once the remaining roots form the whole mesh, so distant\n * instances can draw a handful of triangles (or nothing, with `prune`) instead of a full meshlet.\n */\n tailSimplify?: boolean;\n /** Stop the tail at this many triangles. */\n minRootTriangles?: number;\n /**\n * Let coarse LODs switch to voxel proxies when those are more accurate than simplified triangles\n * (foliage and other aggregate geometry; solid meshes keep their triangles). Default true.\n */\n voxelLods?: boolean;\n onProgress?: (fraction: number) => void | Promise<void>;\n}\n\nexport interface VirtualMeshData {\n positions: Float32Array;\n normals: Float32Array;\n colors: Float32Array | null;\n /** uv per vertex, or null when the source had none. */\n uvs: Float32Array | null;\n /** Concatenated meshlet triangle lists, indexing `positions`. */\n indices: Uint32Array;\n meshletCount: number;\n /**\n * 4 x vec4 per meshlet:\n * [0] LOD sphere (center, radius) - shared by all meshlets created from the same group\n * [1] parent LOD sphere (center, radius)\n * [2] (error, parentError, 0, 0) - object-space; parentError = ERROR_INFINITY for roots\n * [3] culling sphere (center, radius) - the meshlet's own geometry\n */\n meshletBounds: Float32Array;\n /**\n * uvec4 per meshlet: (triangleCount, firstIndex, lodLevel, vertexOffset).\n * `firstIndex / 3` is also the meshlet's first entry in `meshletTriangles`.\n */\n meshletInfo: Uint32Array;\n /** Global vertex ids, per meshlet, in meshlet-local order (`vertexOffset` indexes this). */\n meshletVertices: Uint32Array;\n /** One packed triangle per entry: three meshlet-local vertex ids in bits 0-7, 8-15, 16-23. */\n meshletTriangles: Uint32Array;\n /** Meshlets are sorted by LOD level. Per level: [firstMeshlet, meshletCount]. */\n levelRanges: Uint32Array;\n /** Per level: [smallest own error, largest parent error] in object space (parent may be ERROR_INFINITY). */\n levelErrors: Float32Array;\n /**\n * Per level: [largest own error, smallest parent error] in object space. Used by the fast path: if every\n * meshlet of a level passes the LOD test at the nearest distance (largest own error) and at the farthest\n * (smallest parent error), the level needs no per-meshlet test.\n */\n levelGuardErrors: Float32Array;\n /** Sphere enclosing every LOD and parent sphere: bounds the distances the LOD test can see. */\n lodBoundsSphere: [number, number, number, number];\n /** Sphere enclosing every meshlet's culling sphere (all LODs): if an instance sphere is inside the frustum, so are they. */\n cullBoundsSphere: [number, number, number, number];\n /**\n * DAG links, CSR form: meshlet i is replaced by coarser meshlets\n * `replacementIndices[replacementStart[i] .. replacementStart[i + 1]]`. Empty for coarsest meshlets.\n */\n replacementStart: Uint32Array;\n replacementIndices: Uint32Array;\n /** Whole-object bounding sphere (center xyz, radius). */\n boundingSphere: [number, number, number, number];\n stats: {\n leafTriangles: number;\n leafMeshlets: number;\n rootTriangles: number;\n rootMeshlets: number;\n lodLevels: number;\n /** Coarse levels built from voxel proxies (see voxelProxy.ts). */\n voxelLevels: number;\n buildMs: number;\n };\n}\n\ntype Sphere = [number, number, number, number];\n\ninterface WipMeshlet {\n indices: Uint32Array;\n lodLevel: number;\n lodSphere: Sphere;\n error: number;\n parentSphere: Sphere;\n parentError: number;\n cullSphere: Sphere;\n boundaryEdges: number[];\n center: [number, number, number];\n /** Coarser meshlets that replaced this one (the outputs of the group it was merged into). */\n replacements: WipMeshlet[];\n /** Global vertex ids of this meshlet's unique vertices (meshlet-local order). */\n vertices: Uint32Array;\n /** Per triangle corner: index into `vertices` (0..MAX_MESHLET_VERTICES-1). */\n localTriangles: Uint8Array;\n}\n\nconst DEFAULTS = {\n groupSize: 12,\n maxLodLevels: 24,\n maxGroupKeepRatio: 0.9,\n simplifyRatio: 0.5,\n minLevelReduction: 0.03,\n prune: false,\n tailSimplify: true,\n minRootTriangles: 4,\n voxelLods: true,\n};\n\n/** The tail (whole-object simplification, where voxel proxies can take over) starts at this many triangles. */\nconst TAIL_START_TRIANGLES = 1024;\n/** Voxel proxy resolutions tried for each tail step (cells along the longest side). */\nconst VOXEL_RESOLUTIONS = [64, 32, 16, 8, 4];\n\nconst yieldToBrowser = () => new Promise<void>((r) => setTimeout(r, 0));\n\nexport async function buildVirtualMesh(src: VirtualMeshSource, options: VirtualMeshBuildOptions = {}): Promise<VirtualMeshData> {\n const opts = { ...DEFAULTS, ...options };\n const t0 = performance.now();\n await MeshoptClusterizer.ready;\n await MeshoptSimplifier.ready;\n\n // Vertex buffers grow when voxel proxies add their own vertices (appendVertices).\n let positions = src.positions;\n let normals = src.normals;\n let colors = src.colors ?? null;\n let uvs = src.uvs ?? null;\n // Vertices sharing a position (UV/normal seams) are the same vertex topologically.\n let weld = MeshoptSimplifier.generatePositionRemap(positions, 3);\n let voxelLevels = 0;\n const flags: SimplifierFlags[] = ['LockBorder', 'ErrorAbsolute'];\n if (opts.prune) flags.push('Prune');\n\n const all: WipMeshlet[] = [];\n const proxyCache = new Map<number, VoxelProxy | null>();\n const leafs = splitIntoMeshlets(src.indices, 0, null, 0);\n let current = leafs;\n let lastTriangles = countTriangles(current);\n let lodLevels = 1;\n const estimatedTotal = Math.max(1, leafs.length * 2);\n\n for (let level = 1; level <= opts.maxLodLevels && current.length > 1; level++) {\n // Small enough to treat as one piece: the tail takes over (and may switch to voxel proxies).\n if (opts.tailSimplify && lastTriangles <= TAIL_START_TRIANGLES) break;\n const groups = partitionMeshlets(current, opts.groupSize);\n const next: WipMeshlet[] = [];\n\n for (const groupIdx of groups) {\n const group = groupIdx.map((i) => current[i]);\n const merged = concatIndices(group);\n const local = compact(merged, positions);\n const target = Math.max(3, Math.floor((merged.length * opts.simplifyRatio) / 3) * 3);\n const [simplified, simplifyError] = MeshoptSimplifier.simplify(local.indices, local.positions, 3, target, 1e10, flags);\n\n if (simplified.length > merged.length * opts.maxGroupKeepRatio) {\n continue; // cannot reduce this group any further: its meshlets stay roots\n }\n\n // Monotonic LOD bounds: the group sphere encloses every child LOD sphere,\n // and the group error is never smaller than any child error.\n const lodSphere = enclosingSphere(group.map((m) => m.lodSphere));\n const childError = Math.max(...group.map((m) => m.error));\n // meshopt's error is vertex displacement; it misses silhouette loss (pruned parts, collapsed sheets).\n const shapeError = Math.max(simplifyError, extentShrink(local.indices, simplified, local.positions));\n const error = childError + Math.max(shapeError, 1e-7);\n for (const child of group) {\n child.parentSphere = lodSphere;\n child.parentError = error;\n }\n\n const globalIndices = new Uint32Array(simplified.length);\n for (let i = 0; i < simplified.length; i++) globalIndices[i] = local.toGlobal[simplified[i]];\n if (globalIndices.length > 0) {\n const outputs = splitIntoMeshlets(globalIndices, level, lodSphere, error);\n next.push(...outputs);\n for (const child of group) child.replacements = outputs;\n }\n }\n\n await opts.onProgress?.(Math.min(0.99, all.length / estimatedTotal));\n await yieldToBrowser();\n\n if (next.length === 0) break;\n lodLevels = level + 1;\n current = next;\n\n const triangles = countTriangles(current);\n if (triangles > lastTriangles * (1 - opts.minLevelReduction)) break;\n lastTriangles = triangles;\n }\n\n // Every root, not only the last level: groups that could not be reduced (e.g. UV-seam fans at a sphere's\n // poles) leave roots on earlier levels, and together the roots still cover the whole mesh.\n if (opts.tailSimplify) lodLevels = simplifyTail(all.filter((m) => m.parentError >= ERROR_INFINITY), lodLevels);\n\n await opts.onProgress?.(1);\n return pack({ positions, normals, colors: colors ?? undefined, uvs: uvs ?? undefined, indices: src.indices }, all, lodLevels, voxelLevels, performance.now() - t0);\n\n /** Adds vertices to the shared buffers and returns the index of the first one. */\n function appendVertices(p: Float32Array, n: Float32Array, c: Float32Array | null, uv: Float32Array | null) {\n const first = positions.length / 3;\n const count = p.length / 3;\n const grow = (a: Float32Array, b: Float32Array) => {\n const out = new Float32Array(a.length + b.length);\n out.set(a);\n out.set(b, a.length);\n return out;\n };\n positions = grow(positions, p);\n normals = grow(normals, n);\n if (colors) colors = grow(colors, c ?? new Float32Array(count * 3).fill(1));\n if (uvs) uvs = grow(uvs, uv ?? new Float32Array(count * 2));\n const w = new Uint32Array(weld.length + count);\n w.set(weld);\n for (let i = 0; i < count; i++) w[weld.length + i] = first + i;\n weld = w;\n return first;\n }\n\n /** Voxel proxies of the full-detail mesh, built on first use per resolution. */\n function voxelProxy(resolution: number): VoxelProxy | null {\n if (!proxyCache.has(resolution)) proxyCache.set(resolution, buildVoxelProxy(src.positions, src.colors, src.indices, resolution, src.uvs));\n return proxyCache.get(resolution)!;\n }\n\n /**\n * Below one meshlet: merge all remaining roots and keep halving. Borders can be unlocked because\n * the roots cover the whole mesh, so no other meshlet shares them.\n */\n function simplifyTail(roots: WipMeshlet[], levels: number): number {\n if (roots.length === 0) return levels;\n\n const tailFlags: SimplifierFlags[] = ['ErrorAbsolute'];\n if (opts.prune) tailFlags.push('Prune');\n let nodes = roots;\n let level = levels;\n for (; level < levels + opts.maxLodLevels; level++) {\n const merged = concatIndices(nodes);\n if (merged.length / 3 <= opts.minRootTriangles) break;\n const local = compact(merged, positions);\n const target = Math.max(3, Math.floor(merged.length / 2 / 3) * 3);\n const keepLimit = merged.length * opts.maxGroupKeepRatio;\n const childError = Math.max(...nodes.map((m) => m.error));\n\n // Candidate 1: simplify the current triangles (errors accumulate level over level).\n let [result, error] = MeshoptSimplifier.simplify(local.indices, local.positions, 3, target, 1e10, tailFlags);\n if (result.length > keepLimit) {\n // Topology blocks regular collapses (e.g. many disconnected parts): try sloppy simplification.\n const [sloppy, relativeError] = MeshoptSimplifier.simplifySloppy(local.indices, local.positions, 3, null, target, 1);\n if (sloppy.length < result.length) {\n result = sloppy;\n error = relativeError * MeshoptSimplifier.getScale(local.positions, 3);\n }\n }\n let globalIndices: Uint32Array | null = null;\n let parentError = Infinity;\n if (result.length <= keepLimit) {\n parentError = childError + Math.max(Math.max(error, extentShrink(local.indices, result, local.positions)), 1e-7);\n globalIndices = new Uint32Array(result.length);\n for (let i = 0; i < result.length; i++) globalIndices[i] = local.toGlobal[result[i]];\n }\n\n // Candidate 2: a simplified voxel proxy of the full-detail mesh. Its error is measured against the\n // original directly, so it does not accumulate. It wins when triangles can only shrink the shape.\n let voxel: { proxy: VoxelProxy; indices: Uint32Array } | null = null;\n if (opts.voxelLods) {\n for (const resolution of VOXEL_RESOLUTIONS) {\n const proxy = voxelProxy(resolution);\n if (!proxy) continue;\n const proxyTarget = Math.min(target, proxy.indices.length);\n const [simplified, proxyError] = MeshoptSimplifier.simplify(proxy.indices, proxy.positions, 3, proxyTarget, 1e10, ['ErrorAbsolute']);\n if (simplified.length === 0 || simplified.length > keepLimit) continue;\n const voxelError = Math.max(childError * (1 + 1e-5) + 1e-7, VOXEL_ERROR_CELLS * proxy.cellSize + proxyError);\n if (voxelError < parentError) {\n parentError = voxelError;\n voxel = { proxy, indices: simplified };\n }\n }\n }\n if (!Number.isFinite(parentError)) break;\n if (voxel) {\n // Copy the proxy vertices this level uses into the shared vertex buffers.\n const used = compact(voxel.indices, voxel.proxy.positions);\n const pick = (src: Float32Array, size = 3) => {\n const out = new Float32Array(used.toGlobal.length * size);\n used.toGlobal.forEach((v, i) => out.set(src.subarray(v * size, v * size + size), i * size));\n return out;\n };\n const { proxy } = voxel;\n const first = appendVertices(used.positions, pick(proxy.normals), proxy.colors ? pick(proxy.colors) : null, proxy.uvs ? pick(proxy.uvs, 2) : null);\n globalIndices = used.indices.map((i) => i + first);\n voxelLevels++;\n }\n\n const lodSphere = enclosingSphere(nodes.map((m) => m.lodSphere));\n for (const node of nodes) {\n node.parentSphere = lodSphere;\n node.parentError = parentError;\n }\n if (globalIndices!.length === 0) return level + 1; // pruned away entirely beyond this distance\n\n const outputs = splitIntoMeshlets(globalIndices!, level, lodSphere, parentError);\n for (const node of nodes) node.replacements = outputs;\n nodes = outputs;\n }\n return level;\n }\n\n ////////////////\n\n function splitIntoMeshlets(indices: Uint32Array, lodLevel: number, lodSphere: Sphere | null, error: number): WipMeshlet[] {\n const local = compact(indices, positions);\n const built = MeshoptClusterizer.buildMeshlets(local.indices, local.positions, 3, MAX_MESHLET_VERTICES, MAX_MESHLET_TRIANGLES, 0);\n const result: WipMeshlet[] = [];\n\n for (let m = 0; m < built.meshletCount; m++) {\n const vertexOffset = built.meshlets[m * 4 + 0];\n const triangleOffset = built.meshlets[m * 4 + 1];\n const vertexCount = built.meshlets[m * 4 + 2];\n const triangleCount = built.meshlets[m * 4 + 3];\n const vertices = new Uint32Array(vertexCount);\n for (let v = 0; v < vertexCount; v++) vertices[v] = local.toGlobal[built.vertices[vertexOffset + v]];\n const localTriangles = built.triangles.slice(triangleOffset, triangleOffset + triangleCount * 3);\n const meshletIndices = new Uint32Array(triangleCount * 3);\n for (let i = 0; i < triangleCount * 3; i++) meshletIndices[i] = vertices[localTriangles[i]];\n\n const cullSphere = boundingSphere(meshletIndices, positions);\n const meshlet: WipMeshlet = {\n indices: meshletIndices,\n lodLevel,\n lodSphere: lodSphere ?? cullSphere,\n error,\n parentSphere: [0, 0, 0, 0],\n parentError: ERROR_INFINITY,\n cullSphere,\n boundaryEdges: findBoundaryEdges(meshletIndices, weld),\n center: [cullSphere[0], cullSphere[1], cullSphere[2]],\n replacements: [],\n vertices,\n localTriangles,\n };\n result.push(meshlet);\n all.push(meshlet);\n }\n return result;\n }\n}\n\nfunction pack(src: VirtualMeshSource, unsorted: WipMeshlet[], lodLevels: number, voxelLevels: number, buildMs: number): VirtualMeshData {\n // Sorted by LOD level so every level is a contiguous range (used for per-instance level ranges).\n const all = [...unsorted].sort((a, b) => a.lodLevel - b.lodLevel);\n const meshletCount = all.length;\n const indices = new Uint32Array(all.reduce((acc, m) => acc + m.indices.length, 0));\n const meshletBounds = new Float32Array(meshletCount * MESHLET_BOUNDS_STRIDE);\n const meshletInfo = new Uint32Array(meshletCount * MESHLET_INFO_STRIDE);\n const indexOf = new Map<WipMeshlet, number>();\n all.forEach((m, i) => indexOf.set(m, i));\n const replacementStart = new Uint32Array(meshletCount + 1);\n const replacementIndices: number[] = [];\n all.forEach((m, i) => {\n replacementStart[i] = replacementIndices.length;\n for (const r of m.replacements) replacementIndices.push(indexOf.get(r)!);\n });\n replacementStart[meshletCount] = replacementIndices.length;\n\n const meshletVertices = new Uint32Array(all.reduce((acc, m) => acc + m.vertices.length, 0));\n const meshletTriangles = new Uint32Array(indices.length / 3);\n let firstIndex = 0;\n let vertexOffset = 0;\n const stats = { leafTriangles: 0, leafMeshlets: 0, rootTriangles: 0, rootMeshlets: 0, lodLevels, voxelLevels, buildMs };\n all.forEach((m, i) => {\n indices.set(m.indices, firstIndex);\n meshletVertices.set(m.vertices, vertexOffset);\n const t = m.localTriangles;\n for (let k = 0, tri = firstIndex / 3; k < t.length; k += 3, tri++) {\n meshletTriangles[tri] = t[k] | (t[k + 1] << 8) | (t[k + 2] << 16);\n }\n const b = i * MESHLET_BOUNDS_STRIDE;\n meshletBounds.set(m.lodSphere, b);\n meshletBounds.set(m.parentSphere, b + 4);\n meshletBounds[b + 8] = m.error;\n meshletBounds[b + 9] = m.parentError;\n meshletBounds.set(m.cullSphere, b + 12);\n\n const triangleCount = m.indices.length / 3;\n const o = i * MESHLET_INFO_STRIDE;\n meshletInfo[o + 0] = triangleCount;\n meshletInfo[o + 1] = firstIndex;\n meshletInfo[o + 2] = m.lodLevel;\n meshletInfo[o + 3] = vertexOffset;\n firstIndex += m.indices.length;\n vertexOffset += m.vertices.length;\n\n if (m.lodLevel === 0) {\n stats.leafTriangles += triangleCount;\n stats.leafMeshlets += 1;\n }\n if (m.parentError >= ERROR_INFINITY) {\n stats.rootTriangles += triangleCount;\n stats.rootMeshlets += 1;\n }\n });\n\n const whole = enclosingSphere(all.filter((m) => m.lodLevel === 0).map((m) => m.cullSphere));\n\n // Per level: [start, count] and [smallest own error, largest parent error] (object space).\n const levelCount = all.length ? all[all.length - 1].lodLevel + 1 : 0;\n const levelRanges = new Uint32Array(levelCount * 2);\n const levelErrors = new Float32Array(levelCount * 2);\n const levelGuardErrors = new Float32Array(levelCount * 2);\n for (let l = 0; l < levelCount; l++) {\n levelErrors[l * 2] = Infinity;\n levelErrors[l * 2 + 1] = 0;\n levelGuardErrors[l * 2] = 0;\n levelGuardErrors[l * 2 + 1] = Infinity;\n }\n all.forEach((m, i) => {\n const l = m.lodLevel;\n if (levelRanges[l * 2 + 1] === 0) levelRanges[l * 2] = i;\n levelRanges[l * 2 + 1]++;\n levelErrors[l * 2] = Math.min(levelErrors[l * 2], m.error);\n levelErrors[l * 2 + 1] = Math.max(levelErrors[l * 2 + 1], m.parentError);\n levelGuardErrors[l * 2] = Math.max(levelGuardErrors[l * 2], m.error);\n levelGuardErrors[l * 2 + 1] = Math.min(levelGuardErrors[l * 2 + 1], m.parentError);\n });\n // Encloses every sphere the LOD test can look at, so per-instance distance bounds stay conservative.\n const lodBoundsSphere = enclosingSphere([\n ...all.map((m) => m.lodSphere),\n ...all.filter((m) => m.parentError < ERROR_INFINITY).map((m) => m.parentSphere),\n ]);\n const cullBoundsSphere = enclosingSphere(all.map((m) => m.cullSphere));\n return {\n positions: src.positions,\n normals: src.normals,\n colors: src.colors ?? null,\n uvs: src.uvs ?? null,\n indices,\n meshletCount,\n meshletBounds,\n meshletInfo,\n replacementStart,\n replacementIndices: Uint32Array.from(replacementIndices),\n meshletVertices,\n meshletTriangles,\n levelRanges,\n levelErrors,\n levelGuardErrors,\n lodBoundsSphere,\n cullBoundsSphere,\n boundingSphere: whole,\n stats,\n };\n}\n\n/**\n * How far the simplified mesh's bounding box retreats from the original's, per side (max over the 6\n * sides). An empty result counts as losing the whole extent. Used as a floor for the LOD error so a\n * version that lost its silhouette is only drawn once that loss is below the pixel threshold.\n */\nexport function extentShrink(before: Uint32Array, after: Uint32Array, positions: Float32Array): number {\n const box = (indices: Uint32Array) => {\n const min = [Infinity, Infinity, Infinity];\n const max = [-Infinity, -Infinity, -Infinity];\n for (let i = 0; i < indices.length; i++) {\n const o = indices[i] * 3;\n for (let k = 0; k < 3; k++) {\n const v = positions[o + k];\n if (v < min[k]) min[k] = v;\n if (v > max[k]) max[k] = v;\n }\n }\n return { min, max };\n };\n const a = box(before);\n if (after.length === 0) return Math.max(a.max[0] - a.min[0], a.max[1] - a.min[1], a.max[2] - a.min[2]) / 2;\n const b = box(after);\n let shrink = 0;\n for (let k = 0; k < 3; k++) shrink = Math.max(shrink, b.min[k] - a.min[k], a.max[k] - b.max[k]);\n return shrink;\n}\n\n/**\n * Vertex id -> local id scratch for compact(), all -1 between calls. A typed-array lookup instead of a Map:\n * compact() runs several times per group, so this is one of the hottest loops of the build.\n */\nlet localOf = new Int32Array(0);\n\n/** Re-index a triangle subset into a compact local vertex buffer so meshopt only touches what it needs. */\nfunction compact(indices: Uint32Array, positions: Float32Array) {\n const vertexCount = positions.length / 3;\n if (localOf.length < vertexCount) localOf = new Int32Array(vertexCount).fill(-1);\n const toGlobalAll = new Uint32Array(indices.length);\n const localIndices = new Uint32Array(indices.length);\n let count = 0;\n for (let i = 0; i < indices.length; i++) {\n const g = indices[i];\n let l = localOf[g];\n if (l < 0) {\n l = count++;\n localOf[g] = l;\n toGlobalAll[l] = g;\n }\n localIndices[i] = l;\n }\n const toGlobal = toGlobalAll.subarray(0, count);\n const localPositions = new Float32Array(count * 3);\n for (let i = 0; i < count; i++) {\n const g = toGlobal[i];\n localOf[g] = -1;\n localPositions[i * 3 + 0] = positions[g * 3 + 0];\n localPositions[i * 3 + 1] = positions[g * 3 + 1];\n localPositions[i * 3 + 2] = positions[g * 3 + 2];\n }\n return { indices: localIndices, positions: localPositions, toGlobal };\n}\n\n/** Open-addressing scratch for findBoundaryEdges(): edge keys, use counts and insertion order. */\nlet edgeTableKeys = new Float64Array(1024);\nlet edgeTableCounts = new Uint8Array(1024);\nlet edgeOrder = new Int32Array(512);\n\n/** Edges used by exactly one triangle, keyed by position-welded vertex ids (in first-seen order). */\nfunction findBoundaryEdges(indices: Uint32Array, weld: Uint32Array): number[] {\n const edgeCount = indices.length;\n let size = edgeTableKeys.length;\n if (size < edgeCount * 2) {\n while (size < edgeCount * 2) size <<= 1;\n edgeTableKeys = new Float64Array(size);\n edgeTableCounts = new Uint8Array(size);\n edgeOrder = new Int32Array(size / 2);\n }\n const mask = size - 1;\n let inserted = 0;\n for (let t = 0; t < indices.length; t += 3) {\n for (let k = 0; k < 3; k++) {\n const a = weld[indices[t + k]];\n const b = weld[indices[t + ((k + 1) % 3)]];\n const key = edgeKey(a, b);\n let h = (Math.imul(a < b ? a : b, 0x9e3779b1) ^ Math.imul(a < b ? b : a, 0x85ebca6b)) & mask;\n while (edgeTableCounts[h] !== 0 && edgeTableKeys[h] !== key) h = (h + 1) & mask;\n if (edgeTableCounts[h] === 0) {\n edgeTableKeys[h] = key;\n edgeOrder[inserted++] = h;\n }\n if (edgeTableCounts[h] < 255) edgeTableCounts[h]++;\n }\n }\n const result: number[] = [];\n for (let i = 0; i < inserted; i++) {\n const h = edgeOrder[i];\n if (edgeTableCounts[h] === 1) result.push(edgeTableKeys[h]);\n edgeTableCounts[h] = 0;\n }\n return result;\n}\n\n/** Order-independent edge id. Safe while vertex ids stay below 2^26. */\nexport const edgeKey = (a: number, b: number) => (a < b ? a * 67108864 + b : b * 67108864 + a);\n\nfunction concatIndices(meshlets: WipMeshlet[]) {\n const result = new Uint32Array(meshlets.reduce((acc, m) => acc + m.indices.length, 0));\n let offset = 0;\n for (const m of meshlets) {\n result.set(m.indices, offset);\n offset += m.indices.length;\n }\n return result;\n}\n\nconst countTriangles = (meshlets: WipMeshlet[]) => meshlets.reduce((acc, m) => acc + m.indices.length / 3, 0);\n\nfunction boundingSphere(indices: Uint32Array, positions: Float32Array): Sphere {\n const min = [Infinity, Infinity, Infinity];\n const max = [-Infinity, -Infinity, -Infinity];\n for (let i = 0; i < indices.length; i++) {\n const o = indices[i] * 3;\n for (let k = 0; k < 3; k++) {\n const v = positions[o + k];\n if (v < min[k]) min[k] = v;\n if (v > max[k]) max[k] = v;\n }\n }\n const cx = (min[0] + max[0]) / 2;\n const cy = (min[1] + max[1]) / 2;\n const cz = (min[2] + max[2]) / 2;\n let r2 = 0;\n for (let i = 0; i < indices.length; i++) {\n const o = indices[i] * 3;\n const dx = positions[o] - cx;\n const dy = positions[o + 1] - cy;\n const dz = positions[o + 2] - cz;\n r2 = Math.max(r2, dx * dx + dy * dy + dz * dz);\n }\n return [cx, cy, cz, Math.sqrt(r2)];\n}\n\n/** Sphere enclosing all given spheres (meshoptimizer's computeSphereBounds), padded for float error. */\nfunction enclosingSphere(spheres: Sphere[]): Sphere {\n if (spheres.length === 1) return [...spheres[0]] as Sphere;\n const centers = new Float32Array(spheres.length * 3);\n const radii = new Float32Array(spheres.length);\n spheres.forEach((s, i) => {\n centers.set([s[0], s[1], s[2]], i * 3);\n radii[i] = s[3];\n });\n const b = MeshoptClusterizer.computeSphereBounds(centers, 3, radii, 1);\n let radius = b.radius;\n // guarantee containment regardless of the approximation used\n for (const s of spheres) {\n const d = Math.hypot(s[0] - b.centerX, s[1] - b.centerY, s[2] - b.centerZ) + s[3];\n radius = Math.max(radius, d);\n }\n return [b.centerX, b.centerY, b.centerZ, radius * 1.0001];\n}\n","/**\n * Binary container for `VirtualMeshData` (`.vgeo`, \"virtual geometry\").\n *\n * Layout (little-endian):\n * 0 magic 'VGEO'\n * 4 u32 format version\n * 8 u32 header byte length (UTF-8 JSON, then space-padded to 4 bytes)\n * 12 u32 checksum of everything after this 16-byte prefix\n * 16 JSON header\n * .. payload: one 4-byte aligned blob per typed-array field\n *\n * The header lists every typed-array field (name, array type, length, encoding, payload offset and size)\n * and carries every other field as JSON, so fields added to `VirtualMeshData` later are stored without\n * format changes. Compression is lossless: meshoptimizer's vertex and index codecs, optionally followed by\n * deflate, whichever is smallest per field. `indices` is not stored: it is rebuilt from the meshlet arrays.\n */\nimport { MeshoptDecoder, MeshoptEncoder } from 'meshoptimizer';\nimport { MESHLET_INFO_STRIDE } from '../constants.js';\nimport type { VirtualMeshData } from '../preprocess/buildVirtualMesh.js';\n\n/** Bumped whenever the container layout or an encoding changes; older readers reject newer files. */\nexport const VG_FORMAT_VERSION = 1;\n\nconst MAGIC = 0x4f454756; // 'VGEO' read as a little-endian u32\nconst PREFIX_BYTES = 16;\n\nexport interface VirtualMeshEncodeOptions {\n /** Store `indices` instead of rebuilding it from the meshlet arrays on decode. Default false. */\n keepIndices?: boolean;\n /** Lossless compression with meshoptimizer's codecs. Default true; false stores every array uncompressed. */\n compress?: boolean;\n /**\n * Also deflate fields where that makes them smaller (about 30% smaller files, about 2x slower decoding).\n * Default true; ignored where `CompressionStream` is unavailable. The IndexedDB cache turns it off.\n */\n deflate?: boolean;\n}\n\ntype Encoding = 'raw' | 'meshopt-vertex' | 'meshlet-triangles' | 'meshlet-indices';\n\ninterface FieldEntry {\n name: string;\n type: TypedArrayName;\n length: number;\n encoding: Encoding;\n /** Bytes per element group for 'meshopt-vertex'. */\n stride?: number;\n /** The encoded blob is additionally deflate-compressed. */\n deflate?: boolean;\n /** Payload-relative byte offset and size of the blob. */\n offset: number;\n byteLength: number;\n}\n\ninterface Header {\n generator: string;\n /** Every top-level key of the original object, in order. */\n keys: string[];\n fields: FieldEntry[];\n values: Record<string, unknown>;\n}\n\ntype AnyTypedArray =\n | Int8Array\n | Uint8Array\n | Uint8ClampedArray\n | Int16Array\n | Uint16Array\n | Int32Array\n | Uint32Array\n | Float32Array\n | Float64Array;\n\nconst TYPED_ARRAYS = {\n Int8Array,\n Uint8Array,\n Uint8ClampedArray,\n Int16Array,\n Uint16Array,\n Int32Array,\n Uint32Array,\n Float32Array,\n Float64Array,\n};\ntype TypedArrayName = keyof typeof TYPED_ARRAYS;\n\n/**\n * Per-field encoder hints, from measurements on the demo assets. `strides`: element groups (bytes) to try with\n * the vertex codec (unknown fields use their element size, at least 4). `deflateRaw`: also try deflate on the\n * uncompressed array (meshletBounds repeats whole spheres, which deflate finds and the vertex codec does not).\n */\nconst FIELD_HINTS: Record<string, { strides?: number[]; deflateRaw?: boolean }> = {\n positions: { strides: [12] },\n normals: { strides: [12] },\n colors: { strides: [12] },\n uvs: { strides: [8] },\n tangents: { strides: [16] },\n meshletBounds: { strides: [64], deflateRaw: true },\n meshletInfo: { strides: [16] },\n};\n\nexport class VirtualMeshFormatError extends Error {\n constructor(message: string) {\n super(`three-virtual-geometry: ${message}`);\n this.name = 'VirtualMeshFormatError';\n }\n}\n\nexport async function encodeVirtualMesh(data: VirtualMeshData, options: VirtualMeshEncodeOptions = {}): Promise<Uint8Array> {\n const compress = options.compress ?? true;\n if (compress) await MeshoptEncoder.ready;\n const record = data as unknown as Record<string, unknown>;\n const keys = Object.keys(record).filter((k) => record[k] !== undefined && typeof record[k] !== 'function');\n const fields: FieldEntry[] = [];\n const blobs: Uint8Array[] = [];\n const values: Record<string, unknown> = {};\n let offset = 0;\n\n for (const name of keys) {\n const value = record[name];\n if (!ArrayBuffer.isView(value)) {\n values[name] = value;\n continue;\n }\n const type = value.constructor.name as TypedArrayName;\n if (!(type in TYPED_ARRAYS)) throw new VirtualMeshFormatError(`cannot serialize field \"${name}\" of type ${type}`);\n const array = value as AnyTypedArray;\n let blob: Uint8Array;\n let entry: Omit<FieldEntry, 'offset' | 'byteLength'>;\n if (name === 'indices' && !options.keepIndices && indicesMatchMeshlets(data)) {\n entry = { name, type, length: array.length, encoding: 'meshlet-indices' };\n blob = new Uint8Array(0);\n } else if (compress) {\n ({ entry, blob } = await encodeField(name, type, array, data, options.deflate ?? true));\n } else {\n entry = { name, type, length: array.length, encoding: 'raw' };\n blob = bytesOf(array);\n }\n fields.push({ ...entry, offset, byteLength: blob.length });\n blobs.push(blob);\n offset += align4(blob.length);\n }\n\n const headerJson: Header = { generator: 'three-virtual-geometry', keys, fields, values };\n const headerBytes = new TextEncoder().encode(JSON.stringify(headerJson, jsonReplacer));\n const headerPadded = align4(headerBytes.length);\n const out = new Uint8Array(PREFIX_BYTES + headerPadded + offset);\n out.set(headerBytes, PREFIX_BYTES);\n out.fill(0x20, PREFIX_BYTES + headerBytes.length, PREFIX_BYTES + headerPadded);\n const payloadStart = PREFIX_BYTES + headerPadded;\n fields.forEach((f, i) => out.set(blobs[i], payloadStart + f.offset));\n const view = new DataView(out.buffer);\n view.setUint32(0, MAGIC, true);\n view.setUint32(4, VG_FORMAT_VERSION, true);\n view.setUint32(8, headerBytes.length, true);\n view.setUint32(12, checksum(out, PREFIX_BYTES), true);\n return out;\n}\n\nexport async function decodeVirtualMesh(input: ArrayBuffer | ArrayBufferView): Promise<VirtualMeshData> {\n let bytes = ArrayBuffer.isView(input) ? new Uint8Array(input.buffer, input.byteOffset, input.byteLength) : new Uint8Array(input);\n if (bytes.byteOffset % 4 !== 0) bytes = bytes.slice(); // checksum and payload views need 4-byte alignment\n const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);\n if (bytes.length < PREFIX_BYTES || view.getUint32(0, true) !== MAGIC) {\n throw new VirtualMeshFormatError('not a three-virtual-geometry geometry file (bad magic bytes)');\n }\n const version = view.getUint32(4, true);\n if (version !== VG_FORMAT_VERSION) {\n throw new VirtualMeshFormatError(`unsupported geometry format version ${version} (this build reads version ${VG_FORMAT_VERSION}); re-bake the file`);\n }\n const headerLength = view.getUint32(8, true);\n const payloadStart = PREFIX_BYTES + align4(headerLength);\n if (payloadStart > bytes.length || bytes.length % 4 !== 0) throw new VirtualMeshFormatError('geometry file is truncated');\n // Header and field bounds are checked before the checksum so truncation gets its own message.\n\n let header: Header;\n try {\n header = JSON.parse(new TextDecoder().decode(bytes.subarray(PREFIX_BYTES, PREFIX_BYTES + headerLength)), jsonReviver);\n } catch {\n throw new VirtualMeshFormatError('geometry file is corrupt or truncated (unreadable header)');\n }\n if (!header || !Array.isArray(header.fields) || !Array.isArray(header.keys) || typeof header.values !== 'object') {\n throw new VirtualMeshFormatError('geometry file is corrupt (malformed header)');\n }\n\n const payload = bytes.subarray(payloadStart);\n const arrays: Record<string, AnyTypedArray> = {};\n // Derived encodings read other fields, so they go last.\n const order = [...header.fields].sort((a, b) => rank(a.encoding) - rank(b.encoding));\n if (order.some((f) => f.encoding !== 'raw')) await MeshoptDecoder.ready;\n for (const field of order) {\n const Ctor = TYPED_ARRAYS[field.type];\n if (!Ctor || !Number.isInteger(field.length) || field.length < 0) throw new VirtualMeshFormatError(`geometry file is corrupt (field \"${field.name}\")`);\n if (field.offset % 4 !== 0 || field.offset + field.byteLength > payload.length) {\n throw new VirtualMeshFormatError(`geometry file is truncated (field \"${field.name}\")`);\n }\n }\n if (checksum(bytes, PREFIX_BYTES) !== view.getUint32(12, true)) throw new VirtualMeshFormatError('geometry file is corrupt (checksum mismatch)');\n const fail = (field: FieldEntry, e: unknown) =>\n e instanceof VirtualMeshFormatError ? e : new VirtualMeshFormatError(`geometry file is corrupt (field \"${field.name}\": ${(e as Error).message})`);\n // Inflate every deflated field at once (runs concurrently where the platform allows), then decode in order.\n const blobs = await Promise.all(\n order.map((f) => {\n const blob = payload.subarray(f.offset, f.offset + f.byteLength);\n return f.deflate ? inflate(blob).catch((e) => Promise.reject(fail(f, e))) : blob;\n })\n );\n for (let i = 0; i < order.length; i++) {\n try {\n arrays[order[i].name] = await decodeField({ ...order[i], deflate: false }, blobs[i], arrays);\n } catch (e) {\n throw fail(order[i], e);\n }\n }\n\n const result: Record<string, unknown> = {};\n for (const key of header.keys) result[key] = key in arrays ? arrays[key] : header.values[key];\n return result as unknown as VirtualMeshData;\n}\n\n/** Fetches and decodes a baked `.vgeo` file, or decodes bytes that are already in memory. */\nexport async function loadVirtualMesh(source: string | URL | ArrayBuffer | ArrayBufferView, init?: RequestInit): Promise<VirtualMeshData> {\n if (typeof source !== 'string' && !(source instanceof URL)) return decodeVirtualMesh(source);\n const response = await fetch(source, init);\n if (!response.ok) throw new Error(`three-virtual-geometry: failed to load ${source} (HTTP ${response.status})`);\n return decodeVirtualMesh(await response.arrayBuffer());\n}\n\n// ------------------------------------------------------------------ encoding\n\nasync function encodeField(name: string, type: TypedArrayName, array: AnyTypedArray, data: VirtualMeshData, useDeflate: boolean) {\n const raw = bytesOf(array);\n const base = { name, type, length: array.length };\n const hint = FIELD_HINTS[name] ?? {};\n const rawCandidate = { entry: { ...base, encoding: 'raw' as Encoding }, blob: raw };\n const candidates: { entry: Omit<FieldEntry, 'offset' | 'byteLength'>; blob: Uint8Array }[] = [rawCandidate];\n\n // Always much smaller than the vertex codec on meshlet triangles, so that one is only a fallback there.\n const triangles = name === 'meshletTriangles' && array instanceof Uint32Array ? encodeMeshletTriangles(array, data.meshletInfo) : null;\n if (triangles) candidates.push({ entry: { ...base, encoding: 'meshlet-triangles' }, blob: triangles });\n else if (raw.length % 4 === 0 && raw.length > 0) {\n const strides = (hint.strides ?? [Math.max(4, array.BYTES_PER_ELEMENT)]).filter((s) => s % 4 === 0 && s <= 256 && raw.length % s === 0);\n for (const stride of strides) {\n const blob = MeshoptEncoder.encodeVertexBufferLevel(raw, raw.length / stride, stride, 2, 1);\n candidates.push({ entry: { ...base, encoding: 'meshopt-vertex', stride }, blob });\n }\n }\n candidates.sort((a, b) => a.blob.length - b.blob.length);\n if (useDeflate && canDeflate() && raw.length >= 64) {\n // Deflate is slow to run on everything: try it on the best codec output (and on the raw data if hinted).\n const toDeflate = hint.deflateRaw && candidates[0] !== rawCandidate ? [candidates[0], rawCandidate] : [candidates[0]];\n for (const c of toDeflate) candidates.push({ entry: { ...c.entry, deflate: true }, blob: await deflate(c.blob) });\n candidates.sort((a, b) => a.blob.length - b.blob.length);\n }\n\n for (const c of candidates) {\n // The chosen encoding is decoded once and compared, so a stored file always round-trips exactly.\n const decoded = await decodeField({ ...c.entry, offset: 0, byteLength: c.blob.length }, c.blob, { meshletInfo: data.meshletInfo });\n if (sameBytes(bytesOf(decoded), raw)) return c;\n }\n return rawCandidate;\n}\n\n/**\n * Meshlet triangles as one index buffer over meshlet-vertex slots (vertexOffset + local id). Meshlet-local\n * ids are in first-use order, so that buffer is ideal input for the index codec. The codec may rotate the\n * corners of a triangle, so each triangle's rotation is stored too (2 bits) to keep the exact corner order.\n * Layout: u32 codec byte length, codec bytes (padded to 4), packed rotations.\n */\nfunction encodeMeshletTriangles(triangles: Uint32Array, meshletInfo: Uint32Array | undefined): Uint8Array | null {\n if (!(meshletInfo instanceof Uint32Array)) return null;\n const slots = new Uint32Array(triangles.length * 3);\n const covered = new Uint8Array(triangles.length);\n for (let m = 0; m < meshletInfo.length; m += MESHLET_INFO_STRIDE) {\n const count = meshletInfo[m];\n const first = meshletInfo[m + 1] / 3;\n const vertexOffset = meshletInfo[m + 3];\n if (first + count > triangles.length) return null;\n for (let t = first; t < first + count; t++) {\n const packed = triangles[t];\n if (covered[t] || packed >>> 24 !== 0) return null;\n covered[t] = 1;\n slots[t * 3] = vertexOffset + (packed & 255);\n slots[t * 3 + 1] = vertexOffset + ((packed >> 8) & 255);\n slots[t * 3 + 2] = vertexOffset + ((packed >> 16) & 255);\n }\n }\n if (!covered.every((c) => c === 1)) return null;\n\n const codec = MeshoptEncoder.encodeIndexBuffer(bytesOf(slots), slots.length, 4);\n const decoded = new Uint32Array(slots.length);\n MeshoptDecoder.decodeIndexBuffer(bytesOf(decoded), slots.length, 4, codec);\n const rotations = new Uint8Array(Math.ceil(triangles.length / 4));\n for (let t = 0; t < triangles.length; t++) {\n const a = slots[t * 3], b = slots[t * 3 + 1], c = slots[t * 3 + 2];\n const x = decoded[t * 3], y = decoded[t * 3 + 1], z = decoded[t * 3 + 2];\n let r: number;\n if (a === x && b === y && c === z) r = 0;\n else if (a === y && b === z && c === x) r = 1;\n else if (a === z && b === x && c === y) r = 2;\n else return null;\n rotations[t >> 2] |= r << ((t & 3) * 2);\n }\n const out = new Uint8Array(4 + align4(codec.length) + rotations.length);\n new DataView(out.buffer).setUint32(0, codec.length, true);\n out.set(codec, 4);\n out.set(rotations, 4 + align4(codec.length));\n return out;\n}\n\n/** True if `indices` is exactly what decoding rebuilds from meshletInfo / meshletVertices / meshletTriangles. */\nfunction indicesMatchMeshlets(data: VirtualMeshData): boolean {\n const { indices, meshletInfo, meshletVertices, meshletTriangles } = data;\n if (!(indices instanceof Uint32Array && meshletInfo instanceof Uint32Array && meshletVertices instanceof Uint32Array && meshletTriangles instanceof Uint32Array)) {\n return false;\n }\n try {\n return sameBytes(bytesOf(rebuildIndices(indices.length, meshletInfo, meshletVertices, meshletTriangles)), bytesOf(indices));\n } catch {\n return false;\n }\n}\n\n// ------------------------------------------------------------------ decoding\n\nconst rank = (e: Encoding) => (e === 'meshlet-triangles' ? 1 : e === 'meshlet-indices' ? 2 : 0);\n\nasync function decodeField(field: FieldEntry, blob: Uint8Array, arrays: Record<string, AnyTypedArray>): Promise<AnyTypedArray> {\n const Ctor = TYPED_ARRAYS[field.type];\n const out = new Ctor(field.length);\n const target = bytesOf(out);\n const src = field.deflate ? await inflate(blob) : blob;\n switch (field.encoding) {\n case 'raw':\n if (src.length !== target.length) throw new VirtualMeshFormatError(`geometry file is corrupt (field \"${field.name}\" has the wrong size)`);\n target.set(src);\n break;\n case 'meshopt-vertex': {\n const stride = field.stride ?? 0;\n if (stride <= 0 || stride % 4 !== 0 || target.length % stride !== 0) throw new VirtualMeshFormatError(`geometry file is corrupt (field \"${field.name}\" stride)`);\n MeshoptDecoder.decodeVertexBuffer(target, target.length / stride, stride, src);\n break;\n }\n case 'meshlet-triangles':\n decodeMeshletTriangles(out as Uint32Array, src, requireArray(arrays, 'meshletInfo', field.name));\n break;\n case 'meshlet-indices':\n out.set(\n rebuildIndices(\n field.length,\n requireArray(arrays, 'meshletInfo', field.name),\n requireArray(arrays, 'meshletVertices', field.name),\n requireArray(arrays, 'meshletTriangles', field.name)\n )\n );\n break;\n default:\n throw new VirtualMeshFormatError(`unknown encoding \"${field.encoding}\" for field \"${field.name}\"`);\n }\n return out;\n}\n\nfunction requireArray(arrays: Record<string, AnyTypedArray>, name: string, forField: string): Uint32Array {\n const a = arrays[name];\n if (!(a instanceof Uint32Array)) throw new VirtualMeshFormatError(`geometry file is corrupt (\"${forField}\" needs \"${name}\")`);\n return a;\n}\n\nfunction decodeMeshletTriangles(out: Uint32Array, blob: Uint8Array, meshletInfo: Uint32Array) {\n const codecLength = new DataView(blob.buffer, blob.byteOffset, blob.byteLength).getUint32(0, true);\n const rotationsStart = 4 + align4(codecLength);\n if (rotationsStart + Math.ceil(out.length / 4) > blob.length) throw new Error('truncated triangle data');\n const slots = new Uint32Array(out.length * 3);\n MeshoptDecoder.decodeIndexBuffer(bytesOf(slots), slots.length, 4, blob.subarray(4, 4 + codecLength));\n const rotations = blob.subarray(rotationsStart);\n for (let m = 0; m < meshletInfo.length; m += MESHLET_INFO_STRIDE) {\n const count = meshletInfo[m];\n const first = meshletInfo[m + 1] / 3;\n const vertexOffset = meshletInfo[m + 3];\n if (first + count > out.length) throw new Error('meshlet range out of bounds');\n for (let t = first; t < first + count; t++) {\n const r = (rotations[t >> 2] >> ((t & 3) * 2)) & 3;\n const x = slots[t * 3] - vertexOffset, y = slots[t * 3 + 1] - vertexOffset, z = slots[t * 3 + 2] - vertexOffset;\n const [a, b, c] = r === 0 ? [x, y, z] : r === 1 ? [y, z, x] : [z, x, y];\n if ((a | b | c) >>> 8 !== 0) throw new Error('meshlet-local vertex id out of range');\n out[t] = a | (b << 8) | (c << 16);\n }\n }\n}\n\n/** `indices[firstIndex + 3t + k]` = global vertex of corner k of the meshlet's triangle t. */\nfunction rebuildIndices(length: number, meshletInfo: Uint32Array, meshletVertices: Uint32Array, meshletTriangles: Uint32Array): Uint32Array {\n const indices = new Uint32Array(length);\n for (let m = 0; m < meshletInfo.length; m += MESHLET_INFO_STRIDE) {\n const count = meshletInfo[m];\n const first = meshletInfo[m + 1];\n const vertexOffset = meshletInfo[m + 3];\n if (first + count * 3 > length || first / 3 + count > meshletTriangles.length) throw new VirtualMeshFormatError('geometry file is corrupt (meshlet range out of bounds)');\n for (let t = 0; t < count; t++) {\n const packed = meshletTriangles[first / 3 + t];\n for (let k = 0; k < 3; k++) {\n const v = vertexOffset + ((packed >> (8 * k)) & 255);\n if (v >= meshletVertices.length) throw new VirtualMeshFormatError('geometry file is corrupt (meshlet vertex out of bounds)');\n indices[first + t * 3 + k] = meshletVertices[v];\n }\n }\n }\n return indices;\n}\n\n// ------------------------------------------------------------------ helpers\n\nconst align4 = (n: number) => (n + 3) & ~3;\n\nfunction bytesOf(a: ArrayBufferView): Uint8Array {\n return new Uint8Array(a.buffer, a.byteOffset, a.byteLength);\n}\n\nfunction sameBytes(a: Uint8Array, b: Uint8Array) {\n if (a.length !== b.length) return false;\n if (a.byteOffset % 4 === 0 && b.byteOffset % 4 === 0 && a.length % 4 === 0) {\n const x = new Uint32Array(a.buffer, a.byteOffset, a.length / 4);\n const y = new Uint32Array(b.buffer, b.byteOffset, b.length / 4);\n for (let i = 0; i < x.length; i++) if (x[i] !== y[i]) return false;\n return true;\n }\n for (let i = 0; i < a.length; i++) if (a[i] !== b[i]) return false;\n return true;\n}\n\n/** 32-bit multiplicative hash over the u32 words from `start` (catches truncation and bit rot, not tampering). */\nfunction checksum(bytes: Uint8Array, start: number): number {\n const words = new Uint32Array(bytes.buffer, bytes.byteOffset + start, (bytes.length - start) >> 2);\n let h = 0x811c9dc5 ^ words.length;\n for (let i = 0; i < words.length; i++) {\n h = Math.imul(h ^ words[i], 0x01000193);\n h ^= h >>> 15;\n }\n return h >>> 0;\n}\n\nconst canDeflate = () => typeof CompressionStream !== 'undefined' && typeof DecompressionStream !== 'undefined';\n\nasync function deflate(bytes: Uint8Array): Promise<Uint8Array> {\n const stream = new Blob([bytes as Uint8Array<ArrayBuffer>]).stream().pipeThrough(new CompressionStream('deflate-raw'));\n return new Uint8Array(await new Response(stream).arrayBuffer());\n}\n\nasync function inflate(bytes: Uint8Array): Promise<Uint8Array> {\n if (typeof DecompressionStream === 'undefined') throw new VirtualMeshFormatError('this environment cannot decompress the geometry file (no DecompressionStream)');\n const stream = new Blob([bytes as Uint8Array<ArrayBuffer>]).stream().pipeThrough(new DecompressionStream('deflate-raw'));\n return new Uint8Array(await new Response(stream).arrayBuffer());\n}\n\n/** JSON has no Infinity/NaN; error fields use them (e.g. root parent errors). */\nfunction jsonReplacer(key: string, value: unknown) {\n if (typeof value === 'number' && !Number.isFinite(value)) return { $number: String(value) };\n if (ArrayBuffer.isView(value)) throw new VirtualMeshFormatError(`typed array nested inside field \"${key}\" cannot be serialized; store it as a top-level field`);\n return value;\n}\n\nfunction jsonReviver(_key: string, value: unknown) {\n if (value && typeof value === 'object' && !Array.isArray(value)) {\n const keys = Object.keys(value);\n if (keys.length === 1 && keys[0] === '$number') return Number((value as { $number: string }).$number);\n }\n return value;\n}\n","/**\n * `buildVirtualMeshCached`: `buildVirtualMesh` behind a persistent IndexedDB cache, keyed by a SHA-256 of the\n * source arrays and build options. The first load builds and stores the encoded result; later loads decode\n * it. Any cache problem (no IndexedDB, private mode, quota, corrupt entry) falls back to building.\n */\nimport { buildVirtualMesh, type VirtualMeshBuildOptions, type VirtualMeshData, type VirtualMeshSource } from '../preprocess/buildVirtualMesh.js';\nimport { decodeVirtualMesh, encodeVirtualMesh, VG_FORMAT_VERSION } from './serialize.js';\n\n/**\n * Part of every cache key. Bump it whenever `buildVirtualMesh` produces different output for the same input\n * (algorithm or default changes), so stale cached builds are never returned.\n */\nexport const VG_BUILD_VERSION = 3;\n\nexport interface VirtualGeometryCacheOptions {\n /**\n * Fixed cache key instead of a content hash (skips hashing the source). You must change it whenever the\n * source mesh or build options change.\n */\n key?: string;\n /** 'indexeddb' (default) or false to always build. */\n store?: 'indexeddb' | false;\n}\n\nexport interface VirtualGeometryCachedBuildOptions extends VirtualMeshBuildOptions {\n cache?: VirtualGeometryCacheOptions;\n}\n\nconst DB_NAME = 'three-virtual-geometry-cache';\nconst DATA_STORE = 'meshes';\nconst META_STORE = 'meta';\n/** Least recently used entries are evicted above this total size. */\nconst MAX_CACHE_BYTES = 512 * 1024 * 1024;\nconst OPEN_TIMEOUT_MS = 3000;\n\ninterface MetaEntry {\n size: number;\n lastUsed: number;\n}\n\n/**\n * Same as `buildVirtualMesh`, plus a persistent cache. On a hit the build is skipped, `onProgress(1)` is still\n * called, and `stats.buildMs` reports the time this call took (hashing, lookup and decoding).\n */\nexport async function buildVirtualMeshCached(source: VirtualMeshSource, options: VirtualGeometryCachedBuildOptions = {}): Promise<VirtualMeshData> {\n const { cache, ...buildOptions } = options;\n if (cache?.store === false || !hasIndexedDb()) return buildVirtualMesh(source, buildOptions);\n\n const t0 = performance.now();\n const key = await virtualMeshCacheKey(source, buildOptions, cache?.key).catch(() => null);\n const db = key ? await openDb() : null;\n if (!db || !key) return buildVirtualMesh(source, buildOptions);\n\n const bytes = await readEntry(db, key);\n if (bytes) {\n try {\n const data = await decodeVirtualMesh(bytes);\n if (data.stats) data.stats.buildMs = performance.now() - t0;\n touchEntry(db, key);\n await buildOptions.onProgress?.(1);\n return data;\n } catch {\n deleteEntry(db, key); // unreadable (e.g. written by another format version): rebuild below\n }\n }\n\n const data = await buildVirtualMesh(source, buildOptions);\n try {\n // No deflate: the cache optimizes for decode speed (deflate saves ~30% space but doubles decode time).\n const encoded = await encodeVirtualMesh(data, { deflate: false });\n void writeEntry(db, key, encoded); // not awaited: the build result is ready, storing happens in the background\n } catch {\n // never fail a build because of the cache\n }\n return data;\n}\n\n/** Deletes every cached build. Resolves even if IndexedDB is unavailable. */\nexport async function clearVirtualMeshCache(): Promise<void> {\n if (!hasIndexedDb()) return;\n const db = await openDb();\n if (!db) return;\n await new Promise<void>((resolve) => {\n try {\n const tx = db.transaction([DATA_STORE, META_STORE], 'readwrite');\n tx.objectStore(DATA_STORE).clear();\n tx.objectStore(META_STORE).clear();\n tx.oncomplete = tx.onerror = tx.onabort = () => resolve();\n } catch {\n resolve();\n }\n });\n}\n\n// ------------------------------------------------------------------ key\n\n/** SHA-256 over every source field (typed arrays by content), the build options and the format versions. */\nexport async function virtualMeshCacheKey(source: VirtualMeshSource, options: VirtualMeshBuildOptions = {}, customKey?: string): Promise<string> {\n const versions = `v${VG_BUILD_VERSION}.${VG_FORMAT_VERSION}`;\n if (customKey !== undefined) return `${versions}:key:${customKey}`;\n const subtle = globalThis.crypto?.subtle;\n if (!subtle) throw new Error('crypto.subtle unavailable');\n\n const record = source as unknown as Record<string, unknown>;\n const names = Object.keys(record)\n .filter((k) => record[k] !== undefined && record[k] !== null)\n .sort();\n const describe: unknown[] = [];\n const parts: Promise<ArrayBuffer>[] = [];\n for (const name of names) {\n const value = record[name];\n if (ArrayBuffer.isView(value)) {\n describe.push([name, value.constructor.name, value.byteLength]);\n // Hashed per array, then combined: avoids concatenating hundreds of MB into one buffer.\n parts.push(subtle.digest('SHA-256', value as ArrayBufferView<ArrayBuffer>));\n } else {\n describe.push([name, value]);\n }\n }\n const optionEntries = Object.entries(options)\n .filter(([, v]) => v !== undefined && typeof v !== 'function')\n .sort(([a], [b]) => (a < b ? -1 : 1));\n const text = new TextEncoder().encode(JSON.stringify({ versions, source: describe, options: optionEntries }));\n const digests = await Promise.all(parts);\n const combined = new Uint8Array(text.length + digests.length * 32);\n combined.set(text);\n digests.forEach((d, i) => combined.set(new Uint8Array(d), text.length + i * 32));\n const hash = new Uint8Array(await subtle.digest('SHA-256', combined));\n return `${versions}:sha256:${Array.from(hash, (b) => b.toString(16).padStart(2, '0')).join('')}`;\n}\n\n// ------------------------------------------------------------------ IndexedDB\n\nfunction hasIndexedDb() {\n try {\n return typeof indexedDB !== 'undefined' && indexedDB !== null;\n } catch {\n return false; // some sandboxed iframes throw on access\n }\n}\n\nlet dbPromise: Promise<IDBDatabase | null> | null = null;\n\n/** Resolves to null instead of rejecting: no database just means no cache. */\nfunction openDb(): Promise<IDBDatabase | null> {\n dbPromise ??= new Promise<IDBDatabase | null>((resolve) => {\n const timer = setTimeout(() => resolve(null), OPEN_TIMEOUT_MS);\n const done = (db: IDBDatabase | null) => {\n clearTimeout(timer);\n resolve(db);\n };\n try {\n const request = indexedDB.open(DB_NAME, 1);\n request.onupgradeneeded = () => {\n const db = request.result;\n if (!db.objectStoreNames.contains(DATA_STORE)) db.createObjectStore(DATA_STORE);\n if (!db.objectStoreNames.contains(META_STORE)) db.createObjectStore(META_STORE);\n };\n request.onsuccess = () => {\n const db = request.result;\n // Another tab deleting or upgrading the database: let it, and stop caching in this one.\n db.onversionchange = () => {\n db.close();\n dbPromise = Promise.resolve(null);\n };\n done(db);\n };\n request.onerror = request.onblocked = () => done(null);\n } catch {\n done(null);\n }\n });\n return dbPromise;\n}\n\nfunction readEntry(db: IDBDatabase, key: string): Promise<Uint8Array | null> {\n return new Promise((resolve) => {\n try {\n const request = db.transaction(DATA_STORE, 'readonly').objectStore(DATA_STORE).get(key);\n request.onsuccess = () => {\n const value = request.result;\n resolve(value instanceof ArrayBuffer ? new Uint8Array(value) : value instanceof Uint8Array ? value : null);\n };\n request.onerror = () => resolve(null);\n } catch {\n resolve(null);\n }\n });\n}\n\nfunction writeEntry(db: IDBDatabase, key: string, bytes: Uint8Array): Promise<void> {\n return new Promise<void>((resolve) => {\n try {\n const tx = db.transaction([DATA_STORE, META_STORE], 'readwrite');\n tx.objectStore(DATA_STORE).put(bytes.buffer.byteLength === bytes.length ? bytes.buffer : bytes.slice().buffer, key);\n tx.objectStore(META_STORE).put({ size: bytes.length, lastUsed: Date.now() } satisfies MetaEntry, key);\n tx.oncomplete = () => resolve();\n tx.onerror = tx.onabort = () => resolve(); // e.g. QuotaExceededError\n } catch {\n resolve();\n }\n }).then(() => evict(db, key));\n}\n\nfunction touchEntry(db: IDBDatabase, key: string) {\n try {\n const tx = db.transaction(META_STORE, 'readwrite');\n const store = tx.objectStore(META_STORE);\n const request = store.get(key);\n request.onsuccess = () => {\n const meta = request.result as MetaEntry | undefined;\n if (meta) store.put({ ...meta, lastUsed: Date.now() }, key);\n };\n } catch {\n // only affects eviction order\n }\n}\n\nfunction deleteEntry(db: IDBDatabase, key: string) {\n try {\n const tx = db.transaction([DATA_STORE, META_STORE], 'readwrite');\n tx.objectStore(DATA_STORE).delete(key);\n tx.objectStore(META_STORE).delete(key);\n } catch {\n // a stale entry costs disk space only\n }\n}\n\n/** Drops least recently used entries (never `keep`) while the cache is over MAX_CACHE_BYTES. */\nfunction evict(db: IDBDatabase, keep: string): Promise<void> {\n return new Promise<void>((resolve) => {\n try {\n const tx = db.transaction([DATA_STORE, META_STORE], 'readwrite');\n const meta = tx.objectStore(META_STORE);\n const keysRequest = meta.getAllKeys();\n const valuesRequest = meta.getAll();\n valuesRequest.onsuccess = () => {\n const keys = keysRequest.result as string[];\n const entries = (valuesRequest.result as MetaEntry[]).map((m, i) => ({ key: keys[i], ...m }));\n let total = entries.reduce((acc, e) => acc + e.size, 0);\n entries.sort((a, b) => a.lastUsed - b.lastUsed);\n for (const e of entries) {\n if (total <= MAX_CACHE_BYTES) break;\n if (e.key === keep) continue;\n tx.objectStore(DATA_STORE).delete(e.key);\n meta.delete(e.key);\n total -= e.size;\n }\n };\n tx.oncomplete = tx.onerror = tx.onabort = () => resolve();\n } catch {\n resolve();\n }\n });\n}\n","import { ERROR_INFINITY, FAST_PATH_MARGIN, FAST_PATH_MAX_MESHLETS, MESHLET_BOUNDS_STRIDE } from '../constants.js';\nimport type { VirtualMeshData } from '../preprocess/buildVirtualMesh.js';\n\n/** Camera parameters the LOD test needs. Same values the GPU pass uses. */\nexport interface CutView {\n /** Column-major world-to-view matrix (camera.matrixWorldInverse.elements). */\n viewMatrix: ArrayLike<number>;\n /** projection[1][1] * viewportHeight / 2: converts view-space error to pixels. */\n projScale: number;\n near: number;\n /**\n * Uniform scale of the instance, applied to the sphere radii and errors as the GPU does. `viewMatrix`\n * must then include the instance's scale in its centers too (view * model). Default 1.\n */\n scale?: number;\n}\n\n/**\n * CPU reference for the GPU LOD selection (no frustum culling, identity model matrix).\n * A meshlet is in the cut when its own projected error is within `threshold` pixels and its\n * parent's projected error is not. Returns one flag per meshlet.\n *\n * Use it to test the DAG (see `verifyCutCoverage`) or to pick LODs on the CPU, e.g. for physics or AI.\n */\nexport function selectCut(data: VirtualMeshData, view: CutView, threshold: number): Uint8Array {\n const v = view.viewMatrix;\n const B = data.meshletBounds;\n const selected = new Uint8Array(data.meshletCount);\n\n const s = view.scale ?? 1;\n const projectedError = (cx: number, cy: number, cz: number, r: number, error: number) => {\n if (error >= ERROR_INFINITY * 0.5) return Infinity;\n const x = v[0] * cx + v[4] * cy + v[8] * cz + v[12];\n const y = v[1] * cx + v[5] * cy + v[9] * cz + v[13];\n const z = v[2] * cx + v[6] * cy + v[10] * cz + v[14];\n const distance = Math.max(Math.hypot(x, y, z) - r * s, view.near);\n return (error * s * view.projScale) / distance;\n };\n\n for (let i = 0; i < data.meshletCount; i++) {\n const b = i * MESHLET_BOUNDS_STRIDE;\n const own = projectedError(B[b], B[b + 1], B[b + 2], B[b + 3], B[b + 8]);\n const parent = projectedError(B[b + 4], B[b + 5], B[b + 6], B[b + 7], B[b + 9]);\n selected[i] = own <= threshold && parent > threshold ? 1 : 0;\n }\n return selected;\n}\n\n/**\n * Checks that a cut has no holes: every leaf meshlet (LOD 0) is covered by a selected meshlet on its\n * path to the coarsest level (itself or one of its replacements, recursively).\n * Returns the indices of uncovered leaves (empty array = valid cut).\n */\nexport function verifyCutCoverage(data: VirtualMeshData, selected: Uint8Array): number[] {\n const covered = new Int8Array(data.meshletCount).fill(-1); // -1 unknown, 0 no, 1 yes\n const { replacementStart: start, replacementIndices: list } = data;\n\n const isCovered = (i: number): boolean => {\n if (covered[i] !== -1) return covered[i] === 1;\n let result = selected[i] === 1;\n for (let k = start[i]; !result && k < start[i + 1]; k++) result = isCovered(list[k]);\n covered[i] = result ? 1 : 0;\n return result;\n };\n\n const holes: number[] = [];\n for (let i = 0; i < data.meshletCount; i++) {\n if (data.meshletInfo[i * 4 + 2] === 0 && !isCovered(i)) holes.push(i);\n }\n return holes;\n}\n\n/** Distance from the camera to the instance's LOD sphere, and the band [dMin, dMax] every LOD test distance falls in. */\nfunction lodDistanceBounds(data: VirtualMeshData, view: CutView): [number, number] {\n const v = view.viewMatrix;\n const [cx, cy, cz, r] = data.lodBoundsSphere;\n const x = v[0] * cx + v[4] * cy + v[8] * cz + v[12];\n const y = v[1] * cx + v[5] * cy + v[9] * cz + v[13];\n const z = v[2] * cx + v[6] * cy + v[10] * cz + v[14];\n const d = Math.hypot(x, y, z);\n const R = r * (view.scale ?? 1);\n return [Math.max(d - R, view.near), Math.max(d + R, view.near)];\n}\n\n/**\n * CPU reference for the GPU instance pass: the contiguous range of meshlets (sorted by LOD level)\n * that can possibly pass the LOD test for an instance, from distance bounds alone.\n *\n * Every LOD and parent sphere lies inside `lodBoundsSphere`, so the distance to any of them is within\n * [D - R, D + R]. A level can contribute only if its smallest own error could be within the threshold\n * at the farthest distance and its largest parent error could exceed it at the nearest.\n * Returns [start, end) or [0, 0] when nothing can be selected.\n */\nexport function instanceMeshletRange(data: VirtualMeshData, view: CutView, threshold: number): [number, number] {\n const [dMin, dMax] = lodDistanceBounds(data, view);\n\n const k = (view.scale ?? 1) * view.projScale;\n let lo = -1;\n let hi = -1;\n const levels = data.levelRanges.length / 2;\n for (let l = 0; l < levels; l++) {\n const minOwn = data.levelErrors[l * 2];\n const maxParent = data.levelErrors[l * 2 + 1];\n const ownPossible = (minOwn * k) / dMax <= threshold;\n const parentPossible = maxParent >= ERROR_INFINITY * 0.5 || (maxParent * k) / dMin > threshold;\n if (ownPossible && parentPossible) {\n if (lo < 0) lo = l;\n hi = l;\n }\n }\n if (lo < 0) return [0, 0];\n return [data.levelRanges[lo * 2], data.levelRanges[hi * 2] + data.levelRanges[hi * 2 + 1]];\n}\n\n/**\n * CPU reference for the GPU fast path of the instance pass. Returns the range [start, end) when every\n * meshlet in it is guaranteed to be selected by the LOD test, for any distance the instance can have, and\n * the range is at most FAST_PATH_MAX_MESHLETS long. Otherwise returns null (use the per-meshlet pass).\n *\n * Guarantee per level, over the distance band [dMin, dMax] of `instanceMeshletRange`:\n * - largest own error projects to <= threshold at dMin (its closest possible distance), and\n * - smallest parent error projects to > threshold at dMax (its farthest possible distance).\n * A small relative margin keeps float rounding on the GPU from flipping a borderline meshlet.\n * The caller must also check that the instance is fully inside the frustum (see `cullBoundsSphere`).\n */\nexport function instanceGuaranteedRange(data: VirtualMeshData, view: CutView, threshold: number): [number, number] | null {\n const [dMin, dMax] = lodDistanceBounds(data, view);\n const margin = FAST_PATH_MARGIN;\n const k = (view.scale ?? 1) * view.projScale;\n\n let lo = -1;\n let hi = -1;\n let possibleMeshlets = 0;\n let guaranteedMeshlets = 0;\n const levels = data.levelRanges.length / 2;\n for (let l = 0; l < levels; l++) {\n const minOwn = data.levelErrors[l * 2];\n const maxParent = data.levelErrors[l * 2 + 1];\n const ownPossible = (minOwn * k) / dMax <= threshold;\n const parentPossible = maxParent >= ERROR_INFINITY * 0.5 || (maxParent * k) / dMin > threshold;\n if (!ownPossible || !parentPossible) continue;\n if (lo < 0) lo = l;\n hi = l;\n const size = data.levelRanges[l * 2 + 1];\n possibleMeshlets += size;\n\n const maxOwn = data.levelGuardErrors[l * 2];\n const minParent = data.levelGuardErrors[l * 2 + 1];\n const ownSure = (maxOwn * k) / dMin <= threshold * (1 - margin);\n const parentSure = minParent >= ERROR_INFINITY * 0.5 || (minParent * k) / dMax > threshold * (1 + margin);\n if (ownSure && parentSure) guaranteedMeshlets += size;\n }\n if (lo < 0) return null;\n const start = data.levelRanges[lo * 2];\n const end = data.levelRanges[hi * 2] + data.levelRanges[hi * 2 + 1];\n // Possible levels must be contiguous (no impossible level inside the range) and all guaranteed.\n if (possibleMeshlets !== end - start || guaranteedMeshlets !== possibleMeshlets) return null;\n if (possibleMeshlets > FAST_PATH_MAX_MESHLETS) return null;\n return [start, end];\n}\n","/**\n * Texture coordinates for materials on a VirtualMesh.\n *\n * A VirtualMesh pulls its vertices from storage buffers, so its placeholder geometry has no `uv` attribute and\n * three's default texture lookups (`uv()`) would read nothing. The vertex stage writes the pulled UV into the\n * `vgUv` varying, and `bindVirtualGeometryTextures` points the material's textures at it.\n */\nimport * as THREE from 'three/webgpu';\nimport {\n bumpMap,\n context,\n float,\n mat3,\n materialColor,\n materialReference,\n negateOnBackSide,\n normalView,\n positionView,\n sqrt,\n texture,\n transformNormalToView,\n varyingProperty,\n vec3,\n vec4,\n} from 'three/tsl';\n\ntype Node = any; // eslint-disable-line @typescript-eslint/no-explicit-any\n\n/** Interpolated texture coordinates of the current fragment (vec2), for custom material nodes. */\nexport const vgUv = varyingProperty('vec2', 'vVgUv');\n\n/** Plain 2D textures sample `vgUv`; cube, 3D and environment lookups keep their own coordinates. */\nfunction getUV(node: Node): Node {\n if (node?.isTextureNode !== true || node.isCubeTextureNode || node.isTexture3DNode) return undefined;\n return vgUv;\n}\n\n/** Texture lookup at `vgUv`, with the texture's offset/repeat/rotation applied like three's own maps. */\nexport function vgTexture(map: THREE.Texture): Node {\n return (texture(map, vgUv) as Node).setUpdateMatrix(true);\n}\n\nconst TWO_CHANNEL_FORMATS: number[] = [THREE.RGFormat, THREE.RED_GREEN_RGTC2_Format, THREE.RG11_EAC_Format];\n\n/**\n * Normal map without precomputed tangents: the tangent frame comes from screen-space derivatives of the view\n * position and `vgUv` (same construction as three's derivative tangents, http://www.thetenthplanet.de/archives/1180).\n */\nexport function vgNormalMap(map: THREE.Texture, scale: Node, type: THREE.NormalMapTypes = THREE.TangentSpaceNormalMap): Node {\n const sample: Node = vgTexture(map);\n let n: Node = sample.xyz.mul(2).sub(1);\n if (TWO_CHANNEL_FORMATS.includes(map.format)) {\n const xy = sample.xy.mul(2).sub(1);\n n = vec3(xy, sqrt(float(1).sub(xy.dot(xy)).max(0)));\n }\n n = vec3(n.xy.mul(scale), n.z);\n // Object space is the VirtualMesh's space (world space): correct for instances without rotation.\n if (type === THREE.ObjectSpaceNormalMap) return transformNormalToView(n);\n\n const q0: Node = (positionView as Node).dFdx();\n const q1: Node = (positionView as Node).dFdy();\n const st0: Node = (vgUv as Node).dFdx();\n const st1: Node = (vgUv as Node).dFdy();\n const N: Node = normalView;\n const q1perp = q1.cross(N);\n const q0perp = N.cross(q0);\n const T = q1perp.mul(st0.x).add(q0perp.mul(st1.x));\n const B = q1perp.mul(st0.y).add(q0perp.mul(st1.y));\n const det = T.dot(T).max(B.dot(B));\n const s = det.equal(0).select(0, det.inverseSqrt());\n return (mat3(negateOnBackSide(T.mul(s)), negateOnBackSide(B.mul(s)), N) as Node).mul(n).normalize();\n}\n\n/**\n * Makes a material's textures sample `vgUv`. Called by VirtualMesh on the material it takes over.\n *\n * - `map` and `alphaMap` move into `colorNode` (and are cleared on the material): the shadow pass reads\n * `colorNode.a` for alpha-tested shadows, but would sample the material's `map` with the missing `uv()`.\n * - Normal, bump and clearcoat normal maps become explicit normal nodes, because three builds normals in a\n * context that ignores custom UVs.\n * - Every other texture lookup without explicit coordinates (roughness, metalness, emissive, AO, light,\n * clearcoat, sheen, transmission maps, textures in your own nodes, ...) gets `vgUv` through\n * `material.contextNode`. A `getUV` in your own `contextNode` takes precedence.\n *\n * Nodes the material already has are kept: only properties three would otherwise read implicitly are rewired.\n */\nexport function bindVirtualGeometryTextures(material: THREE.NodeMaterial) {\n const m = material as Node;\n if (!m.colorNode && (isTexture(m.map) || isTexture(m.alphaMap))) {\n // With `map` cleared below, materialColor is just the color uniform (live, like three's).\n let color: Node = vec4(materialColor as Node, 1);\n if (isTexture(m.map)) {\n const sample = vgTexture(m.map);\n color = vec4((materialColor as Node).mul(sample.rgb), sample.a);\n }\n if (isTexture(m.alphaMap)) color = vec4(color.rgb, color.a.mul(vgTexture(m.alphaMap).g));\n m.colorNode = color;\n m.map = null;\n m.alphaMap = null;\n }\n if (!m.normalNode) {\n if (isTexture(m.normalMap)) m.normalNode = vgNormalMap(m.normalMap, materialReference('normalScale', 'vec2'), m.normalMapType);\n else if (isTexture(m.bumpMap)) m.normalNode = bumpMap(vgTexture(m.bumpMap).r, materialReference('bumpScale', 'float'));\n }\n if (!m.clearcoatNormalNode && isTexture(m.clearcoatNormalMap)) {\n m.clearcoatNormalNode = vgNormalMap(m.clearcoatNormalMap, materialReference('clearcoatNormalScale', 'vec2'));\n }\n m.contextNode = m.contextNode ? context(m.contextNode, { getUV }) : context({ getUV });\n material.needsUpdate = true;\n}\n\nconst isTexture = (t: unknown): t is THREE.Texture => (t as THREE.Texture | null)?.isTexture === true;\n","/**\n * Shared GPU buffers and compute passes for many VirtualMeshes.\n *\n * Every mesh's vertices, meshlets, level table and instances are appended to one set of storage buffers, and one\n * fixed set of compute passes selects the cut for all of them. CPU cost, shader count and pipeline compilation\n * therefore do not grow with the number of unique meshes: a level with hundreds of different props costs the\n * same 12 dispatches per frame as a scene with one. Each mesh still gets its own indexed indirect draw (its own\n * material), into a region of the pool's shared index buffer laid out each frame by a prefix sum.\n *\n * Per frame (all on the GPU):\n * 0. reset - clears the counters.\n * 1. cells - one thread per cell (CELL_SIZE instances of one mesh, Morton-ordered): frustum, sub-pixel and\n * draw-distance tests on the cell's bounding sphere. Visible cells are appended to a list.\n * 2. instance - one workgroup per visible cell: per-instance tests, occlusion, then the LOD level range per\n * cut (camera and shadow). Instances whose few meshlets are all certain to pass emit them\n * directly (fast path); the others go to a work list.\n * 3. meshlet - one workgroup per work item: per-meshlet frustum/occlusion culling and the LOD test\n * `parentError > t && error <= t`. Selected meshlets get a draw slot and a range inside their\n * mesh's region of the index buffer.\n * 4. prefix - one thread: lays the meshes' regions out one after another and writes each mesh's draw args.\n * 5. expand - one workgroup per drawn meshlet: writes 3 indices per triangle. An index encodes\n * `drawSlot * 128 + meshletLocalVertex`; the material's positionNode decodes it and pulls the\n * vertex from storage buffers, so any three.js NodeMaterial works unchanged.\n *\n * A pool is bounded by WebGPU's storage-buffer binding size; VirtualGeometry opens another pool when one is full.\n * Buffers grow by reallocation (the nodes are rebuilt, and the pipelines recompiled in the background).\n *\n * Based on nanite-webgpu (MIT, Marcin Matuszczyk): cullMeshletsPass + rasterizeHwPass.\n */\nimport * as THREE from 'three/webgpu';\nimport {\n Fn,\n If,\n Loop,\n Return,\n atomicAdd,\n atomicLoad,\n atomicStore,\n bitcast,\n bool,\n dot,\n float,\n instanceIndex,\n length,\n localId,\n mat4,\n max,\n min,\n normalLocal,\n normalize,\n numWorkgroups,\n select,\n storage,\n uint,\n uniform,\n unpackUnorm2x16,\n uvec4,\n varyingProperty,\n vec3,\n vec4,\n vertexIndex,\n workgroupArray,\n workgroupBarrier,\n workgroupId,\n} from 'three/tsl';\nimport { ERROR_INFINITY, FAST_PATH_MARGIN, FAST_PATH_MAX_MESHLETS, MAX_MESHLET_VERTICES, MESHLET_BOUNDS_STRIDE, MESHLET_INFO_STRIDE } from '../constants.js';\nimport type { VirtualMeshData } from '../preprocess/buildVirtualMesh.js';\nimport type { VirtualGeometry } from './VirtualGeometry.js';\nimport { vgUv } from './vgMaterial.js';\n\nconst minNode = min as (a: unknown, b: unknown) => any; // eslint-disable-line @typescript-eslint/no-explicit-any\nconst maxNode = max as (a: unknown, b: unknown) => any; // eslint-disable-line @typescript-eslint/no-explicit-any\ntype Node = any; // TSL node typings are too strict for the graph code below; runtime is verified in the browser\n\n/** World-space normal of the current vertex, usable in material color/roughness nodes. */\nexport const vgWorldNormal = varyingProperty('vec3', 'vVgWorldNormal');\nexport const vgMeshletVarying = varyingProperty('float', 'vVgMeshlet');\nexport const vgLodVarying = varyingProperty('float', 'vVgLod');\nexport const vgInstanceVarying = varyingProperty('float', 'vVgInstance');\nexport const vgTintVarying = varyingProperty('vec3', 'vVgTint');\n\n/** Bits of an index used for the meshlet-local vertex; the rest is the draw slot. */\nexport const LOCAL_VERTEX_BITS = Math.ceil(Math.log2(MAX_MESHLET_VERTICES));\nconst LOCAL_VERTEX_MASK = (1 << LOCAL_VERTEX_BITS) - 1;\nconst MAX_DISPATCH = 65535;\n/** Instances per cell. A cell is a contiguous range of one mesh's Morton-sorted instances. */\nexport const CELL_SIZE = 128;\nconst CULL_GROUP = 64;\nconst MESHLET_GROUP = 64;\nconst EXPAND_GROUP = 64;\n/** Level-table entries cached in workgroup memory by the instance pass (2 vec4 per level). */\nconst MAX_LEVELS = 48;\n/** vec4s per mesh record in the mesh table. */\nconst MESH_STRIDE = 6;\n/** vec4s per instance: 4 matrix columns, then (tint rgb, mesh slot). */\nconst INSTANCE_STRIDE = 5;\n/** vec4s per cell: bounding sphere, then (max instance radius, mesh slot, first instance, instance count). */\nconst CELL_STRIDE = 2;\n/** Fraction of `maxDrawDistance` over which instances shrink to nothing before they are culled. */\nexport const DRAW_DISTANCE_FADE = 0.15;\n/** Stand-in for an infinite draw distance on the GPU. */\nexport const NO_DRAW_DISTANCE = 1e30;\n/** Global counters: [0] visible cells, [1] occluded instances, then CUT_COUNTERS per cut. */\nconst CUT_COUNTERS = 5;\nconst C_SELECTED = 0;\nconst C_DRAWN = 1;\nconst C_SURVIVED = 2;\nconst C_WORK = 3;\nconst C_REQUESTED = 4;\nconst PER_MESH_COUNTERS = 2 + 2 * CUT_COUNTERS;\n\nexport interface PoolCapacity {\n /** Max meshlets drawn per frame, per cut. */\n meshlets: number;\n /** Max triangles drawn per frame by the camera cut (its index buffer). */\n triangles: number;\n /** Max triangles drawn per frame into shadow maps. */\n shadowTriangles: number;\n}\n\n/** CPU-side record of one mesh's place in the pool. */\nexport interface PoolEntry {\n slot: number;\n data: VirtualMeshData;\n vertexBase: number;\n meshletBase: number;\n meshletVertexBase: number;\n triangleBase: number;\n levelBase: number;\n levelCount: number;\n instanceBase: number;\n instanceCount: number;\n cellBase: number;\n cellCount: number;\n uvScale: [number, number];\n uvOffset: [number, number];\n}\n\n/** Growable typed array with a GPU attribute; growth replaces the attribute (the pool then rebuilds its nodes). */\nclass GrowBuffer<T extends Float32Array | Uint32Array> {\n array: T;\n attribute: THREE.StorageBufferAttribute;\n used = 0;\n constructor(\n private readonly make: (n: number) => T,\n readonly itemSize: number,\n capacity: number,\n /** Largest capacity (items) whose binding stays under the pool's byte limit. */\n private readonly maxItems = Infinity\n ) {\n this.array = make(Math.max(1, capacity) * itemSize);\n this.attribute = new THREE.StorageBufferAttribute(this.array, itemSize);\n }\n get capacity() {\n return this.array.length / this.itemSize;\n }\n /** Reserves `count` items; returns the first, or -1 when the buffer must grow first. */\n reserve(count: number) {\n if (this.used + count > this.capacity) return -1;\n const first = this.used;\n this.used += count;\n return first;\n }\n /** Reallocates to hold at least `needed` items (keeps the contents). */\n grow(needed: number) {\n // Grow ahead (fewer rebuilds), but never past the binding limit: the pool checked that `needed` fits.\n const next = this.make(Math.min(Math.max(needed, Math.ceil(this.capacity * 1.6)), Math.max(needed, this.maxItems)) * this.itemSize);\n next.set(this.array);\n this.array = next;\n this.attribute = new THREE.StorageBufferAttribute(this.array, this.itemSize);\n }\n /** Marks items [first, first + count) for upload. */\n touch(first: number, count: number) {\n if (count <= 0) return;\n this.attribute.addUpdateRange(first * this.itemSize, count * this.itemSize);\n this.attribute.needsUpdate = true;\n }\n}\n\nconst f32 = (n: number) => new Float32Array(n);\nconst u32 = (n: number) => new Uint32Array(n);\n\nexport class GeometryPool {\n readonly entries: (PoolEntry | null)[] = [];\n /** Highest used mesh slot + 1 (the prefix pass loops over this many). */\n readonly meshSlots = uniform(0, 'uint');\n readonly cellCount = uniform(0, 'uint');\n readonly maxBytes: number;\n readonly capacity: PoolCapacity;\n\n // geometry\n readonly vertexData: GrowBuffer<Uint32Array>; // uvec4: position float bits xyz + octahedral normal\n readonly vertexAttrs: GrowBuffer<Uint32Array>; // uvec2: rgba8 color + uv (2 x unorm16 over the mesh's uv bounds)\n readonly meshletBounds: GrowBuffer<Float32Array>; // 4 x vec4 per meshlet\n readonly meshletInfo: GrowBuffer<Uint32Array>; // uvec4: triangleCount, firstIndex, lodLevel, vertexOffset (pool-global)\n readonly meshletVertices: GrowBuffer<Uint32Array>; // pool-global vertex ids\n readonly meshletTriangles: GrowBuffer<Uint32Array>; // 3 x u8 local ids\n // scene\n readonly meshTable: GrowBuffer<Float32Array>; // MESH_STRIDE vec4 per slot, then the level tables (2 vec4 per level)\n readonly instances: GrowBuffer<Float32Array>; // INSTANCE_STRIDE vec4 per instance\n readonly cells: GrowBuffer<Float32Array>; // CELL_STRIDE vec4 per cell\n private meshSlotCapacity: number;\n private levelUsed = 0;\n\n // per frame (rebuilt with the nodes)\n private countersAttribute!: THREE.StorageBufferAttribute;\n drawArgsAttribute!: THREE.IndirectStorageBufferAttribute;\n cameraIndex!: THREE.StorageBufferAttribute;\n shadowIndex!: THREE.StorageBufferAttribute;\n computeNodes: THREE.ComputeNode[] = [];\n positionNode: Node = null;\n /** Bumped on every rebuild: meshes re-point their geometry and material when it changes. */\n version = 0;\n private needsRebuild = true;\n private indexBuffersReady = false;\n pipelineState: 'none' | 'compiling' | 'ready' = 'none';\n /** The cut needs recomputing (camera moved, instances or settings changed). */\n dirty = true;\n /** True once a cut was computed (its camera index buffer can then serve as occluders). */\n hasCut = false;\n\n constructor(\n private readonly context: VirtualGeometry,\n capacity: PoolCapacity,\n maxBytes: number\n ) {\n this.capacity = capacity;\n this.maxBytes = maxBytes;\n this.meshSlotCapacity = 64;\n const limit = (bytesPerItem: number) => Math.floor(maxBytes / bytesPerItem);\n this.vertexData = new GrowBuffer(u32, 4, 1 << 16, limit(16));\n this.vertexAttrs = new GrowBuffer(u32, 2, 1 << 16, limit(8));\n this.meshletBounds = new GrowBuffer(f32, 16, 1 << 12, limit(64));\n this.meshletInfo = new GrowBuffer(u32, 4, 1 << 12, limit(16));\n this.meshletVertices = new GrowBuffer(u32, 1, 1 << 18, limit(4));\n this.meshletTriangles = new GrowBuffer(u32, 1, 1 << 18, limit(4));\n this.meshTable = new GrowBuffer(f32, 4, this.meshSlotCapacity * MESH_STRIDE + 1024, limit(16));\n this.meshTable.used = this.meshSlotCapacity * MESH_STRIDE;\n // In vec4s: whole instances only, and the work list (2 x 16 bytes per instance) stays smaller.\n this.instances = new GrowBuffer(f32, 4, 1 << 12, limit(16 * INSTANCE_STRIDE) * INSTANCE_STRIDE);\n this.cells = new GrowBuffer(f32, 4, 1 << 8, limit(16));\n }\n\n /** Bytes the geometry of `data` takes in this pool (the largest single binding is what must fit). */\n static bytesOf(data: VirtualMeshData) {\n return Math.max((data.positions.length / 3) * 16, data.meshletVertices.length * 4, data.meshletTriangles.length * 4, data.meshletCount * 64);\n }\n\n /** True when `data` (and `instanceCount` instances) still fit under the binding-size limit. */\n fits(data: VirtualMeshData, instanceCount: number) {\n const after = (used: number, add: number, bytesPerItem: number) => (used + add) * bytesPerItem <= this.maxBytes;\n return (\n after(this.vertexData.used, data.positions.length / 3, 16) &&\n after(this.meshletBounds.used, data.meshletCount, 64) &&\n after(this.meshletVertices.used, data.meshletVertices.length, 4) &&\n after(this.meshletTriangles.used, data.meshletTriangles.length, 4) &&\n after(this.instances.used, instanceCount * INSTANCE_STRIDE, 16)\n );\n }\n\n // ------------------------------------------------------------------ meshes\n\n /** Appends a mesh's geometry and instances. Returns its entry (`slot` is its index in the mesh table). */\n add(data: VirtualMeshData, matrices: Float32Array, colors: Float32Array | undefined, gpuToInput: Uint32Array): PoolEntry {\n let slot = this.entries.indexOf(null);\n if (slot === -1) slot = this.entries.length;\n if (slot >= this.meshSlotCapacity) this.growMeshSlots(slot + 1);\n\n const vertexCount = data.positions.length / 3;\n const levelCount = data.levelRanges.length / 2;\n const instanceCount = matrices.length / 16;\n const cellCount = Math.ceil(instanceCount / CELL_SIZE);\n const at = <T extends Float32Array | Uint32Array>(buffer: GrowBuffer<T>, count: number) => {\n let first = buffer.reserve(count);\n if (first === -1) {\n buffer.grow(buffer.used + count);\n this.needsRebuild = true;\n first = buffer.reserve(count);\n }\n return first;\n };\n const entry: PoolEntry = {\n slot,\n data,\n vertexBase: at(this.vertexData, vertexCount),\n meshletBase: at(this.meshletBounds, data.meshletCount),\n meshletVertexBase: at(this.meshletVertices, data.meshletVertices.length),\n triangleBase: at(this.meshletTriangles, data.meshletTriangles.length),\n levelBase: 0,\n levelCount,\n instanceBase: at(this.instances, instanceCount * INSTANCE_STRIDE) / INSTANCE_STRIDE,\n instanceCount,\n cellBase: at(this.cells, cellCount * CELL_STRIDE) / CELL_STRIDE,\n cellCount,\n uvScale: [1, 1],\n uvOffset: [0, 0],\n };\n at(this.meshletInfo, data.meshletCount);\n at(this.vertexAttrs, vertexCount);\n // Level table entries live after the mesh records.\n entry.levelBase = this.meshSlotCapacity * MESH_STRIDE + this.levelUsed;\n if (entry.levelBase + levelCount * 2 > this.meshTable.capacity) {\n this.meshTable.grow(entry.levelBase + levelCount * 2);\n this.needsRebuild = true;\n }\n this.levelUsed += levelCount * 2;\n this.meshTable.used = Math.max(this.meshTable.used, entry.levelBase + levelCount * 2);\n\n this.entries[slot] = entry;\n this.writeGeometry(entry);\n this.writeInstances(entry, matrices, colors, gpuToInput);\n this.writeMeshRecord(entry, { maxDrawDistance: NO_DRAW_DISTANCE, minPixelRadius: 0, enabled: 1, shadow: 1, occlusion: 0 });\n this.meshSlots.value = Math.max(this.meshSlots.value, slot + 1);\n this.cellCount.value = this.cells.used / CELL_STRIDE;\n this.dirty = true;\n return entry;\n }\n\n /** Frees a mesh's slot (its buffer ranges are reclaimed when the pool is next repacked). */\n remove(entry: PoolEntry) {\n this.writeFlags(entry, { enabled: 0 });\n this.entries[entry.slot] = null;\n // Its cells stay in the cell buffer but point at a disabled slot, so they are rejected at once.\n this.dirty = true;\n }\n\n private growMeshSlots(needed: number) {\n // The level tables start after the mesh records: move them up.\n const old = this.meshSlotCapacity;\n const next = Math.max(needed, old * 2);\n const shift = (next - old) * MESH_STRIDE;\n const levelsStart = old * MESH_STRIDE;\n const grownSize = this.meshTable.used + shift;\n if (grownSize > this.meshTable.capacity) this.meshTable.grow(grownSize);\n const table = this.meshTable.array;\n table.copyWithin((levelsStart + shift) * 4, levelsStart * 4, this.meshTable.used * 4);\n table.fill(0, levelsStart * 4, (levelsStart + shift) * 4);\n this.meshTable.used += shift;\n this.meshSlotCapacity = next;\n for (const entry of this.entries) {\n if (!entry) continue;\n entry.levelBase += shift;\n table[(entry.slot * MESH_STRIDE + 3) * 4 + 3] = entry.levelBase;\n }\n this.needsRebuild = true;\n }\n\n private writeGeometry(e: PoolEntry) {\n const d = e.data;\n const vertexCount = d.positions.length / 3;\n // Vertices: position bits + octahedral normal.\n const vd = this.vertexData.array;\n const asFloat = new Float32Array(vd.buffer, vd.byteOffset, vd.length);\n for (let i = 0; i < vertexCount; i++) {\n const o = (e.vertexBase + i) * 4;\n asFloat[o] = d.positions[i * 3];\n asFloat[o + 1] = d.positions[i * 3 + 1];\n asFloat[o + 2] = d.positions[i * 3 + 2];\n vd[o + 3] = encodeOctNormal(d.normals[i * 3], d.normals[i * 3 + 1], d.normals[i * 3 + 2]);\n }\n this.vertexData.touch(e.vertexBase, vertexCount);\n // Per-vertex color (white without colors) and uv (quantized over the mesh's uv bounds).\n const va = this.vertexAttrs.array;\n const uv = d.uvs ? packUvs(d.uvs) : null;\n if (uv) {\n e.uvScale = uv.scale;\n e.uvOffset = uv.offset;\n }\n const q = (x: number) => Math.round(Math.max(0, Math.min(1, x)) * 255);\n for (let i = 0; i < vertexCount; i++) {\n const o = (e.vertexBase + i) * 2;\n va[o] = d.colors ? (q(d.colors[i * 3]) | (q(d.colors[i * 3 + 1]) << 8) | (q(d.colors[i * 3 + 2]) << 16) | (255 << 24)) >>> 0 : 0xffffffff;\n va[o + 1] = uv ? uv.packed[i] : 0;\n }\n this.vertexAttrs.touch(e.vertexBase, vertexCount);\n // Meshlets, rebased to pool-global vertex / index ranges.\n this.meshletBounds.array.set(d.meshletBounds, e.meshletBase * 16);\n this.meshletBounds.touch(e.meshletBase, d.meshletCount);\n const info = this.meshletInfo.array;\n for (let m = 0; m < d.meshletCount; m++) {\n const o = (e.meshletBase + m) * 4;\n const s = m * MESHLET_INFO_STRIDE;\n info[o] = d.meshletInfo[s];\n info[o + 1] = d.meshletInfo[s + 1] + e.triangleBase * 3;\n info[o + 2] = d.meshletInfo[s + 2];\n info[o + 3] = d.meshletInfo[s + 3] + e.meshletVertexBase;\n }\n this.meshletInfo.touch(e.meshletBase, d.meshletCount);\n const mv = this.meshletVertices.array;\n for (let i = 0; i < d.meshletVertices.length; i++) mv[e.meshletVertexBase + i] = d.meshletVertices[i] + e.vertexBase;\n this.meshletVertices.touch(e.meshletVertexBase, d.meshletVertices.length);\n this.meshletTriangles.array.set(d.meshletTriangles, e.triangleBase);\n this.meshletTriangles.touch(e.triangleBase, d.meshletTriangles.length);\n // Level table: (first meshlet, count, smallest own error, largest parent error), (largest own, smallest parent).\n const t = this.meshTable.array;\n for (let l = 0; l < e.levelCount; l++) {\n const o = (e.levelBase + l * 2) * 4;\n t[o] = d.levelRanges[l * 2] + e.meshletBase;\n t[o + 1] = d.levelRanges[l * 2 + 1];\n t[o + 2] = d.levelErrors[l * 2];\n t[o + 3] = d.levelErrors[l * 2 + 1];\n t[o + 4] = d.levelGuardErrors[l * 2];\n t[o + 5] = d.levelGuardErrors[l * 2 + 1];\n t[o + 6] = 0;\n t[o + 7] = 0;\n }\n this.meshTable.touch(e.levelBase, e.levelCount * 2);\n }\n\n /** Writes a mesh record: bounding spheres, levers, level table location, uv packing, flags. */\n writeMeshRecord(e: PoolEntry, o: { maxDrawDistance: number; minPixelRadius: number; enabled: number; shadow: number; occlusion: number }) {\n const t = this.meshTable.array;\n const base = e.slot * MESH_STRIDE * 4;\n t.set(e.data.boundingSphere, base);\n t.set(e.data.lodBoundsSphere, base + 4);\n t.set(e.data.cullBoundsSphere, base + 8);\n t.set([o.maxDrawDistance, o.minPixelRadius, e.levelCount, e.levelBase], base + 12);\n t.set([e.uvScale[0], e.uvScale[1], e.uvOffset[0], e.uvOffset[1]], base + 16);\n t.set([o.enabled, o.shadow, o.occlusion, 0], base + 20);\n this.meshTable.touch(e.slot * MESH_STRIDE, MESH_STRIDE);\n this.dirty = true;\n }\n\n /** Updates some of a mesh's per-frame levers (only what changed is uploaded). */\n writeFlags(e: PoolEntry, o: { maxDrawDistance?: number; minPixelRadius?: number; enabled?: number; shadow?: number; occlusion?: number }) {\n const t = this.meshTable.array;\n const base = e.slot * MESH_STRIDE * 4;\n const set = (index: number, value: number | undefined) => {\n if (value === undefined || t[base + index] === value) return;\n t[base + index] = value;\n this.meshTable.touch(e.slot * MESH_STRIDE + (index >> 2), 1);\n this.dirty = true;\n };\n set(12, o.maxDrawDistance);\n set(13, o.minPixelRadius);\n set(20, o.enabled);\n set(21, o.shadow);\n set(22, o.occlusion);\n }\n\n readFlag(e: PoolEntry, index: 'maxDrawDistance' | 'minPixelRadius' | 'enabled' | 'shadow' | 'occlusion') {\n const offsets = { maxDrawDistance: 12, minPixelRadius: 13, enabled: 20, shadow: 21, occlusion: 22 };\n return this.meshTable.array[e.slot * MESH_STRIDE * 4 + offsets[index]];\n }\n\n private writeInstances(e: PoolEntry, matrices: Float32Array, colors: Float32Array | undefined, gpuToInput: Uint32Array) {\n const a = this.instances.array;\n for (let g = 0; g < e.instanceCount; g++) {\n const src = gpuToInput[g];\n const o = (e.instanceBase + g) * INSTANCE_STRIDE * 4;\n a.set(matrices.subarray(src * 16, src * 16 + 16), o);\n if (colors) a.set(colors.subarray(src * 4, src * 4 + 3), o + 16);\n else a.fill(1, o + 16, o + 19);\n a[o + 19] = e.slot;\n }\n this.instances.touch(e.instanceBase * INSTANCE_STRIDE, e.instanceCount * INSTANCE_STRIDE);\n for (let c = 0; c < e.cellCount; c++) this.computeCell(e, c);\n this.cells.touch(e.cellBase * CELL_STRIDE, e.cellCount * CELL_STRIDE);\n }\n\n /** Writes one instance matrix (GPU order index within the mesh). Call `commitInstances` afterwards. */\n setMatrix(e: PoolEntry, gpuIndex: number, matrix: THREE.Matrix4) {\n matrix.toArray(this.instances.array, (e.instanceBase + gpuIndex) * INSTANCE_STRIDE * 4);\n }\n\n /** Uploads changed instances and refreshes the bounds of the given cells. */\n commitInstances(e: PoolEntry, cells: Iterable<number>) {\n this.instances.touch(e.instanceBase * INSTANCE_STRIDE, e.instanceCount * INSTANCE_STRIDE);\n for (const c of cells) {\n this.computeCell(e, c);\n this.cells.touch((e.cellBase + c) * CELL_STRIDE, CELL_STRIDE);\n }\n this.dirty = true;\n }\n\n /**\n * Bounding sphere of one cell's instances: the AABB of their world-space object spheres gives the center, and\n * the radius reaches every instance sphere. Both radii are inflated a little so float32 rounding on the GPU can\n * never make the cell test stricter than the per-instance test.\n */\n private computeCell(e: PoolEntry, cell: number) {\n const m = this.instances.array;\n const first = cell * CELL_SIZE;\n const end = Math.min(first + CELL_SIZE, e.instanceCount);\n const s = new Float64Array(4);\n const lo = [Infinity, Infinity, Infinity];\n const hi = [-Infinity, -Infinity, -Infinity];\n let maxRadius = 0;\n for (let g = first; g < end; g++) {\n instanceSphere(m, (e.instanceBase + g) * INSTANCE_STRIDE * 4, e.data.boundingSphere, s);\n for (let a = 0; a < 3; a++) {\n lo[a] = Math.min(lo[a], s[a] - s[3]);\n hi[a] = Math.max(hi[a], s[a] + s[3]);\n }\n maxRadius = Math.max(maxRadius, s[3]);\n }\n const cx = (lo[0] + hi[0]) / 2;\n const cy = (lo[1] + hi[1]) / 2;\n const cz = (lo[2] + hi[2]) / 2;\n let radius = 0;\n for (let g = first; g < end; g++) {\n instanceSphere(m, (e.instanceBase + g) * INSTANCE_STRIDE * 4, e.data.boundingSphere, s);\n radius = Math.max(radius, Math.hypot(s[0] - cx, s[1] - cy, s[2] - cz) + s[3]);\n }\n const o = (e.cellBase + cell) * CELL_STRIDE * 4;\n this.cells.array.set([cx, cy, cz, radius * (1 + 1e-4) + 1e-3, maxRadius * (1 + 1e-4) + 1e-4, e.slot, e.instanceBase + first, end - first], o);\n }\n\n // ------------------------------------------------------------------ GPU\n\n /**\n * Index buffers are written by compute and read by draws. three.js picks GPU buffer usage from the first use,\n * so create them as index buffers (INDEX | STORAGE) before any compute. Also rebuilds the nodes after growth.\n */\n prepare(renderer: THREE.WebGPURenderer) {\n this.ensureBuilt();\n if (this.indexBuffersReady) return;\n const backend = renderer.backend as unknown as { createIndexAttribute(a: unknown): void };\n backend.createIndexAttribute(this.cameraIndex);\n backend.createIndexAttribute(this.shadowIndex);\n this.indexBuffersReady = true;\n }\n\n /** Builds the nodes if the pool's buffers grew since the last build (or it was never built). */\n ensureBuilt() {\n if (this.needsRebuild) this.build();\n }\n\n /** Recreates the per-frame buffers and every node (after the pool's buffers grew). */\n build() {\n this.needsRebuild = false;\n this.indexBuffersReady = false;\n this.pipelineState = 'none';\n this.hasCut = false;\n this.version++;\n for (const node of this.computeNodes) node.dispose();\n\n const ctx = this.context;\n const cap = this.capacity;\n const slots = this.meshSlotCapacity;\n const maxDrawn = cap.meshlets;\n const instanceCapacity = Math.floor(this.instances.capacity / INSTANCE_STRIDE);\n const cellCapacity = Math.floor(this.cells.capacity / CELL_STRIDE);\n const cameraIndexCapacity = cap.triangles * 3;\n const shadowIndexCapacity = cap.shadowTriangles * 3;\n\n // Attribute objects of the growable buffers (replaced when they grew).\n const storageOf = (buffer: GrowBuffer<Float32Array | Uint32Array>, type: string): Node => (storage as Node)(buffer.attribute, type, buffer.capacity);\n const vertexData: Node = storageOf(this.vertexData, 'uvec4').toReadOnly();\n const vertexAttrs: Node = storageOf(this.vertexAttrs, 'uvec2').toReadOnly();\n const bounds: Node = storageOf(this.meshletBounds, 'vec4').toReadOnly();\n const info: Node = storageOf(this.meshletInfo, 'uvec4').toReadOnly();\n const meshletVertices: Node = storageOf(this.meshletVertices, 'uint').toReadOnly();\n const meshletTriangles: Node = storageOf(this.meshletTriangles, 'uint').toReadOnly();\n const meshTable: Node = storageOf(this.meshTable, 'vec4').toReadOnly();\n const instances: Node = storageOf(this.instances, 'vec4').toReadOnly();\n const cells: Node = storageOf(this.cells, 'vec4').toReadOnly();\n\n // Per-frame buffers.\n // counters: PER_MESH_COUNTERS globals, then per cut and mesh slot (requested indices, region start).\n this.countersAttribute = new THREE.StorageBufferAttribute(new Uint32Array(PER_MESH_COUNTERS + 2 * slots * 2), 1);\n // drawIndexedIndirect args per cut and mesh slot: indexCount, instanceCount, firstIndex, baseVertex, firstInstance.\n this.drawArgsAttribute = new THREE.IndirectStorageBufferAttribute(new Uint32Array(2 * slots * 5), 1);\n this.cameraIndex = new THREE.StorageBufferAttribute(new Uint32Array(cameraIndexCapacity), 1);\n this.shadowIndex = new THREE.StorageBufferAttribute(new Uint32Array(shadowIndexCapacity), 1);\n const cellListAttribute = new THREE.StorageBufferAttribute(new Uint32Array(cellCapacity * 4), 4);\n // (instance, first meshlet, end meshlet, mesh slot | occlusion << 31) per cut.\n const workListAttribute = new THREE.StorageBufferAttribute(new Uint32Array(instanceCapacity * 2 * 4), 4);\n // (instance, meshlet, first index within the mesh's region, triangle count); slots are absolute over both cuts.\n const drawListAttribute = new THREE.StorageBufferAttribute(new Uint32Array(maxDrawn * 2 * 4), 4);\n const dispatchAttr = () => new THREE.IndirectStorageBufferAttribute(new Uint32Array(3), 3);\n const instanceArgsAttribute = dispatchAttr();\n const meshletArgsAttributes = [dispatchAttr(), dispatchAttr()];\n const expandArgsAttributes = [dispatchAttr(), dispatchAttr()];\n\n const counters: Node = storage(this.countersAttribute, 'uint', this.countersAttribute.count).toAtomic();\n const drawArgs: Node = storage(this.drawArgsAttribute, 'uint', this.drawArgsAttribute.count);\n const cameraIndex: Node = storage(this.cameraIndex, 'uint', cameraIndexCapacity);\n const shadowIndex: Node = storage(this.shadowIndex, 'uint', shadowIndexCapacity);\n const cellList: Node = storage(cellListAttribute, 'uvec4', cellCapacity);\n const cellListRead: Node = storage(cellListAttribute, 'uvec4', cellCapacity).toReadOnly();\n const workList: Node = storage(workListAttribute, 'uvec4', instanceCapacity * 2);\n const drawList: Node = storage(drawListAttribute, 'uvec4', maxDrawn * 2);\n const drawListRead: Node = storage(drawListAttribute, 'uvec4', maxDrawn * 2).toReadOnly();\n const instanceArgs: Node = storage(instanceArgsAttribute, 'uint', 3);\n const meshletArgs = meshletArgsAttributes.map((a) => storage(a, 'uint', 3) as Node);\n const expandArgs = expandArgsAttributes.map((a) => storage(a, 'uint', 3) as Node);\n\n const counter = (cut: number, i: number) => counters.element(2 + cut * CUT_COUNTERS + i);\n const meshCount = (cut: number, slot: Node) => counters.element(uint(PER_MESH_COUNTERS + cut * slots * 2).add(slot.mul(2)));\n const meshStart = (cut: number, slot: Node) => counters.element(uint(PER_MESH_COUNTERS + cut * slots * 2 + 1).add(slot.mul(2)));\n const cutCapacity = [cameraIndexCapacity, shadowIndexCapacity];\n const indexBuffers = [cameraIndex, shadowIndex];\n\n const shadowThreshold: Node = ctx.errorThreshold.mul(ctx.shadowErrorScale);\n const thresholds = [ctx.errorThreshold as Node, shadowThreshold];\n const minPixelsGlobal: Node = ctx.minPixelRadius;\n const occlusion = ctx.occlusion;\n\n const instanceColumn = (instanceId: Node, k: number) => instances.element(instanceId.mul(INSTANCE_STRIDE).add(k));\n const modelOf = (instanceId: Node) => {\n const c = [0, 1, 2, 3].map((k) => instanceColumn(instanceId, k).toVar());\n const model = mat4(c[0], c[1], c[2], c[3]).toVar();\n const scale = max(length(c[0].xyz), max(length(c[1].xyz), length(c[2].xyz))).toVar();\n return { model, scale, columns: c };\n };\n const meshRecord = (slot: Node, k: number) => meshTable.element(slot.mul(MESH_STRIDE).add(k));\n\n const projectedError = (model: Node, scale: Node, sphere: Node, error: Node) => {\n const viewCenter: Node = (ctx.viewMatrix as Node).mul(model.mul(vec4(sphere.xyz, 1)));\n const distance = max(length(viewCenter.xyz).sub(sphere.w.mul(scale)), ctx.near) as Node;\n const pixels = error.mul(scale).div(distance).mul(ctx.projScale);\n return select(error.greaterThanEqual(ERROR_INFINITY * 0.5), float(ERROR_INFINITY), pixels);\n };\n\n /**\n * Signed distance of a sphere to the camera frustum (negative radius-or-more = fully outside). With `swept`,\n * the sphere is swept along shadowSweep (the light direction): a caster outside the view can still throw a\n * shadow into it, so it is kept if ANY point of that segment is inside the plane: d(center) + max(0, dot(n, sweep)).\n */\n const frustumDistance = (center: Node, swept: Node | boolean) => {\n let minDistance: Node = float(1e30);\n for (const plane of ctx.frustumPlanes) {\n let d: Node = dot(plane.xyz, center).add(plane.w);\n if (swept !== false) d = d.add(max(dot(plane.xyz, ctx.shadowSweep), 0).mul(swept === true ? 1 : select(swept, float(1), float(0))));\n minDistance = min(minDistance, d);\n }\n return minDistance;\n };\n\n /** Hidden behind the occluders; the sphere grows by the error threshold (occluders are LOD-simplified). */\n const occludedSphere = (occlusionOn: Node, worldCenter: Node, radius: Node) => {\n const viewCenter: Node = (ctx.viewMatrix as Node).mul(vec4(worldCenter, 1)).xyz.toVar();\n const margin = viewCenter.z.abs().mul(ctx.errorThreshold).div(ctx.projScale);\n return occlusionOn.and((occlusion.activeNode as Node).equal(1)).and(occlusion.occluded(viewCenter, radius.add(margin)));\n };\n\n const dispatchArgs = (target: Node, count: Node) => {\n target.element(0).assign(minNode(count, uint(MAX_DISPATCH)));\n target.element(1).assign(count.add(MAX_DISPATCH - 1).div(MAX_DISPATCH));\n target.element(2).assign(uint(1));\n };\n\n // ---------- 0. reset ----------\n const resetNode = Fn(() => {\n const i = instanceIndex;\n If(i.lessThan(uint(PER_MESH_COUNTERS)), () => {\n atomicStore(counters.element(i), uint(0));\n });\n If(i.lessThan(this.meshSlots.mul(4)), () => {\n // count and start of slot i>>1 for both cuts\n const cut = i.div(this.meshSlots.mul(2));\n const rest = i.mod(this.meshSlots.mul(2));\n atomicStore(counters.element(uint(PER_MESH_COUNTERS).add(cut.mul(slots * 2)).add(rest)), uint(0));\n });\n })().compute(Math.max(PER_MESH_COUNTERS, slots * 4), [64]);\n\n // ---------- 1. cells ----------\n const cellNode = Fn(() => {\n If(instanceIndex.greaterThanEqual(this.cellCount), () => {\n Return();\n });\n const cell = instanceIndex.toVar();\n const sphere = cells.element(cell.mul(CELL_STRIDE)).toVar();\n const record = cells.element(cell.mul(CELL_STRIDE).add(1)).toVar();\n const slot = uint(record.y).toVar();\n const flags = meshRecord(slot, 5).toVar();\n If(flags.x.equal(0), () => {\n Return(); // removed or invisible mesh\n });\n const center = sphere.xyz.toVar();\n const radius = sphere.w.toVar();\n If(ctx.frustumCulling.equal(1).and(frustumDistance(center, flags.y.greaterThan(0.5)).lessThan(radius.negate())), () => {\n Return();\n });\n const levers = meshRecord(slot, 3).toVar();\n const minPixels = max(minPixelsGlobal, levers.y);\n // Every instance lies within `radius` of the cell center, so its view distance is at least\n // viewDistance - radius, and its radius is at most maxRadius.\n const maxRadius = record.x;\n const viewDistance = length((ctx.viewMatrix as Node).mul(vec4(center, 1)).xyz).toVar();\n const gap = viewDistance.sub(radius).toVar();\n If(gap.greaterThan(maxRadius).and(maxRadius.mul(ctx.projScale).div(max(gap, 1e-6)).lessThan(minPixels)), () => {\n Return();\n });\n If(gap.greaterThan(levers.x), () => {\n Return(); // beyond the draw distance\n });\n const at = (atomicAdd(counters.element(0), uint(1)) as Node).toVar();\n cellList.element(at).assign(uvec4(slot, uint(record.z), uint(record.w), cell));\n })().compute(cellCapacity, [CULL_GROUP]);\n\n const cellArgsNode = Fn(() => {\n dispatchArgs(instanceArgs, (atomicLoad(counters.element(0)) as Node).toVar());\n })().compute(1);\n\n // ---------- 2. instances ----------\n // The mesh's level table is cached in workgroup memory: every instance of a cell belongs to one mesh.\n const levelCache: Node = workgroupArray('vec4', MAX_LEVELS * 2);\n\n /** Emits the level range of one instance for one cut, then its fast path or its work-list entry. */\n const selectLevels = (\n cut: number,\n slot: Node,\n levelCount: Node,\n occlusionFlag: Node,\n cullBounds: Node,\n instanceId: Node,\n model: Node,\n scale: Node,\n pixelsAtMin: Node,\n pixelsAtMax: Node\n ) => {\n const threshold = thresholds[cut];\n const first = uint(0xffffffff).toVar();\n const last = uint(0).toVar();\n const possibleMeshlets = uint(0).toVar();\n const guaranteedMeshlets = uint(0).toVar();\n Loop({ start: uint(0), end: levelCount, type: 'uint', condition: '<' }, ({ i }: { i: Node }) => {\n const l0 = levelCache.element(i.mul(2)).toVar(); // first meshlet, count, smallest own error, largest parent error\n const l1 = levelCache.element(i.mul(2).add(1)).toVar(); // largest own error, smallest parent error\n const levelFirst = uint(l0.x).toVar();\n const size = uint(l0.y).toVar();\n const possible = l0.z\n .mul(pixelsAtMax)\n .lessThanEqual(threshold)\n .and(l0.w.greaterThanEqual(ERROR_INFINITY * 0.5).or(l0.w.mul(pixelsAtMin).greaterThan(threshold)));\n // Every meshlet of the level passes for any distance in [min, max]: largest own error at the nearest\n // distance, smallest parent error at the farthest. Relative margin keeps float rounding on our side.\n const sure = l1.x\n .mul(pixelsAtMin)\n .lessThanEqual(threshold.mul(1 - FAST_PATH_MARGIN))\n .and(l1.y.greaterThanEqual(ERROR_INFINITY * 0.5).or(l1.y.mul(pixelsAtMax).greaterThan(threshold.mul(1 + FAST_PATH_MARGIN))));\n If(possible, () => {\n first.assign(minNode(first, levelFirst));\n last.assign(maxNode(last, levelFirst.add(size)));\n possibleMeshlets.addAssign(size);\n If(sure, () => {\n guaranteedMeshlets.addAssign(size);\n });\n });\n });\n\n const cullCenter = model.mul(vec4(cullBounds.xyz, 1)).xyz.toVar();\n const cullRadius = cullBounds.w.mul(scale).toVar();\n // Possible levels must be contiguous, all guaranteed, few, and every meshlet inside the frustum.\n const fastPath = possibleMeshlets\n .greaterThan(uint(0))\n .and(possibleMeshlets.equal(last.sub(first)))\n .and(guaranteedMeshlets.equal(possibleMeshlets))\n .and(possibleMeshlets.lessThanEqual(uint(FAST_PATH_MAX_MESHLETS)))\n .and(ctx.frustumCulling.equal(0).or(frustumDistance(cullCenter, cut === 1).greaterThanEqual(cullRadius)))\n .toVar();\n\n If(last.greaterThan(first), () => {\n atomicAdd(counter(cut, C_SURVIVED), uint(1));\n If(fastPath, () => {\n const base = (atomicAdd(counter(cut, C_SELECTED), possibleMeshlets) as Node).toVar();\n for (let k = 0; k < FAST_PATH_MAX_MESHLETS; k++) {\n If(uint(k).lessThan(possibleMeshlets).and(base.add(k).lessThan(uint(maxDrawn))), () => {\n const meshletId = first.add(k).toVar();\n const triangleCount = info.element(meshletId).x.toVar();\n const firstIndex = (atomicAdd(meshCount(cut, slot), triangleCount.mul(3)) as Node).toVar();\n drawList.element(base.add(k + cut * maxDrawn)).assign(uvec4(instanceId, meshletId, firstIndex, triangleCount));\n });\n }\n }).Else(() => {\n const item = (atomicAdd(counter(cut, C_WORK), uint(1)) as Node).toVar();\n const tag = slot.bitOr(select(occlusionFlag, uint(0x80000000), uint(0)));\n workList.element(item.add(cut * instanceCapacity)).assign(uvec4(instanceId, first, last, tag));\n });\n });\n };\n\n const instanceNode = Fn(() => {\n // No early return before the barrier (WGSL needs uniform control flow there): workgroups past the\n // visible-cell count (the dispatch is rounded up) load no levels and process no instances.\n const cellIndex = workgroupId.x.add(workgroupId.y.mul(numWorkgroups.x)).toVar();\n const valid = cellIndex.lessThan(atomicLoad(counters.element(0)) as Node).toVar();\n const cell = cellListRead.element(minNode(cellIndex, uint(cellCapacity - 1))).toVar(); // (mesh slot, first instance, count, cell)\n const slot = cell.x;\n const levers = meshRecord(slot, 3).toVar(); // draw distance, min pixel radius, level count, level base\n const levelCount = select(valid, minNode(uint(levers.z), uint(MAX_LEVELS)), uint(0)).toVar();\n const levelBase = uint(levers.w).toVar();\n Loop({ start: localId.x, end: levelCount.mul(2), type: 'uint', condition: '<', update: CULL_GROUP }, ({ i }: { i: Node }) => {\n levelCache.element(i).assign(meshTable.element(levelBase.add(i)));\n });\n workgroupBarrier();\n If(valid.not(), () => {\n Return();\n });\n\n const objectSphere = meshRecord(slot, 0).toVar();\n const lodBounds = meshRecord(slot, 1).toVar();\n const cullBounds = meshRecord(slot, 2).toVar();\n const flags = meshRecord(slot, 5).toVar(); // enabled, shadow, occlusion\n const shadowOn = flags.y.greaterThan(0.5);\n const occlusionOn = flags.z.greaterThan(0.5);\n const minPixels = max(minPixelsGlobal, levers.y).toVar();\n const maxDrawDistance = levers.x.toVar();\n const end = cell.y.add(cell.z);\n Loop({ start: cell.y.add(localId.x), end, type: 'uint', condition: '<', update: CULL_GROUP }, ({ i }: { i: Node }) => {\n const instanceId = i.toVar();\n const { model, scale } = modelOf(instanceId);\n const center = model.mul(vec4(objectSphere.xyz, 1)).xyz.toVar();\n const radius = objectSphere.w.mul(scale).toVar();\n const noFrustum = ctx.frustumCulling.equal(0);\n const inCamera = noFrustum.or(frustumDistance(center, false).greaterThanEqual(radius.negate())).toVar();\n const inShadow = shadowOn.and(noFrustum.or(frustumDistance(center, true).greaterThanEqual(radius.negate()))).toVar();\n // Sub-pixel instances and instances beyond the draw distance: both cuts.\n const viewDistance = length((ctx.viewMatrix as Node).mul(vec4(center, 1)).xyz).toVar();\n const tooSmall = viewDistance.greaterThan(radius).and(radius.mul(ctx.projScale).div(viewDistance).lessThan(minPixels));\n const tooFar = viewDistance.sub(radius).greaterThan(maxDrawDistance);\n const keep = inCamera.or(inShadow).and(tooSmall.not()).and(tooFar.not());\n If(keep, () => {\n If(inCamera.and(occludedSphere(occlusionOn, center, radius)), () => {\n inCamera.assign(bool(false));\n atomicAdd(counters.element(1), uint(1));\n });\n const lodCenter: Node = (ctx.viewMatrix as Node).mul(model.mul(vec4(lodBounds.xyz, 1)));\n const d = length(lodCenter.xyz).toVar();\n const r = lodBounds.w.mul(scale);\n const pixelsAtMin = scale.mul(ctx.projScale).div(max(d.sub(r), ctx.near)).toVar();\n const pixelsAtMax = scale.mul(ctx.projScale).div(max(d.add(r), ctx.near)).toVar();\n If(inCamera, () => {\n selectLevels(0, slot, levelCount, occlusionOn, cullBounds, instanceId, model, scale, pixelsAtMin, pixelsAtMax);\n });\n If(inShadow, () => {\n selectLevels(1, slot, levelCount, bool(false), cullBounds, instanceId, model, scale, pixelsAtMin, pixelsAtMax);\n });\n });\n });\n })().compute(instanceArgsAttribute as unknown as number, [CULL_GROUP]);\n\n // ---------- 3. meshlets ----------\n const meshletPass = (cut: number) => {\n const argsNode = Fn(() => {\n dispatchArgs(meshletArgs[cut], (atomicLoad(counter(cut, C_WORK)) as Node).toVar());\n })().compute(1);\n const passNode = Fn(() => {\n const item = workgroupId.x.add(workgroupId.y.mul(numWorkgroups.x)).toVar();\n If(item.greaterThanEqual(atomicLoad(counter(cut, C_WORK)) as Node), () => {\n Return();\n });\n const work = workList.element(item.add(cut * instanceCapacity)).toVar();\n const instanceId = work.x;\n const slot = work.w.bitAnd(0x7fffffff).toVar();\n const occlusionOn = work.w.shiftRight(31).equal(1);\n const { model, scale } = modelOf(instanceId);\n Loop({ start: work.y.add(localId.x), end: work.z, type: 'uint', condition: '<', update: MESHLET_GROUP }, ({ i }: { i: Node }) => {\n const meshletId = i;\n const boundsBase = meshletId.mul(MESHLET_BOUNDS_STRIDE / 4).toVar();\n const cullSphere = bounds.element(boundsBase.add(3));\n const center = model.mul(vec4(cullSphere.xyz, 1)).xyz;\n let visible: Node = ctx.frustumCulling.equal(0).or(frustumDistance(center, cut === 1).greaterThanEqual(cullSphere.w.mul(scale).negate()));\n if (cut === 0) visible = visible.and(occludedSphere(occlusionOn, center, cullSphere.w.mul(scale)).not());\n // LOD selection: draw this meshlet iff its own error is small enough but its parent's is not.\n const errors = bounds.element(boundsBase.add(2));\n const ownError = projectedError(model, scale, bounds.element(boundsBase), errors.x);\n const parentError = projectedError(model, scale, bounds.element(boundsBase.add(1)), errors.y);\n If(visible.and(ownError.lessThanEqual(thresholds[cut])).and(parentError.greaterThan(thresholds[cut])), () => {\n const at = (atomicAdd(counter(cut, C_SELECTED), uint(1)) as Node).toVar();\n If(at.lessThan(uint(maxDrawn)), () => {\n const triangleCount = info.element(meshletId).x.toVar();\n const firstIndex = (atomicAdd(meshCount(cut, slot), triangleCount.mul(3)) as Node).toVar();\n drawList.element(at.add(cut * maxDrawn)).assign(uvec4(instanceId, meshletId, firstIndex, triangleCount));\n });\n });\n });\n })().compute(meshletArgsAttributes[cut] as unknown as number, [MESHLET_GROUP]);\n return [argsNode, passNode];\n };\n\n // ---------- 4. prefix: lay the meshes' regions out, write draw args and the expand dispatch ----------\n const prefixPass = (cut: number) =>\n Fn(() => {\n const start = uint(0).toVar();\n const capacity = uint(cutCapacity[cut]);\n Loop({ start: uint(0), end: this.meshSlots, type: 'uint', condition: '<' }, ({ i }: { i: Node }) => {\n const requested = (atomicLoad(meshCount(cut, i)) as Node).toVar();\n atomicStore(meshStart(cut, i), start);\n const room = select(start.lessThan(capacity), capacity.sub(start), uint(0));\n const args = uint(cut * slots * 5).add(i.mul(5)).toVar();\n drawArgs.element(args).assign(minNode(requested, room));\n drawArgs.element(args.add(1)).assign(uint(1));\n drawArgs.element(args.add(2)).assign(start);\n drawArgs.element(args.add(3)).assign(uint(0));\n drawArgs.element(args.add(4)).assign(uint(0));\n start.addAssign(requested);\n });\n atomicStore(counter(cut, C_REQUESTED), start);\n const drawn = minNode(atomicLoad(counter(cut, C_SELECTED)) as Node, uint(maxDrawn)).toVar();\n atomicStore(counter(cut, C_DRAWN), drawn);\n dispatchArgs(expandArgs[cut], drawn);\n })().compute(1);\n\n // ---------- 5. expand ----------\n const expandPass = (cut: number) =>\n Fn(() => {\n const at = workgroupId.x.add(workgroupId.y.mul(numWorkgroups.x)).toVar();\n If(at.greaterThanEqual(atomicLoad(counter(cut, C_DRAWN)) as Node), () => {\n Return();\n });\n const drawSlot = at.add(cut * maxDrawn).toVar();\n const entry = drawListRead.element(drawSlot).toVar();\n const slot = uint(instanceColumn(entry.x, 4).w).toVar();\n const regionStart = (atomicLoad(meshStart(cut, slot)) as Node).toVar();\n const firstTriangle = info.element(entry.y).y.div(3).toVar();\n const base = drawSlot.shiftLeft(LOCAL_VERTEX_BITS).toVar();\n const buffer = indexBuffers[cut];\n Loop({ start: localId.x, end: entry.w, type: 'uint', condition: '<', update: EXPAND_GROUP }, ({ i }: { i: Node }) => {\n const index = regionStart.add(entry.z).add(i.mul(3)).toVar();\n If(index.add(2).lessThan(uint(cutCapacity[cut])), () => {\n const packed = meshletTriangles.element(firstTriangle.add(i)).toVar();\n buffer.element(index).assign(base.bitOr(packed.bitAnd(255)));\n buffer.element(index.add(1)).assign(base.bitOr(packed.shiftRight(8).bitAnd(255)));\n buffer.element(index.add(2)).assign(base.bitOr(packed.shiftRight(16).bitAnd(255)));\n });\n });\n })().compute(expandArgsAttributes[cut] as unknown as number, [EXPAND_GROUP]);\n\n this.computeNodes = [\n resetNode,\n cellNode,\n cellArgsNode,\n instanceNode,\n ...meshletPass(0),\n ...meshletPass(1),\n prefixPass(0),\n prefixPass(1),\n expandPass(0),\n expandPass(1),\n ];\n\n // ---------- vertex pulling (shared by every mesh of the pool, both cuts) ----------\n this.positionNode = Fn(() => {\n const slot = vertexIndex.shiftRight(LOCAL_VERTEX_BITS);\n const localVertex = vertexIndex.bitAnd(LOCAL_VERTEX_MASK);\n const entry = drawListRead.element(slot).toVar();\n const instanceId = entry.x;\n const meshletId = entry.y;\n const meshletInfo = info.element(meshletId).toVar();\n const vertexId: Node = meshletVertices.element(meshletInfo.w.add(localVertex)).toVar();\n\n const { model, columns } = modelOf(instanceId);\n const tintAndSlot = instanceColumn(instanceId, 4).toVar();\n const meshSlot = uint(tintAndSlot.w).toVar();\n const levers = meshRecord(meshSlot, 3);\n const uvPacking = meshRecord(meshSlot, 4).toVar();\n const packedVertex = vertexData.element(vertexId).toVar();\n const attrs = vertexAttrs.element(vertexId).toVar();\n const localPosition: Node = bitcast(packedVertex.xyz, 'vec3');\n // Draw-distance fade: shrink toward the instance origin over the last DRAW_DISTANCE_FADE of the distance.\n // Distance from the main camera (context.viewMatrix), also in the shadow pass, so shadows fade with it.\n const maxDrawDistance = levers.x;\n const origin = columns[3].xyz;\n const originDistance = length((ctx.viewMatrix as Node).mul(vec4(origin, 1)).xyz);\n const fade = maxDrawDistance.sub(originDistance).div(maxDrawDistance.mul(DRAW_DISTANCE_FADE)).clamp(0, 1);\n const worldPosition = origin.add(model.mul(vec4(localPosition, 0)).xyz.mul(fade));\n const worldNormal = normalize(model.mul(vec4(decodeOctNormal(packedVertex.w), 0)).xyz);\n normalLocal.assign(worldNormal);\n vgWorldNormal.assign(worldNormal);\n\n vgMeshletVarying.assign(float(meshletId));\n vgLodVarying.assign(float(meshletInfo.z));\n vgInstanceVarying.assign(float(instanceId));\n vgTintVarying.assign(tintAndSlot.xyz.mul(unpackRgba8(attrs.x).xyz));\n vgUv.assign((unpackUnorm2x16(attrs.y) as Node).mul(uvPacking.xy).add(uvPacking.zw));\n return worldPosition;\n })();\n }\n\n /** Stats of the last computed cut, from a readback of the counters buffer. */\n async readCounters(renderer: THREE.WebGPURenderer) {\n const words = new Uint32Array(await renderer.getArrayBufferAsync(this.countersAttribute));\n const slots = this.meshSlotCapacity;\n const cut = (c: number) => ({\n selected: words[2 + c * CUT_COUNTERS + C_SELECTED],\n drawn: words[2 + c * CUT_COUNTERS + C_DRAWN],\n survived: words[2 + c * CUT_COUNTERS + C_SURVIVED],\n requestedTriangles: words[2 + c * CUT_COUNTERS + C_REQUESTED] / 3,\n });\n const perMesh = (c: number, slot: number) => words[PER_MESH_COUNTERS + (c * slots + slot) * 2] / 3;\n return { camera: cut(0), shadow: cut(1), occluded: words[1], perMesh };\n }\n\n /** Byte offset of a mesh's draw args for a cut (0: camera, 1: shadow) in `drawArgsAttribute`. */\n drawArgsOffset(cut: number, slot: number) {\n return (cut * this.meshSlotCapacity + slot) * 20;\n }\n\n dispose() {\n for (const node of this.computeNodes) node.dispose();\n this.computeNodes = [];\n }\n}\n\n/**\n * World-space bounding sphere of the instance whose column-major matrix starts at `base`, computed the same way\n * the instance pass does: center = model * sphere center, radius = sphere radius * max column length.\n */\nexport function instanceSphere(m: ArrayLike<number>, base: number, sphere: number[], out: Float64Array) {\n const [sx, sy, sz, sr] = sphere;\n out[0] = m[base] * sx + m[base + 4] * sy + m[base + 8] * sz + m[base + 12];\n out[1] = m[base + 1] * sx + m[base + 5] * sy + m[base + 9] * sz + m[base + 13];\n out[2] = m[base + 2] * sx + m[base + 6] * sy + m[base + 10] * sz + m[base + 14];\n const c0 = Math.hypot(m[base], m[base + 1], m[base + 2]);\n const c1 = Math.hypot(m[base + 4], m[base + 5], m[base + 6]);\n const c2 = Math.hypot(m[base + 8], m[base + 9], m[base + 10]);\n out[3] = sr * Math.max(c0, c1, c2);\n}\n\n/** Octahedral normal (two snorm16 in one u32) -> unit vector. */\nfunction decodeOctNormal(packed: Node): Node {\n const bits: Node = bitcast(packed, 'int');\n const u = float(bits.shiftLeft(16).shiftRight(16)).div(32767);\n const v = float(bits.shiftRight(16)).div(32767);\n const z = float(1).sub(u.abs()).sub(v.abs());\n const t = maxNode(z.negate(), 0);\n const x = u.add(select(u.greaterThanEqual(0), t.negate(), t));\n const y = v.add(select(v.greaterThanEqual(0), t.negate(), t));\n return normalize(vec3(x, y, z));\n}\n\nfunction unpackRgba8(packed: Node): Node {\n return vec4(float(packed.bitAnd(255)), float(packed.shiftRight(8).bitAnd(255)), float(packed.shiftRight(16).bitAnd(255)), float(packed.shiftRight(24))).div(255);\n}\n\nexport function encodeOctNormal(nx: number, ny: number, nz: number): number {\n const l1 = Math.abs(nx) + Math.abs(ny) + Math.abs(nz) || 1;\n let u = nx / l1;\n let v = ny / l1;\n if (nz < 0) {\n const pu = (1 - Math.abs(v)) * (u >= 0 ? 1 : -1);\n const pv = (1 - Math.abs(u)) * (v >= 0 ? 1 : -1);\n u = pu;\n v = pv;\n }\n const su = Math.round(Math.max(-1, Math.min(1, u)) * 32767) & 0xffff;\n const sv = Math.round(Math.max(-1, Math.min(1, v)) * 32767) & 0xffff;\n return (su | (sv << 16)) >>> 0;\n}\n\n/** xyz as float bits + octahedral-encoded normal, 4 x u32 per vertex. */\nexport function packVertices(positions: Float32Array, normals: Float32Array): Uint32Array {\n const count = positions.length / 3;\n const out = new Uint32Array(count * 4);\n const asFloat = new Float32Array(out.buffer);\n for (let i = 0; i < count; i++) {\n asFloat[i * 4 + 0] = positions[i * 3 + 0];\n asFloat[i * 4 + 1] = positions[i * 3 + 1];\n asFloat[i * 4 + 2] = positions[i * 3 + 2];\n out[i * 4 + 3] = encodeOctNormal(normals[i * 3], normals[i * 3 + 1], normals[i * 3 + 2]);\n }\n return out;\n}\n\n/**\n * uv per vertex as two unorm16 in one u32, quantized over the bounds of all UVs (also tiling UVs outside 0..1).\n * Decode: unpackUnorm2x16(packed) * scale + offset. One step is 1/65535 of the range: well below a texel of a 4K\n * texture for 0..1 UVs.\n */\nexport function packUvs(uvs: Float32Array): { packed: Uint32Array; scale: [number, number]; offset: [number, number] } {\n const count = uvs.length / 2;\n const lo = [Infinity, Infinity];\n const hi = [-Infinity, -Infinity];\n for (let i = 0; i < uvs.length; i++) {\n const k = i & 1;\n if (uvs[i] < lo[k]) lo[k] = uvs[i];\n if (uvs[i] > hi[k]) hi[k] = uvs[i];\n }\n if (count === 0) lo[0] = lo[1] = hi[0] = hi[1] = 0;\n const scale: [number, number] = [hi[0] - lo[0] || 1, hi[1] - lo[1] || 1];\n const packed = new Uint32Array(count);\n const q = (v: number, k: number) => Math.round(Math.max(0, Math.min(1, (v - lo[k]) / scale[k])) * 65535);\n for (let i = 0; i < count; i++) packed[i] = (q(uvs[i * 2], 0) | (q(uvs[i * 2 + 1], 1) << 16)) >>> 0;\n return { packed, scale, offset: [lo[0], lo[1]] };\n}\n\n/** Spread the low 10 bits of v so that two zero bits sit between consecutive ones. */\nfunction spreadBits10(v: number): number {\n v &= 0x3ff;\n v = (v | (v << 16)) & 0x030000ff;\n v = (v | (v << 8)) & 0x0300f00f;\n v = (v | (v << 4)) & 0x030c30c3;\n v = (v | (v << 2)) & 0x09249249;\n return v;\n}\n\n/**\n * Instance indices sorted along a 30-bit Morton curve over the instance centers, so that consecutive slots are\n * spatially close and a fixed-size run of slots forms a compact cell.\n */\nexport function mortonOrder(matrices: Float32Array, sphere: number[]): Uint32Array {\n const n = matrices.length / 16;\n const s = new Float64Array(4);\n const centers = new Float64Array(n * 3);\n const lo = [Infinity, Infinity, Infinity];\n const hi = [-Infinity, -Infinity, -Infinity];\n for (let i = 0; i < n; i++) {\n instanceSphere(matrices, i * 16, sphere, s);\n for (let a = 0; a < 3; a++) {\n centers[i * 3 + a] = s[a];\n lo[a] = Math.min(lo[a], s[a]);\n hi[a] = Math.max(hi[a], s[a]);\n }\n }\n const extent = Math.max(hi[0] - lo[0], hi[1] - lo[1], hi[2] - lo[2], 1e-9);\n const codes = new Uint32Array(n);\n for (let i = 0; i < n; i++) {\n const q = (a: number) => Math.min(1023, Math.max(0, Math.floor(((centers[i * 3 + a] - lo[a]) / extent) * 1024)));\n codes[i] = (spreadBits10(q(0)) | (spreadBits10(q(1)) << 1) | (spreadBits10(q(2)) << 2)) >>> 0;\n }\n return radixOrder(codes);\n}\n\n/**\n * Indices sorted by 30-bit key: LSD radix sort, two passes of 15 bits. O(n), and stable, so equal keys keep index\n * order (same result as a stable comparison sort). Millions of instances sort in tens of milliseconds.\n */\nfunction radixOrder(keys: Uint32Array): Uint32Array {\n const n = keys.length;\n let order = Uint32Array.from({ length: n }, (_, i) => i);\n let next = new Uint32Array(n);\n const counts = new Uint32Array(1 << 15);\n for (const shift of [0, 15]) {\n counts.fill(0);\n for (let i = 0; i < n; i++) counts[(keys[i] >>> shift) & 0x7fff]++;\n let sum = 0;\n for (let b = 0; b < counts.length; b++) {\n const c = counts[b];\n counts[b] = sum;\n sum += c;\n }\n for (let i = 0; i < n; i++) {\n const index = order[i];\n next[counts[(keys[index] >>> shift) & 0x7fff]++] = index;\n }\n [order, next] = [next, order];\n }\n return order;\n}\n","/**\n * A renderable set of instances of one preprocessed mesh (a three.js Mesh, so it goes into any scene).\n *\n * The geometry and instances live in a GeometryPool shared with other meshes; the pool's compute passes select\n * the cut for all of its meshes at once (see GeometryPool). This object holds the material and two geometries,\n * the camera cut and the shadow cut, which draw this mesh's region of the pool's index buffers.\n */\nimport * as THREE from 'three/webgpu';\nimport { cameraViewMatrix, faceDirection, hash, materialColor, normalize, select, vec3, vec4 } from 'three/tsl';\nimport { VG_DEBUG_MODES } from '../constants.js';\nimport type { VirtualMeshData } from '../preprocess/buildVirtualMesh.js';\nimport type { VirtualGeometry } from './VirtualGeometry.js';\nimport {\n CELL_SIZE,\n NO_DRAW_DISTANCE,\n mortonOrder,\n vgInstanceVarying,\n vgLodVarying,\n vgMeshletVarying,\n vgTintVarying,\n vgWorldNormal,\n type GeometryPool,\n type PoolEntry,\n} from './GeometryPool.js';\nimport { bindVirtualGeometryTextures } from './vgMaterial.js';\n\nexport { vgWorldNormal, encodeOctNormal, packVertices, packUvs } from './GeometryPool.js';\n\nexport interface VirtualMeshInstances {\n /** 16 floats (column-major Matrix4) per instance. */\n matrices: Float32Array;\n /** Optional rgba tint per instance (multiplied with the material color). */\n colors?: Float32Array;\n}\n\nexport interface VirtualMeshOptions {\n /**\n * Cull distance in world units: instances farther than this are not drawn (and cost almost nothing, since\n * whole cells are rejected at once). They shrink to nothing over the last 15% of the distance, so there is\n * no visible pop. Default: Infinity. Can be changed later via `mesh.maxDrawDistance`.\n */\n maxDrawDistance?: number;\n /**\n * Hide instances whose bounding sphere is smaller than this many pixels (radius) on screen. Combined with\n * `VirtualGeometry.minPixelRadius` (the larger one wins). Default: 0. Also settable via `mesh.minPixelRadius`.\n */\n minPixelRadius?: number;\n /** @deprecated Draw capacity is shared per pool now: see `VirtualGeometryOptions`. Ignored. */\n maxDrawnMeshlets?: number;\n /** @deprecated Draw capacity is shared per pool now: see `VirtualGeometryOptions`. Ignored. */\n maxDrawnTriangles?: number;\n}\n\ntype Node = any; // TSL node typings are too strict for the graph code below; runtime is verified in the browser\n\n/**\n * Untouched copy of every material a VirtualMesh has taken over. A mesh rewires its material's nodes, so two\n * meshes cannot share one material object: the second one gets a clone of the original instead, as if the caller\n * had passed separate materials.\n */\nconst pristineMaterials = new WeakMap<THREE.NodeMaterial, THREE.NodeMaterial>();\n\nfunction claimMaterial(material: THREE.NodeMaterial): THREE.NodeMaterial {\n const pristine = pristineMaterials.get(material);\n if (pristine) return pristine.clone();\n pristineMaterials.set(material, material.clone());\n return material;\n}\n\nfunction placeholderGeometry() {\n const geometry = new THREE.BufferGeometry();\n // Placeholder attributes; real vertex data is pulled from storage buffers in the vertex shader.\n geometry.setAttribute('position', new THREE.BufferAttribute(new Float32Array(3), 3));\n geometry.setAttribute('normal', new THREE.BufferAttribute(new Float32Array(3), 3));\n return geometry;\n}\n\nexport class VirtualMesh extends THREE.Mesh<THREE.BufferGeometry, THREE.NodeMaterial> {\n readonly isVirtualMesh = true;\n readonly data: VirtualMeshData;\n readonly instanceCount: number;\n readonly fullDetailTriangles: number;\n /** The pool holding this mesh's geometry and instances, and its record there. Set by `VirtualGeometry`. */\n pool!: GeometryPool;\n entry!: PoolEntry;\n /** Geometries drawing this mesh's region of the pool's camera and shadow index buffers. */\n readonly cameraGeometry = placeholderGeometry();\n readonly shadowGeometry = placeholderGeometry();\n /** `context.frameCount` of the last shadow-map render of this mesh. */\n lastShadowFrame = 0;\n /**\n * Lever: draw this mesh into the occlusion depth pass, so it can hide other geometry. Default: solid\n * materials (opaque, single-sided, no alpha test). Foliage is mostly holes, so it only gets tested.\n */\n occluder: boolean;\n /** Lever: let occlusion culling remove hidden instances and meshlets of this mesh. */\n occlusionCulling = true;\n /** GPU instance slot of each caller instance (inverse of the Morton order). */\n readonly gpuIndexOf: Uint32Array;\n /** Morton order: caller instance of each GPU slot. */\n readonly gpuToInput: Uint32Array;\n private readonly dirtyCells = new Set<number>();\n private drawingShadow = false;\n private poolVersion = -1;\n private readonly context: VirtualGeometry;\n\n /** Cull distance in world units (Infinity: never). See `VirtualMeshOptions.maxDrawDistance`. */\n get maxDrawDistance() {\n const d = this.pool.readFlag(this.entry, 'maxDrawDistance');\n return d >= NO_DRAW_DISTANCE ? Infinity : d;\n }\n set maxDrawDistance(distance: number) {\n this.pool.writeFlags(this.entry, { maxDrawDistance: Number.isFinite(distance) ? Math.max(0, distance) : NO_DRAW_DISTANCE });\n }\n\n /** Per-mesh minimum on-screen radius in pixels. See `VirtualMeshOptions.minPixelRadius`. */\n get minPixelRadius() {\n return this.pool.readFlag(this.entry, 'minPixelRadius');\n }\n set minPixelRadius(pixels: number) {\n this.pool.writeFlags(this.entry, { minPixelRadius: Math.max(0, pixels) });\n }\n\n /** The pool's per-frame draw capacity (shared by every mesh of the pool). */\n get capacity() {\n return { meshlets: this.pool.capacity.meshlets, triangles: this.pool.capacity.triangles };\n }\n\n constructor(context: VirtualGeometry, data: VirtualMeshData, material: THREE.NodeMaterial, instances: VirtualMeshInstances, options: VirtualMeshOptions = {}) {\n material = claimMaterial(material);\n const geometry = placeholderGeometry();\n super(geometry, material);\n this.context = context;\n this.data = data;\n this.frustumCulled = false; // culling happens on the GPU\n this.instanceCount = instances.matrices.length / 16;\n this.fullDetailTriangles = data.stats.leafTriangles * this.instanceCount;\n this.occluder = material.side !== THREE.DoubleSide && !material.transparent && material.alphaTest === 0 && !material.alphaHash;\n\n // The pool stores the instances in Morton order, so each cell is a contiguous range of slots.\n this.gpuToInput = mortonOrder(instances.matrices, data.boundingSphere);\n this.gpuIndexOf = new Uint32Array(this.instanceCount);\n for (let g = 0; g < this.instanceCount; g++) this.gpuIndexOf[this.gpuToInput[g]] = g;\n context.register(this, instances);\n if (options.maxDrawDistance !== undefined) this.maxDrawDistance = options.maxDrawDistance;\n if (options.minPixelRadius !== undefined) this.minPixelRadius = options.minPixelRadius;\n\n // Material: textures sample the pulled UVs, per-instance tint, debug views. The position node comes from\n // the pool (set in syncPool, again whenever the pool rebuilds its buffers).\n bindVirtualGeometryTextures(material);\n const base = vec4(material.colorNode ?? (materialColor as Node)).toVar() as Node;\n const randomColor = (seed: Node) => vec3(hash(seed), hash(seed.add(17.17)), hash(seed.add(43.43)));\n const debugColor = select(\n context.debugMode.equal(VG_DEBUG_MODES.meshlets),\n randomColor(vgMeshletVarying.add(vgInstanceVarying.mul(0.618))),\n select(context.debugMode.equal(VG_DEBUG_MODES.lodLevel), randomColor(vgLodVarying.add(3)), randomColor(vgInstanceVarying))\n );\n // Alpha passes through, so alpha-tested and transparent materials (and their shadows) keep working.\n material.colorNode = vec4(select(context.debugMode.equal(VG_DEBUG_MODES.shaded), base.xyz.mul(vgTintVarying), debugColor), base.w);\n // Two-sided foliage: back faces must light with the outward normal (normalNode is in view space).\n if (material.side === THREE.DoubleSide && !material.normalNode) {\n material.normalNode = normalize((cameraViewMatrix as Node).mul(vec4(vgWorldNormal, 0)).xyz.mul(faceDirection as Node));\n }\n this.syncPool();\n this.geometry = this.cameraGeometry;\n geometry.dispose();\n\n // The shadow pass calls onBeforeShadow and then onBeforeRender for each caster; the camera pass only\n // onBeforeRender. Each pass keeps its own render object and picks up `geometry` at draw time, so swapping\n // it here makes the shadow pass draw the shadow cut and the camera pass the camera cut.\n this.onBeforeShadow = (_renderer: unknown, _object: unknown, _camera: unknown, shadowCamera: THREE.Camera) => {\n this.lastShadowFrame = context.frameCount;\n context.noteShadowCamera(shadowCamera);\n this.drawingShadow = true;\n this.geometry = this.shadowGeometry;\n };\n // context.register() installed the auto-update hook as onBeforeRender: keep calling it after the swap.\n const autoUpdateHook = this.onBeforeRender;\n this.onBeforeRender = (...args: Parameters<THREE.Object3D['onBeforeRender']>) => {\n if (this.drawingShadow) this.drawingShadow = false;\n else this.geometry = this.cameraGeometry;\n autoUpdateHook.apply(this, args);\n };\n }\n\n /** Points the geometries and the material at the pool's current buffers and nodes (after a pool rebuild). */\n syncPool() {\n const pool = this.pool;\n if (this.poolVersion === pool.version || !pool.positionNode) return;\n this.poolVersion = pool.version;\n this.cameraGeometry.setIndex(pool.cameraIndex as unknown as THREE.BufferAttribute);\n this.cameraGeometry.setIndirect(pool.drawArgsAttribute, pool.drawArgsOffset(0, this.entry.slot));\n this.shadowGeometry.setIndex(pool.shadowIndex as unknown as THREE.BufferAttribute);\n this.shadowGeometry.setIndirect(pool.drawArgsAttribute, pool.drawArgsOffset(1, this.entry.slot));\n this.material.positionNode = pool.positionNode;\n this.material.needsUpdate = true;\n }\n\n /** Force the next `VirtualGeometry.update` to recompute the cut. */\n markCutDirty() {\n this.pool.dirty = true;\n }\n\n /** Update one instance transform. Call `commitInstances()` after a batch of changes. */\n setMatrixAt(index: number, matrix: THREE.Matrix4) {\n const slot = this.gpuIndexOf[index];\n this.pool.setMatrix(this.entry, slot, matrix);\n this.dirtyCells.add(Math.floor(slot / CELL_SIZE));\n }\n\n commitInstances() {\n this.pool.commitInstances(this.entry, this.dirtyCells);\n this.dirtyCells.clear();\n }\n\n /**\n * Stop rendering this mesh and drop it from its context. The GPU buffers are released when the\n * renderer frees them; call this before removing the object from the scene for good.\n */\n dispose(context?: VirtualGeometry) {\n this.visible = false;\n (context ?? this.context).unregister(this);\n this.removeFromParent();\n }\n\n /** Triangles drawn for this mesh by the last computed cut (camera and shadow), from one readback. */\n async readStats(renderer: THREE.WebGPURenderer) {\n const c = await this.pool.readCounters(renderer);\n return { drawnTriangles: c.perMesh(0, this.entry.slot), shadowTriangles: c.perMesh(1, this.entry.slot) };\n }\n}\n","import * as THREE from 'three/webgpu';\n\ntype MaterialClass = new () => THREE.Material;\n\n/** Classic mesh material type -> [classic class (whose copy() knows every property), node material class]. */\nconst CONVERSIONS: Record<string, [MaterialClass, new () => THREE.NodeMaterial]> = {\n MeshPhysicalMaterial: [THREE.MeshPhysicalMaterial, THREE.MeshPhysicalNodeMaterial],\n MeshStandardMaterial: [THREE.MeshStandardMaterial, THREE.MeshStandardNodeMaterial],\n MeshPhongMaterial: [THREE.MeshPhongMaterial, THREE.MeshPhongNodeMaterial],\n MeshLambertMaterial: [THREE.MeshLambertMaterial, THREE.MeshLambertNodeMaterial],\n MeshBasicMaterial: [THREE.MeshBasicMaterial, THREE.MeshBasicNodeMaterial],\n MeshToonMaterial: [THREE.MeshToonMaterial, THREE.MeshToonNodeMaterial],\n MeshMatcapMaterial: [THREE.MeshMatcapMaterial, THREE.MeshMatcapNodeMaterial],\n MeshNormalMaterial: [THREE.MeshNormalMaterial, THREE.MeshNormalNodeMaterial],\n};\n\n/** Subclasses keep their parent's flags: check the most derived first. */\nconst FLAGS: [string, string][] = [\n ['isMeshPhysicalMaterial', 'MeshPhysicalMaterial'],\n ['isMeshStandardMaterial', 'MeshStandardMaterial'],\n ['isMeshPhongMaterial', 'MeshPhongMaterial'],\n ['isMeshLambertMaterial', 'MeshLambertMaterial'],\n ['isMeshBasicMaterial', 'MeshBasicMaterial'],\n ['isMeshToonMaterial', 'MeshToonMaterial'],\n ['isMeshMatcapMaterial', 'MeshMatcapMaterial'],\n ['isMeshNormalMaterial', 'MeshNormalMaterial'],\n];\n\nfunction conversionOf(material: THREE.Material) {\n const flags = material as unknown as Record<string, unknown>;\n const type = CONVERSIONS[material.type] ? material.type : FLAGS.find(([flag]) => flags[flag] === true)?.[1];\n return type ? CONVERSIONS[type] : null;\n}\n\n/** True when `toNodeMaterial` can convert the material (node materials, and the classic mesh materials). */\nexport function canConvertToNodeMaterial(material: THREE.Material): boolean {\n return (material as THREE.NodeMaterial).isNodeMaterial === true || conversionOf(material) !== null;\n}\n\n/**\n * The node-material equivalent of a classic mesh material: MeshStandardMaterial -> MeshStandardNodeMaterial,\n * and likewise for Physical, Phong, Lambert, Basic, Toon, Matcap and Normal. Every property is copied (colors,\n * maps and their texture objects, transparency, alphaTest, side, blending, userData, ...). Node materials are\n * returned as they are; materials without a node equivalent (ShaderMaterial, ...) return null.\n */\nexport function toNodeMaterial(material: THREE.Material): THREE.NodeMaterial | null {\n if ((material as THREE.NodeMaterial).isNodeMaterial) return material as THREE.NodeMaterial;\n const conversion = conversionOf(material);\n if (!conversion) return null;\n const [Classic, Node] = conversion;\n const result = new Node();\n const defines = (result as unknown as { defines?: unknown }).defines;\n // The classic copy() lists every property of its material type; the node material has the same ones.\n (Classic.prototype.copy as (this: THREE.Material, source: THREE.Material) => THREE.Material).call(result, material);\n (result as unknown as { defines?: unknown }).defines = defines;\n return result;\n}\n","import * as THREE from 'three/webgpu';\nimport type { VirtualMeshSource } from './core/preprocess/buildVirtualMesh.js';\n\ntype Attribute = THREE.BufferAttribute | THREE.InterleavedBufferAttribute;\n\nexport interface FromGeometryOptions {\n /**\n * Keep the `uv` attribute. Vertices are then welded by position and UV, so UV seams stay separate vertices\n * (the simplifier treats them as seams, not borders). Default: true when the geometry has a `uv` attribute.\n */\n uvs?: boolean;\n /** Keep the `color` attribute as per-vertex colors (multiplied with the material color). Default: false. */\n colors?: boolean;\n /**\n * 'compute' (default): smooth normals over the position-welded mesh, ignoring the `normal` attribute.\n * 'keep': use the geometry's normals; vertices with different normals stay separate, so hard edges stay hard.\n */\n normals?: 'compute' | 'keep';\n /** Only this range of the index buffer (or of the vertices, for non-indexed geometry), e.g. one of `geometry.groups`. */\n range?: { start: number; count: number };\n}\n\n/** Weld tolerance per channel: positions and UVs need to match almost exactly, normals and colors a little less. */\nconst POSITION_TOLERANCE = 1e-6;\nconst ATTRIBUTE_TOLERANCE = 1e-4;\n\n/**\n * Weld vertices and produce a `VirtualMeshSource`. By default vertices are welded by position (and UV when the\n * geometry has UVs) and get smooth normals, so meshlets share edges. See `FromGeometryOptions`.\n */\nexport function fromBufferGeometry(geometry: THREE.BufferGeometry, options: FromGeometryOptions = {}): VirtualMeshSource {\n const position = geometry.attributes.position as Attribute;\n const uv = (options.uvs ?? true) ? (geometry.attributes.uv as Attribute | undefined) : undefined;\n const color = options.colors ? (geometry.attributes.color as Attribute | undefined) : undefined;\n const normal = options.normals === 'keep' ? (geometry.attributes.normal as Attribute | undefined) : undefined;\n const index = geometry.index;\n const total = index ? index.count : position.count;\n const start = Math.max(0, Math.min(total, options.range?.start ?? 0));\n const count = Math.floor((Math.min(total, start + (options.range?.count ?? total)) - start) / 3) * 3;\n const vertexOf = (corner: number) => (index ? index.getX(start + corner) : start + corner);\n\n // Position-only weld: the topology smooth normals are computed on (and the whole result when nothing else is kept).\n const byPosition = weld(count, vertexOf, [{ attribute: position, size: 3, tolerance: POSITION_TOLERANCE }]);\n const positions = gather(byPosition.firstVertex, position, 3);\n let smoothNormals: Float32Array | null = null;\n if (!normal) {\n const g = new THREE.BufferGeometry();\n g.setAttribute('position', new THREE.BufferAttribute(positions, 3));\n g.setIndex(new THREE.BufferAttribute(byPosition.indices, 1));\n g.computeVertexNormals();\n smoothNormals = g.attributes.normal.array as Float32Array;\n }\n if (!uv && !color && !normal) return { positions, normals: smoothNormals!, indices: byPosition.indices };\n\n // Full weld: vertices that differ in any kept attribute stay separate (seams).\n const channels = [{ attribute: position, size: 3, tolerance: POSITION_TOLERANCE }];\n if (uv) channels.push({ attribute: uv, size: 2, tolerance: POSITION_TOLERANCE });\n if (normal) channels.push({ attribute: normal, size: 3, tolerance: ATTRIBUTE_TOLERANCE });\n if (color) channels.push({ attribute: color, size: 3, tolerance: ATTRIBUTE_TOLERANCE });\n const full = weld(count, vertexOf, channels);\n const result: VirtualMeshSource = { positions: gather(full.firstVertex, position, 3), normals: new Float32Array(0), indices: full.indices };\n if (normal) {\n result.normals = gather(full.firstVertex, normal, 3);\n for (let i = 0; i < result.normals.length; i += 3) {\n const l = Math.hypot(result.normals[i], result.normals[i + 1], result.normals[i + 2]) || 1;\n result.normals[i] /= l;\n result.normals[i + 1] /= l;\n result.normals[i + 2] /= l;\n }\n } else {\n // Every seam copy of a vertex gets the smooth normal of its position.\n result.normals = new Float32Array(full.firstVertex.length * 3);\n for (let w = 0; w < full.firstVertex.length; w++) {\n const p = byPosition.indices[full.firstCorner[w]];\n result.normals.set(smoothNormals!.subarray(p * 3, p * 3 + 3), w * 3);\n }\n }\n if (uv) result.uvs = gather(full.firstVertex, uv, 2);\n if (color) result.colors = gather(full.firstVertex, color, 3);\n return result;\n}\n\nfunction gather(vertices: Uint32Array, attribute: Attribute, size: number): Float32Array {\n const out = new Float32Array(vertices.length * size);\n for (let i = 0; i < vertices.length; i++) {\n for (let k = 0; k < size; k++) out[i * size + k] = attribute.getComponent(vertices[i], k);\n }\n return out;\n}\n\n/**\n * Same result as three's `mergeVertices` on the given channels (same quantization, vertices in first-use\n * order), but with an open-addressing hash table on the quantized values instead of string keys: about 10x\n * faster on million-triangle meshes. Returns, per welded vertex, the source vertex and corner that created it.\n */\nfunction weld(\n count: number,\n vertexOf: (corner: number) => number,\n channels: { attribute: Attribute; size: number; tolerance: number }[]\n) {\n const width = channels.reduce((a, c) => a + c.size, 0);\n const quantize = channels.map(({ tolerance }) => {\n const multiplier = Math.pow(10, Math.log10(1 / tolerance));\n return { multiplier, additive: tolerance * 0.5 * multiplier };\n });\n let size = 1;\n while (size < count * 2) size <<= 1;\n const mask = size - 1;\n const table = new Int32Array(size).fill(-1); // slot -> welded vertex\n const keys = new Float64Array(count * width); // quantized values per welded vertex (exact integers)\n const key = new Float64Array(width);\n const firstVertex = new Uint32Array(count);\n const firstCorner = new Uint32Array(count);\n const indices = new Uint32Array(count);\n let welded = 0;\n for (let i = 0; i < count; i++) {\n const v = vertexOf(i);\n let h = 0;\n let o = 0;\n for (let c = 0; c < channels.length; c++) {\n const { attribute, size: n } = channels[c];\n const { multiplier, additive } = quantize[c];\n for (let k = 0; k < n; k++, o++) {\n key[o] = Math.trunc(attribute.getComponent(v, k) * multiplier + additive);\n h = (h ^ Math.imul(key[o] | 0, HASH_PRIMES[o % HASH_PRIMES.length])) | 0;\n }\n }\n h &= mask;\n for (;;) {\n const w = table[h];\n if (w < 0) {\n table[h] = welded;\n keys.set(key, welded * width);\n firstVertex[welded] = v;\n firstCorner[welded] = i;\n indices[i] = welded++;\n break;\n }\n let same = true;\n for (let k = 0; k < width && same; k++) same = keys[w * width + k] === key[k];\n if (same) {\n indices[i] = w;\n break;\n }\n h = (h + 1) & mask;\n }\n }\n return { indices, firstVertex: firstVertex.slice(0, welded), firstCorner: firstCorner.slice(0, welded) };\n}\n\nconst HASH_PRIMES = [73856093, 19349663, 83492791, 2654435761, 2246822519, 3266489917, 668265263, 374761393, 1181783497, 3735928559, 2028178513];\n\n/**\n * Concatenate several already-welded meshes into one source mesh with per-vertex colors.\n * Each part uses its own `colors` if present, otherwise the given flat `color`.\n */\nexport function mergeSources(parts: { mesh: VirtualMeshSource; color?: THREE.ColorRepresentation }[]): VirtualMeshSource {\n const vertexCount = parts.reduce((a, p) => a + p.mesh.positions.length / 3, 0);\n const indexCount = parts.reduce((a, p) => a + p.mesh.indices.length, 0);\n const positions = new Float32Array(vertexCount * 3);\n const normals = new Float32Array(vertexCount * 3);\n const colors = new Float32Array(vertexCount * 3);\n const uvs = parts.some((p) => p.mesh.uvs) ? new Float32Array(vertexCount * 2) : null;\n const indices = new Uint32Array(indexCount);\n const c = new THREE.Color();\n let v = 0;\n let i = 0;\n for (const { mesh, color = 0xffffff } of parts) {\n const n = mesh.positions.length / 3;\n positions.set(mesh.positions, v * 3);\n normals.set(mesh.normals, v * 3);\n if (uvs && mesh.uvs) uvs.set(mesh.uvs, v * 2);\n if (mesh.colors) colors.set(mesh.colors, v * 3);\n else {\n c.set(color);\n for (let k = 0; k < n; k++) colors.set([c.r, c.g, c.b], (v + k) * 3);\n }\n for (let k = 0; k < mesh.indices.length; k++) indices[i + k] = mesh.indices[k] + v;\n v += n;\n i += mesh.indices.length;\n }\n return uvs ? { positions, normals, colors, uvs, indices } : { positions, normals, colors, indices };\n}\n","/**\n * One-call scene import: every static mesh of an Object3D (e.g. a loaded glTF scene) becomes VirtualGeometry geometry.\n *\n * Meshes are grouped by (geometry, geometry group, material, render flags), so repeated geometry becomes one\n * VirtualMesh with one instance per occurrence (InstancedMesh instances included). Each unique geometry range\n * is built once. Skinned and morphing meshes, points, lines and sprites are left alone and keep rendering.\n */\nimport * as THREE from 'three/webgpu';\nimport { buildVirtualMeshCached } from '../io/cache.js';\nimport { buildVirtualMesh, type VirtualMeshBuildOptions, type VirtualMeshData, type VirtualMeshSource } from '../preprocess/buildVirtualMesh.js';\nimport { fromBufferGeometry } from '../../source.js';\nimport type { VirtualGeometry } from '../runtime/VirtualGeometry.js';\nimport type { VirtualMesh, VirtualMeshOptions } from '../runtime/VirtualMesh.js';\nimport { canConvertToNodeMaterial, toNodeMaterial } from './toNodeMaterial.js';\n\n/** Builds one DAG. Same signature as `buildVirtualMesh`, so a caching builder drops in here or via `options.builder`. */\nexport type VirtualGeometryBuilder = (source: VirtualMeshSource, options?: VirtualMeshBuildOptions) => Promise<VirtualMeshData>;\n// Cached in IndexedDB: importing the same model again (e.g. the next page load) skips the build.\nconst defaultBuilder: VirtualGeometryBuilder = buildVirtualMeshCached;\n\nexport interface VirtualGeometryImportOptions {\n /** DAG build options for every geometry (`onProgress` is driven by the import; use `onProgress` below). */\n build?: Omit<VirtualMeshBuildOptions, 'onProgress'>;\n /** Options for each created VirtualMesh (e.g. `maxDrawDistance`), or a function returning them per group. */\n mesh?: VirtualMeshOptions | ((group: VirtualGeometryImportGroup) => VirtualMeshOptions | undefined);\n /** Return false to leave a mesh as it is (it keeps rendering normally). Called for every compatible mesh. */\n filter?: (mesh: THREE.Mesh) => boolean;\n /**\n * true (default): the VirtualMeshes are added to `object` and the converted meshes stop rendering (their\n * leaf meshes are taken out of the graph, meshes with children stay with their layers cleared; `dispose()`\n * restores both). false: nothing in the scene changes; add `result.object` yourself.\n */\n replace?: boolean;\n /** Overall progress in 0..1 while building. May be async (awaited), e.g. to let the page repaint. */\n onProgress?: (fraction: number) => void | Promise<void>;\n /** Converts a source material. Default: node materials are cloned, classic mesh materials go through `toNodeMaterial`. */\n material?: (material: THREE.Material, group: VirtualGeometryImportGroup) => THREE.NodeMaterial | null;\n /** DAG builder (default `buildVirtualMesh`), e.g. a cached one with the same signature. */\n builder?: VirtualGeometryBuilder;\n}\n\n/** Meshes that share geometry, geometry range, material and render flags: one VirtualMesh. */\nexport interface VirtualGeometryImportGroup {\n geometry: THREE.BufferGeometry;\n /** Index range (vertex range for non-indexed geometry) this group draws: one entry of `geometry.groups`, clipped to the draw range. */\n range: { start: number; count: number };\n material: THREE.Material;\n /** Column-major world matrix per instance (16 floats each), in the order of `instances`. */\n matrices: Float32Array;\n /** rgba per instance, from `InstancedMesh.instanceColor` (null when no source has instance colors). */\n colors: Float32Array | null;\n /** Source of each instance: the mesh, and the instance index for an InstancedMesh (else -1). */\n instances: { object: THREE.Mesh; index: number }[];\n /** Per-vertex colors are used (`material.vertexColors` and a `color` attribute), like three would. */\n vertexColors: boolean;\n castShadow: boolean;\n receiveShadow: boolean;\n /** False when the mesh or one of its ancestors is hidden. */\n visible: boolean;\n renderOrder: number;\n layers: number;\n /** From the first source mesh. */\n name: string;\n userData: Record<string, unknown>;\n}\n\nconst converted = new WeakSet<THREE.Object3D>();\n\n/** Why a mesh is left alone, or null when it can be converted. */\nexport function incompatibility(mesh: THREE.Object3D): string | null {\n const m = mesh as THREE.Mesh & { isSkinnedMesh?: boolean; isBatchedMesh?: boolean; isVirtualMesh?: boolean };\n if (!m.isMesh) return 'not a mesh';\n if (m.isVirtualMesh) return 'already a VirtualMesh';\n if (m.isSkinnedMesh) return 'skinned';\n if (m.isBatchedMesh) return 'batched';\n const geometry = m.geometry;\n if (!geometry?.attributes?.position || (geometry as THREE.InstancedBufferGeometry).isInstancedBufferGeometry) return 'unsupported geometry';\n const morph = geometry.morphAttributes;\n if ((morph.position?.length ?? 0) > 0 || (morph.normal?.length ?? 0) > 0 || (m.morphTargetInfluences?.length ?? 0) > 0) return 'morph targets';\n const materials = Array.isArray(m.material) ? m.material : [m.material];\n if (materials.some((mat) => !mat || !canConvertToNodeMaterial(mat))) return 'material without a node equivalent';\n return null;\n}\n\n/**\n * Collects the convertible meshes under `root` into instance groups (pure CPU work, no GPU, testable in Node).\n * World matrices are read after updating them, so the result matches what three would render now.\n */\nexport function collectVirtualGeometryGroups(root: THREE.Object3D, filter?: (mesh: THREE.Mesh) => boolean) {\n root.updateWorldMatrix(true, true);\n const groups = new Map<string, VirtualGeometryImportGroup & { matrixList: number[]; colorList: number[] | null }>();\n const meshes: THREE.Mesh[] = [];\n const skipped: { object: THREE.Object3D; reason: string }[] = [];\n const instanceMatrix = new THREE.Matrix4();\n const world = new THREE.Matrix4();\n const color = new THREE.Color();\n\n root.traverse((object) => {\n if (!(object as THREE.Mesh).isMesh || converted.has(object)) return;\n const mesh = object as THREE.Mesh;\n const reason = incompatibility(mesh) ?? (filter && !filter(mesh) ? 'filtered out' : null);\n if (reason) {\n skipped.push({ object: mesh, reason });\n return;\n }\n const geometry = mesh.geometry;\n const materials = Array.isArray(mesh.material) ? mesh.material : [mesh.material];\n const drawn = drawnRanges(geometry, Array.isArray(mesh.material));\n if (drawn.length === 0) return;\n meshes.push(mesh);\n const instanced = (mesh as THREE.InstancedMesh).isInstancedMesh ? (mesh as THREE.InstancedMesh) : null;\n const count = instanced ? instanced.count : 1;\n const visible = isVisible(mesh);\n\n for (const { start, count: rangeCount, materialIndex } of drawn) {\n const material = materials[materialIndex];\n if (!material) continue;\n const vertexColors = material.vertexColors === true && geometry.attributes.color !== undefined;\n const key = [geometry.id, start, rangeCount, material.uuid, mesh.castShadow, mesh.receiveShadow, visible, mesh.renderOrder, mesh.layers.mask].join(':');\n let group = groups.get(key);\n if (!group) {\n group = {\n geometry,\n range: { start, count: rangeCount },\n material,\n matrices: new Float32Array(0),\n colors: null,\n instances: [],\n vertexColors,\n castShadow: mesh.castShadow,\n receiveShadow: mesh.receiveShadow,\n visible,\n renderOrder: mesh.renderOrder,\n layers: mesh.layers.mask,\n name: mesh.name,\n userData: { ...mesh.userData },\n matrixList: [],\n colorList: null,\n };\n groups.set(key, group);\n }\n for (let i = 0; i < count; i++) {\n if (instanced) {\n instanced.getMatrixAt(i, instanceMatrix);\n world.multiplyMatrices(mesh.matrixWorld, instanceMatrix);\n } else world.copy(mesh.matrixWorld);\n group.matrixList.push(...world.elements);\n const tinted = !!instanced?.instanceColor;\n if (tinted) instanced!.getColorAt(i, color);\n if (tinted && !group.colorList) group.colorList = new Array(group.instances.length * 4).fill(1);\n if (group.colorList) {\n if (tinted) group.colorList.push(color.r, color.g, color.b, 1);\n else group.colorList.push(1, 1, 1, 1);\n }\n group.instances.push({ object: mesh, index: instanced ? i : -1 });\n }\n }\n });\n\n const result: VirtualGeometryImportGroup[] = [];\n for (const { matrixList, colorList, ...group } of groups.values()) {\n group.matrices = Float32Array.from(matrixList);\n group.colors = colorList ? Float32Array.from(colorList) : null;\n result.push(group);\n }\n return { groups: result, meshes, skipped };\n}\n\n/** The (start, count, materialIndex) ranges three draws for this geometry, clipped to its draw range. */\nfunction drawnRanges(geometry: THREE.BufferGeometry, multiMaterial: boolean) {\n const total = geometry.index ? geometry.index.count : geometry.attributes.position.count;\n const drawStart = Math.max(0, geometry.drawRange.start);\n const drawEnd = Math.min(total, drawStart + geometry.drawRange.count);\n const ranges = multiMaterial ? geometry.groups : [{ start: 0, count: total, materialIndex: 0 }];\n const out: { start: number; count: number; materialIndex: number }[] = [];\n for (const g of ranges) {\n const start = Math.max(g.start, drawStart);\n const end = Math.min(g.start + g.count, drawEnd);\n if (end - start >= 3) out.push({ start, count: end - start, materialIndex: g.materialIndex ?? 0 });\n }\n return out;\n}\n\nfunction isVisible(object: THREE.Object3D) {\n for (let o: THREE.Object3D | null = object; o; o = o.parent) if (!o.visible) return false;\n return true;\n}\n\n/** Result of `VirtualGeometry.add()`: the created meshes, and how to undo the import. */\nexport class VirtualGeometryImport {\n /** Holds every created VirtualMesh. Added to the imported object unless `replace: false`. */\n readonly object = new THREE.Group();\n /** One VirtualMesh per entry of `groups`. */\n readonly meshes: VirtualMesh[] = [];\n groups: VirtualGeometryImportGroup[];\n /** Meshes that were left alone, and why. */\n readonly skipped: { object: THREE.Object3D; reason: string }[];\n readonly stats = { sourceMeshes: 0, instances: 0, uniqueGeometries: 0, buildMs: 0 };\n private readonly hidden = new Map<THREE.Object3D, number>();\n /** Converted leaf meshes taken out of the graph, with their former parent (restored by `dispose`). */\n private readonly detached = new Map<THREE.Object3D, THREE.Object3D>();\n\n constructor(\n private readonly context: VirtualGeometry,\n collected: ReturnType<typeof collectVirtualGeometryGroups>\n ) {\n this.object.name = 'VirtualGeometryImport';\n this.groups = collected.groups;\n this.skipped = collected.skipped;\n this.stats.sourceMeshes = collected.meshes.length;\n this.stats.instances = collected.groups.reduce((a, g) => a + g.instances.length, 0);\n }\n\n /** @internal Stops the given source meshes from rendering (restored by `dispose`). */\n hide(meshes: THREE.Mesh[], root: THREE.Object3D) {\n const emptied = new Set<THREE.Object3D>();\n for (const mesh of meshes) {\n converted.add(mesh);\n // Leaf meshes leave the graph: three.js would still traverse them every frame (matrix updates and\n // render-list projection), which costs more CPU than the rendering itself in scenes with thousands of\n // props. Meshes with children (lights, skinned parts, ...) stay, with their layers cleared.\n if (mesh.children.length === 0 && mesh.parent) {\n this.detached.set(mesh, mesh.parent);\n emptied.add(mesh.parent);\n mesh.parent.remove(mesh);\n continue;\n }\n if (!this.hidden.has(mesh)) this.hidden.set(mesh, mesh.layers.mask);\n mesh.layers.disableAll();\n }\n // Plain groups left empty (e.g. one root node per prop) go too, walking up, but never `root` itself.\n for (let node of emptied) {\n while (node !== root && node.children.length === 0 && node.parent && (node.type === 'Group' || node.type === 'Object3D')) {\n const parent: THREE.Object3D = node.parent;\n this.detached.set(node, parent);\n parent.remove(node);\n node = parent;\n }\n }\n }\n\n /** World matrix of a source object, also when it (or its ancestors) were taken out of the graph. */\n private worldMatrixOf(object: THREE.Object3D): THREE.Matrix4 {\n const parent = this.detached.get(object);\n if (!parent) {\n object.updateWorldMatrix(true, false);\n return object.matrixWorld;\n }\n object.updateMatrix();\n return object.matrixWorld.multiplyMatrices(this.worldMatrixOf(parent), object.matrix);\n }\n\n /**\n * Re-reads every source mesh's current world matrix into the instances (call after moving the imported\n * object or animating its nodes). Instances are baked in world space at import time otherwise.\n */\n syncTransforms() {\n const m = new THREE.Matrix4();\n const instanceMatrix = new THREE.Matrix4();\n const roots = new Set<THREE.Object3D>();\n this.groups.forEach((group, g) => {\n const mesh = this.meshes[g];\n group.instances.forEach(({ object, index }, i) => {\n if (!roots.has(object)) {\n this.worldMatrixOf(object);\n roots.add(object);\n }\n if (index >= 0) {\n (object as THREE.InstancedMesh).getMatrixAt(index, instanceMatrix);\n m.multiplyMatrices(object.matrixWorld, instanceMatrix);\n } else m.copy(object.matrixWorld);\n mesh.setMatrixAt(i, m);\n });\n mesh.commitInstances();\n });\n }\n\n /** Removes the VirtualMeshes and lets the source meshes render again. */\n dispose() {\n for (const mesh of this.meshes) {\n mesh.dispose(this.context);\n mesh.material.dispose();\n mesh.geometry.dispose();\n }\n this.meshes.length = 0;\n for (const [mesh, mask] of this.hidden) {\n mesh.layers.mask = mask;\n converted.delete(mesh);\n }\n this.hidden.clear();\n for (const [mesh, parent] of this.detached) {\n parent.add(mesh);\n converted.delete(mesh);\n }\n this.detached.clear();\n this.object.removeFromParent();\n }\n}\n\n/**\n * Converts every compatible mesh under `object` to VirtualGeometry geometry. See `VirtualGeometry.add`.\n */\nexport async function virtualMeshesFromObject3D(context: VirtualGeometry, object: THREE.Object3D, options: VirtualGeometryImportOptions = {}): Promise<VirtualGeometryImport> {\n const t0 = performance.now();\n const build = options.builder ?? defaultBuilder;\n const collected = collectVirtualGeometryGroups(object, options.filter);\n const result = new VirtualGeometryImport(context, collected);\n\n // One build per geometry range (and vertex color use): groups that differ only in material or flags share it.\n const sources = new Map<string, { group: VirtualGeometryImportGroup; triangles: number; data?: VirtualMeshData }>();\n const sourceKey = (g: VirtualGeometryImportGroup) => `${g.geometry.id}:${g.range.start}:${g.range.count}:${g.vertexColors}`;\n for (const group of result.groups) {\n const key = sourceKey(group);\n if (!sources.has(key)) sources.set(key, { group, triangles: group.range.count / 3 });\n }\n result.stats.uniqueGeometries = sources.size;\n const total = [...sources.values()].reduce((a, s) => a + s.triangles, 0) || 1;\n let done = 0;\n for (const source of sources.values()) {\n const { geometry, range, vertexColors } = source.group;\n const mesh = fromBufferGeometry(geometry, {\n range,\n colors: vertexColors,\n normals: geometry.attributes.normal ? 'keep' : 'compute',\n });\n source.data = await build(mesh, {\n ...options.build,\n onProgress: (f) => options.onProgress?.((done + f * source.triangles) / total),\n });\n done += source.triangles;\n }\n\n const materials = new Map<string, THREE.NodeMaterial | null>();\n const createdGroups: VirtualGeometryImportGroup[] = [];\n const failed = new Set<THREE.Object3D>();\n for (const group of result.groups) {\n const material = convertMaterial(group, options, materials);\n if (!material) {\n for (const { object: source } of group.instances) failed.add(source);\n continue;\n }\n const meshOptions = typeof options.mesh === 'function' ? options.mesh(group) : options.mesh;\n const mesh = context.createMesh(sources.get(sourceKey(group))!.data!, material, { matrices: group.matrices, colors: group.colors ?? undefined }, meshOptions);\n // Vertices are pulled in world space: the mesh itself must stay at identity wherever it is attached.\n mesh.matrixAutoUpdate = false;\n mesh.matrixWorldAutoUpdate = false;\n mesh.name = group.name;\n mesh.userData = { ...group.userData };\n mesh.castShadow = group.castShadow;\n mesh.receiveShadow = group.receiveShadow;\n mesh.visible = group.visible;\n mesh.renderOrder = group.renderOrder;\n mesh.layers.mask = group.layers;\n result.meshes.push(mesh);\n createdGroups.push(group);\n result.object.add(mesh);\n }\n result.groups = createdGroups;\n\n if (options.replace ?? true) {\n // A mesh with any part that could not be converted keeps rendering (its converted parts are drawn twice).\n result.hide(collected.meshes.filter((m) => !failed.has(m)), object);\n object.add(result.object);\n }\n await options.onProgress?.(1);\n result.stats.buildMs = performance.now() - t0;\n return result;\n}\n\n/**\n * Node material for a group. Node materials are cloned so the source mesh keeps its own (VirtualMesh rewires the\n * material it gets). glTF normal maps authored against tangents need the derivative-tangent sign (normalScale.y\n * flipped), which GLTFLoader only applies when the geometry has no tangents.\n */\nfunction convertMaterial(group: VirtualGeometryImportGroup, options: VirtualGeometryImportOptions, cache: Map<string, THREE.NodeMaterial | null>) {\n const source = group.material as THREE.MeshStandardMaterial;\n const flipNormalY = !!(source.normalMap && group.geometry.attributes.tangent && source.normalMap.flipY === false);\n const key = `${source.uuid}:${flipNormalY}`;\n if (cache.has(key)) return cache.get(key)!;\n let material: THREE.NodeMaterial | null;\n if (options.material) material = options.material(source, group);\n else {\n material = toNodeMaterial(source);\n if (material === (source as THREE.Material)) material = (source as unknown as THREE.NodeMaterial).clone();\n }\n if (material && flipNormalY) {\n const scale = (material as unknown as { normalScale?: THREE.Vector2 }).normalScale;\n if (scale) (material as unknown as { normalScale: THREE.Vector2 }).normalScale = scale.clone().setY(-scale.y);\n }\n cache.set(key, material);\n return material;\n}\n","/**\n * Occlusion culling against a hierarchical depth buffer (HZB), on by default.\n *\n * Per frame, before the cut is computed:\n * 1. occluder pass - the occluder meshes' previous-frame camera cuts (their index buffers still hold them)\n * are drawn depth-only with the CURRENT camera into a small depth target. That geometry was visible last\n * frame, so it is a subset of the real occluders.\n * 2. HZB build - mip 0 is that depth (copied into a storage buffer), each further mip is the MAX of its\n * 2x2 children: a texel only hides what lies behind all of its occluders.\n * 3. cull - an instance or meshlet sphere is dropped from the camera cut when its projected box, read at\n * the mip where it covers at most 2x2 texels, is entirely behind the max depth there.\n *\n * Why it is safe: removing occluders can only push the depth buffer back, so anything hidden by the subset\n * is hidden by the full scene. Stale or missing occluders cost efficiency, never correctness. The occluders\n * are LOD-simplified (they may bulge up to the error threshold in front of the true surface), so the tested\n * sphere is grown by that error first.\n *\n * Only meshes flagged `occluder` are drawn in step 1 (by default: opaque, single-sided, no alpha test, i.e.\n * solid geometry such as terrain, rocks, buildings; foliage is mostly holes). Every mesh is tested, unless\n * its `occlusionCulling` is off. Shadow cuts are never occlusion culled: a caster hidden from the camera can\n * still shadow something visible.\n *\n * Storage: the whole HZB (a header with each mip's offset and size, then all mips) is one storage buffer,\n * sized for `maxSize`, so nothing is reallocated on resize.\n */\nimport * as THREE from 'three/webgpu';\nimport { Fn, If, Return, ceil, clamp, exp2, float, floor, instanceIndex, int, ivec2, log2, max, min, select, storage, texture, uint, uniform, vec3, vec4 } from 'three/tsl';\nimport type { VirtualMesh } from './VirtualMesh.js';\n\n/** Upper bound on mip levels (maxSize up to 32768). */\nconst MAX_LEVELS = 16;\n/** Header at the start of the HZB buffer: per level [offset, width, height, 0], then the level count. */\nconst HEADER_SIZE = MAX_LEVELS * 4 + 4;\nconst LEVEL_COUNT_SLOT = MAX_LEVELS * 4;\nconst WORKGROUP = 64;\nconst NO_NODES: THREE.ComputeNode[] = [];\n\n/** Mean frame time: with pipelined or batched submission, single frame times vary; the mean is the throughput. */\nconst mean = (values: number[]) => values.reduce((a, b) => a + b, 0) / values.length;\n\nconst minNode = min as (a: unknown, b: unknown) => any; // eslint-disable-line @typescript-eslint/no-explicit-any\nconst maxNode = max as (a: unknown, b: unknown) => any; // eslint-disable-line @typescript-eslint/no-explicit-any\ntype Node = any; // TSL node typings are too strict for the graph code below; runtime is verified in the browser\n\nexport class OcclusionCulling {\n /** Lever: set false to turn occlusion culling off (no occluder pass, no HZB, nothing culled by it). */\n enabled = true;\n /**\n * Lever: decide by measurement. Whether occlusion pays off depends on the scene and the GPU: the occluder\n * pass has a fixed cost, which wins in cities and interiors and loses in open landscapes. With `auto`,\n * frame times are compared with occlusion off and on (`autoProbeFrames` each), the faster setting is kept\n * for `autoHoldFrames`, then measured again. Within 3% (e.g. both capped by vsync) it stays off.\n * Set false to keep it on whenever `enabled`.\n */\n auto = true;\n autoProbeFrames = 40;\n autoHoldFrames = 900;\n /** The auto setting currently in use (true: occlusion on). */\n autoChoice = false;\n // Starts in 'hold' (off) and probes after a 120-frame warm-up: the first frames compile pipelines.\n private phase: 'probeOff' | 'probeOn' | 'hold' = 'hold';\n private phaseFrames = this.autoHoldFrames - 120;\n private samples: number[] = [];\n private offMean = 0;\n private lastTick = 0;\n /** Depth resolution relative to the drawing buffer. Lower is cheaper and culls a little less. */\n resolutionScale = 0.5;\n /** Largest HZB dimension in texels (memory ~1.33 * maxSize^2 * 4 bytes). */\n readonly maxSize: number;\n /** True when this frame's HZB holds at least one occluder (the cull kernels test against it only then). */\n active = false;\n /** 1 while this frame's HZB is valid; the cull kernels only occlusion-cull then. */\n readonly activeNode = uniform(0, 'uint');\n\n private readonly depthScene = new THREE.Scene();\n private readonly proxies = new Map<VirtualMesh, THREE.Mesh>();\n private readonly projection: Node;\n private readonly near: Node;\n private readonly levelCapacity: number;\n private readonly levelOffsets: number[] = [];\n private readonly hzbAttribute: THREE.StorageBufferAttribute;\n private readonly hzbWrite: Node;\n private readonly hzbRead: Node;\n /** Copy + reduce kernels for the current depth size, dispatched with this frame's cut (one submission). */\n private buildNodes: THREE.ComputeNode[] = [];\n private renderTarget: THREE.RenderTarget | null = null;\n private width = 0;\n private height = 0;\n private levels = 0;\n private readonly bufferSize = new THREE.Vector2();\n\n constructor(projection: Node, near: Node, maxSize = 1024) {\n this.maxSize = Math.max(1, Math.min(1 << (MAX_LEVELS - 1), maxSize));\n this.projection = projection;\n this.near = near;\n\n let dim = this.maxSize;\n let total = HEADER_SIZE;\n let levelCapacity = 0;\n for (;;) {\n this.levelOffsets.push(total);\n total += dim * dim;\n levelCapacity++;\n if (dim === 1) break;\n dim = Math.ceil(dim / 2);\n }\n this.levelCapacity = levelCapacity;\n this.hzbAttribute = new THREE.StorageBufferAttribute(new Float32Array(total), 1);\n this.hzbWrite = storage(this.hzbAttribute, 'float', total);\n // Separate node: toReadOnly() changes the node it is called on.\n this.hzbRead = storage(this.hzbAttribute, 'float', total).toReadOnly();\n\n }\n\n /**\n * True only when a sphere (view-space center, radius) is certainly hidden. Any doubt (touching the near\n * plane, outside the screen) keeps it.\n */\n occluded(viewCenter: Node, radius: Node): Node {\n // Closed-form bounds of the sphere's view-space box (perspective camera, looking down -z): over the box,\n // x / depth is extreme at its corners, so each axis needs only the near and far depth. Same result as\n // projecting the 8 corners, at a fraction of the cost.\n const p: Node = this.projection;\n const depth = viewCenter.z.negate();\n const nearDepth = depth.sub(radius).toVar();\n const farDepth = depth.add(radius);\n const xLo = viewCenter.x.sub(radius);\n const xHi = viewCenter.x.add(radius);\n const yLo = viewCenter.y.sub(radius);\n const yHi = viewCenter.y.add(radius);\n // ndc.x = P00 * x / depth - P02 (P02, P12 are zero unless the frustum is off-center); P00, P11 > 0.\n const sx = p.element(0).x;\n const sy = p.element(1).y;\n const minX = minNode(xLo.div(nearDepth), xLo.div(farDepth)).mul(sx).sub(p.element(2).x);\n const maxX = maxNode(xHi.div(nearDepth), xHi.div(farDepth)).mul(sx).sub(p.element(2).x);\n const minY = minNode(yLo.div(nearDepth), yLo.div(farDepth)).mul(sy).sub(p.element(2).y);\n const maxY = maxNode(yHi.div(nearDepth), yHi.div(farDepth)).mul(sy).sub(p.element(2).y);\n // Depth of the nearest point: ndc.z = -P22 + P23 / depth.\n const minZ = p.element(3).z.div(nearDepth).sub(p.element(2).z);\n const behind = nearDepth.lessThanEqual(this.near);\n\n // Footprint in mip-0 texels. Row 0 is the top of the screen (WebGPU texture origin).\n const hzb = this.hzbRead;\n const W = hzb.element(1);\n const H = hzb.element(2);\n const zero = float(0);\n const x0 = clamp(floor(minX.mul(0.5).add(0.5).mul(W)), zero, W.sub(1));\n const x1 = clamp(floor(maxX.mul(0.5).add(0.5).mul(W)), zero, W.sub(1));\n const y0 = clamp(floor(float(0.5).sub(maxY.mul(0.5)).mul(H)), zero, H.sub(1));\n const y1 = clamp(floor(float(0.5).sub(minY.mul(0.5)).mul(H)), zero, H.sub(1));\n\n // The mip whose texels are at least as big as the footprint: then it spans at most 2x2 of them.\n const extent = maxNode(x1.sub(x0), y1.sub(y0)).add(1);\n const levelF = minNode(ceil(log2(extent)), hzb.element(LEVEL_COUNT_SLOT).sub(1));\n const entry = uint(levelF).mul(4);\n const scale = exp2(levelF);\n const offset = hzb.element(entry);\n const levelW = hzb.element(entry.add(1));\n const levelH = hzb.element(entry.add(2));\n const sampleAt = (fx: Node, fy: Node): Node => {\n const tx = clamp(floor(fx.div(scale)), zero, levelW.sub(1));\n const ty = clamp(floor(fy.div(scale)), zero, levelH.sub(1));\n return hzb.element(uint(offset.add(ty.mul(levelW)).add(tx)));\n };\n const hzbMax = maxNode(maxNode(sampleAt(x0, y0), sampleAt(x1, y0)), maxNode(sampleAt(x0, y1), sampleAt(x1, y1)));\n\n // Hidden when the nearest point of the box is behind every occluder in its on-screen footprint (parts\n // off screen are not visible anyway).\n return behind.not().and(minZ.lessThan(1)).and(minZ.greaterThan(hzbMax.add(1e-6)));\n }\n\n /** Called once per frame by the context: feeds the auto A/B measurement (see `auto`). */\n tick(now: number) {\n const dt = this.lastTick ? now - this.lastTick : 0;\n this.lastTick = now;\n if (!this.auto || !this.enabled) return;\n this.phaseFrames++;\n // Skip the first frames after a switch (pipelines, stale cuts), and stalls (tab switches, loading).\n if (this.phase !== 'hold' && this.phaseFrames > 5 && dt > 0 && dt < 250) this.samples.push(dt);\n if (this.phase === 'probeOff' && this.samples.length >= this.autoProbeFrames) {\n this.offMean = mean(this.samples);\n this.next('probeOn');\n } else if (this.phase === 'probeOn' && this.samples.length >= this.autoProbeFrames) {\n this.autoChoice = mean(this.samples) < this.offMean * 0.97;\n this.next('hold');\n } else if (this.phase === 'hold' && this.phaseFrames >= this.autoHoldFrames) {\n this.next('probeOff');\n }\n }\n\n private next(phase: 'probeOff' | 'probeOn' | 'hold') {\n this.phase = phase;\n this.phaseFrames = 0;\n this.samples = [];\n }\n\n private autoWanted() {\n return this.phase === 'probeOn' || (this.phase === 'hold' && this.autoChoice);\n }\n\n /** Depth-only proxy of a mesh's camera cut, created on first use and kept in sync with its pool. */\n private proxyOf(mesh: VirtualMesh) {\n let proxy = this.proxies.get(mesh);\n if (!proxy) {\n proxy = new THREE.Mesh(mesh.cameraGeometry, new THREE.MeshBasicNodeMaterial({ colorWrite: false }));\n proxy.frustumCulled = false;\n this.depthScene.add(proxy);\n this.proxies.set(mesh, proxy);\n }\n const material = proxy.material as THREE.MeshBasicNodeMaterial;\n if (material.positionNode !== mesh.pool.positionNode) {\n material.positionNode = mesh.pool.positionNode; // same vertex pulling as the shaded mesh\n material.needsUpdate = true;\n }\n return proxy;\n }\n\n unregisterMesh(mesh: VirtualMesh) {\n const proxy = this.proxies.get(mesh);\n if (!proxy) return;\n this.proxies.delete(mesh);\n proxy.removeFromParent();\n (proxy.material as THREE.Material).dispose();\n }\n\n /**\n * Whether occlusion culling runs this frame (enabled, a supported camera and depth mode, and the auto tuner\n * wants it). Meshes get their per-mesh flag from this before the cut is computed.\n */\n wantsFrame(renderer: THREE.WebGPURenderer, camera: THREE.Camera, _frame: number) {\n const r = renderer as unknown as { reversedDepthBuffer?: boolean; logarithmicDepthBuffer?: boolean };\n // The test assumes a perspective camera and standard [0, 1] depth.\n const supported = (camera as THREE.PerspectiveCamera).isPerspectiveCamera && !r.reversedDepthBuffer && !r.logarithmicDepthBuffer;\n return this.enabled && supported && (!this.auto || this.autoWanted());\n }\n\n /**\n * Renders the occluders' last camera cuts into the depth target and returns the compute kernels that turn\n * it into the HZB; run them before the cut (the caller prepends them to the same compute submission).\n * Sets `activeNode`, which the cull kernels check: without occluders this frame, nothing is occlusion culled.\n */\n beginFrame(renderer: THREE.WebGPURenderer, camera: THREE.Camera, meshes: readonly VirtualMesh[]): THREE.ComputeNode[] {\n let any = false;\n for (const mesh of meshes) {\n const occluder = mesh.visible && mesh.occluder && mesh.pool.hasCut && !!mesh.pool.positionNode;\n if (!occluder && !this.proxies.has(mesh)) continue;\n const proxy = this.proxyOf(mesh);\n proxy.visible = occluder;\n any = any || occluder;\n }\n this.active = any;\n this.activeNode.value = any ? 1 : 0;\n if (!any) return NO_NODES;\n\n renderer.getDrawingBufferSize(this.bufferSize);\n const s = Math.min(this.resolutionScale, this.maxSize / Math.max(this.bufferSize.x, this.bufferSize.y));\n const w = Math.max(1, Math.round(this.bufferSize.x * s));\n const h = Math.max(1, Math.round(this.bufferSize.y * s));\n if (w !== this.width || h !== this.height) this.resize(w, h);\n\n // The depth scene has no lights, so this renders no shadow maps.\n const previous = renderer.getRenderTarget();\n renderer.setRenderTarget(this.renderTarget);\n renderer.render(this.depthScene, camera);\n renderer.setRenderTarget(previous);\n return this.buildNodes;\n }\n\n private resize(w: number, h: number) {\n const old = this.buildNodes;\n this.renderTarget?.dispose();\n const depthTexture = new THREE.DepthTexture(w, h);\n depthTexture.type = THREE.FloatType;\n this.renderTarget = new THREE.RenderTarget(w, h, { depthBuffer: true, depthTexture });\n this.width = w;\n this.height = h;\n\n const header = this.hzbAttribute.array as Float32Array;\n header.fill(0, 0, HEADER_SIZE);\n let lw = w;\n let lh = h;\n let levels = 0;\n for (let i = 0; i < this.levelCapacity; i++) {\n header[i * 4] = this.levelOffsets[i];\n header[i * 4 + 1] = lw;\n header[i * 4 + 2] = lh;\n levels++;\n if (lw === 1 && lh === 1) break;\n lw = Math.max(1, Math.ceil(lw / 2));\n lh = Math.max(1, Math.ceil(lh / 2));\n }\n this.levels = levels;\n header[LEVEL_COUNT_SLOT] = levels;\n this.hzbAttribute.needsUpdate = true;\n\n // Mip 0: depth texture -> the first region of the HZB buffer.\n const depth = texture(depthTexture);\n const hzb = this.hzbWrite;\n const copyNode = Fn(() => {\n const idx = instanceIndex;\n const dstW = uint(hzb.element(1));\n const dstH = uint(hzb.element(2));\n If(idx.greaterThanEqual(dstW.mul(dstH)), () => {\n Return();\n });\n const x = idx.mod(dstW);\n const y = idx.div(dstW);\n // Through a var: an inline uint() of a storage element is dropped by the WGSL builder (f32 + u32).\n const dstOffset = uint(hzb.element(0)).toVar();\n hzb.element(dstOffset.add(idx)).assign(depth.load(ivec2(int(x), int(y))));\n })().compute(w * h, [WORKGROUP]);\n this.buildNodes = [copyNode];\n\n // Mip i = max of the 2x2 texels of mip i-1 (disjoint regions of the same read-write binding).\n lw = w;\n lh = h;\n for (let i = 1; i < levels; i++) {\n lw = Math.max(1, Math.ceil(lw / 2));\n lh = Math.max(1, Math.ceil(lh / 2));\n this.buildNodes.push(\n Fn(() => {\n const idx = instanceIndex;\n const dstOffset = uint(hzb.element(i * 4)).toVar();\n const dstW = uint(hzb.element(i * 4 + 1));\n const dstH = uint(hzb.element(i * 4 + 2));\n If(idx.greaterThanEqual(dstW.mul(dstH)), () => {\n Return();\n });\n const x = idx.mod(dstW);\n const y = idx.div(dstW);\n const srcOffset = uint(hzb.element((i - 1) * 4)).toVar();\n const srcW = uint(hzb.element((i - 1) * 4 + 1));\n const srcH = uint(hzb.element((i - 1) * 4 + 2));\n const x0 = x.mul(2);\n const y0 = y.mul(2);\n const x1 = minNode(x0.add(1), srcW.sub(1));\n const y1 = minNode(y0.add(1), srcH.sub(1));\n const row0 = srcOffset.add(y0.mul(srcW));\n const row1 = srcOffset.add(y1.mul(srcW));\n const v = maxNode(maxNode(hzb.element(row0.add(x0)), hzb.element(row0.add(x1))), maxNode(hzb.element(row1.add(x0)), hzb.element(row1.add(x1))));\n hzb.element(dstOffset.add(idx)).assign(v);\n })().compute(lw * lh, [WORKGROUP])\n );\n }\n for (const node of old) node.dispose();\n }\n\n dispose() {\n this.renderTarget?.dispose();\n this.renderTarget = null;\n for (const mesh of [...this.proxies.keys()]) this.unregisterMesh(mesh);\n }\n}\n","import * as THREE from 'three/webgpu';\nimport { uniform } from 'three/tsl';\nimport type { VirtualMesh, VirtualMeshInstances, VirtualMeshOptions } from './VirtualMesh.js';\nimport { OcclusionCulling } from './OcclusionCulling.js';\nimport { VirtualMesh as VirtualMeshClass } from './VirtualMesh.js';\nimport type { VirtualMeshData } from '../preprocess/buildVirtualMesh.js';\nimport { GeometryPool, NO_DRAW_DISTANCE, type PoolCapacity } from './GeometryPool.js';\nimport { virtualMeshesFromObject3D, type VirtualGeometryImport, type VirtualGeometryImportOptions } from '../import/fromObject3D.js';\n\nexport { VG_DEBUG_MODES } from '../constants.js';\n\n/** Length of the camera + settings vector compared by `VirtualGeometry.cutInputsChanged`. */\nconst CUT_INPUT_COUNT = 16 + 16 + 12;\n\nexport interface VirtualGeometryStats {\n drawnMeshlets: number;\n drawnTriangles: number;\n /** Triangles if every instance were drawn at full detail (no LOD, no culling). */\n fullDetailTriangles: number;\n instances: number;\n /** Instances that survived instance culling (frustum, sub-pixel). */\n visibleInstances: number;\n /** Triangles the LOD cut asked for. Above drawnTriangles means some mesh ran out of index buffer. */\n requestedTriangles: number;\n /** True when a mesh dropped meshlets for lack of capacity (visible as flicker). */\n overflow: boolean;\n /** Fullest draw buffer of any mesh, as a fraction of its capacity (above 1: overflow). */\n capacityUse: number;\n /** Instances hidden from the camera by occlusion culling. */\n occludedInstances: number;\n /** Triangles drawn into shadow maps (the coarser shadow cut). */\n shadowTriangles: number;\n}\n\n/**\n * Per-frame state shared by every `VirtualMesh`: camera uniforms used by the\n * GPU culling/LOD-selection kernels, plus global settings.\n */\nconst ZERO = new THREE.Vector3();\n\n/**\n * Threshold that brings a too-full draw buffer back to ~85%: triangles scale with about 1/threshold^2, so\n * one step lands near the target even from a large overflow (at most 2x per step, at least 4%).\n */\nfunction capacityStep(threshold: number, use: number) {\n return Math.min(64, threshold * Math.min(2, Math.max(1.04, Math.sqrt(use / 0.85))));\n}\n\nexport interface VirtualGeometryOptions {\n /** Max triangles drawn per frame per pool (camera). Default 10M (120 MB of indices, under the 128 MB binding limit). */\n maxTriangles?: number;\n /** Max triangles drawn into shadow maps per frame per pool. Default 4M. */\n maxShadowTriangles?: number;\n /** Max meshlets drawn per frame per pool. Default 1M. */\n maxMeshlets?: number;\n /**\n * Largest storage-buffer binding a pool may use, in bytes. A pool that would exceed it is closed and a new one\n * opened. Default 120 MB (WebGPU guarantees 128 MB; raise it if you request a higher device limit).\n */\n maxPoolBytes?: number;\n}\n\nexport class VirtualGeometry {\n readonly viewMatrix = uniform(new THREE.Matrix4());\n readonly projectionMatrix = uniform(new THREE.Matrix4());\n /** `projection[1][1] * viewportHeight / 2`: converts view-space error to pixels. */\n readonly projScale = uniform(1);\n readonly near = uniform(0.1);\n /** Max projected error, in pixels, a meshlet may have to be drawn. */\n readonly errorThreshold = uniform(1);\n\n /**\n * Lever: target number of drawn triangles per frame. When > 0, the error threshold is adjusted (slowly, see\n * adaptThreshold) to keep the drawn triangle count near this budget. Off by default: a fixed threshold gives\n * the steadiest image, because LODs then only switch with distance, never all at once.\n */\n triangleBudget = 0;\n /** Bounds for the automatically adjusted error threshold, in pixels. */\n thresholdRange: [number, number] = [0.5, 3];\n /** Latest GPU readback, updated every `statsInterval` frames while a budget or HUD is active. */\n lastStats: VirtualGeometryStats | null = null;\n statsInterval = 10;\n /** Frames updated so far. */\n frameCount = 0;\n /** The user's threshold while the capacity guard holds a coarser one (no budget), else null. */\n private guardBase: number | null = null;\n /** Consecutive stats readbacks with the drawn triangles outside the budget's deadband. */\n private outOfBand = 0;\n private guardWritten = NaN;\n private statsPending = false;\n readonly frustumCulling = uniform(1, 'uint');\n readonly debugMode = uniform(0, 'uint');\n /**\n * Instances whose bounding sphere projects to a smaller radius than this (pixels) are skipped. 0 disables.\n * The sphere is never smaller than the object, so at 0.7 nothing wider than ~1.4 px on screen is dropped.\n */\n readonly minPixelRadius = uniform(0.7);\n readonly frustumPlanes = Array.from({ length: 6 }, () => uniform(new THREE.Vector4()));\n /**\n * Direction * length that light travels (e.g. sun direction * 300). When non-zero, frustum culling\n * keeps meshlets whose shadow, swept along this vector, can reach the view frustum, so shadow\n * casters just outside the view still cast shadows. Zero disables it.\n */\n readonly shadowSweep = uniform(new THREE.Vector3());\n /**\n * Set `shadowSweep` automatically from the shadow cameras of the lights that render the meshes (direction\n * of an orthographic shadow camera, length = its larger extent). Turn off to set `shadowSweep` yourself.\n */\n autoShadowSweep = true;\n /**\n * Shadow maps use a coarser cut: the error threshold times this. Shadows are soft and seen from the camera\n * at a distance, so this saves most of the shadow-pass triangles with no visible change. 1 = camera detail.\n */\n readonly shadowErrorScale = uniform(3);\n private readonly detectedSweep = new THREE.Vector3();\n private detectedSweepFrame = -Infinity;\n\n /**\n * Occlusion culling (on by default): geometry hidden behind solid meshes is not drawn. Levers:\n * `occlusion.enabled`, `occlusion.resolutionScale`, and per mesh `occluder` / `occlusionCulling`.\n */\n readonly occlusion = new OcclusionCulling(this.projectionMatrix, this.near);\n\n /** Skip LOD selection/culling and keep drawing the last selection (for inspecting the cut). */\n freeze = false;\n /**\n * Run `update()` automatically before every render of a scene that contains this context's meshes, with the\n * camera that render uses (default true). Shadow-map renders reuse the cut of the camera being rendered.\n * Calling `update()` yourself still works: a render right after it with the same camera does not repeat it.\n */\n autoUpdate = true;\n /**\n * Measure the error threshold in CSS pixels (default) instead of device pixels. On a 2x display,\n * device pixels would request ~4x the triangles for detail nobody can see.\n */\n errorInCssPixels = true;\n\n readonly meshes: VirtualMesh[] = [];\n /** Shared buffers and compute passes; meshes go into the first pool with room (see GeometryPool). */\n readonly pools: GeometryPool[] = [];\n private readonly capacity: PoolCapacity;\n private readonly maxPoolBytes: number;\n\n constructor(options: VirtualGeometryOptions = {}) {\n this.capacity = {\n triangles: options.maxTriangles ?? 10_000_000,\n shadowTriangles: options.maxShadowTriangles ?? 4_000_000,\n meshlets: Math.min(options.maxMeshlets ?? 1 << 20, 1 << 24),\n };\n this.maxPoolBytes = options.maxPoolBytes ?? 120 * 1024 * 1024;\n }\n\n private readonly frustum = new THREE.Frustum();\n private readonly projScreen = new THREE.Matrix4();\n private readonly size = new THREE.Vector2();\n /** Compute nodes dispatched this frame (reused to avoid per-frame allocation). */\n private readonly computeList: THREE.ComputeNode[] = [];\n private readonly dispatchedPools: GeometryPool[] = [];\n /** Frames where `update` ran no compute pass because nothing the cut depends on changed. */\n skippedFrames = 0;\n /** Inputs of the cut as of the last frame that changed them (NaN until the first frame). */\n private readonly cutInputs = new Float64Array(CUT_INPUT_COUNT).fill(NaN);\n private readonly cutInputsScratch = new Float64Array(CUT_INPUT_COUNT);\n /** Scenes whose onBeforeRender runs the auto update (installed the first time one of our meshes renders in them). */\n private readonly sceneHooks = new WeakMap<THREE.Object3D, THREE.Object3D['onBeforeRender']>();\n /** `renderer.info.render.calls` and camera of the last automatic and the last manual update. */\n private autoCall = -1;\n private autoCamera: THREE.Camera | null = null;\n private manualCall = -1;\n private manualCamera: THREE.Camera | null = null;\n private updatingAuto = false;\n\n /**\n * Converts every static mesh under `object` (e.g. `gltf.scene`) to VirtualGeometry geometry, in place: meshes sharing\n * geometry and material become one VirtualMesh with many instances, materials are converted to node materials\n * with their textures, and the originals stop rendering. Skinned/morphing meshes, points and lines are left\n * alone. Returns the created meshes and a `dispose()` that restores the originals. See `VirtualGeometryImportOptions`.\n */\n add(object: THREE.Object3D, options?: VirtualGeometryImportOptions): Promise<VirtualGeometryImport> {\n return virtualMeshesFromObject3D(this, object, options);\n }\n\n /** Create a renderable mesh from a built DAG. Add the result to any three.js scene. */\n createMesh(data: VirtualMeshData, material: THREE.NodeMaterial, instances: VirtualMeshInstances, options?: VirtualMeshOptions): VirtualMesh {\n return new VirtualMeshClass(this, data, material, instances, options);\n }\n\n /**\n * Lever: compile a pool's compute pipelines in the background before its first dispatch (default), so adding\n * meshes never freezes the page; they appear once ready. False: compile on first use (a hitch).\n */\n asyncCompile = true;\n\n private compilePool(renderer: THREE.WebGPURenderer, pool: GeometryPool) {\n pool.pipelineState = 'compiling';\n const version = pool.version;\n const done = () => {\n if (pool.version !== version) return; // rebuilt meanwhile: compiles again\n pool.pipelineState = 'ready';\n pool.dirty = true;\n };\n renderer.compileComputeAsync(pool.computeNodes).then(done, done);\n }\n\n /** Builds pools whose buffers grew and points their meshes at the new buffers. */\n private preparePools(renderer: THREE.WebGPURenderer) {\n for (const pool of this.pools) pool.prepare(renderer);\n // A pool may also have been rebuilt while meshes were being added: syncPool is a version check.\n for (const mesh of this.meshes) mesh.syncPool();\n }\n\n /**\n * Optional, for loading screens: compiles every pipeline the scene needs (compute and render), so the first\n * frames neither freeze nor show meshes popping in. Call after adding the meshes, before the first render.\n */\n async compileAsync(renderer: THREE.WebGPURenderer, scene: THREE.Object3D, camera: THREE.Camera) {\n this.preparePools(renderer);\n const pending = this.pools.filter((p) => p.pipelineState !== 'ready');\n for (const pool of pending) pool.pipelineState = 'compiling';\n await Promise.all(pending.map((p) => renderer.compileComputeAsync(p.computeNodes).catch(() => undefined)));\n for (const pool of pending) {\n pool.pipelineState = 'ready';\n pool.dirty = true;\n }\n await renderer.compileAsync(scene, camera);\n }\n\n /** Called by meshes from onBeforeShadow: remembers the light direction for `autoShadowSweep`. */\n noteShadowCamera(shadowCamera: THREE.Camera) {\n if (this.detectedSweepFrame === this.frameCount) return;\n const ortho = shadowCamera as THREE.OrthographicCamera;\n if (!ortho.isOrthographicCamera) return; // spot/point lights: no single direction to sweep along\n const extent = Math.max(ortho.top - ortho.bottom, ortho.right - ortho.left) / ortho.zoom;\n shadowCamera.getWorldDirection(this.detectedSweep).multiplyScalar(extent);\n this.detectedSweepFrame = this.frameCount;\n }\n\n /** Puts the mesh's geometry and instances into the first pool with room (a new pool when none has). */\n register(mesh: VirtualMesh, instances: VirtualMeshInstances) {\n const instanceCount = instances.matrices.length / 16;\n if (GeometryPool.bytesOf(mesh.data) > this.maxPoolBytes) {\n throw new Error(`VirtualGeometry: a single mesh needs more than maxPoolBytes (${this.maxPoolBytes} bytes) of GPU buffer`);\n }\n let pool = this.pools.find((p) => p.fits(mesh.data, instanceCount));\n if (!pool) {\n pool = new GeometryPool(this, this.capacity, this.maxPoolBytes);\n this.pools.push(pool);\n }\n mesh.pool = pool;\n mesh.entry = pool.add(mesh.data, instances.matrices, instances.colors, mesh.gpuToInput);\n pool.ensureBuilt(); // nodes are only rebuilt when the pool's buffers grew\n this.meshes.push(mesh);\n mesh.onBeforeRender = (renderer, scene, camera) => this.autoUpdateFor(renderer as unknown as THREE.WebGPURenderer, scene, camera, false);\n }\n\n /**\n * Auto update, from a VirtualMesh's onBeforeRender. The first time, this also hooks the scene's onBeforeRender,\n * which runs before the render pass starts (so shadow maps rendered inside the pass already see the new cut);\n * later frames update from there. A compute submitted from inside a pass still runs before that pass on the\n * GPU, because the pass is submitted when it ends.\n */\n private autoUpdateFor(renderer: THREE.WebGPURenderer, scene: THREE.Object3D, camera: THREE.Camera, fromScene: boolean) {\n if (!this.autoUpdate || this.meshes.length === 0) return;\n // Shadow maps draw the cut of the camera being rendered (see shadowSweep), never their own.\n if ((scene as THREE.Scene).overrideMaterial && (scene as THREE.Scene & { overrideMaterial: { isShadowPassMaterial?: boolean } }).overrideMaterial.isShadowPassMaterial) return;\n if (!fromScene && (scene as THREE.Scene).isScene) {\n // The scene hook already ran for this render; (re)install it if missing, e.g. replaced by user code.\n if (scene.onBeforeRender === this.sceneHooks.get(scene)) return;\n const previous = scene.onBeforeRender;\n // eslint-disable-next-line @typescript-eslint/no-this-alias\n const context = this;\n const hook: THREE.Object3D['onBeforeRender'] = function (this: THREE.Object3D, r, s, c, ...rest) {\n context.autoUpdateFor(r as unknown as THREE.WebGPURenderer, s, c, true);\n previous.call(this, r, s, c, ...rest);\n };\n scene.onBeforeRender = hook;\n this.sceneHooks.set(scene, hook);\n }\n // Once per render call, and not for the render right after a manual update() with the same camera.\n const call = renderer.info.render.calls;\n if (camera === this.autoCamera && call === this.autoCall) return;\n if (camera === this.manualCamera && call === this.manualCall + 1) return;\n this.autoCall = call;\n this.autoCamera = camera;\n this.updatingAuto = true;\n try {\n this.update(renderer, camera as THREE.PerspectiveCamera);\n } finally {\n this.updatingAuto = false;\n }\n }\n\n unregister(mesh: VirtualMesh) {\n const i = this.meshes.indexOf(mesh);\n if (i === -1) return;\n this.meshes.splice(i, 1);\n mesh.pool.remove(mesh.entry);\n this.occlusion.unregisterMesh(mesh);\n }\n\n /** Dispose every mesh created by this context. */\n dispose() {\n for (const mesh of [...this.meshes]) mesh.dispose(this);\n for (const pool of this.pools) pool.dispose();\n this.pools.length = 0;\n this.occlusion.dispose();\n }\n\n /**\n * Runs LOD selection + culling on the GPU for `camera`. With `autoUpdate` (default) the renderer calls this\n * for you before each render; call it yourself before `renderer.render` when `autoUpdate` is false.\n * When the camera, the settings and every mesh's instances are unchanged, the compute passes are\n * skipped and the previous cut (index buffer + draw args) is drawn again.\n */\n update(renderer: THREE.WebGPURenderer, camera: THREE.PerspectiveCamera) {\n if (!this.updatingAuto) {\n this.manualCall = renderer.info.render.calls;\n this.manualCamera = camera;\n }\n if (this.freeze) return;\n this.occlusion.tick(performance.now());\n\n camera.updateMatrixWorld();\n this.viewMatrix.value.copy(camera.matrixWorldInverse);\n if (!this.projectionMatrix.value.equals(camera.projectionMatrix)) this.projectionMatrix.value.copy(camera.projectionMatrix);\n renderer.getDrawingBufferSize(this.size);\n // Errors are measured in CSS pixels, so a threshold means the same thing at any devicePixelRatio.\n const cssHeight = this.size.y / (this.errorInCssPixels ? renderer.getPixelRatio() : 1);\n // Only write uniforms that changed: a static camera then costs no uniform updates at all.\n const projScale = camera.projectionMatrix.elements[5] * cssHeight * 0.5;\n if (this.projScale.value !== projScale) this.projScale.value = projScale;\n if (this.near.value !== camera.near) this.near.value = camera.near;\n\n this.projScreen.multiplyMatrices(camera.projectionMatrix, camera.matrixWorldInverse);\n this.frustum.setFromProjectionMatrix(this.projScreen, THREE.WebGPUCoordinateSystem);\n for (let i = 0; i < 6; i++) {\n const { normal, constant } = this.frustum.planes[i];\n const p = this.frustumPlanes[i].value;\n if (p.x !== normal.x || p.y !== normal.y || p.z !== normal.z || p.w !== constant) {\n p.set(normal.x, normal.y, normal.z, constant);\n }\n }\n\n if (this.autoShadowSweep) {\n const sweep = this.frameCount - this.detectedSweepFrame <= 2 ? this.detectedSweep : ZERO;\n if (!this.shadowSweep.value.equals(sweep)) this.shadowSweep.value.copy(sweep);\n }\n // Per-mesh flags in the pools' mesh tables: visibility, shadows (only for meshes a shadow-casting light\n // rendered recently, reported from onBeforeShadow; a newly lit mesh starts casting one frame later) and\n // occlusion. writeFlags only uploads (and dirties the pool) when a value changes.\n const occlusionWanted = this.occlusion.wantsFrame(renderer, camera, this.frameCount);\n for (const mesh of this.meshes) {\n mesh.pool.writeFlags(mesh.entry, {\n enabled: mesh.visible ? 1 : 0,\n shadow: mesh.castShadow && this.frameCount - mesh.lastShadowFrame <= 2 ? 1 : 0,\n occlusion: occlusionWanted && mesh.occlusionCulling ? 1 : 0,\n });\n }\n\n // Anything the cut depends on changed: every pool needs a new cut.\n if (this.cutInputsChanged(camera, renderer.getPixelRatio())) {\n for (const pool of this.pools) pool.dirty = true;\n }\n\n this.preparePools(renderer);\n const nodes = this.computeList;\n nodes.length = 0;\n const dispatched = this.dispatchedPools;\n dispatched.length = 0;\n for (const pool of this.pools) {\n if (!pool.dirty || pool.entries.length === 0) continue;\n if (pool.pipelineState !== 'ready') {\n if (this.asyncCompile) {\n // Compile in the background: the pool's meshes show up a few frames later instead of a freeze.\n if (pool.pipelineState === 'none') this.compilePool(renderer, pool);\n continue;\n }\n pool.pipelineState = 'ready';\n }\n for (const node of pool.computeNodes) nodes.push(node);\n dispatched.push(pool);\n }\n if (nodes.length > 0) {\n // Depth of last frame's solid geometry from this frame's camera: what this frame's cut is tested against.\n const hzbNodes = occlusionWanted ? this.occlusion.beginFrame(renderer, camera, this.meshes) : [];\n if (hzbNodes.length) nodes.unshift(...hzbNodes);\n renderer.compute(nodes);\n for (const pool of dispatched) {\n pool.dirty = false;\n pool.hasCut = true;\n }\n } else {\n this.skippedFrames++;\n }\n\n this.frameCount++;\n // One small readback every statsInterval frames feeds the budget controller, the capacity guard (always\n // on: an overflow would flicker) and the occlusion auto pause.\n if (this.meshes.length > 0 && !this.statsPending && this.frameCount % this.statsInterval === 0) {\n this.statsPending = true;\n this.readStats(renderer)\n .then((s) => {\n this.lastStats = s;\n this.adaptThreshold(s);\n })\n .finally(() => (this.statsPending = false));\n }\n }\n\n\n /**\n * True when anything the GPU cut reads from the context differs from the last frame that was computed\n * (and records the new values). Exact comparison on purpose: an unmoved camera recomputes the same\n * matrices bit for bit, while any real change, including a budget-controller step, differs.\n */\n private cutInputsChanged(camera: THREE.PerspectiveCamera, pixelRatio: number): boolean {\n const cur = this.cutInputsScratch;\n let i = 0;\n for (let k = 0; k < 16; k++) cur[i++] = camera.matrixWorldInverse.elements[k];\n for (let k = 0; k < 16; k++) cur[i++] = camera.projectionMatrix.elements[k];\n cur[i++] = camera.near;\n cur[i++] = this.size.x;\n cur[i++] = this.size.y;\n cur[i++] = pixelRatio;\n cur[i++] = this.errorInCssPixels ? 1 : 0;\n cur[i++] = this.errorThreshold.value;\n cur[i++] = this.minPixelRadius.value;\n cur[i++] = this.frustumCulling.value;\n cur[i++] = this.debugMode.value;\n const sweep = this.shadowSweep.value;\n cur[i++] = sweep.x;\n cur[i++] = sweep.y;\n cur[i++] = sweep.z;\n\n for (let k = 0; k < CUT_INPUT_COUNT; k++) {\n if (cur[k] !== this.cutInputs[k]) {\n this.cutInputs.set(cur);\n return true;\n }\n }\n return false;\n }\n\n /**\n * Slow multiplicative controller. Drawn triangles grow roughly with 1/threshold^2. Every change of the\n * threshold re-picks LODs across the whole screen, so it moves rarely (deadband) and in small steps.\n *\n * Draw capacity is a hard constraint: an overflowing mesh drops meshlets in a different order every frame,\n * which flickers. So the controller coarsens *before* a buffer is full, never refines into one, and may go\n * above `thresholdRange[1]` only for capacity, coming back down as soon as there is room.\n */\n private adaptThreshold(stats: VirtualGeometryStats) {\n const t = this.errorThreshold.value;\n const use = stats.capacityUse;\n if (this.triangleBudget <= 0) {\n this.guardCapacity(stats, t);\n return;\n }\n this.guardBase = null;\n const [lo, hi] = this.thresholdRange;\n if (stats.overflow || use > 0.9) {\n this.errorThreshold.value = capacityStep(t, use);\n return;\n }\n if (stats.drawnTriangles <= 0) return;\n const ratio = stats.drawnTriangles / this.triangleBudget;\n // Every change re-picks LODs across the whole screen at once, which is far more visible than the\n // distance-driven switches of a fixed threshold. So: a wide deadband, and only after the count stayed out of\n // it for several readbacks in a row (moving through a scene makes it swing briefly all the time).\n if (Math.abs(ratio - 1) < 0.2) {\n this.outOfBand = 0;\n return;\n }\n if (++this.outOfBand < 3) return;\n let next = t * Math.min(1.03, Math.max(0.97, Math.sqrt(ratio)));\n // Back inside the range: gradually from above (capacity pushed it there), clamped otherwise.\n next = t > hi ? Math.max(hi, Math.min(next, t * 0.97)) : Math.min(hi, Math.max(lo, next));\n // Refining multiplies the drawn triangles by about (t / next)^2: never step into a full buffer.\n if (next < t && use * (t / next) ** 2 > 0.85) return;\n this.errorThreshold.value = next;\n }\n\n /**\n * Without a budget the threshold is the user's, except that draw capacity stays a hard limit: coarsen\n * temporarily before a buffer fills up, and return to the user's value once there is room again.\n */\n private guardCapacity(stats: VirtualGeometryStats, t: number) {\n // Changed since the guard last wrote it (by the user, or the budget was just switched off): new target.\n if (t !== this.guardWritten) this.guardBase = null;\n let next = t;\n if (stats.overflow || stats.capacityUse > 0.9) {\n this.guardBase ??= t;\n next = capacityStep(t, stats.capacityUse);\n } else if (this.guardBase !== null && t > this.guardBase) {\n const back = Math.max(this.guardBase, t * 0.97);\n if (stats.capacityUse * (t / back) ** 2 <= 0.85) next = back;\n if (next === this.guardBase) this.guardBase = null;\n }\n if (next !== t) this.errorThreshold.value = next;\n this.guardWritten = this.errorThreshold.value;\n }\n\n /** GPU -> CPU readback of the last culling result. Async; never call every frame. One small readback per pool. */\n async readStats(renderer: THREE.WebGPURenderer): Promise<VirtualGeometryStats> {\n const result: VirtualGeometryStats = {\n drawnMeshlets: 0,\n drawnTriangles: 0,\n fullDetailTriangles: 0,\n instances: 0,\n visibleInstances: 0,\n requestedTriangles: 0,\n overflow: false,\n capacityUse: 0,\n occludedInstances: 0,\n shadowTriangles: 0,\n };\n for (const mesh of this.meshes) {\n if (!mesh.visible) continue;\n result.fullDetailTriangles += mesh.fullDetailTriangles;\n result.instances += mesh.instanceCount;\n }\n for (const pool of this.pools) {\n if (!pool.hasCut) continue;\n const c = await pool.readCounters(renderer);\n const cap = pool.capacity;\n result.drawnMeshlets += c.camera.drawn;\n result.drawnTriangles += Math.min(c.camera.requestedTriangles, cap.triangles);\n result.requestedTriangles += c.camera.requestedTriangles;\n result.visibleInstances += c.camera.survived;\n result.occludedInstances += c.occluded;\n result.shadowTriangles += Math.min(c.shadow.requestedTriangles, cap.shadowTriangles);\n if (c.camera.selected > cap.meshlets || c.camera.requestedTriangles > cap.triangles) result.overflow = true;\n if (c.shadow.selected > cap.meshlets || c.shadow.requestedTriangles > cap.shadowTriangles) result.overflow = true;\n result.capacityUse = Math.max(\n result.capacityUse,\n c.camera.requestedTriangles / cap.triangles,\n c.camera.selected / cap.meshlets,\n c.shadow.requestedTriangles / cap.shadowTriangles,\n c.shadow.selected / cap.meshlets\n );\n }\n return result;\n }\n}\n"],"mappings":"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"}
|