playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
282 lines (281 loc) • 11 kB
TypeScript
/**
* Configuration object specifying a data binding for GSplatProcessor.
* Defines where to read from (source) or write to (destination) including
* the resource, component for instance textures, and which streams to access.
*/
export type GSplatProcessorBinding = {
/**
* - Resource to read/write from.
*/
resource?: GSplatResourceBase;
/**
* - Component for instance textures. If provided,
* resource is automatically resolved from the component.
*/
component?: GSplatComponent;
/**
* - Names of streams to read/write. For destination, this is
* required. For source, if omitted, all format streams except destination streams are used
* automatically, providing getCenter/getColor/etc functions. Specify explicitly to limit
* which streams are bound.
*/
streams?: string[];
};
/**
* @import { GraphicsDevice } from '../../platform/graphics/graphics-device.js'
* @import { GSplatResourceBase } from '../../scene/gsplat/gsplat-resource-base.js'
* @import { GSplatStreamDescriptor } from '../../scene/gsplat/gsplat-format.js'
* @import { Texture as TextureType } from '../../platform/graphics/texture.js'
* @import { StorageBuffer } from '../../platform/graphics/storage-buffer.js'
* @import { GSplatComponent } from '../components/gsplat/component.js'
*/
/**
* @typedef {object} GSplatProcessorBinding
* Configuration object specifying a data binding for GSplatProcessor.
* Defines where to read from (source) or write to (destination) including
* the resource, component for instance textures, and which streams to access.
* @property {GSplatResourceBase} [resource] - Resource to read/write from.
* @property {GSplatComponent} [component] - Component for instance textures. If provided,
* resource is automatically resolved from the component.
* @property {string[]} [streams] - Names of streams to read/write. For destination, this is
* required. For source, if omitted, all format streams except destination streams are used
* automatically, providing getCenter/getColor/etc functions. Specify explicitly to limit
* which streams are bound.
*/
/**
* GSplatProcessor enables GPU-based processing of Gaussian Splat data using custom shader code.
* Gaussian Splats store per-splat attributes (position, rotation, scale, color, spherical harmonics)
* in texture streams. This processor reads from source streams and writes results to destination
* streams, enabling operations like painting, selection marking, or custom data transforms.
*
* Custom streams can be added to loaded gsplat resources via {@link GSplatFormat#addExtraStreams},
* or you can create fully procedural splat data using {@link GSplatContainer}.
*
* The source and destination can reference the same resource or component, as long as the read and
* write streams don't overlap (you cannot read and write the same stream in one pass).
*
* By default (when source streams are not specified), the processor provides access to the format's
* built-in getCenter(), getRotation(), getScale(), and getColor() functions for reading splat data.
* Note: getCenter() must be called first as it loads shared data used by the other functions.
*
* Custom uniforms can be passed to the shader via {@link setParameter}, including scalar values,
* vectors, and additional textures for effects like brush patterns or lookup tables.
*
* The following built-in uniforms are available in processing shaders:
* - `srcNumSplats` (uint) - Number of splats in source resource
* - `dstNumSplats` (uint) - Number of splats in destination resource
*
* @example
* // Create a processor that reads splat positions and writes to a customColor texture
* const processor = new pc.GSplatProcessor(
* app.graphicsDevice,
* { component: entity.gsplat }, // source: all streams auto-bound
* { component: entity.gsplat, streams: ['customColor'] }, // destination: customColor stream only
* {
* processGLSL: `
* uniform vec4 uPaintSphere;
* uniform vec4 uPaintColor;
*
* void process() {
* vec3 center = getCenter();
* float dist = distance(center, uPaintSphere.xyz);
* if (dist < uPaintSphere.w) {
* writeCustomColor(uPaintColor);
* } else {
* writeCustomColor(vec4(0.0));
* }
* }
* `,
* processWGSL: `
* uniform uPaintSphere: vec4f;
* uniform uPaintColor: vec4f;
*
* fn process() {
* let center = getCenter();
* let dist = distance(center, uniform.uPaintSphere.xyz);
* if (dist < uniform.uPaintSphere.w) {
* writeCustomColor(uniform.uPaintColor);
* } else {
* writeCustomColor(vec4f(0.0));
* }
* }
* `
* }
* );
*
* // Set uniforms and execute
* processor.setParameter('uPaintSphere', [0, 1, 0, 0.5]);
* processor.setParameter('uPaintColor', [1, 0, 0, 1]);
* processor.process();
*
* @category Graphics
*/
export class GSplatProcessor {
/**
* Creates a new GSplatProcessor instance.
*
* @param {GraphicsDevice} device - The graphics device.
* @param {GSplatProcessorBinding} source - Source configuration specifying where to read from.
* Can specify resource directly or component (for instance textures).
* @param {GSplatProcessorBinding} destination - Destination configuration specifying where to write.
* Can specify resource directly or component (for instance textures).
* @param {object} options - Shader options for the processing logic.
* @param {string} [options.processGLSL] - GLSL code at module scope. Must define a `void process()`
* function that implements the processing logic. Can include uniform declarations and helper functions.
* @param {string} [options.processWGSL] - WGSL code at module scope. Must define a `fn process()`
* function that implements the processing logic. Can include uniform declarations and helper functions.
*/
constructor(device: GraphicsDevice, source: GSplatProcessorBinding, destination: GSplatProcessorBinding, options: {
processGLSL?: string;
processWGSL?: string;
});
/**
* @type {GraphicsDevice}
* @private
*/
private _device;
/**
* Source binding configuration.
*
* @type {GSplatProcessorBinding}
* @private
*/
private _source;
/**
* Destination binding configuration.
*
* @type {GSplatProcessorBinding}
* @private
*/
private _destination;
/**
* Source resource (resolved from binding).
*
* @type {GSplatResourceBase}
* @private
*/
private _srcResource;
/**
* Destination resource (resolved from binding).
*
* @type {GSplatResourceBase}
* @private
*/
private _dstResource;
/**
* @type {GSplatStreamDescriptor[]}
* @private
*/
private _dstStreamDescriptors;
/**
* Set of destination stream names for quick lookup.
*
* @type {Set<string>}
* @private
*/
private _dstStreamNames;
/**
* Whether to use all input streams (no specific source streams requested).
*
* @type {boolean}
* @private
*/
private _useAllInputStreams;
/**
* Pre-resolved source textures to bind during process().
*
* @type {Array<{name: string, texture: TextureType}>}
* @private
*/
private _srcTextures;
/**
* @type {RenderTarget|null}
* @private
*/
private _renderTarget;
/**
* @type {QuadRender|null}
* @private
*/
private _quadRender;
/**
* @type {RenderPassShaderQuad|null}
* @private
*/
private _renderPass;
/**
* Shader parameters set by the user.
*
* @type {Map<string, { scopeId: object, data: number|number[]|ArrayBufferView|TextureType|StorageBuffer }>}
* @private
*/
private _parameters;
/**
* The blend state to use when processing. Allows accumulation of results
* (e.g., additive blending for painting). Defaults to no blending.
*
* @type {BlendState}
*/
blendState: BlendState;
/**
* Destroys this processor and releases all resources.
*/
destroy(): void;
/**
* Resolves a texture for the given stream name from a binding configuration.
*
* Resolution order:
* 1. Component instance texture (if component provided and stream is instance-level)
* 2. Resource texture
*
* @param {GSplatProcessorBinding} binding - The binding configuration.
* @param {string} name - The stream name.
* @param {GSplatResourceBase} resource - The resolved resource.
* @returns {TextureType|null} The resolved texture, or null if not found.
* @private
*/
private _resolveTexture;
/**
* Creates the MRT render target for destination streams.
*
* @private
*/
private _createRenderTarget;
/**
* Creates the shader and QuadRender for processing.
*
* @param {object} options - Shader options.
* @private
*/
private _createShader;
/**
* Sets a shader parameter for this processor. Parameters are applied during processing.
*
* @param {string} name - The name of the parameter (uniform name in shader).
* @param {number|number[]|ArrayBufferView|TextureType|StorageBuffer} data - The value for the parameter.
*/
setParameter(name: string, data: number | number[] | ArrayBufferView | TextureType | StorageBuffer): void;
/**
* Gets a shader parameter value previously set with {@link setParameter}.
*
* @param {string} name - The name of the parameter.
* @returns {number|number[]|ArrayBufferView|TextureType|StorageBuffer|undefined} The parameter value, or undefined if not set.
*/
getParameter(name: string): number | number[] | ArrayBufferView | TextureType | StorageBuffer | undefined;
/**
* Removes a shader parameter.
*
* @param {string} name - The name of the parameter to remove.
*/
deleteParameter(name: string): void;
/**
* Executes the processing, reading from source streams and writing to destination streams.
*/
process(): void;
}
import type { GSplatResourceBase } from '../../scene/gsplat/gsplat-resource-base.js';
import type { GSplatComponent } from '../components/gsplat/component.js';
import { BlendState } from '../../platform/graphics/blend-state.js';
import type { Texture as TextureType } from '../../platform/graphics/texture.js';
import type { StorageBuffer } from '../../platform/graphics/storage-buffer.js';
import type { GraphicsDevice } from '../../platform/graphics/graphics-device.js';