@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.
729 lines (728 loc) • 29.4 kB
JavaScript
import { NodeMaterialBlockConnectionPointTypes } from "./Enums/nodeMaterialBlockConnectionPointTypes.js";
import { NodeMaterialBlockTargets } from "./Enums/nodeMaterialBlockTargets.js";
import { ShaderStore as EngineShaderStore } from "../../Engines/shaderStore.js";
import { Process } from "../../Engines/Processors/shaderProcessor.js";
import { WebGLShaderProcessor } from "../../Engines/WebGL/webGLShaderProcessors.js";
import { Logger } from "../../Misc/logger.js";
/**
* Class used to store node based material build state
*/
export class NodeMaterialBuildState {
constructor() {
/** Gets or sets a boolean indicating if the current state can emit uniform buffers */
this.supportUniformBuffers = false;
/**
* Gets the list of emitted attributes
*/
this.attributes = [];
/**
* Gets the list of emitted uniforms
*/
this.uniforms = [];
/**
* Gets the list of emitted constants
*/
this.constants = [];
/**
* Gets the list of emitted samplers
*/
this.samplers = [];
/**
* Gets the list of emitted functions
*/
this.functions = {};
/**
* Gets the list of emitted extensions
*/
this.extensions = {};
/**
* Gets the list of emitted prePass outputs - if using the prepass
*/
this.prePassOutput = {};
/**
* Gets the list of emitted counters
*/
this.counters = {};
/** @internal */
this._terminalBlocks = new Set();
/** @internal */
this._attributeDeclaration = "";
/** @internal */
this._uniformDeclaration = "";
/** @internal */
this._constantDeclaration = "";
/** @internal */
this._samplerDeclaration = "";
/** @internal */
this._varyingTransfer = "";
/** @internal */
this._injectAtEnd = "";
/** @internal */
this._injectAtTop = "";
/** @internal */
this._customEntryHeader = "";
/** @internal */
this._repeatableContentAnchorIndex = 0;
/** @internal */
this._builtCompilationString = "";
/**
* Gets the emitted compilation strings
*/
this.compilationString = "";
}
/**
* Gets the current shader language to use
*/
get shaderLanguage() {
return this.sharedData.nodeMaterial.shaderLanguage;
}
/** Gets suffix to add behind type casting */
get fSuffix() {
return this.shaderLanguage === 1 /* ShaderLanguage.WGSL */ ? "f" : "";
}
/**
* Returns the processed, compiled shader code
* @param defines defines to use for the shader processing
* @returns the raw shader code used by the engine
*/
async getProcessedShaderAsync(defines) {
if (!this._builtCompilationString) {
Logger.Error("getProcessedShaderAsync: Shader not built yet.");
return "";
}
const engine = this.sharedData.nodeMaterial.getScene().getEngine();
const options = {
defines: defines.split("\n"),
indexParameters: undefined,
isFragment: this.target === NodeMaterialBlockTargets.Fragment,
shouldUseHighPrecisionShader: engine._shouldUseHighPrecisionShader,
processor: engine._getShaderProcessor(this.shaderLanguage),
supportsUniformBuffers: engine.supportsUniformBuffers,
shadersRepository: EngineShaderStore.GetShadersRepository(this.shaderLanguage),
includesShadersStore: EngineShaderStore.GetIncludesShadersStore(this.shaderLanguage),
version: (engine.version * 100).toString(),
platformName: engine.shaderPlatformName,
processingContext: null,
isNDCHalfZRange: engine.isNDCHalfZRange,
useReverseDepthBuffer: engine.useReverseDepthBuffer,
};
// Export WebGL2 shaders with WebGL1 syntax for max compatibility
if (!engine.isWebGPU && engine.version > 1.0) {
options.processor = new WebGLShaderProcessor();
}
return await new Promise((resolve) => {
Process(this._builtCompilationString, options, (migratedCode, _) => {
resolve(migratedCode);
}, engine);
});
}
/**
* Finalize the compilation strings
* @param state defines the current compilation state
*/
finalize(state) {
const emitComments = state.sharedData.emitComments;
const isFragmentMode = this.target === NodeMaterialBlockTargets.Fragment;
let entryPointString = `\n${emitComments ? "//Entry point\n" : ""}`;
if (this._customEntryHeader) {
entryPointString += this._customEntryHeader;
}
else if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
if (isFragmentMode) {
entryPointString += ` \nfn main(input: FragmentInputs) -> FragmentOutputs {\n${this.sharedData.varyingInitializationsFragment}`;
}
else {
entryPointString += ` \nfn main(input: VertexInputs) -> FragmentInputs{\n`;
}
}
else {
entryPointString += `void main(void) {\n`;
}
this.compilationString = entryPointString + this.compilationString;
if (this._constantDeclaration) {
this.compilationString = `\n${emitComments ? "//Constants\n" : ""}${this._constantDeclaration}\n${this.compilationString}`;
}
let functionCode = "";
for (const functionName in this.functions) {
functionCode += this.functions[functionName] + `\n`;
}
this.compilationString = `\n${functionCode}\n${this.compilationString}`;
if (!isFragmentMode && this._varyingTransfer) {
this.compilationString = `${this.compilationString}\n${this._varyingTransfer}`;
}
if (this._injectAtEnd) {
this.compilationString = `${this.compilationString}\n${this._injectAtEnd}`;
}
this.compilationString = `${this.compilationString}\n}`;
if (this.sharedData.varyingDeclaration) {
this.compilationString = `\n${emitComments ? "//Varyings\n" : ""}${isFragmentMode ? this.sharedData.varyingDeclarationFragment : this.sharedData.varyingDeclaration}\n${this.compilationString}`;
}
if (this._samplerDeclaration) {
this.compilationString = `\n${emitComments ? "//Samplers\n" : ""}${this._samplerDeclaration}\n${this.compilationString}`;
}
if (this._uniformDeclaration) {
this.compilationString = `\n${emitComments ? "//Uniforms\n" : ""}${this._uniformDeclaration}\n${this.compilationString}`;
}
if (this._attributeDeclaration && !isFragmentMode) {
this.compilationString = `\n${emitComments ? "//Attributes\n" : ""}${this._attributeDeclaration}\n${this.compilationString}`;
}
if (this.shaderLanguage !== 1 /* ShaderLanguage.WGSL */) {
this.compilationString = "precision highp float;\n" + this.compilationString;
this.compilationString = "#if defined(WEBGL2) || defined(WEBGPU)\nprecision highp sampler2DArray;\n#endif\n" + this.compilationString;
if (isFragmentMode) {
this.compilationString =
"#if defined(PREPASS)\r\n#extension GL_EXT_draw_buffers : require\r\nlayout(location = 0) out highp vec4 glFragData[SCENE_MRT_COUNT];\r\nhighp vec4 gl_FragColor;\r\n#endif\r\n" +
this.compilationString;
}
for (const extensionName in this.extensions) {
const extension = this.extensions[extensionName];
this.compilationString = `\n${extension}\n${this.compilationString}`;
}
}
if (this._injectAtTop) {
this.compilationString = `${this._injectAtTop}\n${this.compilationString}`;
}
this._builtCompilationString = this.compilationString;
}
/** @internal */
get _repeatableContentAnchor() {
return `###___ANCHOR${this._repeatableContentAnchorIndex++}___###`;
}
/**
* @internal
*/
_getFreeVariableName(prefix) {
prefix = this.sharedData.formatConfig.formatVariablename(prefix);
if (this.sharedData.variableNames[prefix] === undefined) {
this.sharedData.variableNames[prefix] = 0;
// Check reserved words
if (prefix === "output" || prefix === "texture") {
return prefix + this.sharedData.variableNames[prefix];
}
return prefix;
}
else {
this.sharedData.variableNames[prefix]++;
}
return prefix + this.sharedData.variableNames[prefix];
}
/**
* @internal
*/
_getFreeDefineName(prefix) {
if (this.sharedData.defineNames[prefix] === undefined) {
this.sharedData.defineNames[prefix] = 0;
}
else {
this.sharedData.defineNames[prefix]++;
}
return prefix + this.sharedData.defineNames[prefix];
}
/**
* @internal
*/
_excludeVariableName(name) {
this.sharedData.variableNames[name] = 0;
}
/**
* @internal
*/
_emit2DSampler(name, define = "", force = false, annotation, unsignedSampler, precision) {
if (this.samplers.indexOf(name) < 0 || force) {
if (define) {
this._samplerDeclaration += `#if ${define}\n`;
}
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
const unsignedSamplerPrefix = unsignedSampler ? "u" : "f";
this._samplerDeclaration += `var ${name + `Sampler`}: sampler;\n`;
this._samplerDeclaration += `var ${name}: texture_2d<${unsignedSamplerPrefix}32>;\n`;
}
else {
const unsignedSamplerPrefix = unsignedSampler ? "u" : "";
const precisionDecl = precision ?? "";
this._samplerDeclaration += `uniform ${precisionDecl} ${unsignedSamplerPrefix}sampler2D ${name}; ${annotation ? annotation : ""}\n`;
}
if (define) {
this._samplerDeclaration += `#endif\n`;
}
if (!force) {
this.samplers.push(name);
}
}
}
/**
* @internal
*/
_emitCubeSampler(name, define = "", force = false) {
if (this.samplers.indexOf(name) < 0 || force) {
if (define) {
this._samplerDeclaration += `#if ${define}\n`;
}
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
this._samplerDeclaration += `var ${name + `Sampler`}: sampler;\n`;
this._samplerDeclaration += `var ${name}: texture_cube<f32>;\n`;
}
else {
this._samplerDeclaration += `uniform samplerCube ${name};\n`;
}
if (define) {
this._samplerDeclaration += `#endif\n`;
}
if (!force) {
this.samplers.push(name);
}
}
}
/**
* @internal
*/
_emit2DArraySampler(name) {
if (this.samplers.indexOf(name) < 0) {
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
this._samplerDeclaration += `var ${name + `Sampler`}: sampler;\n`;
this._samplerDeclaration += `var ${name}: texture_2d_array<f32>;\n`;
}
else {
this._samplerDeclaration += `uniform sampler2DArray ${name};\n`;
}
this.samplers.push(name);
}
}
/**
* @internal
*/
_getGLType(type) {
switch (type) {
case NodeMaterialBlockConnectionPointTypes.Float:
return "float";
case NodeMaterialBlockConnectionPointTypes.Int:
return "int";
case NodeMaterialBlockConnectionPointTypes.Vector2:
return "vec2";
case NodeMaterialBlockConnectionPointTypes.Color3:
case NodeMaterialBlockConnectionPointTypes.Vector3:
return "vec3";
case NodeMaterialBlockConnectionPointTypes.Color4:
case NodeMaterialBlockConnectionPointTypes.Vector4:
return "vec4";
case NodeMaterialBlockConnectionPointTypes.Matrix:
return "mat4";
}
return "";
}
/**
* @internal
*/
_getShaderType(type) {
const isWGSL = this.shaderLanguage === 1 /* ShaderLanguage.WGSL */;
switch (type) {
case NodeMaterialBlockConnectionPointTypes.Float:
return isWGSL ? "f32" : "float";
case NodeMaterialBlockConnectionPointTypes.Int:
return isWGSL ? "i32" : "int";
case NodeMaterialBlockConnectionPointTypes.Vector2:
return isWGSL ? "vec2f" : "vec2";
case NodeMaterialBlockConnectionPointTypes.Color3:
case NodeMaterialBlockConnectionPointTypes.Vector3:
return isWGSL ? "vec3f" : "vec3";
case NodeMaterialBlockConnectionPointTypes.Color4:
case NodeMaterialBlockConnectionPointTypes.Vector4:
return isWGSL ? "vec4f" : "vec4";
case NodeMaterialBlockConnectionPointTypes.Matrix:
return isWGSL ? "mat4x4f" : "mat4";
}
return "";
}
/**
* @internal
*/
_emitExtension(name, extension, define = "") {
if (this.extensions[name]) {
return;
}
if (define) {
extension = `#if ${define}\n${extension}\n#endif`;
}
this.extensions[name] = extension;
}
/**
* @internal
*/
_emitFunction(name, code, comments) {
if (this.functions[name]) {
return;
}
if (this.sharedData.emitComments) {
code = comments + `\n` + code;
}
this.functions[name] = code;
}
/**
* @internal
*/
_emitCodeFromInclude(includeName, comments, options) {
const store = EngineShaderStore.GetIncludesShadersStore(this.shaderLanguage);
if (options && options.repeatKey) {
return `#include<${includeName}>${options.substitutionVars ? "(" + options.substitutionVars + ")" : ""}[0..${options.repeatKey}]\n`;
}
let code = store[includeName] + "\n";
if (this.sharedData.emitComments) {
code = comments + `\n` + code;
}
if (!options) {
return code;
}
if (options.replaceStrings) {
for (let index = 0; index < options.replaceStrings.length; index++) {
const replaceString = options.replaceStrings[index];
code = code.replace(replaceString.search, replaceString.replace);
}
}
return code;
}
/**
* @internal
*/
_emitFunctionFromInclude(includeName, comments, options, storeKey = "") {
const key = includeName + storeKey;
if (this.functions[key]) {
return;
}
const store = EngineShaderStore.GetIncludesShadersStore(this.shaderLanguage);
if (!options || (!options.removeAttributes && !options.removeUniforms && !options.removeVaryings && !options.removeIfDef && !options.replaceStrings)) {
if (options && options.repeatKey) {
this.functions[key] = `#include<${includeName}>${options.substitutionVars ? "(" + options.substitutionVars + ")" : ""}[0..${options.repeatKey}]\n`;
}
else {
this.functions[key] = `#include<${includeName}>${options?.substitutionVars ? "(" + options?.substitutionVars + ")" : ""}\n`;
}
if (this.sharedData.emitComments) {
this.functions[key] = comments + `\n` + this.functions[key];
}
return;
}
this.functions[key] = store[includeName];
if (this.sharedData.emitComments) {
this.functions[key] = comments + `\n` + this.functions[key];
}
if (options.removeIfDef) {
this.functions[key] = this.functions[key].replace(/^\s*?#ifdef.+$/gm, "");
this.functions[key] = this.functions[key].replace(/^\s*?#endif.*$/gm, "");
this.functions[key] = this.functions[key].replace(/^\s*?#else.*$/gm, "");
this.functions[key] = this.functions[key].replace(/^\s*?#elif.*$/gm, "");
}
if (options.removeAttributes) {
this.functions[key] = this.functions[key].replace(/\s*?attribute .+?;/g, "\n");
}
if (options.removeUniforms) {
this.functions[key] = this.functions[key].replace(/\s*?uniform .*?;/g, "\n");
}
if (options.removeVaryings) {
this.functions[key] = this.functions[key].replace(/\s*?(varying|in) .+?;/g, "\n");
}
if (options.replaceStrings) {
for (let index = 0; index < options.replaceStrings.length; index++) {
const replaceString = options.replaceStrings[index];
this.functions[key] = this.functions[key].replace(replaceString.search, replaceString.replace);
}
}
}
/**
* @internal
*/
_registerTempVariable(name) {
if (this.sharedData.temps.indexOf(name) !== -1) {
return false;
}
this.sharedData.temps.push(name);
return true;
}
/**
* @internal
*/
_emitVaryingFromString(name, type, define = "", notDefine = false) {
if (this.sharedData.varyings.indexOf(name) !== -1) {
return false;
}
this.sharedData.varyings.push(name);
const shaderType = this._getShaderType(type);
const emitCode = (forFragment = false) => {
let code = "";
if (define) {
if (define.startsWith("defined(")) {
code += `#if ${define}\n`;
}
else {
code += `${notDefine ? "#ifndef" : "#ifdef"} ${define}\n`;
}
}
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
switch (shaderType) {
case "mat4x4f":
// We can't pass a matrix as a varying in WGSL, so we need to split it into 4 vectors
code += `varying ${name}_r0: vec4f;\n`;
code += `varying ${name}_r1: vec4f;\n`;
code += `varying ${name}_r2: vec4f;\n`;
code += `varying ${name}_r3: vec4f;\n`;
if (forFragment) {
code += `var<private> ${name}: mat4x4f;\n`;
this.sharedData.varyingInitializationsFragment += `${name} = mat4x4f(fragmentInputs.${name}_r0, fragmentInputs.${name}_r1, fragmentInputs.${name}_r2, fragmentInputs.${name}_r3);\n`;
}
break;
default:
code += `varying ${name}: ${shaderType};\n`;
break;
}
}
else {
code += `varying ${shaderType} ${name};\n`;
}
if (define) {
code += `#endif\n`;
}
return code;
};
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
this.sharedData.varyingDeclaration += emitCode(false);
this.sharedData.varyingDeclarationFragment += emitCode(true);
}
else {
const code = emitCode();
this.sharedData.varyingDeclaration += code;
this.sharedData.varyingDeclarationFragment += code;
}
return true;
}
/**
* @internal
*/
_getVaryingName(name) {
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
return (this.target !== NodeMaterialBlockTargets.Fragment ? "vertexOutputs." : "fragmentInputs.") + name;
}
return name;
}
/**
* @internal
*/
_emitUniformFromString(name, type, define = "", notDefine = false) {
if (this.uniforms.indexOf(name) !== -1) {
return;
}
this.uniforms.push(name);
if (define) {
if (define.startsWith("defined(")) {
this._uniformDeclaration += `#if ${define}\n`;
}
else {
this._uniformDeclaration += `${notDefine ? "#ifndef" : "#ifdef"} ${define}\n`;
}
}
if (this.sharedData.formatConfig.getUniformAnnotation) {
this._uniformDeclaration += this.sharedData.formatConfig.getUniformAnnotation(name);
}
const shaderType = this._getShaderType(type);
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
this._uniformDeclaration += `uniform ${name}: ${shaderType};\n`;
}
else {
this._uniformDeclaration += `uniform ${shaderType} ${name};\n`;
}
if (define) {
this._uniformDeclaration += `#endif\n`;
}
}
/**
* @internal
*/
_generateTernary(trueStatement, falseStatement, condition) {
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
return `select(${falseStatement}, ${trueStatement}, ${condition})`;
}
return `(${condition}) ? ${trueStatement} : ${falseStatement}`;
}
/**
* @internal
*/
_emitFloat(value) {
if (value.toString() === value.toFixed(0)) {
return `${value}.0`;
}
return value.toString();
}
/**
* @internal
*/
_declareOutput(output, isConst) {
return this._declareLocalVar(output.associatedVariableName, output.type, isConst);
}
/**
* @internal
*/
_declareLocalVar(name, type, isConst) {
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
return `${isConst ? "const" : "var"} ${name}: ${this._getShaderType(type)}`;
}
else {
return `${isConst ? "const " : ""}${this._getShaderType(type)} ${name}`;
}
}
/**
* @internal
*/
_samplerCubeFunc() {
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
return "textureSample";
}
return "textureCube";
}
/**
* @internal
*/
_samplerFunc() {
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
return "textureSample";
}
return "texture2D";
}
/**
* @internal
*/
_samplerLODFunc() {
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
return "textureSampleLevel";
}
return "texture2DLodEXT";
}
_toLinearSpace(output) {
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
if (output.type === NodeMaterialBlockConnectionPointTypes.Color3 || output.type === NodeMaterialBlockConnectionPointTypes.Vector3) {
return `toLinearSpaceVec3(${output.associatedVariableName})`;
}
return `toLinearSpace(${output.associatedVariableName})`;
}
return `toLinearSpace(${output.associatedVariableName})`;
}
/**
* @internal
*/
_generateTextureSample(uv, samplerName) {
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
return `${this._samplerFunc()}(${samplerName},${samplerName + `Sampler`}, ${uv})`;
}
return `${this._samplerFunc()}(${samplerName}, ${uv})`;
}
/**
* @internal
*/
_generateTextureSampleLOD(uv, samplerName, lod) {
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
return `${this._samplerLODFunc()}(${samplerName},${samplerName + `Sampler`}, ${uv}, ${lod})`;
}
return `${this._samplerLODFunc()}(${samplerName}, ${uv}, ${lod})`;
}
/**
* @internal
*/
_generateTextureSampleCube(uv, samplerName) {
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
return `${this._samplerCubeFunc()}(${samplerName},${samplerName + `Sampler`}, ${uv})`;
}
return `${this._samplerCubeFunc()}(${samplerName}, ${uv})`;
}
/**
* @internal
*/
_generateTextureSampleCubeLOD(uv, samplerName, lod) {
if (this.shaderLanguage === 1 /* ShaderLanguage.WGSL */) {
return `${this._samplerCubeFunc()}(${samplerName},${samplerName + `Sampler`}, ${uv}, ${lod})`;
}
return `${this._samplerCubeFunc()}(${samplerName}, ${uv}, ${lod})`;
}
_convertVariableDeclarationToWGSL(type, dest, source) {
return source.replace(new RegExp(`(${type})\\s+(\\w+)`, "g"), `var $2: ${dest}`);
}
_convertVariableConstructorsToWGSL(type, dest, source) {
return source.replace(new RegExp(`(${type})\\(`, "g"), ` ${dest}(`);
}
_convertOutParametersToWGSL(source) {
return source.replace(new RegExp(`out\\s+var\\s+(\\w+)\\s*:\\s*(\\w+)`, "g"), `$1: ptr<function, $2>`);
}
_convertTernaryOperandsToWGSL(source) {
return source.replace(new RegExp(`\\[(.*?)\\?(.*?):(.*)\\]`, "g"), (match, condition, trueCase, falseCase) => `select(${falseCase}, ${trueCase}, ${condition})`);
}
_convertModOperatorsToWGSL(source) {
return source.replace(new RegExp(`mod\\((.+?),\\s*(.+?)\\)`, "g"), (match, left, right) => `((${left})%(${right}))`);
}
_convertConstToWGSL(source) {
return source.replace(new RegExp(`const var`, "g"), `const`);
}
_convertInnerFunctionsToWGSL(source) {
return source.replace(new RegExp(`inversesqrt`, "g"), `inverseSqrt`);
}
_convertFunctionsToWGSL(source) {
const regex = /var\s+(\w+)\s*:\s*(\w+)\((.*)\)/g;
let match;
while ((match = regex.exec(source)) !== null) {
const funcName = match[1];
const funcType = match[2];
const params = match[3]; // All parameters as a single string
// Processing the parameters to match 'name: type' format
const formattedParams = params.replace(/var\s/g, "");
// Constructing the final output string
source = source.replace(match[0], `fn ${funcName}(${formattedParams}) -> ${funcType}`);
}
return source;
}
_babylonSLtoWGSL(code) {
// variable declarations
code = this._convertVariableDeclarationToWGSL("void", "voidnull", code);
code = this._convertVariableDeclarationToWGSL("bool", "bool", code);
code = this._convertVariableDeclarationToWGSL("int", "i32", code);
code = this._convertVariableDeclarationToWGSL("uint", "u32", code);
code = this._convertVariableDeclarationToWGSL("float", "f32", code);
code = this._convertVariableDeclarationToWGSL("vec2", "vec2f", code);
code = this._convertVariableDeclarationToWGSL("vec3", "vec3f", code);
code = this._convertVariableDeclarationToWGSL("vec4", "vec4f", code);
code = this._convertVariableDeclarationToWGSL("mat2", "mat2x2f", code);
code = this._convertVariableDeclarationToWGSL("mat3", "mat3x3f", code);
code = this._convertVariableDeclarationToWGSL("mat4", "mat4x4f", code);
// Type constructors
code = this._convertVariableConstructorsToWGSL("float", "f32", code);
code = this._convertVariableConstructorsToWGSL("vec2", "vec2f", code);
code = this._convertVariableConstructorsToWGSL("vec3", "vec3f", code);
code = this._convertVariableConstructorsToWGSL("vec4", "vec4f", code);
code = this._convertVariableConstructorsToWGSL("mat2", "mat2x2f", code);
code = this._convertVariableConstructorsToWGSL("mat3", "mat3x3f", code);
code = this._convertVariableConstructorsToWGSL("mat4", "mat4x4f", code);
// Ternary operands
code = this._convertTernaryOperandsToWGSL(code);
// Mod operators
code = this._convertModOperatorsToWGSL(code);
// Const
code = this._convertConstToWGSL(code);
// Inner functions
code = this._convertInnerFunctionsToWGSL(code);
// Out paramters
code = this._convertOutParametersToWGSL(code);
code = code.replace(/\[\*\]/g, "*");
// Functions
code = this._convertFunctionsToWGSL(code);
// Remove voidnull
code = code.replace(/\s->\svoidnull/g, "");
// Derivatives
code = code.replace(/dFdx/g, "dpdx");
code = code.replace(/dFdy/g, "dpdy");
return code;
}
_convertTernaryOperandsToGLSL(source) {
return source.replace(new RegExp(`\\[(.+?)\\?(.+?):(.+)\\]`, "g"), (match, condition, trueCase, falseCase) => `${condition} ? ${trueCase} : ${falseCase}`);
}
_babylonSLtoGLSL(code) {
/** Remove BSL specifics */
code = code.replace(/\[\*\]/g, "");
code = this._convertTernaryOperandsToGLSL(code);
return code;
}
}
//# sourceMappingURL=nodeMaterialBuildState.js.map