@animech-public/playcanvas
Version:
PlayCanvas WebGL game engine
135 lines (132 loc) • 4.94 kB
JavaScript
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 };