Browse Source

Add a metallic/roughness texture block

Popov72 5 years ago
parent
commit
8dd4ed58d0

+ 7 - 4
nodeEditor/src/blockTools.ts

@@ -62,9 +62,10 @@ import { DerivativeBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/deriva
 import { RefractBlock } from 'babylonjs/Materials/Node/Blocks/refractBlock';
 import { ReflectBlock } from 'babylonjs/Materials/Node/Blocks/reflectBlock';
 import { DesaturateBlock } from 'babylonjs/Materials/Node/Blocks/desaturateBlock';
-import { PBRMetallicRoughnessBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/pbrMetallicRoughnessBlock';
-import { SheenBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/sheenBlock';
-import { AmbientOcclusionBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/ambientOcclusionBlock';
+import { PBRMetallicRoughnessBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/PBR/pbrMetallicRoughnessBlock';
+import { SheenBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/PBR/sheenBlock';
+import { AmbientOcclusionBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/PBR/ambientOcclusionBlock';
+import { MetallicRoughnessTextureBlock } from 'babylonjs/Materials/Node/Blocks/Fragment/PBR/MetallicRoughnessTextureBlock';
 
 export class BlockTools {
     public static GetBlockFromString(data: string, scene: Scene, nodeMaterial: NodeMaterial) {
@@ -441,7 +442,9 @@ export class BlockTools {
                 return new SheenBlock("Sheen");
             case "AmbientOcclusionBlock":
                 return new AmbientOcclusionBlock("AmbientOcclusion");
-        }
+            case "MetallicRoughnessTextureBlock":
+                return new MetallicRoughnessTextureBlock("MetallicRoughness texture");
+            }
 
         return null;
     }

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

@@ -119,7 +119,8 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
         "Rotate2dBlock": "Rotates UV coordinates around the W axis.",
         "PBRMetallicRoughnessBlock": "PBR metallic/roughness material",
         "SheenBlock": "Sheen block",
-        "AmbientOcclusionBlock": "Ambient occlusion block"
+        "AmbientOcclusionBlock": "Ambient occlusion block",
+        "MetallicRoughnessTextureBlock": "Metallic/Roughness texture block"
     };
 
     constructor(props: INodeListComponentProps) {
@@ -148,7 +149,7 @@ export class NodeListComponent extends React.Component<INodeListComponentProps,
             Mesh: ["InstancesBlock", "PositionBlock", "UVBlock", "ColorBlock", "NormalBlock", "PerturbNormalBlock", "NormalBlendBlock" , "TangentBlock", "MatrixIndicesBlock", "MatrixWeightsBlock", "WorldPositionBlock", "WorldNormalBlock", "WorldTangentBlock", "FrontFacingBlock"],
             Noises: ["RandomNumberBlock", "SimplexPerlin3DBlock", "WorleyNoise3DBlock"],
             Output_Nodes: ["VertexOutputBlock", "FragmentOutputBlock", "DiscardBlock"],
-            PBR: ["AmbientOcclusionBlock", "PBRMetallicRoughnessBlock", "SheenBlock"],
+            PBR: ["PBRMetallicRoughnessBlock", "AmbientOcclusionBlock", "MetallicRoughnessTextureBlock", "SheenBlock"],
             Range: ["ClampBlock", "RemapBlock", "NormalizeBlock"],
             Round: ["RoundBlock", "CeilingBlock", "FloorBlock"],
             Scene: ["FogBlock", "CameraPositionBlock", "FogColorBlock", "ImageProcessingBlock", "LightBlock", "LightInformationBlock", "ViewDirectionBlock"],

+ 1 - 0
nodeEditor/src/diagram/displayLedger.ts

@@ -20,4 +20,5 @@ DisplayLedger.RegisteredControls["RemapBlock"] = RemapDisplayManager;
 DisplayLedger.RegisteredControls["TrigonometryBlock"] = TrigonometryDisplayManager;
 DisplayLedger.RegisteredControls["TextureBlock"] = TextureDisplayManager;
 DisplayLedger.RegisteredControls["ReflectionTextureBlock"] = TextureDisplayManager;
+DisplayLedger.RegisteredControls["MetallicRoughnessTextureBlock"] = TextureDisplayManager;
 DisplayLedger.RegisteredControls["DiscardBlock"] = DiscardDisplayManager;

+ 1 - 0
nodeEditor/src/diagram/propertyLedger.ts

@@ -19,4 +19,5 @@ PropertyLedger.RegisteredControls["LightBlock"] = LightPropertyTabComponent;
 PropertyLedger.RegisteredControls["LightInformationBlock"] = LightInformationPropertyTabComponent;
 PropertyLedger.RegisteredControls["TextureBlock"] = TexturePropertyTabComponent;
 PropertyLedger.RegisteredControls["ReflectionTextureBlock"] = TexturePropertyTabComponent;
+PropertyLedger.RegisteredControls["MetallicRoughnessTextureBlock"] = TexturePropertyTabComponent;
 PropertyLedger.RegisteredControls["TrigonometryBlock"] = TrigonometryPropertyTabComponent;

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

@@ -0,0 +1,4 @@
+export * from "./pbrMetallicRoughnessBlock";
+export * from "./sheenBlock";
+export * from "./ambientOcclusionBlock";
+export * from "./metallicRoughnessTextureBlock";

+ 70 - 0
src/Materials/Node/Blocks/Fragment/PBR/metallicRoughnessTextureBlock.ts

@@ -0,0 +1,70 @@
+import { NodeMaterial, NodeMaterialDefines } from '../../../nodeMaterial';
+import { _TypeStore } from '../../../../../Misc/typeStore';
+import { editableInPropertyPage, PropertyTypeForEdition } from "../../../nodeMaterialDecorator";
+import { AbstractMesh } from '../../../../../Meshes/abstractMesh';
+import { TextureBlock } from '../../Dual/textureBlock';
+import { NodeMaterialBlockConnectionPointTypes } from '../../../Enums/nodeMaterialBlockConnectionPointTypes';
+import { NodeMaterialBlockTargets } from '../../../Enums/nodeMaterialBlockTargets';
+import { NodeMaterialConnectionPointCustomObject } from "../../../nodeMaterialConnectionPointCustomObject";
+import { NodeMaterialConnectionPoint, NodeMaterialConnectionPointDirection } from '../../../nodeMaterialBlockConnectionPoint';
+
+export class MetallicRoughnessTextureBlock extends TextureBlock {
+
+    @editableInPropertyPage("AO from red channel", PropertyTypeForEdition.Boolean, "METALLIC WORKFLOW")
+    public useAmbientOcclusionFromMetallicTextureRed: boolean = false;
+
+    @editableInPropertyPage("Metallness from blue channel", PropertyTypeForEdition.Boolean, "METALLIC WORKFLOW")
+    public useMetallnessFromMetallicTextureBlue: boolean = true;
+
+    @editableInPropertyPage("Roughness from alpha channel", PropertyTypeForEdition.Boolean, "METALLIC WORKFLOW")
+    public useRoughnessFromMetallicTextureAlpha: boolean = false;
+
+    @editableInPropertyPage("Roughness from green channel", PropertyTypeForEdition.Boolean, "METALLIC WORKFLOW")
+    public useRoughnessFromMetallicTextureGreen: boolean = true;
+
+    @editableInPropertyPage("Metallic F0 from alpha channel", PropertyTypeForEdition.Boolean, "METALLIC WORKFLOW")
+    public useMetallicF0FactorFromMetallicTexture: boolean = false;
+
+    /**
+     * Create a new MetallicRoughnessTextureBlock
+     * @param name defines the block name
+     */
+    public constructor(name: string) {
+        super(name);
+
+        this._outputs = [];
+
+        this.registerOutput("rgba", NodeMaterialBlockConnectionPointTypes.Color4, NodeMaterialBlockTargets.Neutral, new NodeMaterialConnectionPointCustomObject("rgba", this, NodeMaterialConnectionPointDirection.Output, MetallicRoughnessTextureBlock, "MetallicRoughnessTextureBlock", "metalRoughText"));
+        this.registerOutput("rgb", NodeMaterialBlockConnectionPointTypes.Color3, NodeMaterialBlockTargets.Neutral);
+        this.registerOutput("r", NodeMaterialBlockConnectionPointTypes.Float, NodeMaterialBlockTargets.Neutral);
+        this.registerOutput("g", NodeMaterialBlockConnectionPointTypes.Float, NodeMaterialBlockTargets.Neutral);
+        this.registerOutput("b", NodeMaterialBlockConnectionPointTypes.Float, NodeMaterialBlockTargets.Neutral);
+        this.registerOutput("a", NodeMaterialBlockConnectionPointTypes.Float, NodeMaterialBlockTargets.Neutral);
+    }
+
+    /**
+     * Gets the current class name
+     * @returns the class name
+     */
+    public getClassName() {
+        return "MetallicRoughnessTextureBlock";
+    }
+
+    /**
+     * Gets the rgba output component
+     */
+    public get metalRoughText(): NodeMaterialConnectionPoint {
+        return this._outputs[0];
+    }
+
+    public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
+        defines.setValue("AOSTOREINMETALMAPRED", this.useAmbientOcclusionFromMetallicTextureRed);
+        defines.setValue("METALLNESSSTOREINMETALMAPBLUE", this.useMetallnessFromMetallicTextureBlue);
+        defines.setValue("ROUGHNESSSTOREINMETALMAPALPHA", this.useRoughnessFromMetallicTextureAlpha);
+        defines.setValue("ROUGHNESSSTOREINMETALMAPGREEN",  !this.useRoughnessFromMetallicTextureAlpha && this.useRoughnessFromMetallicTextureGreen);
+        defines.setValue("METALLICF0FACTORFROMMETALLICMAP", this.useMetallicF0FactorFromMetallicTexture);
+    }
+
+}
+
+_TypeStore.RegisteredTypes["BABYLON.MetallicRoughnessTextureBlock"] = MetallicRoughnessTextureBlock;

+ 103 - 62
src/Materials/Node/Blocks/Fragment/PBR/pbrMetallicRoughnessBlock.ts

@@ -19,6 +19,7 @@ import { editableInPropertyPage, PropertyTypeForEdition } from "../../../nodeMat
 import { NodeMaterialConnectionPointCustomObject } from "../../../nodeMaterialConnectionPointCustomObject";
 import { AmbientOcclusionBlock } from './ambientOcclusionBlock';
 import { SheenBlock } from './sheenBlock';
+import { MetallicRoughnessTextureBlock } from './metallicRoughnessTextureBlock';
 
 export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
     private _lightId: number;
@@ -39,9 +40,9 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         this.registerInput("cameraPosition", NodeMaterialBlockConnectionPointTypes.Vector3, false, NodeMaterialBlockTargets.Fragment);
         this.registerInput("baseColor", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("baseTexture", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("metallic", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("roughness", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
-        this.registerInput("metalRoughText", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("metallic", NodeMaterialBlockConnectionPointTypes.Float, false, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("roughness", NodeMaterialBlockConnectionPointTypes.Float, false, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("metalRoughText", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment, new NodeMaterialConnectionPointCustomObject("metalRoughText", this, NodeMaterialConnectionPointDirection.Input, MetallicRoughnessTextureBlock, "MetallicRoughnessTextureBlock", "rgba"));
         this.registerInput("opacityTexture", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("ambientColor", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("ambientOcclusion", NodeMaterialBlockConnectionPointTypes.Object, true, NodeMaterialBlockTargets.Fragment, new NodeMaterialConnectionPointCustomObject("ambientOcclusion", this, NodeMaterialConnectionPointDirection.Input, AmbientOcclusionBlock, "AOBlock"));
@@ -88,6 +89,9 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
     public initialize(state: NodeMaterialBuildState) {
         state._excludeVariableName("surfaceAlbedo");
         state._excludeVariableName("alpha");
+        state._excludeVariableName("baseColor");
+        state._excludeVariableName("diffuseBase");
+        state._excludeVariableName("metallicRoughness");
     }
 
     /**
@@ -228,6 +232,7 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
 
     public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
         defines.setValue("PBR", true);
+        defines.setValue("METALLICWORKFLOW", true);
 
         // Albedo & Opacity
         if (this.baseTexture.isConnected) {
@@ -249,6 +254,11 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
 
         defines.setValue("AMBIENT", aoBlock?.texture.isConnected ?? false);
 
+        aoBlock?.prepareDefines(mesh, nodeMaterial, defines);
+
+        // Reflectivity
+        defines.setValue("REFLECTIVITY", this.metalRoughTexture.isConnected);
+
         if (!defines._areLightsDirty) {
             return;
         }
@@ -449,69 +459,100 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
             aoDirectLightIntensity += ".";
         }
 
-        if (this._lightId === 0) {
-            // _____________________________ Geometry Information ____________________________
-            if (state._registerTempVariable("viewDirectionW")) {
-                state.compilationString += `vec3 viewDirectionW = normalize(${this.cameraPosition.associatedVariableName} - ${"v_" + worldPos.associatedVariableName}.xyz);\r\n`;
-            }
+        // _____________________________ Geometry Information ____________________________
+        if (state._registerTempVariable("viewDirectionW")) {
+            state.compilationString += `vec3 viewDirectionW = normalize(${this.cameraPosition.associatedVariableName} - ${"v_" + worldPos.associatedVariableName}.xyz);\r\n`;
+        }
 
-            state.compilationString += `vec3 geometricNormalW = ${this.worldNormal.associatedVariableName}.xyz;\r\n`;
+        state.compilationString += `vec3 geometricNormalW = ${this.worldNormal.associatedVariableName}.xyz;\r\n`;
 
-            state.compilationString += `vec3 normalW = ${normalShading.isConnected ? normalShading.associatedVariableName + ".xyz" : "geometricNormalW"};\r\n`;
+        state.compilationString += `vec3 normalW = ${normalShading.isConnected ? normalShading.associatedVariableName + ".xyz" : "geometricNormalW"};\r\n`;
 
-            state.compilationString += state._emitCodeFromInclude("pbrBlockNormalFinal", comments, {
-                replaceStrings: [
-                    { search: /vPositionW/g, replace: worldPos.associatedVariableName },
-                    { search: /vEyePosition.w/g, replace: "1." },
-                ]
-            });
+        state.compilationString += state._emitCodeFromInclude("pbrBlockNormalFinal", comments, {
+            replaceStrings: [
+                { search: /vPositionW/g, replace: worldPos.associatedVariableName },
+                { search: /vEyePosition.w/g, replace: "1." },
+            ]
+        });
 
-            // _____________________________ Albedo & Opacity ______________________________
-            state.compilationString += `albedoOpacityOutParams albedoOpacityOut;\r\n`;
-
-            const albedoColor = this.baseColor.isConnected ? this.baseColor.associatedVariableName : "vec4(1., 1., 1., 1.)";
-            const albedoTexture = this.baseTexture.isConnected ? this.baseTexture.associatedVariableName : "";
-            const opacityTexture = this.opacityTexture.isConnected ? this.opacityTexture.associatedVariableName : "";
-
-            state.compilationString += `albedoOpacityBlock(
-                    ${albedoColor},
-                #ifdef ALBEDO
-                    ${albedoTexture},
-                    vec2(1., 1.),
-                #endif
-                #ifdef OPACITY
-                    ${opacityTexture},
-                    vec2(1., 1.),
-                #endif
-                    albedoOpacityOut
-                );
-
-                vec3 surfaceAlbedo = albedoOpacityOut.surfaceAlbedo;
-                float alpha = albedoOpacityOut.alpha;\r\n`;
-
-            state.compilationString += state._emitCodeFromInclude("depthPrePass", comments);
-
-            // _____________________________ AO  _______________________________
-            state.compilationString += `ambientOcclusionOutParams aoOut;\r\n`;
-
-            const aoTexture = aoBlock?.texture.isConnected ? aoBlock.texture.associatedVariableName : "vec2(0., 0.)";
-            const aoLevel = "1.";
-            const aoIntensity = aoBlock?.intensity.isConnected ? aoBlock.intensity.associatedVariableName : "1.";
-
-            state.compilationString += `ambientOcclusionBlock(
-                #ifdef AMBIENT
-                    ${aoTexture},
-                    vec4(0., ${aoLevel}, ${aoIntensity}, 0.),
-                #endif
-                    aoOut
-                );\r\n`;
-
-            // _____________________________ Reflectivity _______________________________
-            state.compilationString += `vec3 baseColor = surfaceAlbedo;\r\nreflectivityOutParams reflectivityOut;\r\n`;
-
-            // _____________________________ Direct Lighting Info __________________________________
-            state.compilationString += state._emitCodeFromInclude("pbrBlockDirectLighting", comments);
-        }
+        // _____________________________ Albedo & Opacity ______________________________
+        state.compilationString += `albedoOpacityOutParams albedoOpacityOut;\r\n`;
+
+        const albedoColor = this.baseColor.isConnected ? this.baseColor.associatedVariableName : "vec4(1., 1., 1., 1.)";
+        const albedoTexture = this.baseTexture.isConnected ? this.baseTexture.associatedVariableName : "";
+        const opacityTexture = this.opacityTexture.isConnected ? this.opacityTexture.associatedVariableName : "";
+
+        state.compilationString += `albedoOpacityBlock(
+                ${albedoColor},
+            #ifdef ALBEDO
+                ${albedoTexture},
+                vec2(1., 1.),
+            #endif
+            #ifdef OPACITY
+                ${opacityTexture},
+                vec2(1., 1.),
+            #endif
+                albedoOpacityOut
+            );
+
+            vec3 surfaceAlbedo = albedoOpacityOut.surfaceAlbedo;
+            float alpha = albedoOpacityOut.alpha;\r\n`;
+
+        state.compilationString += state._emitCodeFromInclude("depthPrePass", comments);
+
+        // _____________________________ AO  _______________________________
+        state.compilationString += `ambientOcclusionOutParams aoOut;\r\n`;
+
+        const aoTexture = aoBlock?.texture.isConnected ? aoBlock.texture.associatedVariableName : "vec2(0., 0.)";
+        const aoLevel = "1.";
+        const aoIntensity = aoBlock?.intensity.isConnected ? aoBlock.intensity.associatedVariableName : "1.";
+
+        state.compilationString += `ambientOcclusionBlock(
+            #ifdef AMBIENT
+                ${aoTexture},
+                vec4(0., ${aoLevel}, ${aoIntensity}, 0.),
+            #endif
+                aoOut
+            );\r\n`;
+
+        // _____________________________ Reflectivity _______________________________
+        const metalRoughTexture = this.metalRoughTexture.isConnected ? this.metalRoughTexture.associatedVariableName : null;
+
+        state.compilationString += `vec3 baseColor = surfaceAlbedo;\r\nreflectivityOutParams reflectivityOut;\r\n`;
+
+        state.compilationString += `reflectivityBlock(
+            vec4(${this.metallic.associatedVariableName}, ${this.roughness.associatedVariableName}, 0., 0.04),
+        #ifdef METALLICWORKFLOW
+            surfaceAlbedo,
+        #endif
+        #ifdef REFLECTIVITY
+            vec3(0., 0., ${aoIntensity}),
+            ${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`;
+
+        // _____________________________ Compute Geometry info _________________________________
+        //#include<pbrBlockGeometryInfo>
+
+        // _____________________________ Direct Lighting Info __________________________________
+        state.compilationString += state._emitCodeFromInclude("pbrBlockDirectLighting", comments);
 
         /*if (this.light) {
             state.compilationString += state._emitCodeFromInclude("lightFragment", comments, {

+ 1 - 3
src/Materials/Node/Blocks/Fragment/index.ts

@@ -5,6 +5,4 @@ export * from "./perturbNormalBlock";
 export * from "./discardBlock";
 export * from "./frontFacingBlock";
 export * from "./derivativeBlock";
-export * from "./PBR/pbrMetallicRoughnessBlock";
-export * from "./PBR/sheenBlock";
-export * from "./PBR/ambientOcclusionBlock";
+export * from "./PBR/index";