playcanvas
Version:
PlayCanvas WebGL game engine
96 lines (93 loc) • 3.77 kB
JavaScript
import { Debug } from '../../core/debug.js';
import { PIXELFORMAT_RGBA16F, PIXELFORMAT_R32U, ADDRESS_CLAMP_TO_EDGE, FILTER_NEAREST } from '../../platform/graphics/constants.js';
import { RenderTarget } from '../../platform/graphics/render-target.js';
import { Texture } from '../../platform/graphics/texture.js';
import { GSplatWorkBufferRenderPass } from './gsplat-work-buffer-render-pass.js';
let id = 0;
/**
* @import { GSplatInfo } from "./gsplat-info.js"
* @import { GraphicsDevice } from '../../platform/graphics/graphics-device.js'
* @import { GraphNode } from '../graph-node.js';
*/ /**
* @ignore
*/ class GSplatWorkBuffer {
constructor(device){
/** @type {number} */ this.id = id++;
this.device = device;
this.colorTexture = this.createTexture('splatColor', PIXELFORMAT_RGBA16F, 1, 1);
this.covATexture = this.createTexture('covA', PIXELFORMAT_RGBA16F, 1, 1);
this.covBTexture = this.createTexture('covB', PIXELFORMAT_RGBA16F, 1, 1);
this.centerTexture = this.createTexture('center', PIXELFORMAT_RGBA16F, 1, 1);
this.renderTarget = new RenderTarget({
name: `GsplatWorkBuffer-MRT-${this.id}`,
colorBuffers: [
this.colorTexture,
this.centerTexture,
this.covATexture,
this.covBTexture
],
depth: false,
flipY: true
});
this.orderTexture = this.createTexture('SplatGlobalOrder', PIXELFORMAT_R32U, 1, 1);
// Create the optimized render pass for batched splat rendering
this.renderPass = new GSplatWorkBufferRenderPass(device);
this.renderPass.init(this.renderTarget);
}
destroy() {
this.renderPass?.destroy();
this.colorTexture?.destroy();
this.covATexture?.destroy();
this.covBTexture?.destroy();
this.centerTexture?.destroy();
this.orderTexture?.destroy();
this.renderTarget?.destroy();
}
get textureSize() {
return this.orderTexture.width;
}
setOrderData(data) {
const len = this.orderTexture.width * this.orderTexture.height;
if (len !== data.length) {
Debug.error('setOrderData: data length mismatch, got:', data.length, 'expected:', len, `(${this.orderTexture.width}x${this.orderTexture.height})`);
}
// upload data to texture
this.orderTexture._levels[0] = data;
this.orderTexture.upload();
}
createTexture(name, format, w, h) {
return new Texture(this.device, {
name: name,
width: w,
height: h,
format: format,
cubemap: false,
mipmaps: false,
minFilter: FILTER_NEAREST,
magFilter: FILTER_NEAREST,
addressU: ADDRESS_CLAMP_TO_EDGE,
addressV: ADDRESS_CLAMP_TO_EDGE
});
}
/**
* @param {number} textureSize - The texture size to resize to.
*/ resize(textureSize) {
Debug.assert(textureSize);
this.renderTarget.resize(textureSize, textureSize);
this.orderTexture.resize(textureSize, textureSize);
}
/**
* Render given splats to the work buffer.
*
* @param {GSplatInfo[]} splats - The splats to render.
* @param {GraphNode} cameraNode - The camera node.
* @param {number[][]|undefined} colorsByLod - Array of RGB colors per LOD. Index by lodIndex; if a
* shorter array is provided, index 0 will be reused as fallback.
*/ render(splats, cameraNode, colorsByLod) {
// render splats using render pass
if (this.renderPass.update(splats, cameraNode, colorsByLod)) {
this.renderPass.render();
}
}
}
export { GSplatWorkBuffer };