playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
140 lines (137 loc) • 5.73 kB
JavaScript
import gsplatOutputVS from '../shader-lib/wgsl/chunks/gsplat/vert/gsplatOutput.js';
import { shaderChunksWGSL } from '../shader-lib/wgsl/collections/shader-chunks-wgsl.js';
import { FisheyeProjection } from '../graphics/fisheye-projection.js';
/**
* @import { StorageBuffer } from '../../platform/graphics/storage-buffer.js'
* @import { ShaderMaterial } from '../materials/shader-material.js'
* @import { Layer } from '../layer.js'
* @import { GraphNode } from '../graph-node.js'
* @import { GraphicsDevice } from '../../platform/graphics/graphics-device.js'
* @import { GSplatWorkBuffer } from './gsplat-work-buffer.js'
* @import { FogParams } from '../fog-params.js'
*/ /**
* Base class for splat renderers. Holds common state shared by all renderer
* implementations (instanced-quad, compute-based, etc.). Derived classes
* implement the actual rendering strategy.
*
* @ignore
*/ class GSplatRenderer {
destroy() {}
/**
* Sets the render mode for this renderer.
*
* @param {number} renderMode - Bitmask flags controlling render passes (GSPLAT_FORWARD, GSPLAT_SHADOW, or both).
*/ setRenderMode(renderMode) {
this.renderMode = renderMode;
}
/**
* Returns the material used by this renderer, or null if not applicable.
*
* @type {ShaderMaterial|null}
*/ get material() {
return null;
}
/**
* Sets the data source providing format and texture access. The base implementation updates
* the workBuffer and notifies derived classes of the format change. Derived classes (e.g.
* the compute renderer) may override this to decouple from the work buffer entirely.
*
* The source object must provide:
* - `format` — a {@link GSplatFormat} describing the texture streams and shader read code.
* - `getTexture(name)` — a function returning a {@link Texture} for a given stream name.
*
* @param {object} source - The data source (typically a {@link GSplatWorkBuffer}).
*/ setDataSource(source) {
this.workBuffer = source;
this.onWorkBufferFormatChanged();
}
/**
* Called when the work buffer format has changed. Derived classes reconfigure
* their rendering resources (materials, pipelines, bindings, etc.).
*/ onWorkBufferFormatChanged() {}
/**
* Updates the renderer with the current splat count and texture size.
*
* @param {number} count - The number of visible splats.
* @param {number} textureSize - The work buffer texture size.
*/ update(count, textureSize) {}
/**
* Configures the renderer to use GPU-sorted data for rendering.
*
* @param {number} drawSlot - The indirect draw slot index.
* @param {StorageBuffer} sortedIds - Buffer containing sorted visible splat IDs.
* @param {StorageBuffer} numSplatsBuffer - Buffer containing the visible splat count.
* @param {number} textureSize - The work buffer texture size.
*/ setGpuSortedRendering(drawSlot, sortedIds, numSplatsBuffer, textureSize) {}
/**
* Switches the renderer to CPU-sorted rendering mode.
*/ setCpuSortedRendering() {}
/**
* Binds the current order data (texture or storage buffer) for CPU-sorted rendering.
*/ setOrderData() {}
/**
* Per-frame update for the renderer (material syncing, parameter updates).
*
* @param {object} params - The gsplat parameters.
* @param {number} [exposure] - Scene exposure value.
* @param {FogParams} [fogParams] - Fog parameters.
*/ frameUpdate(params, exposure, fogParams) {}
/**
* Updates the overdraw visualization mode.
*
* @param {object} params - The gsplat parameters.
*/ updateOverdrawMode(params) {}
/**
* Populates a cincludes map with tonemapping, gamma, decode and gsplatOutput
* shader chunks needed by compute tile-count shaders.
*
* @param {Map<string, string>} cincludes - The shader includes map to populate.
* @protected
*/ _createTonemapIncludes(cincludes) {
cincludes.set('gsplatOutputVS', gsplatOutputVS);
const chunkNames = [
'tonemappingPS',
'tonemappingNonePS',
'tonemappingLinearPS',
'tonemappingFilmicPS',
'tonemappingHejlPS',
'tonemappingAcesPS',
'tonemappingAces2PS',
'tonemappingNeutralPS',
'decodePS',
'gammaPS'
];
for (const name of chunkNames){
cincludes.set(name, shaderChunksWGSL[name]);
}
}
/**
* @param {GraphicsDevice} device - The graphics device.
* @param {GraphNode} node - The graph node.
* @param {GraphNode} cameraNode - The camera node.
* @param {Layer} layer - The layer to add mesh instances to.
* @param {GSplatWorkBuffer} workBuffer - The work buffer containing splat data.
*/ constructor(device, node, cameraNode, layer, workBuffer){
/**
* Cached work buffer format version for detecting extra stream changes.
*
* @type {number}
* @protected
*/ this._workBufferFormatVersion = -1;
/**
* Fisheye projection helper shared by all renderer paths.
* The manager calls update() during culling; renderers read the computed values
* when binding uniforms.
*
* @type {FisheyeProjection}
* @ignore
*/ this.fisheyeProj = new FisheyeProjection();
this.device = device;
this.node = node;
this.cameraNode = cameraNode;
this.layer = layer;
this.workBuffer = workBuffer;
this._workBufferFormatVersion = workBuffer?.format.extraStreamsVersion ?? -1;
}
}
export { GSplatRenderer };