Selaa lähdekoodia

Merge pull request #7873 from Popov72/pbr-shader-refactoring

PBR shader code refactoring
David Catuhe 5 vuotta sitten
vanhempi
commit
93ec6f67f5

+ 11 - 11
src/Shaders/ShadersInclude/lightFragment.fx

@@ -57,7 +57,7 @@
             #ifdef HEMILIGHT{X}
                 info.diffuse = computeHemisphericDiffuseLighting(preInfo, light{X}.vLightDiffuse.rgb, light{X}.vLightGround);
             #elif defined(SS_TRANSLUCENCY)
-                info.diffuse = computeDiffuseAndTransmittedLighting(preInfo, light{X}.vLightDiffuse.rgb, transmittance);
+                info.diffuse = computeDiffuseAndTransmittedLighting(preInfo, light{X}.vLightDiffuse.rgb, subSurfaceOut.transmittance);
             #else
                 info.diffuse = computeDiffuseLighting(preInfo, light{X}.vLightDiffuse.rgb);
             #endif
@@ -65,9 +65,9 @@
             // Specular contribution
             #ifdef SPECULARTERM
                 #ifdef ANISOTROPIC
-                    info.specular = computeAnisotropicSpecularLighting(preInfo, viewDirectionW, normalW, anisotropicTangent, anisotropicBitangent, anisotropy, specularEnvironmentR0, specularEnvironmentR90, AARoughnessFactors.x, light{X}.vLightDiffuse.rgb);
+                    info.specular = computeAnisotropicSpecularLighting(preInfo, viewDirectionW, normalW, anisotropicOut.anisotropicTangent, anisotropicOut.anisotropicBitangent, anisotropicOut.anisotropy, clearcoatOut.specularEnvironmentR0, specularEnvironmentR90, AARoughnessFactors.x, light{X}.vLightDiffuse.rgb);
                 #else
-                    info.specular = computeSpecularLighting(preInfo, normalW, specularEnvironmentR0, specularEnvironmentR90, AARoughnessFactors.x, light{X}.vLightDiffuse.rgb);
+                    info.specular = computeSpecularLighting(preInfo, normalW, clearcoatOut.specularEnvironmentR0, specularEnvironmentR90, AARoughnessFactors.x, light{X}.vLightDiffuse.rgb);
                 #endif
             #endif
 
@@ -75,31 +75,31 @@
             #ifdef SHEEN
                 #ifdef SHEEN_LINKWITHALBEDO
                     // BE Carefull: Sheen intensity is replacing the roughness value.
-                    preInfo.roughness = sheenIntensity;
+                    preInfo.roughness = sheenOut.sheenIntensity;
                 #else
                     #ifdef HEMILIGHT{X}
-                        preInfo.roughness = sheenRoughness;
+                        preInfo.roughness = sheenOut.sheenRoughness;
                     #else
-                        preInfo.roughness = adjustRoughnessFromLightProperties(sheenRoughness, light{X}.vLightSpecular.a, preInfo.lightDistance);
+                        preInfo.roughness = adjustRoughnessFromLightProperties(sheenOut.sheenRoughness, light{X}.vLightSpecular.a, preInfo.lightDistance);
                     #endif
                 #endif
-                info.sheen = computeSheenLighting(preInfo, normalW, sheenColor, specularEnvironmentR90, AARoughnessFactors.x, light{X}.vLightDiffuse.rgb);
+                info.sheen = computeSheenLighting(preInfo, normalW, sheenOut.sheenColor, specularEnvironmentR90, AARoughnessFactors.x, light{X}.vLightDiffuse.rgb);
             #endif
 
             // Clear Coat contribution
             #ifdef CLEARCOAT
                 // Simulates Light radius
                 #ifdef HEMILIGHT{X}
-                    preInfo.roughness = clearCoatRoughness;
+                    preInfo.roughness = clearcoatOut.clearCoatRoughness;
                 #else
-                    preInfo.roughness = adjustRoughnessFromLightProperties(clearCoatRoughness, light{X}.vLightSpecular.a, preInfo.lightDistance);
+                    preInfo.roughness = adjustRoughnessFromLightProperties(clearcoatOut.clearCoatRoughness, light{X}.vLightSpecular.a, preInfo.lightDistance);
                 #endif
 
-                info.clearCoat = computeClearCoatLighting(preInfo, clearCoatNormalW, clearCoatAARoughnessFactors.x, clearCoatIntensity, light{X}.vLightDiffuse.rgb);
+                info.clearCoat = computeClearCoatLighting(preInfo, clearcoatOut.clearCoatNormalW, clearcoatOut.clearCoatAARoughnessFactors.x, clearcoatOut.clearCoatIntensity, light{X}.vLightDiffuse.rgb);
                 
                 #ifdef CLEARCOAT_TINT
                     // Absorption
-                    absorption = computeClearCoatLightingAbsorption(clearCoatNdotVRefract, preInfo.L, clearCoatNormalW, clearCoatColor, clearCoatThickness, clearCoatIntensity);
+                    absorption = computeClearCoatLightingAbsorption(clearcoatOut.clearCoatNdotVRefract, preInfo.L, clearcoatOut.clearCoatNormalW, clearcoatOut.clearCoatColor, clearcoatOut.clearCoatThickness, clearcoatOut.clearCoatIntensity);
                     info.diffuse *= absorption;
                     #ifdef SPECULARTERM
                         info.specular *= absorption;

+ 73 - 0
src/Shaders/ShadersInclude/pbrBlockAlbedoOpacity.fx

@@ -0,0 +1,73 @@
+struct albedoOpacityOutParams
+{
+    vec3 surfaceAlbedo;
+    float alpha;
+};
+
+void albedoOpacityBlock(
+    const in vec4 vAlbedoColor,
+#ifdef ALBEDO
+    const in vec4 albedoTexture,
+    const in vec2 vAlbedoInfos,
+#endif
+#ifdef OPACITY
+    const in vec4 opacityMap,
+    const in vec2 vOpacityInfos,
+#endif
+    out albedoOpacityOutParams outParams
+)
+{
+    // _____________________________ Albedo Information ______________________________
+    vec3 surfaceAlbedo = vAlbedoColor.rgb;
+    float alpha = vAlbedoColor.a;
+
+    #ifdef ALBEDO
+        #if defined(ALPHAFROMALBEDO) || defined(ALPHATEST)
+            alpha *= albedoTexture.a;
+        #endif
+
+        #ifdef GAMMAALBEDO
+            surfaceAlbedo *= toLinearSpace(albedoTexture.rgb);
+        #else
+            surfaceAlbedo *= albedoTexture.rgb;
+        #endif
+
+        surfaceAlbedo *= vAlbedoInfos.y;
+    #endif
+
+    #ifdef VERTEXCOLOR
+        surfaceAlbedo *= vColor.rgb;
+    #endif
+
+    #define CUSTOM_FRAGMENT_UPDATE_ALBEDO
+
+    // _____________________________ Alpha Information _______________________________
+    #ifdef OPACITY
+        #ifdef OPACITYRGB
+            alpha = getLuminance(opacityMap.rgb);
+        #else
+            alpha *= opacityMap.a;
+        #endif
+
+        alpha *= vOpacityInfos.y;
+    #endif
+
+    #ifdef VERTEXALPHA
+        alpha *= vColor.a;
+    #endif
+
+    #if !defined(SS_LINKREFRACTIONTOTRANSPARENCY) && !defined(ALPHAFRESNEL)
+        #ifdef ALPHATEST
+            if (alpha < ALPHATESTVALUE)
+                discard;
+
+            #ifndef ALPHABLEND
+                // Prevent to blend with the canvas.
+                alpha = 1.0;
+            #endif
+        #endif
+    #endif
+
+    outParams.surfaceAlbedo = surfaceAlbedo;
+    outParams.alpha = alpha;
+}

+ 44 - 0
src/Shaders/ShadersInclude/pbrBlockAlphaFresnel.fx

@@ -0,0 +1,44 @@
+#ifdef ALPHAFRESNEL
+#if defined(ALPHATEST) || defined(ALPHABLEND)
+    struct alphaFresnelOutParams
+    {
+        float alpha;
+    };
+
+    void alphaFresnelBlock(
+        const in vec3 normalW,
+        const in vec3 viewDirectionW,
+        const in float alpha,
+        const in float microSurface,
+        out alphaFresnelOutParams outParams
+    )
+    {
+        // Convert approximate perceptual opacity (gamma-encoded opacity) to linear opacity (absorptance, or inverse transmission)
+        // for use with the linear HDR render target. The final composition will be converted back to gamma encoded values for eventual display.
+        // Uses power 2.0 rather than 2.2 for simplicity/efficiency, and because the mapping does not need to map the gamma applied to RGB.
+        float opacityPerceptual = alpha;
+
+        #ifdef LINEARALPHAFRESNEL
+            float opacity0 = opacityPerceptual;
+        #else
+            float opacity0 = opacityPerceptual * opacityPerceptual;
+        #endif
+        float opacity90 = fresnelGrazingReflectance(opacity0);
+
+        vec3 normalForward = faceforward(normalW, -viewDirectionW, normalW);
+
+        // Calculate the appropriate linear opacity for the current viewing angle (formally, this quantity is the "directional absorptance").
+        outParams.alpha = getReflectanceFromAnalyticalBRDFLookup_Jones(saturate(dot(viewDirectionW, normalForward)), vec3(opacity0), vec3(opacity90), sqrt(microSurface)).x;
+
+        #ifdef ALPHATEST
+            if (outParams.alpha < ALPHATESTVALUE)
+                discard;
+
+            #ifndef ALPHABLEND
+                // Prevent to blend with the canvas.
+                outParams.alpha = 1.0;
+            #endif
+        #endif
+    }
+#endif
+#endif

+ 32 - 0
src/Shaders/ShadersInclude/pbrBlockAmbientOcclusion.fx

@@ -0,0 +1,32 @@
+struct ambientOcclusionOutParams
+{
+    vec3 ambientOcclusionColor;
+#if DEBUGMODE > 0
+    vec3 ambientOcclusionColorMap;
+#endif
+};
+
+void ambientOcclusionBlock(
+#ifdef AMBIENT
+    const in vec3 ambientOcclusionColorMap_,
+    const in vec4 vAmbientInfos,
+#endif
+    out ambientOcclusionOutParams outParams
+)
+{
+    vec3 ambientOcclusionColor = vec3(1., 1., 1.);
+
+    #ifdef AMBIENT
+        vec3 ambientOcclusionColorMap = ambientOcclusionColorMap_ * vAmbientInfos.y;
+        #ifdef AMBIENTINGRAYSCALE
+            ambientOcclusionColorMap = vec3(ambientOcclusionColorMap.r, ambientOcclusionColorMap.r, ambientOcclusionColorMap.r);
+        #endif
+        ambientOcclusionColor = mix(ambientOcclusionColor, ambientOcclusionColorMap, vAmbientInfos.z);
+    #endif
+
+    outParams.ambientOcclusionColor = ambientOcclusionColor;
+
+    #if DEBUGMODE > 0
+        outParams.ambientOcclusionColorMap = ambientOcclusionColorMap;
+    #endif
+}

+ 48 - 0
src/Shaders/ShadersInclude/pbrBlockAnisotropic.fx

@@ -0,0 +1,48 @@
+#ifdef ANISOTROPIC
+    struct anisotropicOutParams
+    {
+        float anisotropy;
+        vec3 anisotropicTangent;
+        vec3 anisotropicBitangent;
+        vec3 anisotropicNormal;
+    #if DEBUGMODE > 0
+        vec3 anisotropyMapData;
+    #endif
+    };
+
+    void anisotropicBlock(
+        const in vec3 vAnisotropy,
+    #ifdef ANISOTROPIC_TEXTURE
+        const in vec2 vAnisotropyInfos,
+        const in vec2 vAnisotropyUV,
+        const in vec2 uvOffset,
+        const in sampler2D anisotropySampler,
+    #endif
+        const in mat3 TBN,
+        const in vec3 normalW,
+        const in vec3 viewDirectionW,
+        out anisotropicOutParams outParams
+    )
+    {
+        float anisotropy = vAnisotropy.b;
+        vec3 anisotropyDirection = vec3(vAnisotropy.xy, 0.);
+
+        #ifdef ANISOTROPIC_TEXTURE
+            vec3 anisotropyMapData = texture2D(anisotropySampler, vAnisotropyUV + uvOffset).rgb * vAnisotropyInfos.y;
+            anisotropy *= anisotropyMapData.b;
+            anisotropyDirection.rg *= anisotropyMapData.rg * 2.0 - 1.0;
+            #if DEBUGMODE > 0
+                outParams.anisotropyMapData = anisotropyMapData;
+            #endif
+        #endif
+
+        mat3 anisoTBN = mat3(normalize(TBN[0]), normalize(TBN[1]), normalize(TBN[2]));
+        vec3 anisotropicTangent = normalize(anisoTBN * anisotropyDirection);
+        vec3 anisotropicBitangent = normalize(cross(anisoTBN[2], anisotropicTangent));
+        
+        outParams.anisotropy = anisotropy;
+        outParams.anisotropicTangent = anisotropicTangent;
+        outParams.anisotropicBitangent = anisotropicBitangent;
+        outParams.anisotropicNormal = getAnisotropicBentNormals(anisotropicTangent, anisotropicBitangent, normalW, viewDirectionW, anisotropy);
+    }
+#endif

+ 319 - 0
src/Shaders/ShadersInclude/pbrBlockClearcoat.fx

@@ -0,0 +1,319 @@
+struct clearcoatOutParams
+{
+    vec3 specularEnvironmentR0;
+    float conservationFactor;
+    vec3 clearCoatNormalW;
+    vec2 clearCoatAARoughnessFactors;
+    float clearCoatIntensity;
+    float clearCoatRoughness;
+#ifdef REFLECTION
+    vec3 finalClearCoatRadianceScaled;
+#endif
+#ifdef CLEARCOAT_TINT
+    vec3 absorption;
+    float clearCoatNdotVRefract;
+    vec3 clearCoatColor;
+    float clearCoatThickness;
+#endif
+#if defined(ENVIRONMENTBRDF) && defined(MS_BRDF_ENERGY_CONSERVATION)
+    vec3 energyConservationFactorClearCoat;
+#endif
+#if DEBUGMODE > 0
+    mat3 TBNClearCoat;
+    vec2 clearCoatMapData;
+    vec4 clearCoatTintMapData;
+    vec4 environmentClearCoatRadiance;
+    float clearCoatNdotV;
+    vec3 clearCoatEnvironmentReflectance;
+#endif
+};
+
+#ifdef CLEARCOAT
+    void clearcoatBlock(
+        const in vec3 vPositionW,
+        const in vec3 geometricNormalW,
+        const in vec3 viewDirectionW,
+        const in vec2 vClearCoatParams,
+        const in vec2 uvOffset,
+        const in vec3 specularEnvironmentR0,
+    #ifdef CLEARCOAT_TEXTURE
+        const in vec2 vClearCoatUV,
+        const in vec2 vClearCoatInfos,
+        const in sampler2D clearCoatSampler,
+    #endif
+    #ifdef CLEARCOAT_TINT
+        const in vec4 vClearCoatTintParams,
+        const in float clearCoatColorAtDistance,
+        const in vec4 vClearCoatRefractionParams,
+        #ifdef CLEARCOAT_TINT_TEXTURE
+            const in vec2 vClearCoatTintUV_,
+            const in sampler2D clearCoatTintSampler,
+        #endif
+    #endif
+    #ifdef CLEARCOAT_BUMP
+        const in vec2 vClearCoatBumpInfos,
+        const in vec2 vClearCoatBumpUV_,
+        const in sampler2D clearCoatBumpSampler,
+        #if defined(TANGENT) && defined(NORMAL)
+            const in mat3 vTBN,
+        #else
+            const in vec2 vClearCoatTangentSpaceParams,
+        #endif
+        #ifdef OBJECTSPACE_NORMALMAP
+            const in mat4 normalMatrix,
+        #endif
+    #endif
+    #if defined(FORCENORMALFORWARD) && defined(NORMAL)
+        const in vec3 faceNormal,
+    #endif
+    #ifdef REFLECTION
+        const in vec3 vReflectionMicrosurfaceInfos,
+        const in vec4 vLightingIntensity,
+        #ifdef REFLECTIONMAP_3D
+            const in samplerCube reflectionSampler,
+        #else
+            const in sampler2D reflectionSampler,
+        #endif
+        #ifndef LODBASEDMICROSFURACE
+            const in sampler2D reflectionSamplerLow,
+            const in sampler2D reflectionSamplerHigh,
+        #endif
+    #endif
+    #if defined(ENVIRONMENTBRDF) && !defined(REFLECTIONMAP_SKYBOX)
+        #ifdef RADIANCEOCCLUSION
+            const in float ambientMonochrome,
+        #endif
+    #endif
+        out clearcoatOutParams outParams
+    )
+    {
+        // Clear COAT parameters.
+        float clearCoatIntensity = vClearCoatParams.x;
+        float clearCoatRoughness = vClearCoatParams.y;
+
+        #ifdef CLEARCOAT_TEXTURE
+            vec2 clearCoatMapData = texture2D(clearCoatSampler, vClearCoatUV + uvOffset).rg * vClearCoatInfos.y;
+            clearCoatIntensity *= clearCoatMapData.x;
+            clearCoatRoughness *= clearCoatMapData.y;
+            #if DEBUGMODE > 0
+                outParams.clearCoatMapData = clearCoatMapData;
+            #endif
+        #endif
+
+        outParams.clearCoatIntensity = clearCoatIntensity;
+        outParams.clearCoatRoughness = clearCoatRoughness;
+
+        #ifdef CLEARCOAT_TINT
+            vec3 clearCoatColor = vClearCoatTintParams.rgb;
+            float clearCoatThickness = vClearCoatTintParams.a;
+
+            #ifdef CLEARCOAT_TINT_TEXTURE
+                vec4 clearCoatTintMapData = texture2D(clearCoatTintSampler, vClearCoatTintUV_ + uvOffset);
+                clearCoatColor *= toLinearSpace(clearCoatTintMapData.rgb);
+                clearCoatThickness *= clearCoatTintMapData.a;
+                #if DEBUGMODE > 0
+                    outParams.clearCoatTintMapData = clearCoatTintMapData;
+                #endif
+            #endif
+
+            outParams.clearCoatColor = computeColorAtDistanceInMedia(clearCoatColor, clearCoatColorAtDistance);
+            outParams.clearCoatThickness = clearCoatThickness;
+        #endif
+
+        // remapping and linearization of clear coat roughness
+        // Let s see how it ends up in gltf
+        // clearCoatRoughness = mix(0.089, 0.6, clearCoatRoughness);
+
+        // Remap F0 to account for the change of interface within the material.
+        vec3 specularEnvironmentR0Updated = getR0RemappedForClearCoat(specularEnvironmentR0);
+        outParams.specularEnvironmentR0 = mix(specularEnvironmentR0, specularEnvironmentR0Updated, clearCoatIntensity);
+
+        // Needs to use the geometric normal before bump for this.
+        vec3 clearCoatNormalW = geometricNormalW;
+
+        #ifdef CLEARCOAT_BUMP
+            #ifdef NORMALXYSCALE
+                float clearCoatNormalScale = 1.0;
+            #else
+                float clearCoatNormalScale = vClearCoatBumpInfos.y;
+            #endif
+
+            #if defined(TANGENT) && defined(NORMAL)
+                mat3 TBNClearCoat = vTBN;
+            #else
+                mat3 TBNClearCoat = cotangent_frame(clearCoatNormalW * clearCoatNormalScale, vPositionW, vClearCoatBumpUV, vClearCoatTangentSpaceParams);
+            #endif
+
+            #if DEBUGMODE > 0
+                outParams.TBNClearCoat = TBNClearCoat;
+            #endif
+
+            #ifdef OBJECTSPACE_NORMALMAP
+                clearCoatNormalW = normalize(texture2D(clearCoatBumpSampler, vClearCoatBumpUV + uvOffset).xyz  * 2.0 - 1.0);
+                clearCoatNormalW = normalize(mat3(normalMatrix) * clearCoatNormalW);
+            #else
+                clearCoatNormalW = perturbNormal(TBNClearCoat, texture2D(clearCoatBumpSampler, vClearCoatBumpUV + uvOffset).xyz, vClearCoatBumpInfos.y);
+            #endif
+        #endif
+
+        #if defined(FORCENORMALFORWARD) && defined(NORMAL)
+            clearCoatNormalW *= sign(dot(clearCoatNormalW, faceNormal));
+        #endif
+
+        #if defined(TWOSIDEDLIGHTING) && defined(NORMAL)
+            clearCoatNormalW = gl_FrontFacing ? clearCoatNormalW : -clearCoatNormalW;
+        #endif
+
+        outParams.clearCoatNormalW = clearCoatNormalW;
+
+        // Clear Coat AA
+        outParams.clearCoatAARoughnessFactors = getAARoughnessFactors(clearCoatNormalW.xyz);
+
+        // Compute N dot V.
+        float clearCoatNdotVUnclamped = dot(clearCoatNormalW, viewDirectionW);
+        // The order 1886 page 3.
+        float clearCoatNdotV = absEps(clearCoatNdotVUnclamped);
+
+        #if DEBUGMODE > 0
+            outParams.clearCoatNdotV = clearCoatNdotV;
+        #endif
+
+        #ifdef CLEARCOAT_TINT
+            // Used later on in the light fragment and ibl.
+            vec3 clearCoatVRefract = -refract(vPositionW, clearCoatNormalW, vClearCoatRefractionParams.y);
+            // The order 1886 page 3.
+            outParams.clearCoatNdotVRefract = absEps(dot(clearCoatNormalW, clearCoatVRefract));
+        #endif
+
+        #if defined(ENVIRONMENTBRDF) && !defined(REFLECTIONMAP_SKYBOX)
+            // BRDF Lookup
+            vec3 environmentClearCoatBrdf = getBRDFLookup(clearCoatNdotV, clearCoatRoughness);
+        #endif
+
+        // Clear Coat Reflection
+        #if defined(REFLECTION)
+            float clearCoatAlphaG = convertRoughnessToAverageSlope(clearCoatRoughness);
+
+            #ifdef SPECULARAA
+                // Adapt linear roughness (alphaG) to geometric curvature of the current pixel.
+                clearCoatAlphaG += outParams.clearCoatAARoughnessFactors.y;
+            #endif
+
+            vec4 environmentClearCoatRadiance = vec4(0., 0., 0., 0.);
+
+            vec3 clearCoatReflectionVector = computeReflectionCoords(vec4(vPositionW, 1.0), clearCoatNormalW);
+            #ifdef REFLECTIONMAP_OPPOSITEZ
+                clearCoatReflectionVector.z *= -1.0;
+            #endif
+
+            // _____________________________ 2D vs 3D Maps ________________________________
+            #ifdef REFLECTIONMAP_3D
+                vec3 clearCoatReflectionCoords = clearCoatReflectionVector;
+            #else
+                vec2 clearCoatReflectionCoords = clearCoatReflectionVector.xy;
+                #ifdef REFLECTIONMAP_PROJECTION
+                    clearCoatReflectionCoords /= clearCoatReflectionVector.z;
+                #endif
+                clearCoatReflectionCoords.y = 1.0 - clearCoatReflectionCoords.y;
+            #endif
+
+            #if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX)
+                float clearCoatReflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, clearCoatAlphaG, clearCoatNdotVUnclamped);
+            #elif defined(LINEARSPECULARREFLECTION)
+                float clearCoatReflectionLOD = getLinearLodFromRoughness(vReflectionMicrosurfaceInfos.x, clearCoatRoughness);
+            #else
+                float clearCoatReflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, clearCoatAlphaG);
+            #endif
+
+            #ifdef LODBASEDMICROSFURACE
+                // Apply environment convolution scale/offset filter tuning parameters to the mipmap LOD selection
+                clearCoatReflectionLOD = clearCoatReflectionLOD * vReflectionMicrosurfaceInfos.y + vReflectionMicrosurfaceInfos.z;
+                float requestedClearCoatReflectionLOD = clearCoatReflectionLOD;
+
+                environmentClearCoatRadiance = sampleReflectionLod(reflectionSampler, clearCoatReflectionCoords, requestedClearCoatReflectionLOD);
+            #else
+                float lodClearCoatReflectionNormalized = saturate(clearCoatReflectionLOD / log2(vReflectionMicrosurfaceInfos.x));
+                float lodClearCoatReflectionNormalizedDoubled = lodClearCoatReflectionNormalized * 2.0;
+
+                vec4 environmentClearCoatMid = sampleReflection(reflectionSampler, clearCoatReflectionCoords);
+                if (lodClearCoatReflectionNormalizedDoubled < 1.0) {
+                    environmentClearCoatRadiance = mix(
+                        sampleReflection(reflectionSamplerHigh, clearCoatReflectionCoords),
+                        environmentClearCoatMid,
+                        lodClearCoatReflectionNormalizedDoubled
+                    );
+                } else {
+                    environmentClearCoatRadiance = mix(
+                        environmentClearCoatMid,
+                        sampleReflection(reflectionSamplerLow, clearCoatReflectionCoords),
+                        lodClearCoatReflectionNormalizedDoubled - 1.0
+                    );
+                }
+            #endif
+
+            #ifdef RGBDREFLECTION
+                environmentClearCoatRadiance.rgb = fromRGBD(environmentClearCoatRadiance);
+            #endif
+
+            #ifdef GAMMAREFLECTION
+                environmentClearCoatRadiance.rgb = toLinearSpace(environmentClearCoatRadiance.rgb);
+            #endif
+
+            // _____________________________ Levels _____________________________________
+            environmentClearCoatRadiance.rgb *= vReflectionInfos.x;
+            environmentClearCoatRadiance.rgb *= vReflectionColor.rgb;
+
+            #if DEBUGMODE > 0
+                outParams.environmentClearCoatRadiance = environmentClearCoatRadiance;
+            #endif
+
+            // _________________________ Clear Coat Environment Oclusion __________________________
+            #if defined(ENVIRONMENTBRDF) && !defined(REFLECTIONMAP_SKYBOX)
+                vec3 clearCoatEnvironmentReflectance = getReflectanceFromBRDFLookup(vec3(vClearCoatRefractionParams.x), environmentClearCoatBrdf);
+
+                #ifdef RADIANCEOCCLUSION
+                    float clearCoatSeo = environmentRadianceOcclusion(ambientMonochrome, clearCoatNdotVUnclamped);
+                    clearCoatEnvironmentReflectance *= clearCoatSeo;
+                #endif
+
+                #ifdef HORIZONOCCLUSION
+                    #ifdef BUMP
+                        #ifdef REFLECTIONMAP_3D
+                            float clearCoatEho = environmentHorizonOcclusion(-viewDirectionW, clearCoatNormalW, geometricNormalW);
+                            clearCoatEnvironmentReflectance *= clearCoatEho;
+                        #endif
+                    #endif
+                #endif
+            #else
+                // Jones implementation of a well balanced fast analytical solution.
+                vec3 clearCoatEnvironmentReflectance = getReflectanceFromAnalyticalBRDFLookup_Jones(clearCoatNdotV, vec3(1.), vec3(1.), sqrt(1. - clearCoatRoughness));
+            #endif
+
+            clearCoatEnvironmentReflectance *= clearCoatIntensity;
+
+            #if DEBUGMODE > 0
+                outParams.clearCoatEnvironmentReflectance = clearCoatEnvironmentReflectance;
+            #endif
+
+            outParams.finalClearCoatRadianceScaled = 
+                environmentClearCoatRadiance.rgb *
+                clearCoatEnvironmentReflectance *
+                vLightingIntensity.z;
+        #endif
+
+        #if defined(CLEARCOAT_TINT)
+            // NdotL = NdotV in IBL
+            outParams.absorption = computeClearCoatAbsorption(outParams.clearCoatNdotVRefract, outParams.clearCoatNdotVRefract, outParams.clearCoatColor, clearCoatThickness, clearCoatIntensity);
+        #endif
+
+        // clear coat energy conservation
+        float fresnelIBLClearCoat = fresnelSchlickGGX(clearCoatNdotV, vClearCoatRefractionParams.x, CLEARCOATREFLECTANCE90);
+        fresnelIBLClearCoat *= clearCoatIntensity;
+
+        outParams.conservationFactor = (1. - fresnelIBLClearCoat);
+
+        #if defined(ENVIRONMENTBRDF) && defined(MS_BRDF_ENERGY_CONSERVATION)
+            outParams.energyConservationFactorClearCoat = getEnergyConservationFactor(outParams.specularEnvironmentR0, environmentClearCoatBrdf);
+        #endif
+    }
+#endif

+ 32 - 0
src/Shaders/ShadersInclude/pbrBlockDirectLighting.fx

@@ -0,0 +1,32 @@
+vec3 diffuseBase = vec3(0., 0., 0.);
+#ifdef SPECULARTERM
+    vec3 specularBase = vec3(0., 0., 0.);
+#endif
+#ifdef CLEARCOAT
+    vec3 clearCoatBase = vec3(0., 0., 0.);
+#endif
+#ifdef SHEEN
+    vec3 sheenBase = vec3(0., 0., 0.);
+#endif
+
+#ifdef LIGHTMAP
+    vec4 lightmapColor = texture2D(lightmapSampler, vLightmapUV + uvOffset);
+
+    #ifdef RGBDLIGHTMAP
+        lightmapColor.rgb = fromRGBD(lightmapColor);
+    #endif
+
+    #ifdef GAMMALIGHTMAP
+        lightmapColor.rgb = toLinearSpace(lightmapColor.rgb);
+    #endif
+    lightmapColor.rgb *= vLightmapInfos.y;
+#endif
+
+// Direct Lighting Variables
+preLightingInfo preInfo;
+lightingInfo info;
+float shadow = 1.; // 1 - shadowLevel
+
+#if defined(CLEARCOAT) && defined(CLEARCOAT_TINT)
+    vec3 absorption = vec3(0.);
+#endif

+ 47 - 0
src/Shaders/ShadersInclude/pbrBlockFinalColorComposition.fx

@@ -0,0 +1,47 @@
+vec4 finalColor = vec4(
+        finalAmbient +
+        finalDiffuse +
+#ifndef UNLIT
+    #ifdef REFLECTION
+        finalIrradiance +
+    #endif
+    #ifdef SPECULARTERM
+        finalSpecularScaled +
+    #endif
+    #ifdef SHEEN
+        finalSheenScaled +
+    #endif
+    #ifdef CLEARCOAT
+        finalClearCoatScaled +
+    #endif
+    #ifdef REFLECTION
+        finalRadianceScaled +
+        #if defined(SHEEN) && defined(ENVIRONMENTBRDF)
+            sheenOut.finalSheenRadianceScaled +
+        #endif
+        #ifdef CLEARCOAT
+            clearcoatOut.finalClearCoatRadianceScaled +
+        #endif
+    #endif
+    #ifdef SS_REFRACTION
+        subSurfaceOut.finalRefraction +
+    #endif
+#endif
+        finalEmissive,
+        alpha);
+
+// _____________________________ LightMappping _____________________________________
+#ifdef LIGHTMAP
+    #ifndef LIGHTMAPEXCLUDED
+        #ifdef USELIGHTMAPASSHADOWMAP
+            finalColor.rgb *= lightmapColor.rgb;
+        #else
+            finalColor.rgb += lightmapColor.rgb;
+        #endif
+    #endif
+#endif
+
+#define CUSTOM_FRAGMENT_BEFORE_FOG
+
+// _____________________________ Finally ___________________________________________
+finalColor = max(finalColor, 0.0);

+ 133 - 0
src/Shaders/ShadersInclude/pbrBlockFinalLitComponents.fx

@@ -0,0 +1,133 @@
+// ______________________________________________________________________________
+// _____________________________ Energy Conservation  ___________________________
+// Apply Energy Conservation.
+// _____________________________ IBL BRDF + Energy Cons ________________________________
+#if defined(ENVIRONMENTBRDF)
+    #ifdef MS_BRDF_ENERGY_CONSERVATION
+        vec3 energyConservationFactor = getEnergyConservationFactor(clearcoatOut.specularEnvironmentR0, environmentBrdf);
+    #endif
+#endif
+
+#ifndef METALLICWORKFLOW
+    #ifdef SPECULAR_GLOSSINESS_ENERGY_CONSERVATION
+        surfaceAlbedo.rgb = (1. - reflectance) * surfaceAlbedo.rgb;
+    #endif
+#endif
+
+#if defined(SHEEN) && defined(SHEEN_ALBEDOSCALING) && defined(ENVIRONMENTBRDF)
+    surfaceAlbedo.rgb = sheenOut.sheenAlbedoScaling * surfaceAlbedo.rgb;
+#endif
+
+// _____________________________ Irradiance ______________________________________
+#ifdef REFLECTION
+    vec3 finalIrradiance = reflectionOut.environmentIrradiance;
+
+    #if defined(CLEARCOAT)
+        finalIrradiance *= clearcoatOut.conservationFactor;
+        #if defined(CLEARCOAT_TINT)
+            finalIrradiance *= clearcoatOut.absorption;
+        #endif
+    #endif
+
+    #if defined(SS_REFRACTION)
+        finalIrradiance *= subSurfaceOut.refractionFactorForIrradiance;
+    #endif
+
+    #if defined(SS_TRANSLUCENCY)
+        finalIrradiance += subSurfaceOut.refractionIrradiance;
+    #endif
+
+    finalIrradiance *= surfaceAlbedo.rgb;
+    finalIrradiance *= vLightingIntensity.z;
+#endif
+
+// _____________________________ Specular ________________________________________
+#ifdef SPECULARTERM
+    vec3 finalSpecular = specularBase;
+    finalSpecular = max(finalSpecular, 0.0);
+
+    vec3 finalSpecularScaled = finalSpecular * vLightingIntensity.x * vLightingIntensity.w;
+
+    #if defined(ENVIRONMENTBRDF) && defined(MS_BRDF_ENERGY_CONSERVATION)
+        finalSpecularScaled *= energyConservationFactor;
+    #endif
+
+    #if defined(SHEEN) && defined(ENVIRONMENTBRDF) && defined(SHEEN_ALBEDOSCALING)
+        finalSpecularScaled *= sheenOut.sheenAlbedoScaling;
+    #endif
+#endif
+
+// _____________________________ Radiance ________________________________________
+#ifdef REFLECTION
+    vec3 finalRadiance = reflectionOut.environmentRadiance.rgb;
+    finalRadiance *= subSurfaceOut.specularEnvironmentReflectance;
+
+    vec3 finalRadianceScaled = finalRadiance * vLightingIntensity.z;
+
+    #if defined(ENVIRONMENTBRDF) && defined(MS_BRDF_ENERGY_CONSERVATION)
+        finalRadianceScaled *= energyConservationFactor;
+    #endif
+
+    #if defined(SHEEN) && defined(ENVIRONMENTBRDF) && defined(SHEEN_ALBEDOSCALING)
+        finalRadianceScaled *= sheenOut.sheenAlbedoScaling;
+    #endif
+#endif
+
+// ________________________________ Sheen ________________________________________
+#ifdef SHEEN
+    vec3 finalSheen = sheenBase * sheenOut.sheenColor;
+    finalSheen = max(finalSheen, 0.0);
+
+    vec3 finalSheenScaled = finalSheen * vLightingIntensity.x * vLightingIntensity.w;
+    
+    #if defined(CLEARCOAT) && defined(REFLECTION) && defined(ENVIRONMENTBRDF)
+        sheenOut.finalSheenRadianceScaled *= clearcoatOut.conservationFactor;
+
+        #if defined(CLEARCOAT_TINT)
+            sheenOut.finalSheenRadianceScaled *= clearcoatOut.absorption;
+        #endif
+    #endif
+#endif
+
+// _____________________________ Clear Coat _______________________________________
+#ifdef CLEARCOAT
+    vec3 finalClearCoat = clearCoatBase;
+    finalClearCoat = max(finalClearCoat, 0.0);
+
+    vec3 finalClearCoatScaled = finalClearCoat * vLightingIntensity.x * vLightingIntensity.w;
+
+    #if defined(ENVIRONMENTBRDF) && defined(MS_BRDF_ENERGY_CONSERVATION)
+        finalClearCoatScaled *= clearcoatOut.energyConservationFactorClearCoat;
+    #endif
+
+    #ifdef SS_REFRACTION
+        subSurfaceOut.finalRefraction *= clearcoatOut.conservationFactor;
+
+        #ifdef CLEARCOAT_TINT
+            subSurfaceOut.finalRefraction *= clearcoatOut.absorption;
+        #endif
+    #endif
+#endif
+
+// _____________________________ Highlights on Alpha _____________________________
+#ifdef ALPHABLEND
+    float luminanceOverAlpha = 0.0;
+    #if	defined(REFLECTION) && defined(RADIANCEOVERALPHA)
+        luminanceOverAlpha += getLuminance(finalRadianceScaled);
+        #if defined(CLEARCOAT)
+            luminanceOverAlpha += getLuminance(clearcoatOut.finalClearCoatRadianceScaled);
+        #endif
+    #endif
+
+    #if defined(SPECULARTERM) && defined(SPECULAROVERALPHA)
+        luminanceOverAlpha += getLuminance(finalSpecularScaled);
+    #endif
+
+    #if defined(CLEARCOAT) && defined(CLEARCOATOVERALPHA)
+        luminanceOverAlpha += getLuminance(finalClearCoatScaled);
+    #endif
+
+    #if defined(RADIANCEOVERALPHA) || defined(SPECULAROVERALPHA)
+        alpha = saturate(alpha + luminanceOverAlpha * luminanceOverAlpha);
+    #endif
+#endif

+ 32 - 0
src/Shaders/ShadersInclude/pbrBlockFinalUnlitComponents.fx

@@ -0,0 +1,32 @@
+// _____________________________ Diffuse ________________________________________
+vec3 finalDiffuse = diffuseBase;
+finalDiffuse *= surfaceAlbedo.rgb;
+finalDiffuse = max(finalDiffuse, 0.0);
+finalDiffuse *= vLightingIntensity.x;
+
+// _____________________________ Ambient ________________________________________
+vec3 finalAmbient = vAmbientColor;
+finalAmbient *= surfaceAlbedo.rgb;
+
+// _____________________________ Emissive ________________________________________
+vec3 finalEmissive = vEmissiveColor;
+#ifdef EMISSIVE
+vec3 emissiveColorTex = texture2D(emissiveSampler, vEmissiveUV + uvOffset).rgb;
+finalEmissive *= toLinearSpace(emissiveColorTex.rgb);
+finalEmissive *=  vEmissiveInfos.y;
+#endif
+finalEmissive *= vLightingIntensity.y;
+
+// ______________________________ Ambient ________________________________________
+#ifdef AMBIENT
+vec3 ambientOcclusionForDirectDiffuse = mix(vec3(1.), aoOut.ambientOcclusionColor, vAmbientInfos.w);
+#else
+vec3 ambientOcclusionForDirectDiffuse = aoOut.ambientOcclusionColor;
+#endif
+
+finalAmbient *= aoOut.ambientOcclusionColor;
+finalDiffuse *= ambientOcclusionForDirectDiffuse;
+
+#if !defined(UNLIT) && defined(REFLECTION)
+finalIrradiance *= aoOut.ambientOcclusionColor;
+#endif

+ 35 - 0
src/Shaders/ShadersInclude/pbrBlockGeometryInfo.fx

@@ -0,0 +1,35 @@
+float NdotVUnclamped = dot(normalW, viewDirectionW);
+// The order 1886 page 3.
+float NdotV = absEps(NdotVUnclamped);
+float alphaG = convertRoughnessToAverageSlope(roughness);
+vec2 AARoughnessFactors = getAARoughnessFactors(normalW.xyz);
+
+#ifdef SPECULARAA
+    // Adapt linear roughness (alphaG) to geometric curvature of the current pixel.
+    alphaG += AARoughnessFactors.y;
+#endif
+
+#if defined(ENVIRONMENTBRDF)
+    // BRDF Lookup
+    vec3 environmentBrdf = getBRDFLookup(NdotV, roughness);
+#endif
+
+#if defined(ENVIRONMENTBRDF) && !defined(REFLECTIONMAP_SKYBOX)
+    #ifdef RADIANCEOCCLUSION
+        #ifdef AMBIENTINGRAYSCALE
+            float ambientMonochrome = aoOut.ambientOcclusionColor.r;
+        #else
+            float ambientMonochrome = getLuminance(aoOut.ambientOcclusionColor);
+        #endif
+
+        float seo = environmentRadianceOcclusion(ambientMonochrome, NdotVUnclamped);
+    #endif
+
+    #ifdef HORIZONOCCLUSION
+        #ifdef BUMP
+            #ifdef REFLECTIONMAP_3D
+                float eho = environmentHorizonOcclusion(-viewDirectionW, normalW, geometricNormalW);
+            #endif
+        #endif
+    #endif
+#endif

+ 15 - 0
src/Shaders/ShadersInclude/pbrBlockImageProcessing.fx

@@ -0,0 +1,15 @@
+#ifdef IMAGEPROCESSINGPOSTPROCESS
+    // Sanitize output incase invalid normals or tangents have caused div by 0 or undefined behavior
+    // this also limits the brightness which helpfully reduces over-sparkling in bloom (native handles this in the bloom blur shader)
+    finalColor.rgb = clamp(finalColor.rgb, 0., 30.0);
+#else
+    // Alway run to ensure we are going back to gamma space.
+    finalColor = applyImageProcessing(finalColor);
+#endif
+
+    finalColor.a *= visibility;
+
+#ifdef PREMULTIPLYALPHA
+    // Convert to associative (premultiplied) format if needed.
+    finalColor.rgb *= finalColor.a;
+#endif

+ 12 - 0
src/Shaders/ShadersInclude/pbrBlockNormalFinal.fx

@@ -0,0 +1,12 @@
+#if defined(FORCENORMALFORWARD) && defined(NORMAL)
+    vec3 faceNormal = normalize(cross(dFdx(vPositionW), dFdy(vPositionW))) * vEyePosition.w;
+    #if defined(TWOSIDEDLIGHTING)
+        faceNormal = gl_FrontFacing ? faceNormal : -faceNormal;
+    #endif
+
+    normalW *= sign(dot(normalW, faceNormal));
+#endif
+
+#if defined(TWOSIDEDLIGHTING) && defined(NORMAL)
+    normalW = gl_FrontFacing ? normalW : -normalW;
+#endif

+ 13 - 0
src/Shaders/ShadersInclude/pbrBlockNormalGeometric.fx

@@ -0,0 +1,13 @@
+vec3 viewDirectionW = normalize(vEyePosition.xyz - vPositionW);
+
+#ifdef NORMAL
+    vec3 normalW = normalize(vNormalW);
+#else
+    vec3 normalW = normalize(cross(dFdx(vPositionW), dFdy(vPositionW))) * vEyePosition.w;
+#endif
+
+vec3 geometricNormalW = normalW;
+
+#if defined(TWOSIDEDLIGHTING) && defined(NORMAL)
+    geometricNormalW = gl_FrontFacing ? geometricNormalW : -geometricNormalW;
+#endif

+ 26 - 0
src/Shaders/ShadersInclude/pbrBlockReflectance.fx

@@ -0,0 +1,26 @@
+#if defined(ENVIRONMENTBRDF) && !defined(REFLECTIONMAP_SKYBOX)
+    vec3 specularEnvironmentReflectance = getReflectanceFromBRDFLookup(clearcoatOut.specularEnvironmentR0, environmentBrdf);
+
+    #ifdef RADIANCEOCCLUSION
+        specularEnvironmentReflectance *= seo;
+    #endif
+
+    #ifdef HORIZONOCCLUSION
+        #ifdef BUMP
+            #ifdef REFLECTIONMAP_3D
+                specularEnvironmentReflectance *= eho;
+            #endif
+        #endif
+    #endif
+#else
+    // Jones implementation of a well balanced fast analytical solution.
+    vec3 specularEnvironmentReflectance = getReflectanceFromAnalyticalBRDFLookup_Jones(NdotV, clearcoatOut.specularEnvironmentR0, specularEnvironmentR90, sqrt(microSurface));
+#endif
+
+#ifdef CLEARCOAT
+    specularEnvironmentReflectance *= clearcoatOut.conservationFactor;
+
+    #if defined(CLEARCOAT_TINT)
+        specularEnvironmentReflectance *= clearcoatOut.absorption;
+    #endif
+#endif

+ 4 - 0
src/Shaders/ShadersInclude/pbrBlockReflectance0.fx

@@ -0,0 +1,4 @@
+float reflectance = max(max(reflectivityOut.surfaceReflectivityColor.r, reflectivityOut.surfaceReflectivityColor.g), reflectivityOut.surfaceReflectivityColor.b);
+float reflectance90 = fresnelGrazingReflectance(reflectance);
+vec3 specularEnvironmentR0 = reflectivityOut.surfaceReflectivityColor.rgb;
+vec3 specularEnvironmentR90 = vec3(1.0, 1.0, 1.0) * reflectance90;

+ 182 - 0
src/Shaders/ShadersInclude/pbrBlockReflection.fx

@@ -0,0 +1,182 @@
+#ifdef REFLECTION
+    struct reflectionOutParams
+    {
+        vec4 environmentRadiance;
+        vec3 environmentIrradiance;
+    #ifdef REFLECTIONMAP_3D
+        vec3 reflectionCoords;
+    #else
+        vec2 reflectionCoords;
+    #endif
+    #ifdef SS_TRANSLUCENCY
+        #ifdef USESPHERICALFROMREFLECTIONMAP
+            #if !defined(NORMAL) || !defined(USESPHERICALINVERTEX)
+                vec3 irradianceVector;
+            #endif
+        #endif
+    #endif
+    };
+
+    void reflectionBlock(
+        const in vec3 vPositionW,
+        const in vec3 normalW,
+        const in float alphaG,
+        const in vec3 vReflectionMicrosurfaceInfos,
+        const in vec2 vReflectionInfos,
+    #ifdef ANISOTROPIC
+        const in anisotropicOutParams anisotropicOut,
+    #endif
+    #if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX)
+        const in float NdotVUnclamped,
+    #endif
+    #ifdef LINEARSPECULARREFLECTION
+        const in float roughness,
+    #endif
+    #ifdef REFLECTIONMAP_3D
+        const in samplerCube reflectionSampler,
+    #else
+        const in sampler2D reflectionSampler,
+    #endif
+    #if defined(NORMAL) && defined(USESPHERICALINVERTEX)
+        const in vec3 vEnvironmentIrradiance,
+    #endif
+    #ifdef USESPHERICALFROMREFLECTIONMAP
+        #if !defined(NORMAL) || !defined(USESPHERICALINVERTEX)
+            const in mat4 reflectionMatrix,
+        #endif
+    #endif
+    #ifdef USEIRRADIANCEMAP
+        #ifdef REFLECTIONMAP_3D
+            const in samplerCube irradianceSampler,
+        #else
+            const in sampler2D irradianceSampler,
+        #endif
+    #endif
+        out reflectionOutParams outParams
+    )
+    {
+        vec4 environmentRadiance = vec4(0., 0., 0., 0.);
+        vec3 environmentIrradiance = vec3(0., 0., 0.);
+
+        #ifdef ANISOTROPIC
+            vec3 reflectionVector = computeReflectionCoords(vec4(vPositionW, 1.0), anisotropicOut.anisotropicNormal);
+        #else
+            vec3 reflectionVector = computeReflectionCoords(vec4(vPositionW, 1.0), normalW);
+        #endif
+
+        #ifdef REFLECTIONMAP_OPPOSITEZ
+            reflectionVector.z *= -1.0;
+        #endif
+
+        // _____________________________ 2D vs 3D Maps ________________________________
+        #ifdef REFLECTIONMAP_3D
+            vec3 reflectionCoords = reflectionVector;
+        #else
+            vec2 reflectionCoords = reflectionVector.xy;
+            #ifdef REFLECTIONMAP_PROJECTION
+                reflectionCoords /= reflectionVector.z;
+            #endif
+            reflectionCoords.y = 1.0 - reflectionCoords.y;
+        #endif
+
+        #if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX)
+            float reflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, alphaG, NdotVUnclamped);
+        #elif defined(LINEARSPECULARREFLECTION)
+            float reflectionLOD = getLinearLodFromRoughness(vReflectionMicrosurfaceInfos.x, roughness);
+        #else
+            float reflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, alphaG);
+        #endif
+
+        #ifdef LODBASEDMICROSFURACE
+            // Apply environment convolution scale/offset filter tuning parameters to the mipmap LOD selection
+            reflectionLOD = reflectionLOD * vReflectionMicrosurfaceInfos.y + vReflectionMicrosurfaceInfos.z;
+
+            #ifdef LODINREFLECTIONALPHA
+                // Automatic LOD adjustment to ensure that the smoothness-based environment LOD selection
+                // is constrained to appropriate LOD levels in order to prevent aliasing.
+                // The environment map is first sampled without custom LOD selection to determine
+                // the hardware-selected LOD, and this is then used to constrain the final LOD selection
+                // so that excessive surface smoothness does not cause aliasing (e.g. on curved geometry
+                // where the normal is varying rapidly).
+
+                // Note: Shader Model 4.1 or higher can provide this directly via CalculateLevelOfDetail(), and
+                // manual calculation via derivatives is also possible, but for simplicity we use the
+                // hardware LOD calculation with the alpha channel containing the LOD for each mipmap.
+                float automaticReflectionLOD = UNPACK_LOD(sampleReflection(reflectionSampler, reflectionCoords).a);
+                float requestedReflectionLOD = max(automaticReflectionLOD, reflectionLOD);
+            #else
+                float requestedReflectionLOD = reflectionLOD;
+            #endif
+
+            environmentRadiance = sampleReflectionLod(reflectionSampler, reflectionCoords, requestedReflectionLOD);
+        #else
+            float lodReflectionNormalized = saturate(reflectionLOD / log2(vReflectionMicrosurfaceInfos.x));
+            float lodReflectionNormalizedDoubled = lodReflectionNormalized * 2.0;
+
+            vec4 environmentSpecularMid = sampleReflection(reflectionSampler, reflectionCoords);
+            if(lodReflectionNormalizedDoubled < 1.0){
+                environmentRadiance = mix(
+                    sampleReflection(reflectionSamplerHigh, reflectionCoords),
+                    environmentSpecularMid,
+                    lodReflectionNormalizedDoubled
+                );
+            }else{
+                environmentRadiance = mix(
+                    environmentSpecularMid,
+                    sampleReflection(reflectionSamplerLow, reflectionCoords),
+                    lodReflectionNormalizedDoubled - 1.0
+                );
+            }
+        #endif
+
+        #ifdef RGBDREFLECTION
+            environmentRadiance.rgb = fromRGBD(environmentRadiance);
+        #endif
+
+        #ifdef GAMMAREFLECTION
+            environmentRadiance.rgb = toLinearSpace(environmentRadiance.rgb);
+        #endif
+
+        // _____________________________ Irradiance ________________________________
+        #ifdef USESPHERICALFROMREFLECTIONMAP
+            #if defined(NORMAL) && defined(USESPHERICALINVERTEX)
+                environmentIrradiance = vEnvironmentIrradiance;
+            #else
+                #ifdef ANISOTROPIC
+                    vec3 irradianceVector = vec3(reflectionMatrix * vec4(anisotropicOut.anisotropicNormal, 0)).xyz;
+                #else
+                    vec3 irradianceVector = vec3(reflectionMatrix * vec4(normalW, 0)).xyz;
+                #endif
+
+                #ifdef REFLECTIONMAP_OPPOSITEZ
+                    irradianceVector.z *= -1.0;
+                #endif
+
+                environmentIrradiance = computeEnvironmentIrradiance(irradianceVector);
+
+                #ifdef SS_TRANSLUCENCY
+                    outParams.irradianceVector = irradianceVector;
+                #endif
+            #endif
+        #elif defined(USEIRRADIANCEMAP)
+            vec4 environmentIrradiance4 = sampleReflection(irradianceSampler, reflectionCoords);
+            environmentIrradiance = environmentIrradiance4.rgb;
+            #ifdef RGBDREFLECTION
+                environmentIrradiance.rgb = fromRGBD(environmentIrradiance4);
+            #endif
+
+            #ifdef GAMMAREFLECTION
+                environmentIrradiance.rgb = toLinearSpace(environmentIrradiance.rgb);
+            #endif
+        #endif
+
+        // _____________________________ Levels _____________________________________
+        environmentRadiance.rgb *= vReflectionInfos.x;
+        environmentRadiance.rgb *= vReflectionColor.rgb;
+        environmentIrradiance *= vReflectionColor.rgb;
+
+        outParams.environmentRadiance = environmentRadiance;
+        outParams.environmentIrradiance = environmentIrradiance;
+        outParams.reflectionCoords = reflectionCoords;
+    }
+#endif

+ 161 - 0
src/Shaders/ShadersInclude/pbrBlockReflectivity.fx

@@ -0,0 +1,161 @@
+struct reflectivityOutParams
+{
+    float microSurface;
+    float roughness;
+    vec3 surfaceReflectivityColor;
+#ifdef METALLICWORKFLOW
+    vec3 surfaceAlbedo;
+#endif
+#if defined(METALLICWORKFLOW) && defined(REFLECTIVITY)  && defined(AOSTOREINMETALMAPRED)
+    vec3 ambientOcclusionColor;
+#endif
+#if DEBUGMODE > 0
+    vec4 surfaceMetallicColorMap;
+    vec4 surfaceReflectivityColorMap;
+    vec2 metallicRoughness;
+    vec3 metallicF0;
+#endif
+};
+
+void reflectivityBlock(
+    const in vec4 vReflectivityColor,
+    const in vec2 uvOffset,
+#ifdef METALLICWORKFLOW
+    const in vec3 surfaceAlbedo,
+#endif
+#ifdef REFLECTIVITY
+    const in vec3 vReflectivityInfos,
+    const in vec2 vReflectivityUV,
+    const in sampler2D reflectivitySampler,
+#endif
+#if defined(METALLICWORKFLOW) && defined(REFLECTIVITY)  && defined(AOSTOREINMETALMAPRED)
+    const in vec3 ambientOcclusionColor,
+#endif
+#ifdef MICROSURFACEMAP
+    const in vec2 vMicroSurfaceSamplerUV_,
+    const in vec2 vMicroSurfaceSamplerInfos,
+    const in sampler2D microSurfaceSampler,
+#endif
+    out reflectivityOutParams outParams
+)
+{
+    float microSurface = vReflectivityColor.a;
+    vec3 surfaceReflectivityColor = vReflectivityColor.rgb;
+
+    #ifdef METALLICWORKFLOW
+        vec2 metallicRoughness = surfaceReflectivityColor.rg;
+
+        #ifdef REFLECTIVITY
+            vec4 surfaceMetallicColorMap = texture2D(reflectivitySampler, vReflectivityUV + uvOffset);
+
+            #if DEBUGMODE > 0
+                outParams.surfaceMetallicColorMap = surfaceMetallicColorMap;
+            #endif
+
+            #ifdef AOSTOREINMETALMAPRED
+                vec3 aoStoreInMetalMap = vec3(surfaceMetallicColorMap.r, surfaceMetallicColorMap.r, surfaceMetallicColorMap.r);
+                outParams.ambientOcclusionColor = mix(ambientOcclusionColor, aoStoreInMetalMap, vReflectivityInfos.z);
+            #endif
+
+            #ifdef METALLNESSSTOREINMETALMAPBLUE
+                metallicRoughness.r *= surfaceMetallicColorMap.b;
+            #else
+                metallicRoughness.r *= surfaceMetallicColorMap.r;
+            #endif
+
+            #ifdef ROUGHNESSSTOREINMETALMAPALPHA
+                metallicRoughness.g *= surfaceMetallicColorMap.a;
+            #else
+                #ifdef ROUGHNESSSTOREINMETALMAPGREEN
+                    metallicRoughness.g *= surfaceMetallicColorMap.g;
+                #endif
+            #endif
+        #endif
+
+        #ifdef MICROSURFACEMAP
+            vec4 microSurfaceTexel = texture2D(microSurfaceSampler, vMicroSurfaceSamplerUV_ + uvOffset) * vMicroSurfaceSamplerInfos.y;
+            metallicRoughness.g *= microSurfaceTexel.r;
+        #endif
+
+        #if DEBUGMODE > 0
+            outParams.metallicRoughness = metallicRoughness;
+        #endif
+
+        #define CUSTOM_FRAGMENT_UPDATE_METALLICROUGHNESS
+        
+        // Compute microsurface from roughness.
+        microSurface = 1.0 - metallicRoughness.g;
+
+        // Diffuse is used as the base of the reflectivity.
+        vec3 baseColor = surfaceAlbedo;
+
+        #ifdef REFLECTANCE
+            // *** NOT USED ANYMORE ***
+            // Following Frostbite Remapping,
+            // https://seblagarde.files.wordpress.com/2015/07/course_notes_moving_frostbite_to_pbr_v32.pdf page 115
+            // vec3 f0 = 0.16 * reflectance * reflectance * (1.0 - metallic) + baseColor * metallic;
+            // where 0.16 * reflectance * reflectance remaps the reflectance to allow storage in 8 bit texture
+
+            // Compute the converted diffuse.
+            outParams.surfaceAlbedo = baseColor.rgb * (1.0 - metallicRoughness.r);
+
+            // Compute the converted reflectivity.
+            surfaceReflectivityColor = mix(0.16 * reflectance * reflectance, baseColor, metallicRoughness.r);
+        #else
+            vec3 metallicF0 = vec3(vReflectivityColor.a, vReflectivityColor.a, vReflectivityColor.a);
+            #ifdef METALLICF0FACTORFROMMETALLICMAP
+                #ifdef REFLECTIVITY
+                    metallicF0 *= surfaceMetallicColorMap.a;
+                #endif
+            #endif
+
+            #if DEBUGMODE > 0
+                outParams.metallicF0 = metallicF0;
+            #endif
+
+            // Compute the converted diffuse.
+            outParams.surfaceAlbedo = mix(baseColor.rgb * (1.0 - metallicF0.r), vec3(0., 0., 0.), metallicRoughness.r);
+
+            // Compute the converted reflectivity.
+            surfaceReflectivityColor = mix(metallicF0, baseColor, metallicRoughness.r);
+        #endif
+    #else
+        #ifdef REFLECTIVITY
+            vec4 surfaceReflectivityColorMap = texture2D(reflectivitySampler, vReflectivityUV + uvOffset);
+            surfaceReflectivityColor *= toLinearSpace(surfaceReflectivityColorMap.rgb);
+            surfaceReflectivityColor *= vReflectivityInfos.y;
+
+            #if DEBUGMODE > 0
+                outParams.surfaceReflectivityColorMap = surfaceReflectivityColorMap;
+                vec2 metallicRoughness;
+                vec3 metallicF0;
+            #endif
+
+            #ifdef MICROSURFACEFROMREFLECTIVITYMAP
+                microSurface *= surfaceReflectivityColorMap.a;
+                microSurface *= vReflectivityInfos.z;
+            #else
+                #ifdef MICROSURFACEAUTOMATIC
+                    microSurface *= computeDefaultMicroSurface(microSurface, surfaceReflectivityColor);
+                #endif
+
+                #ifdef MICROSURFACEMAP
+                    vec4 microSurfaceTexel = texture2D(microSurfaceSampler, vMicroSurfaceSamplerUV_ + uvOffset) * vMicroSurfaceSamplerInfos.y;
+                    microSurface *= microSurfaceTexel.r;
+                #endif
+                
+                #define CUSTOM_FRAGMENT_UPDATE_MICROSURFACE
+                
+            #endif
+        #endif
+    #endif
+
+	// Adapt microSurface.
+    microSurface = saturate(microSurface);
+    // Compute roughness.
+    float roughness = 1. - microSurface;
+
+    outParams.microSurface = microSurface;
+    outParams.roughness = roughness;
+    outParams.surfaceReflectivityColor = surfaceReflectivityColor;
+}

+ 212 - 0
src/Shaders/ShadersInclude/pbrBlockSheen.fx

@@ -0,0 +1,212 @@
+#ifdef SHEEN
+    struct sheenOutParams
+    {
+        float sheenIntensity;
+        vec3 sheenColor;
+        float sheenRoughness;
+    #ifdef SHEEN_LINKWITHALBEDO
+        vec3 surfaceAlbedo;
+    #endif
+    #if defined(ENVIRONMENTBRDF) && defined(SHEEN_ALBEDOSCALING)
+        float sheenAlbedoScaling;
+    #endif
+    #if defined(REFLECTION) && defined(ENVIRONMENTBRDF)
+        vec3 finalSheenRadianceScaled;
+    #endif
+    #if DEBUGMODE > 0
+        vec4 sheenMapData;
+        vec3 sheenEnvironmentReflectance;
+    #endif
+    };
+
+    void sheenBlock(
+        const in vec4 vSheenColor,
+    #ifdef SHEEN_ROUGHNESS
+        const in float vSheenRoughness,
+    #endif
+        const in float roughness,
+    #ifdef SHEEN_TEXTURE
+        const in vec2 vSheenUV,
+        const in vec2 vSheenInfos,
+        const in vec2 uvOffset,
+        const in sampler2D sheenSampler,
+    #endif
+        const in float reflectance,
+    #ifdef SHEEN_LINKWITHALBEDO
+        const in vec3 baseColor,
+        const in vec3 surfaceAlbedo,
+    #endif
+    #ifdef ENVIRONMENTBRDF
+        const in float NdotV,
+    #endif
+    #if defined(REFLECTION) && defined(ENVIRONMENTBRDF)
+        const in vec2 AARoughnessFactors,
+        const in vec3 vReflectionMicrosurfaceInfos,
+        const in vec2 vReflectionInfos,
+        const in vec3 vReflectionColor,
+        const in vec4 vLightingIntensity,
+        #ifdef REFLECTIONMAP_3D
+            const in samplerCube reflectionSampler,
+            const in vec3 reflectionCoords,
+        #else
+            const in sampler2D reflectionSampler,
+            const in vec2 reflectionCoords,
+        #endif
+        const in float NdotVUnclamped,
+        #ifndef LODBASEDMICROSFURACE
+            const in sampler2D reflectionSamplerLow,
+            const in sampler2D reflectionSamplerHigh,
+        #endif
+        const in vec3 environmentBrdf,
+        #if !defined(REFLECTIONMAP_SKYBOX) && defined(RADIANCEOCCLUSION)
+            const in float seo,
+        #endif
+        #if !defined(REFLECTIONMAP_SKYBOX) && defined(HORIZONOCCLUSION) && defined(BUMP) && defined(REFLECTIONMAP_3D)
+            const in float eho,
+        #endif
+    #endif
+        out sheenOutParams outParams
+    )
+    {
+        float sheenIntensity = vSheenColor.a;
+
+        #ifdef SHEEN_TEXTURE
+            vec4 sheenMapData = texture2D(sheenSampler, vSheenUV + uvOffset) * vSheenInfos.y;
+            sheenIntensity *= sheenMapData.a;
+            #if DEBUGMODE > 0
+                outParams.sheenMapData = sheenMapData;
+            #endif
+        #endif
+
+        #ifdef SHEEN_LINKWITHALBEDO
+            float sheenFactor = pow5(1.0-sheenIntensity);
+            vec3 sheenColor = baseColor.rgb*(1.0-sheenFactor);
+            float sheenRoughness = sheenIntensity;
+            outParams.surfaceAlbedo = surfaceAlbedo * sheenFactor;
+        #else
+            vec3 sheenColor = vSheenColor.rgb;
+            #ifdef SHEEN_TEXTURE
+                sheenColor.rgb *= toLinearSpace(sheenMapData.rgb);
+            #endif
+            
+            #ifdef SHEEN_ROUGHNESS
+                float sheenRoughness = vSheenRoughness;
+            #else
+                float sheenRoughness = roughness;
+            #endif
+
+            // Sheen Lobe Layering.
+            #if !defined(SHEEN_ALBEDOSCALING)
+                sheenIntensity *= (1. - reflectance);
+            #endif
+
+            // Remap F0 and sheen.
+            sheenColor *= sheenIntensity;
+        #endif
+
+        // _____________________________ Sheen Environment __________________________
+        #ifdef ENVIRONMENTBRDF
+                /*#ifdef SHEEN_SOFTER
+                vec3 environmentSheenBrdf = vec3(0., 0., getBRDFLookupCharlieSheen(NdotV, sheenRoughness));
+            #else*/
+                #ifdef SHEEN_ROUGHNESS
+                    vec3 environmentSheenBrdf = getBRDFLookup(NdotV, sheenRoughness);
+                #else
+                    vec3 environmentSheenBrdf = environmentBrdf;
+                #endif
+            /*#endif*/
+        #endif
+
+        #if defined(REFLECTION) && defined(ENVIRONMENTBRDF)
+            float sheenAlphaG = convertRoughnessToAverageSlope(sheenRoughness);
+
+            #ifdef SPECULARAA
+                // Adapt linear roughness (alphaG) to geometric curvature of the current pixel.
+                sheenAlphaG += AARoughnessFactors.y;
+            #endif
+
+            vec4 environmentSheenRadiance = vec4(0., 0., 0., 0.);
+
+            // _____________________________ 2D vs 3D Maps ________________________________
+            #if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX)
+                float sheenReflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, sheenAlphaG, NdotVUnclamped);
+            #elif defined(LINEARSPECULARREFLECTION)
+                float sheenReflectionLOD = getLinearLodFromRoughness(vReflectionMicrosurfaceInfos.x, sheenRoughness);
+            #else
+                float sheenReflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, sheenAlphaG);
+            #endif
+
+            #ifdef LODBASEDMICROSFURACE
+                // Apply environment convolution scale/offset filter tuning parameters to the mipmap LOD selection
+                sheenReflectionLOD = sheenReflectionLOD * vReflectionMicrosurfaceInfos.y + vReflectionMicrosurfaceInfos.z;
+                environmentSheenRadiance = sampleReflectionLod(reflectionSampler, reflectionCoords, sheenReflectionLOD);
+            #else
+                float lodSheenReflectionNormalized = saturate(sheenReflectionLOD / log2(vReflectionMicrosurfaceInfos.x));
+                float lodSheenReflectionNormalizedDoubled = lodSheenReflectionNormalized * 2.0;
+
+                vec4 environmentSheenMid = sampleReflection(reflectionSampler, reflectionCoords);
+                if (lodSheenReflectionNormalizedDoubled < 1.0){
+                    environmentSheenRadiance = mix(
+                        sampleReflection(reflectionSamplerHigh, reflectionCoords),
+                        environmentSheenMid,
+                        lodSheenReflectionNormalizedDoubled
+                    );
+                } else {
+                    environmentSheenRadiance = mix(
+                        environmentSheenMid,
+                        sampleReflection(reflectionSamplerLow, reflectionCoords),
+                        lodSheenReflectionNormalizedDoubled - 1.0
+                    );
+                }
+            #endif
+
+            #ifdef RGBDREFLECTION
+                environmentSheenRadiance.rgb = fromRGBD(environmentSheenRadiance);
+            #endif
+
+            #ifdef GAMMAREFLECTION
+                environmentSheenRadiance.rgb = toLinearSpace(environmentSheenRadiance.rgb);
+            #endif
+
+            // _____________________________ Levels _____________________________________
+            environmentSheenRadiance.rgb *= vReflectionInfos.x;
+            environmentSheenRadiance.rgb *= vReflectionColor.rgb;
+
+            vec3 sheenEnvironmentReflectance = getSheenReflectanceFromBRDFLookup(sheenColor, environmentSheenBrdf);
+
+            #if !defined(REFLECTIONMAP_SKYBOX) && defined(RADIANCEOCCLUSION)
+                sheenEnvironmentReflectance *= seo;
+            #endif
+            #if !defined(REFLECTIONMAP_SKYBOX) && defined(HORIZONOCCLUSION) && defined(BUMP) && defined(REFLECTIONMAP_3D)
+                sheenEnvironmentReflectance *= eho;
+            #endif
+
+            #if DEBUGMODE > 0
+                outParams.sheenEnvironmentReflectance = sheenEnvironmentReflectance;
+            #endif
+
+            outParams.finalSheenRadianceScaled = 
+                environmentSheenRadiance.rgb *
+                sheenEnvironmentReflectance *
+                vLightingIntensity.z;
+
+            // #if defined(MS_BRDF_ENERGY_CONSERVATION)
+                // The sheen does not use the same BRDF so not energy conservation is possible
+                // Should be less a problem as it is usually not metallic
+                // finalSheenScaled *= energyConservationFactor;
+            // #endif
+        #endif
+
+        #if defined(ENVIRONMENTBRDF) && defined(SHEEN_ALBEDOSCALING)
+            // Sheen Lobe Layering.
+            // environmentSheenBrdf.b is (integral on hemisphere)[f_sheen*cos(theta)*dtheta*dphi], which happens to also be the directional albedo needed for albedo scaling.
+            // See section 6.2.3 in https://dassaultsystemes-technology.github.io/EnterprisePBRShadingModel/spec-2021x.md.html#components/sheen
+            outParams.sheenAlbedoScaling = 1.0 - sheenIntensity * max(max(sheenColor.r, sheenColor.g), sheenColor.b) * environmentSheenBrdf.b;
+        #endif
+
+        // _____________________________ Out parameters __________________________
+        outParams.sheenIntensity = sheenIntensity;
+        outParams.sheenColor = sheenColor;
+        outParams.sheenRoughness = sheenRoughness;
+    }
+#endif

+ 339 - 0
src/Shaders/ShadersInclude/pbrBlockSubSurface.fx

@@ -0,0 +1,339 @@
+struct subSurfaceOutParams
+{
+    vec3 specularEnvironmentReflectance;
+#ifdef SS_REFRACTION
+    vec3 finalRefraction;
+    vec3 surfaceAlbedo;
+    #ifdef SS_LINKREFRACTIONTOTRANSPARENCY
+        float alpha;
+    #endif
+    #ifdef REFLECTION
+        float refractionFactorForIrradiance;
+    #endif
+#endif
+#ifdef SS_TRANSLUCENCY
+    vec3 transmittance;
+    #ifdef REFLECTION
+        vec3 refractionIrradiance;
+    #endif
+#endif
+#if DEBUGMODE > 0
+    vec4 thicknessMap;
+    vec4 environmentRefraction;
+    vec3 refractionTransmittance;
+#endif
+};
+
+#ifdef SUBSURFACE
+    void subSurfaceBlock(
+        const in vec2 vThicknessParam,
+        const in vec4 vTintColor,
+        const in vec3 normalW,
+        const in vec3 specularEnvironmentReflectance,
+    #ifdef SS_THICKNESSANDMASK_TEXTURE
+        const in vec2 vThicknessUV,
+        const in vec2 uvOffset,
+        const in sampler2D thicknessSampler,
+    #endif
+    #ifdef REFLECTION
+        #ifdef SS_TRANSLUCENCY
+            const in mat4 reflectionMatrix,
+            #ifdef USESPHERICALFROMREFLECTIONMAP
+                #if !defined(NORMAL) || !defined(USESPHERICALINVERTEX)
+                    const in vec3 irradianceVector_,
+                #endif
+            #endif
+            #ifdef USEIRRADIANCEMAP
+                #ifdef REFLECTIONMAP_3D
+                    const in samplerCube irradianceSampler,
+                #else
+                    const in sampler2D irradianceSampler,
+                #endif
+            #endif
+        #endif
+    #endif
+    #ifdef SS_REFRACTION
+        const in vec3 vPositionW,
+        const in vec3 viewDirectionW,
+        const in mat4 view,
+        const in vec3 surfaceAlbedo,
+        const in vec4 vRefractionInfos,
+        const in mat4 refractionMatrix,
+        const in vec3 vRefractionMicrosurfaceInfos,
+        const in vec4 vLightingIntensity,
+        #ifdef SS_LINKREFRACTIONTOTRANSPARENCY
+            const in float alpha,
+        #endif
+        #ifdef SS_LODINREFRACTIONALPHA
+            const in float NdotVUnclamped,
+        #endif
+        #ifdef SS_LINEARSPECULARREFRACTION
+            const in float roughness,
+        #else
+            const in float alphaG,
+        #endif
+        #ifdef SS_REFRACTIONMAP_3D
+            const in samplerCube refractionSampler,
+            #ifndef LODBASEDMICROSFURACE
+                const in samplerCube refractionSamplerLow,
+                const in samplerCube refractionSamplerHigh,
+            #endif
+        #else
+            const in sampler2D refractionSampler,
+            #ifndef LODBASEDMICROSFURACE
+                const in sampler2D refractionSamplerLow,
+                const in sampler2D refractionSamplerHigh,
+            #endif
+        #endif
+        #ifdef ANISOTROPIC
+            const in anisotropicOutParams anisotropicOut,
+        #endif
+    #endif
+    #ifdef SS_TRANSLUCENCY
+        const in vec3 vDiffusionDistance,
+    #endif
+        out subSurfaceOutParams outParams
+    )
+    {
+        outParams.specularEnvironmentReflectance = specularEnvironmentReflectance;
+
+    // ______________________________________________________________________________________
+    // _____________________________ Intensities & thickness ________________________________
+    // ______________________________________________________________________________________
+    #ifdef SS_REFRACTION
+        float refractionIntensity = vSubSurfaceIntensity.x;
+        #ifdef SS_LINKREFRACTIONTOTRANSPARENCY
+            refractionIntensity *= (1.0 - alpha);
+            // Put alpha back to 1;
+            outParams.alpha = 1.0;
+        #endif
+    #endif
+    #ifdef SS_TRANSLUCENCY
+        float translucencyIntensity = vSubSurfaceIntensity.y;
+    #endif
+    #ifdef SS_SCATTERING
+        float scatteringIntensity = vSubSurfaceIntensity.z;
+    #endif
+
+    #ifdef SS_THICKNESSANDMASK_TEXTURE
+        vec4 thicknessMap = texture2D(thicknessSampler, vThicknessUV + uvOffset);
+        float thickness = thicknessMap.r * vThicknessParam.y + vThicknessParam.x;
+
+        #if DEBUGMODE > 0
+            outParams.thicknessMap = thicknessMap;
+        #endif
+
+        #ifdef SS_MASK_FROM_THICKNESS_TEXTURE
+            #ifdef SS_REFRACTION
+                refractionIntensity *= thicknessMap.g;
+            #endif
+            #ifdef SS_TRANSLUCENCY
+                translucencyIntensity *= thicknessMap.b;
+            #endif
+            #ifdef SS_SCATTERING
+                scatteringIntensity *= thicknessMap.a;
+            #endif
+        #endif
+    #else
+        float thickness = vThicknessParam.y;
+    #endif
+
+    // _________________________________________________________________________________________
+    // _____________________________ Translucency transmittance ________________________________
+    // _________________________________________________________________________________________
+    #ifdef SS_TRANSLUCENCY
+        thickness = maxEps(thickness);
+        vec3 transmittance = transmittanceBRDF_Burley(vTintColor.rgb, vDiffusionDistance, thickness);
+        transmittance *= translucencyIntensity;
+        outParams.transmittance = transmittance;
+    #endif
+
+    // _____________________________________________________________________________________
+    // _____________________________ Refraction environment ________________________________
+    // _____________________________________________________________________________________
+    #ifdef SS_REFRACTION
+        vec4 environmentRefraction = vec4(0., 0., 0., 0.);
+
+        #ifdef ANISOTROPIC
+            vec3 refractionVector = refract(-viewDirectionW, anisotropicOut.anisotropicNormal, vRefractionInfos.y);
+        #else
+            vec3 refractionVector = refract(-viewDirectionW, normalW, vRefractionInfos.y);
+        #endif
+
+        #ifdef SS_REFRACTIONMAP_OPPOSITEZ
+            refractionVector.z *= -1.0;
+        #endif
+
+        // _____________________________ 2D vs 3D Maps ________________________________
+        #ifdef SS_REFRACTIONMAP_3D
+            refractionVector.y = refractionVector.y * vRefractionInfos.w;
+            vec3 refractionCoords = refractionVector;
+            refractionCoords = vec3(refractionMatrix * vec4(refractionCoords, 0));
+        #else
+            vec3 vRefractionUVW = vec3(refractionMatrix * (view * vec4(vPositionW + refractionVector * vRefractionInfos.z, 1.0)));
+            vec2 refractionCoords = vRefractionUVW.xy / vRefractionUVW.z;
+            refractionCoords.y = 1.0 - refractionCoords.y;
+        #endif
+
+        #ifdef SS_LODINREFRACTIONALPHA
+            float refractionLOD = getLodFromAlphaG(vRefractionMicrosurfaceInfos.x, alphaG, NdotVUnclamped);
+        #elif defined(SS_LINEARSPECULARREFRACTION)
+            float refractionLOD = getLinearLodFromRoughness(vRefractionMicrosurfaceInfos.x, roughness);
+        #else
+            float refractionLOD = getLodFromAlphaG(vRefractionMicrosurfaceInfos.x, alphaG);
+        #endif
+
+        #ifdef LODBASEDMICROSFURACE
+            // Apply environment convolution scale/offset filter tuning parameters to the mipmap LOD selection
+            refractionLOD = refractionLOD * vRefractionMicrosurfaceInfos.y + vRefractionMicrosurfaceInfos.z;
+
+            #ifdef SS_LODINREFRACTIONALPHA
+                // Automatic LOD adjustment to ensure that the smoothness-based environment LOD selection
+                // is constrained to appropriate LOD levels in order to prevent aliasing.
+                // The environment map is first sampled without custom LOD selection to determine
+                // the hardware-selected LOD, and this is then used to constrain the final LOD selection
+                // so that excessive surface smoothness does not cause aliasing (e.g. on curved geometry
+                // where the normal is varying rapidly).
+
+                // Note: Shader Model 4.1 or higher can provide this directly via CalculateLevelOfDetail(), and
+                // manual calculation via derivatives is also possible, but for simplicity we use the 
+                // hardware LOD calculation with the alpha channel containing the LOD for each mipmap.
+                float automaticRefractionLOD = UNPACK_LOD(sampleRefraction(refractionSampler, refractionCoords).a);
+                float requestedRefractionLOD = max(automaticRefractionLOD, refractionLOD);
+            #else
+                float requestedRefractionLOD = refractionLOD;
+            #endif
+
+            environmentRefraction = sampleRefractionLod(refractionSampler, refractionCoords, requestedRefractionLOD);
+        #else
+            float lodRefractionNormalized = saturate(refractionLOD / log2(vRefractionMicrosurfaceInfos.x));
+            float lodRefractionNormalizedDoubled = lodRefractionNormalized * 2.0;
+
+            vec4 environmentRefractionMid = sampleRefraction(refractionSampler, refractionCoords);
+            if (lodRefractionNormalizedDoubled < 1.0){
+                environmentRefraction = mix(
+                    sampleRefraction(refractionSamplerHigh, refractionCoords),
+                    environmentRefractionMid,
+                    lodRefractionNormalizedDoubled
+                );
+            } else {
+                environmentRefraction = mix(
+                    environmentRefractionMid,
+                    sampleRefraction(refractionSamplerLow, refractionCoords),
+                    lodRefractionNormalizedDoubled - 1.0
+                );
+            }
+        #endif
+
+        #ifdef SS_RGBDREFRACTION
+            environmentRefraction.rgb = fromRGBD(environmentRefraction);
+        #endif
+
+        #ifdef SS_GAMMAREFRACTION
+            environmentRefraction.rgb = toLinearSpace(environmentRefraction.rgb);
+        #endif
+
+        // _____________________________ Levels _____________________________________
+        environmentRefraction.rgb *= vRefractionInfos.x;
+    #endif
+
+    // _______________________________________________________________________________
+    // _____________________________ Final Refraction ________________________________
+    // _______________________________________________________________________________
+    #ifdef SS_REFRACTION
+        vec3 refractionTransmittance = vec3(refractionIntensity);
+        #ifdef SS_THICKNESSANDMASK_TEXTURE
+            vec3 volumeAlbedo = computeColorAtDistanceInMedia(vTintColor.rgb, vTintColor.w);
+
+            // // Simulate Flat Surface
+            // thickness /=  dot(refractionVector, -normalW);
+
+            // // Simulate Curved Surface
+            // float NdotRefract = dot(normalW, refractionVector);
+            // thickness *= -NdotRefract;
+
+            refractionTransmittance *= cocaLambert(volumeAlbedo, thickness);
+        #elif defined(SS_LINKREFRACTIONTOTRANSPARENCY)
+            // Tint the material with albedo.
+            float maxChannel = max(max(surfaceAlbedo.r, surfaceAlbedo.g), surfaceAlbedo.b);
+            vec3 volumeAlbedo = saturate(maxChannel * surfaceAlbedo);
+
+            // Tint reflectance
+            environmentRefraction.rgb *= volumeAlbedo;
+        #else
+            // Compute tint from min distance only.
+            vec3 volumeAlbedo = computeColorAtDistanceInMedia(vTintColor.rgb, vTintColor.w);
+            refractionTransmittance *= cocaLambert(volumeAlbedo, vThicknessParam.y);
+        #endif
+
+        // Decrease Albedo Contribution
+        outParams.surfaceAlbedo = surfaceAlbedo * (1. - refractionIntensity);
+
+        #ifdef REFLECTION
+            // Decrease irradiance Contribution
+            outParams.refractionFactorForIrradiance = (1. - refractionIntensity);
+            //environmentIrradiance *= (1. - refractionIntensity);
+        #endif
+
+        // Add Multiple internal bounces.
+        vec3 bounceSpecularEnvironmentReflectance = (2.0 * specularEnvironmentReflectance) / (1.0 + specularEnvironmentReflectance);
+        outParams.specularEnvironmentReflectance = mix(bounceSpecularEnvironmentReflectance, specularEnvironmentReflectance, refractionIntensity);
+
+        // In theory T = 1 - R.
+        refractionTransmittance *= 1.0 - outParams.specularEnvironmentReflectance;
+
+        #if DEBUGMODE > 0
+            outParams.refractionTransmittance = refractionTransmittance;
+        #endif
+
+        outParams.finalRefraction = environmentRefraction.rgb * refractionTransmittance * vLightingIntensity.z;
+
+        #if DEBUGMODE > 0
+            outParams.environmentRefraction = environmentRefraction;
+        #endif
+    #endif
+
+    // __________________________________________________________________________________
+    // _______________________________  IBL Translucency ________________________________
+    // __________________________________________________________________________________
+    #if defined(REFLECTION) && defined(SS_TRANSLUCENCY)
+        #if defined(NORMAL) && defined(USESPHERICALINVERTEX) || !defined(USESPHERICALFROMREFLECTIONMAP)
+            vec3 irradianceVector = vec3(reflectionMatrix * vec4(normalW, 0)).xyz;
+            #ifdef REFLECTIONMAP_OPPOSITEZ
+                irradianceVector.z *= -1.0;
+            #endif
+        #else
+            vec3 irradianceVector = irradianceVector_;
+        #endif
+
+        #if defined(USESPHERICALFROMREFLECTIONMAP)
+            vec3 refractionIrradiance = computeEnvironmentIrradiance(-irradianceVector);
+        #elif defined(USEIRRADIANCEMAP)
+            #ifdef REFLECTIONMAP_3D
+                vec3 irradianceCoords = irradianceVector;
+            #else
+                vec2 irradianceCoords = irradianceVector.xy;
+                #ifdef REFLECTIONMAP_PROJECTION
+                    irradianceCoords /= irradianceVector.z;
+                #endif
+                irradianceCoords.y = 1.0 - irradianceCoords.y;
+            #endif
+
+            vec4 refractionIrradiance = sampleReflection(irradianceSampler, -irradianceCoords);
+            #ifdef RGBDREFLECTION
+                refractionIrradiance.rgb = fromRGBD(refractionIrradiance);
+            #endif
+
+            #ifdef GAMMAREFLECTION
+                refractionIrradiance.rgb = toLinearSpace(refractionIrradiance.rgb);
+            #endif
+        #else
+            vec4 refractionIrradiance = vec4(0.);
+        #endif
+
+        refractionIrradiance.rgb *= transmittance;
+        outParams.refractionIrradiance = refractionIrradiance.rgb;
+    #endif
+    }
+#endif
+

+ 30 - 30
src/Shaders/ShadersInclude/pbrDebug.fx

@@ -9,11 +9,11 @@
     #elif DEBUGMODE == 2 && defined(NORMAL)
         gl_FragColor.rgb = vNormalW.rgb;
         #define DEBUGMODE_NORMALIZE
-    #elif DEBUGMODE == 3 && (defined(BUMP) || defined(PARALLAX) || defined(ANISOTROPIC))
+    #elif DEBUGMODE == 3 && defined(BUMP) || DEBUGMODE == 3 && defined(PARALLAX) || DEBUGMODE == 3 && defined(ANISOTROPIC)
         // Tangents
         gl_FragColor.rgb = TBN[0];
         #define DEBUGMODE_NORMALIZE
-    #elif DEBUGMODE == 4 && (defined(BUMP) || defined(PARALLAX) || defined(ANISOTROPIC))
+    #elif DEBUGMODE == 4 && defined(BUMP) || DEBUGMODE == 4 && defined(PARALLAX) || DEBUGMODE == 4 && defined(ANISOTROPIC)
         // BiTangents
         gl_FragColor.rgb = TBN[1];
         #define DEBUGMODE_NORMALIZE
@@ -27,30 +27,30 @@
         gl_FragColor.rgb = vec3(vMainUV2, 0.0);
     #elif DEBUGMODE == 8 && defined(CLEARCOAT) && defined(CLEARCOAT_BUMP)
         // ClearCoat Tangents
-        gl_FragColor.rgb = TBNClearCoat[0];
+        gl_FragColor.rgb = clearcoatOut.TBNClearCoat[0];
         #define DEBUGMODE_NORMALIZE
     #elif DEBUGMODE == 9 && defined(CLEARCOAT) && defined(CLEARCOAT_BUMP)
         // ClearCoat BiTangents
-        gl_FragColor.rgb = TBNClearCoat[1];
+        gl_FragColor.rgb = clearcoatOut.TBNClearCoat[1];
         #define DEBUGMODE_NORMALIZE
     #elif DEBUGMODE == 10 && defined(CLEARCOAT)
         // ClearCoat Bump Normals
-        gl_FragColor.rgb = clearCoatNormalW;
+        gl_FragColor.rgb = clearcoatOut.clearCoatNormalW;
         #define DEBUGMODE_NORMALIZE
     #elif DEBUGMODE == 11 && defined(ANISOTROPIC)
-        gl_FragColor.rgb = anisotropicNormal;
+        gl_FragColor.rgb = anisotropicOut.anisotropicNormal;
         #define DEBUGMODE_NORMALIZE
     #elif DEBUGMODE == 12 && defined(ANISOTROPIC)
-        gl_FragColor.rgb = anisotropicTangent;
+        gl_FragColor.rgb = anisotropicOut.anisotropicTangent;
         #define DEBUGMODE_NORMALIZE
     #elif DEBUGMODE == 13 && defined(ANISOTROPIC)
-        gl_FragColor.rgb = anisotropicBitangent;
+        gl_FragColor.rgb = anisotropicOut.anisotropicBitangent;
         #define DEBUGMODE_NORMALIZE
 // Maps
     #elif DEBUGMODE == 20 && defined(ALBEDO)
         gl_FragColor.rgb = albedoTexture.rgb;
     #elif DEBUGMODE == 21 && defined(AMBIENT)
-        gl_FragColor.rgb = ambientOcclusionColorMap.rgb;
+        gl_FragColor.rgb = aoOut.ambientOcclusionColorMap.rgb;
     #elif DEBUGMODE == 22 && defined(OPACITY)
         gl_FragColor.rgb = opacityMap.rgb;
     #elif DEBUGMODE == 23 && defined(EMISSIVE)
@@ -60,30 +60,30 @@
         gl_FragColor.rgb = lightmapColor.rgb;
         #define DEBUGMODE_GAMMA
     #elif DEBUGMODE == 25 && defined(REFLECTIVITY) && defined(METALLICWORKFLOW)
-        gl_FragColor.rgb = surfaceMetallicColorMap.rgb;
+        gl_FragColor.rgb = reflectivityOut.surfaceMetallicColorMap.rgb;
     #elif DEBUGMODE == 26 && defined(REFLECTIVITY) && !defined(METALLICWORKFLOW)
-        gl_FragColor.rgb = surfaceReflectivityColorMap.rgb;
+        gl_FragColor.rgb = reflectivityOut.surfaceReflectivityColorMap.rgb;
         #define DEBUGMODE_GAMMA
     #elif DEBUGMODE == 27 && defined(CLEARCOAT) && defined(CLEARCOAT_TEXTURE)
-        gl_FragColor.rgb = vec3(clearCoatMapData.rg, 0.0);
+        gl_FragColor.rgb = vec3(clearcoatOut.clearCoatMapData.rg, 0.0);
     #elif DEBUGMODE == 28 && defined(CLEARCOAT) && defined(CLEARCOAT_TINT) && defined(CLEARCOAT_TINT_TEXTURE)
-        gl_FragColor.rgb = clearCoatTintMapData.rgb;
+        gl_FragColor.rgb = clearcoatOut.clearCoatTintMapData.rgb;
     #elif DEBUGMODE == 29 && defined(SHEEN) && defined(SHEEN_TEXTURE)
-        gl_FragColor.rgb = sheenMapData.rgb;
+        gl_FragColor.rgb = sheenOut.sheenMapData.rgb;
     #elif DEBUGMODE == 30 && defined(ANISOTROPIC) && defined(ANISOTROPIC_TEXTURE)
-        gl_FragColor.rgb = anisotropyMapData.rgb;
+        gl_FragColor.rgb = anisotropicOut.anisotropyMapData.rgb;
     #elif DEBUGMODE == 31 && defined(SUBSURFACE) && defined(SS_THICKNESSANDMASK_TEXTURE)
-        gl_FragColor.rgb = thicknessMap.rgb;
+        gl_FragColor.rgb = subSurfaceOut.thicknessMap.rgb;
 // Env
     #elif DEBUGMODE == 40 && defined(SS_REFRACTION)
         // Base color.
-        gl_FragColor.rgb = environmentRefraction.rgb;
+        gl_FragColor.rgb = subSurfaceOut.environmentRefraction.rgb;
         #define DEBUGMODE_GAMMA
     #elif DEBUGMODE == 41 && defined(REFLECTION)
-        gl_FragColor.rgb = environmentRadiance.rgb;
+        gl_FragColor.rgb = reflectionOut.environmentRadiance.rgb;
         #define DEBUGMODE_GAMMA
     #elif DEBUGMODE == 42 && defined(CLEARCOAT) && defined(REFLECTION)
-        gl_FragColor.rgb = environmentClearCoatRadiance;
+        gl_FragColor.rgb = clearcoatOut.environmentClearCoatRadiance.rgb;
         #define DEBUGMODE_GAMMA
 // Lighting
     #elif DEBUGMODE == 50
@@ -99,19 +99,19 @@
         gl_FragColor.rgb = sheenBase.rgb;
         #define DEBUGMODE_GAMMA
     #elif DEBUGMODE == 54 && defined(REFLECTION)
-        gl_FragColor.rgb = environmentIrradiance.rgb;
+        gl_FragColor.rgb = reflectionOut.environmentIrradiance.rgb;
         #define DEBUGMODE_GAMMA
 // Lighting Params
     #elif DEBUGMODE == 60
         gl_FragColor.rgb = surfaceAlbedo.rgb;
         #define DEBUGMODE_GAMMA
     #elif DEBUGMODE == 61
-        gl_FragColor.rgb = specularEnvironmentR0;
+        gl_FragColor.rgb = clearcoatOut.specularEnvironmentR0;
         #define DEBUGMODE_GAMMA
     #elif DEBUGMODE == 62 && defined(METALLICWORKFLOW)
-        gl_FragColor.rgb = vec3(metallicRoughness.r);
+        gl_FragColor.rgb = vec3(reflectivityOut.metallicRoughness.r);
     #elif DEBUGMODE == 71 && defined(METALLICWORKFLOW)
-        gl_FragColor.rgb = metallicF0;
+        gl_FragColor.rgb = reflectivityOut.metallicF0;
     #elif DEBUGMODE == 63
         gl_FragColor.rgb = vec3(roughness);
     #elif DEBUGMODE == 64
@@ -119,16 +119,16 @@
     #elif DEBUGMODE == 65
         gl_FragColor.rgb = vec3(NdotV);
     #elif DEBUGMODE == 66 && defined(CLEARCOAT) && defined(CLEARCOAT_TINT)
-        gl_FragColor.rgb = clearCoatColor.rgb;
+        gl_FragColor.rgb = clearcoatOut.clearCoatColor.rgb;
         #define DEBUGMODE_GAMMA
     #elif DEBUGMODE == 67 && defined(CLEARCOAT)
-        gl_FragColor.rgb = vec3(clearCoatRoughness);
+        gl_FragColor.rgb = vec3(clearcoatOut.clearCoatRoughness);
     #elif DEBUGMODE == 68 && defined(CLEARCOAT)
-        gl_FragColor.rgb = vec3(clearCoatNdotV);
+        gl_FragColor.rgb = vec3(clearcoatOut.clearCoatNdotV);
     #elif DEBUGMODE == 69 && defined(SUBSURFACE) && defined(SS_TRANSLUCENCY)
-        gl_FragColor.rgb = transmittance;
+        gl_FragColor.rgb = subSurfaceOut.transmittance;
     #elif DEBUGMODE == 70 && defined(SUBSURFACE) && defined(SS_REFRACTION)
-        gl_FragColor.rgb = refractionTransmittance;
+        gl_FragColor.rgb = subSurfaceOut.refractionTransmittance;
 // Misc
     #elif DEBUGMODE == 80 && defined(RADIANCEOCCLUSION)
         gl_FragColor.rgb = vec3(seo);
@@ -140,10 +140,10 @@
         gl_FragColor.rgb = specularEnvironmentReflectance;
         #define DEBUGMODE_GAMMA
     #elif DEBUGMODE == 84 && defined(CLEARCOAT) && defined(ENVIRONMENTBRDF) && !defined(REFLECTIONMAP_SKYBOX)
-        gl_FragColor.rgb = clearCoatEnvironmentReflectance;
+        gl_FragColor.rgb = clearcoatOut.clearCoatEnvironmentReflectance;
         #define DEBUGMODE_GAMMA
     #elif DEBUGMODE == 85 && defined(SHEEN) && defined(REFLECTION)
-        gl_FragColor.rgb = sheenEnvironmentReflectance;
+        gl_FragColor.rgb = sheenOut.sheenEnvironmentReflectance;
         #define DEBUGMODE_GAMMA
     #elif DEBUGMODE == 86 && defined(ALPHABLEND)
         gl_FragColor.rgb = vec3(luminanceOverAlpha);

Tiedoston diff-näkymää rajattu, sillä se on liian suuri
+ 266 - 1134
src/Shaders/pbr.fragment.fx