import * as THREE from 'three/webgpu'; import type { SplatSHReadNodes } from './SplatSHResource.js'; import type { TSLFloatNode, TSLStorageNode, TSLUintNode, TSLUniformNode, TSLVec3Node, TSLVec4Node } from '../types/tsl.js'; export type GaussianSplatsLightingMode = 'unlit' | 'lit'; export type GaussianSplatsAlphaMode = 'straight' | 'premultiplied'; export interface GaussianSplatsColorPreset { exposure: number; contrast: number; saturation: number; vibrance: number; highlights: number; shadows: number; } export type GaussianSplatsCompositing = 'faithful' | 'linear' | 'display'; export interface GaussianSplatsMaterialOptions { lightingMode?: GaussianSplatsLightingMode | undefined; /** * Blend-space of the unlit color path. 'linear' (default) linearizes per splat and lets the * renderer encode after blending; 'display' composites the stored display-encoded colors — * the 3DGS training convention — and requires NoToneMapping + LinearSRGBColorSpace output. * 'faithful' is 'display' for a color-managed renderer: the owning GaussianSplats brackets the * draw (see SplatBlendBracket) and flips `displayBlend` per render; without a bracket it * renders as 'linear'. */ compositing?: GaussianSplatsCompositing | undefined; alphaClip?: number | undefined; fragmentAlphaClip?: number | undefined; minPixelRadius?: number | undefined; maxPixelRadius?: number | undefined; globalOpacity?: number | undefined; sigmaCoverage?: number | undefined; adaptiveSigma?: boolean | undefined; adaptiveSigmaThreshold?: number | undefined; srgbToLinear?: boolean | undefined; exposure?: number | undefined; contrast?: number | undefined; saturation?: number | undefined; vibrance?: number | undefined; highlights?: number | undefined; shadows?: number | undefined; shStrength?: number | undefined; shSpecularIntensity?: number | undefined; roughness?: number | undefined; metalness?: number | undefined; alphaBoost?: number | undefined; normalSmoothing?: number | undefined; alphaMode?: GaussianSplatsAlphaMode | undefined; debugMode?: GaussianSplatsDebugModeValue | undefined; tileCulling?: boolean | undefined; } export interface GaussianSplatsSourceReadNodes { readPosition(splatIndex: TSLUintNode): TSLVec3Node; readScale(splatIndex: TSLUintNode): TSLVec3Node; readRotation(splatIndex: TSLUintNode): TSLVec4Node; readColor(splatIndex: TSLUintNode): TSLVec4Node; } export interface GaussianSplatsMaterialBuffers { projected: TSLStorageNode<'vec4'>; sortKeys: TSLStorageNode<'uint'> | null; sortIndices: TSLStorageNode<'uint'> | null; sortPairs: TSLStorageNode<'uvec2'> | null; resolvedSH?: TSLStorageNode<'vec4'> | null | undefined; [name: string]: unknown; } export interface GaussianSplatsSourceResource { buildReadNodes(buffers: never): GaussianSplatsSourceReadNodes; } export interface GaussianSplatsSHResource { buildReadNodes(buffers: never): SplatSHReadNodes; } export interface GaussianSplatsMaterialUniforms { modelMatrix: TSLUniformNode<'mat4', THREE.Matrix4>; inverseModelMatrix: TSLUniformNode<'mat4', THREE.Matrix4>; viewMatrix: TSLUniformNode<'mat4', THREE.Matrix4>; inverseViewMatrix: TSLUniformNode<'mat4', THREE.Matrix4>; cameraPosition: TSLUniformNode<'vec3', THREE.Vector3>; screenSize: TSLUniformNode<'vec2', THREE.Vector2>; focalLength: TSLUniformNode<'vec2', THREE.Vector2>; splatCount: TSLUniformNode<'uint', number>; near: TSLUniformNode<'float', number>; far: TSLUniformNode<'float', number>; maxStdDev: TSLUniformNode<'float', number>; opacityAwareRadius: TSLUniformNode<'bool', boolean>; fragmentAlphaClip: TSLUniformNode<'float', number>; shStrength: TSLUniformNode<'float', number>; } /** * True when a material can use the F1 record fast path: standard unlit shading with no * custom nodes, debug modes, or tile culling — every per-splat vertex input then lives in * the projected records. Shared by the material's vertex selection and the mesh-side * resolver build so the two can never disagree. */ export declare function computeRecordColorEligibility(material: GaussianSplatsMaterial | null | undefined): boolean; export interface GaussianSplatsMaterialSource { maxSplats: number; sortCount: number; _sortKeyUsesSpatialHash?: (() => boolean) | undefined; sortAlgorithm: 'radix' | 'bitonic'; compaction: boolean; buffers: GaussianSplatsMaterialBuffers; uniforms: GaussianSplatsMaterialUniforms; _projectedRecordCount: number; _hasSurfaceRecord: boolean; _colorRecordIndex: number; invalidate?: (() => unknown) | undefined; _sourceResource: GaussianSplatsSourceResource; _enableSH: boolean; _maxDataSHDegree: number; _shDegree: number; _shResource?: GaussianSplatsSHResource | null | undefined; _shResolver?: { enabled: boolean; markDirty?: () => void; } | null | undefined; _recordResolverActive?: boolean | undefined; staticGroup?: { needsUpdate: boolean; } | null | undefined; } export type GaussianSplatPositionNode = (position: TSLVec3Node, splatIndex: TSLUintNode) => TSLVec3Node; export type GaussianSplatScaleNode = (scale: TSLVec3Node, position: TSLVec3Node, splatIndex: TSLUintNode) => TSLVec3Node; export type GaussianSplatRotationNode = (rotation: TSLVec4Node, position: TSLVec3Node, splatIndex: TSLUintNode) => TSLVec4Node; export type GaussianSplatColorNode = (color: TSLVec4Node, position: TSLVec3Node, splatIndex: TSLUintNode) => TSLVec3Node | TSLVec4Node; export type GaussianSplatSHCoefficientNode = (coefficient: TSLVec3Node, coefficientIndex: number, position: TSLVec3Node, splatIndex: TSLUintNode) => TSLVec3Node; export type GaussianSplatOpacityNode = (alpha: TSLFloatNode, position: TSLVec3Node, splatIndex: TSLUintNode) => TSLFloatNode; type GaussianFloatUniform = TSLUniformNode<'float', number>; /** * Debug visualization modes for Gaussian Splats. * @enum {number} */ export declare const GaussianSplatsDebugMode: { /** Normal rendering with colors and Gaussian falloff */ readonly NONE: 0; /** Show Gaussian alpha as grayscale */ readonly GAUSSIAN_ALPHA: 1; /** Show splat colors without Gaussian falloff */ readonly FLAT_COLOR: 2; /** Show conic (inverse covariance) values as RGB */ readonly CONIC: 3; /** Show power value (Gaussian exponent) */ readonly POWER: 4; /** Show UV coordinates */ readonly UV: 5; /** Show depth value */ readonly DEPTH: 6; /** Show color intensity/luminance (helps debug SH) */ readonly LUMINANCE: 7; /** Show color as hue (helps debug SH color shifts) */ readonly HUE: 8; /** Show base opacity (alpha channel) */ readonly OPACITY: 9; /** Show SH contribution magnitude (view-dependent color changes) */ readonly SH_CONTRIBUTION: 10; /** Show Morton ordering as rainbow gradient (smooth = good cache locality) */ readonly MORTON: 11; /** Show tile boundaries as colored grid overlay (for tile-based culling debug) */ readonly TILE: 12; }; export type GaussianSplatsDebugModeValue = typeof GaussianSplatsDebugMode[keyof typeof GaussianSplatsDebugMode]; /** * Preset configurations for common color looks. * @enum {Object} */ export declare const GaussianSplatsPreset: { /** Default neutral settings */ readonly DEFAULT: { readonly exposure: 1; readonly contrast: 1; readonly saturation: 1; readonly vibrance: 0; readonly highlights: 0; readonly shadows: 0; }; /** Cinematic film look with rich shadows */ readonly CINEMATIC: { readonly exposure: 0.95; readonly contrast: 1.1; readonly saturation: 0.95; readonly vibrance: 0.1; readonly highlights: -0.1; readonly shadows: 0.15; }; /** Vibrant, punchy colors */ readonly VIBRANT: { readonly exposure: 1.05; readonly contrast: 1.15; readonly saturation: 1.2; readonly vibrance: 0.2; readonly highlights: 0; readonly shadows: 0.1; }; /** Natural, realistic appearance */ readonly NATURAL: { readonly exposure: 1; readonly contrast: 1; readonly saturation: 1.05; readonly vibrance: 0.05; readonly highlights: 0; readonly shadows: 0.05; }; /** High contrast dramatic look */ readonly DRAMATIC: { readonly exposure: 0.9; readonly contrast: 1.25; readonly saturation: 0.9; readonly vibrance: 0.15; readonly highlights: -0.15; readonly shadows: 0.2; }; }; export type GaussianSplatsPresetName = keyof typeof GaussianSplatsPreset; /** * Custom NodeMaterial for rendering Gaussian Splats. * * This material handles: * - Billboard quad generation from sorted splat indices * - Ellipse computation from 2D covariance matrix * - Gaussian alpha falloff evaluation * - Proper alpha blending for transparency * * @class GaussianSplatsMaterial * @extends NodeMaterial * @short Material for rendering Gaussian Splats with anisotropic ellipses and alpha blending. * @category Materials * @tags WebGPU */ export declare class GaussianSplatsMaterial extends THREE.MeshPhysicalNodeMaterial { threeBlocksDisposeRenderUniforms: boolean; readonly isGaussianSplatsMaterial: true; _splats: GaussianSplatsMaterialSource; _lightingMode: GaussianSplatsLightingMode; _compositing: GaussianSplatsCompositing; _displayBlendUniform: GaussianFloatUniform; _alphaClipUniform: GaussianFloatUniform; _minPixelRadiusUniform: GaussianFloatUniform; _maxPixelRadiusUniform: GaussianFloatUniform; _globalOpacityUniform: GaussianFloatUniform; _sigmaCoverageUniform: GaussianFloatUniform; _adaptiveSigma: boolean; _adaptiveSigmaThresholdUniform: GaussianFloatUniform; _alphaMode: GaussianSplatsAlphaMode; _premultiplied: boolean; recordColorPathActive: boolean; _exposureUniform: GaussianFloatUniform; _contrastUniform: GaussianFloatUniform; _saturationUniform: GaussianFloatUniform; _vibranceUniform: GaussianFloatUniform; _highlightsUniform: GaussianFloatUniform; _shadowsUniform: GaussianFloatUniform; _shStrengthUniform: GaussianFloatUniform; _alphaBoostUniform: GaussianFloatUniform; _normalSmoothingUniform: GaussianFloatUniform; _shSpecularIntensityUniform: GaussianFloatUniform; _roughnessUniform: GaussianFloatUniform; _metalnessUniform: GaussianFloatUniform; _debugModeUniform: GaussianFloatUniform; _tileCulling: boolean; _tileCullingUniforms: unknown | null; _tileBufferNodes: unknown | null; customPositionNode: GaussianSplatPositionNode | null; customScaleNode: GaussianSplatScaleNode | null; customRotationNode: GaussianSplatRotationNode | null; customColorNode: GaussianSplatColorNode | null; customSHCoefficientNode: GaussianSplatSHCoefficientNode | null; customOpacityNode: GaussianSplatOpacityNode | null; opacityNode: TSLFloatNode | null; static get type(): 'GaussianSplatsMaterial'; /** * Create a Gaussian Splats material. * * @param {GaussianSplats} splats The GaussianSplats instance. * @param {Object} [options={}] Material options. * @param {string} [options.lightingMode='unlit'] Lighting mode: 'unlit' (DC+SH combined, no PBR) or 'lit' (DC as diffuse albedo, SH as specular color). * @param {number} [options.alphaClip=0.00196] Base opacity threshold - entire splats with opacity below this are culled (0 = disabled). * @param {number} [options.fragmentAlphaClip=0.00196] Fragment opacity threshold - discards nearly invisible Gaussian fringes before blending. * @param {number} [options.minPixelRadius=0.0] Minimum splat radius in pixels - splats smaller than this are culled. Raise only as an explicit performance tradeoff. * @param {number} [options.maxPixelRadius=512] Maximum splat radius in pixels - prevents huge splats from dominating. * @param {number} [options.globalOpacity=1.0] Global opacity multiplier for all splats (0.0 to 1.0). * @param {number} [options.sigmaCoverage=2.0] Sigma multiplier for splat quad size (2.0 = SuperSplat default). * @param {boolean} [options.adaptiveSigma=false] Crop sub-threshold splat quads to reduce overdraw. Explicit perf tradeoff (cropped edges can sit at visible alpha for opaque splats); prefer opacityAwareRadius. * @param {number} [options.adaptiveSigmaThreshold=8.0] Threshold in pixels for adaptive sigma - splats below this get reduced quads. * @param {boolean} [options.srgbToLinear=false] Convert splat colors from sRGB to linear color space. * @param {number} [options.exposure=1.0] Exposure/brightness multiplier (0.1 to 3.0). * @param {number} [options.contrast=1.0] Contrast adjustment (0.5 = flat, 1.0 = normal, 2.0 = high). * @param {number} [options.saturation=1.0] Color saturation (0 = grayscale, 1 = normal, 2 = oversaturated). * @param {number} [options.vibrance=0.0] Selective saturation for muted colors (-1 to 1). * @param {number} [options.highlights=0.0] Highlight adjustment (-1 to 1). * @param {number} [options.shadows=0.0] Shadow lift adjustment (-1 to 1). * @param {number} [options.shStrength=1.0] SH strength - controls view-dependent color intensity (0=flat, 1=normal, >1=exaggerated). * @param {number} [options.shSpecularIntensity=1.0] SH specular intensity for lit mode - scales SH contribution in specular path (0=no specular, 1=normal). * @param {number} [options.roughness=0.5] Surface roughness for lit mode PBR (0=mirror, 1=fully rough). * @param {number} [options.metalness=0.0] Surface metalness for lit mode PBR (0=dielectric, 1=metal). * @param {number} [options.alphaBoost=1.0] Alpha boost - increases opacity via power function (1=normal, >1=more opaque, reduces see-through). * @param {number} [options.normalSmoothing=0.85] Normal stabilization strength (0=raw ellipsoid normals, 1=fully confidence and edge weighted). * @param {'straight'|'premultiplied'} [options.alphaMode='straight'] Output and blending alpha contract. Straight is bit-exact to reference 3DGS compositing for canvas/sRGB targets; premultiplied (unlit only) multiplies the vertex-graded color in the renderer's blend space for transparent-target accumulation. */ constructor(splats: GaussianSplatsMaterialSource, options?: GaussianSplatsMaterialOptions); _applyAlphaMode(): void; /** * Premultiplied output is only expressible in unlit mode, where the custom outputNode can * premultiply the vertex-graded output. Lit mode falls back to straight-alpha blending. * @private */ get _effectivePremultiplied(): boolean; /** * Build TSL shader nodes. * @private */ _buildNodes(): void; /** * Select depth and shadow-lookup nodes for the active lighting mode. * * Lit mode with the third projected record evaluates the RaDe-GS planar depth per fragment — * splats lean smoothly through mesh geometry instead of popping at their center depth — and * samples received shadows at the reconstructed per-fragment surface point rather than the * flat splat center (which blocked one whole splat at a time). * @private */ _applyDepthAndShadowNodes(): void; /** * Build the opacity node with visibility and boundary masking. * Handles discards via opacity masks + alphaTest. * @private */ _buildOpacityNode(): void; /** * Move a stored (display-encoded) color into the space this draw blends in. * @private */ _blendSpaceColor(stored: TSLVec3Node): TSLVec3Node; /** Blend-space contract this material was built with. */ get compositing(): GaussianSplatsCompositing; /** 'faithful' only: whether this render blends display-encoded colors (set by the owning mesh). */ get displayBlend(): boolean; set displayBlend(value: boolean); /** * Apply lighting mode to color/emissive nodes. * Color processing in linear space - tonemapping should be applied by renderer post-process. * @private */ _applyLightingMode(): void; /** * Get the current lighting mode. * @returns {string} The lighting mode ('unlit' or 'lit'). */ get lightingMode(): GaussianSplatsLightingMode; /** * Set the lighting mode. * - 'unlit': DC + SH combined as emissive (no PBR lighting, default) * - 'lit': DC as diffuse albedo (colorNode), SH as specular color (specularColorNode) * In lit mode, DC receives diffuse lights and envmap, while SH drives specular highlights. * @param {string} value - Lighting mode. */ set lightingMode(value: GaussianSplatsLightingMode); /** * Get the current alpha clip threshold. * @returns {number} The alpha threshold below which splats are discarded. */ get alphaClip(): number; /** * Set the alpha clip threshold for per-splat culling. * Splats with base opacity below this value are entirely discarded. * Higher values = fewer outlier splats but may lose detail. * Lower values = more detail but may show stray splats. * @param {number} value - Opacity threshold (0.0 to 1.0). */ set alphaClip(value: number); /** * Get the per-fragment opacity cutoff. * @returns {number} The alpha-test threshold. */ get fragmentAlphaClip(): number; /** * Set the per-fragment opacity cutoff used to remove nearly invisible fringes. * @param {number} value - Alpha-test threshold (0-1). */ set fragmentAlphaClip(value: number); /** * Get the minimum pixel radius for splats. * @returns {number} The minimum splat radius in pixels. */ get minPixelRadius(): number; /** * Set the minimum pixel radius for splats. * Splats smaller than this are culled to remove noise. * @param {number} value - Minimum radius in pixels (default: 0.0). */ set minPixelRadius(value: number); /** * Get the maximum pixel radius for splats. * @returns {number} The maximum splat radius in pixels. */ get maxPixelRadius(): number; /** * Set the maximum pixel radius for splats. * Prevents extremely large splats from dominating the scene. * @param {number} value - Maximum radius in pixels (default: 512). */ set maxPixelRadius(value: number); /** * Get the global opacity multiplier. * @returns {number} The global opacity (0.0 to 1.0). */ get globalOpacity(): number; /** * Set the global opacity multiplier. * Scales all splat opacities uniformly. * @param {number} value - Opacity multiplier (0.0 = invisible, 1.0 = full opacity). */ set globalOpacity(value: number); /** * Get the sigma coverage value. * @returns {number} The sigma multiplier for quad size (2.0 = SuperSplat default). */ get sigmaCoverage(): number; /** * Set the sigma coverage for splat quad size. * Controls how many standard deviations the quad covers. * - 2.0: SuperSplat default (optimal visual quality) * - 3.0: Standard 3DGS (covers 99.7% of Gaussian, more overdraw) * @param {number} value - Sigma multiplier (typically 1.5 to 3.0). */ set sigmaCoverage(value: number); /** * Get whether adaptive sigma is enabled. * When enabled, small splats get reduced quad size to minimize overdraw. * @returns {boolean} Whether adaptive sigma is enabled. */ get adaptiveSigma(): boolean; /** * Set whether adaptive sigma is enabled. * When enabled, splats smaller than adaptiveSigmaThreshold get reduced quad size. * This reduces overdraw for scenes with many small splats. * @param {boolean} value - Whether to enable adaptive sigma. */ set adaptiveSigma(value: boolean); /** * Get the adaptive sigma threshold in pixels. * @returns {number} The threshold below which splats get reduced sigma. */ get adaptiveSigmaThreshold(): number; /** * Set the adaptive sigma threshold in pixels. * Splats with screen radius below this threshold get progressively smaller quads. * @param {number} value - Threshold in pixels (default: 8.0). */ set adaptiveSigmaThreshold(value: number); /** * Get the current exposure value. * @returns {number} The exposure multiplier. */ get exposure(): number; /** * Set the exposure (brightness multiplier). * @param {number} value - Exposure value (typically 0.1 to 3.0, default 1.0). */ set exposure(value: number); /** * Get the current contrast value. * @returns {number} The contrast multiplier. */ get contrast(): number; /** * Set the contrast adjustment. * @param {number} value - Contrast value (0.5 = flat, 1.0 = normal, 2.0 = high). */ set contrast(value: number); /** * Get the current saturation value. * @returns {number} The saturation multiplier. */ get saturation(): number; /** * Set the saturation adjustment. * @param {number} value - Saturation (0 = grayscale, 1 = normal, 2 = oversaturated). */ set saturation(value: number); /** * Get the current vibrance value. * @returns {number} The vibrance amount. */ get vibrance(): number; /** * Set the vibrance (selective saturation for muted colors). * @param {number} value - Vibrance amount (-1 to 1, 0 = no change). */ set vibrance(value: number); /** * Get the current highlights adjustment. * @returns {number} The highlights value. */ get highlights(): number; /** * Set the highlights adjustment. * @param {number} value - Highlights (-1 to 1, 0 = no change). */ set highlights(value: number); /** * Get the current shadows adjustment. * @returns {number} The shadows value. */ get shadows(): number; /** * Set the shadows adjustment (lift dark areas). * @param {number} value - Shadows (-1 to 1, 0 = no change). */ set shadows(value: number); /** * Get the SH strength multiplier. * @returns {number} The SH strength value. */ get shStrength(): number; /** * Set the SH strength - controls view-dependent color intensity. * @param {number} value - 0 = flat (no view-dependence), 1 = normal (default), >1 = exaggerated specular. */ set shStrength(value: number); /** * Get the alpha boost value. * @returns {number} The alpha boost multiplier. */ get alphaBoost(): number; /** * Set the alpha boost - increases splat opacity via power function. * Higher values make splats more opaque, reducing see-through artifacts. * @param {number} value - 1.0 = normal (default), >1 = more opaque (e.g., 2.0 for high SH scenes). */ set alphaBoost(value: number); /** * Get the normal stabilization strength. * @returns {number} The normal smoothing value (0-1). */ get normalSmoothing(): number; /** * Set how strongly lit splats filter ambiguous and transparent-edge normals. * @param {number} value - 0 = raw ellipsoid normals, 1 = fully stabilized normals. */ set normalSmoothing(value: number); /** * Get the SH specular intensity for lit mode. * @returns {number} The SH specular intensity value. */ get shSpecularIntensity(): number; /** * Set the SH specular intensity for lit mode. * Controls how much SH contributes to specular highlights. * @param {number} value - 0 = no SH specular, 1 = normal (default), >1 = exaggerated. */ set shSpecularIntensity(value: number); /** * Get the surface roughness for lit mode PBR. * @returns {number} The roughness value (0-1). */ get roughness(): number; /** * Set the surface roughness for lit mode PBR. * @param {number} value - 0 = mirror smooth, 1 = fully rough (default 0.5). */ set roughness(value: number); /** * Get the surface metalness for lit mode PBR. * @returns {number} The metalness value (0-1). */ get metalness(): number; /** * Set the surface metalness for lit mode PBR. * @param {number} value - 0 = dielectric (default), 1 = fully metallic. */ set metalness(value: number); /** * Get whether premultiplied-alpha output is enabled. * @returns {boolean} Whether output uses premultiplied-alpha encoding and blending. */ get premultiplied(): boolean; /** * Compatibility alias for alphaMode. * @param {boolean} value - Whether to premultiply colors. */ set premultiplied(value: boolean); /** @type {'straight'|'premultiplied'} */ get alphaMode(): GaussianSplatsAlphaMode; /** Set matching output encoding and blend factors. */ set alphaMode(value: GaussianSplatsAlphaMode); /** * Apply a preset configuration. * @param {string} presetName - Name of the preset (e.g., 'CINEMATIC', 'VIBRANT'). */ applyPreset(presetName: GaussianSplatsPresetName | Readonly): void; /** * Dispose of material resources. */ dispose(): void; } export {};