UNPKG

@animech-public/playcanvas

Version:
135 lines (132 loc) 4.94 kB
import { extends as _extends } from '../../../_virtual/_rollupPluginBabelHelpers.js'; import { Vec2 } from '../../core/math/vec2.js'; import { PIXELFORMAT_RGBA32U, PIXELFORMAT_RGBA32F, FILTER_NEAREST, ADDRESS_CLAMP_TO_EDGE } from '../../platform/graphics/constants.js'; import { Texture } from '../../platform/graphics/texture.js'; import { BoundingBox } from '../../core/shape/bounding-box.js'; import { createGSplatCompressedMaterial } from './gsplat-compressed-material.js'; const strideCopy = (target, targetStride, src, srcStride, numEntries) => { for (let i = 0; i < numEntries; ++i) { for (let j = 0; j < srcStride; ++j) { target[i * targetStride + j] = src[i * srcStride + j]; } } }; class GSplatCompressed { constructor(device, gsplatData) { this.device = void 0; this.numSplats = void 0; this.aabb = void 0; this.centers = void 0; this.packedTexture = void 0; this.chunkTexture = void 0; this.shTexture0 = void 0; this.shTexture1 = void 0; this.shTexture2 = void 0; const { chunkData, chunkSize, numChunks, numSplats, vertexData, shBands } = gsplatData; this.device = device; this.numSplats = numSplats; this.aabb = new BoundingBox(); gsplatData.calcAabb(this.aabb); this.centers = new Float32Array(numSplats * 3); gsplatData.getCenters(this.centers); this.packedTexture = this.createTexture('packedData', PIXELFORMAT_RGBA32U, this.evalTextureSize(numSplats), vertexData); const chunkTextureSize = this.evalTextureSize(numChunks); chunkTextureSize.x *= 5; this.chunkTexture = this.createTexture('chunkData', PIXELFORMAT_RGBA32F, chunkTextureSize); const chunkTextureData = this.chunkTexture.lock(); strideCopy(chunkTextureData, 20, chunkData, chunkSize, numChunks); if (chunkSize === 12) { for (let i = 0; i < numChunks; ++i) { chunkTextureData[i * 20 + 15] = 1; chunkTextureData[i * 20 + 16] = 1; chunkTextureData[i * 20 + 17] = 1; } } this.chunkTexture.unlock(); if (shBands > 0) { const { shData } = gsplatData; const size = this.evalTextureSize(numSplats); const texture0 = this.createTexture('shTexture0', PIXELFORMAT_RGBA32U, size); const texture1 = this.createTexture('shTexture1', PIXELFORMAT_RGBA32U, size); const texture2 = this.createTexture('shTexture2', PIXELFORMAT_RGBA32U, size); const data0 = texture0.lock(); const data1 = texture1.lock(); const data2 = texture2.lock(); const target0 = new Uint8Array(data0.buffer); const target1 = new Uint8Array(data1.buffer); const target2 = new Uint8Array(data2.buffer); const srcCoeffs = [3, 8, 15][shBands - 1]; for (let i = 0; i < numSplats; ++i) { for (let j = 0; j < 15; ++j) { target0[i * 16 + j] = j < srcCoeffs ? shData[(i * 3 + 0) * srcCoeffs + j] : 127; target1[i * 16 + j] = j < srcCoeffs ? shData[(i * 3 + 1) * srcCoeffs + j] : 127; target2[i * 16 + j] = j < srcCoeffs ? shData[(i * 3 + 2) * srcCoeffs + j] : 127; } } texture0.unlock(); texture1.unlock(); texture2.unlock(); this.shTexture0 = texture0; this.shTexture1 = texture1; this.shTexture2 = texture2; } else { this.shTexture0 = null; this.shTexture1 = null; this.shTexture2 = null; } } destroy() { var _this$packedTexture, _this$chunkTexture, _this$shTexture, _this$shTexture2, _this$shTexture3; (_this$packedTexture = this.packedTexture) == null || _this$packedTexture.destroy(); (_this$chunkTexture = this.chunkTexture) == null || _this$chunkTexture.destroy(); (_this$shTexture = this.shTexture0) == null || _this$shTexture.destroy(); (_this$shTexture2 = this.shTexture1) == null || _this$shTexture2.destroy(); (_this$shTexture3 = this.shTexture2) == null || _this$shTexture3.destroy(); } createMaterial(options) { const hasSH = this.shTexture0 !== null; const result = createGSplatCompressedMaterial(_extends({}, hasSH ? { defines: ['USE_SH'] } : {}, options)); result.setParameter('packedTexture', this.packedTexture); result.setParameter('chunkTexture', this.chunkTexture); result.setParameter('tex_params', new Float32Array([this.numSplats, this.packedTexture.width, this.chunkTexture.width / 5, 0])); if (hasSH) { result.setParameter('shTexture0', this.shTexture0); result.setParameter('shTexture1', this.shTexture1); result.setParameter('shTexture2', this.shTexture2); } return result; } evalTextureSize(count) { const width = Math.ceil(Math.sqrt(count)); const height = Math.ceil(count / width); return new Vec2(width, height); } createTexture(name, format, size, data) { return new Texture(this.device, _extends({ name: name, width: size.x, height: size.y, format: format, cubemap: false, mipmaps: false, minFilter: FILTER_NEAREST, magFilter: FILTER_NEAREST, addressU: ADDRESS_CLAMP_TO_EDGE, addressV: ADDRESS_CLAMP_TO_EDGE }, data ? { levels: [data] } : {})); } } export { GSplatCompressed };