playcanvas
Version:
Open-source WebGL/WebGPU 3D engine for the web
226 lines (225 loc) • 9.51 kB
TypeScript
/**
* Represents a snapshot of gsplat state for rendering. This class captures all necessary data
* at a point in time and should not hold references back to the source placement. All required
* data should be copied or referenced, allowing placement to be modified without affecting the info.
*
* @ignore
*/
export class GSplatInfo {
/**
* Create a new GSplatInfo.
*
* @param {GraphicsDevice} device - The graphics device.
* @param {GSplatResourceBase} resource - The splat resource.
* @param {GSplatPlacement} placement - The placement of the splat.
* @param {Function|null} [consumeRenderDirty] - Callback to consume render dirty flag.
* @param {GSplatOctreeNode[]|null} [octreeNodes] - Octree nodes for bounds lookup.
* @param {NodeInfo[]|null} [nodeInfos] - Per-node info array from octree instance.
*/
constructor(device: GraphicsDevice, resource: GSplatResourceBase, placement: GSplatPlacement, consumeRenderDirty?: Function | null, octreeNodes?: GSplatOctreeNode[] | null, nodeInfos?: NodeInfo[] | null);
/** @type {GraphicsDevice} */
device: GraphicsDevice;
/** @type {GSplatResourceBase} */
resource: GSplatResourceBase;
/** @type {GraphNode} */
node: GraphNode;
/** @type {number} */
lodIndex: number;
/**
* Unique identifier from the placement, used for picking.
*
* @type {number}
*/
placementId: number;
/**
* Unique allocation identifier for persistent work buffer allocation tracking.
* Copied from the source placement.
*
* @type {number}
*/
allocId: number;
/**
* Identifies the bounds group this splat belongs to. All file placements from the same
* octree instance share the parent placement's allocId. Non-octree placements use their
* own allocId. Used to deduplicate bounds and transform texture entries.
*
* @type {number}
*/
parentPlacementId: number;
/** @type {number} */
numSplats: number;
/** @type {number} */
activeSplats: number;
/**
* Array of intervals for remapping of indices, each two consecutive numbers represent
* start and end of a range of splats.
*
* @type {number[]}
*/
intervals: number[];
/**
* Per-interval pixel offsets in the work buffer. For non-octree splats this has one entry.
* For octree splats each entry corresponds to one interval in this.intervals.
*
* @type {number[]}
*/
intervalOffsets: number[];
/**
* Per-interval allocation IDs for persistent tracking. Parallel to intervals: for octree
* splats each entry is the NodeInfo.allocId for that interval's node; for non-octree
* splats this has one entry equal to this.allocId.
*
* @type {number[]}
*/
intervalAllocIds: number[];
/**
* Per-interval octree node indices. Parallel to intervals: for octree splats each entry
* is the nodeIndex for that interval. Empty for non-octree splats.
*
* @type {number[]}
*/
intervalNodeIndices: number[];
/** @type {Mat4} */
previousWorldTransform: Mat4;
/** @type {BoundingBox} */
aabb: BoundingBox;
/**
* Small RGBA32U texture storing per-sub-draw data for instanced interval rendering.
* Each texel: R = rowStart | (numRows << 16), G = colStart, B = colEnd, A = sourceBase.
* Created lazily by {@link ensureSubDrawTexture} when needed for rendering.
*
* @type {Texture|null}
*/
subDrawTexture: Texture | null;
/**
* Number of sub-draw instances for instanced interval rendering.
*/
subDrawCount: number;
/**
* Number of bounding sphere entries this GSplatInfo contributes to the shared bounds texture.
*/
numBoundsEntries: number;
/**
* Base index into the shared bounds sphere texture for this GSplatInfo's entries.
*/
boundsBaseIndex: number;
/**
* Octree nodes array reference for writing bounding sphere data. Set when the GSplatInfo
* is created from an octree placement.
*
* @type {GSplatOctreeNode[]|null}
*/
octreeNodes: GSplatOctreeNode[] | null;
/**
* Per-node info array from the octree instance, providing allocId for each node.
* Indexed by nodeIndex. Null for non-octree splats.
*
* @type {NodeInfo[]|null}
*/
nodeInfos: NodeInfo[] | null;
/** @type {number} */
colorAccumulatedTranslation: number;
/**
* Per-instance shader parameters. Reference to the component's parameters Map.
*
* @type {Map<string, {scopeId: ScopeId, data: *}>|null}
*/
parameters: Map<string, {
scopeId: ScopeId;
data: any;
}> | null;
/**
* Function to get current work buffer modifier from source placement.
* Retrieved live (not snapshotted) to ensure shader configuration stays current.
*
* @type {(() => ({ code: string, hash: number }|null))|null}
*/
getWorkBufferModifier: (() => ({
code: string;
hash: number;
} | null)) | null;
/**
* Function to get current instance streams from source placement.
* Retrieved live (not snapshotted) to ensure streams are available after lazy creation.
*
* @type {(() => GSplatStreams|null)|null}
*/
getInstanceStreams: (() => GSplatStreams | null) | null;
/**
* Callback to consume render dirty flag from the source placement.
*
* @type {Function|null}
* @private
*/
private _consumeRenderDirty;
destroy(): void;
/**
* Sets per-interval pixel offsets for this splat. Sub-draw computation and GPU texture
* creation are deferred to {@link ensureSubDrawTexture} to avoid work for splats that
* may never be rendered (e.g. intermediate world states or unchanged splats).
*
* @param {number[]} intervalOffsets - Per-interval pixel offsets in the work buffer.
*/
setLayout(intervalOffsets: number[]): void;
/**
* Ensures the sub-draw texture exists, computing sub-draw data and creating the GPU texture
* on first call. Must be called outside a render pass (e.g. in the render pass update method)
* since WebGPU does not allow texture creation inside a render pass.
*
* @param {number} textureWidth - The work buffer texture width.
*/
ensureSubDrawTexture(textureWidth: number): void;
/**
* Updates the flattened intervals array from placement intervals. Intervals are sorted and
* stored as half-open pairs [start, end). Called once from the constructor; sub-draw data
* is built later in setLayout when the work buffer texture width is known.
*
* @param {Map<number, Vec2>} intervals - Map of node index to inclusive [x, y] intervals.
*/
updateIntervals(intervals: Map<number, Vec2>): void;
/**
* Splits an interval at row boundaries into sub-draws (partial first row, full middle rows,
* partial last row) and appends them to the sub-draw data array.
*
* @param {Uint32Array} subDrawData - The output array to append sub-draw entries to.
* @param {number} subDrawCount - Current number of sub-draws already in the array.
* @param {number} sourceBase - Source splat index for this interval.
* @param {number} size - Number of splats in this interval.
* @param {number} targetOffset - Pixel offset in the work buffer texture.
* @param {number} textureWidth - Width of the work buffer texture.
* @returns {number} Updated sub-draw count.
*/
appendSubDraws(subDrawData: Uint32Array, subDrawCount: number, sourceBase: number, size: number, targetOffset: number, textureWidth: number): number;
/**
* Builds the sub-draw data texture from the current intervals (or a synthetic full-range
* interval when none exist). Each interval is split at row boundaries of the work buffer
* texture to produce axis-aligned rectangles stored as a small RGBA32U texture.
*
* @param {number} textureWidth - The work buffer texture width.
*/
updateSubDraws(textureWidth: number): void;
update(): any;
/**
* Writes bounding sphere data for this GSplatInfo into a shared Float32Array.
* For octree resources, writes spheres for ALL nodes (indexed by nodeIndex) to keep
* boundsBaseIndex stable across LOD changes.
* For non-octree resources, computes a single sphere from the resource AABB.
*
* @param {Float32Array} data - The shared bounds sphere data array.
* @param {number} offset - The float offset to start writing at.
*/
writeBoundsSpheres(data: Float32Array, offset: number): void;
get hasSphericalHarmonics(): boolean;
}
import type { GraphicsDevice } from "../../platform/graphics/graphics-device.js";
import type { GSplatResourceBase } from "../gsplat/gsplat-resource-base.js";
import type { GraphNode } from '../graph-node.js';
import { Mat4 } from '../../core/math/mat4.js';
import { BoundingBox } from '../../core/shape/bounding-box.js';
import { Texture } from '../../platform/graphics/texture.js';
import type { GSplatOctreeNode } from './gsplat-octree-node.js';
import type { NodeInfo } from './gsplat-octree-instance.js';
import type { ScopeId } from '../../platform/graphics/scope-id.js';
import type { GSplatStreams } from "../gsplat/gsplat-streams.js";
import { Vec2 } from '../../core/math/vec2.js';
import type { GSplatPlacement } from "./gsplat-placement.js";