@babylonjs/core
Version:
Getting started? Play directly with the Babylon.js API using our [playground](https://playground.babylonjs.com/). It also contains a lot of samples to learn how to use it.
186 lines • 6.8 kB
JavaScript
import { __decorate } from "../../tslib.es6.js";
import { serialize, expandToProperty } from "../../Misc/decorators.js";
import { Color3 } from "../../Maths/math.color.js";
import { MaterialPluginBase } from "../materialPluginBase.js";
import { RegisterClass } from "../../Misc/typeStore.js";
import { GetGaussianSplattingMaxPartCount } from "./gaussianSplattingMaterial.js";
/**
* Plugin for GaussianSplattingMaterial that replaces per-splat colors with a
* solid color per compound-mesh part. Each part index maps to a single Color3
* value, which is looked up in a uniform array in the fragment shader.
*/
export class GaussianSplattingSolidColorMaterialPlugin extends MaterialPluginBase {
/** @internal */
_onIsEnabledChanged() {
// Intentional no-op: isEnabled is applied via a uniform in
// bindForSubMesh, so no dirty-marking or recompilation is needed.
}
/**
* Creates a new GaussianSplatSolidColorPlugin.
* @param material The GaussianSplattingMaterial to attach the plugin to.
* @param partColors A map from part index to the solid Color3 for that part.
* @param maxPartCount The maximum number of parts supported. This determines the size of the uniform array.
*/
constructor(material, partColors, maxPartCount) {
super(material, "GaussianSplatSolidColor", 200);
this._isEnabled = true;
/**
* Whether the solid-color override is active. When false, splats
* render with their original per-splat colors.
* Toggled via a shader uniform so no recompilation is required.
*/
this.isEnabled = true;
this._partColors = partColors;
this._maxPartCount = maxPartCount ?? GetGaussianSplattingMaxPartCount(material.getScene().getEngine());
this._enable(true);
}
/**
* Updates the part colors dynamically.
* @param partColors A map from part index to the solid Color3 for that part.
*/
updatePartColors(partColors) {
this._partColors = partColors;
}
// --- Plugin overrides ---
/**
* @returns the class name
*/
getClassName() {
return "GaussianSplattingSolidColorMaterialPlugin";
}
/**
* Indicates this plugin supports both GLSL and WGSL.
* @param shaderLanguage the shader language to check
* @returns true for GLSL and WGSL
*/
isCompatible(shaderLanguage) {
switch (shaderLanguage) {
case 0 /* ShaderLanguage.GLSL */:
case 1 /* ShaderLanguage.WGSL */:
return true;
default:
return false;
}
}
/**
* Always ready — no textures or async resources to wait on.
* @param _defines the defines
* @param _scene the scene
* @param _engine the engine
* @param _subMesh the submesh
* @returns true
*/
isReadyForSubMesh(_defines, _scene, _engine, _subMesh) {
return true;
}
/**
* Returns custom shader code fragments to inject solid-color rendering.
*
* @param shaderType "vertex" or "fragment"
* @param shaderLanguage the shader language to use (default: GLSL)
* @returns null or a map of injection point names to code strings
*/
getCustomCode(shaderType, shaderLanguage = 0 /* ShaderLanguage.GLSL */) {
const maxPartCount = this._maxPartCount;
if (shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
return this._getCustomCodeWGSL(shaderType, maxPartCount);
}
return this._getCustomCodeGLSL(shaderType, maxPartCount);
}
_getCustomCodeGLSL(shaderType, maxPartCount) {
if (shaderType === "vertex") {
return {
CUSTOM_VERTEX_DEFINITIONS: `varying float vPartIndex;`,
CUSTOM_VERTEX_UPDATE: `
#if IS_COMPOUND
vPartIndex = float(splat.partIndex);
#else
vPartIndex = 0.0;
#endif
`,
};
}
else if (shaderType === "fragment") {
return {
CUSTOM_FRAGMENT_DEFINITIONS: `
varying float vPartIndex;
uniform float solidColorEnabled;
uniform vec3 partColors[${maxPartCount}];
`,
CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR: `
if (solidColorEnabled > 0.5) {
int partIdx = int(vPartIndex + 0.5);
finalColor = vec4(partColors[partIdx], finalColor.w);
}
`,
};
}
return null;
}
_getCustomCodeWGSL(shaderType, maxPartCount) {
if (shaderType === "vertex") {
return {
CUSTOM_VERTEX_DEFINITIONS: `varying vPartIndex: f32;`,
CUSTOM_VERTEX_UPDATE: `
#if IS_COMPOUND
vertexOutputs.vPartIndex = f32(splat.partIndex);
#else
vertexOutputs.vPartIndex = 0.0;
#endif
`,
};
}
else if (shaderType === "fragment") {
return {
CUSTOM_FRAGMENT_DEFINITIONS: `
varying vPartIndex: f32;
uniform solidColorEnabled: f32;
uniform partColors: array<vec3f, ${maxPartCount}>;
`,
CUSTOM_FRAGMENT_BEFORE_FRAGCOLOR: `
if (uniforms.solidColorEnabled > 0.5) {
var partIdx: i32 = i32(fragmentInputs.vPartIndex + 0.5);
finalColor = vec4f(uniforms.partColors[partIdx], finalColor.w);
}
`,
};
}
return null;
}
/**
* Registers the plugin uniforms with the engine so that
* the Effect can resolve their locations.
* @returns uniform descriptions
*/
getUniforms() {
return {
externalUniforms: ["partColors", "solidColorEnabled"],
};
}
/**
* Binds the plugin uniforms each frame.
* @param _uniformBuffer the uniform buffer (unused — we bind directly on the effect)
* @param _scene the current scene
* @param _engine the current engine
* @param subMesh the submesh being rendered
*/
bindForSubMesh(_uniformBuffer, _scene, _engine, subMesh) {
const effect = subMesh.effect;
if (!effect) {
return;
}
effect.setFloat("solidColorEnabled", this._isEnabled ? 1.0 : 0.0);
const colorArray = [];
for (let i = 0; i < this._maxPartCount; i++) {
const color = this._partColors[i] ?? new Color3(0, 0, 0);
colorArray.push(color.r, color.g, color.b);
}
effect.setArray3("partColors", colorArray);
}
}
__decorate([
serialize(),
expandToProperty("_onIsEnabledChanged")
], GaussianSplattingSolidColorMaterialPlugin.prototype, "isEnabled", void 0);
RegisterClass("BABYLON.GaussianSplattingSolidColorMaterialPlugin", GaussianSplattingSolidColorMaterialPlugin);
//# sourceMappingURL=gaussianSplattingSolidColorMaterialPlugin.js.map