Browse Source

Add the ClearCoat block to the NME

Popov72 5 years ago
parent
commit
09a408e06a

+ 3 - 0
nodeEditor/src/blockTools.ts

@@ -68,6 +68,7 @@ import { AmbientOcclusionBlock } from 'babylonjs/Materials/Node/Blocks/PBR/ambie
 import { ReflectivityBlock } from 'babylonjs/Materials/Node/Blocks/PBR/reflectivityBlock';
 import { ReflectivityBlock } from 'babylonjs/Materials/Node/Blocks/PBR/reflectivityBlock';
 import { AnisotropyBlock } from 'babylonjs/Materials/Node/Blocks/PBR/anisotropyBlock';
 import { AnisotropyBlock } from 'babylonjs/Materials/Node/Blocks/PBR/anisotropyBlock';
 import { ReflectionBlock } from 'babylonjs/Materials/Node/Blocks/PBR/reflectionBlock';
 import { ReflectionBlock } from 'babylonjs/Materials/Node/Blocks/PBR/reflectionBlock';
+import { ClearCoatBlock } from 'babylonjs/Materials/Node/Blocks/PBR/clearCoatBlock';
 
 
 export class BlockTools {
 export class BlockTools {
     public static GetBlockFromString(data: string, scene: Scene, nodeMaterial: NodeMaterial) {
     public static GetBlockFromString(data: string, scene: Scene, nodeMaterial: NodeMaterial) {
@@ -450,6 +451,8 @@ export class BlockTools {
                 return new AnisotropyBlock("Anisotropy");
                 return new AnisotropyBlock("Anisotropy");
             case "ReflectionBlock":
             case "ReflectionBlock":
                 return new ReflectionBlock("Reflection");
                 return new ReflectionBlock("Reflection");
+            case "ClearCoatBlock":
+                return new ClearCoatBlock("ClearCoat");
         }
         }
 
 
         return null;
         return null;

+ 3 - 2
nodeEditor/src/components/nodeList/nodeListComponent.tsx

@@ -122,7 +122,8 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
         "AmbientOcclusionBlock": "PBR Ambient occlusion block",
         "AmbientOcclusionBlock": "PBR Ambient occlusion block",
         "ReflectivityBlock": "PBR Reflectivity block",
         "ReflectivityBlock": "PBR Reflectivity block",
         "AnisotropyBlock": "PBR Anisotropy block",
         "AnisotropyBlock": "PBR Anisotropy block",
-        "ReflectionBlock": "PBR Reflection block"
+        "ReflectionBlock": "PBR Reflection block",
+        "ClearCoatBlock": "PBR ClearCoat block",
     };
     };
 
 
     constructor(props: INodeListComponentProps) {
     constructor(props: INodeListComponentProps) {
@@ -151,7 +152,7 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
             Mesh: ["InstancesBlock", "PositionBlock", "UVBlock", "ColorBlock", "NormalBlock", "PerturbNormalBlock", "NormalBlendBlock" , "TangentBlock", "MatrixIndicesBlock", "MatrixWeightsBlock", "WorldPositionBlock", "WorldNormalBlock", "WorldTangentBlock", "FrontFacingBlock"],
             Mesh: ["InstancesBlock", "PositionBlock", "UVBlock", "ColorBlock", "NormalBlock", "PerturbNormalBlock", "NormalBlendBlock" , "TangentBlock", "MatrixIndicesBlock", "MatrixWeightsBlock", "WorldPositionBlock", "WorldNormalBlock", "WorldTangentBlock", "FrontFacingBlock"],
             Noises: ["RandomNumberBlock", "SimplexPerlin3DBlock", "WorleyNoise3DBlock"],
             Noises: ["RandomNumberBlock", "SimplexPerlin3DBlock", "WorleyNoise3DBlock"],
             Output_Nodes: ["VertexOutputBlock", "FragmentOutputBlock", "DiscardBlock"],
             Output_Nodes: ["VertexOutputBlock", "FragmentOutputBlock", "DiscardBlock"],
-            PBR: ["PBRMetallicRoughnessBlock", "AmbientOcclusionBlock", "AnisotropyBlock", "ReflectionBlock", "ReflectivityBlock", "SheenBlock"],
+            PBR: ["PBRMetallicRoughnessBlock", "AmbientOcclusionBlock", "AnisotropyBlock", "ClearCoatBlock", "ReflectionBlock", "ReflectivityBlock", "SheenBlock"],
             Range: ["ClampBlock", "RemapBlock", "NormalizeBlock"],
             Range: ["ClampBlock", "RemapBlock", "NormalizeBlock"],
             Round: ["RoundBlock", "CeilingBlock", "FloorBlock"],
             Round: ["RoundBlock", "CeilingBlock", "FloorBlock"],
             Scene: ["FogBlock", "CameraPositionBlock", "FogColorBlock", "ImageProcessingBlock", "LightBlock", "LightInformationBlock", "ViewDirectionBlock"],
             Scene: ["FogBlock", "CameraPositionBlock", "FogColorBlock", "ImageProcessingBlock", "LightBlock", "LightInformationBlock", "ViewDirectionBlock"],

+ 301 - 0
src/Materials/Node/Blocks/PBR/clearCoatBlock.ts

@@ -0,0 +1,301 @@
+import { NodeMaterialBlock } from '../../nodeMaterialBlock';
+import { NodeMaterialBlockConnectionPointTypes } from '../../Enums/nodeMaterialBlockConnectionPointTypes';
+import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
+import { NodeMaterialConnectionPoint, NodeMaterialConnectionPointDirection } from '../../nodeMaterialBlockConnectionPoint';
+import { NodeMaterialBlockTargets } from '../../Enums/nodeMaterialBlockTargets';
+import { _TypeStore } from '../../../../Misc/typeStore';
+import { InputBlock } from '../Input/inputBlock';
+import { NodeMaterialConnectionPointCustomObject } from "../../nodeMaterialConnectionPointCustomObject";
+import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
+import { AbstractMesh } from '../../../../Meshes/abstractMesh';
+import { ReflectionBlock } from './reflectionBlock';
+import { Scene } from '../../../../scene';
+import { Nullable } from '../../../../types';
+import { Mesh } from '../../../../Meshes/mesh';
+import { SubMesh } from '../../../../Meshes/subMesh';
+import { Effect } from '../../../effect';
+import { PBRMetallicRoughnessBlock } from './pbrMetallicRoughnessBlock';
+import { PerturbNormalBlock } from '../Fragment/perturbNormalBlock';
+
+/**
+ * Block used to implement the clear coat module of the PBR material
+ */
+export class ClearCoatBlock extends NodeMaterialBlock {
+
+    private _scene: Scene;
+
+    /**
+     * Create a new ClearCoatBlock
+     * @param name defines the block name
+     */
+    public constructor(name: string) {
+        super(name, NodeMaterialBlockTargets.Fragment);
+
+        this._isUnique = true;
+
+        this.registerInput("intensity", NodeMaterialBlockConnectionPointTypes.Float, false, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("roughness", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("ior", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("texture", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("bumpTexture", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("uv", NodeMaterialBlockConnectionPointTypes.Vector2, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("tintColor", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("tintAtDistance", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("tintThickness", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("tintTexture", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
+
+        this.registerOutput("clearcoat", NodeMaterialBlockConnectionPointTypes.Object, NodeMaterialBlockTargets.Fragment,
+            new NodeMaterialConnectionPointCustomObject("clearcoat", this, NodeMaterialConnectionPointDirection.Output, ClearCoatBlock, "ClearCoatBlock"));
+    }
+
+    /**
+     * Initialize the block and prepare the context for build
+     * @param state defines the state that will be used for the build
+     */
+    public initialize(state: NodeMaterialBuildState) {
+        state._excludeVariableName("clearcoatOut");
+        state._excludeVariableName("vClearCoatParams");
+        state._excludeVariableName("vClearCoatTintParams");
+        state._excludeVariableName("vClearCoatRefractionParams");
+        state._excludeVariableName("vClearCoatTangentSpaceParams");
+    }
+
+    /**
+     * Gets the current class name
+     * @returns the class name
+     */
+    public getClassName() {
+        return "ClearCoatBlock";
+    }
+
+    /**
+     * Gets the intensity input component
+     */
+    public get intensity(): NodeMaterialConnectionPoint {
+        return this._inputs[0];
+    }
+
+    /**
+     * Gets the roughness input component
+     */
+    public get roughness(): NodeMaterialConnectionPoint {
+        return this._inputs[1];
+    }
+
+    /**
+     * Gets the ior input component
+     */
+    public get ior(): NodeMaterialConnectionPoint {
+        return this._inputs[2];
+    }
+
+    /**
+     * Gets the texture input component
+     */
+    public get texture(): NodeMaterialConnectionPoint {
+        return this._inputs[3];
+    }
+
+    /**
+     * Gets the bump texture input component
+     */
+    public get bumpTexture(): NodeMaterialConnectionPoint {
+        return this._inputs[4];
+    }
+
+    /**
+     * Gets the uv input component
+     */
+    public get uv(): NodeMaterialConnectionPoint {
+        return this._inputs[5];
+    }
+
+    /**
+     * Gets the tint color input component
+     */
+    public get tintColor(): NodeMaterialConnectionPoint {
+        return this._inputs[6];
+    }
+
+    /**
+     * Gets the tint "at distance" input component
+     */
+    public get tintAtDistance(): NodeMaterialConnectionPoint {
+        return this._inputs[7];
+    }
+
+    /**
+     * Gets the tint thickness input component
+     */
+    public get tintThickness(): NodeMaterialConnectionPoint {
+        return this._inputs[8];
+    }
+
+    /**
+     * Gets the tint texture input component
+     */
+    public get tintTexture(): NodeMaterialConnectionPoint {
+        return this._inputs[9];
+    }
+
+    /**
+     * Gets the clear coat object output component
+     */
+    public get clearcoat(): NodeMaterialConnectionPoint {
+        return this._outputs[0];
+    }
+
+    public autoConfigure(material: NodeMaterial) {
+        if (!this.intensity.isConnected) {
+            let intensityInput = new InputBlock("ClearCoat intensity", NodeMaterialBlockTargets.Fragment, NodeMaterialBlockConnectionPointTypes.Float);
+            intensityInput.value = 1;
+            intensityInput.output.connectTo(this.intensity);
+        }
+    }
+
+    public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
+        super.prepareDefines(mesh, nodeMaterial, defines);
+
+        defines.setValue("CLEARCOAT", true);
+        defines.setValue("CLEARCOAT_TEXTURE", this.texture.isConnected);
+        defines.setValue("CLEARCOAT_TINT", this.tintColor.isConnected || this.tintTexture.isConnected);
+        defines.setValue("CLEARCOAT_BUMP", this.bumpTexture.isConnected);
+    }
+
+    public bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh, subMesh?: SubMesh) {
+        super.bind(effect, nodeMaterial, mesh);
+
+        // Clear Coat Refraction params
+        const indexOfRefraction = this.ior.connectInputBlock?.value ?? 1.5;
+
+        const a = 1 - indexOfRefraction;
+        const b = 1 + indexOfRefraction;
+        const f0 = Math.pow((-a / b), 2); // Schlicks approx: (ior1 - ior2) / (ior1 + ior2) where ior2 for air is close to vacuum = 1.
+        const eta = 1 / indexOfRefraction;
+
+        effect.setFloat4("vClearCoatRefractionParams", f0, eta, a, b);
+
+        // Clear Coat tangent space params
+        const mainPBRBlock = this.clearcoat.hasEndpoints ? this.clearcoat.endpoints[0].ownerBlock as PBRMetallicRoughnessBlock : null;
+        const perturbedNormalBlock = mainPBRBlock?.perturbedNormal.isConnected ? mainPBRBlock.perturbedNormal.connectedPoint!.ownerBlock as PerturbNormalBlock : null;
+
+        if (this._scene._mirroredCameraPosition) {
+            effect.setFloat2("vClearCoatTangentSpaceParams", perturbedNormalBlock?.invertX ? 1.0 : -1.0, perturbedNormalBlock?.invertY ? 1.0 : -1.0);
+        } else {
+            effect.setFloat2("vClearCoatTangentSpaceParams", perturbedNormalBlock?.invertX ? -1.0 : 1.0, perturbedNormalBlock?.invertY ? -1.0 : 1.0);
+        }
+    }
+
+    /**
+     * Gets the main code of the block (fragment side)
+     * @param state current state of the node material building
+     * @param ccBlock instance of a ClearCoatBlock or null if the code must be generated without an active clear coat module
+     * @param reflectionBlock instance of a ReflectionBlock null if the code must be generated without an active reflection module
+     * @param worldPosVarName name of the variable holding the world position
+     * @returns the shader code
+     */
+    public static GetCode(state: NodeMaterialBuildState, ccBlock: Nullable<ClearCoatBlock>, reflectionBlock: Nullable<ReflectionBlock>, worldPosVarName: string): string {
+        let code = "";
+
+        const intensity = ccBlock?.intensity.isConnected ? ccBlock.intensity.associatedVariableName : "1.";
+        const roughness = ccBlock?.roughness.isConnected ? ccBlock.roughness.associatedVariableName : "0.";
+        const texture = ccBlock?.texture.isConnected ? ccBlock.texture.associatedVariableName : "vec2(0.)";
+        const bumpTexture = ccBlock?.bumpTexture.isConnected ? ccBlock.bumpTexture.associatedVariableName : "vec4(0.)";
+        const uv = ccBlock?.uv.isConnected ? ccBlock.uv.associatedVariableName : "vec2(0.)";
+
+        const tintColor = ccBlock?.tintColor.isConnected ? ccBlock.tintColor.associatedVariableName : "vec3(1.)";
+        const tintThickness = ccBlock?.tintThickness.isConnected ? ccBlock.tintThickness.associatedVariableName : "1.";
+        const tintAtDistance = ccBlock?.tintAtDistance.isConnected ? ccBlock.tintAtDistance.associatedVariableName : "1.";
+        const tintTexture = ccBlock?.tintTexture.isConnected ? ccBlock.tintTexture.associatedVariableName : "vec4(0.)";
+
+        if (ccBlock) {
+            state._emitUniformFromString("vClearCoatRefractionParams", "vec4");
+            state._emitUniformFromString("vClearCoatTangentSpaceParams", "vec2");
+        }
+
+        code = `clearcoatOutParams clearcoatOut;
+
+        #ifdef CLEARCOAT
+            vec2 vClearCoatParams = vec2(${intensity}, ${roughness});
+            vec4 vClearCoatTintParams = vec4(${tintColor}, ${tintThickness});
+
+            clearcoatBlock(
+                ${worldPosVarName}.xyz,
+                geometricNormalW,
+                viewDirectionW,
+                vClearCoatParams,
+                specularEnvironmentR0,
+            #ifdef CLEARCOAT_TEXTURE
+                ${texture},
+            #endif
+            #ifdef CLEARCOAT_TINT
+                vClearCoatTintParams,
+                ${tintAtDistance},
+                vClearCoatRefractionParams,
+                #ifdef CLEARCOAT_TINT_TEXTURE
+                    ${tintTexture},
+                #endif
+            #endif
+            #ifdef CLEARCOAT_BUMP
+                vec2(0., 1.),
+                ${bumpTexture},
+                ${uv},
+                #if defined(TANGENT) && defined(NORMAL)
+                    vTBN,
+                #else
+                    vClearCoatTangentSpaceParams,
+                #endif
+                #ifdef OBJECTSPACE_NORMALMAP
+                    normalMatrix,
+                #endif
+            #endif
+            #if defined(FORCENORMALFORWARD) && defined(NORMAL)
+                faceNormal,
+            #endif
+            #ifdef REFLECTION
+                ${reflectionBlock?._vReflectionMicrosurfaceInfosName},
+                ${reflectionBlock?._vReflectionInfosName},
+                ${reflectionBlock?.reflectionColor},
+                vLightingIntensity,
+                #ifdef ${reflectionBlock?._define3DName}
+                    ${reflectionBlock?._cubeSamplerName},
+                #else
+                    ${reflectionBlock?._2DSamplerName},
+                #endif
+                #ifndef LODBASEDMICROSFURACE
+                    #ifdef ${reflectionBlock?._define3DName}
+                        ${reflectionBlock?._cubeSamplerName},
+                        ${reflectionBlock?._cubeSamplerName},
+                    #else
+                        ${reflectionBlock?._2DSamplerName},
+                        ${reflectionBlock?._2DSamplerName},
+                    #endif
+                #endif
+            #endif
+            #if defined(ENVIRONMENTBRDF) && !defined(${reflectionBlock?._defineSkyboxName})
+                #ifdef RADIANCEOCCLUSION
+                    ambientMonochrome,
+                #endif
+            #endif
+                clearcoatOut
+            );
+        #else
+            clearcoatOut.specularEnvironmentR0 = specularEnvironmentR0;
+        #endif\r\n`;
+
+        return code;
+    }
+
+    protected _buildBlock(state: NodeMaterialBuildState) {
+        this._scene = state.sharedData.scene;
+
+        if (state.target === NodeMaterialBlockTargets.Fragment) {
+            state.sharedData.bindableBlocks.push(this);
+            state.sharedData.blocksWithDefines.push(this);
+        }
+
+        return this;
+    }
+}
+
+_TypeStore.RegisteredTypes["BABYLON.ClearCoatBlock"] = ClearCoatBlock;

+ 1 - 0
src/Materials/Node/Blocks/PBR/index.ts

@@ -4,3 +4,4 @@ export * from "./ambientOcclusionBlock";
 export * from "./reflectivityBlock";
 export * from "./reflectivityBlock";
 export * from "./anisotropyBlock";
 export * from "./anisotropyBlock";
 export * from "./reflectionBlock";
 export * from "./reflectionBlock";
+export * from "./clearCoatBlock";

+ 19 - 8
src/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.ts

@@ -25,6 +25,7 @@ import { BRDFTextureTools } from '../../../../Misc/brdfTextureTools';
 import { MaterialFlags } from '../../../materialFlags';
 import { MaterialFlags } from '../../../materialFlags';
 import { AnisotropyBlock } from './anisotropyBlock';
 import { AnisotropyBlock } from './anisotropyBlock';
 import { ReflectionBlock } from './reflectionBlock';
 import { ReflectionBlock } from './reflectionBlock';
+import { ClearCoatBlock } from './clearCoatBlock';
 
 
 const mapOutputToVariable: { [name: string] : [string, string] } = {
 const mapOutputToVariable: { [name: string] : [string, string] } = {
     "ambient":      ["finalAmbient", ""],
     "ambient":      ["finalAmbient", ""],
@@ -83,7 +84,8 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
             new NodeMaterialConnectionPointCustomObject("reflection", this, NodeMaterialConnectionPointDirection.Input, ReflectionBlock, "ReflectionBlock"));
             new NodeMaterialConnectionPointCustomObject("reflection", this, NodeMaterialConnectionPointDirection.Input, ReflectionBlock, "ReflectionBlock"));
         this.registerInput("sheen", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
         this.registerInput("sheen", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
             new NodeMaterialConnectionPointCustomObject("sheen", this, NodeMaterialConnectionPointDirection.Input, SheenBlock, "SheenBlock"));
             new NodeMaterialConnectionPointCustomObject("sheen", this, NodeMaterialConnectionPointDirection.Input, SheenBlock, "SheenBlock"));
-        this.registerInput("clearCoat", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("clearCoat", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
+            new NodeMaterialConnectionPointCustomObject("clearcoat", this, NodeMaterialConnectionPointDirection.Input, ClearCoatBlock, "ClearCoatBlock"));
         this.registerInput("subSurface", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("subSurface", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("anisotropy", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
         this.registerInput("anisotropy", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
             new NodeMaterialConnectionPointCustomObject("anisotropy", this, NodeMaterialConnectionPointDirection.Input, AnisotropyBlock, "AnisotropyBlock"));
             new NodeMaterialConnectionPointCustomObject("anisotropy", this, NodeMaterialConnectionPointDirection.Input, AnisotropyBlock, "AnisotropyBlock"));
@@ -834,7 +836,6 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         state._emitFunctionFromInclude("pbrBlockAmbientOcclusion", comments);
         state._emitFunctionFromInclude("pbrBlockAmbientOcclusion", comments);
         state._emitFunctionFromInclude("pbrBlockAlphaFresnel", comments);
         state._emitFunctionFromInclude("pbrBlockAlphaFresnel", comments);
         state._emitFunctionFromInclude("pbrBlockAnisotropic", comments);
         state._emitFunctionFromInclude("pbrBlockAnisotropic", comments);
-        state._emitFunctionFromInclude("pbrBlockClearcoat", comments);
         state._emitFunctionFromInclude("pbrBlockSubSurface", comments);
         state._emitFunctionFromInclude("pbrBlockSubSurface", comments);
 
 
         //
         //
@@ -942,12 +943,22 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
             ]
             ]
         });
         });
 
 
-            // _____________________________ Clear Coat ____________________________
-            state.compilationString += `clearcoatOutParams clearcoatOut;
-                #ifdef CLEARCOAT
-                #else
-                    clearcoatOut.specularEnvironmentR0 = specularEnvironmentR0;
-                #endif\r\n`;
+        // _____________________________ Clear Coat ____________________________
+        const clearcoatBlock = this.clearcoat.isConnected ? this.clearcoat.connectedPoint?.ownerBlock as ClearCoatBlock : null;
+
+        state.compilationString += ClearCoatBlock.GetCode(state, clearcoatBlock, reflectionBlock, worldPosVarName);
+
+        state._emitFunctionFromInclude("pbrBlockClearcoat", comments, {
+            replaceStrings: [
+                { search: /computeReflectionCoords/g, replace: "computeReflectionCoordsPBR" },
+                { search: /REFLECTIONMAP_3D/g, replace: reflectionBlock?._define3DName ?? "REFLECTIONMAP_3D" },
+                { search: /REFLECTIONMAP_OPPOSITEZ/g, replace: reflectionBlock?._defineOppositeZ ?? "REFLECTIONMAP_OPPOSITEZ" },
+                { search: /REFLECTIONMAP_PROJECTION/g, replace: reflectionBlock?._defineProjectionName ?? "REFLECTIONMAP_PROJECTION" },
+                { search: /REFLECTIONMAP_SKYBOX/g, replace: reflectionBlock?._defineSkyboxName ?? "REFLECTIONMAP_SKYBOX" },
+                { search: /LODINREFLECTIONALPHA/g, replace: reflectionBlock?._defineLODReflectionAlpha ?? "LODINREFLECTIONALPHA" },
+                { search: /LINEARSPECULARREFLECTION/g, replace: reflectionBlock?._defineLinearSpecularReflection ?? "LINEARSPECULARREFLECTION" },
+            ]
+        });
 
 
         // _________________________ Specular Environment Reflectance __________________________
         // _________________________ Specular Environment Reflectance __________________________
         state.compilationString += state._emitCodeFromInclude("pbrBlockReflectance", comments, {
         state.compilationString += state._emitCodeFromInclude("pbrBlockReflectance", comments, {