@babylonjs/loaders 9.19.1 → 9.20.1
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/SPLAT/gaussianSplattingStream.d.ts +170 -1
- package/SPLAT/gaussianSplattingStream.js +516 -40
- package/SPLAT/gaussianSplattingStream.js.map +1 -1
- package/SPLAT/gaussianSplattingWorkBuffer.d.ts +163 -4
- package/SPLAT/gaussianSplattingWorkBuffer.js +683 -35
- package/SPLAT/gaussianSplattingWorkBuffer.js.map +1 -1
- package/SPLAT/gaussianSplattingWorkBufferShaders.d.ts +70 -2
- package/SPLAT/gaussianSplattingWorkBufferShaders.js +465 -4
- package/SPLAT/gaussianSplattingWorkBufferShaders.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.d.ts +16 -1
- package/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.js +232 -25
- package/glTF/2.0/Extensions/KHR_interactivity/declarationMapper.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphParser.d.ts +52 -2
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphParser.js +108 -7
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityGraphParser.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityHostResolver.d.ts +37 -0
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityHostResolver.js +69 -0
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityHostResolver.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityReferences.d.ts +44 -0
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityReferences.js +51 -0
- package/glTF/2.0/Extensions/KHR_interactivity/interactivityReferences.js.map +1 -0
- package/glTF/2.0/Extensions/KHR_interactivity.pure.d.ts +1 -0
- package/glTF/2.0/Extensions/KHR_interactivity.pure.js +143 -12
- package/glTF/2.0/Extensions/KHR_interactivity.pure.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_node_hoverability.pure.js +6 -0
- package/glTF/2.0/Extensions/KHR_node_hoverability.pure.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_node_selectability.pure.js +4 -0
- package/glTF/2.0/Extensions/KHR_node_selectability.pure.js.map +1 -1
- package/glTF/2.0/Extensions/KHR_node_visibility.pure.js +11 -0
- package/glTF/2.0/Extensions/KHR_node_visibility.pure.js.map +1 -1
- package/glTF/2.0/Extensions/babylonScenePathToObjectConverter.d.ts +126 -0
- package/glTF/2.0/Extensions/babylonScenePathToObjectConverter.js +251 -0
- package/glTF/2.0/Extensions/babylonScenePathToObjectConverter.js.map +1 -0
- package/glTF/2.0/Extensions/compositePathToObjectConverter.d.ts +51 -0
- package/glTF/2.0/Extensions/compositePathToObjectConverter.js +51 -0
- package/glTF/2.0/Extensions/compositePathToObjectConverter.js.map +1 -0
- package/glTF/2.0/Extensions/gltfPathToObjectConverter.js +69 -7
- package/glTF/2.0/Extensions/gltfPathToObjectConverter.js.map +1 -1
- package/glTF/2.0/Extensions/interactivityAssetPathToObjectConverter.d.ts +41 -0
- package/glTF/2.0/Extensions/interactivityAssetPathToObjectConverter.js +108 -0
- package/glTF/2.0/Extensions/interactivityAssetPathToObjectConverter.js.map +1 -0
- package/glTF/2.0/Extensions/interactivityRefPathToObjectConverter.d.ts +28 -0
- package/glTF/2.0/Extensions/interactivityRefPathToObjectConverter.js +71 -0
- package/glTF/2.0/Extensions/interactivityRefPathToObjectConverter.js.map +1 -0
- package/glTF/2.0/Extensions/objectModelMapping.d.ts +118 -30
- package/glTF/2.0/Extensions/objectModelMapping.js +472 -70
- package/glTF/2.0/Extensions/objectModelMapping.js.map +1 -1
- package/glTF/2.0/Extensions/transmissionHelper.js +4 -0
- package/glTF/2.0/Extensions/transmissionHelper.js.map +1 -1
- package/glTF/2.0/glTFLoader.pure.js +2 -1
- package/glTF/2.0/glTFLoader.pure.js.map +1 -1
- package/package.json +3 -3
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"gaussianSplattingWorkBuffer.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/gaussianSplattingWorkBuffer.ts"],"names":[],"mappings":"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","sourcesContent":["import { MultiRenderTarget } from \"core/Materials/Textures/multiRenderTarget\";\r\nimport { ShaderMaterial } from \"core/Materials/shaderMaterial\";\r\nimport { ShaderLanguage } from \"core/Materials/shaderLanguage\";\r\nimport { Constants } from \"core/Engines/constants\";\r\nimport { Mesh } from \"core/Meshes/mesh\";\r\nimport { VertexData } from \"core/Meshes/mesh.vertexData\";\r\nimport { Color4 } from \"core/Maths/math.color\";\r\nimport { Vector3, Vector4 } from \"core/Maths/math.vector\";\r\nimport { type Texture } from \"core/Materials/Textures/texture\";\r\nimport { type Scene } from \"core/scene\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { type ISogTexturePack } from \"./splatDefs\";\r\nimport {\r\n GaussianSplattingWorkBufferVertexShaderGLSL,\r\n GaussianSplattingWorkBufferFragmentShaderGLSL,\r\n GaussianSplattingWorkBufferVertexShaderWGSL,\r\n GaussianSplattingWorkBufferFragmentShaderWGSL,\r\n GaussianSplattingWorkBufferRelayoutFragmentShaderGLSL,\r\n GaussianSplattingWorkBufferRelayoutFragmentShaderWGSL,\r\n GaussianSplattingWorkBufferRelayoutShaderName,\r\n} from \"./gaussianSplattingWorkBufferShaders\";\r\nimport { RawTexture } from \"core/Materials/Textures/rawTexture\";\r\n\r\n/**\r\n * A unified, GPU-decoded Gaussian Splatting work buffer.\r\n *\r\n * Holds a square MRT texture set (centers / covA / covB / colors) sized to a fixed splat capacity\r\n * (PlayCanvas-style: `ceil(sqrt(capacity))`). Each streamed SOG file is decoded directly on the GPU\r\n * (no CPU readback) into its allocated pixel range. The decoded textures are consumed unchanged by the\r\n * standard (non-SOG) Gaussian Splatting draw path.\r\n *\r\n * @experimental\r\n */\r\nexport class GaussianSplattingWorkBuffer {\r\n private readonly _scene: Scene;\r\n private readonly _mrt: MultiRenderTarget;\r\n private readonly _textureSize: number;\r\n private readonly _shaderLanguage: ShaderLanguage;\r\n private readonly _material: ShaderMaterial;\r\n private readonly _quad: Mesh;\r\n // Relayout (defrag) copy material, created lazily on first relayout.\r\n private _copyMaterial: Nullable<ShaderMaterial> = null;\r\n // Reusable destination->source index map for the relayout pass (created lazily, sized to the work buffer).\r\n private _relayoutMapData: Nullable<Float32Array> = null;\r\n private _relayoutMapTexture: Nullable<RawTexture> = null;\r\n private _disposed = false;\r\n // Reused WebGL framebuffer for the async centers readback (created lazily, freed in dispose).\r\n private _readFbo: Nullable<WebGLFramebuffer> = null;\r\n\r\n /**\r\n * True when the engine supports the non-blocking GPU readback used by {@link readCentersRangeAsync}:\r\n * WebGL2 (PBO + fence) or WebGPU (copyTextureToBuffer + mapAsync). When false (e.g. WebGL1), callers must\r\n * decode positions on the CPU instead.\r\n */\r\n public get supportsAsyncCentersReadback(): boolean {\r\n const engine = this._scene.getEngine();\r\n if (engine.isWebGPU) {\r\n return true;\r\n }\r\n const glEngine = engine as unknown as { _gl?: WebGL2RenderingContext; _readPixelsAsync?: unknown; webGLVersion?: number };\r\n return !!glEngine._gl && typeof glEngine._readPixelsAsync === \"function\" && (glEngine.webGLVersion ?? 0) >= 2;\r\n }\r\n\r\n /**\r\n * Square edge length (in pixels) of the work-buffer textures.\r\n */\r\n public get textureSize(): number {\r\n return this._textureSize;\r\n }\r\n\r\n /**\r\n * The decoded work-buffer textures: [centers, covA, covB, colors].\r\n */\r\n public get textures(): Texture[] {\r\n return this._mrt.textures;\r\n }\r\n\r\n /**\r\n * Creates a work buffer sized to hold `capacity` splats.\r\n * @param scene hosting scene\r\n * @param capacity total number of splats the work buffer must address\r\n */\r\n constructor(scene: Scene, capacity: number) {\r\n this._scene = scene;\r\n this._shaderLanguage = scene.getEngine().isWebGPU ? ShaderLanguage.WGSL : ShaderLanguage.GLSL;\r\n this._textureSize = Math.max(1, Math.ceil(Math.sqrt(Math.max(1, capacity))));\r\n\r\n // The decode buffer accumulates (clear disabled) so each decode preserves previously-decoded files.\r\n this._mrt = this._createMrt(\"gsWorkBuffer\", true);\r\n\r\n // One persistent decode material + fullscreen-triangle quad, reused (with per-file uniforms)\r\n // for every decode so the shader is compiled only once.\r\n this._material = this._createMaterial();\r\n this._quad = this._createQuad();\r\n this._quad.material = this._material;\r\n }\r\n\r\n /**\r\n * Creates a 4-attachment MRT (centers F32 / covA / covB / colors U8) sized to the work buffer. covA/covB\r\n * use HALF_FLOAT when the engine can render to it, matching the precision the non-streamed\r\n * GaussianSplattingMesh path already uses for these same two textures (see\r\n * `gaussianSplattingMeshBase.pure.ts`'s `createTextureFromDataF16` covA/covB textures); centers stays F32\r\n * and colors stays U8 in both paths.\r\n * @param name MRT and attachment base name\r\n * @param disableClear when true, clearing is suppressed so renders accumulate (the decode buffer); when\r\n * false the MRT clears to zero on each render (the temporary relayout buffer, so gaps stay zeroed)\r\n * @returns the created MRT\r\n */\r\n private _createMrt(name: string, disableClear: boolean): MultiRenderTarget {\r\n const covType = this._scene.getEngine()._caps.textureHalfFloatRender ? Constants.TEXTURETYPE_HALF_FLOAT : Constants.TEXTURETYPE_FLOAT;\r\n const mrt = new MultiRenderTarget(\r\n name,\r\n { width: this._textureSize, height: this._textureSize },\r\n 4,\r\n this._scene,\r\n {\r\n types: [Constants.TEXTURETYPE_FLOAT, covType, covType, Constants.TEXTURETYPE_UNSIGNED_BYTE],\r\n samplingModes: [\r\n Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n ],\r\n formats: [Constants.TEXTUREFORMAT_RGBA, Constants.TEXTUREFORMAT_RGBA, Constants.TEXTUREFORMAT_RGBA, Constants.TEXTUREFORMAT_RGBA],\r\n generateDepthBuffer: false,\r\n generateDepthTexture: false,\r\n generateMipMaps: false,\r\n },\r\n [`${name}Centers`, `${name}CovA`, `${name}CovB`, `${name}Colors`]\r\n );\r\n mrt.clearColor = new Color4(0, 0, 0, 0);\r\n mrt.renderList = [];\r\n if (disableClear) {\r\n mrt.onClearObservable.add(() => {});\r\n }\r\n return mrt;\r\n }\r\n\r\n /**\r\n * Decodes one SOG file into the work buffer at the given splat offset (accumulating; previously\r\n * decoded files are preserved). Resolves once the GPU decode has been issued. The caller may\r\n * dispose the source pack textures after this resolves.\r\n * @param pack the SOG texture pack (GPU source textures + per-file decode parameters)\r\n * @param offset first splat index (pixel offset) for this file in the work buffer\r\n */\r\n public async decodeAsync(pack: ISogTexturePack, offset: number): Promise<void> {\r\n if (this._disposed) {\r\n return;\r\n }\r\n this._applyPack(pack, offset);\r\n // Render the decode pass at the start of a frame (the safe point for custom render targets),\r\n // once the shader is compiled — never re-entrantly from a promise/observable continuation.\r\n await new Promise<void>((resolve) => {\r\n const attempt = () => {\r\n if (this._disposed) {\r\n resolve();\r\n return;\r\n }\r\n if (!this._material.isReady(this._quad)) {\r\n this._scene.onBeforeRenderObservable.addOnce(attempt);\r\n return;\r\n }\r\n this._mrt.renderList = [this._quad];\r\n this._mrt.render();\r\n resolve();\r\n };\r\n this._scene.onBeforeRenderObservable.addOnce(attempt);\r\n });\r\n }\r\n\r\n /**\r\n * Whether the relayout copy shader is compiled and ready. Lazily creates the copy material on first call.\r\n * Callers should poll this before {@link relayoutSync} (which must only run when ready).\r\n * @returns true when {@link relayoutSync} can run this frame\r\n */\r\n public isRelayoutReady(): boolean {\r\n if (this._disposed) {\r\n return false;\r\n }\r\n if (!this._copyMaterial) {\r\n this._copyMaterial = this._createCopyMaterial();\r\n }\r\n return this._copyMaterial.isReady(this._quad);\r\n }\r\n\r\n /**\r\n * Relayouts the decoded work-buffer textures to a new (defragmented) splat layout, keeping the same\r\n * texture instances so the consuming mesh does not need to re-bind. `srcIndexByDst[d]` is the source splat\r\n * index whose decoded data should end up at destination index `d`, or a negative value for a gap (left\r\n * zeroed). Uses a temporary MRT ping-pong (old -> temp via the map, then temp -> old identity) so\r\n * overlapping moves stay correct. Must be called at a frame-safe point (inside `onBeforeRender`) and only\r\n * when {@link isRelayoutReady} returns true.\r\n * @param srcIndexByDst per-destination source splat index (negative = gap)\r\n */\r\n public relayoutSync(srcIndexByDst: Float32Array): void {\r\n if (this._disposed || !this._copyMaterial) {\r\n return;\r\n }\r\n const size = this._textureSize;\r\n // Reuse the map buffer and its GPU texture across relayouts (the work-buffer size is fixed).\r\n if (!this._relayoutMapData) {\r\n this._relayoutMapData = new Float32Array(size * size);\r\n }\r\n const mapData = this._relayoutMapData;\r\n mapData.fill(-1);\r\n mapData.set(srcIndexByDst.subarray(0, Math.min(srcIndexByDst.length, mapData.length)));\r\n if (!this._relayoutMapTexture) {\r\n this._relayoutMapTexture = new RawTexture(\r\n mapData,\r\n size,\r\n size,\r\n Constants.TEXTUREFORMAT_R,\r\n this._scene,\r\n false,\r\n false,\r\n Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n Constants.TEXTURETYPE_FLOAT\r\n );\r\n } else {\r\n this._relayoutMapTexture.update(mapData);\r\n }\r\n const mapTexture = this._relayoutMapTexture;\r\n // The temporary ping-pong MRT is (re)created per relayout rather than kept resident: it is the same size\r\n // as the work buffer, so a persistent copy would double GPU memory and defeat the streaming memory budget.\r\n const temp = this._createMrt(\"gsRelayoutTemp\", false);\r\n try {\r\n // Pass 1: old -> temp using the map (temp gets the new layout; gaps stay zeroed by the clear).\r\n this._renderRelayoutPass(temp, this._mrt.textures, mapTexture, 1);\r\n // Pass 2: temp -> old, identity (old textures get the new layout, full overwrite).\r\n this._renderRelayoutPass(this._mrt, temp.textures, mapTexture, 0);\r\n } finally {\r\n temp.dispose();\r\n this._quad.material = this._material;\r\n }\r\n }\r\n\r\n /**\r\n * Renders one relayout copy pass into the target MRT, sampling the given source textures.\r\n * @param target destination MRT\r\n * @param sources the four source work-buffer textures\r\n * @param mapTexture the R32F destination-to-source index map\r\n * @param useMap 1 to read source indices from the map (gaps discarded), 0 for an identity copy\r\n */\r\n private _renderRelayoutPass(target: MultiRenderTarget, sources: Texture[], mapTexture: RawTexture, useMap: number): void {\r\n const material = this._copyMaterial!;\r\n material.setTexture(\"uMapTex\", mapTexture);\r\n material.setTexture(\"uSrc0\", sources[0]);\r\n material.setTexture(\"uSrc1\", sources[1]);\r\n material.setTexture(\"uSrc2\", sources[2]);\r\n material.setTexture(\"uSrc3\", sources[3]);\r\n material.setInt(\"uDstWidth\", this._textureSize);\r\n material.setInt(\"uSrcWidth\", this._textureSize);\r\n material.setInt(\"uUseMap\", useMap);\r\n this._quad.material = material;\r\n target.renderList = [this._quad];\r\n target.render();\r\n }\r\n\r\n private _createCopyMaterial(): ShaderMaterial {\r\n const isWGSL = this._shaderLanguage === ShaderLanguage.WGSL;\r\n const material = new ShaderMaterial(\r\n GaussianSplattingWorkBufferRelayoutShaderName,\r\n this._scene,\r\n {\r\n vertexSource: isWGSL ? GaussianSplattingWorkBufferVertexShaderWGSL : GaussianSplattingWorkBufferVertexShaderGLSL,\r\n fragmentSource: isWGSL ? GaussianSplattingWorkBufferRelayoutFragmentShaderWGSL : GaussianSplattingWorkBufferRelayoutFragmentShaderGLSL,\r\n },\r\n {\r\n attributes: [\"position\"],\r\n uniforms: [\"uDstWidth\", \"uSrcWidth\", \"uUseMap\"],\r\n samplers: [\"uMapTex\", \"uSrc0\", \"uSrc1\", \"uSrc2\", \"uSrc3\"],\r\n shaderLanguage: this._shaderLanguage,\r\n }\r\n );\r\n material.backFaceCulling = false;\r\n material.disableDepthWrite = true;\r\n return material;\r\n }\r\n\r\n /**\r\n * Asynchronously reads back the decoded splat centers (stride-4 xyzw, w=1) for a contiguous splat range\r\n * from the work buffer's centers texture, using a non-blocking GPU readback (WebGL2 PBO + fence, or WebGPU\r\n * copyTextureToBuffer + mapAsync) so it never stalls the frame the way a CPU image decode does. The centers\r\n * texture already holds the GPU-decoded positions (identical to the CPU decode), so this replaces decoding\r\n * positions on the CPU from the means images. Returns null when async readback is unsupported (caller should\r\n * fall back to CPU decoding).\r\n * @param splatOffset first splat index of the range\r\n * @param splatCount number of splats in the range\r\n * @returns a stride-4 Float32Array of length `splatCount * 4`, or null when unsupported/failed\r\n */\r\n public async readCentersRangeAsync(splatOffset: number, splatCount: number): Promise<Nullable<Float32Array>> {\r\n if (this._disposed || splatCount <= 0 || !this.supportsAsyncCentersReadback) {\r\n return null;\r\n }\r\n\r\n const width = this._textureSize;\r\n // The range maps to whole texel rows [rowStart, rowEnd); read that rectangle and slice the exact range.\r\n // Splat i lives at texel (i % width, floor(i / width)) in both decode and draw, so the readback (which\r\n // indexes the same texture storage directly, with no UV/flip) yields splat i at buffer position\r\n // i - rowStart * width on every backend.\r\n const rowStart = Math.floor(splatOffset / width);\r\n const rowEnd = Math.ceil((splatOffset + splatCount) / width);\r\n const rowCount = rowEnd - rowStart;\r\n const startInBuffer = (splatOffset - rowStart * width) * 4;\r\n const sliceEnd = startInBuffer + splatCount * 4;\r\n const centers = this._mrt.textures[0];\r\n\r\n const engine = this._scene.getEngine();\r\n\r\n if (engine.isWebGPU) {\r\n // WebGPU: copyTextureToBuffer of the row span + mapAsync (genuinely non-blocking). noDataConversion\r\n // returns the raw RGBA32F floats tightly packed (the 256-byte row alignment is removed internally).\r\n const result = await centers.readPixels(0, 0, null, true, true, 0, rowStart, width, rowCount);\r\n if (this._disposed || !result) {\r\n return null;\r\n }\r\n const floats = result instanceof Float32Array ? result : new Float32Array(result.buffer, result.byteOffset, result.byteLength / 4);\r\n return floats.length >= sliceEnd ? (floats.subarray(startInBuffer, sliceEnd) as Float32Array) : null;\r\n }\r\n\r\n // WebGL2: read directly from the centers texture via a reused FBO + async PBO readback.\r\n const glEngine = engine as unknown as {\r\n _gl: WebGL2RenderingContext;\r\n _currentFramebuffer: Nullable<WebGLFramebuffer>;\r\n _readPixelsAsync(x: number, y: number, w: number, h: number, format: number, type: number, o: ArrayBufferView): Nullable<Promise<ArrayBufferView>>;\r\n };\r\n const gl = glEngine._gl;\r\n const hardware = centers.getInternalTexture()?._hardwareTexture?.underlyingResource as Nullable<WebGLTexture>;\r\n if (!hardware) {\r\n return null;\r\n }\r\n const buffer = new Float32Array(width * rowCount * 4);\r\n if (!this._readFbo) {\r\n this._readFbo = gl.createFramebuffer();\r\n }\r\n const previousFbo = glEngine._currentFramebuffer;\r\n gl.bindFramebuffer(gl.FRAMEBUFFER, this._readFbo);\r\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, hardware, 0);\r\n gl.readBuffer(gl.COLOR_ATTACHMENT0);\r\n\r\n // _readPixelsAsync issues the readPixels into a PBO synchronously, then resolves once the GPU fence\r\n // signals — so the framebuffer can be restored immediately while the transfer completes off-thread.\r\n const promise = glEngine._readPixelsAsync(0, rowStart, width, rowCount, gl.RGBA, gl.FLOAT, buffer);\r\n gl.bindFramebuffer(gl.FRAMEBUFFER, previousFbo);\r\n // gl.readBuffer is global state: restore the default-framebuffer read source (BACK) so later\r\n // readPixels on the default framebuffer aren't left pointing at COLOR_ATTACHMENT0. When restoring to\r\n // another FBO, COLOR_ATTACHMENT0 is the correct default read buffer, so only reset for the default one.\r\n if (!previousFbo) {\r\n gl.readBuffer(gl.BACK);\r\n }\r\n if (!promise) {\r\n return null;\r\n }\r\n await promise;\r\n if (this._disposed || buffer.length < sliceEnd) {\r\n return null;\r\n }\r\n return buffer.subarray(startInBuffer, sliceEnd) as Float32Array;\r\n }\r\n\r\n /**\r\n * Disposes the work buffer and its decode resources.\r\n */\r\n public dispose(): void {\r\n this._disposed = true;\r\n if (this._readFbo) {\r\n (this._scene.getEngine() as unknown as { _gl?: WebGL2RenderingContext })._gl?.deleteFramebuffer(this._readFbo);\r\n this._readFbo = null;\r\n }\r\n this._quad.dispose();\r\n this._material.dispose(true, false);\r\n this._copyMaterial?.dispose(true, false);\r\n this._relayoutMapTexture?.dispose();\r\n this._mrt.dispose();\r\n }\r\n\r\n private _createQuad(): Mesh {\r\n const quad = new Mesh(\"gsWorkBufferQuad\", this._scene);\r\n const vertexData = new VertexData();\r\n // Fullscreen triangle in clip space (the vertex shader passes positions straight through).\r\n vertexData.positions = [-1, -1, 0, 3, -1, 0, -1, 3, 0];\r\n vertexData.indices = [0, 1, 2];\r\n vertexData.applyToMesh(quad);\r\n // Render only inside the work-buffer MRT, never in the main scene pass.\r\n this._scene.removeMesh(quad);\r\n return quad;\r\n }\r\n\r\n private _createMaterial(): ShaderMaterial {\r\n const isWGSL = this._shaderLanguage === ShaderLanguage.WGSL;\r\n const material = new ShaderMaterial(\r\n \"gsSogDecode\",\r\n this._scene,\r\n {\r\n vertexSource: isWGSL ? GaussianSplattingWorkBufferVertexShaderWGSL : GaussianSplattingWorkBufferVertexShaderGLSL,\r\n fragmentSource: isWGSL ? GaussianSplattingWorkBufferFragmentShaderWGSL : GaussianSplattingWorkBufferFragmentShaderGLSL,\r\n },\r\n {\r\n attributes: [\"position\"],\r\n uniforms: [\"sogMeansMin\", \"sogMeansMax\", \"sogScalesMin\", \"sogScalesMax\", \"sogSh0Min\", \"sogSh0Max\", \"uVersion\", \"uOffset\", \"uCount\", \"uDestWidth\", \"uSrcWidth\"],\r\n samplers: [\"sogMeansLTex\", \"sogMeansUTex\", \"sogScalesTex\", \"sogQuatsTex\", \"sogSh0Tex\", \"sogCodebookTex\"],\r\n shaderLanguage: this._shaderLanguage,\r\n }\r\n );\r\n material.backFaceCulling = false;\r\n material.disableDepthWrite = true;\r\n return material;\r\n }\r\n\r\n private _applyPack(pack: ISogTexturePack, offset: number): void {\r\n const material = this._material;\r\n const srcWidth = (pack.meansTextureL as Texture).getSize().width;\r\n\r\n material.setTexture(\"sogMeansLTex\", pack.meansTextureL);\r\n material.setTexture(\"sogMeansUTex\", pack.meansTextureU);\r\n material.setTexture(\"sogScalesTex\", pack.scalesTexture);\r\n material.setTexture(\"sogQuatsTex\", pack.quatsTexture);\r\n material.setTexture(\"sogSh0Tex\", pack.sh0Texture);\r\n // Codebook only used for v2; bind a harmless placeholder otherwise so the sampler is always set.\r\n material.setTexture(\"sogCodebookTex\", pack.codebookTexture ?? pack.sh0Texture);\r\n\r\n material.setVector3(\"sogMeansMin\", new Vector3(pack.meansMin[0], pack.meansMin[1], pack.meansMin[2]));\r\n material.setVector3(\"sogMeansMax\", new Vector3(pack.meansMax[0], pack.meansMax[1], pack.meansMax[2]));\r\n const sMin = pack.scalesMin ?? [0, 0, 0];\r\n const sMax = pack.scalesMax ?? [0, 0, 0];\r\n material.setVector3(\"sogScalesMin\", new Vector3(sMin[0], sMin[1], sMin[2]));\r\n material.setVector3(\"sogScalesMax\", new Vector3(sMax[0], sMax[1], sMax[2]));\r\n const c0Min = pack.sh0Min ?? [0, 0, 0, 0];\r\n const c0Max = pack.sh0Max ?? [0, 0, 0, 0];\r\n material.setVector4(\"sogSh0Min\", new Vector4(c0Min[0], c0Min[1], c0Min[2], c0Min[3]));\r\n material.setVector4(\"sogSh0Max\", new Vector4(c0Max[0], c0Max[1], c0Max[2], c0Max[3]));\r\n\r\n material.setInt(\"uVersion\", pack.version);\r\n material.setInt(\"uOffset\", offset);\r\n material.setInt(\"uCount\", pack.splatCount);\r\n material.setInt(\"uDestWidth\", this._textureSize);\r\n material.setInt(\"uSrcWidth\", srcWidth);\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"gaussianSplattingWorkBuffer.js","sourceRoot":"","sources":["../../../../dev/loaders/src/SPLAT/gaussianSplattingWorkBuffer.ts"],"names":[],"mappings":"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","sourcesContent":["import { Logger } from \"core/Misc/logger\";\r\nimport { MultiRenderTarget } from \"core/Materials/Textures/multiRenderTarget\";\r\nimport { ShaderMaterial } from \"core/Materials/shaderMaterial\";\r\nimport { ShaderLanguage } from \"core/Materials/shaderLanguage\";\r\nimport { Constants } from \"core/Engines/constants\";\r\nimport { Mesh } from \"core/Meshes/mesh\";\r\nimport { VertexData } from \"core/Meshes/mesh.vertexData\";\r\nimport { Color4 } from \"core/Maths/math.color\";\r\nimport { Vector3, Vector4 } from \"core/Maths/math.vector\";\r\nimport { type Texture } from \"core/Materials/Textures/texture\";\r\nimport { type BaseTexture } from \"core/Materials/Textures/baseTexture\";\r\nimport { type Scene } from \"core/scene\";\r\nimport { type Nullable } from \"core/types\";\r\nimport { type ISogTexturePack } from \"./splatDefs\";\r\nimport {\r\n GaussianSplattingWorkBufferVertexShaderGLSL,\r\n GaussianSplattingWorkBufferFragmentShaderGLSL,\r\n GaussianSplattingWorkBufferVertexShaderWGSL,\r\n GaussianSplattingWorkBufferFragmentShaderWGSL,\r\n GaussianSplattingWorkBufferRelayoutFragmentShaderGLSL,\r\n GaussianSplattingWorkBufferRelayoutFragmentShaderWGSL,\r\n GaussianSplattingWorkBufferRelayoutShaderName,\r\n GaussianSplattingWorkBufferShDecodeShaderName,\r\n GaussianSplattingWorkBufferShDecodeFragmentShaderGLSL,\r\n GaussianSplattingWorkBufferShDecodeFragmentShaderWGSL,\r\n GaussianSplattingWorkBufferShCopyShaderName,\r\n GaussianSplattingWorkBufferShCopyFragmentShaderGLSL,\r\n GaussianSplattingWorkBufferShCopyFragmentShaderWGSL,\r\n GaussianSplattingWorkBufferRotationDecodeShaderName,\r\n GaussianSplattingWorkBufferRotationDecodeFragmentShaderGLSL,\r\n GaussianSplattingWorkBufferRotationDecodeFragmentShaderWGSL,\r\n GaussianSplattingWorkBufferRotCopyShaderName,\r\n GaussianSplattingWorkBufferRotCopyFragmentShaderGLSL,\r\n GaussianSplattingWorkBufferRotCopyFragmentShaderWGSL,\r\n} from \"./gaussianSplattingWorkBufferShaders\";\r\nimport { RawTexture } from \"core/Materials/Textures/rawTexture\";\r\n\r\n/**\r\n * A unified, GPU-decoded Gaussian Splatting work buffer.\r\n *\r\n * Holds a square MRT texture set (centers / covA / covB / colors) sized to a fixed splat capacity\r\n * (`ceil(sqrt(capacity))`). Each streamed SOG file is decoded directly on the GPU\r\n * (no CPU readback) into its allocated pixel range. The decoded textures are consumed unchanged by the\r\n * standard (non-SOG) Gaussian Splatting draw path.\r\n *\r\n * @experimental\r\n */\r\nexport class GaussianSplattingWorkBuffer {\r\n private readonly _scene: Scene;\r\n // Not readonly: a hosted work buffer is rebound to the compound's NEW atlas MRT after a grow (see rebindAtlas).\r\n private _mrt: MultiRenderTarget;\r\n private readonly _textureSize: number;\r\n private readonly _shaderLanguage: ShaderLanguage;\r\n private readonly _material: ShaderMaterial;\r\n private readonly _quad: Mesh;\r\n // When true this work buffer owns (and disposes) its MRT. False when it wraps an external atlas (a compound\r\n // mesh's MRT) it must not dispose. In the external case the MRT is wide (dstWidth x atlasHeight), decodes are\r\n // offset by _baseOffset (the reserved region's first splat), and _textureSize is the atlas WIDTH.\r\n private readonly _ownsMrt: boolean;\r\n // Not readonly: a hosted region can be RELOCATED to a new base when the compound compacts its atlas\r\n // (reclaiming a removed part's rows). backupRegion() reads from the old base, setBaseOffset() updates it,\r\n // then rebindAtlas() + restoreRegion() writes to the new base.\r\n private _baseOffset: number;\r\n // Splat count this work buffer addresses. Standalone: the whole (square) buffer. Hosted: the reserved\r\n // region's (row-aligned) capacity — used to scope a relayout to the region's atlas rows.\r\n private readonly _capacity: number;\r\n // Relayout (defrag) copy material, created lazily on first relayout.\r\n private _copyMaterial: Nullable<ShaderMaterial> = null;\r\n // Reusable destination->source index map for the relayout pass (created lazily, sized to the work buffer).\r\n private _relayoutMapData: Nullable<Float32Array> = null;\r\n private _relayoutMapTexture: Nullable<RawTexture> = null;\r\n // Transient backup of a hosted region's four textures, held between backupRegion() and restoreRegion() so the\r\n // GPU-decoded data survives the compound recreating its atlas on a grow (adding a part / a second stream).\r\n private _backupMrt: Nullable<MultiRenderTarget> = null;\r\n private _disposed = false;\r\n // Reused WebGL framebuffer for the async centers readback (created lazily, freed in dispose).\r\n private _readFbo: Nullable<WebGLFramebuffer> = null;\r\n\r\n // Higher-order spherical-harmonics. Each SH texture is its own single-attachment integer render target\r\n // (RGBA_INTEGER/UNSIGNED_INTEGER, 16 SH scalar-bytes per texel) so a decode/relayout pass writes exactly one\r\n // attachment, keeping within WebGPU's per-sample color-attachment byte budget. Empty when SH is off.\r\n private _shMrts: MultiRenderTarget[] = [];\r\n // True when this work buffer owns (and disposes) its SH render targets (standalone). False when they are the\r\n // hosting compound's shared SH atlas (hosted) — borrowed, not disposed. Rebound alongside the core atlas.\r\n private _ownsShMrts = false;\r\n // The SH decode material (packed-u32 dequant), created only when SH is requested. Reused across files/passes.\r\n private _shMaterial: Nullable<ShaderMaterial> = null;\r\n // Integer SH relayout/backup copy material (usampler2D -> uvec4), created lazily alongside the float copy.\r\n private _shCopyMaterial: Nullable<ShaderMaterial> = null;\r\n // Transient region-sized integer backups of the SH textures, held between backupRegion() and restoreRegion()\r\n // so the baked SH survives the compound recreating its SH atlas on a grow/compaction (parallel to _backupMrt).\r\n private _backupShMrts: Nullable<MultiRenderTarget[]> = null;\r\n\r\n // Rotation/scale. One 3-attachment half-float render target (rotA / rotB / rotScale) holding the per-splat\r\n // rotation matrix + scale that voxel-based IBL shadowing consumes. Null when rotation decode is off.\r\n private _rotMrt: Nullable<MultiRenderTarget> = null;\r\n // True when this work buffer owns (and disposes) its rotation target (standalone). False when it is the hosting\r\n // compound's shared rotation atlas (hosted) — borrowed, rebound alongside the core atlas, never disposed here.\r\n private _ownsRotMrt = false;\r\n // The rotation/scale decode material, created only when rotation is requested. Reused across files.\r\n private _rotMaterial: Nullable<ShaderMaterial> = null;\r\n // Rotation/scale relayout/backup copy material (3-out float copy), created lazily alongside the float copy.\r\n private _rotCopyMaterial: Nullable<ShaderMaterial> = null;\r\n // Transient region-sized backup of the rotation textures, held between backupRegion() and restoreRegion() so the\r\n // decoded rotation/scale survives the compound recreating its rotation atlas on a grow/compaction.\r\n private _backupRotMrt: Nullable<MultiRenderTarget> = null;\r\n\r\n /**\r\n * True when the engine supports the non-blocking GPU readback used by {@link readCentersRangeAsync}:\r\n * WebGL2 (PBO + fence) or WebGPU (copyTextureToBuffer + mapAsync). When false (e.g. WebGL1), callers must\r\n * decode positions on the CPU instead.\r\n */\r\n public get supportsAsyncCentersReadback(): boolean {\r\n const engine = this._scene.getEngine();\r\n if (engine.isWebGPU) {\r\n return true;\r\n }\r\n const glEngine = engine as unknown as { _gl?: WebGL2RenderingContext; _readPixelsAsync?: unknown; webGLVersion?: number };\r\n return !!glEngine._gl && typeof glEngine._readPixelsAsync === \"function\" && (glEngine.webGLVersion ?? 0) >= 2;\r\n }\r\n\r\n /**\r\n * Square edge length (in pixels) of the work-buffer textures.\r\n */\r\n public get textureSize(): number {\r\n return this._textureSize;\r\n }\r\n\r\n /**\r\n * The decoded work-buffer textures: [centers, covA, covB, colors].\r\n */\r\n public get textures(): Texture[] {\r\n return this._mrt.textures;\r\n }\r\n\r\n /**\r\n * The baked higher-order SH textures (packed-u32, one per `ceil(coeffs*3/16)`), consumed by the draw path's\r\n * `computeSHWeighted`/`decompose` as `shTexture0..N`. Empty when SH decoding is not enabled.\r\n */\r\n public get shTextures(): Texture[] {\r\n return this._shMrts.map((m) => m.textures[0]);\r\n }\r\n\r\n /**\r\n * The decoded rotation/scale textures ([rotationsA, rotationsB, rotationScale], half-float), consumed by the\r\n * voxel-IBL path as `rotationsATexture`/`rotationsBTexture`/`rotationScaleTexture`. Empty when rotation decode\r\n * is not enabled.\r\n */\r\n public get rotationTextures(): Texture[] {\r\n return this._rotMrt ? this._rotMrt.textures : [];\r\n }\r\n\r\n /**\r\n * Creates a work buffer sized to hold `capacity` splats.\r\n *\r\n * Standalone (default): the work buffer creates and owns a square MRT sized `ceil(sqrt(capacity))`, with\r\n * decodes addressed from splat 0.\r\n *\r\n * Hosted (`externalAtlas` provided): the work buffer decodes/reads back into an externally-owned MRT (a\r\n * compound mesh's shared atlas) instead of creating its own. Decodes are placed at `externalAtlas.baseOffset`\r\n * (the reserved region's first splat) and addressed over `externalAtlas.width` (the wide atlas width), so the\r\n * streamed splats land in the compound's atlas and sort/draw together with the static parts.\r\n * @param scene hosting scene\r\n * @param capacity total number of splats the work buffer must address\r\n * @param externalAtlas optional external atlas to decode into instead of creating an owned square MRT\r\n * @param sh optional higher-order SH decode configuration. `textureCount = ceil(coeffs*3/16)` for the max SH\r\n * degree across the streamed files. Standalone: the work buffer creates that many owned single-attachment\r\n * integer render targets. Hosted: `externalMrts` are the compound's shared SH atlas targets (borrowed).\r\n * @param rotationScale optional rotation/scale decode configuration (for voxel-IBL shadows). When present the\r\n * work buffer decodes each splat's rotation matrix + scale into a 3-attachment half-float target. Standalone:\r\n * the work buffer creates and owns that target. Hosted: `externalMrt` is the compound's shared rotation atlas.\r\n */\r\n constructor(\r\n scene: Scene,\r\n capacity: number,\r\n externalAtlas?: { mrt: MultiRenderTarget; width: number; baseOffset: number },\r\n sh?: { textureCount: number; externalMrts?: MultiRenderTarget[] },\r\n rotationScale?: { externalMrt?: MultiRenderTarget }\r\n ) {\r\n this._scene = scene;\r\n this._shaderLanguage = scene.getEngine().isWebGPU ? ShaderLanguage.WGSL : ShaderLanguage.GLSL;\r\n this._capacity = Math.max(1, capacity);\r\n\r\n if (externalAtlas) {\r\n this._mrt = externalAtlas.mrt;\r\n this._textureSize = externalAtlas.width;\r\n this._baseOffset = externalAtlas.baseOffset;\r\n this._ownsMrt = false;\r\n } else {\r\n this._textureSize = Math.max(1, Math.ceil(Math.sqrt(Math.max(1, capacity))));\r\n this._baseOffset = 0;\r\n this._ownsMrt = true;\r\n // The decode buffer accumulates (clear disabled) so each decode preserves previously-decoded files.\r\n this._mrt = this._createMrt(\"gsWorkBuffer\", true);\r\n }\r\n\r\n // Higher-order SH: one single-attachment integer target per packed-u32 SH texture. Standalone owns square\r\n // targets sized like the core atlas; hosted borrows the compound's wide shared SH atlas targets.\r\n if (sh && sh.textureCount > 0) {\r\n if (sh.externalMrts) {\r\n this._shMrts = sh.externalMrts.slice(0, sh.textureCount);\r\n this._ownsShMrts = false;\r\n } else {\r\n for (let k = 0; k < sh.textureCount; k++) {\r\n this._shMrts.push(this._createShMrt(`gsWorkBufferSh${k}`, true));\r\n }\r\n this._ownsShMrts = true;\r\n }\r\n this._shMaterial = this._createShMaterial();\r\n }\r\n\r\n // Rotation/scale: one 3-attachment half-float target. Standalone owns a square target sized like the core\r\n // atlas; hosted borrows the compound's wide shared rotation atlas.\r\n if (rotationScale) {\r\n if (rotationScale.externalMrt) {\r\n this._rotMrt = rotationScale.externalMrt;\r\n this._ownsRotMrt = false;\r\n } else {\r\n this._rotMrt = this._createRotMrt(\"gsWorkBufferRot\", true);\r\n this._ownsRotMrt = true;\r\n }\r\n this._rotMaterial = this._createRotMaterial();\r\n }\r\n\r\n // One persistent decode material + fullscreen-triangle quad, reused (with per-file uniforms)\r\n // for every decode so the shader is compiled only once.\r\n this._material = this._createMaterial();\r\n this._quad = this._createQuad();\r\n this._quad.material = this._material;\r\n\r\n // Hosted: start compiling the copy shader now so backupRegion()/restoreRegion() are ready by the time\r\n // the compound grows its atlas (a synchronous, non-frame-driven event we can't wait on).\r\n if (!this._ownsMrt) {\r\n this.isRelayoutReady();\r\n }\r\n }\r\n\r\n /**\r\n * Rebinds a hosted work buffer to a new atlas MRT (after the compound recreated it on a grow). No-op for a\r\n * standalone work buffer, which owns its MRT.\r\n * @param mrt the compound's new shared atlas\r\n */\r\n public rebindAtlas(mrt: MultiRenderTarget): void {\r\n if (!this._ownsMrt) {\r\n this._mrt = mrt;\r\n }\r\n }\r\n\r\n /**\r\n * Rebinds a hosted work buffer to the compound's NEW shared SH atlas (after the compound recreated it on a\r\n * grow/compaction). No-op when SH isn't in use or the work buffer owns its SH targets (standalone).\r\n * @param shMrts the compound's new shared SH render targets (one per packed-u32 SH texture)\r\n */\r\n public rebindShAtlas(shMrts: Nullable<MultiRenderTarget[]>): void {\r\n if (!this._ownsShMrts && shMrts && this._shMrts.length) {\r\n this._shMrts = shMrts.slice(0, this._shMrts.length);\r\n }\r\n }\r\n\r\n /**\r\n * Rebinds a hosted work buffer to the compound's NEW shared rotation atlas (after the compound recreated it on a\r\n * grow/compaction). No-op when rotation isn't in use or the work buffer owns its rotation target (standalone).\r\n * @param rotMrt the compound's new shared rotation atlas\r\n */\r\n public rebindRotAtlas(rotMrt: Nullable<MultiRenderTarget>): void {\r\n if (!this._ownsRotMrt && rotMrt && this._rotMrt) {\r\n this._rotMrt = rotMrt;\r\n }\r\n }\r\n\r\n /**\r\n * Relocates this hosted region to a new base splat offset in the shared atlas (used when the compound\r\n * compacts its atlas and this region's rows move). Subsequent decode/render/readback and\r\n * {@link restoreRegion} all address from the new base. Call between {@link backupRegion} (which read from\r\n * the old base) and {@link restoreRegion} (which will write to the new base). No-op for a standalone\r\n * work buffer, which owns its square MRT at base 0.\r\n * @param baseOffset the region's new first splat index in the atlas\r\n */\r\n public setBaseOffset(baseOffset: number): void {\r\n if (!this._ownsMrt) {\r\n this._baseOffset = baseOffset;\r\n }\r\n }\r\n\r\n /**\r\n * True once the backup/restore/relayout copy shaders are compiled, so {@link backupRegion} can preserve the\r\n * region across an atlas rebuild. Callers that decode into a hosted region should await this before writing\r\n * data, so a later grow/compaction can never race shader compilation and drop the region.\r\n */\r\n public get canBackup(): boolean {\r\n return this._disposed || this._ownsMrt ? false : this.isRelayoutReady();\r\n }\r\n\r\n /**\r\n * Copies this hosted region's four decoded textures out of the shared atlas into an internal backup MRT so\r\n * they survive the compound recreating the atlas on a grow. Call immediately before the atlas is recreated,\r\n * then {@link rebindAtlas} + {@link restoreRegion} after.\r\n */\r\n public backupRegion(): void {\r\n if (this._disposed || this._ownsMrt) {\r\n return;\r\n }\r\n if (!this.isRelayoutReady()) {\r\n // The copy shaders should be compiled well before any grow (callers warm them before decoding), so this\r\n // path means a grow raced compilation; warn rather than silently drop the region's GPU data on the restore.\r\n Logger.Warn(\"GaussianSplattingWorkBuffer: backup skipped because the copy shaders are not ready; streamed region data may be lost on the atlas rebuild.\");\r\n return;\r\n }\r\n const width = this._textureSize;\r\n const regionRows = Math.max(1, Math.floor(this._capacity / width));\r\n const baseRow = Math.floor(this._baseOffset / width);\r\n if (!this._backupMrt) {\r\n this._backupMrt = this._createMrt(\"gsAtlasBackup\", false, width, regionRows);\r\n }\r\n // Identity copy of the region out of the atlas: with useMap=0 and dstBaseRow=-baseRow the shader reads\r\n // atlas texel ((p.y + baseRow) * width + p.x) — the region's global texel — into backup texel p.\r\n this._renderRelayoutPass(this._backupMrt, this._mrt.textures, this._mrt.textures[0], 0, width, width, 0, -baseRow);\r\n // Same for each baked SH texture (one integer copy pass per texture).\r\n if (this._shMrts.length && this._shCopyMaterial) {\r\n if (!this._backupShMrts) {\r\n this._backupShMrts = this._shMrts.map((_, k) => this._createShMrt(`gsShAtlasBackup${k}`, false, width, regionRows));\r\n }\r\n for (let k = 0; k < this._shMrts.length; k++) {\r\n this._renderShCopyPass(this._backupShMrts[k], this._shMrts[k].textures[0], this._mrt.textures[0], 0, width, width, 0, -baseRow);\r\n }\r\n }\r\n // Same for the rotation/scale textures (one 3-out float copy pass).\r\n if (this._rotMrt && this._rotCopyMaterial) {\r\n if (!this._backupRotMrt) {\r\n this._backupRotMrt = this._createRotMrt(\"gsRotAtlasBackup\", false, width, regionRows);\r\n }\r\n this._renderRotCopyPass(this._backupRotMrt, this._rotMrt.textures, this._mrt.textures[0], 0, width, width, 0, -baseRow);\r\n }\r\n this._quad.material = this._material;\r\n }\r\n\r\n /**\r\n * Restores the backed-up region into the (new) atlas, confined by a scissor to the region's rows so no other\r\n * part is touched. Call {@link rebindAtlas} to the new atlas first. Frees the backup afterwards.\r\n */\r\n public restoreRegion(): void {\r\n if (this._disposed || this._ownsMrt || !this._backupMrt || !this._copyMaterial) {\r\n return;\r\n }\r\n const width = this._textureSize;\r\n const regionRows = Math.max(1, Math.floor(this._capacity / width));\r\n const baseRow = Math.floor(this._baseOffset / width);\r\n const engine = this._scene.getEngine();\r\n engine.enableScissor(0, baseRow, width, regionRows);\r\n try {\r\n // useMap=0 identity with dstBaseRow=baseRow: atlas texel p reads backup texel ((p.y - baseRow)*width + p.x).\r\n this._renderRelayoutPass(this._mrt, this._backupMrt.textures, this._backupMrt.textures[0], 0, width, width, 0, baseRow);\r\n // Restore each baked SH texture the same way (scissored to the region's rows). The map placeholder must\r\n // be a FLOAT texture (uMapTex is texture_2d<f32>) even though useMap=0 doesn't sample it — WebGPU still\r\n // validates the bound texture's sample type against the layout. Use the atlas centers (F32).\r\n if (this._backupShMrts && this._shMrts.length && this._shCopyMaterial) {\r\n for (let k = 0; k < this._shMrts.length && k < this._backupShMrts.length; k++) {\r\n this._renderShCopyPass(this._shMrts[k], this._backupShMrts[k].textures[0], this._mrt.textures[0], 0, width, width, 0, baseRow);\r\n }\r\n }\r\n // Restore the rotation/scale textures the same way (3-out float copy, scissored to the region's rows).\r\n if (this._backupRotMrt && this._rotMrt && this._rotCopyMaterial) {\r\n this._renderRotCopyPass(this._rotMrt, this._backupRotMrt.textures, this._mrt.textures[0], 0, width, width, 0, baseRow);\r\n }\r\n } finally {\r\n engine.disableScissor();\r\n this._quad.material = this._material;\r\n }\r\n this._backupMrt.dispose();\r\n this._backupMrt = null;\r\n if (this._backupShMrts) {\r\n for (const mrt of this._backupShMrts) {\r\n mrt.dispose();\r\n }\r\n this._backupShMrts = null;\r\n }\r\n this._backupRotMrt?.dispose();\r\n this._backupRotMrt = null;\r\n }\r\n\r\n /**\r\n * Creates a 4-attachment MRT (centers F32 / covA / covB / colors U8) sized to the work buffer. covA/covB\r\n * use HALF_FLOAT when the engine can render to it, matching the precision the non-streamed\r\n * GaussianSplattingMesh path already uses for these same two textures (see\r\n * `gaussianSplattingMeshBase.pure.ts`'s `createTextureFromDataF16` covA/covB textures); centers stays F32\r\n * and colors stays U8 in both paths.\r\n * @param name MRT and attachment base name\r\n * @param disableClear when true, clearing is suppressed so renders accumulate (the decode buffer); when\r\n * false the MRT clears to zero on each render (the temporary relayout buffer, so gaps stay zeroed)\r\n * @param width texture width (defaults to the work-buffer size; the region row width for a scoped relayout)\r\n * @param height texture height (defaults to the work-buffer size; the region row count for a scoped relayout)\r\n * @returns the created MRT\r\n */\r\n private _createMrt(name: string, disableClear: boolean, width: number = this._textureSize, height: number = this._textureSize): MultiRenderTarget {\r\n const covType = this._scene.getEngine()._caps.textureHalfFloatRender ? Constants.TEXTURETYPE_HALF_FLOAT : Constants.TEXTURETYPE_FLOAT;\r\n const mrt = new MultiRenderTarget(\r\n name,\r\n { width, height },\r\n 4,\r\n this._scene,\r\n {\r\n types: [Constants.TEXTURETYPE_FLOAT, covType, covType, Constants.TEXTURETYPE_UNSIGNED_BYTE],\r\n samplingModes: [\r\n Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n ],\r\n formats: [Constants.TEXTUREFORMAT_RGBA, Constants.TEXTUREFORMAT_RGBA, Constants.TEXTUREFORMAT_RGBA, Constants.TEXTUREFORMAT_RGBA],\r\n generateDepthBuffer: false,\r\n generateDepthTexture: false,\r\n generateMipMaps: false,\r\n },\r\n [`${name}Centers`, `${name}CovA`, `${name}CovB`, `${name}Colors`]\r\n );\r\n mrt.clearColor = new Color4(0, 0, 0, 0);\r\n mrt.renderList = [];\r\n if (disableClear) {\r\n mrt.onClearObservable.add(() => {});\r\n }\r\n return mrt;\r\n }\r\n\r\n /**\r\n * Creates a single-attachment integer render target (RGBA_INTEGER / UNSIGNED_INTEGER) that holds one packed-u32\r\n * baked-SH texture. One attachment per pass keeps within WebGPU's per-sample color-attachment byte budget and\r\n * matches the format/type of the draw path's `shTexture0..N` samplers (`_GaussianSplattingBytesPerShTexel`).\r\n * @param name attachment name\r\n * @param disableClear when true, clearing is suppressed so SH decodes accumulate across files\r\n * @param width texture width (defaults to the work-buffer size)\r\n * @param height texture height (defaults to the work-buffer size)\r\n * @returns the created single-attachment integer MRT\r\n */\r\n private _createShMrt(name: string, disableClear: boolean, width: number = this._textureSize, height: number = this._textureSize): MultiRenderTarget {\r\n const mrt = new MultiRenderTarget(\r\n name,\r\n { width, height },\r\n 1,\r\n this._scene,\r\n {\r\n types: [Constants.TEXTURETYPE_UNSIGNED_INTEGER],\r\n formats: [Constants.TEXTUREFORMAT_RGBA_INTEGER],\r\n samplingModes: [Constants.TEXTURE_NEAREST_SAMPLINGMODE],\r\n generateDepthBuffer: false,\r\n generateDepthTexture: false,\r\n generateMipMaps: false,\r\n },\r\n [name]\r\n );\r\n mrt.clearColor = new Color4(0, 0, 0, 0);\r\n mrt.renderList = [];\r\n if (disableClear) {\r\n mrt.onClearObservable.add(() => {});\r\n }\r\n return mrt;\r\n }\r\n\r\n /**\r\n * Creates a 3-attachment half-float MRT ([rotA, rotB, rotScale]) holding the per-splat rotation matrix + scale\r\n * consumed by voxel-IBL shadowing. RGBA half-float when the engine can render to it (matching the covariance\r\n * precision), else full float. 3 attachments = 24 B/sample, within WebGPU's per-sample budget (its own pass).\r\n * @param name MRT and attachment base name\r\n * @param disableClear when true, clearing is suppressed so decodes accumulate (the decode buffer)\r\n * @param width texture width (defaults to the work-buffer size; the region row width for a scoped relayout)\r\n * @param height texture height (defaults to the work-buffer size; the region row count for a scoped relayout)\r\n * @returns the created MRT\r\n */\r\n private _createRotMrt(name: string, disableClear: boolean, width: number = this._textureSize, height: number = this._textureSize): MultiRenderTarget {\r\n const rotType = this._scene.getEngine()._caps.textureHalfFloatRender ? Constants.TEXTURETYPE_HALF_FLOAT : Constants.TEXTURETYPE_FLOAT;\r\n const mrt = new MultiRenderTarget(\r\n name,\r\n { width, height },\r\n 3,\r\n this._scene,\r\n {\r\n types: [rotType, rotType, rotType],\r\n formats: [Constants.TEXTUREFORMAT_RGBA, Constants.TEXTUREFORMAT_RGBA, Constants.TEXTUREFORMAT_RGBA],\r\n samplingModes: [Constants.TEXTURE_NEAREST_SAMPLINGMODE, Constants.TEXTURE_NEAREST_SAMPLINGMODE, Constants.TEXTURE_NEAREST_SAMPLINGMODE],\r\n generateDepthBuffer: false,\r\n generateDepthTexture: false,\r\n generateMipMaps: false,\r\n },\r\n [`${name}A`, `${name}B`, `${name}Scale`]\r\n );\r\n mrt.clearColor = new Color4(0, 0, 0, 0);\r\n mrt.renderList = [];\r\n if (disableClear) {\r\n mrt.onClearObservable.add(() => {});\r\n }\r\n return mrt;\r\n }\r\n\r\n /**\r\n * Decodes one SOG file into the work buffer at the given splat offset (accumulating; previously\r\n * decoded files are preserved). Resolves once the GPU decode has been issued. The caller may\r\n * dispose the source pack textures after this resolves.\r\n * @param pack the SOG texture pack (GPU source textures + per-file decode parameters)\r\n * @param offset first splat index (pixel offset) for this file in the work buffer\r\n */\r\n public async decodeAsync(pack: ISogTexturePack, offset: number): Promise<void> {\r\n if (this._disposed) {\r\n return;\r\n }\r\n this._applyPack(pack);\r\n // When SH is enabled, bake EVERY file's region — even a file with no higher-order SH (a coarse LOD may drop\r\n // it): those get uCoeffs=0 so the whole region neutral-fills (128), keeping mixed-degree files consistent.\r\n const decodeSh = this._shMaterial !== null && this._shMrts.length > 0;\r\n if (decodeSh) {\r\n this._applyShPack(pack);\r\n }\r\n const decodeRot = this._rotMaterial !== null && this._rotMrt !== null;\r\n if (decodeRot) {\r\n this._applyRotPack(pack);\r\n }\r\n // Render the decode pass at the start of a frame (the safe point for custom render targets),\r\n // once the shader is compiled — never re-entrantly from a promise/observable continuation.\r\n await new Promise<void>((resolve) => {\r\n const attempt = () => {\r\n if (this._disposed) {\r\n resolve();\r\n return;\r\n }\r\n if (!this._material.isReady(this._quad) || (decodeSh && !this._shMaterial!.isReady(this._quad)) || (decodeRot && !this._rotMaterial!.isReady(this._quad))) {\r\n this._scene.onBeforeRenderObservable.addOnce(attempt);\r\n return;\r\n }\r\n // Scissor every pass to just this file's atlas rows so the fullscreen triangle only shades the region\r\n // it writes, not the whole (wide) atlas. Correct because the shaders already discard outside the exact\r\n // splat range, and the row band is a superset of it.\r\n const width = this._textureSize;\r\n // Bind uOffset at render time from the live _baseOffset so it shares one value with the scissor below:\r\n // compactAtlas() can relocate this region (via setBaseOffset) during the defer window.\r\n const globalOffset = this._baseOffset + offset;\r\n this._material.setInt(\"uOffset\", globalOffset);\r\n if (decodeSh) {\r\n this._shMaterial!.setInt(\"uOffset\", globalOffset);\r\n }\r\n if (decodeRot) {\r\n this._rotMaterial!.setInt(\"uOffset\", globalOffset);\r\n }\r\n const firstRow = Math.floor(globalOffset / width);\r\n const rowCount = Math.max(1, Math.ceil((globalOffset + pack.splatCount) / width) - firstRow);\r\n const engine = this._scene.getEngine();\r\n engine.enableScissor(0, firstRow, width, rowCount);\r\n try {\r\n this._quad.material = this._material;\r\n this._mrt.renderList = [this._quad];\r\n this._mrt.render();\r\n // Bake this file's higher-order SH: one pass per packed-u32 SH texture (uShTextureIndex selects the\r\n // 16 SH scalars written this pass). Files with fewer coefficients neutral-fill (128) higher bands.\r\n if (decodeSh) {\r\n for (let k = 0; k < this._shMrts.length; k++) {\r\n this._shMaterial!.setInt(\"uShTextureIndex\", k);\r\n this._quad.material = this._shMaterial!;\r\n this._shMrts[k].renderList = [this._quad];\r\n this._shMrts[k].render();\r\n }\r\n this._quad.material = this._material;\r\n }\r\n // Bake this file's rotation/scale into the 3-attachment half-float rotation target (one pass).\r\n if (decodeRot) {\r\n this._quad.material = this._rotMaterial!;\r\n this._rotMrt!.renderList = [this._quad];\r\n this._rotMrt!.render();\r\n this._quad.material = this._material;\r\n }\r\n } finally {\r\n engine.disableScissor();\r\n }\r\n resolve();\r\n };\r\n this._scene.onBeforeRenderObservable.addOnce(attempt);\r\n });\r\n }\r\n\r\n /**\r\n * Whether the relayout copy shader is compiled and ready. Lazily creates the copy material on first call.\r\n * Callers should poll this before {@link relayoutSync} (which must only run when ready).\r\n * @returns true when {@link relayoutSync} can run this frame\r\n */\r\n public isRelayoutReady(): boolean {\r\n if (this._disposed) {\r\n return false;\r\n }\r\n if (!this._copyMaterial) {\r\n this._copyMaterial = this._createCopyMaterial();\r\n }\r\n // When SH is in use, the integer copy shader must also be compiled before a backup/restore/relayout can run.\r\n if (this._shMrts.length && !this._shCopyMaterial) {\r\n this._shCopyMaterial = this._createShCopyMaterial();\r\n }\r\n // Same for the rotation/scale 3-out float copy shader when rotation is in use.\r\n if (this._rotMrt && !this._rotCopyMaterial) {\r\n this._rotCopyMaterial = this._createRotCopyMaterial();\r\n }\r\n // `isReady` reports \"not ready\" when a bound sampler points at a disposed texture (a previous backup/relayout\r\n // binds its temp MRTs as sources, then frees them). The copy passes bind fresh textures every call, so re-point\r\n // the materials at the live atlas textures first; the check then reflects only whether the shader compiled.\r\n this._bindCopyMaterialsToAtlas();\r\n const shReady = this._shMrts.length === 0 || (this._shCopyMaterial !== null && this._shCopyMaterial.isReady(this._quad));\r\n const rotReady = !this._rotMrt || (this._rotCopyMaterial !== null && this._rotCopyMaterial.isReady(this._quad));\r\n return this._copyMaterial.isReady(this._quad) && shReady && rotReady;\r\n }\r\n\r\n /**\r\n * Re-points the relayout/backup copy materials' samplers at the live atlas textures (valid, never freed), so a\r\n * later {@link isRelayoutReady} check isn't tripped by a stale binding to a disposed temp/backup MRT.\r\n */\r\n private _bindCopyMaterialsToAtlas(): void {\r\n const t = this._mrt.textures;\r\n if (this._copyMaterial) {\r\n this._copyMaterial.setTexture(\"uMapTex\", t[0]);\r\n this._copyMaterial.setTexture(\"uSrc0\", t[0]);\r\n this._copyMaterial.setTexture(\"uSrc1\", t[1]);\r\n this._copyMaterial.setTexture(\"uSrc2\", t[2]);\r\n this._copyMaterial.setTexture(\"uSrc3\", t[3]);\r\n }\r\n if (this._shCopyMaterial && this._shMrts.length) {\r\n this._shCopyMaterial.setTexture(\"uMapTex\", t[0]);\r\n this._shCopyMaterial.setTexture(\"uSrcSh\", this._shMrts[0].textures[0]);\r\n }\r\n if (this._rotCopyMaterial && this._rotMrt) {\r\n const r = this._rotMrt.textures;\r\n this._rotCopyMaterial.setTexture(\"uMapTex\", t[0]);\r\n this._rotCopyMaterial.setTexture(\"uSrc0\", r[0]);\r\n this._rotCopyMaterial.setTexture(\"uSrc1\", r[1]);\r\n this._rotCopyMaterial.setTexture(\"uSrc2\", r[2]);\r\n }\r\n }\r\n\r\n /**\r\n * Relayouts the decoded work-buffer textures to a new (defragmented) splat layout, keeping the same\r\n * texture instances so the consuming mesh does not need to re-bind. `srcIndexByDst[d]` is the source splat\r\n * index whose decoded data should end up at destination index `d`, or a negative value for a gap (left\r\n * zeroed). Uses a temporary MRT ping-pong (old -> temp via the map, then temp -> old identity) so\r\n * overlapping moves stay correct. Must be called at a frame-safe point (inside `onBeforeRender`) and only\r\n * when {@link isRelayoutReady} returns true.\r\n * @param srcIndexByDst per-destination source splat index (negative = gap)\r\n */\r\n public relayoutSync(srcIndexByDst: Float32Array): void {\r\n if (this._disposed || !this._copyMaterial) {\r\n return;\r\n }\r\n // Map dimensions: standalone maps the whole square buffer; hosted maps just the region's rows.\r\n const width = this._textureSize;\r\n const mapW = width;\r\n const mapH = this._ownsMrt ? width : Math.max(1, Math.floor(this._capacity / width));\r\n // Reuse the map buffer + its GPU texture across relayouts (dimensions are fixed for a work buffer).\r\n if (!this._relayoutMapData) {\r\n this._relayoutMapData = new Float32Array(mapW * mapH);\r\n }\r\n const mapData = this._relayoutMapData;\r\n mapData.fill(-1);\r\n mapData.set(srcIndexByDst.subarray(0, Math.min(srcIndexByDst.length, mapData.length)));\r\n if (!this._relayoutMapTexture) {\r\n this._relayoutMapTexture = new RawTexture(\r\n mapData,\r\n mapW,\r\n mapH,\r\n Constants.TEXTUREFORMAT_R,\r\n this._scene,\r\n false,\r\n false,\r\n Constants.TEXTURE_NEAREST_SAMPLINGMODE,\r\n Constants.TEXTURETYPE_FLOAT\r\n );\r\n } else {\r\n this._relayoutMapTexture.update(mapData);\r\n }\r\n const mapTexture = this._relayoutMapTexture;\r\n\r\n if (this._ownsMrt) {\r\n // Standalone: the work buffer owns the whole square texture, so a full ping-pong is safe.\r\n const temp = this._createMrt(\"gsRelayoutTemp\", false);\r\n try {\r\n this._renderRelayoutPass(temp, this._mrt.textures, mapTexture, 1); // old -> temp via map (gaps cleared)\r\n this._renderRelayoutPass(this._mrt, temp.textures, mapTexture, 0); // temp -> old, identity full overwrite\r\n } finally {\r\n temp.dispose();\r\n }\r\n // Same ping-pong for each baked SH texture (integer copy, one temp per texture).\r\n if (this._shMrts.length && this._shCopyMaterial) {\r\n for (let k = 0; k < this._shMrts.length; k++) {\r\n const shTemp = this._createShMrt(\"gsShRelayoutTemp\", false);\r\n try {\r\n this._renderShCopyPass(shTemp, this._shMrts[k].textures[0], mapTexture, 1);\r\n this._renderShCopyPass(this._shMrts[k], shTemp.textures[0], mapTexture, 0);\r\n } finally {\r\n shTemp.dispose();\r\n }\r\n }\r\n }\r\n // Same ping-pong for the rotation/scale textures (3-out float copy).\r\n if (this._rotMrt && this._rotCopyMaterial) {\r\n const rotTemp = this._createRotMrt(\"gsRotRelayoutTemp\", false);\r\n try {\r\n this._renderRotCopyPass(rotTemp, this._rotMrt.textures, mapTexture, 1);\r\n this._renderRotCopyPass(this._rotMrt, rotTemp.textures, mapTexture, 0);\r\n } finally {\r\n rotTemp.dispose();\r\n }\r\n }\r\n this._quad.material = this._material;\r\n return;\r\n }\r\n\r\n // Hosted (shared compound atlas): scope the ping-pong to THIS region's row band so other parts are never\r\n // touched. `_baseOffset` and `_capacity` are row-aligned (reserveStreamingPart), so the band is exact.\r\n const baseRow = Math.floor(this._baseOffset / width);\r\n const regionRows = mapH;\r\n const engine = this._scene.getEngine();\r\n // Region-sized temp (width x regionRows) — memory stays proportional to the region, not the whole atlas.\r\n const temp = this._createMrt(\"gsRelayoutTemp\", false, width, regionRows);\r\n // One region-sized integer temp per baked SH texture (same ping-pong, integer format).\r\n const shTemps = this._shMrts.length && this._shCopyMaterial ? this._shMrts.map((_, k) => this._createShMrt(`gsShRelayoutTemp${k}`, false, width, regionRows)) : [];\r\n // One region-sized rotation temp (3-attachment float) when rotation is in use.\r\n const rotTemp = this._rotMrt && this._rotCopyMaterial ? this._createRotMrt(\"gsRotRelayoutTemp\", false, width, regionRows) : null;\r\n try {\r\n // Pass 1: atlas region -> temp via map. The map is region-local; uSrcBaseOffset shifts each source\r\n // index to its GLOBAL atlas texel (uSrcWidth = atlas width). Temp is exactly the band, so no scissor.\r\n this._renderRelayoutPass(temp, this._mrt.textures, mapTexture, 1, /*dstWidth*/ width, /*srcWidth*/ width, /*srcBaseOffset*/ this._baseOffset, /*dstBaseRow*/ 0);\r\n for (let k = 0; k < shTemps.length; k++) {\r\n this._renderShCopyPass(shTemps[k], this._shMrts[k].textures[0], mapTexture, 1, width, width, this._baseOffset, 0);\r\n }\r\n if (rotTemp) {\r\n this._renderRotCopyPass(rotTemp, this._rotMrt!.textures, mapTexture, 1, width, width, this._baseOffset, 0);\r\n }\r\n // Pass 2: temp -> atlas region, identity within the band. uDstBaseRow maps the atlas destination row\r\n // back into the region-local temp; the scissor confines writes to the band so static parts are safe.\r\n engine.enableScissor(0, baseRow, width, regionRows);\r\n try {\r\n this._renderRelayoutPass(this._mrt, temp.textures, mapTexture, 0, /*dstWidth*/ width, /*srcWidth*/ width, /*srcBaseOffset*/ 0, /*dstBaseRow*/ baseRow);\r\n for (let k = 0; k < shTemps.length; k++) {\r\n this._renderShCopyPass(this._shMrts[k], shTemps[k].textures[0], mapTexture, 0, width, width, 0, baseRow);\r\n }\r\n if (rotTemp) {\r\n this._renderRotCopyPass(this._rotMrt!, rotTemp.textures, mapTexture, 0, width, width, 0, baseRow);\r\n }\r\n } finally {\r\n engine.disableScissor();\r\n }\r\n } finally {\r\n temp.dispose();\r\n for (const t of shTemps) {\r\n t.dispose();\r\n }\r\n rotTemp?.dispose();\r\n this._quad.material = this._material;\r\n }\r\n }\r\n\r\n /**\r\n * Renders one relayout copy pass into the target MRT, sampling the given source textures.\r\n * @param target destination MRT\r\n * @param sources the four source work-buffer textures\r\n * @param mapTexture the R32F destination-to-source index map (only sampled when `useMap` is 1; any bound texture otherwise)\r\n * @param useMap 1 to read source indices from the map (gaps discarded), 0 for an identity copy\r\n * @param dstWidth destination width used to linearize the destination texel (defaults to the work-buffer size)\r\n * @param srcWidth source width used to convert a linear source index to a texel (defaults to the work-buffer size)\r\n * @param srcBaseOffset added to each mapped source index so a region-local map reads the correct global atlas texel (hosted relayout)\r\n * @param dstBaseRow subtracted from the destination row so an identity copy reads the region-local temp (hosted relayout)\r\n */\r\n private _renderRelayoutPass(\r\n target: MultiRenderTarget,\r\n sources: Texture[],\r\n mapTexture: BaseTexture,\r\n useMap: number,\r\n dstWidth: number = this._textureSize,\r\n srcWidth: number = this._textureSize,\r\n srcBaseOffset: number = 0,\r\n dstBaseRow: number = 0\r\n ): void {\r\n const material = this._copyMaterial!;\r\n material.setTexture(\"uMapTex\", mapTexture);\r\n material.setTexture(\"uSrc0\", sources[0]);\r\n material.setTexture(\"uSrc1\", sources[1]);\r\n material.setTexture(\"uSrc2\", sources[2]);\r\n material.setTexture(\"uSrc3\", sources[3]);\r\n material.setInt(\"uDstWidth\", dstWidth);\r\n material.setInt(\"uSrcWidth\", srcWidth);\r\n material.setInt(\"uUseMap\", useMap);\r\n material.setInt(\"uSrcBaseOffset\", srcBaseOffset);\r\n material.setInt(\"uDstBaseRow\", dstBaseRow);\r\n this._quad.material = material;\r\n target.renderList = [this._quad];\r\n target.render();\r\n }\r\n\r\n private _createCopyMaterial(): ShaderMaterial {\r\n const isWGSL = this._shaderLanguage === ShaderLanguage.WGSL;\r\n const material = new ShaderMaterial(\r\n GaussianSplattingWorkBufferRelayoutShaderName,\r\n this._scene,\r\n {\r\n vertexSource: isWGSL ? GaussianSplattingWorkBufferVertexShaderWGSL : GaussianSplattingWorkBufferVertexShaderGLSL,\r\n fragmentSource: isWGSL ? GaussianSplattingWorkBufferRelayoutFragmentShaderWGSL : GaussianSplattingWorkBufferRelayoutFragmentShaderGLSL,\r\n },\r\n {\r\n attributes: [\"position\"],\r\n uniforms: [\"uDstWidth\", \"uSrcWidth\", \"uUseMap\", \"uSrcBaseOffset\", \"uDstBaseRow\"],\r\n samplers: [\"uMapTex\", \"uSrc0\", \"uSrc1\", \"uSrc2\", \"uSrc3\"],\r\n shaderLanguage: this._shaderLanguage,\r\n }\r\n );\r\n material.backFaceCulling = false;\r\n material.disableDepthWrite = true;\r\n return material;\r\n }\r\n\r\n /**\r\n * Renders one INTEGER SH copy pass (one packed-u32 SH texture) into the target, sampling one integer source.\r\n * Same index/map/base math as {@link _renderRelayoutPass} but for the integer SH format.\r\n * @param target destination single-attachment integer MRT\r\n * @param srcSh the integer SH source texture\r\n * @param mapTexture the R32F destination-to-source index map (sampled only when `useMap` is 1)\r\n * @param useMap 1 to read source indices from the map (gaps discarded), 0 for an identity copy\r\n * @param dstWidth destination width used to linearize the destination texel\r\n * @param srcWidth source width used to convert a linear source index to a texel\r\n * @param srcBaseOffset added to each mapped source index (region-local map -> global atlas texel)\r\n * @param dstBaseRow subtracted from the destination row for an identity copy of a region-local temp\r\n */\r\n private _renderShCopyPass(\r\n target: MultiRenderTarget,\r\n srcSh: Texture,\r\n mapTexture: BaseTexture,\r\n useMap: number,\r\n dstWidth: number = this._textureSize,\r\n srcWidth: number = this._textureSize,\r\n srcBaseOffset: number = 0,\r\n dstBaseRow: number = 0\r\n ): void {\r\n const material = this._shCopyMaterial!;\r\n material.setTexture(\"uMapTex\", mapTexture);\r\n material.setTexture(\"uSrcSh\", srcSh);\r\n material.setInt(\"uDstWidth\", dstWidth);\r\n material.setInt(\"uSrcWidth\", srcWidth);\r\n material.setInt(\"uUseMap\", useMap);\r\n material.setInt(\"uSrcBaseOffset\", srcBaseOffset);\r\n material.setInt(\"uDstBaseRow\", dstBaseRow);\r\n this._quad.material = material;\r\n target.renderList = [this._quad];\r\n target.render();\r\n }\r\n\r\n private _createShCopyMaterial(): ShaderMaterial {\r\n const isWGSL = this._shaderLanguage === ShaderLanguage.WGSL;\r\n const material = new ShaderMaterial(\r\n GaussianSplattingWorkBufferShCopyShaderName,\r\n this._scene,\r\n {\r\n vertexSource: isWGSL ? GaussianSplattingWorkBufferVertexShaderWGSL : GaussianSplattingWorkBufferVertexShaderGLSL,\r\n fragmentSource: isWGSL ? GaussianSplattingWorkBufferShCopyFragmentShaderWGSL : GaussianSplattingWorkBufferShCopyFragmentShaderGLSL,\r\n },\r\n {\r\n attributes: [\"position\"],\r\n uniforms: [\"uDstWidth\", \"uSrcWidth\", \"uUseMap\", \"uSrcBaseOffset\", \"uDstBaseRow\"],\r\n samplers: [\"uMapTex\", \"uSrcSh\"],\r\n shaderLanguage: this._shaderLanguage,\r\n }\r\n );\r\n material.backFaceCulling = false;\r\n material.disableDepthWrite = true;\r\n return material;\r\n }\r\n\r\n /**\r\n * Renders one rotation/scale copy pass (the three half-float rotation textures) into the target. Same\r\n * index/map/base math as {@link _renderRelayoutPass} but with three attachments.\r\n * @param target destination 3-attachment MRT\r\n * @param sources the three source rotation textures ([rotA, rotB, rotScale])\r\n * @param mapTexture the R32F destination-to-source index map (sampled only when `useMap` is 1)\r\n * @param useMap 1 to read source indices from the map (gaps discarded), 0 for an identity copy\r\n * @param dstWidth destination width used to linearize the destination texel\r\n * @param srcWidth source width used to convert a linear source index to a texel\r\n * @param srcBaseOffset added to each mapped source index (region-local map -> global atlas texel)\r\n * @param dstBaseRow subtracted from the destination row for an identity copy of a region-local temp\r\n */\r\n private _renderRotCopyPass(\r\n target: MultiRenderTarget,\r\n sources: Texture[],\r\n mapTexture: BaseTexture,\r\n useMap: number,\r\n dstWidth: number = this._textureSize,\r\n srcWidth: number = this._textureSize,\r\n srcBaseOffset: number = 0,\r\n dstBaseRow: number = 0\r\n ): void {\r\n const material = this._rotCopyMaterial!;\r\n material.setTexture(\"uMapTex\", mapTexture);\r\n material.setTexture(\"uSrc0\", sources[0]);\r\n material.setTexture(\"uSrc1\", sources[1]);\r\n material.setTexture(\"uSrc2\", sources[2]);\r\n material.setInt(\"uDstWidth\", dstWidth);\r\n material.setInt(\"uSrcWidth\", srcWidth);\r\n material.setInt(\"uUseMap\", useMap);\r\n material.setInt(\"uSrcBaseOffset\", srcBaseOffset);\r\n material.setInt(\"uDstBaseRow\", dstBaseRow);\r\n this._quad.material = material;\r\n target.renderList = [this._quad];\r\n target.render();\r\n }\r\n\r\n private _createRotCopyMaterial(): ShaderMaterial {\r\n const isWGSL = this._shaderLanguage === ShaderLanguage.WGSL;\r\n const material = new ShaderMaterial(\r\n GaussianSplattingWorkBufferRotCopyShaderName,\r\n this._scene,\r\n {\r\n vertexSource: isWGSL ? GaussianSplattingWorkBufferVertexShaderWGSL : GaussianSplattingWorkBufferVertexShaderGLSL,\r\n fragmentSource: isWGSL ? GaussianSplattingWorkBufferRotCopyFragmentShaderWGSL : GaussianSplattingWorkBufferRotCopyFragmentShaderGLSL,\r\n },\r\n {\r\n attributes: [\"position\"],\r\n uniforms: [\"uDstWidth\", \"uSrcWidth\", \"uUseMap\", \"uSrcBaseOffset\", \"uDstBaseRow\"],\r\n samplers: [\"uMapTex\", \"uSrc0\", \"uSrc1\", \"uSrc2\"],\r\n shaderLanguage: this._shaderLanguage,\r\n }\r\n );\r\n material.backFaceCulling = false;\r\n material.disableDepthWrite = true;\r\n return material;\r\n }\r\n\r\n /**\r\n * Asynchronously reads back the decoded splat centers (stride-4 xyzw, w=1) for a contiguous splat range\r\n * from the work buffer's centers texture, using a non-blocking GPU readback (WebGL2 PBO + fence, or WebGPU\r\n * copyTextureToBuffer + mapAsync) so it never stalls the frame the way a CPU image decode does. The centers\r\n * texture already holds the GPU-decoded positions (identical to the CPU decode), so this replaces decoding\r\n * positions on the CPU from the means images. Returns null when async readback is unsupported (caller should\r\n * fall back to CPU decoding).\r\n * @param splatOffset first splat index of the range\r\n * @param splatCount number of splats in the range\r\n * @returns a stride-4 Float32Array of length `splatCount * 4`, or null when unsupported/failed\r\n */\r\n public async readCentersRangeAsync(splatOffset: number, splatCount: number): Promise<Nullable<Float32Array>> {\r\n if (this._disposed || splatCount <= 0 || !this.supportsAsyncCentersReadback) {\r\n return null;\r\n }\r\n\r\n const width = this._textureSize;\r\n // Shift the region-local offset by the atlas base so the readback targets the same global texels the\r\n // decode wrote (0 base for a standalone work buffer).\r\n const globalOffset = this._baseOffset + splatOffset;\r\n // The range maps to whole texel rows [rowStart, rowEnd); read that rectangle and slice the exact range.\r\n // Splat i lives at texel (i % width, floor(i / width)) in both decode and draw, so the readback (which\r\n // indexes the same texture storage directly, with no UV/flip) yields splat i at buffer position\r\n // i - rowStart * width on every backend.\r\n const rowStart = Math.floor(globalOffset / width);\r\n const rowEnd = Math.ceil((globalOffset + splatCount) / width);\r\n const rowCount = rowEnd - rowStart;\r\n const startInBuffer = (globalOffset - rowStart * width) * 4;\r\n const sliceEnd = startInBuffer + splatCount * 4;\r\n const centers = this._mrt.textures[0];\r\n\r\n const engine = this._scene.getEngine();\r\n\r\n if (engine.isWebGPU) {\r\n // WebGPU: copyTextureToBuffer of the row span + mapAsync (genuinely non-blocking). noDataConversion\r\n // returns the raw RGBA32F floats tightly packed (the 256-byte row alignment is removed internally).\r\n const result = await centers.readPixels(0, 0, null, true, true, 0, rowStart, width, rowCount);\r\n if (this._disposed || !result) {\r\n return null;\r\n }\r\n const floats = result instanceof Float32Array ? result : new Float32Array(result.buffer, result.byteOffset, result.byteLength / 4);\r\n return floats.length >= sliceEnd ? (floats.subarray(startInBuffer, sliceEnd) as Float32Array) : null;\r\n }\r\n\r\n // WebGL2: read directly from the centers texture via a reused FBO + async PBO readback.\r\n const glEngine = engine as unknown as {\r\n _gl: WebGL2RenderingContext;\r\n _currentFramebuffer: Nullable<WebGLFramebuffer>;\r\n _readPixelsAsync(x: number, y: number, w: number, h: number, format: number, type: number, o: ArrayBufferView): Nullable<Promise<ArrayBufferView>>;\r\n };\r\n const gl = glEngine._gl;\r\n const hardware = centers.getInternalTexture()?._hardwareTexture?.underlyingResource as Nullable<WebGLTexture>;\r\n if (!hardware) {\r\n return null;\r\n }\r\n const buffer = new Float32Array(width * rowCount * 4);\r\n if (!this._readFbo) {\r\n this._readFbo = gl.createFramebuffer();\r\n }\r\n const previousFbo = glEngine._currentFramebuffer;\r\n gl.bindFramebuffer(gl.FRAMEBUFFER, this._readFbo);\r\n gl.framebufferTexture2D(gl.FRAMEBUFFER, gl.COLOR_ATTACHMENT0, gl.TEXTURE_2D, hardware, 0);\r\n gl.readBuffer(gl.COLOR_ATTACHMENT0);\r\n\r\n // _readPixelsAsync issues the readPixels into a PBO synchronously, then resolves once the GPU fence\r\n // signals — so the framebuffer can be restored immediately while the transfer completes off-thread.\r\n const promise = glEngine._readPixelsAsync(0, rowStart, width, rowCount, gl.RGBA, gl.FLOAT, buffer);\r\n gl.bindFramebuffer(gl.FRAMEBUFFER, previousFbo);\r\n // gl.readBuffer is global state: restore the default-framebuffer read source (BACK) so later\r\n // readPixels on the default framebuffer aren't left pointing at COLOR_ATTACHMENT0. When restoring to\r\n // another FBO, COLOR_ATTACHMENT0 is the correct default read buffer, so only reset for the default one.\r\n if (!previousFbo) {\r\n gl.readBuffer(gl.BACK);\r\n }\r\n if (!promise) {\r\n return null;\r\n }\r\n await promise;\r\n if (this._disposed || buffer.length < sliceEnd) {\r\n return null;\r\n }\r\n return buffer.subarray(startInBuffer, sliceEnd) as Float32Array;\r\n }\r\n\r\n /**\r\n * Disposes the work buffer and its decode resources.\r\n */\r\n public dispose(): void {\r\n this._disposed = true;\r\n if (this._readFbo) {\r\n (this._scene.getEngine() as unknown as { _gl?: WebGL2RenderingContext })._gl?.deleteFramebuffer(this._readFbo);\r\n this._readFbo = null;\r\n }\r\n this._quad.dispose();\r\n this._material.dispose(true, false);\r\n this._shMaterial?.dispose(true, false);\r\n this._rotMaterial?.dispose(true, false);\r\n this._copyMaterial?.dispose(true, false);\r\n this._shCopyMaterial?.dispose(true, false);\r\n this._rotCopyMaterial?.dispose(true, false);\r\n this._relayoutMapTexture?.dispose();\r\n this._backupMrt?.dispose();\r\n this._backupMrt = null;\r\n if (this._backupShMrts) {\r\n for (const mrt of this._backupShMrts) {\r\n mrt.dispose();\r\n }\r\n this._backupShMrts = null;\r\n }\r\n this._backupRotMrt?.dispose();\r\n this._backupRotMrt = null;\r\n // Only dispose the MRT when we own it; an external atlas belongs to the hosting compound mesh.\r\n if (this._ownsMrt) {\r\n this._mrt.dispose();\r\n }\r\n // Same ownership rule for the SH targets (standalone owns; hosted borrows the compound's shared SH atlas).\r\n if (this._ownsShMrts) {\r\n for (const mrt of this._shMrts) {\r\n mrt.dispose();\r\n }\r\n }\r\n this._shMrts = [];\r\n // Same ownership rule for the rotation target.\r\n if (this._ownsRotMrt) {\r\n this._rotMrt?.dispose();\r\n }\r\n this._rotMrt = null;\r\n }\r\n\r\n private _createQuad(): Mesh {\r\n const quad = new Mesh(\"gsWorkBufferQuad\", this._scene);\r\n const vertexData = new VertexData();\r\n // Fullscreen triangle in clip space (the vertex shader passes positions straight through).\r\n vertexData.positions = [-1, -1, 0, 3, -1, 0, -1, 3, 0];\r\n vertexData.indices = [0, 1, 2];\r\n vertexData.applyToMesh(quad);\r\n // Render only inside the work-buffer MRT, never in the main scene pass.\r\n this._scene.removeMesh(quad);\r\n return quad;\r\n }\r\n\r\n private _createMaterial(): ShaderMaterial {\r\n const isWGSL = this._shaderLanguage === ShaderLanguage.WGSL;\r\n const material = new ShaderMaterial(\r\n \"gsSogDecode\",\r\n this._scene,\r\n {\r\n vertexSource: isWGSL ? GaussianSplattingWorkBufferVertexShaderWGSL : GaussianSplattingWorkBufferVertexShaderGLSL,\r\n fragmentSource: isWGSL ? GaussianSplattingWorkBufferFragmentShaderWGSL : GaussianSplattingWorkBufferFragmentShaderGLSL,\r\n },\r\n {\r\n attributes: [\"position\"],\r\n uniforms: [\"sogMeansMin\", \"sogMeansMax\", \"sogScalesMin\", \"sogScalesMax\", \"sogSh0Min\", \"sogSh0Max\", \"uVersion\", \"uOffset\", \"uCount\", \"uDestWidth\", \"uSrcWidth\"],\r\n samplers: [\"sogMeansLTex\", \"sogMeansUTex\", \"sogScalesTex\", \"sogQuatsTex\", \"sogSh0Tex\", \"sogCodebookTex\"],\r\n shaderLanguage: this._shaderLanguage,\r\n }\r\n );\r\n material.backFaceCulling = false;\r\n material.disableDepthWrite = true;\r\n return material;\r\n }\r\n\r\n private _applyPack(pack: ISogTexturePack): void {\r\n const material = this._material;\r\n const srcWidth = (pack.meansTextureL as Texture).getSize().width;\r\n\r\n material.setTexture(\"sogMeansLTex\", pack.meansTextureL);\r\n material.setTexture(\"sogMeansUTex\", pack.meansTextureU);\r\n material.setTexture(\"sogScalesTex\", pack.scalesTexture);\r\n material.setTexture(\"sogQuatsTex\", pack.quatsTexture);\r\n material.setTexture(\"sogSh0Tex\", pack.sh0Texture);\r\n // Codebook only used for v2; bind a harmless placeholder otherwise so the sampler is always set.\r\n material.setTexture(\"sogCodebookTex\", pack.codebookTexture ?? pack.sh0Texture);\r\n\r\n material.setVector3(\"sogMeansMin\", new Vector3(pack.meansMin[0], pack.meansMin[1], pack.meansMin[2]));\r\n material.setVector3(\"sogMeansMax\", new Vector3(pack.meansMax[0], pack.meansMax[1], pack.meansMax[2]));\r\n const sMin = pack.scalesMin ?? [0, 0, 0];\r\n const sMax = pack.scalesMax ?? [0, 0, 0];\r\n material.setVector3(\"sogScalesMin\", new Vector3(sMin[0], sMin[1], sMin[2]));\r\n material.setVector3(\"sogScalesMax\", new Vector3(sMax[0], sMax[1], sMax[2]));\r\n const c0Min = pack.sh0Min ?? [0, 0, 0, 0];\r\n const c0Max = pack.sh0Max ?? [0, 0, 0, 0];\r\n material.setVector4(\"sogSh0Min\", new Vector4(c0Min[0], c0Min[1], c0Min[2], c0Min[3]));\r\n material.setVector4(\"sogSh0Max\", new Vector4(c0Max[0], c0Max[1], c0Max[2], c0Max[3]));\r\n\r\n material.setInt(\"uVersion\", pack.version);\r\n // uOffset is bound at render time in decodeAsync (from the live _baseOffset).\r\n material.setInt(\"uCount\", pack.splatCount);\r\n material.setInt(\"uDestWidth\", this._textureSize);\r\n material.setInt(\"uSrcWidth\", srcWidth);\r\n }\r\n\r\n private _createShMaterial(): ShaderMaterial {\r\n const isWGSL = this._shaderLanguage === ShaderLanguage.WGSL;\r\n const material = new ShaderMaterial(\r\n GaussianSplattingWorkBufferShDecodeShaderName,\r\n this._scene,\r\n {\r\n vertexSource: isWGSL ? GaussianSplattingWorkBufferVertexShaderWGSL : GaussianSplattingWorkBufferVertexShaderGLSL,\r\n fragmentSource: isWGSL ? GaussianSplattingWorkBufferShDecodeFragmentShaderWGSL : GaussianSplattingWorkBufferShDecodeFragmentShaderGLSL,\r\n },\r\n {\r\n attributes: [\"position\"],\r\n uniforms: [\"sogShnMin\", \"sogShnMax\", \"uVersion\", \"uOffset\", \"uCount\", \"uDestWidth\", \"uSrcWidth\", \"uCoeffs\", \"uShTextureIndex\"],\r\n samplers: [\"sogShLabelsTex\", \"sogShCentroidsTex\", \"sogCodebookTex\"],\r\n shaderLanguage: this._shaderLanguage,\r\n }\r\n );\r\n material.backFaceCulling = false;\r\n material.disableDepthWrite = true;\r\n return material;\r\n }\r\n\r\n private _applyShPack(pack: ISogTexturePack): void {\r\n const material = this._shMaterial!;\r\n // A file may carry no higher-order SH (coarse LOD): fall back to sh0Texture as a harmless placeholder for the\r\n // label/centroid samplers and set uCoeffs=0 so the shader neutral-fills every coefficient (128 -> 0 lighting).\r\n const hasSh = !!pack.shLabelsTexture && !!pack.shCentroidsTexture;\r\n const labels = pack.shLabelsTexture ?? pack.sh0Texture;\r\n const centroids = pack.shCentroidsTexture ?? pack.sh0Texture;\r\n material.setTexture(\"sogShLabelsTex\", labels);\r\n material.setTexture(\"sogShCentroidsTex\", centroids);\r\n // Codebook only used for v2; bind a harmless placeholder otherwise so the sampler is always set.\r\n material.setTexture(\"sogCodebookTex\", pack.codebookTexture ?? labels);\r\n material.setFloat(\"sogShnMin\", pack.shnMin ?? 0);\r\n material.setFloat(\"sogShnMax\", pack.shnMax ?? 0);\r\n material.setInt(\"uVersion\", pack.version);\r\n // uOffset is bound at render time in decodeAsync (from the live _baseOffset).\r\n material.setInt(\"uCount\", pack.splatCount);\r\n material.setInt(\"uDestWidth\", this._textureSize);\r\n material.setInt(\"uSrcWidth\", (labels as Texture).getSize().width);\r\n // Higher-order coefficient count for THIS file (bands=3 -> 15). 0 when the file has no SH -> full neutral fill.\r\n material.setInt(\"uCoeffs\", hasSh ? pack.shCoeffCount : 0);\r\n }\r\n\r\n private _createRotMaterial(): ShaderMaterial {\r\n const isWGSL = this._shaderLanguage === ShaderLanguage.WGSL;\r\n const material = new ShaderMaterial(\r\n GaussianSplattingWorkBufferRotationDecodeShaderName,\r\n this._scene,\r\n {\r\n vertexSource: isWGSL ? GaussianSplattingWorkBufferVertexShaderWGSL : GaussianSplattingWorkBufferVertexShaderGLSL,\r\n fragmentSource: isWGSL ? GaussianSplattingWorkBufferRotationDecodeFragmentShaderWGSL : GaussianSplattingWorkBufferRotationDecodeFragmentShaderGLSL,\r\n },\r\n {\r\n attributes: [\"position\"],\r\n uniforms: [\"sogScalesMin\", \"sogScalesMax\", \"uVersion\", \"uOffset\", \"uCount\", \"uDestWidth\", \"uSrcWidth\"],\r\n samplers: [\"sogScalesTex\", \"sogQuatsTex\", \"sogCodebookTex\"],\r\n shaderLanguage: this._shaderLanguage,\r\n }\r\n );\r\n material.backFaceCulling = false;\r\n material.disableDepthWrite = true;\r\n return material;\r\n }\r\n\r\n private _applyRotPack(pack: ISogTexturePack): void {\r\n const material = this._rotMaterial!;\r\n const srcWidth = (pack.scalesTexture as Texture).getSize().width;\r\n material.setTexture(\"sogScalesTex\", pack.scalesTexture);\r\n material.setTexture(\"sogQuatsTex\", pack.quatsTexture);\r\n // Codebook only used for v2; bind a harmless placeholder otherwise so the sampler is always set.\r\n material.setTexture(\"sogCodebookTex\", pack.codebookTexture ?? pack.scalesTexture);\r\n const sMin = pack.scalesMin ?? [0, 0, 0];\r\n const sMax = pack.scalesMax ?? [0, 0, 0];\r\n material.setVector3(\"sogScalesMin\", new Vector3(sMin[0], sMin[1], sMin[2]));\r\n material.setVector3(\"sogScalesMax\", new Vector3(sMax[0], sMax[1], sMax[2]));\r\n material.setInt(\"uVersion\", pack.version);\r\n // uOffset is bound at render time in decodeAsync (from the live _baseOffset).\r\n material.setInt(\"uCount\", pack.splatCount);\r\n material.setInt(\"uDestWidth\", this._textureSize);\r\n material.setInt(\"uSrcWidth\", srcWidth);\r\n }\r\n}\r\n"]}
|
|
@@ -23,6 +23,41 @@ export declare const GaussianSplattingWorkBufferVertexShaderWGSL = "\nattribute
|
|
|
23
23
|
* Fragment shader (WGSL/WebGPU) — same decode as the GLSL variant, writing 4 MRT attachments.
|
|
24
24
|
*/
|
|
25
25
|
export declare const GaussianSplattingWorkBufferFragmentShaderWGSL = "\nvar sogMeansLTexSampler : sampler;\nvar sogMeansLTex : texture_2d<f32>;\nvar sogMeansUTexSampler : sampler;\nvar sogMeansUTex : texture_2d<f32>;\nvar sogScalesTexSampler : sampler;\nvar sogScalesTex : texture_2d<f32>;\nvar sogQuatsTexSampler : sampler;\nvar sogQuatsTex : texture_2d<f32>;\nvar sogSh0TexSampler : sampler;\nvar sogSh0Tex : texture_2d<f32>;\nvar sogCodebookTexSampler : sampler;\nvar sogCodebookTex : texture_2d<f32>;\n\nuniform sogMeansMin : vec3<f32>;\nuniform sogMeansMax : vec3<f32>;\nuniform sogScalesMin : vec3<f32>;\nuniform sogScalesMax : vec3<f32>;\nuniform sogSh0Min : vec4<f32>;\nuniform sogSh0Max : vec4<f32>;\nuniform uVersion : i32;\nuniform uOffset : i32;\nuniform uCount : i32;\nuniform uDestWidth : i32;\nuniform uSrcWidth : i32;\n\n@fragment\nfn main(input : FragmentInputs) -> FragmentOutputs {\n let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\n let global : i32 = p.y * uniforms.uDestWidth + p.x;\n if (global < uniforms.uOffset || global >= uniforms.uOffset + uniforms.uCount) {\n discard;\n }\n let k : i32 = global - uniforms.uOffset;\n let src : vec2<i32> = vec2<i32>(k - (k / uniforms.uSrcWidth) * uniforms.uSrcWidth, k / uniforms.uSrcWidth);\n\n let mL : vec3<f32> = textureLoad(sogMeansLTex, src, 0).xyz;\n let mU : vec3<f32> = textureLoad(sogMeansUTex, src, 0).xyz;\n let sRaw : vec3<f32> = textureLoad(sogScalesTex, src, 0).xyz;\n let qRaw : vec4<f32> = textureLoad(sogQuatsTex, src, 0);\n let c0 : vec4<f32> = textureLoad(sogSh0Tex, src, 0);\n\n let q16 : vec3<f32> = (mU * 256.0 + mL) * (255.0 / 65535.0);\n let nPos : vec3<f32> = mix(uniforms.sogMeansMin, uniforms.sogMeansMax, q16);\n let center : vec3<f32> = sign(nPos) * (exp(abs(nPos)) - vec3<f32>(1.0));\n\n var splatScale : vec3<f32>;\n if (uniforms.uVersion == 2) {\n let sIdx : vec3<f32> = floor(sRaw * 255.0 + 0.5);\n splatScale.x = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.x), 0), 0).r);\n splatScale.y = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.y), 0), 0).r);\n splatScale.z = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.z), 0), 0).r);\n } else {\n splatScale = exp(mix(uniforms.sogScalesMin, uniforms.sogScalesMax, sRaw));\n }\n\n let invSqrt2 : f32 = 0.70710678118;\n let qabc : vec3<f32> = (qRaw.xyz - vec3<f32>(0.5)) * 2.0 * invSqrt2;\n let qMode : i32 = i32(qRaw.w * 255.0 + 0.5) - 252;\n let qd : f32 = sqrt(max(0.0, 1.0 - dot(qabc, qabc)));\n var quat : vec4<f32>;\n if (qMode == 0) {\n quat = vec4<f32>(qd, qabc.x, qabc.y, qabc.z);\n } else if (qMode == 1) {\n quat = vec4<f32>(qabc.x, qd, qabc.y, qabc.z);\n } else if (qMode == 2) {\n quat = vec4<f32>(qabc.x, qabc.y, qd, qabc.z);\n } else {\n quat = vec4<f32>(qabc.x, qabc.y, qabc.z, qd);\n }\n\n let qw : f32 = quat.x;\n let qx : f32 = quat.y;\n let qy : f32 = quat.z;\n let qz : f32 = quat.w;\n let R : mat3x3<f32> = mat3x3<f32>(\n 1.0 - 2.0 * (qy * qy + qz * qz), 2.0 * (qx * qy + qw * qz), 2.0 * (qx * qz - qw * qy),\n 2.0 * (qx * qy - qw * qz), 1.0 - 2.0 * (qx * qx + qz * qz), 2.0 * (qy * qz + qw * qx),\n 2.0 * (qx * qz + qw * qy), 2.0 * (qy * qz - qw * qx), 1.0 - 2.0 * (qx * qx + qy * qy)\n );\n let S2 : mat3x3<f32> = mat3x3<f32>(\n 4.0 * splatScale.x * splatScale.x, 0.0, 0.0,\n 0.0, 4.0 * splatScale.y * splatScale.y, 0.0,\n 0.0, 0.0, 4.0 * splatScale.z * splatScale.z\n );\n let Sigma : mat3x3<f32> = R * S2 * transpose(R);\n\n let SH_C0 : f32 = 0.28209479177387814;\n var colRgb : vec3<f32>;\n var colA : f32;\n if (uniforms.uVersion == 2) {\n var c3 : vec3<f32>;\n c3.x = textureLoad(sogCodebookTex, vec2<i32>(256 + i32(c0.x * 255.0 + 0.5), 0), 0).r;\n c3.y = textureLoad(sogCodebookTex, vec2<i32>(256 + i32(c0.y * 255.0 + 0.5), 0), 0).r;\n c3.z = textureLoad(sogCodebookTex, vec2<i32>(256 + i32(c0.z * 255.0 + 0.5), 0), 0).r;\n colRgb = vec3<f32>(0.5) + c3 * SH_C0;\n colA = c0.w;\n } else {\n let cLerp : vec4<f32> = mix(uniforms.sogSh0Min, uniforms.sogSh0Max, c0);\n colRgb = vec3<f32>(0.5) + cLerp.xyz * SH_C0;\n colA = 1.0 / (1.0 + exp(-cLerp.w));\n }\n\n fragmentOutputs.fragData0 = vec4<f32>(center, 1.0);\n fragmentOutputs.fragData1 = vec4<f32>(Sigma[0][0], Sigma[0][1], Sigma[0][2], Sigma[1][1]);\n fragmentOutputs.fragData2 = vec4<f32>(Sigma[1][2], Sigma[2][2], 0.0, 0.0);\n fragmentOutputs.fragData3 = vec4<f32>(colRgb, colA);\n}\n";
|
|
26
|
+
/**
|
|
27
|
+
* Shader name for the rotation/scale decode pass (the three half-float textures voxel-IBL shadowing consumes).
|
|
28
|
+
*/
|
|
29
|
+
export declare const GaussianSplattingWorkBufferRotationDecodeShaderName = "gsSogRotDecodeToWorkBuffer";
|
|
30
|
+
/**
|
|
31
|
+
* Rotation/scale decode fragment shader (GLSL/WebGL2). Reconstructs each splat's rotation matrix R and scale and
|
|
32
|
+
* writes the three half-float textures the voxel shader samples (rotationsATexture/B/Scale). The layout lets the
|
|
33
|
+
* voxel shader reconstruct the same R and scale, so streamed splats get the same ellipsoid the draw path renders:
|
|
34
|
+
* rotA = (R col0.xyz, R col1.x)
|
|
35
|
+
* rotB = (R col1.yz, R col2.xy)
|
|
36
|
+
* rotScale = (R col2.z, 2*scale.x, 2*scale.y, 2*scale.z)
|
|
37
|
+
*/
|
|
38
|
+
export declare const GaussianSplattingWorkBufferRotationDecodeFragmentShaderGLSL = "precision highp float;\nprecision highp int;\n\nuniform sampler2D sogScalesTex;\nuniform sampler2D sogQuatsTex;\nuniform sampler2D sogCodebookTex;\n\nuniform vec3 sogScalesMin;\nuniform vec3 sogScalesMax;\nuniform int uVersion;\nuniform int uOffset;\nuniform int uCount;\nuniform int uDestWidth;\nuniform int uSrcWidth;\n\nlayout(location = 0) out vec4 glFragData[3];\n\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n int global = p.y * uDestWidth + p.x;\n if (global < uOffset || global >= uOffset + uCount) {\n discard;\n }\n int k = global - uOffset;\n ivec2 src = ivec2(k - (k / uSrcWidth) * uSrcWidth, k / uSrcWidth);\n\n vec3 sRaw = texelFetch(sogScalesTex, src, 0).xyz;\n vec4 qRaw = texelFetch(sogQuatsTex, src, 0);\n\n vec3 splatScale;\n if (uVersion == 2) {\n vec3 sIdx = floor(sRaw * 255.0 + 0.5);\n splatScale.x = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.x), 0), 0).r);\n splatScale.y = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.y), 0), 0).r);\n splatScale.z = exp(texelFetch(sogCodebookTex, ivec2(int(sIdx.z), 0), 0).r);\n } else {\n splatScale = exp(mix(sogScalesMin, sogScalesMax, sRaw));\n }\n\n const float invSqrt2 = 0.70710678118;\n vec3 qabc = (qRaw.xyz - vec3(0.5)) * 2.0 * invSqrt2;\n int qMode = int(qRaw.w * 255.0 + 0.5) - 252;\n float qd = sqrt(max(0.0, 1.0 - dot(qabc, qabc)));\n vec4 quat;\n if (qMode == 0) {\n quat = vec4(qd, qabc.x, qabc.y, qabc.z);\n } else if (qMode == 1) {\n quat = vec4(qabc.x, qd, qabc.y, qabc.z);\n } else if (qMode == 2) {\n quat = vec4(qabc.x, qabc.y, qd, qabc.z);\n } else {\n quat = vec4(qabc.x, qabc.y, qabc.z, qd);\n }\n\n float qw = quat.x, qx = quat.y, qy = quat.z, qz = quat.w;\n mat3 R = mat3(\n 1.0 - 2.0 * (qy * qy + qz * qz), 2.0 * (qx * qy + qw * qz), 2.0 * (qx * qz - qw * qy),\n 2.0 * (qx * qy - qw * qz), 1.0 - 2.0 * (qx * qx + qz * qz), 2.0 * (qy * qz + qw * qx),\n 2.0 * (qx * qz + qw * qy), 2.0 * (qy * qz - qw * qx), 1.0 - 2.0 * (qx * qx + qy * qy)\n );\n\n glFragData[0] = vec4(R[0], R[1].x);\n glFragData[1] = vec4(R[1].y, R[1].z, R[2].x, R[2].y);\n glFragData[2] = vec4(R[2].z, 2.0 * splatScale.x, 2.0 * splatScale.y, 2.0 * splatScale.z);\n}\n";
|
|
39
|
+
/**
|
|
40
|
+
* Rotation/scale decode fragment shader (WGSL/WebGPU) — same decode as the GLSL variant, writing 3 half-float MRT
|
|
41
|
+
* attachments.
|
|
42
|
+
*/
|
|
43
|
+
export declare const GaussianSplattingWorkBufferRotationDecodeFragmentShaderWGSL = "\nvar sogScalesTexSampler : sampler;\nvar sogScalesTex : texture_2d<f32>;\nvar sogQuatsTexSampler : sampler;\nvar sogQuatsTex : texture_2d<f32>;\nvar sogCodebookTexSampler : sampler;\nvar sogCodebookTex : texture_2d<f32>;\n\nuniform sogScalesMin : vec3<f32>;\nuniform sogScalesMax : vec3<f32>;\nuniform uVersion : i32;\nuniform uOffset : i32;\nuniform uCount : i32;\nuniform uDestWidth : i32;\nuniform uSrcWidth : i32;\n\n@fragment\nfn main(input : FragmentInputs) -> FragmentOutputs {\n let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\n let global : i32 = p.y * uniforms.uDestWidth + p.x;\n if (global < uniforms.uOffset || global >= uniforms.uOffset + uniforms.uCount) {\n discard;\n }\n let k : i32 = global - uniforms.uOffset;\n let src : vec2<i32> = vec2<i32>(k - (k / uniforms.uSrcWidth) * uniforms.uSrcWidth, k / uniforms.uSrcWidth);\n\n let sRaw : vec3<f32> = textureLoad(sogScalesTex, src, 0).xyz;\n let qRaw : vec4<f32> = textureLoad(sogQuatsTex, src, 0);\n\n var splatScale : vec3<f32>;\n if (uniforms.uVersion == 2) {\n let sIdx : vec3<f32> = floor(sRaw * 255.0 + 0.5);\n splatScale.x = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.x), 0), 0).r);\n splatScale.y = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.y), 0), 0).r);\n splatScale.z = exp(textureLoad(sogCodebookTex, vec2<i32>(i32(sIdx.z), 0), 0).r);\n } else {\n splatScale = exp(mix(uniforms.sogScalesMin, uniforms.sogScalesMax, sRaw));\n }\n\n let invSqrt2 : f32 = 0.70710678118;\n let qabc : vec3<f32> = (qRaw.xyz - vec3<f32>(0.5)) * 2.0 * invSqrt2;\n let qMode : i32 = i32(qRaw.w * 255.0 + 0.5) - 252;\n let qd : f32 = sqrt(max(0.0, 1.0 - dot(qabc, qabc)));\n var quat : vec4<f32>;\n if (qMode == 0) {\n quat = vec4<f32>(qd, qabc.x, qabc.y, qabc.z);\n } else if (qMode == 1) {\n quat = vec4<f32>(qabc.x, qd, qabc.y, qabc.z);\n } else if (qMode == 2) {\n quat = vec4<f32>(qabc.x, qabc.y, qd, qabc.z);\n } else {\n quat = vec4<f32>(qabc.x, qabc.y, qabc.z, qd);\n }\n\n let qw : f32 = quat.x;\n let qx : f32 = quat.y;\n let qy : f32 = quat.z;\n let qz : f32 = quat.w;\n let R : mat3x3<f32> = mat3x3<f32>(\n 1.0 - 2.0 * (qy * qy + qz * qz), 2.0 * (qx * qy + qw * qz), 2.0 * (qx * qz - qw * qy),\n 2.0 * (qx * qy - qw * qz), 1.0 - 2.0 * (qx * qx + qz * qz), 2.0 * (qy * qz + qw * qx),\n 2.0 * (qx * qz + qw * qy), 2.0 * (qy * qz - qw * qx), 1.0 - 2.0 * (qx * qx + qy * qy)\n );\n\n fragmentOutputs.fragData0 = vec4<f32>(R[0], R[1].x);\n fragmentOutputs.fragData1 = vec4<f32>(R[1].y, R[1].z, R[2].x, R[2].y);\n fragmentOutputs.fragData2 = vec4<f32>(R[2].z, 2.0 * splatScale.x, 2.0 * splatScale.y, 2.0 * splatScale.z);\n}\n";
|
|
44
|
+
/**
|
|
45
|
+
* Shader name for the SOG higher-order SH decode pass (bakes one packed-u32 SH texture per pass).
|
|
46
|
+
*/
|
|
47
|
+
export declare const GaussianSplattingWorkBufferShDecodeShaderName = "gsSogShDecodeToWorkBuffer";
|
|
48
|
+
/**
|
|
49
|
+
* SH decode fragment shader (GLSL/WebGL2). Decodes one SOG file's higher-order spherical-harmonics into one
|
|
50
|
+
* packed-u32 SH texture at the region offset, in the layout the draw path's `computeSHWeighted`/`decompose`
|
|
51
|
+
* expects (16 SH scalar-bytes per RGBA-u32 texel, little-endian; one texel per splat). Run once per SH texture
|
|
52
|
+
* (`uShTextureIndex` selects the 16 scalars written this pass). Coefficients this file lacks are written neutral
|
|
53
|
+
* (128 == 0 after `decompose`), so a lower-band file mixes correctly with higher-band ones.
|
|
54
|
+
*/
|
|
55
|
+
export declare const GaussianSplattingWorkBufferShDecodeFragmentShaderGLSL = "precision highp float;\nprecision highp int;\n\nuniform sampler2D sogShLabelsTex;\nuniform sampler2D sogShCentroidsTex;\nuniform sampler2D sogCodebookTex;\nuniform float sogShnMin;\nuniform float sogShnMax;\nuniform int uVersion;\nuniform int uOffset;\nuniform int uCount;\nuniform int uDestWidth;\nuniform int uSrcWidth;\nuniform int uCoeffs;\nuniform int uShTextureIndex;\n\nlayout(location = 0) out uvec4 outSh;\n\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n int global = p.y * uDestWidth + p.x;\n if (global < uOffset || global >= uOffset + uCount) {\n discard;\n }\n int kLocal = global - uOffset;\n\n // 16-bit label for this source splat (LSB in r, MSB in g), indexed over the labels texture's own width.\n ivec2 lsz = textureSize(sogShLabelsTex, 0);\n ivec2 lsrc = ivec2(kLocal - (kLocal / lsz.x) * lsz.x, kLocal / lsz.x);\n vec4 labelRaw = texelFetch(sogShLabelsTex, lsrc, 0);\n int n = int(labelRaw.r * 255.0 + 0.5) + int(labelRaw.g * 255.0 + 0.5) * 256;\n int u = (n - (n / 64) * 64) * uCoeffs;\n int v = n / 64;\n\n uint packed0 = 0u;\n uint packed1 = 0u;\n uint packed2 = 0u;\n uint packed3 = 0u;\n\n for (int b = 0; b < 16; b++) {\n int s = uShTextureIndex * 16 + b; // flat SH scalar index\n int kc = s / 3; // higher-order coefficient (0-based)\n int j = s - kc * 3; // channel (0=r,1=g,2=b)\n float byteVal = 128.0; // neutral (decompose(128) ~= 0)\n if (kc < uCoeffs) {\n vec4 centroidRaw = texelFetch(sogShCentroidsTex, ivec2(u + kc, v), 0);\n float ch = (j == 0) ? centroidRaw.r : ((j == 1) ? centroidRaw.g : centroidRaw.b);\n float coeff;\n if (uVersion == 2) {\n int cidx = int(ch * 255.0 + 0.5);\n coeff = texelFetch(sogCodebookTex, ivec2(512 + cidx, 0), 0).r;\n } else {\n coeff = mix(sogShnMin, sogShnMax, ch);\n }\n byteVal = clamp(coeff * 127.5 + 127.5, 0.0, 255.0);\n }\n uint bv = uint(byteVal + 0.5);\n int comp = b / 4;\n uint contrib = bv << uint((b - comp * 4) * 8);\n if (comp == 0) { packed0 |= contrib; }\n else if (comp == 1) { packed1 |= contrib; }\n else if (comp == 2) { packed2 |= contrib; }\n else { packed3 |= contrib; }\n }\n outSh = uvec4(packed0, packed1, packed2, packed3);\n}\n";
|
|
56
|
+
/**
|
|
57
|
+
* SH decode fragment shader (WGSL/WebGPU) — same as the GLSL variant. The integer output (`vec4<u32>` fragData)
|
|
58
|
+
* requires the WGSL processor's integer-fragData support.
|
|
59
|
+
*/
|
|
60
|
+
export declare const GaussianSplattingWorkBufferShDecodeFragmentShaderWGSL = "\nvar sogShLabelsTexSampler : sampler;\nvar sogShLabelsTex : texture_2d<f32>;\nvar sogShCentroidsTexSampler : sampler;\nvar sogShCentroidsTex : texture_2d<f32>;\nvar sogCodebookTexSampler : sampler;\nvar sogCodebookTex : texture_2d<f32>;\n\nuniform sogShnMin : f32;\nuniform sogShnMax : f32;\nuniform uVersion : i32;\nuniform uOffset : i32;\nuniform uCount : i32;\nuniform uDestWidth : i32;\nuniform uSrcWidth : i32;\nuniform uCoeffs : i32;\nuniform uShTextureIndex : i32;\n\n@fragment\nfn main(input : FragmentInputs) -> FragmentOutputs {\n let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\n let global : i32 = p.y * uniforms.uDestWidth + p.x;\n if (global < uniforms.uOffset || global >= uniforms.uOffset + uniforms.uCount) {\n discard;\n }\n let kLocal : i32 = global - uniforms.uOffset;\n\n let lsz : vec2<i32> = vec2<i32>(textureDimensions(sogShLabelsTex, 0));\n let lsrc : vec2<i32> = vec2<i32>(kLocal - (kLocal / lsz.x) * lsz.x, kLocal / lsz.x);\n let labelRaw : vec4<f32> = textureLoad(sogShLabelsTex, lsrc, 0);\n let n : i32 = i32(labelRaw.r * 255.0 + 0.5) + i32(labelRaw.g * 255.0 + 0.5) * 256;\n let u : i32 = (n - (n / 64) * 64) * uniforms.uCoeffs;\n let v : i32 = n / 64;\n\n var packed : array<u32, 4> = array<u32, 4>(0u, 0u, 0u, 0u);\n\n for (var b : i32 = 0; b < 16; b = b + 1) {\n let s : i32 = uniforms.uShTextureIndex * 16 + b;\n let kc : i32 = s / 3;\n let j : i32 = s - kc * 3;\n var byteVal : f32 = 128.0;\n if (kc < uniforms.uCoeffs) {\n let centroidRaw : vec4<f32> = textureLoad(sogShCentroidsTex, vec2<i32>(u + kc, v), 0);\n var ch : f32 = centroidRaw.b;\n if (j == 0) { ch = centroidRaw.r; } else if (j == 1) { ch = centroidRaw.g; }\n var coeff : f32;\n if (uniforms.uVersion == 2) {\n let cidx : i32 = i32(ch * 255.0 + 0.5);\n coeff = textureLoad(sogCodebookTex, vec2<i32>(512 + cidx, 0), 0).r;\n } else {\n coeff = mix(uniforms.sogShnMin, uniforms.sogShnMax, ch);\n }\n byteVal = clamp(coeff * 127.5 + 127.5, 0.0, 255.0);\n }\n let bv : u32 = u32(byteVal + 0.5);\n let comp : i32 = b / 4;\n packed[comp] = packed[comp] | (bv << u32((b - comp * 4) * 8));\n }\n fragmentOutputs.fragData0 = vec4<u32>(packed[0], packed[1], packed[2], packed[3]);\n}\n";
|
|
26
61
|
/**
|
|
27
62
|
* Shader name for the work-buffer relayout (defrag/compaction) copy pass.
|
|
28
63
|
*/
|
|
@@ -33,8 +68,41 @@ export declare const GaussianSplattingWorkBufferRelayoutShaderName = "gsWorkBuff
|
|
|
33
68
|
* texel reads its source splat index from `uMapTex` (R32F; a negative value marks a gap and is discarded so
|
|
34
69
|
* the cleared destination stays zero). In identity mode the source texel equals the destination texel.
|
|
35
70
|
*/
|
|
36
|
-
export declare const GaussianSplattingWorkBufferRelayoutFragmentShaderGLSL = "precision highp float;\nprecision highp int;\n\nuniform sampler2D uMapTex;\nuniform sampler2D uSrc0;\nuniform sampler2D uSrc1;\nuniform sampler2D uSrc2;\nuniform sampler2D uSrc3;\nuniform int uDstWidth;\nuniform int uSrcWidth;\nuniform int uUseMap;\n\nlayout(location = 0) out vec4 glFragData[4];\n\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n int srcIdx;\n if (uUseMap == 1) {\n float m = texelFetch(uMapTex, p, 0).r;\n if (m < 0.0) {\n discard;\n }\n srcIdx = int(m + 0.5);\n } else {\n srcIdx = p.y * uDstWidth + p.x;\n }\n ivec2 s = ivec2(srcIdx - (srcIdx / uSrcWidth) * uSrcWidth, srcIdx / uSrcWidth);\n glFragData[0] = texelFetch(uSrc0, s, 0);\n glFragData[1] = texelFetch(uSrc1, s, 0);\n glFragData[2] = texelFetch(uSrc2, s, 0);\n glFragData[3] = texelFetch(uSrc3, s, 0);\n}\n";
|
|
71
|
+
export declare const GaussianSplattingWorkBufferRelayoutFragmentShaderGLSL = "precision highp float;\nprecision highp int;\n\nuniform sampler2D uMapTex;\nuniform sampler2D uSrc0;\nuniform sampler2D uSrc1;\nuniform sampler2D uSrc2;\nuniform sampler2D uSrc3;\nuniform int uDstWidth;\nuniform int uSrcWidth;\nuniform int uUseMap;\n// Region-scoped relayout (hosted compound atlas), both default 0 (standalone square path unchanged):\n// uSrcBaseOffset \u2014 added to the map's (region-local) source index so pass 1 reads the correct GLOBAL atlas texel.\n// uDstBaseRow \u2014 subtracted from the atlas destination row so pass 2's identity copy reads the region-local temp.\nuniform int uSrcBaseOffset;\nuniform int uDstBaseRow;\n\nlayout(location = 0) out vec4 glFragData[4];\n\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n int srcIdx;\n if (uUseMap == 1) {\n float m = texelFetch(uMapTex, p, 0).r;\n if (m < 0.0) {\n discard;\n }\n srcIdx = uSrcBaseOffset + int(m + 0.5);\n } else {\n srcIdx = (p.y - uDstBaseRow) * uDstWidth + p.x;\n }\n ivec2 s = ivec2(srcIdx - (srcIdx / uSrcWidth) * uSrcWidth, srcIdx / uSrcWidth);\n glFragData[0] = texelFetch(uSrc0, s, 0);\n glFragData[1] = texelFetch(uSrc1, s, 0);\n glFragData[2] = texelFetch(uSrc2, s, 0);\n glFragData[3] = texelFetch(uSrc3, s, 0);\n}\n";
|
|
72
|
+
/**
|
|
73
|
+
* Shader name for the INTEGER (packed-u32 SH) relayout/backup copy pass. Same index/map/base math as the float
|
|
74
|
+
* relayout shader, but samples ONE integer SH source texture (`usampler2D`) and writes ONE integer attachment,
|
|
75
|
+
* so it moves one baked SH texture per pass (parallel to the four-out float copy).
|
|
76
|
+
*/
|
|
77
|
+
export declare const GaussianSplattingWorkBufferShCopyShaderName = "gsWorkBufferShCopy";
|
|
78
|
+
/**
|
|
79
|
+
* Integer SH relayout/backup copy fragment shader (GLSL/WebGL2). Copies one packed-u32 SH texture from a source
|
|
80
|
+
* layout to a destination layout, one output texel per draw. Map mode (`uUseMap == 1`) reads each destination
|
|
81
|
+
* texel's source splat index from `uMapTex` (R32F; negative = gap, discarded); identity mode copies texel-for-texel
|
|
82
|
+
* (region backup/restore). `uSrcBaseOffset`/`uDstBaseRow` scope the copy to a hosted region's atlas rows (default 0).
|
|
83
|
+
*/
|
|
84
|
+
export declare const GaussianSplattingWorkBufferShCopyFragmentShaderGLSL = "precision highp float;\nprecision highp int;\nprecision highp usampler2D;\n\nuniform sampler2D uMapTex;\nuniform usampler2D uSrcSh;\nuniform int uDstWidth;\nuniform int uSrcWidth;\nuniform int uUseMap;\nuniform int uSrcBaseOffset;\nuniform int uDstBaseRow;\n\nlayout(location = 0) out uvec4 outSh;\n\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n int srcIdx;\n if (uUseMap == 1) {\n float m = texelFetch(uMapTex, p, 0).r;\n if (m < 0.0) {\n discard;\n }\n srcIdx = uSrcBaseOffset + int(m + 0.5);\n } else {\n srcIdx = (p.y - uDstBaseRow) * uDstWidth + p.x;\n }\n ivec2 s = ivec2(srcIdx - (srcIdx / uSrcWidth) * uSrcWidth, srcIdx / uSrcWidth);\n outSh = texelFetch(uSrcSh, s, 0);\n}\n";
|
|
85
|
+
/**
|
|
86
|
+
* Integer SH relayout/backup copy fragment shader (WGSL/WebGPU) — same copy as the GLSL variant. The integer output
|
|
87
|
+
* (`vec4<u32>` fragData) requires the WGSL processor's integer-fragData support.
|
|
88
|
+
*/
|
|
89
|
+
export declare const GaussianSplattingWorkBufferShCopyFragmentShaderWGSL = "\nvar uMapTexSampler : sampler;\nvar uMapTex : texture_2d<f32>;\n// Integer source sampled via textureLoad only \u2014 NO paired sampler (a sampler on a Uint texture fails WebGPU\n// validation: \"None of the supported sample types (Uint)\"). Mirrors the draw shader's shTexture0 declaration.\nvar uSrcSh : texture_2d<u32>;\n\nuniform uDstWidth : i32;\nuniform uSrcWidth : i32;\nuniform uUseMap : i32;\nuniform uSrcBaseOffset : i32;\nuniform uDstBaseRow : i32;\n\n@fragment\nfn main(input : FragmentInputs) -> FragmentOutputs {\n let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\n var srcIdx : i32;\n if (uniforms.uUseMap == 1) {\n let m : f32 = textureLoad(uMapTex, p, 0).r;\n if (m < 0.0) {\n discard;\n }\n srcIdx = uniforms.uSrcBaseOffset + i32(m + 0.5);\n } else {\n srcIdx = (p.y - uniforms.uDstBaseRow) * uniforms.uDstWidth + p.x;\n }\n let s : vec2<i32> = vec2<i32>(srcIdx - (srcIdx / uniforms.uSrcWidth) * uniforms.uSrcWidth, srcIdx / uniforms.uSrcWidth);\n // Wrap in an explicit vec4<u32> so the WGSL processor emits an integer fragData location (its detection keys\n // off a literal vec4<u32>/vec4u in the assignment; a bare textureLoad(...) would default to vec4<f32>).\n fragmentOutputs.fragData0 = vec4<u32>(textureLoad(uSrcSh, s, 0));\n}\n";
|
|
90
|
+
/**
|
|
91
|
+
* Shader name for the rotation/scale relayout/backup copy pass. Same index/map/base math as the four-out float
|
|
92
|
+
* relayout shader, but moves the THREE half-float rotation/scale textures in one pass (their own separate atlas).
|
|
93
|
+
*/
|
|
94
|
+
export declare const GaussianSplattingWorkBufferRotCopyShaderName = "gsWorkBufferRotCopy";
|
|
95
|
+
/**
|
|
96
|
+
* Rotation/scale relayout/backup copy fragment shader (GLSL/WebGL2). Copies the three half-float rotation/scale
|
|
97
|
+
* textures from a source layout to a destination layout, one output texel per draw. Identical to the four-out
|
|
98
|
+
* float relayout shader but with three attachments (the rotation atlas has no fourth texture).
|
|
99
|
+
*/
|
|
100
|
+
export declare const GaussianSplattingWorkBufferRotCopyFragmentShaderGLSL = "precision highp float;\nprecision highp int;\n\nuniform sampler2D uMapTex;\nuniform sampler2D uSrc0;\nuniform sampler2D uSrc1;\nuniform sampler2D uSrc2;\nuniform int uDstWidth;\nuniform int uSrcWidth;\nuniform int uUseMap;\nuniform int uSrcBaseOffset;\nuniform int uDstBaseRow;\n\nlayout(location = 0) out vec4 glFragData[3];\n\nvoid main() {\n ivec2 p = ivec2(gl_FragCoord.xy);\n int srcIdx;\n if (uUseMap == 1) {\n float m = texelFetch(uMapTex, p, 0).r;\n if (m < 0.0) {\n discard;\n }\n srcIdx = uSrcBaseOffset + int(m + 0.5);\n } else {\n srcIdx = (p.y - uDstBaseRow) * uDstWidth + p.x;\n }\n ivec2 s = ivec2(srcIdx - (srcIdx / uSrcWidth) * uSrcWidth, srcIdx / uSrcWidth);\n glFragData[0] = texelFetch(uSrc0, s, 0);\n glFragData[1] = texelFetch(uSrc1, s, 0);\n glFragData[2] = texelFetch(uSrc2, s, 0);\n}\n";
|
|
101
|
+
/**
|
|
102
|
+
* Rotation/scale relayout/backup copy fragment shader (WGSL/WebGPU) — same copy as the GLSL variant, 3 attachments.
|
|
103
|
+
*/
|
|
104
|
+
export declare const GaussianSplattingWorkBufferRotCopyFragmentShaderWGSL = "\nvar uMapTexSampler : sampler;\nvar uMapTex : texture_2d<f32>;\nvar uSrc0Sampler : sampler;\nvar uSrc0 : texture_2d<f32>;\nvar uSrc1Sampler : sampler;\nvar uSrc1 : texture_2d<f32>;\nvar uSrc2Sampler : sampler;\nvar uSrc2 : texture_2d<f32>;\n\nuniform uDstWidth : i32;\nuniform uSrcWidth : i32;\nuniform uUseMap : i32;\nuniform uSrcBaseOffset : i32;\nuniform uDstBaseRow : i32;\n\n@fragment\nfn main(input : FragmentInputs) -> FragmentOutputs {\n let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\n var srcIdx : i32;\n if (uniforms.uUseMap == 1) {\n let m : f32 = textureLoad(uMapTex, p, 0).r;\n if (m < 0.0) {\n discard;\n }\n srcIdx = uniforms.uSrcBaseOffset + i32(m + 0.5);\n } else {\n srcIdx = (p.y - uniforms.uDstBaseRow) * uniforms.uDstWidth + p.x;\n }\n let s : vec2<i32> = vec2<i32>(srcIdx - (srcIdx / uniforms.uSrcWidth) * uniforms.uSrcWidth, srcIdx / uniforms.uSrcWidth);\n fragmentOutputs.fragData0 = textureLoad(uSrc0, s, 0);\n fragmentOutputs.fragData1 = textureLoad(uSrc1, s, 0);\n fragmentOutputs.fragData2 = textureLoad(uSrc2, s, 0);\n}\n";
|
|
37
105
|
/**
|
|
38
106
|
* Relayout copy fragment shader (WGSL/WebGPU) — same copy as the GLSL variant.
|
|
39
107
|
*/
|
|
40
|
-
export declare const GaussianSplattingWorkBufferRelayoutFragmentShaderWGSL = "\nvar uMapTexSampler : sampler;\nvar uMapTex : texture_2d<f32>;\nvar uSrc0Sampler : sampler;\nvar uSrc0 : texture_2d<f32>;\nvar uSrc1Sampler : sampler;\nvar uSrc1 : texture_2d<f32>;\nvar uSrc2Sampler : sampler;\nvar uSrc2 : texture_2d<f32>;\nvar uSrc3Sampler : sampler;\nvar uSrc3 : texture_2d<f32>;\n\nuniform uDstWidth : i32;\nuniform uSrcWidth : i32;\nuniform uUseMap : i32;\n\n@fragment\nfn main(input : FragmentInputs) -> FragmentOutputs {\n let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\n var srcIdx : i32;\n if (uniforms.uUseMap == 1) {\n let m : f32 = textureLoad(uMapTex, p, 0).r;\n if (m < 0.0) {\n discard;\n }\n srcIdx = i32(m + 0.5);\n } else {\n srcIdx = p.y * uniforms.uDstWidth + p.x;\n }\n let s : vec2<i32> = vec2<i32>(srcIdx - (srcIdx / uniforms.uSrcWidth) * uniforms.uSrcWidth, srcIdx / uniforms.uSrcWidth);\n fragmentOutputs.fragData0 = textureLoad(uSrc0, s, 0);\n fragmentOutputs.fragData1 = textureLoad(uSrc1, s, 0);\n fragmentOutputs.fragData2 = textureLoad(uSrc2, s, 0);\n fragmentOutputs.fragData3 = textureLoad(uSrc3, s, 0);\n}\n";
|
|
108
|
+
export declare const GaussianSplattingWorkBufferRelayoutFragmentShaderWGSL = "\nvar uMapTexSampler : sampler;\nvar uMapTex : texture_2d<f32>;\nvar uSrc0Sampler : sampler;\nvar uSrc0 : texture_2d<f32>;\nvar uSrc1Sampler : sampler;\nvar uSrc1 : texture_2d<f32>;\nvar uSrc2Sampler : sampler;\nvar uSrc2 : texture_2d<f32>;\nvar uSrc3Sampler : sampler;\nvar uSrc3 : texture_2d<f32>;\n\nuniform uDstWidth : i32;\nuniform uSrcWidth : i32;\nuniform uUseMap : i32;\n// Region-scoped relayout (hosted compound atlas), both default 0 (standalone square path unchanged).\nuniform uSrcBaseOffset : i32;\nuniform uDstBaseRow : i32;\n\n@fragment\nfn main(input : FragmentInputs) -> FragmentOutputs {\n let p : vec2<i32> = vec2<i32>(i32(fragmentInputs.position.x), i32(fragmentInputs.position.y));\n var srcIdx : i32;\n if (uniforms.uUseMap == 1) {\n let m : f32 = textureLoad(uMapTex, p, 0).r;\n if (m < 0.0) {\n discard;\n }\n srcIdx = uniforms.uSrcBaseOffset + i32(m + 0.5);\n } else {\n srcIdx = (p.y - uniforms.uDstBaseRow) * uniforms.uDstWidth + p.x;\n }\n let s : vec2<i32> = vec2<i32>(srcIdx - (srcIdx / uniforms.uSrcWidth) * uniforms.uSrcWidth, srcIdx / uniforms.uSrcWidth);\n fragmentOutputs.fragData0 = textureLoad(uSrc0, s, 0);\n fragmentOutputs.fragData1 = textureLoad(uSrc1, s, 0);\n fragmentOutputs.fragData2 = textureLoad(uSrc2, s, 0);\n fragmentOutputs.fragData3 = textureLoad(uSrc3, s, 0);\n}\n";
|