UNPKG

playcanvas

Version:

Open-source WebGL/WebGPU 3D engine for the web

226 lines (225 loc) 9.51 kB
/** * 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";