playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
136 lines (135 loc) • 5.75 kB
JavaScript
var __defProp = Object.defineProperty;
var __defNormalProp = (obj, key, value) => key in obj ? __defProp(obj, key, { enumerable: true, configurable: true, writable: true, value }) : obj[key] = value;
var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "symbol" ? key + "" : key, value);
import {
CULLFACE_NONE,
PRIMITIVE_TRIANGLES
} from "../../platform/graphics/constants.js";
import { BLEND_PREMULTIPLIED } from "../constants.js";
import { ShaderMaterial } from "../materials/shader-material.js";
import { MeshInstance } from "../mesh-instance.js";
import { Mesh } from "../mesh.js";
class GSplatTileComposite {
/**
* @param {GraphicsDevice} device - The graphics device.
* @param {GraphNode} node - The graph node for the mesh instance.
* @param {Function} isVisibleFunc - Visibility callback: `(camera) => boolean`.
*/
constructor(device, node, isVisibleFunc) {
/** @type {GraphicsDevice} */
__publicField(this, "device");
/** @type {ShaderMaterial} */
__publicField(this, "_material");
/** @type {Mesh} */
__publicField(this, "_mesh");
/** @type {MeshInstance} */
__publicField(this, "_meshInstance");
/** @type {ShaderMaterial|null} */
__publicField(this, "_pickMaterial", null);
/** @type {MeshInstance|null} */
__publicField(this, "_pickMeshInstance", null);
/** @type {GraphNode} */
__publicField(this, "_node");
this.device = device;
this._node = node;
this._material = new ShaderMaterial({
uniqueName: "GSplatTileComposite",
vertexWGSL: '#include "gsplatTileCompositeVS"',
fragmentWGSL: '#include "gsplatTileCompositePS"'
});
this._material.blendType = BLEND_PREMULTIPLIED;
this._material.cull = CULLFACE_NONE;
this._material.depthWrite = false;
this._material.update();
this._mesh = new Mesh(device);
this._mesh.primitive[0].type = PRIMITIVE_TRIANGLES;
this._mesh.primitive[0].base = 0;
this._mesh.primitive[0].count = 0;
this._mesh.primitive[0].indexed = false;
this._meshInstance = new MeshInstance(this._mesh, this._material);
this._meshInstance.node = node;
this._meshInstance.instancingCount = 1;
this._meshInstance.isVisibleFunc = isVisibleFunc;
this._meshInstance.pick = false;
}
destroy() {
this._material.destroy();
this._mesh.destroy();
this._meshInstance.destroy();
this._pickMaterial?.destroy();
this._pickMeshInstance?.destroy();
}
get material() {
return this._material;
}
get meshInstance() {
return this._meshInstance;
}
/**
* Per-frame update for color rendering: binds the indirect draw slot and updates material
* parameters on the color mesh instance.
*
* @param {number} drawSlot - The indirect draw slot reserved for this frame.
* @param {Texture} outputTexture - The compute-rasterized splat texture.
* @param {StorageBuffer} rasterizeTileList - Buffer of non-empty tile indices.
* @param {number} numTilesX - Number of tiles horizontally.
* @param {number} screenWidth - Viewport width in pixels.
* @param {number} screenHeight - Viewport height in pixels.
*/
update(drawSlot, outputTexture, rasterizeTileList, numTilesX, screenWidth, screenHeight) {
this._meshInstance.setIndirect(null, drawSlot, 1);
this._material.setParameter("source", outputTexture);
this._material.setParameter("rasterizeTileList", rasterizeTileList);
this._material.setParameter("numTilesX", numTilesX);
this._material.setParameter("screenWidth", screenWidth);
this._material.setParameter("screenHeight", screenHeight);
}
/**
* Lazily creates the pick material and mesh instance, configures them with pick textures
* and tile parameters, and returns the pick mesh instance for the picker to render.
*
* @param {number} drawSlot - The indirect draw slot.
* @param {Texture} pickIdTexture - Compute-generated pick ID texture (r32uint).
* @param {Texture} pickDepthTexture - Compute-generated pick depth texture (rgba16float).
* @param {StorageBuffer} rasterizeTileList - Buffer of non-empty tile indices.
* @param {number} numTilesX - Number of tiles horizontally.
* @param {number} screenWidth - Viewport width in pixels.
* @param {number} screenHeight - Viewport height in pixels.
* @returns {MeshInstance} The configured pick mesh instance.
*/
prepareForPicking(drawSlot, pickIdTexture, pickDepthTexture, rasterizeTileList, numTilesX, screenWidth, screenHeight) {
if (!this._pickMaterial) {
this._pickMaterial = new ShaderMaterial({
uniqueName: "GSplatTileCompositePick",
vertexWGSL: '#include "gsplatTileCompositeVS"',
fragmentWGSL: '#include "gsplatTileCompositePS"'
});
this._pickMaterial.setDefine("PICK_MODE", true);
this._pickMaterial.cull = CULLFACE_NONE;
this._pickMaterial.depthWrite = false;
this._pickMaterial.update();
this._pickMeshInstance = new MeshInstance(this._mesh, this._pickMaterial);
this._pickMeshInstance.node = this._node;
this._pickMeshInstance.instancingCount = 1;
}
const pickMI = (
/** @type {MeshInstance} */
this._pickMeshInstance
);
const pickMat = (
/** @type {ShaderMaterial} */
this._pickMaterial
);
pickMI.setIndirect(null, drawSlot, 1);
pickMat.setParameter("pickIdTexture", pickIdTexture);
pickMat.setParameter("pickDepthTexture", pickDepthTexture);
pickMat.setParameter("rasterizeTileList", rasterizeTileList);
pickMat.setParameter("numTilesX", numTilesX);
pickMat.setParameter("screenWidth", screenWidth);
pickMat.setParameter("screenHeight", screenHeight);
return pickMI;
}
}
export {
GSplatTileComposite
};