瀏覽代碼

Merge pull request #9208 from Popov72/nme-pbr-improvements

NME PBR redesign
David Catuhe 4 年之前
父節點
當前提交
a9390c1d98

+ 0 - 6
nodeEditor/src/blockTools.ts

@@ -65,8 +65,6 @@ import { ReflectBlock } from 'babylonjs/Materials/Node/Blocks/reflectBlock';
 import { DesaturateBlock } from 'babylonjs/Materials/Node/Blocks/desaturateBlock';
 import { PBRMetallicRoughnessBlock } from 'babylonjs/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock';
 import { SheenBlock } from 'babylonjs/Materials/Node/Blocks/PBR/sheenBlock';
-import { AmbientOcclusionBlock } from 'babylonjs/Materials/Node/Blocks/PBR/ambientOcclusionBlock';
-import { ReflectivityBlock } from 'babylonjs/Materials/Node/Blocks/PBR/reflectivityBlock';
 import { AnisotropyBlock } from 'babylonjs/Materials/Node/Blocks/PBR/anisotropyBlock';
 import { ReflectionBlock } from 'babylonjs/Materials/Node/Blocks/PBR/reflectionBlock';
 import { ClearCoatBlock } from 'babylonjs/Materials/Node/Blocks/PBR/clearCoatBlock';
@@ -460,10 +458,6 @@ export class BlockTools {
                 return new PBRMetallicRoughnessBlock("PBRMetallicRoughness");
             case "SheenBlock":
                 return new SheenBlock("Sheen");
-            case "AmbientOcclusionBlock":
-                return new AmbientOcclusionBlock("AmbientOcclusion");
-            case "ReflectivityBlock":
-                return new ReflectivityBlock("Reflectivity");
             case "AnisotropyBlock":
                 return new AnisotropyBlock("Anisotropy");
             case "ReflectionBlock":

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

@@ -130,8 +130,6 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
         "Rotate2dBlock": "Rotates UV coordinates around the W axis.",
         "PBRMetallicRoughnessBlock": "PBR metallic/roughness material",
         "SheenBlock": "PBR Sheen block",
-        "AmbientOcclusionBlock": "PBR Ambient occlusion block",
-        "ReflectivityBlock": "PBR Reflectivity block",
         "AnisotropyBlock": "PBR Anisotropy block",
         "ReflectionBlock": "PBR Reflection block",
         "ClearCoatBlock": "PBR ClearCoat block",
@@ -238,7 +236,7 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
             Noises: ["RandomNumberBlock", "SimplexPerlin3DBlock", "WorleyNoise3DBlock"],
             Output_Nodes: ["VertexOutputBlock", "FragmentOutputBlock", "DiscardBlock"],
             Particle: ["ParticleBlendMultiplyBlock", "ParticleColorBlock", "ParticlePositionWorldBlock", "ParticleRampGradientBlock", "ParticleTextureBlock", "ParticleTextureMaskBlock", "ParticleUVBlock"],
-            PBR: ["PBRMetallicRoughnessBlock", "AmbientOcclusionBlock", "AnisotropyBlock", "ClearCoatBlock", "ReflectionBlock", "ReflectivityBlock", "RefractionBlock", "SheenBlock", "SubSurfaceBlock"],
+            PBR: ["PBRMetallicRoughnessBlock", "AnisotropyBlock", "ClearCoatBlock", "ReflectionBlock", "RefractionBlock", "SheenBlock", "SubSurfaceBlock"],
             PostProcess: ["ScreenPositionBlock", "CurrentScreenBlock"],
             Procedural__Texture: ["ScreenPositionBlock"],
             Range: ["ClampBlock", "RemapBlock", "NormalizeBlock"],

+ 1 - 0
nodeEditor/src/components/preview/previewManager.ts

@@ -99,6 +99,7 @@ export class PreviewManager {
         this._engine = new Engine(targetCanvas, true);
         this._scene = new Scene(this._engine);
         this._scene.clearColor = this._globalState.backgroundColor;
+        this._scene.ambientColor = new Color3(1, 1, 1);
         this._camera = new ArcRotateCamera("Camera", 0, 0.8, 4, Vector3.Zero(), this._scene);
 
         this._camera.lowerRadiusLimit = 3;

+ 4 - 2
nodeEditor/src/diagram/graphFrame.ts

@@ -156,7 +156,7 @@ export class GraphFrame {
 
         for (var i = 0; i < this._exposedInPorts.length; ) { // Input
             var port = this._exposedInPorts[i];
-            if(port.node === null || port.node.enclosingFrameId != this.id) {
+            if(!port || port.node === null || port.node.enclosingFrameId != this.id) {
                 if(this.removePortFromExposedWithNode(port, this._exposedInPorts)) {
                     continue;
                 }
@@ -194,7 +194,9 @@ export class GraphFrame {
         let index = exposedPorts.findIndex(nodePort => nodePort === port);
         if(index >= 0) {
             exposedPorts.splice(index,1)
-            port.exposedPortPosition = -1;
+            if (port) {
+                port.exposedPortPosition = -1;
+            }
             return true;
         }
         return false;

+ 1 - 1
src/Materials/Node/Blocks/Dual/reflectionTextureBaseBlock.ts

@@ -135,7 +135,7 @@ export abstract class ReflectionTextureBaseBlock extends NodeMaterialBlock {
             worldInput.output.connectTo(this.world);
         }
 
-        if (!this.view.isConnected) {
+        if (this.view && !this.view.isConnected) {
             let viewInput = material.getInputBlockByPredicate((b) => b.systemValue === NodeMaterialSystemValues.View);
 
             if (!viewInput) {

+ 0 - 146
src/Materials/Node/Blocks/PBR/ambientOcclusionBlock.ts

@@ -1,146 +0,0 @@
-import { NodeMaterialBlock } from '../../nodeMaterialBlock';
-import { NodeMaterialBlockConnectionPointTypes } from '../../Enums/nodeMaterialBlockConnectionPointTypes';
-import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
-import { NodeMaterialConnectionPoint, NodeMaterialConnectionPointDirection } from '../../nodeMaterialBlockConnectionPoint';
-import { NodeMaterialBlockTargets } from '../../Enums/nodeMaterialBlockTargets';
-import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
-import { Nullable } from '../../../../types';
-import { editableInPropertyPage, PropertyTypeForEdition } from "../../nodeMaterialDecorator";
-import { _TypeStore } from '../../../../Misc/typeStore';
-import { AbstractMesh } from '../../../../Meshes/abstractMesh';
-import { NodeMaterialConnectionPointCustomObject } from "../../nodeMaterialConnectionPointCustomObject";
-import { Scene } from '../../../../scene';
-
-/**
- * Block used to implement the ambient occlusion module of the PBR material
- */
-export class AmbientOcclusionBlock extends NodeMaterialBlock {
-
-    /**
-     * Create a new AmbientOcclusionBlock
-     * @param name defines the block name
-     */
-    public constructor(name: string) {
-        super(name, NodeMaterialBlockTargets.Fragment);
-
-        this._isUnique = true;
-
-        this.registerInput("texture", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("intensity", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("directLightIntensity", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
-
-        this.registerOutput("ambientOcc", NodeMaterialBlockConnectionPointTypes.Object, NodeMaterialBlockTargets.Fragment,
-            new NodeMaterialConnectionPointCustomObject("ambientOcc", this, NodeMaterialConnectionPointDirection.Output, AmbientOcclusionBlock, "AOBlock", "ambientOcc"));
-    }
-
-    /**
-     * Specifies if the ambient texture contains the ambient occlusion information in its red channel only.
-     */
-    @editableInPropertyPage("Ambient in gray scale", PropertyTypeForEdition.Boolean, "AMBIENT", { "notifiers": { "update": true }})
-    public useAmbientInGrayScale: boolean = false;
-
-    /**
-     * 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("aoOut");
-    }
-
-    /**
-     * Gets the current class name
-     * @returns the class name
-     */
-    public getClassName() {
-        return "AmbientOcclusionBlock";
-    }
-
-    /**
-     * Gets the texture input component
-     */
-    public get texture(): NodeMaterialConnectionPoint {
-        return this._inputs[0];
-    }
-
-    /**
-     * Gets the texture intensity component
-     */
-    public get intensity(): NodeMaterialConnectionPoint {
-        return this._inputs[1];
-    }
-
-    /**
-     * Gets the direct light intensity input component
-     */
-    public get directLightIntensity(): NodeMaterialConnectionPoint {
-        return this._inputs[2];
-    }
-
-    /**
-     * Gets the ambient occlusion object output component
-     */
-    public get ambientOcc(): NodeMaterialConnectionPoint {
-        return this._outputs[0];
-    }
-
-    /**
-     * Gets the main code of the block (fragment side)
-     * @param block instance of an AmbientOcclusionBlock or null if the code must be generated without an active ambient occlusion module
-     * @returns the shader code
-     */
-    public static GetCode(block: Nullable<AmbientOcclusionBlock>): string {
-        let code = `ambientOcclusionOutParams aoOut;\r\n`;
-
-        const aoTexture = block?.texture.isConnected ? block.texture.associatedVariableName : "vec3(0.)";
-        const aoIntensity = block?.intensity.isConnected ? block.intensity.associatedVariableName : "1.";
-
-        code += `ambientOcclusionBlock(
-            #ifdef AMBIENT
-                ${aoTexture},
-                vec4(0., 1.0, ${aoIntensity}, 0.),
-            #endif
-                aoOut
-            );\r\n`;
-
-        return code;
-    }
-
-    public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
-        super.prepareDefines(mesh, nodeMaterial, defines);
-
-        defines.setValue("AMBIENT", this.texture.isConnected, true);
-        defines.setValue("AMBIENTINGRAYSCALE", this.useAmbientInGrayScale, true);
-    }
-
-    protected _buildBlock(state: NodeMaterialBuildState) {
-        if (state.target === NodeMaterialBlockTargets.Fragment) {
-            state.sharedData.blocksWithDefines.push(this);
-        }
-
-        return this;
-    }
-
-    protected _dumpPropertiesCode() {
-        let codeString: string;
-
-        codeString = `${this._codeVariableName}.useAmbientInGrayScale = ${this.useAmbientInGrayScale};\r\n`;
-
-        return codeString;
-    }
-
-    public serialize(): any {
-        let serializationObject = super.serialize();
-
-        serializationObject.useAmbientInGrayScale = this.useAmbientInGrayScale;
-
-        return serializationObject;
-    }
-
-    public _deserialize(serializationObject: any, scene: Scene, rootUrl: string) {
-        super._deserialize(serializationObject, scene, rootUrl);
-
-        this.useAmbientInGrayScale = serializationObject.useAmbientInGrayScale;
-    }
-}
-
-_TypeStore.RegisteredTypes["BABYLON.AmbientOcclusionBlock"] = AmbientOcclusionBlock;

+ 4 - 13
src/Materials/Node/Blocks/PBR/anisotropyBlock.ts

@@ -35,7 +35,6 @@ export class AnisotropyBlock extends NodeMaterialBlock {
 
         this.registerInput("intensity", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("direction", NodeMaterialBlockConnectionPointTypes.Vector2, true, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("texture", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("uv", NodeMaterialBlockConnectionPointTypes.Vector2, true); // need this property and the next one in case there's no PerturbNormal block connected to the main PBR block
         this.registerInput("worldTangent", NodeMaterialBlockConnectionPointTypes.Vector4, true);
 
@@ -75,24 +74,17 @@ export class AnisotropyBlock extends NodeMaterialBlock {
     }
 
     /**
-     * Gets the texture input component
-     */
-    public get texture(): NodeMaterialConnectionPoint {
-        return this._inputs[2];
-    }
-
-    /**
      * Gets the uv input component
      */
     public get uv(): NodeMaterialConnectionPoint {
-        return this._inputs[3];
+        return this._inputs[2];
     }
 
     /**
      * Gets the worldTangent input component
      */
     public get worldTangent(): NodeMaterialConnectionPoint {
-        return this._inputs[4];
+        return this._inputs[3];
     }
 
     /**
@@ -160,13 +152,12 @@ export class AnisotropyBlock extends NodeMaterialBlock {
 
         const intensity = this.intensity.isConnected ? this.intensity.associatedVariableName : "1.0";
         const direction = this.direction.isConnected ? this.direction.associatedVariableName : "vec2(1., 0.)";
-        const texture = this.texture.isConnected ? this.texture.associatedVariableName : "vec3(0.)";
 
         code += `anisotropicOutParams anisotropicOut;
             anisotropicBlock(
                 vec3(${direction}, ${intensity}),
             #ifdef ANISOTROPIC_TEXTURE
-                ${texture},
+                vec3(0.),
             #endif
                 TBN,
                 normalW,
@@ -181,7 +172,7 @@ export class AnisotropyBlock extends NodeMaterialBlock {
         super.prepareDefines(mesh, nodeMaterial, defines);
 
         defines.setValue("ANISOTROPIC", true);
-        defines.setValue("ANISOTROPIC_TEXTURE", this.texture.isConnected, true);
+        defines.setValue("ANISOTROPIC_TEXTURE", false, true);
     }
 
     protected _buildBlock(state: NodeMaterialBuildState) {

+ 48 - 26
src/Materials/Node/Blocks/PBR/clearCoatBlock.ts

@@ -16,6 +16,8 @@ import { SubMesh } from '../../../../Meshes/subMesh';
 import { Effect } from '../../../effect';
 import { PBRMetallicRoughnessBlock } from './pbrMetallicRoughnessBlock';
 import { PerturbNormalBlock } from '../Fragment/perturbNormalBlock';
+import { PBRClearCoatConfiguration } from '../../../PBR/pbrClearCoatConfiguration';
+import { editableInPropertyPage, PropertyTypeForEdition } from "../../nodeMaterialDecorator";
 
 /**
  * Block used to implement the clear coat module of the PBR material
@@ -35,9 +37,8 @@ export class ClearCoatBlock extends NodeMaterialBlock {
 
         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("indexOfRefraction", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("normalMapColor", NodeMaterialBlockConnectionPointTypes.Color3, 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);
@@ -49,6 +50,12 @@ export class ClearCoatBlock extends NodeMaterialBlock {
     }
 
     /**
+     * Defines if the F0 value should be remapped to account for the interface change in the material.
+     */
+    @editableInPropertyPage("Remap F0 on interface change", PropertyTypeForEdition.Boolean, "ADVANCED")
+    public remapF0OnInterfaceChange: boolean = true;
+
+    /**
      * Initialize the block and prepare the context for build
      * @param state defines the state that will be used for the build
      */
@@ -85,57 +92,50 @@ export class ClearCoatBlock extends NodeMaterialBlock {
     /**
      * Gets the ior input component
      */
-    public get ior(): NodeMaterialConnectionPoint {
+    public get indexOfRefraction(): 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];
+    public get normalMapColor(): NodeMaterialConnectionPoint {
+        return this._inputs[3];
     }
 
     /**
      * Gets the uv input component
      */
     public get uv(): NodeMaterialConnectionPoint {
-        return this._inputs[5];
+        return this._inputs[4];
     }
 
     /**
      * Gets the tint color input component
      */
     public get tintColor(): NodeMaterialConnectionPoint {
-        return this._inputs[6];
+        return this._inputs[5];
     }
 
     /**
      * Gets the tint "at distance" input component
      */
     public get tintAtDistance(): NodeMaterialConnectionPoint {
-        return this._inputs[7];
+        return this._inputs[6];
     }
 
     /**
      * Gets the tint thickness input component
      */
     public get tintThickness(): NodeMaterialConnectionPoint {
-        return this._inputs[8];
+        return this._inputs[7];
     }
 
     /**
      * Gets the world tangent input component
      */
     public get worldTangent(): NodeMaterialConnectionPoint {
-        return this._inputs[9];
+        return this._inputs[8];
     }
 
     /**
@@ -157,18 +157,19 @@ export class ClearCoatBlock extends NodeMaterialBlock {
         super.prepareDefines(mesh, nodeMaterial, defines);
 
         defines.setValue("CLEARCOAT", true);
-        defines.setValue("CLEARCOAT_TEXTURE", this.texture.isConnected, true);
+        defines.setValue("CLEARCOAT_TEXTURE", false, true);
         defines.setValue("CLEARCOAT_USE_ROUGHNESS_FROM_MAINTEXTURE", true, true);
         defines.setValue("CLEARCOAT_TINT", this.tintColor.isConnected || this.tintThickness.isConnected || this.tintAtDistance.isConnected, true);
-        defines.setValue("CLEARCOAT_BUMP", this.bumpTexture.isConnected, true);
-        defines.setValue("CLEARCOAT_DEFAULTIOR", this.ior.isConnected ? this.ior.connectInputBlock!.value === 1.5 : false, true);
+        defines.setValue("CLEARCOAT_BUMP", this.normalMapColor.isConnected, true);
+        defines.setValue("CLEARCOAT_DEFAULTIOR", this.indexOfRefraction.isConnected ? this.indexOfRefraction.connectInputBlock!.value === PBRClearCoatConfiguration._DefaultIndexOfRefraction : true, true);
+        defines.setValue("CLEARCOAT_REMAP_F0", this.remapF0OnInterfaceChange, true);
     }
 
     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 indexOfRefraction = this.indexOfRefraction.connectInputBlock?.value ?? PBRClearCoatConfiguration._DefaultIndexOfRefraction;
 
         const a = 1 - indexOfRefraction;
         const b = 1 + indexOfRefraction;
@@ -230,8 +231,7 @@ export class ClearCoatBlock extends NodeMaterialBlock {
 
         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 normalMapColor = ccBlock?.normalMapColor.isConnected ? ccBlock.normalMapColor.associatedVariableName : "vec3(0.)";
         const uv = ccBlock?.uv.isConnected ? ccBlock.uv.associatedVariableName : "vec2(0.)";
 
         const tintColor = ccBlock?.tintColor.isConnected ? ccBlock.tintColor.associatedVariableName : "vec3(1.)";
@@ -262,7 +262,7 @@ export class ClearCoatBlock extends NodeMaterialBlock {
                 vClearCoatParams,
                 specularEnvironmentR0,
             #ifdef CLEARCOAT_TEXTURE
-                ${texture}.rg,
+                vec2(0.),
             #endif
             #ifdef CLEARCOAT_TINT
                 vClearCoatTintParams,
@@ -274,7 +274,7 @@ export class ClearCoatBlock extends NodeMaterialBlock {
             #endif
             #ifdef CLEARCOAT_BUMP
                 vec2(0., 1.),
-                ${bumpTexture},
+                vec4(${normalMapColor}, 0.),
                 ${uv},
                 #if defined(${vTBNAvailable ? "TANGENT" : "IGNORE"}) && defined(NORMAL)
                     vTBN,
@@ -332,6 +332,28 @@ export class ClearCoatBlock extends NodeMaterialBlock {
 
         return this;
     }
+
+    protected _dumpPropertiesCode() {
+        let codeString: string = "";
+
+        codeString += `${this._codeVariableName}.remapF0OnInterfaceChange = ${this.remapF0OnInterfaceChange};\r\n`;
+
+        return codeString;
+    }
+
+    public serialize(): any {
+        let serializationObject = super.serialize();
+
+        serializationObject.remapF0OnInterfaceChange = this.remapF0OnInterfaceChange;
+
+        return serializationObject;
+    }
+
+    public _deserialize(serializationObject: any, scene: Scene, rootUrl: string) {
+        super._deserialize(serializationObject, scene, rootUrl);
+
+        this.remapF0OnInterfaceChange = serializationObject.remapF0OnInterfaceChange ?? true;
+    }
 }
 
 _TypeStore.RegisteredTypes["BABYLON.ClearCoatBlock"] = ClearCoatBlock;

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

@@ -1,7 +1,5 @@
 export * from "./pbrMetallicRoughnessBlock";
 export * from "./sheenBlock";
-export * from "./ambientOcclusionBlock";
-export * from "./reflectivityBlock";
 export * from "./anisotropyBlock";
 export * from "./reflectionBlock";
 export * from "./clearCoatBlock";

+ 201 - 117
src/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.ts

@@ -17,9 +17,7 @@ import { PBRBaseMaterial } from '../../../PBR/pbrBaseMaterial';
 import { Scene } from '../../../../scene';
 import { editableInPropertyPage, PropertyTypeForEdition } from "../../nodeMaterialDecorator";
 import { NodeMaterialConnectionPointCustomObject } from "../../nodeMaterialConnectionPointCustomObject";
-import { AmbientOcclusionBlock } from './ambientOcclusionBlock';
 import { SheenBlock } from './sheenBlock';
-import { ReflectivityBlock } from './reflectivityBlock';
 import { BaseTexture } from '../../../Textures/baseTexture';
 import { BRDFTextureTools } from '../../../../Misc/brdfTextureTools';
 import { MaterialFlags } from '../../../materialFlags';
@@ -30,6 +28,7 @@ import { SubSurfaceBlock } from './subSurfaceBlock';
 import { RefractionBlock } from './refractionBlock';
 import { PerturbNormalBlock } from '../Fragment/perturbNormalBlock';
 import { Constants } from '../../../../Engines/constants';
+import { Color3, TmpColors } from '../../../../Maths/math.color';
 
 const mapOutputToVariable: { [name: string] : [string, string] } = {
     "ambient":      ["finalAmbient", ""],
@@ -62,6 +61,9 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
     private _environmentBrdfSamplerName: string;
     private _vNormalWName: string;
     private _invertNormalName: string;
+    private _metallicReflectanceColor: Color3 = Color3.White();
+    private _metallicF0Factor = 1;
+    private _vMetallicReflectanceFactorsName: string;
 
     /**
      * Create a new ReflectionBlock
@@ -74,36 +76,36 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
 
         this.registerInput("worldPosition", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Vertex);
         this.registerInput("worldNormal", NodeMaterialBlockConnectionPointTypes.Vector4, false, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("perturbedNormal", NodeMaterialBlockConnectionPointTypes.Vector4, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("view", NodeMaterialBlockConnectionPointTypes.Matrix, false);
         this.registerInput("cameraPosition", NodeMaterialBlockConnectionPointTypes.Vector3, false, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("baseColor", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("opacityTexture", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("perturbedNormal", NodeMaterialBlockConnectionPointTypes.Vector4, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("baseColor", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("metallic", NodeMaterialBlockConnectionPointTypes.Float, false, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("roughness", NodeMaterialBlockConnectionPointTypes.Float, false, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("ambientOcc", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("opacity", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("indexOfRefraction", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("ambientColor", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("reflectivity", NodeMaterialBlockConnectionPointTypes.Object, false, NodeMaterialBlockTargets.Fragment,
-            new NodeMaterialConnectionPointCustomObject("reflectivity", this, NodeMaterialConnectionPointDirection.Input, ReflectivityBlock, "ReflectivityBlock"));
-        this.registerInput("ambientOcc", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
-            new NodeMaterialConnectionPointCustomObject("ambientOcc", this, NodeMaterialConnectionPointDirection.Input, AmbientOcclusionBlock, "AOBlock"));
         this.registerInput("reflection", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
             new NodeMaterialConnectionPointCustomObject("reflection", this, NodeMaterialConnectionPointDirection.Input, ReflectionBlock, "ReflectionBlock"));
-        this.registerInput("sheen", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
-            new NodeMaterialConnectionPointCustomObject("sheen", this, NodeMaterialConnectionPointDirection.Input, SheenBlock, "SheenBlock"));
         this.registerInput("clearcoat", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
             new NodeMaterialConnectionPointCustomObject("clearcoat", this, NodeMaterialConnectionPointDirection.Input, ClearCoatBlock, "ClearCoatBlock"));
+        this.registerInput("sheen", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
+            new NodeMaterialConnectionPointCustomObject("sheen", this, NodeMaterialConnectionPointDirection.Input, SheenBlock, "SheenBlock"));
         this.registerInput("subsurface", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
             new NodeMaterialConnectionPointCustomObject("subsurface", this, NodeMaterialConnectionPointDirection.Input, SubSurfaceBlock, "SubSurfaceBlock"));
         this.registerInput("anisotropy", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
             new NodeMaterialConnectionPointCustomObject("anisotropy", this, NodeMaterialConnectionPointDirection.Input, AnisotropyBlock, "AnisotropyBlock"));
-        this.registerInput("view", NodeMaterialBlockConnectionPointTypes.Matrix, true);
 
-        this.registerOutput("ambient", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
-        this.registerOutput("diffuse", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
-        this.registerOutput("specular", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
-        this.registerOutput("sheenDir", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
+        this.registerOutput("ambientClr", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
+        this.registerOutput("diffuseDir", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
+        this.registerOutput("specularDir", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("clearcoatDir", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
+        this.registerOutput("sheenDir", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("diffuseInd", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("specularInd", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
-        this.registerOutput("sheenInd", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("clearcoatInd", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
+        this.registerOutput("sheenInd", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("refraction", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("lighting", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Fragment);
         this.registerOutput("shadow", NodeMaterialBlockConnectionPointTypes.Float, NodeMaterialBlockTargets.Fragment);
@@ -143,37 +145,24 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
     public lightFalloff = 0;
 
     /**
-     * Specifies that the alpha is coming form the albedo channel alpha channel for alpha blending.
-     */
-    @editableInPropertyPage("Alpha from albedo", PropertyTypeForEdition.Boolean, "TRANSPARENCY", { "notifiers": { "update": true }})
-    public useAlphaFromAlbedoTexture: boolean = false;
-
-    /**
      * Specifies that alpha test should be used
      */
-    @editableInPropertyPage("Alpha Testing", PropertyTypeForEdition.Boolean, "TRANSPARENCY")
+    @editableInPropertyPage("Alpha Testing", PropertyTypeForEdition.Boolean, "OPACITY")
     public useAlphaTest: boolean = false;
 
     /**
      * Defines the alpha limits in alpha test mode.
      */
-    @editableInPropertyPage("Alpha CutOff", PropertyTypeForEdition.Float, "TRANSPARENCY", { min: 0, max: 1, "notifiers": { "update": true }})
+    @editableInPropertyPage("Alpha CutOff", PropertyTypeForEdition.Float, "OPACITY", { min: 0, max: 1, "notifiers": { "update": true }})
     public alphaTestCutoff: number = 0.5;
 
     /**
      * Specifies that alpha blending should be used
      */
-    @editableInPropertyPage("Alpha blending", PropertyTypeForEdition.Boolean, "TRANSPARENCY")
+    @editableInPropertyPage("Alpha blending", PropertyTypeForEdition.Boolean, "OPACITY")
     public useAlphaBlending: boolean = false;
 
     /**
-     * Defines if the alpha value should be determined via the rgb values.
-     * If true the luminance of the pixel might be used to find the corresponding alpha value.
-     */
-    @editableInPropertyPage("Get alpha from opacity texture RGB", PropertyTypeForEdition.Boolean, "TRANSPARENCY", { "notifiers": { "update": true }})
-    public opacityRGB: boolean = false;
-
-    /**
      * Specifies that the material will keeps the reflection highlights over a transparent surface (only the most luminous ones).
      * A car glass is a good exemple of that. When the street lights reflects on it you can not see what is behind.
      */
@@ -264,18 +253,8 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         { label: "Anisotropic Tangents", value: 12 },
         { label: "Anisotropic Bitangents", value: 13 },
         // Maps
-        { label: "Albedo Map", value: 20 },
-        { label: "Ambient Map", value: 21 },
-        { label: "Opacity Map", value: 22 },
         //{ label: "Emissive Map", value: 23 },
         //{ label: "Light Map", value: 24 },
-        { label: "Metallic Map", value: 25 },
-        { label: "Reflectivity Map", value: 26 },
-        { label: "ClearCoat Map", value: 27 },
-        { label: "ClearCoat Tint Map", value: 28 },
-        { label: "Sheen Map", value: 29 },
-        { label: "Anisotropic Map", value: 30 },
-        { label: "Thickness Map", value: 31 },
         // Env
         { label: "Env Refraction", value: 40 },
         { label: "Env Reflection", value: 41 },
@@ -342,6 +321,13 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         state._excludeVariableName("surfaceAlbedo");
         state._excludeVariableName("alpha");
 
+        state._excludeVariableName("aoOut");
+
+        state._excludeVariableName("baseColor");
+        state._excludeVariableName("reflectivityOut");
+        state._excludeVariableName("microSurface");
+        state._excludeVariableName("roughness");
+
         state._excludeVariableName("NdotVUnclamped");
         state._excludeVariableName("NdotV");
         state._excludeVariableName("alphaG");
@@ -394,9 +380,9 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
     }
 
     /**
-     * Gets the perturbed normal input component
+     * Gets the view matrix parameter
      */
-    public get perturbedNormal(): NodeMaterialConnectionPoint {
+    public get view(): NodeMaterialConnectionPoint {
         return this._inputs[2];
     }
 
@@ -408,114 +394,128 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
     }
 
     /**
-     * Gets the base color input component
+     * Gets the perturbed normal input component
      */
-    public get baseColor(): NodeMaterialConnectionPoint {
+    public get perturbedNormal(): NodeMaterialConnectionPoint {
         return this._inputs[4];
     }
 
     /**
-     * Gets the opacity texture input component
+     * Gets the base color input component
      */
-    public get opacityTexture(): NodeMaterialConnectionPoint {
+    public get baseColor(): NodeMaterialConnectionPoint {
         return this._inputs[5];
     }
 
     /**
-     * Gets the ambient color input component
+     * Gets the metallic input component
      */
-    public get ambientColor(): NodeMaterialConnectionPoint {
+    public get metallic(): NodeMaterialConnectionPoint {
         return this._inputs[6];
     }
 
     /**
-     * Gets the reflectivity object parameters
+     * Gets the roughness input component
      */
-    public get reflectivity(): NodeMaterialConnectionPoint {
+    public get roughness(): NodeMaterialConnectionPoint {
         return this._inputs[7];
     }
 
     /**
-     * Gets the ambient occlusion object parameters
+     * Gets the ambient occlusion input component
      */
     public get ambientOcc(): NodeMaterialConnectionPoint {
         return this._inputs[8];
     }
 
     /**
-     * Gets the reflection object parameters
+     * Gets the opacity input component
      */
-    public get reflection(): NodeMaterialConnectionPoint {
+    public get opacity(): NodeMaterialConnectionPoint {
         return this._inputs[9];
     }
 
     /**
-     * Gets the sheen object parameters
+     * Gets the index of refraction input component
      */
-    public get sheen(): NodeMaterialConnectionPoint {
+    public get indexOfRefraction(): NodeMaterialConnectionPoint {
         return this._inputs[10];
     }
 
     /**
-     * Gets the clear coat object parameters
+     * Gets the ambient color input component
      */
-    public get clearcoat(): NodeMaterialConnectionPoint {
+    public get ambientColor(): NodeMaterialConnectionPoint {
         return this._inputs[11];
     }
 
     /**
-     * Gets the sub surface object parameters
+     * Gets the reflection object parameters
      */
-    public get subsurface(): NodeMaterialConnectionPoint {
+    public get reflection(): NodeMaterialConnectionPoint {
         return this._inputs[12];
     }
 
     /**
-     * Gets the anisotropy object parameters
+     * Gets the clear coat object parameters
      */
-    public get anisotropy(): NodeMaterialConnectionPoint {
+    public get clearcoat(): NodeMaterialConnectionPoint {
         return this._inputs[13];
     }
 
     /**
-     * Gets the view matrix parameter
+     * Gets the sheen object parameters
      */
-    public get view(): NodeMaterialConnectionPoint {
+    public get sheen(): NodeMaterialConnectionPoint {
         return this._inputs[14];
     }
 
     /**
+     * Gets the sub surface object parameters
+     */
+    public get subsurface(): NodeMaterialConnectionPoint {
+        return this._inputs[15];
+    }
+
+    /**
+     * Gets the anisotropy object parameters
+     */
+    public get anisotropy(): NodeMaterialConnectionPoint {
+        return this._inputs[16];
+    }
+
+    /**
      * Gets the ambient output component
      */
-    public get ambient(): NodeMaterialConnectionPoint {
+    public get ambientClr(): NodeMaterialConnectionPoint {
         return this._outputs[0];
     }
 
     /**
      * Gets the diffuse output component
      */
-    public get diffuse(): NodeMaterialConnectionPoint {
+    public get diffuseDir(): NodeMaterialConnectionPoint {
         return this._outputs[1];
     }
 
     /**
      * Gets the specular output component
      */
-    public get specular(): NodeMaterialConnectionPoint {
+    public get specularDir(): NodeMaterialConnectionPoint {
         return this._outputs[2];
     }
 
     /**
-     * Gets the sheen output component
+     * Gets the clear coat output component
      */
-    public get sheenDir(): NodeMaterialConnectionPoint {
+    public get clearcoatDir(): NodeMaterialConnectionPoint {
         return this._outputs[3];
     }
 
     /**
-     * Gets the clear coat output component
+     * Gets the sheen output component
      */
-    public get clearcoatDir(): NodeMaterialConnectionPoint {
+    public get sheenDir(): NodeMaterialConnectionPoint {
         return this._outputs[4];
     }
 
@@ -534,16 +534,16 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
     }
 
     /**
-     * Gets the indirect sheen output component
+     * Gets the indirect clear coat output component
      */
-    public get sheenIndirect(): NodeMaterialConnectionPoint {
+    public get clearcoatIndirect(): NodeMaterialConnectionPoint {
         return this._outputs[7];
     }
 
     /**
-     * Gets the indirect clear coat output component
+     * Gets the indirect sheen output component
      */
-    public get clearcoatIndirect(): NodeMaterialConnectionPoint {
+    public get sheenIndirect(): NodeMaterialConnectionPoint {
         return this._outputs[8];
     }
 
@@ -585,6 +585,16 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
             }
             cameraPositionInput.output.connectTo(this.cameraPosition);
         }
+
+        if (!this.view.isConnected) {
+            let viewInput = material.getInputBlockByPredicate((b) => b.systemValue === NodeMaterialSystemValues.View);
+
+            if (!viewInput) {
+                viewInput = new InputBlock("view");
+                viewInput.setAsSystemValue(NodeMaterialSystemValues.View);
+            }
+            viewInput.output.connectTo(this.view);
+        }
     }
 
     public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
@@ -597,7 +607,19 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         defines.setValue("LODBASEDMICROSFURACE", this._scene.getEngine().getCaps().textureLOD);
 
         // Albedo & Opacity
-        defines.setValue("OPACITY", this.opacityTexture.isConnected, true);
+        defines.setValue("ALBEDO", false, true);
+        defines.setValue("OPACITY", this.opacity.isConnected, true);
+
+        // Ambient occlusion
+        defines.setValue("AMBIENT", true, true);
+        defines.setValue("AMBIENTINGRAYSCALE", false, true);
+
+        // Reflectivity
+        defines.setValue("REFLECTIVITY", false, true);
+        defines.setValue("AOSTOREINMETALMAPRED", false, true);
+        defines.setValue("METALLNESSSTOREINMETALMAPBLUE", false, true);
+        defines.setValue("ROUGHNESSSTOREINMETALMAPALPHA", false, true);
+        defines.setValue("ROUGHNESSSTOREINMETALMAPGREEN",  false, true);
 
         // Lighting & colors
         if (this.lightFalloff === PBRBaseMaterial.LIGHTFALLOFF_STANDARD) {
@@ -612,11 +634,13 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         }
 
         // Transparency
+        const alphaTestCutOffString = this.alphaTestCutoff.toString();
+
         defines.setValue("ALPHABLEND", this.useAlphaBlending, true);
-        defines.setValue("ALPHAFROMALBEDO", this.useAlphaFromAlbedoTexture, true);
+        defines.setValue("ALPHAFROMALBEDO", false, true);
         defines.setValue("ALPHATEST", this.useAlphaTest, true);
-        defines.setValue("ALPHATESTVALUE", this.alphaTestCutoff, true);
-        defines.setValue("OPACITYRGB", this.opacityRGB, true);
+        defines.setValue("ALPHATESTVALUE", alphaTestCutOffString.indexOf('.') < 0 ? alphaTestCutOffString + "." : alphaTestCutOffString, true);
+        defines.setValue("OPACITYRGB", false, true);
 
         // Rendering
         defines.setValue("RADIANCEOVERALPHA", this.useRadianceOverAlpha, true);
@@ -713,6 +737,21 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         effect.setFloat(this._invertNormalName, invertNormal ? -1 : 1);
 
         effect.setFloat4("vLightingIntensity", this.directIntensity, 1, this.environmentIntensity * this._scene.environmentIntensity, this.specularIntensity);
+
+        // reflectivity bindings
+        const outside_ior = 1; // consider air as clear coat and other layers would remap in the shader.
+        const ior = this.indexOfRefraction.connectInputBlock?.value ?? 1.5;
+
+        // We are here deriving our default reflectance from a common value for none metallic surface.
+        // Based of the schlick fresnel approximation model
+        // for dielectrics.
+        const f0 = Math.pow((ior - outside_ior) / (ior + outside_ior), 2);
+
+        // Tweak the default F0 and F90 based on our given setup
+        this._metallicReflectanceColor.scaleToRef(f0 * this._metallicF0Factor, TmpColors.Color3[0]);
+        const metallicF90 = this._metallicF0Factor;
+
+        effect.setColor4(this._vMetallicReflectanceFactorsName, TmpColors.Color3[0], metallicF90);
     }
 
     private _injectVertexCode(state: NodeMaterialBuildState) {
@@ -744,6 +783,10 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
 
         const reflectionBlock = this.reflection.isConnected ? this.reflection.connectedPoint?.ownerBlock as ReflectionBlock : null;
 
+        if (reflectionBlock) {
+            reflectionBlock.viewConnectionPoint = this.view;
+        }
+
         state.compilationString += reflectionBlock?.handleVertexSide(state) ?? "";
 
         state._emitUniformFromString("vDebugMode", "vec2", "defined(IGNORE) || DEBUGMODE > 0");
@@ -773,24 +816,20 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         }
     }
 
-    /**
-     * Gets the code corresponding to the albedo/opacity module
-     * @returns the shader code
-     */
-    public getAlbedoOpacityCode(): string {
+    private _getAlbedoOpacityCode(): string {
         let code = `albedoOpacityOutParams albedoOpacityOut;\r\n`;
 
-        const albedoColor = this.baseColor.isConnected ? this.baseColor.associatedVariableName : "vec4(1., 1., 1., 1.)";
-        const opacityTexture = this.opacityTexture.isConnected ? this.opacityTexture.associatedVariableName : "";
+        const albedoColor = this.baseColor.isConnected ? this.baseColor.associatedVariableName : "vec3(1.)";
+        const opacity = this.opacity.isConnected ? this.opacity.associatedVariableName : "1.";
 
         code += `albedoOpacityBlock(
-                ${albedoColor},
+                vec4(${albedoColor}, 1.),
             #ifdef ALBEDO
                 vec4(1.),
                 vec2(1., 1.),
             #endif
             #ifdef OPACITY
-                ${opacityTexture},
+                vec4(${opacity}),
                 vec2(1., 1.),
             #endif
                 albedoOpacityOut
@@ -802,6 +841,64 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         return code;
     }
 
+    private _getAmbientOcclusionCode(): string {
+        let code = `ambientOcclusionOutParams aoOut;\r\n`;
+
+        const ao = this.ambientOcc.isConnected ? this.ambientOcc.associatedVariableName : "1.";
+
+        code += `ambientOcclusionBlock(
+            #ifdef AMBIENT
+                vec3(${ao}),
+                vec4(0., 1.0, 1.0, 0.),
+            #endif
+                aoOut
+            );\r\n`;
+
+        return code;
+    }
+
+    private _getReflectivityCode(state: NodeMaterialBuildState): string {
+        let code = `reflectivityOutParams reflectivityOut;\r\n`;
+
+        const aoIntensity = "1.";
+
+        this._vMetallicReflectanceFactorsName = state._getFreeVariableName("vMetallicReflectanceFactors");
+        state._emitUniformFromString(this._vMetallicReflectanceFactorsName, "vec4");
+
+        code += `vec3 baseColor = surfaceAlbedo;
+
+            reflectivityBlock(
+                vec4(${this.metallic.associatedVariableName}, ${this.roughness.associatedVariableName}, 0., 0.),
+            #ifdef METALLICWORKFLOW
+                surfaceAlbedo,
+                ${this._vMetallicReflectanceFactorsName},
+            #endif
+            #ifdef REFLECTIVITY
+                vec3(0., 0., ${aoIntensity}),
+                vec4(1.),
+            #endif
+            #if defined(METALLICWORKFLOW) && defined(REFLECTIVITY)  && defined(AOSTOREINMETALMAPRED)
+                aoOut.ambientOcclusionColor,
+            #endif
+            #ifdef MICROSURFACEMAP
+                microSurfaceTexel, <== not handled!
+            #endif
+                reflectivityOut
+            );
+
+            float microSurface = reflectivityOut.microSurface;
+            float roughness = reflectivityOut.roughness;
+
+            #ifdef METALLICWORKFLOW
+                surfaceAlbedo = reflectivityOut.surfaceAlbedo;
+            #endif
+            #if defined(METALLICWORKFLOW) && defined(REFLECTIVITY) && defined(AOSTOREINMETALMAPRED)
+                aoOut.ambientOcclusionColor = reflectivityOut.ambientOcclusionColor;
+            #endif\r\n`;
+
+        return code;
+    }
+
     protected _buildBlock(state: NodeMaterialBuildState) {
         super._buildBlock(state);
 
@@ -923,36 +1020,22 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         });
 
         // _____________________________ Albedo & Opacity ______________________________
-        state.compilationString += this.getAlbedoOpacityCode();
+        state.compilationString += this._getAlbedoOpacityCode();
 
         state.compilationString += state._emitCodeFromInclude("depthPrePass", comments);
 
         // _____________________________ AO  _______________________________
-        const aoBlock = this.ambientOcc.connectedPoint?.ownerBlock as Nullable<AmbientOcclusionBlock>;
-
-        state.compilationString += AmbientOcclusionBlock.GetCode(aoBlock);
+        state.compilationString += this._getAmbientOcclusionCode();
 
         state.compilationString += state._emitCodeFromInclude("pbrBlockLightmapInit", comments);
 
         // _____________________________ UNLIT  _______________________________
-
         state.compilationString += `#ifdef UNLIT
                 vec3 diffuseBase = vec3(1., 1., 1.);
             #else\r\n`;
 
         // _____________________________ Reflectivity _______________________________
-        const subsurfaceBlock = this.subsurface.isConnected ? this.subsurface.connectedPoint?.ownerBlock as SubSurfaceBlock : null;
-        const refractionBlock = this.subsurface.isConnected ? (this.subsurface.connectedPoint?.ownerBlock as SubSurfaceBlock).refraction.connectedPoint?.ownerBlock as RefractionBlock : null;
-
-        const reflectivityBlock = this.reflectivity.connectedPoint?.ownerBlock as Nullable<ReflectivityBlock> ?? null;
-
-        if (reflectivityBlock) {
-            reflectivityBlock.indexOfRefractionConnectionPoint = refractionBlock?.indexOfRefraction ?? null;
-        }
-
-        const aoIntensity = aoBlock?.intensity.isConnected ? aoBlock.intensity.associatedVariableName : "1.";
-
-        state.compilationString += reflectivityBlock?.getCode(state, aoIntensity) ?? "";
+        state.compilationString += this._getReflectivityCode(state);
 
         // _____________________________ Geometry info _________________________________
         state.compilationString += state._emitCodeFromInclude("pbrBlockGeometryInfo", comments, {
@@ -993,7 +1076,7 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         // ___________________ Compute Reflectance aka R0 F0 info _________________________
         state.compilationString += state._emitCodeFromInclude("pbrBlockReflectance0", comments, {
             replaceStrings: [
-                { search: /metallicReflectanceFactors/g, replace: reflectivityBlock?._vMetallicReflectanceFactorsName ?? "metallicReflectanceFactors" },
+                { search: /metallicReflectanceFactors/g, replace: this._vMetallicReflectanceFactorsName },
             ]
         });
         // ________________________________ Sheen ______________________________
@@ -1047,6 +1130,14 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         });
 
         // ___________________________________ SubSurface ______________________________________
+        const subsurfaceBlock = this.subsurface.isConnected ? this.subsurface.connectedPoint?.ownerBlock as SubSurfaceBlock : null;
+        const refractionBlock = this.subsurface.isConnected ? (this.subsurface.connectedPoint?.ownerBlock as SubSurfaceBlock).refraction.connectedPoint?.ownerBlock as RefractionBlock : null;
+
+        if (refractionBlock) {
+            refractionBlock.viewConnectionPoint = this.view;
+            refractionBlock.indexOfRefractionConnectionPoint = this.indexOfRefraction;
+        }
+
         state.compilationString += SubSurfaceBlock.GetCode(state, subsurfaceBlock, reflectionBlock, worldPosVarName);
 
         state._emitFunctionFromInclude("pbrBlockSubSurface", comments, {
@@ -1085,9 +1176,9 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         // _____________________________ Compute Final Unlit Components ________________________
         const aoColor = this.ambientColor.isConnected ? this.ambientColor.associatedVariableName : "vec3(0., 0., 0.)";
 
-        let aoDirectLightIntensity = aoBlock?.directLightIntensity.isConnected ? aoBlock.directLightIntensity.associatedVariableName : PBRBaseMaterial.DEFAULT_AO_ON_ANALYTICAL_LIGHTS.toString();
+        let aoDirectLightIntensity = PBRBaseMaterial.DEFAULT_AO_ON_ANALYTICAL_LIGHTS.toString();
 
-        if (!aoBlock?.directLightIntensity.isConnected && aoDirectLightIntensity.indexOf('.') === -1) {
+        if (aoDirectLightIntensity.indexOf('.') === -1) {
             aoDirectLightIntensity += ".";
         }
 
@@ -1119,7 +1210,6 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
                 { search: /vNormalW/g, replace: this._vNormalWName },
                 { search: /vPositionW/g, replace: worldPosVarName },
                 { search: /albedoTexture\.rgb;/g, replace: "vec3(1.);\r\ngl_FragColor.rgb = toGammaSpace(gl_FragColor.rgb);\r\n" },
-                { search: /opacityMap/g, replace: this.opacityTexture.associatedVariableName },
             ]
         });
 
@@ -1151,11 +1241,9 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         let codeString: string = "";
 
         codeString += `${this._codeVariableName}.lightFalloff = ${this.lightFalloff};\r\n`;
-        codeString += `${this._codeVariableName}.useAlphaFromAlbedoTexture = ${this.useAlphaFromAlbedoTexture};\r\n`;
         codeString += `${this._codeVariableName}.useAlphaTest = ${this.useAlphaTest};\r\n`;
         codeString += `${this._codeVariableName}.alphaTestCutoff = ${this.alphaTestCutoff};\r\n`;
         codeString += `${this._codeVariableName}.useAlphaBlending = ${this.useAlphaBlending};\r\n`;
-        codeString += `${this._codeVariableName}.opacityRGB = ${this.opacityRGB};\r\n`;
         codeString += `${this._codeVariableName}.useRadianceOverAlpha = ${this.useRadianceOverAlpha};\r\n`;
         codeString += `${this._codeVariableName}.useSpecularOverAlpha = ${this.useSpecularOverAlpha};\r\n`;
         codeString += `${this._codeVariableName}.enableSpecularAntiAliasing = ${this.enableSpecularAntiAliasing};\r\n`;
@@ -1181,11 +1269,9 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         }
 
         serializationObject.lightFalloff = this.lightFalloff;
-        serializationObject.useAlphaFromAlbedoTexture = this.useAlphaFromAlbedoTexture;
         serializationObject.useAlphaTest = this.useAlphaTest;
         serializationObject.alphaTestCutoff = this.alphaTestCutoff;
         serializationObject.useAlphaBlending = this.useAlphaBlending;
-        serializationObject.opacityRGB = this.opacityRGB;
         serializationObject.useRadianceOverAlpha = this.useRadianceOverAlpha;
         serializationObject.useSpecularOverAlpha = this.useSpecularOverAlpha;
         serializationObject.enableSpecularAntiAliasing = this.enableSpecularAntiAliasing;
@@ -1211,11 +1297,9 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         }
 
         this.lightFalloff = serializationObject.lightFalloff ?? 0;
-        this.useAlphaFromAlbedoTexture = serializationObject.useAlphaFromAlbedoTexture;
         this.useAlphaTest = serializationObject.useAlphaTest;
         this.alphaTestCutoff = serializationObject.alphaTestCutoff;
         this.useAlphaBlending = serializationObject.useAlphaBlending;
-        this.opacityRGB = serializationObject.opacityRGB;
         this.useRadianceOverAlpha = serializationObject.useRadianceOverAlpha;
         this.useSpecularOverAlpha = serializationObject.useSpecularOverAlpha;
         this.enableSpecularAntiAliasing = serializationObject.enableSpecularAntiAliasing;

+ 5 - 4
src/Materials/Node/Blocks/PBR/reflectionBlock.ts

@@ -36,7 +36,7 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
     private _scene: Scene;
 
     /**
-     * The three properties below are set by the main PBR block prior to calling methods of this class.
+     * The properties below are set by the main PBR block prior to calling methods of this class.
      * This is to avoid having to add them as inputs here whereas they are already inputs of the main block, so already known.
      * It's less burden on the user side in the editor part.
     */
@@ -47,6 +47,8 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
     public worldNormalConnectionPoint: NodeMaterialConnectionPoint;
     /** @hidden */
     public cameraPositionConnectionPoint: NodeMaterialConnectionPoint;
+    /** @hidden */
+    public viewConnectionPoint: NodeMaterialConnectionPoint;
 
     /**
      * Defines if the material uses spherical harmonics vs spherical polynomials for the
@@ -72,7 +74,6 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
 
         this.registerInput("position", NodeMaterialBlockConnectionPointTypes.Vector3, false, NodeMaterialBlockTargets.Vertex);
         this.registerInput("world", NodeMaterialBlockConnectionPointTypes.Matrix, false, NodeMaterialBlockTargets.Vertex);
-        this.registerInput("view", NodeMaterialBlockConnectionPointTypes.Matrix, false, NodeMaterialBlockTargets.Fragment);
         this.registerInput("color", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
 
         this.registerOutput("reflection", NodeMaterialBlockConnectionPointTypes.Object, NodeMaterialBlockTargets.Fragment,
@@ -126,14 +127,14 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
      * Gets the view input component
      */
     public get view(): NodeMaterialConnectionPoint {
-        return this._inputs[2];
+        return this.viewConnectionPoint;
     }
 
     /**
      * Gets the color input component
      */
     public get color(): NodeMaterialConnectionPoint {
-        return this._inputs[3];
+        return this._inputs[2];
     }
 
     /**

+ 0 - 243
src/Materials/Node/Blocks/PBR/reflectivityBlock.ts

@@ -1,243 +0,0 @@
-import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
-import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
-import { NodeMaterialBlock } from '../../nodeMaterialBlock';
-import { _TypeStore } from '../../../../Misc/typeStore';
-import { editableInPropertyPage, PropertyTypeForEdition } from "../../nodeMaterialDecorator";
-import { AbstractMesh } from '../../../../Meshes/abstractMesh';
-import { NodeMaterialBlockConnectionPointTypes } from '../../Enums/nodeMaterialBlockConnectionPointTypes';
-import { NodeMaterialBlockTargets } from '../../Enums/nodeMaterialBlockTargets';
-import { NodeMaterialConnectionPointCustomObject } from "../../nodeMaterialConnectionPointCustomObject";
-import { NodeMaterialConnectionPoint, NodeMaterialConnectionPointDirection } from '../../nodeMaterialBlockConnectionPoint';
-import { Scene } from '../../../../scene';
-import { Nullable } from '../../../../types';
-import { Color3 } from '../../../../Maths/math.color';
-import { TmpColors } from '../../../../Maths/math.color';
-import { Mesh } from '../../../../Meshes/mesh';
-import { SubMesh } from '../../../../Meshes/subMesh';
-import { Effect } from '../../../effect';
-
-/**
- * Block used to implement the reflectivity module of the PBR material
- */
-export class ReflectivityBlock extends NodeMaterialBlock {
-
-    private _metallicReflectanceColor: Color3 = Color3.White();
-    private _metallicF0Factor = 1;
-
-    /** @hidden */
-    public _vMetallicReflectanceFactorsName: string;
-
-    /**
-     * The property below is set by the main PBR block prior to calling methods of this class.
-    */
-
-    /** @hidden */
-    public indexOfRefractionConnectionPoint: Nullable<NodeMaterialConnectionPoint>;
-
-    /**
-     * Specifies if the metallic texture contains the ambient occlusion information in its red channel.
-     */
-    @editableInPropertyPage("AO from red channel", PropertyTypeForEdition.Boolean, "METALLIC WORKFLOW", { "notifiers": { "update": true }})
-    public useAmbientOcclusionFromMetallicTextureRed: boolean = false;
-
-    /**
-     * Specifies if the metallic texture contains the metallness information in its blue channel.
-     */
-    @editableInPropertyPage("Metallness from blue channel", PropertyTypeForEdition.Boolean, "METALLIC WORKFLOW", { "notifiers": { "update": true }})
-    public useMetallnessFromMetallicTextureBlue: boolean = true;
-
-    /**
-     * Specifies if the metallic texture contains the roughness information in its alpha channel.
-     */
-    @editableInPropertyPage("Roughness from alpha channel", PropertyTypeForEdition.Boolean, "METALLIC WORKFLOW", { "notifiers": { "update": true }})
-    public useRoughnessFromMetallicTextureAlpha: boolean = false;
-
-    /**
-     * Specifies if the metallic texture contains the roughness information in its green channel.
-     */
-    @editableInPropertyPage("Roughness from green channel", PropertyTypeForEdition.Boolean, "METALLIC WORKFLOW", { "notifiers": { "update": true }})
-    public useRoughnessFromMetallicTextureGreen: boolean = true;
-
-    /**
-     * Create a new ReflectivityBlock
-     * @param name defines the block name
-     */
-    public constructor(name: string) {
-        super(name, NodeMaterialBlockTargets.Fragment);
-
-        this._isUnique = true;
-
-        this.registerInput("metallic", NodeMaterialBlockConnectionPointTypes.Float, false, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("roughness", NodeMaterialBlockConnectionPointTypes.Float, false, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("texture", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
-
-        this.registerOutput("reflectivity", NodeMaterialBlockConnectionPointTypes.Object, NodeMaterialBlockTargets.Fragment,
-            new NodeMaterialConnectionPointCustomObject("reflectivity", this, NodeMaterialConnectionPointDirection.Output, ReflectivityBlock, "ReflectivityBlock"));
-    }
-
-    /**
-     * 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("baseColor");
-        state._excludeVariableName("reflectivityOut");
-        state._excludeVariableName("microSurface");
-        state._excludeVariableName("roughness");
-    }
-
-    /**
-     * Gets the current class name
-     * @returns the class name
-     */
-    public getClassName() {
-        return "ReflectivityBlock";
-    }
-
-    /**
-     * Gets the metallic input component
-     */
-    public get metallic(): NodeMaterialConnectionPoint {
-        return this._inputs[0];
-    }
-
-    /**
-     * Gets the roughness input component
-     */
-    public get roughness(): NodeMaterialConnectionPoint {
-        return this._inputs[1];
-    }
-
-    /**
-     * Gets the texture input component
-     */
-    public get texture(): NodeMaterialConnectionPoint {
-        return this._inputs[2];
-    }
-
-    /**
-     * Gets the reflectivity object output component
-     */
-    public get reflectivity(): NodeMaterialConnectionPoint {
-        return this._outputs[0];
-    }
-
-    public bind(effect: Effect, nodeMaterial: NodeMaterial, mesh?: Mesh, subMesh?: SubMesh) {
-        super.bind(effect, nodeMaterial, mesh);
-
-        const outside_ior = 1; // consider air as clear coat and other layers would remap in the shader.
-        const ior = this.indexOfRefractionConnectionPoint?.connectInputBlock?.value ?? 1.5;
-
-        // We are here deriving our default reflectance from a common value for none metallic surface.
-        // Based of the schlick fresnel approximation model
-        // for dielectrics.
-        const f0 = Math.pow((ior - outside_ior) / (ior + outside_ior), 2);
-
-        // Tweak the default F0 and F90 based on our given setup
-        this._metallicReflectanceColor.scaleToRef(f0 * this._metallicF0Factor, TmpColors.Color3[0]);
-        const metallicF90 = this._metallicF0Factor;
-
-        effect.setColor4(this._vMetallicReflectanceFactorsName, TmpColors.Color3[0], metallicF90);
-    }
-
-    /**
-     * Gets the main code of the block (fragment side)
-     * @param state current state of the node material building
-     * @param aoIntensityVarName name of the variable with the ambient occlusion intensity
-     * @returns the shader code
-     */
-    public getCode(state: NodeMaterialBuildState, aoIntensityVarName: string): string {
-        const metalRoughTexture = this.texture.isConnected ? this.texture.connectedPoint?.associatedVariableName : null;
-
-        this._vMetallicReflectanceFactorsName = state._getFreeVariableName("vMetallicReflectanceFactors");
-
-        state._emitUniformFromString(this._vMetallicReflectanceFactorsName, "vec4");
-
-        // note: metallic F0 factor = 1
-        let code = `vec3 baseColor = surfaceAlbedo;
-            reflectivityOutParams reflectivityOut;
-
-            reflectivityBlock(
-                vec4(${this.metallic.associatedVariableName}, ${this.roughness.associatedVariableName}, 0., 0.),
-            #ifdef METALLICWORKFLOW
-                surfaceAlbedo,
-                ${this._vMetallicReflectanceFactorsName},
-            #endif
-            #ifdef REFLECTIVITY
-                vec3(0., 0., ${aoIntensityVarName}),
-                ${metalRoughTexture},
-            #endif
-            #if defined(METALLICWORKFLOW) && defined(REFLECTIVITY)  && defined(AOSTOREINMETALMAPRED)
-                aoOut.ambientOcclusionColor,
-            #endif
-            #ifdef MICROSURFACEMAP
-                microSurfaceTexel, <== not handled!
-            #endif
-                reflectivityOut
-            );
-
-            float microSurface = reflectivityOut.microSurface;
-            float roughness = reflectivityOut.roughness;
-
-            #ifdef METALLICWORKFLOW
-                surfaceAlbedo = reflectivityOut.surfaceAlbedo;
-            #endif
-            #if defined(METALLICWORKFLOW) && defined(REFLECTIVITY) && defined(AOSTOREINMETALMAPRED)
-                aoOut.ambientOcclusionColor = reflectivityOut.ambientOcclusionColor;
-            #endif\r\n`;
-
-        return code;
-    }
-
-    public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
-        super.prepareDefines(mesh, nodeMaterial, defines);
-
-        defines.setValue("REFLECTIVITY", this.texture.isConnected, true);
-        defines.setValue("AOSTOREINMETALMAPRED", this.useAmbientOcclusionFromMetallicTextureRed, true);
-        defines.setValue("METALLNESSSTOREINMETALMAPBLUE", this.useMetallnessFromMetallicTextureBlue, true);
-        defines.setValue("ROUGHNESSSTOREINMETALMAPALPHA", this.useRoughnessFromMetallicTextureAlpha, true);
-        defines.setValue("ROUGHNESSSTOREINMETALMAPGREEN",  !this.useRoughnessFromMetallicTextureAlpha && this.useRoughnessFromMetallicTextureGreen, true);
-    }
-
-    protected _buildBlock(state: NodeMaterialBuildState) {
-        if (state.target === NodeMaterialBlockTargets.Fragment) {
-            state.sharedData.blocksWithDefines.push(this);
-            state.sharedData.bindableBlocks.push(this);
-        }
-
-        return this;
-    }
-
-    protected _dumpPropertiesCode() {
-        let codeString: string = "";
-
-        codeString += `${this._codeVariableName}.useAmbientOcclusionFromMetallicTextureRed = ${this.useAmbientOcclusionFromMetallicTextureRed};\r\n`;
-        codeString += `${this._codeVariableName}.useMetallnessFromMetallicTextureBlue = ${this.useMetallnessFromMetallicTextureBlue};\r\n`;
-        codeString += `${this._codeVariableName}.useRoughnessFromMetallicTextureAlpha = ${this.useRoughnessFromMetallicTextureAlpha};\r\n`;
-        codeString += `${this._codeVariableName}.useRoughnessFromMetallicTextureGreen = ${this.useRoughnessFromMetallicTextureGreen};\r\n`;
-
-        return codeString;
-    }
-
-    public serialize(): any {
-        let serializationObject = super.serialize();
-
-        serializationObject.useAmbientOcclusionFromMetallicTextureRed = this.useAmbientOcclusionFromMetallicTextureRed;
-        serializationObject.useMetallnessFromMetallicTextureBlue = this.useMetallnessFromMetallicTextureBlue;
-        serializationObject.useRoughnessFromMetallicTextureAlpha = this.useRoughnessFromMetallicTextureAlpha;
-        serializationObject.useRoughnessFromMetallicTextureGreen = this.useRoughnessFromMetallicTextureGreen;
-
-        return serializationObject;
-    }
-
-    public _deserialize(serializationObject: any, scene: Scene, rootUrl: string) {
-        super._deserialize(serializationObject, scene, rootUrl);
-
-        this.useAmbientOcclusionFromMetallicTextureRed = serializationObject.useAmbientOcclusionFromMetallicTextureRed;
-        this.useMetallnessFromMetallicTextureBlue = serializationObject.useMetallnessFromMetallicTextureBlue;
-        this.useRoughnessFromMetallicTextureAlpha = serializationObject.useRoughnessFromMetallicTextureAlpha;
-        this.useRoughnessFromMetallicTextureGreen = serializationObject.useRoughnessFromMetallicTextureGreen;
-    }
-}
-
-_TypeStore.RegisteredTypes["BABYLON.ReflectivityBlock"] = ReflectivityBlock;

+ 16 - 13
src/Materials/Node/Blocks/PBR/refractionBlock.ts

@@ -46,6 +46,18 @@ export class RefractionBlock extends NodeMaterialBlock {
     private _scene: Scene;
 
     /**
+     * The properties below are set by the main PBR block prior to calling methods of this class.
+     * This is to avoid having to add them as inputs here whereas they are already inputs of the main block, so already known.
+     * It's less burden on the user side in the editor part.
+    */
+
+    /** @hidden */
+    public viewConnectionPoint: NodeMaterialConnectionPoint;
+
+    /** @hidden */
+    public indexOfRefractionConnectionPoint: NodeMaterialConnectionPoint;
+
+    /**
      * This parameters will make the material used its opacity to control how much it is refracting aginst not.
      * Materials half opaque for instance using refraction could benefit from this control.
      */
@@ -73,9 +85,7 @@ export class RefractionBlock extends NodeMaterialBlock {
         this._isUnique = true;
 
         this.registerInput("intensity", NodeMaterialBlockConnectionPointTypes.Float, false, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("indexOfRefraction", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("tintAtDistance", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("view", NodeMaterialBlockConnectionPointTypes.Matrix, false, NodeMaterialBlockTargets.Fragment);
 
         this.registerOutput("refraction", NodeMaterialBlockConnectionPointTypes.Object, NodeMaterialBlockTargets.Fragment,
             new NodeMaterialConnectionPointCustomObject("refraction", this, NodeMaterialConnectionPointDirection.Output, RefractionBlock, "RefractionBlock"));
@@ -97,24 +107,17 @@ export class RefractionBlock extends NodeMaterialBlock {
     }
 
     /**
-     * Gets the index of refraction input component
-     */
-    public get indexOfRefraction(): NodeMaterialConnectionPoint {
-        return this._inputs[1];
-    }
-
-    /**
      * Gets the tint at distance input component
      */
     public get tintAtDistance(): NodeMaterialConnectionPoint {
-        return this._inputs[2];
+        return this._inputs[1];
     }
 
     /**
      * Gets the view input component
      */
     public get view(): NodeMaterialConnectionPoint {
-        return this._inputs[3];
+        return this.viewConnectionPoint;
     }
 
     /**
@@ -146,7 +149,7 @@ export class RefractionBlock extends NodeMaterialBlock {
             intensityInput.output.connectTo(this.intensity);
         }
 
-        if (!this.view.isConnected) {
+        if (this.view && !this.view.isConnected) {
             let viewInput = material.getInputBlockByPredicate((b) => b.systemValue === NodeMaterialSystemValues.View);
 
             if (!viewInput) {
@@ -213,7 +216,7 @@ export class RefractionBlock extends NodeMaterialBlock {
             }
         }
 
-        const indexOfRefraction = this.indexOfRefraction.connectInputBlock?.value ?? 1.5;
+        const indexOfRefraction = this.indexOfRefractionConnectionPoint.connectInputBlock?.value ?? 1.5;
 
         effect.setFloat4(this._vRefractionInfosName, refractionTexture.level, 1 / indexOfRefraction, depth, this.invertRefractionY ? -1 : 1);
 

+ 20 - 48
src/Materials/Node/Blocks/PBR/subSurfaceBlock.ts

@@ -4,7 +4,6 @@ import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
 import { NodeMaterialConnectionPoint, NodeMaterialConnectionPointDirection } from '../../nodeMaterialBlockConnectionPoint';
 import { NodeMaterialBlockTargets } from '../../Enums/nodeMaterialBlockTargets';
 import { _TypeStore } from '../../../../Misc/typeStore';
-import { editableInPropertyPage, PropertyTypeForEdition } from "../../nodeMaterialDecorator";
 import { InputBlock } from '../Input/inputBlock';
 import { NodeMaterialConnectionPointCustomObject } from "../../nodeMaterialConnectionPointCustomObject";
 import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
@@ -27,12 +26,10 @@ export class SubSurfaceBlock extends NodeMaterialBlock {
 
         this._isUnique = true;
 
-        this.registerInput("minThickness", NodeMaterialBlockConnectionPointTypes.Float, false, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("maxThickness", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("thicknessTexture", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("thickness", NodeMaterialBlockConnectionPointTypes.Float, false, NodeMaterialBlockTargets.Fragment);
         this.registerInput("tintColor", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("translucencyIntensity", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("translucencyDiffusionDistance", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("translucencyDiffusionDist", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("refraction", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment,
             new NodeMaterialConnectionPointCustomObject("refraction", this, NodeMaterialConnectionPointDirection.Input, RefractionBlock, "RefractionBlock"));
 
@@ -41,15 +38,6 @@ export class SubSurfaceBlock extends NodeMaterialBlock {
     }
 
     /**
-     * Stores the intensity of the different subsurface effects in the thickness texture.
-     * * the green channel is the translucency intensity.
-     * * the blue channel is the scattering intensity.
-     * * the alpha channel is the refraction intensity.
-     */
-    @editableInPropertyPage("Mask from thickness texture", PropertyTypeForEdition.Boolean, "PROPERTIES", { "notifiers": { "update": true }})
-    public useMaskFromThicknessTexture: boolean = false;
-
-    /**
      * Initialize the block and prepare the context for build
      * @param state defines the state that will be used for the build
      */
@@ -69,52 +57,38 @@ export class SubSurfaceBlock extends NodeMaterialBlock {
     }
 
     /**
-     * Gets the min thickness input component
+     * Gets the thickness component
      */
-    public get minThickness(): NodeMaterialConnectionPoint {
+    public get thickness(): NodeMaterialConnectionPoint {
         return this._inputs[0];
     }
 
     /**
-     * Gets the max thickness input component
-     */
-    public get maxThickness(): NodeMaterialConnectionPoint {
-        return this._inputs[1];
-    }
-
-    /**
-     * Gets the thickness texture component
-     */
-    public get thicknessTexture(): NodeMaterialConnectionPoint {
-        return this._inputs[2];
-    }
-
-    /**
      * Gets the tint color input component
      */
     public get tintColor(): NodeMaterialConnectionPoint {
-        return this._inputs[3];
+        return this._inputs[1];
     }
 
     /**
      * Gets the translucency intensity input component
      */
     public get translucencyIntensity(): NodeMaterialConnectionPoint {
-        return this._inputs[4];
+        return this._inputs[2];
     }
 
     /**
      * Gets the translucency diffusion distance input component
      */
-    public get translucencyDiffusionDistance(): NodeMaterialConnectionPoint {
-        return this._inputs[5];
+    public get translucencyDiffusionDist(): NodeMaterialConnectionPoint {
+        return this._inputs[3];
     }
 
     /**
      * Gets the refraction object parameters
      */
     public get refraction(): NodeMaterialConnectionPoint {
-        return this._inputs[6];
+        return this._inputs[4];
     }
 
     /**
@@ -125,22 +99,22 @@ export class SubSurfaceBlock extends NodeMaterialBlock {
     }
 
     public autoConfigure(material: NodeMaterial) {
-        if (!this.minThickness.isConnected) {
-            let minThicknessInput = new InputBlock("SubSurface min thickness", NodeMaterialBlockTargets.Fragment, NodeMaterialBlockConnectionPointTypes.Float);
-            minThicknessInput.value = 0;
-            minThicknessInput.output.connectTo(this.minThickness);
+        if (!this.thickness.isConnected) {
+            let thicknessInput = new InputBlock("SubSurface thickness", NodeMaterialBlockTargets.Fragment, NodeMaterialBlockConnectionPointTypes.Float);
+            thicknessInput.value = 0;
+            thicknessInput.output.connectTo(this.thickness);
         }
     }
 
     public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
         super.prepareDefines(mesh, nodeMaterial, defines);
 
-        const translucencyEnabled = this.translucencyDiffusionDistance.isConnected || this.translucencyIntensity.isConnected;
+        const translucencyEnabled = this.translucencyDiffusionDist.isConnected || this.translucencyIntensity.isConnected;
 
         defines.setValue("SUBSURFACE", translucencyEnabled || this.refraction.isConnected, true);
         defines.setValue("SS_TRANSLUCENCY", translucencyEnabled, true);
-        defines.setValue("SS_THICKNESSANDMASK_TEXTURE", this.thicknessTexture.isConnected, true);
-        defines.setValue("SS_MASK_FROM_THICKNESS_TEXTURE", this.useMaskFromThicknessTexture, true);
+        defines.setValue("SS_THICKNESSANDMASK_TEXTURE", false, true);
+        defines.setValue("SS_MASK_FROM_THICKNESS_TEXTURE", false, true);
     }
 
     /**
@@ -154,12 +128,10 @@ export class SubSurfaceBlock extends NodeMaterialBlock {
     public static GetCode(state: NodeMaterialBuildState, ssBlock: Nullable<SubSurfaceBlock>, reflectionBlock: Nullable<ReflectionBlock>, worldPosVarName: string): string {
         let code = "";
 
-        const minThickness = ssBlock?.minThickness.isConnected ? ssBlock.minThickness.associatedVariableName : "0.";
-        const maxThickness = ssBlock?.maxThickness.isConnected ? ssBlock.maxThickness.associatedVariableName : "1.";
-        const thicknessTexture = ssBlock?.thicknessTexture.isConnected ? ssBlock.thicknessTexture.associatedVariableName : "vec4(0.)";
+        const thickness = ssBlock?.thickness.isConnected ? ssBlock.thickness.associatedVariableName : "0.";
         const tintColor = ssBlock?.tintColor.isConnected ? ssBlock.tintColor.associatedVariableName : "vec3(1.)";
         const translucencyIntensity = ssBlock?.translucencyIntensity.isConnected ? ssBlock?.translucencyIntensity.associatedVariableName : "1.";
-        const translucencyDiffusionDistance = ssBlock?.translucencyDiffusionDistance.isConnected ? ssBlock?.translucencyDiffusionDistance.associatedVariableName : "vec3(1.)";
+        const translucencyDiffusionDistance = ssBlock?.translucencyDiffusionDist.isConnected ? ssBlock?.translucencyDiffusionDist.associatedVariableName : "vec3(1.)";
 
         const refractionBlock: Nullable<RefractionBlock> = (ssBlock?.refraction.isConnected ? ssBlock?.refraction.connectedPoint?.ownerBlock : null) as Nullable<RefractionBlock>;
 
@@ -172,7 +144,7 @@ export class SubSurfaceBlock extends NodeMaterialBlock {
         code += `subSurfaceOutParams subSurfaceOut;
 
         #ifdef SUBSURFACE
-            vec2 vThicknessParam = vec2(${minThickness}, ${maxThickness} - ${minThickness});
+            vec2 vThicknessParam = vec2(0., ${thickness});
             vec4 vTintColor = vec4(${tintColor}, ${refractionTintAtDistance});
             vec3 vSubSurfaceIntensity = vec3(${refractionIntensity}, ${translucencyIntensity}, 0.);
 
@@ -183,7 +155,7 @@ export class SubSurfaceBlock extends NodeMaterialBlock {
                 normalW,
                 specularEnvironmentReflectance,
             #ifdef SS_THICKNESSANDMASK_TEXTURE
-                ${thicknessTexture},
+                vec4(0.),
             #endif
             #ifdef REFLECTION
                 #ifdef SS_TRANSLUCENCY

+ 1 - 1
src/Materials/Node/nodeMaterialBlock.ts

@@ -591,7 +591,7 @@ export class NodeMaterialBlock {
 
     protected _dumpPropertiesCode() {
         let variableName = this._codeVariableName;
-        return `${variableName}.visibleInInspector = ${this.visibleInInspector}`;
+        return `${variableName}.visibleInInspector = ${this.visibleInInspector};\r\n`;
     }
 
     /** @hidden */

+ 2 - 1
src/Materials/PBR/pbrClearCoatConfiguration.ts

@@ -43,8 +43,9 @@ export class PBRClearCoatConfiguration {
     /**
      * This defaults to 1.5 corresponding to a 0.04 f0 or a 4% reflectance at normal incidence
      * The default fits with a polyurethane material.
+     * @hidden
      */
-    private static readonly _DefaultIndexOfRefraction = 1.5;
+    public static readonly _DefaultIndexOfRefraction = 1.5;
 
     private _isEnabled = false;
     /**

+ 1 - 1
src/Shaders/ShadersInclude/pbrBlockFinalLitComponents.fx

@@ -128,7 +128,7 @@
         luminanceOverAlpha += getLuminance(finalClearCoatScaled);
     #endif
 
-    #if defined(RADIANCEOVERALPHA) || defined(SPECULAROVERALPHA)
+    #if defined(RADIANCEOVERALPHA) || defined(SPECULAROVERALPHA) || defined(CLEARCOATOVERALPHA)
         alpha = saturate(alpha + luminanceOverAlpha * luminanceOverAlpha);
     #endif
 #endif

二進制
tests/validation/ReferenceImages/ktx2decoder.png


二進制
tests/validation/ReferenceImages/node-material-pbr-1.png


+ 1 - 1
tests/validation/config.json

@@ -79,7 +79,7 @@
         },    
         {
             "title": "Node material PBR 1",
-            "playgroundId": "#D8AK3Z#15",
+            "playgroundId": "#D8AK3Z#17",
             "referenceImage": "node-material-pbr-1.png"
         },    
         {