UNPKG

playcanvas

Version:

PlayCanvas WebGL game engine

96 lines (93 loc) 3.77 kB
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 };