浏览代码

Reflection: reuse the existing fragment code block

Popov72 5 年之前
父节点
当前提交
bca2e165da

+ 17 - 12
src/Materials/Node/Blocks/Dual/reflectionTextureBaseBlock.ts

@@ -284,8 +284,10 @@ export abstract class ReflectionTextureBaseBlock extends NodeMaterialBlock {
      * @param worldNormalVarName name of the world normal variable
      * @returns the shader code
      */
-    public handleFragmentSideCodeReflectionCoords(worldNormalVarName: string): string {
-        let worldPos = `v_${this.worldPosition.associatedVariableName}`;
+    public handleFragmentSideCodeReflectionCoords(worldNormalVarName: string, worldPos?: string, onlyReflectionVector = false): string {
+        if (!worldPos) {
+            worldPos = `v_${this.worldPosition.associatedVariableName}`;
+        }
         let reflectionMatrix = this._reflectionMatrixName;
         let direction = `normalize(${this._directionWName})`;
         let positionUVW = `${this._positionUVWName}`;
@@ -337,18 +339,21 @@ export abstract class ReflectionTextureBaseBlock extends NodeMaterialBlock {
 
             #ifdef ${this._defineOppositeZ}
                 ${this._reflectionVectorName}.z *= -1.0;
-            #endif
-
-            #ifdef ${this._define3DName}
-                vec3 ${this._reflectionCoordsName} = ${this._reflectionVectorName};
-            #else
-                vec2 ${this._reflectionCoordsName} = ${this._reflectionVectorName}.xy;
-                #ifdef ${this._defineProjectionName}
-                    ${this._reflectionCoordsName} /= ${this._reflectionVectorName}.z;
-                #endif
-                ${this._reflectionCoordsName}.y = 1.0 - ${this._reflectionCoordsName}.y;
             #endif\r\n`;
 
+        if (!onlyReflectionVector) {
+            code += `
+                #ifdef ${this._define3DName}
+                    vec3 ${this._reflectionCoordsName} = ${this._reflectionVectorName};
+                #else
+                    vec2 ${this._reflectionCoordsName} = ${this._reflectionVectorName}.xy;
+                    #ifdef ${this._defineProjectionName}
+                        ${this._reflectionCoordsName} /= ${this._reflectionVectorName}.z;
+                    #endif
+                    ${this._reflectionCoordsName}.y = 1.0 - ${this._reflectionCoordsName}.y;
+                #endif\r\n`;
+        }
+
         return code;
     }
 

+ 14 - 0
src/Materials/Node/Blocks/PBR/pbrMetallicRoughnessBlock.ts

@@ -864,6 +864,20 @@ export class PBRMetallicRoughnessBlock extends NodeMaterialBlock {
                 state.compilationString += reflectionBlock.getCode(state, anisotropyBlock ? "anisotropicOut.anisotropicNormal" : "normalW", "environmentRadiance", "irradianceVector", "environmentIrradiance");
             }
 
+            state._emitFunctionFromInclude("pbrBlockReflection", comments, {
+                replaceStrings: [
+                    { search: /computeReflectionCoords/g, replace: "computeReflectionCoordsPBR" },
+                    { search: /REFLECTIONMAP_3D/g, replace: reflectionBlock?._define3DName ?? "REFLECTIONMAP_3D" },
+                    { search: /REFLECTIONMAP_OPPOSITEZ/g, replace: reflectionBlock?._defineOppositeZ ?? "REFLECTIONMAP_OPPOSITEZ" },
+                    { search: /REFLECTIONMAP_PROJECTION/g, replace: reflectionBlock?._defineProjectionName ?? "REFLECTIONMAP_PROJECTION" },
+                    { search: /REFLECTIONMAP_SKYBOX/g, replace: reflectionBlock?._defineSkyboxName ?? "REFLECTIONMAP_SKYBOX" },
+                    { search: /LODINREFLECTIONALPHA/g, replace: reflectionBlock?._defineLODReflectionAlpha ?? "LODINREFLECTIONALPHA" },
+                    { search: /LINEARSPECULARREFLECTION/g, replace: reflectionBlock?._defineLinearSpecularReflection ?? "LINEARSPECULARREFLECTION" },
+                    { search: /LODBASEDMICROSFURACE/g, replace: reflectionBlock?._defineLODBasedMicroSurface ?? "LODBASEDMICROSFURACE" },
+                    { search: /REFLECTIONMAP_OPPOSITEZ/g, replace: reflectionBlock?._defineOppositeZ ?? "REFLECTIONMAP_OPPOSITEZ" },
+                ]
+            });
+
             // ___________________ Compute Reflectance aka R0 F0 info _________________________
             state.compilationString += state._emitCodeFromInclude("pbrBlockReflectance0", comments);
 

+ 65 - 78
src/Materials/Node/Blocks/PBR/reflectionBlock.ts

@@ -21,9 +21,12 @@ import { Scene } from '../../../../scene';
  */
 export class ReflectionBlock extends ReflectionTextureBaseBlock {
 
-    private _defineLODReflectionAlpha: string;
-    private _defineLinearSpecularReflection: string;
-    private _defineLODBasedMicroSurface: string;
+    /** @hidden */
+    public _defineLODReflectionAlpha: string;
+    /** @hidden */
+    public _defineLinearSpecularReflection: string;
+    /** @hidden */
+    public _defineLODBasedMicroSurface: string;
     private _vEnvironmentIrradianceName: string;
     private _vReflectionMicrosurfaceInfosName: string;
     private _scene: Scene;
@@ -300,27 +303,6 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
     public getCode(state: NodeMaterialBuildState, normalVarName: string, finalColorVarName: string, finalIrradianceVector: string, finalIrradianceVarName: string): string {
         let code = "";
 
-        code += `
-            struct reflectionOutParams
-            {
-                vec4 environmentRadiance;
-                vec3 environmentIrradiance;
-            #ifdef ${this._define3DName}
-                vec3 reflectionCoords;
-            #else
-                vec2 reflectionCoords;
-            #endif
-            #ifdef SS_TRANSLUCENCY
-                #ifdef USESPHERICALFROMREFLECTIONMAP
-                    #if !defined(NORMAL) || !defined(USESPHERICALINVERTEX)
-                        vec3 irradianceVector;
-                    #endif
-                #endif
-            #endif
-            };\r\n`;
-
-        code += `reflectionOutParams reflectionOut;\r\n`;
-
         this.handleFragmentSideInits(state);
 
         state._emitFunctionFromInclude("harmonicsFunctions", `//${this.name}`, {
@@ -330,75 +312,80 @@ export class ReflectionBlock extends ReflectionTextureBaseBlock {
             ]
         });
 
-        code += this.handleFragmentSideCodeReflectionCoords(normalVarName);
-
-        const varLOD = state._getFreeVariableName("reflectionLOD");
-        const varRequestedLOD = state._getFreeVariableName("requestedReflectionLOD");
-        const varAutomaticLOD = state._getFreeVariableName("automaticReflectionLOD");
+        state._emitFunction("sampleReflection", `
+            #ifdef ${this._define3DName}
+                #define sampleReflection(s, c) textureCube(s, c)
+            #else
+                #define sampleReflection(s, c) texture2D(s, c)
+            #endif\r\n`, `//${this.name}`);
 
-        this._vReflectionMicrosurfaceInfosName = state._getFreeVariableName("vReflectionMicrosurfaceInfos");
+        state._emitFunction("sampleReflectionLod", `
+            #ifdef ${this._define3DName}
+                #define sampleReflectionLod(s, c, l) textureCubeLodEXT(s, c, l)
+            #else
+                #define sampleReflectionLod(s, c, l) texture2DLodEXT(s, c, l)
+            #endif\r\n`, `//${this.name}`);
 
-        state._emitUniformFromString(this._vReflectionMicrosurfaceInfosName, "vec3");
+        const computeReflectionCoordsFunc = `
+            vec3 computeReflectionCoordsPBR(vec4 worldPos, vec3 worldNormal) {
+                ${this.handleFragmentSideCodeReflectionCoords('worldNormal', 'worldPos', true)}
+                return ${this._reflectionVectorName};
+            }\r\n`;
 
-        code += `
-            vec4 ${finalColorVarName} = vec4(0.);
+        state._emitFunction("computeReflectionCoordsPBR", computeReflectionCoordsFunc, `//${this.name}`);
 
-            #if defined(${this._defineLODReflectionAlpha}) && !defined(${this._defineSkyboxName})
-                float ${varLOD} = getLodFromAlphaG(${this._vReflectionMicrosurfaceInfosName}.x, alphaG, NdotVUnclamped);
-            #elif defined(${this._defineLinearSpecularReflection})
-                float ${varLOD} = getLinearLodFromRoughness(${this._vReflectionMicrosurfaceInfosName}.x, roughness);
-            #else
-                float ${varLOD} = getLodFromAlphaG(${this._vReflectionMicrosurfaceInfosName}.x, alphaG);
-            #endif
+        this._vReflectionMicrosurfaceInfosName = state._getFreeVariableName("vReflectionMicrosurfaceInfos");
 
-            #ifdef ${this._defineLODBasedMicroSurface}
-                ${varLOD} = ${varLOD} * ${this._vReflectionMicrosurfaceInfosName}.y + ${this._vReflectionMicrosurfaceInfosName}.z;
+        state._emitUniformFromString(this._vReflectionMicrosurfaceInfosName, "vec3");
 
-                #ifdef ${this._defineLODReflectionAlpha}
-                    #ifdef ${this._define3DName}
-                        float ${varAutomaticLOD} = UNPACK_LOD(textureCube(${this._cubeSamplerName}, ${this._reflectionCoordsName}).a);
-                    #else
-                        float ${varAutomaticLOD} = UNPACK_LOD(texture2D(${this._2DSamplerName}, ${this._reflectionCoordsName}).a);
-                    #endif
-                    float ${varRequestedLOD} = max(${varAutomaticLOD}, ${varLOD});
-                #else
-                    float ${varRequestedLOD} = ${varLOD};
-                #endif\r\n`;
+        const reflectionColor = this.color.isConnected ? this.color.associatedVariableName : "vec3(1., 1., 1.)";
 
-        code += this.handleFragmentSideCodeReflectionColor(varRequestedLOD, "");
+        code += `reflectionOutParams reflectionOut;\r\n`;
 
         code += `
-                ${finalColorVarName} = ${this._reflectionColorName}${this.color.isConnected ? " * vec4(" + this.color.associatedVariableName + ", 1.)" : ""};
+            reflectionBlock(
+                ${"v_" + this.worldPosition.associatedVariableName + ".xyz"},
+                ${normalVarName},
+                alphaG,
+                ${this._vReflectionMicrosurfaceInfosName},
+                vec2(1., 0.),
+                ${reflectionColor},
+            #ifdef ANISOTROPIC
+                anisotropicOut,
+            #endif
+            #if defined(${this._defineLODReflectionAlpha}) && !defined(${this._defineSkyboxName})
+                NdotVUnclamped,
+            #endif
+            #ifdef ${this._defineLinearSpecularReflection}
+                roughness,
+            #endif
+            #ifdef ${this._define3DName}
+                ${this._cubeSamplerName},
             #else
-                // ***not handled***
+                ${this._2DSamplerName},
+            #endif
+            #if defined(NORMAL) && defined(USESPHERICALINVERTEX)
+                ${this._vEnvironmentIrradianceName},
             #endif
-
-            vec3 ${finalIrradianceVarName} = vec3(0.);
             #ifdef USESPHERICALFROMREFLECTIONMAP
-                #if defined(USESPHERICALINVERTEX)
-                    ${finalIrradianceVarName} = ${this._vEnvironmentIrradianceName};
-                #else
-                    #ifdef ANISOTROPIC
-                        vec3 ${finalIrradianceVector} = vec3(${this._reflectionMatrixName} * vec4(anisotropicOut.anisotropicNormal, 0)).xyz;
-                    #else
-                        vec3 ${finalIrradianceVector} = vec3(${this._reflectionMatrixName} * vec4(${normalVarName}.xyz, 0)).xyz;
-                    #endif
-
-                    #ifdef ${this._defineOppositeZ}
-                    ${finalIrradianceVector}.z *= -1.0;
-                    #endif
-
-                    ${finalIrradianceVarName} = computeEnvironmentIrradiance(${finalIrradianceVector});
+                #if !defined(NORMAL) || !defined(USESPHERICALINVERTEX)
+                    ${this._reflectionMatrixName},
                 #endif
             #endif
-
-            #ifdef SS_TRANSLUCENCY
-                reflectionOut.irradianceVector = irradianceVector;
+            #ifdef USEIRRADIANCEMAP
+                irradianceSampler, // ** not handled **
             #endif
-
-            reflectionOut.environmentRadiance = environmentRadiance;
-            reflectionOut.environmentIrradiance = environmentIrradiance;
-            reflectionOut.reflectionCoords = ${this._reflectionCoordsName};\r\n`;
+            #ifndef ${this._defineLODBasedMicroSurface}
+                #ifdef ${this._define3DName}
+                    ${this._cubeSamplerName},
+                    ${this._cubeSamplerName},
+                #else
+                    ${this._2DSamplerName},
+                    ${this._2DSamplerName},
+                #endif
+            #endif
+                reflectionOut
+            );\r\n`;
 
         return code;
     }