Selaa lähdekoodia

Add sheen support (completed)

Popov72 5 vuotta sitten
vanhempi
commit
ff240661ff

+ 4 - 2
src/Materials/Node/Blocks/Dual/reflectionTextureBaseBlock.ts

@@ -46,8 +46,10 @@ export abstract class ReflectionTextureBaseBlock extends NodeMaterialBlock {
     public _defineSkyboxName: string;
     /** @hidden */
     public _defineOppositeZ: string;
-    protected _cubeSamplerName: string;
-    protected _2DSamplerName: string;
+    /** @hidden */
+    public _cubeSamplerName: string;
+    /** @hidden */
+    public _2DSamplerName: string;
     protected _positionUVWName: string;
     protected _directionWName: string;
     protected _reflectionVectorName: string;

+ 15 - 2
src/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.ts

@@ -821,7 +821,6 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
         state._emitFunctionFromInclude("pbrBlockAmbientOcclusion", comments);
         state._emitFunctionFromInclude("pbrBlockAlphaFresnel", comments);
         state._emitFunctionFromInclude("pbrBlockAnisotropic", comments);
-        state._emitFunctionFromInclude("pbrBlockSheen", comments);
         state._emitFunctionFromInclude("pbrBlockClearcoat", comments);
         state._emitFunctionFromInclude("pbrBlockSubSurface", comments);
 
@@ -902,7 +901,6 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
                     { search: /LODINREFLECTIONALPHA/g, replace: reflectionBlock?._defineLODReflectionAlpha ?? "LODINREFLECTIONALPHA" },
                     { search: /LINEARSPECULARREFLECTION/g, replace: reflectionBlock?._defineLinearSpecularReflection ?? "LINEARSPECULARREFLECTION" },
                     { search: /LODBASEDMICROSFURACE/g, replace: reflectionBlock?._defineLODBasedMicroSurface ?? "LODBASEDMICROSFURACE" },
-                    { search: /REFLECTIONMAP_OPPOSITEZ/g, replace: reflectionBlock?._defineOppositeZ ?? "REFLECTIONMAP_OPPOSITEZ" },
                 ]
             });
 
@@ -910,6 +908,21 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
             state.compilationString += state._emitCodeFromInclude("pbrBlockReflectance0", comments);
 
             // ________________________________ Sheen ______________________________
+            const sheenBlock = this.sheen.isConnected ? this.sheen.connectedPoint?.ownerBlock as SheenBlock : null;
+
+            if (sheenBlock) {
+                state.compilationString += sheenBlock.getCode(reflectionBlock);
+            }
+
+            state._emitFunctionFromInclude("pbrBlockSheen", comments, {
+                replaceStrings: [
+                    { search: /REFLECTIONMAP_3D/g, replace: reflectionBlock?._define3DName ?? "REFLECTIONMAP_3D" },
+                    { search: /REFLECTIONMAP_SKYBOX/g, replace: reflectionBlock?._defineSkyboxName ?? "REFLECTIONMAP_SKYBOX" },
+                    { search: /LODINREFLECTIONALPHA/g, replace: reflectionBlock?._defineLODReflectionAlpha ?? "LODINREFLECTIONALPHA" },
+                    { search: /LINEARSPECULARREFLECTION/g, replace: reflectionBlock?._defineLinearSpecularReflection ?? "LINEARSPECULARREFLECTION" },
+                    { search: /LODBASEDMICROSFURACE/g, replace: reflectionBlock?._defineLODBasedMicroSurface ?? "LODBASEDMICROSFURACE" },
+                ]
+            });
 
             // _____________________________ Clear Coat ____________________________
             state.compilationString += `clearcoatOutParams clearcoatOut;

+ 20 - 7
src/Materials/Node/Blocks/PBR/reflectionBlock.ts

@@ -28,7 +28,10 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
     /** @hidden */
     public _defineLODBasedMicroSurface: string;
     private _vEnvironmentIrradianceName: string;
-    private _vReflectionMicrosurfaceInfosName: string;
+    /** @hidden */
+    public _vReflectionMicrosurfaceInfosName: string;
+    /** @hidden */
+    public _vReflectionInfosName: string;
     private _scene: Scene;
 
     /**
@@ -146,6 +149,13 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
         return !!this._getTexture();
     }
 
+    /**
+     * Gets the reflection color (either the name of the variable if the color input is connected, else a default value)
+     */
+    public get reflectionColor(): string {
+        return this.color.isConnected ? this.color.associatedVariableName : "vec3(1., 1., 1.)";
+    }
+
     protected _getTexture(): Nullable<BaseTexture> {
         if (this.texture) {
             return this.texture;
@@ -338,18 +348,20 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
 
         state._emitUniformFromString(this._vReflectionMicrosurfaceInfosName, "vec3");
 
-        const reflectionColor = this.color.isConnected ? this.color.associatedVariableName : "vec3(1., 1., 1.)";
+        this._vReflectionInfosName = state._getFreeVariableName("vReflectionInfos");
+
+        code += `#ifdef REFLECTION
+            vec2 ${this._vReflectionInfosName} = vec2(1., 0.);
 
-        code += `reflectionOutParams reflectionOut;\r\n`;
+            reflectionOutParams reflectionOut;
 
-        code += `
             reflectionBlock(
                 ${"v_" + this.worldPosition.associatedVariableName + ".xyz"},
                 ${normalVarName},
                 alphaG,
                 ${this._vReflectionMicrosurfaceInfosName},
-                vec2(1., 0.),
-                ${reflectionColor},
+                ${this._vReflectionInfosName},
+                ${this.reflectionColor},
             #ifdef ANISOTROPIC
                 anisotropicOut,
             #endif
@@ -385,7 +397,8 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
                 #endif
             #endif
                 reflectionOut
-            );\r\n`;
+            );
+        #endif\r\n`;
 
         return code;
     }

+ 147 - 12
src/Materials/Node/Blocks/PBR/sheenBlock.ts

@@ -4,8 +4,13 @@ import { NodeMaterialBuildState } from '../../nodeMaterialBuildState';
 import { NodeMaterialConnectionPoint, NodeMaterialConnectionPointDirection } from '../../nodeMaterialBlockConnectionPoint';
 import { NodeMaterialBlockTargets } from '../../Enums/nodeMaterialBlockTargets';
 import { _TypeStore } from '../../../../Misc/typeStore';
-import { editableInPropertyPage } from "../../nodeMaterialDecorator";
+import { editableInPropertyPage, PropertyTypeForEdition } from "../../nodeMaterialDecorator";
 import { NodeMaterialConnectionPointCustomObject } from "../../nodeMaterialConnectionPointCustomObject";
+import { NodeMaterial, NodeMaterialDefines } from '../../nodeMaterial';
+import { AbstractMesh } from '../../../../Meshes/abstractMesh';
+import { ReflectionBlock } from './reflectionBlock';
+import { Scene } from '../../../../scene';
+import { Nullable } from '../../../../types';
 
 /**
  * Block used to implement the sheen module of the PBR material
@@ -21,10 +26,10 @@ export class SheenBlock extends NodeMaterialBlock {
 
         this._isUnique = true;
 
-        this.registerInput("texture", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("intensity", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("color", NodeMaterialBlockConnectionPointTypes.Color3, true, NodeMaterialBlockTargets.Fragment);
         this.registerInput("roughness", NodeMaterialBlockConnectionPointTypes.Float, true, NodeMaterialBlockTargets.Fragment);
+        this.registerInput("texture", NodeMaterialBlockConnectionPointTypes.Color4, true, NodeMaterialBlockTargets.Fragment);
 
         this.registerOutput("sheen", NodeMaterialBlockConnectionPointTypes.Object, NodeMaterialBlockTargets.Fragment,
             new NodeMaterialConnectionPointCustomObject("sheen", this, NodeMaterialConnectionPointDirection.Output, SheenBlock, "SheenBlock"));
@@ -35,10 +40,27 @@ export class SheenBlock extends NodeMaterialBlock {
      * It allows the strength of the sheen effect to not depend on the base color of the material,
      * making it easier to setup and tweak the effect
      */
-    @editableInPropertyPage("Albedo scaling")
+    @editableInPropertyPage("Albedo scaling", PropertyTypeForEdition.Boolean, "PROPERTIES", { "notifiers": { "update": true }})
     public albedoScaling: boolean = false;
 
     /**
+     * Defines if the sheen is linked to the sheen color.
+     */
+    @editableInPropertyPage("Link sheen with albedo", PropertyTypeForEdition.Boolean, "PROPERTIES", { "notifiers": { "update": true }})
+    public linkSheenWithAlbedo: 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("sheenOut");
+        state._excludeVariableName("sheenMapData");
+        state._excludeVariableName("vSheenColor");
+        state._excludeVariableName("vSheenRoughness");
+    }
+
+    /**
      * Gets the current class name
      * @returns the class name
      */
@@ -47,30 +69,30 @@ export class SheenBlock extends NodeMaterialBlock {
     }
 
     /**
-     * Gets the texture input component
+     * Gets the intensity input component
      */
-    public get texture(): NodeMaterialConnectionPoint {
+    public get intensity(): NodeMaterialConnectionPoint {
         return this._inputs[0];
     }
 
     /**
-     * Gets the intensity input component
+     * Gets the color input component
      */
-    public get intensity(): NodeMaterialConnectionPoint {
+    public get color(): NodeMaterialConnectionPoint {
         return this._inputs[1];
     }
 
     /**
-     * Gets the color input component
+     * Gets the roughness input component
      */
-    public get color(): NodeMaterialConnectionPoint {
+    public get roughness(): NodeMaterialConnectionPoint {
         return this._inputs[2];
     }
 
     /**
-     * Gets the roughness input component
+     * Gets the texture input component
      */
-    public get roughness(): NodeMaterialConnectionPoint {
+    public get texture(): NodeMaterialConnectionPoint {
         return this._inputs[3];
     }
 
@@ -81,11 +103,124 @@ export class SheenBlock extends NodeMaterialBlock {
         return this._outputs[0];
     }
 
+    public prepareDefines(mesh: AbstractMesh, nodeMaterial: NodeMaterial, defines: NodeMaterialDefines) {
+        super.prepareDefines(mesh, nodeMaterial, defines);
+
+        defines.setValue("SHEEN", true);
+        defines.setValue("SHEEN_LINKWITHALBEDO", this.linkSheenWithAlbedo);
+        defines.setValue("SHEEN_ROUGHNESS", this.roughness.isConnected);
+        defines.setValue("SHEEN_ALBEDOSCALING", this.albedoScaling);
+        defines.setValue("SHEEN_TEXTURE", this.texture.isConnected);
+    }
+
+    /**
+     * Gets the main code of the block (fragment side)
+     * @param reflectionBlock instance of a ReflectionBlock null if the code must be generated without an active reflection module
+     * @returns the shader code
+     */
+    public getCode(reflectionBlock: Nullable<ReflectionBlock>): string {
+        let code = "";
+
+        const color = this.color.isConnected ? this.color.associatedVariableName : "vec3(1.)";
+        const intensity = this.intensity.isConnected ? this.intensity.associatedVariableName : "1.";
+        const roughness = this.roughness.isConnected ? this.roughness.associatedVariableName : "0.";
+        const texture = this.texture.isConnected ? this.texture.associatedVariableName : "vec4(0.)";
+
+        code = `#ifdef SHEEN
+            sheenOutParams sheenOut;
+
+            vec4 vSheenColor = vec4(${color}, ${intensity});
+
+            sheenBlock(
+                vSheenColor,
+            #ifdef SHEEN_ROUGHNESS
+                ${roughness},
+            #endif
+                roughness,
+            #ifdef SHEEN_TEXTURE
+                ${texture},
+            #endif
+                reflectance,
+            #ifdef SHEEN_LINKWITHALBEDO
+                baseColor,
+                surfaceAlbedo,
+            #endif
+            #ifdef ENVIRONMENTBRDF
+                NdotV,
+                environmentBrdf,
+            #endif
+            #if defined(REFLECTION) && defined(ENVIRONMENTBRDF)
+                AARoughnessFactors,
+                ${reflectionBlock?._vReflectionMicrosurfaceInfosName},
+                ${reflectionBlock?._vReflectionInfosName},
+                ${reflectionBlock?.reflectionColor},
+                vLightingIntensity,
+                #ifdef ${reflectionBlock?._define3DName}
+                    ${reflectionBlock?._cubeSamplerName},
+                #else
+                    ${reflectionBlock?._2DSamplerName},
+                #endif
+                reflectionOut.reflectionCoords,
+                NdotVUnclamped,
+                #ifndef ${reflectionBlock?._defineLODBasedMicroSurface}
+                    #ifdef ${reflectionBlock?._define3DName}
+                        ${reflectionBlock?._cubeSamplerName},
+                        ${reflectionBlock?._cubeSamplerName},
+                    #else
+                        ${reflectionBlock?._2DSamplerName},
+                        ${reflectionBlock?._2DSamplerName},
+                    #endif
+                #endif
+                #if !defined(${reflectionBlock?._defineSkyboxName}) && defined(RADIANCEOCCLUSION)
+                    seo,
+                #endif
+                #if !defined(${reflectionBlock?._defineSkyboxName}) && defined(HORIZONOCCLUSION) && defined(BUMP) && defined(${reflectionBlock?._define3DName})
+                    eho,
+                #endif
+            #endif
+                sheenOut
+            );
+
+            #ifdef SHEEN_LINKWITHALBEDO
+                surfaceAlbedo = sheenOut.surfaceAlbedo;
+            #endif
+        #endif\r\n`;
+
+        return code;
+    }
+
     protected _buildBlock(state: NodeMaterialBuildState) {
-        super._buildBlock(state);
+        if (state.target === NodeMaterialBlockTargets.Fragment) {
+            state.sharedData.blocksWithDefines.push(this);
+        }
 
         return this;
     }
+
+    protected _dumpPropertiesCode() {
+        let codeString: string = super._dumpPropertiesCode();
+
+        codeString += `${this._codeVariableName}.albedoScaling = ${this.albedoScaling};\r\n`;
+        codeString += `${this._codeVariableName}.linkSheenWithAlbedo = ${this.linkSheenWithAlbedo};\r\n`;
+
+        return codeString;
+    }
+
+    public serialize(): any {
+        let serializationObject = super.serialize();
+
+        serializationObject.albedoScaling = this.albedoScaling;
+        serializationObject.linkSheenWithAlbedo = this.linkSheenWithAlbedo;
+
+        return serializationObject;
+    }
+
+    public _deserialize(serializationObject: any, scene: Scene, rootUrl: string) {
+        super._deserialize(serializationObject, scene, rootUrl);
+
+        this.albedoScaling = serializationObject.albedoScaling;
+        this.linkSheenWithAlbedo = serializationObject.linkSheenWithAlbedo;
+    }
 }
 
 _TypeStore.RegisteredTypes["BABYLON.SheenBlock"] = SheenBlock;