Browse Source

ifdef everywhere

sebavan 6 years ago
parent
commit
514aa6ae22

+ 287 - 0
src/Shaders/ShadersInclude/pbrBRDFFunctions.fx

@@ -0,0 +1,287 @@
+// Constants
+#define FRESNEL_MAXIMUM_ON_ROUGH 0.25
+
+// ______________________________________________________________________
+//
+//                              BRDF LOOKUP
+// ______________________________________________________________________
+
+#ifdef MS_BRDF_ENERGY_CONSERVATION
+    // http://www.jcgt.org/published/0008/01/03/
+    // http://advances.realtimerendering.com/s2018/Siggraph%202018%20HDRP%20talk_with%20notes.pdf
+    vec3 getEnergyConservationFactor(const vec3 specularEnvironmentR0, vec2 environmentBrdf) {
+        return 1.0 + specularEnvironmentR0 * (1.0 / environmentBrdf.y - 1.0);
+    }
+#endif
+
+#ifdef ENVIRONMENTBRDF
+    vec2 getBRDFLookup(float NdotV, float perceptualRoughness, sampler2D brdfSampler) {
+        // Indexed on cos(theta) and roughness
+        vec2 UV = vec2(NdotV, perceptualRoughness);
+        
+        // We can find the scale and offset to apply to the specular value.
+        vec2 brdfLookup = texture2D(brdfSampler, UV).xy;
+
+        return brdfLookup;
+    }
+
+    vec3 getReflectanceFromBRDFLookup(const vec3 specularEnvironmentR0, vec2 environmentBrdf) {
+        #ifdef BRDF_V_HEIGHT_CORRELATED
+            vec3 reflectance = mix(environmentBrdf.xxx, environmentBrdf.yyy, specularEnvironmentR0);
+        #else
+            vec3 reflectance = specularEnvironmentR0 * environmentBrdf.x + environmentBrdf.y;
+        #endif
+        return reflectance;
+    }
+#else
+    vec3 getReflectanceFromAnalyticalBRDFLookup_Jones(float VdotN, vec3 reflectance0, vec3 reflectance90, float smoothness)
+    {
+        // Schlick fresnel approximation, extended with basic smoothness term so that rough surfaces do not approach reflectance90 at grazing angle
+        float weight = mix(FRESNEL_MAXIMUM_ON_ROUGH, 1.0, smoothness);
+        return reflectance0 + weight * (reflectance90 - reflectance0) * pow5(saturate(1.0 - VdotN));
+    }
+#endif
+
+#if defined(SHEEN) && defined(REFLECTION)
+    /**
+    * Special thanks to @romainguy for all the support :-)
+    * Analytical approximation of the pre-filtered DFG terms for the cloth shading
+    * model. This approximation is based on the Estevez & Kulla distribution term
+    * ("Charlie" sheen) and the Neubelt visibility term. See brdf.fs for more
+    * details.
+    */
+    vec2 getCharlieSheenAnalyticalBRDFLookup_RomainGuy(float NoV, float roughness) {
+        const vec3 c0 = vec3(0.95, 1250.0, 0.0095);
+        const vec4 c1 = vec4(0.04, 0.2, 0.3, 0.2);
+
+        float a = 1.0 - NoV;
+        float b = 1.0 - roughness;
+
+        float n = pow(c1.x + a, 64.0);
+        float e = b - c0.x;
+        float g = exp2(-(e * e) * c0.y);
+        float f = b + c1.y;
+        float a2 = a * a;
+        float a3 = a2 * a;
+        float c = n * g + c1.z * (a + c1.w) * roughness + f * f * a3 * a3 * a2;
+        float r = min(c, 18.0);
+
+        return vec2(r, r * c0.z);
+    }
+
+    vec3 getSheenReflectanceFromBRDFLookup(const vec3 reflectance0, float NdotV, float sheenAlphaG) {
+        vec2 environmentSheenBrdf = getCharlieSheenAnalyticalBRDFLookup_RomainGuy(NdotV, sheenAlphaG);
+        vec3 reflectance = reflectance0 * environmentSheenBrdf.x + environmentSheenBrdf.y;
+
+        return reflectance;
+    }
+#endif
+
+// ______________________________________________________________________
+//
+//                              Schlick/Fresnel
+// ______________________________________________________________________
+
+// Schlick's approximation for R0 (Fresnel Reflectance Values)
+// Keep for references
+// vec3 getR0fromAirToSurfaceIOR(vec3 ior1) {
+//     return getR0fromIOR(ior1, vec3(1.0));
+// }
+
+// vec3 getR0fromIOR(vec3 ior1, vec3 ior2) {
+//     vec3 t = (ior1 - ior2) / (ior1 + ior2);
+//     return t * t;
+// }
+
+// vec3 getIORfromAirToSurfaceR0(vec3 f0) {
+//     vec3 s = sqrt(f0);
+//     return (1.0 + s) / (1.0 - s);
+// }
+
+// f0 Remapping due to layers
+// vec3 getR0RemappedForClearCoat(vec3 f0, vec3 clearCoatF0) {
+//     vec3 iorBase = getIORfromAirToSurfaceR0(f0);
+//     vec3 clearCoatIor = getIORfromAirToSurfaceR0(clearCoatF0);
+//     return getR0fromIOR(iorBase, clearCoatIor);
+// }
+
+vec3 fresnelSchlickGGX(float VdotH, vec3 reflectance0, vec3 reflectance90)
+{
+    return reflectance0 + (reflectance90 - reflectance0) * pow5(1.0 - VdotH);
+}
+
+float fresnelSchlickGGX(float VdotH, float reflectance0, float reflectance90)
+{
+    return reflectance0 + (reflectance90 - reflectance0) * pow5(1.0 - VdotH);
+}
+
+#ifdef CLEARCOAT
+    // Knowing ior clear coat is fix for the material
+    // Solving iorbase = 1 + sqrt(fo) / (1 - sqrt(fo)) and f0base = square((iorbase - iorclearcoat) / (iorbase - iorclearcoat))
+    // provide f0base = square(A + B * sqrt(fo)) / (B + A * sqrt(fo))
+    // where A = 1 - iorclearcoat
+    // and   B = 1 + iorclearcoat
+    vec3 getR0RemappedForClearCoat(vec3 f0) {
+        #ifdef CLEARCOAT_DEFAULTIOR
+            #ifdef MOBILE
+                return saturate(f0 * (f0 * 0.526868 + 0.529324) - 0.0482256);
+            #else
+                return saturate(f0 * (f0 * (0.941892 - 0.263008 * f0) + 0.346479) - 0.0285998);
+            #endif
+        #else
+            vec3 s = sqrt(f0);
+            vec3 t = (vClearCoatRefractionParams.z + vClearCoatRefractionParams.w * s) / (vClearCoatRefractionParams.w + vClearCoatRefractionParams.z * s);
+            return t * t;
+        #endif
+    }
+#endif
+
+// ______________________________________________________________________
+//
+//                              Distribution
+// ______________________________________________________________________
+
+// Trowbridge-Reitz (GGX)
+// Generalised Trowbridge-Reitz with gamma power=2.0
+float normalDistributionFunction_TrowbridgeReitzGGX(float NdotH, float alphaG)
+{
+    // Note: alphaG is average slope (gradient) of the normals in slope-space.
+    // It is also the (trigonometric) tangent of the median distribution value, i.e. 50% of normals have
+    // a tangent (gradient) closer to the macrosurface than this slope.
+    float a2 = square(alphaG);
+    float d = NdotH * NdotH * (a2 - 1.0) + 1.0;
+    return a2 / (PI * d * d);
+}
+
+#ifdef SHEEN
+    // https://knarkowicz.wordpress.com/2018/01/04/cloth-shading/
+    float normalDistributionFunction_CharlieSheen(float NdotH, float alphaG)
+    {
+        float invR = 1. / alphaG;
+        float cos2h = NdotH * NdotH;
+        float sin2h = 1. - cos2h;
+        return (2. + invR) * pow(sin2h, invR * .5) / (2. * PI);
+    }
+#endif
+
+#ifdef ANISOTROPIC
+    // GGX Distribution Anisotropic
+    // https://blog.selfshadow.com/publications/s2012-shading-course/burley/s2012_pbs_disney_brdf_notes_v3.pdf Addenda
+    float normalDistributionFunction_BurleyGGX_Anisotropic(float NdotH, float TdotH, float BdotH, const vec2 alphaTB) {
+        float a2 = alphaTB.x * alphaTB.y;
+        vec3 v = vec3(alphaTB.y * TdotH, alphaTB.x  * BdotH, a2 * NdotH);
+        float v2 = dot(v, v);
+        float w2 = a2 / v2;
+        return a2 * w2 * w2 * RECIPROCAL_PI;
+    }
+#endif
+
+// ______________________________________________________________________
+//
+//                              Visibility/Geometry
+// ______________________________________________________________________
+
+#ifdef BRDF_V_HEIGHT_CORRELATED
+    // GGX Mask/Shadowing Isotropic 
+    // Heitz http://jcgt.org/published/0003/02/03/paper.pdf
+    // https://twvideo01.ubm-us.net/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf
+    float smithVisibility_GGXCorrelated(float NdotL, float NdotV, float alphaG) {
+        #ifdef MOBILE
+            // Appply simplification as all squared root terms are below 1 and squared
+            float GGXV = NdotL * (NdotV * (1.0 - alphaG) + alphaG);
+            float GGXL = NdotV * (NdotL * (1.0 - alphaG) + alphaG);
+            return 0.5 / (GGXV + GGXL);
+        #else
+            float a2 = alphaG * alphaG;
+            float GGXV = NdotL * sqrt(NdotV * (NdotV - a2 * NdotV) + a2);
+            float GGXL = NdotV * sqrt(NdotL * (NdotL - a2 * NdotL) + a2);
+            return 0.5 / (GGXV + GGXL);
+        #endif
+    }
+#else
+    // From Microfacet Models for Refraction through Rough Surfaces, Walter et al. 2007
+    // Keep for references
+    // float smithVisibilityG1_TrowbridgeReitzGGX(float dot, float alphaG)
+    // {
+    //     float tanSquared = (1.0 - dot * dot) / (dot * dot);
+    //     return 2.0 / (1.0 + sqrt(1.0 + alphaG * alphaG * tanSquared));
+    // }
+
+    // float smithVisibility_TrowbridgeReitzGGX_Walter(float NdotL, float NdotV, float alphaG)
+    // {
+    //     float visibility = smithVisibilityG1_TrowbridgeReitzGGX(NdotL, alphaG) * smithVisibilityG1_TrowbridgeReitzGGX(NdotV, alphaG);
+    //     visibility /= (4.0 * NdotL * NdotV); // Cook Torance Denominator  integrated in visibility to avoid issues when visibility function changes.
+    //     return visibility;
+    // }
+
+    // From smithVisibilityG1_TrowbridgeReitzGGX * dot / dot to cancel the cook
+    // torrance denominator :-)
+    float smithVisibilityG1_TrowbridgeReitzGGXFast(float dot, float alphaG)
+    {
+        #ifdef MOBILE
+            // Appply simplification as all squared root terms are below 1 and squared
+            return 1.0 / (dot + alphaG + (1.0 - alphaG) * dot ));
+        #else
+            float alphaSquared = alphaG * alphaG;
+            return 1.0 / (dot + sqrt(alphaSquared + (1.0 - alphaSquared) * dot * dot));
+        #endif
+    }
+
+    float smithVisibility_TrowbridgeReitzGGXFast(float NdotL, float NdotV, float alphaG)
+    {
+        float visibility = smithVisibilityG1_TrowbridgeReitzGGXFast(NdotL, alphaG) * smithVisibilityG1_TrowbridgeReitzGGXFast(NdotV, alphaG);
+        // No Cook Torance Denominator as it is canceled out in the previous form
+        return visibility;
+    }
+#endif
+
+#ifdef ANISOTROPIC
+    // GGX Mask/Shadowing Anisotropic 
+    // Heitz http://jcgt.org/published/0003/02/03/paper.pdf
+    float smithVisibility_GGXCorrelated_Anisotropic(float NdotL, float NdotV, float TdotV, float BdotV, float TdotL, float BdotL, const vec2 alphaTB) {
+        float lambdaV = NdotL * length(vec3(alphaTB.x * TdotV, alphaTB.y * BdotV, NdotV));
+        float lambdaL = NdotV * length(vec3(alphaTB.x * TdotL, alphaTB.y * BdotL, NdotL));
+        float v = 0.5 / (lambdaV + lambdaL);
+        return v;
+    }
+#endif
+
+#ifdef CLEARCOAT
+    float visibility_Kelemen(float VdotH) {
+        // Simplified form integration the cook torrance denminator.
+        // Expanded is nl * nv / vh2 which factor with 1 / (4 * nl * nv)
+        // giving 1 / (4 * vh2))
+        return 0.25 / (VdotH * VdotH); 
+    }
+#endif
+
+#ifdef SHEEN
+    // https://knarkowicz.wordpress.com/2018/01/04/cloth-shading/
+    // https://blog.selfshadow.com/publications/s2017-shading-course/imageworks/s2017_pbs_imageworks_sheen.pdf
+    // http://www.cs.utah.edu/~premoze/dbrdf/dBRDF.pdf
+    float visibility_Ashikhmin(float NdotL, float NdotV)
+    {
+        return 1. / (4. * (NdotL + NdotV - NdotL * NdotV));
+    }
+#endif
+
+// ______________________________________________________________________
+//
+//                              DiffuseBRDF
+// ______________________________________________________________________
+
+// Disney diffuse term
+// https://blog.selfshadow.com/publications/s2012-shading-course/burley/s2012_pbs_disney_brdf_notes_v3.pdf
+// Page 14
+float diffuseBRDF_Burley(float NdotL, float NdotV, float VdotH, float roughness) {
+    // Diffuse fresnel falloff as per Disney principled BRDF, and in the spirit of
+    // of general coupled diffuse/specular models e.g. Ashikhmin Shirley.
+    float diffuseFresnelNV = pow5(saturateEps(1.0 - NdotL));
+    float diffuseFresnelNL = pow5(saturateEps(1.0 - NdotV));
+    float diffuseFresnel90 = 0.5 + 2.0 * VdotH * VdotH * roughness;
+    float fresnel =
+        (1.0 + (diffuseFresnel90 - 1.0) * diffuseFresnelNL) *
+        (1.0 + (diffuseFresnel90 - 1.0) * diffuseFresnelNV);
+
+    return fresnel / PI;
+}

src/Shaders/ShadersInclude/pbrFalloffLightingFunctions.fx → src/Shaders/ShadersInclude/pbrDirectLightingFalloffFunctions.fx


+ 134 - 0
src/Shaders/ShadersInclude/pbrDirectLightingFunctions.fx

@@ -0,0 +1,134 @@
+#define CLEARCOATREFLECTANCE90 1.0
+
+// Light Results
+struct lightingInfo
+{
+    vec3 diffuse;
+    #ifdef SPECULARTERM
+        vec3 specular;
+    #endif
+    #ifdef CLEARCOAT
+        // xyz contains the clearcoat color.
+        // w contains the 1 - clearcoat fresnel to ease the energy conservation computation.
+        vec4 clearCoat;
+    #endif
+    #ifdef SHEEN
+        vec3 sheen;
+    #endif
+};
+
+// Simulate area (small) lights by increasing roughness
+float adjustRoughnessFromLightProperties(float roughness, float lightRadius, float lightDistance) {
+    #if defined(USEPHYSICALLIGHTFALLOFF) || defined(USEGLTFLIGHTFALLOFF)
+        // At small angle this approximation works. 
+        float lightRoughness = lightRadius / lightDistance;
+        // Distribution can sum.
+        float totalRoughness = saturate(lightRoughness + roughness);
+        return totalRoughness;
+    #else
+        return roughness;
+    #endif
+}
+
+vec3 computeHemisphericDiffuseLighting(preLightingInfo info, vec3 lightColor, vec3 groundColor) {
+    return mix(groundColor, lightColor, info.NdotL);
+}
+
+vec3 computeDiffuseLighting(preLightingInfo info, vec3 lightColor) {
+    float diffuseTerm = diffuseBRDF_Burley(info.NdotL, info.NdotV, info.VdotH, info.roughness);
+    return diffuseTerm * info.attenuation * info.NdotL * lightColor;
+}
+
+vec3 computeProjectionTextureDiffuseLighting(sampler2D projectionLightSampler, mat4 textureProjectionMatrix){
+    vec4 strq = textureProjectionMatrix * vec4(vPositionW, 1.0);
+    strq /= strq.w;
+    vec3 textureColor = texture2D(projectionLightSampler, strq.xy).rgb;
+    return toLinearSpace(textureColor);
+}
+
+#ifdef SPECULARTERM
+    vec3 computeSpecularLighting(preLightingInfo info, vec3 N, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor, vec3 lightColor) {
+        float NdotH = saturateEps(dot(N, info.H));
+        float roughness = max(info.roughness, geometricRoughnessFactor);
+        float alphaG = convertRoughnessToAverageSlope(roughness);
+
+        vec3 fresnel = fresnelSchlickGGX(info.VdotH, reflectance0, reflectance90);
+        float distribution = normalDistributionFunction_TrowbridgeReitzGGX(NdotH, alphaG);
+
+        #ifdef BRDF_V_HEIGHT_CORRELATED
+            float visibility = smithVisibility_GGXCorrelated(info.NdotL, info.NdotV, alphaG);
+        #else
+            float visibility = smithVisibility_TrowbridgeReitzGGXFast(info.NdotL, info.NdotV, alphaG);
+        #endif
+
+        vec3 specTerm = fresnel * distribution * visibility;
+        return specTerm * info.attenuation * info.NdotL * lightColor;
+    }
+#endif
+
+#ifdef ANISOTROPIC
+    vec3 computeAnisotropicSpecularLighting(preLightingInfo info, vec3 V, vec3 N, vec3 T, vec3 B, float anisotropy, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor, vec3 lightColor) {
+        float NdotH = saturateEps(dot(N, info.H));
+        float TdotH = dot(T, info.H);
+        float BdotH = dot(B, info.H);
+        float TdotV = dot(T, V);
+        float BdotV = dot(B, V);
+        float TdotL = dot(T, info.L);
+        float BdotL = dot(B, info.L);
+        float alphaG = convertRoughnessToAverageSlope(info.roughness);
+        vec2 alphaTB = getAnisotropicRoughness(alphaG, anisotropy);
+        alphaTB = max(alphaTB, square(geometricRoughnessFactor));
+
+        vec3 fresnel = fresnelSchlickGGX(info.VdotH, reflectance0, reflectance90);
+        float distribution = normalDistributionFunction_BurleyGGX_Anisotropic(NdotH, TdotH, BdotH, alphaTB);
+        float visibility = smithVisibility_GGXCorrelated_Anisotropic(info.NdotL, info.NdotV, TdotV, BdotV, TdotL, BdotL, alphaTB);
+
+        vec3 specTerm = fresnel * distribution * visibility;
+        return specTerm * info.attenuation * info.NdotL * lightColor;
+    }
+#endif
+
+#ifdef CLEARCOAT
+    vec4 computeClearCoatLighting(preLightingInfo info, vec3 Ncc, float geometricRoughnessFactor, float clearCoatIntensity, vec3 lightColor) {
+        float NccdotL = saturateEps(dot(Ncc, info.L));
+        float NccdotH = saturateEps(dot(Ncc, info.H));
+        float clearCoatRoughness = max(info.roughness, geometricRoughnessFactor);
+        float alphaG = convertRoughnessToAverageSlope(clearCoatRoughness);
+
+        float fresnel = fresnelSchlickGGX(info.VdotH, vClearCoatRefractionParams.x, CLEARCOATREFLECTANCE90);
+        fresnel *= clearCoatIntensity;
+        float distribution = normalDistributionFunction_TrowbridgeReitzGGX(NccdotH, alphaG);
+        float visibility = visibility_Kelemen(info.VdotH);
+
+        float clearCoatTerm = fresnel * distribution * visibility;
+
+        return vec4(
+            clearCoatTerm * info.attenuation * NccdotL * lightColor,
+            1.0 - fresnel
+        );
+    }
+
+    vec3 computeClearCoatLightingAbsorption(float NdotVRefract, vec3 L, vec3 Ncc, vec3 clearCoatColor, float clearCoatThickness, float clearCoatIntensity) {
+        vec3 LRefract = -refract(L, Ncc, vClearCoatRefractionParams.y);
+        float NdotLRefract = saturateEps(dot(Ncc, LRefract));
+
+        vec3 absorption = computeClearCoatAbsorption(NdotVRefract, NdotLRefract, clearCoatColor, clearCoatThickness, clearCoatIntensity);
+        return absorption;
+    }
+#endif
+
+#ifdef SHEEN
+    vec3 computeSheenLighting(preLightingInfo info, vec3 N, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor, vec3 lightColor) {
+        float NdotH = saturateEps(dot(N, info.H));
+        float roughness = max(info.roughness, geometricRoughnessFactor);
+        float alphaG = convertRoughnessToAverageSlope(roughness);
+
+        // No Fresnel with sheen
+        // vec3 fresnel = fresnelSchlickGGX(info.VdotH, reflectance0, reflectance90);
+        float distribution = normalDistributionFunction_CharlieSheen(NdotH, alphaG);
+        float visibility = visibility_Ashikhmin(info.NdotL, info.NdotV);
+
+        float sheenTerm = distribution * visibility;
+        return sheenTerm * info.attenuation * info.NdotL * lightColor;
+    }
+#endif

src/Shaders/ShadersInclude/pbrPreLightingFunctions.fx → src/Shaders/ShadersInclude/pbrDirectLightingSetupFunctions.fx


+ 30 - 0
src/Shaders/ShadersInclude/pbrFragmentExtraDeclaration.fx

@@ -0,0 +1,30 @@
+uniform vec4 vEyePosition;
+uniform vec3 vAmbientColor;
+uniform vec4 vCameraInfos;
+
+// Input
+varying vec3 vPositionW;
+
+#if DEBUGMODE > 0
+    uniform vec2 vDebugMode;
+    varying vec4 vClipSpacePosition;
+#endif
+
+#ifdef MAINUV1
+    varying vec2 vMainUV1;
+#endif 
+
+#ifdef MAINUV2 
+    varying vec2 vMainUV2;
+#endif 
+
+#ifdef NORMAL
+    varying vec3 vNormalW;
+    #if defined(USESPHERICALFROMREFLECTIONMAP) && defined(USESPHERICALINVERTEX)
+        varying vec3 vEnvironmentIrradiance;
+    #endif
+#endif
+
+#ifdef VERTEXCOLOR
+    varying vec4 vColor;
+#endif

+ 203 - 0
src/Shaders/ShadersInclude/pbrFragmentSamplersDeclaration.fx

@@ -0,0 +1,203 @@
+#ifdef ALBEDO
+    #if ALBEDODIRECTUV == 1
+        #define vAlbedoUV vMainUV1
+    #elif ALBEDODIRECTUV == 2
+        #define vAlbedoUV vMainUV2
+    #else
+        varying vec2 vAlbedoUV;
+    #endif
+    uniform sampler2D albedoSampler;
+#endif
+
+#ifdef AMBIENT
+    #if AMBIENTDIRECTUV == 1
+        #define vAmbientUV vMainUV1
+    #elif AMBIENTDIRECTUV == 2
+        #define vAmbientUV vMainUV2
+    #else
+        varying vec2 vAmbientUV;
+    #endif
+    uniform sampler2D ambientSampler;
+#endif
+
+#ifdef OPACITY
+    #if OPACITYDIRECTUV == 1
+        #define vOpacityUV vMainUV1
+    #elif OPACITYDIRECTUV == 2
+        #define vOpacityUV vMainUV2
+    #else
+        varying vec2 vOpacityUV;
+    #endif
+    uniform sampler2D opacitySampler;
+#endif
+
+#ifdef EMISSIVE
+    #if EMISSIVEDIRECTUV == 1
+        #define vEmissiveUV vMainUV1
+    #elif EMISSIVEDIRECTUV == 2
+        #define vEmissiveUV vMainUV2
+    #else
+        varying vec2 vEmissiveUV;
+    #endif
+    uniform sampler2D emissiveSampler;
+#endif
+
+#ifdef LIGHTMAP
+    #if LIGHTMAPDIRECTUV == 1
+        #define vLightmapUV vMainUV1
+    #elif LIGHTMAPDIRECTUV == 2
+        #define vLightmapUV vMainUV2
+    #else
+        varying vec2 vLightmapUV;
+    #endif
+    uniform sampler2D lightmapSampler;
+#endif
+
+#ifdef REFLECTIVITY
+    #if REFLECTIVITYDIRECTUV == 1
+        #define vReflectivityUV vMainUV1
+    #elif REFLECTIVITYDIRECTUV == 2
+        #define vReflectivityUV vMainUV2
+    #else
+        varying vec2 vReflectivityUV;
+    #endif
+    uniform sampler2D reflectivitySampler;
+#endif
+
+#ifdef MICROSURFACEMAP
+    #if MICROSURFACEMAPDIRECTUV == 1
+        #define vMicroSurfaceSamplerUV vMainUV1
+    #elif MICROSURFACEMAPDIRECTUV == 2
+        #define vMicroSurfaceSamplerUV vMainUV2
+    #else
+        varying vec2 vMicroSurfaceSamplerUV;
+    #endif
+    uniform sampler2D microSurfaceSampler;
+#endif
+
+#ifdef CLEARCOAT
+    #ifdef CLEARCOAT_TEXTURE
+        #if CLEARCOAT_TEXTUREDIRECTUV == 1
+            #define vClearCoatUV vMainUV1
+        #elif CLEARCOAT_TEXTUREDIRECTUV == 2
+            #define vClearCoatUV vMainUV2
+        #else
+            varying vec2 vClearCoatUV;
+        #endif
+        uniform sampler2D clearCoatSampler;
+    #endif
+
+    #ifdef CLEARCOAT_BUMP
+        #if CLEARCOAT_BUMPDIRECTUV == 1
+            #define vClearCoatBumpUV vMainUV1
+        #elif CLEARCOAT_BUMPDIRECTUV == 2
+            #define vClearCoatBumpUV vMainUV2
+        #else
+            varying vec2 vClearCoatBumpUV;
+        #endif
+        uniform sampler2D clearCoatBumpSampler;
+    #endif
+
+    #ifdef CLEARCOAT_TINT_TEXTURE
+        #if CLEARCOAT_TINT_TEXTUREDIRECTUV == 1
+            #define vClearCoatTintUV vMainUV1
+        #elif CLEARCOAT_TINT_TEXTUREDIRECTUV == 2
+            #define vClearCoatTintUV vMainUV2
+        #else
+            varying vec2 vClearCoatTintUV;
+        #endif
+        uniform sampler2D clearCoatTintSampler;
+    #endif
+#endif
+
+#ifdef SHEEN
+    #ifdef SHEEN_TEXTURE
+        #if SHEEN_TEXTUREDIRECTUV == 1
+            #define vSheenUV vMainUV1
+        #elif SHEEN_TEXTUREDIRECTUV == 2
+            #define vSheenUV vMainUV2
+        #else
+            varying vec2 vSheenUV;
+        #endif
+        uniform sampler2D sheenSampler;
+    #endif
+#endif
+
+#ifdef ANISOTROPIC
+    #ifdef ANISOTROPIC_TEXTURE
+        #if ANISOTROPIC_TEXTUREDIRECTUV == 1
+            #define vAnisotropyUV vMainUV1
+        #elif ANISOTROPIC_TEXTUREDIRECTUV == 2
+            #define vAnisotropyUV vMainUV2
+        #else
+            varying vec2 vAnisotropyUV;
+        #endif
+        uniform sampler2D anisotropySampler;
+    #endif
+#endif
+
+// Refraction
+#ifdef REFRACTION
+    #ifdef REFRACTIONMAP_3D
+        #define sampleRefraction(s, c) textureCube(s, c)
+        
+        uniform samplerCube refractionSampler;
+
+        #ifdef LODBASEDMICROSFURACE
+            #define sampleRefractionLod(s, c, l) textureCubeLodEXT(s, c, l)
+        #else
+            uniform samplerCube refractionSamplerLow;
+            uniform samplerCube refractionSamplerHigh;
+        #endif
+    #else
+        #define sampleRefraction(s, c) texture2D(s, c)
+        
+        uniform sampler2D refractionSampler;
+
+        #ifdef LODBASEDMICROSFURACE
+            #define sampleRefractionLod(s, c, l) texture2DLodEXT(s, c, l)
+        #else
+            uniform samplerCube refractionSamplerLow;
+            uniform samplerCube refractionSamplerHigh;
+        #endif
+    #endif
+#endif
+
+// Reflection
+#ifdef REFLECTION
+    #ifdef REFLECTIONMAP_3D
+        #define sampleReflection(s, c) textureCube(s, c)
+
+        uniform samplerCube reflectionSampler;
+        
+        #ifdef LODBASEDMICROSFURACE
+            #define sampleReflectionLod(s, c, l) textureCubeLodEXT(s, c, l)
+        #else
+            uniform samplerCube reflectionSamplerLow;
+            uniform samplerCube reflectionSamplerHigh;
+        #endif
+    #else
+        #define sampleReflection(s, c) texture2D(s, c)
+
+        uniform sampler2D reflectionSampler;
+
+        #ifdef LODBASEDMICROSFURACE
+            #define sampleReflectionLod(s, c, l) texture2DLodEXT(s, c, l)
+        #else
+            uniform samplerCube reflectionSamplerLow;
+            uniform samplerCube reflectionSamplerHigh;
+        #endif
+    #endif
+
+    #ifdef REFLECTIONMAP_SKYBOX
+        varying vec3 vPositionUVW;
+    #else
+        #if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)
+            varying vec3 vDirectionW;
+        #endif
+    #endif
+#endif
+
+#ifdef ENVIRONMENTBRDF
+    uniform sampler2D environmentBrdfSampler;
+#endif

+ 0 - 471
src/Shaders/ShadersInclude/pbrFunctions.fx

@@ -1,471 +0,0 @@
-// Constants
-#define RECIPROCAL_PI2 0.15915494
-#define RECIPROCAL_PI 0.31830988618
-#define FRESNEL_MAXIMUM_ON_ROUGH 0.25
-
-// AlphaG epsilon to avoid numerical issues
-#define MINIMUMVARIANCE 0.0005
-
-#define CLEARCOATREFLECTANCE90 1.0
-
-float convertRoughnessToAverageSlope(float roughness)
-{
-    // Calculate AlphaG as square of roughness; add epsilon to avoid numerical issues
-    return square(roughness) + MINIMUMVARIANCE;
-}
-
-float adjustRoughnessFromLightProperties(float roughness, float lightRadius, float lightDistance)
-{
-    #if defined(USEPHYSICALLIGHTFALLOFF) || defined(USEGLTFLIGHTFALLOFF)
-        // At small angle this approximation works. 
-        float lightRoughness = lightRadius / lightDistance;
-        // Distribution can sum.
-        float totalRoughness = saturate(lightRoughness + roughness);
-        return totalRoughness;
-    #else
-        return roughness;
-    #endif
-}
-
-float fresnelGrazingReflectance(float reflectance0) {
-    // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect.
-    // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%.
-    float reflectance90 = saturate(reflectance0 * 25.0);
-    return reflectance90;
-}
-
-vec2 getAARoughnessFactors(vec3 normalVector) {
-    #ifdef SPECULARAA
-        vec3 nDfdx = dFdx(normalVector.xyz);
-        vec3 nDfdy = dFdy(normalVector.xyz);
-        float slopeSquare = max(dot(nDfdx, nDfdx), dot(nDfdy, nDfdy));
-
-        // Vive analytical lights roughness factor.
-        float geometricRoughnessFactor = pow(saturate(slopeSquare), 0.333);
-
-        // Adapt linear roughness (alphaG) to geometric curvature of the current pixel.
-        float geometricAlphaGFactor = sqrt(slopeSquare);
-        // BJS factor.
-        geometricAlphaGFactor *= 0.75;
-
-        return vec2(geometricRoughnessFactor, geometricAlphaGFactor);
-    #else
-        return vec2(0.);
-    #endif
-}
-
-
-#ifdef MS_BRDF_ENERGY_CONSERVATION
-    // http://www.jcgt.org/published/0008/01/03/
-    // http://advances.realtimerendering.com/s2018/Siggraph%202018%20HDRP%20talk_with%20notes.pdf
-    vec3 getEnergyConservationFactor(const vec3 specularEnvironmentR0, vec2 environmentBrdf) {
-        return 1.0 + specularEnvironmentR0 * (1.0 / environmentBrdf.y - 1.0);
-    }
-#endif
-
-#ifdef ENVIRONMENTBRDF
-    vec2 getBRDFLookup(float NdotV, float perceptualRoughness, sampler2D brdfSampler) {
-        // Indexed on cos(theta) and roughness
-        vec2 UV = vec2(NdotV, perceptualRoughness);
-        
-        // We can find the scale and offset to apply to the specular value.
-        vec2 brdfLookup = texture2D(brdfSampler, UV).xy;
-
-        return brdfLookup;
-    }
-
-    vec3 getReflectanceFromBRDFLookup(const vec3 specularEnvironmentR0, vec2 environmentBrdf) {
-        #ifdef BRDF_V_HEIGHT_CORRELATED
-            vec3 reflectance = mix(environmentBrdf.xxx, environmentBrdf.yyy, specularEnvironmentR0);
-        #else
-            vec3 reflectance = specularEnvironmentR0 * environmentBrdf.x + environmentBrdf.y;
-        #endif
-        return reflectance;
-    }
-#else
-    vec3 getReflectanceFromAnalyticalBRDFLookup_Jones(float VdotN, vec3 reflectance0, vec3 reflectance90, float smoothness)
-    {
-        // Schlick fresnel approximation, extended with basic smoothness term so that rough surfaces do not approach reflectance90 at grazing angle
-        float weight = mix(FRESNEL_MAXIMUM_ON_ROUGH, 1.0, smoothness);
-        return reflectance0 + weight * (reflectance90 - reflectance0) * pow5(saturate(1.0 - VdotN));
-    }
-#endif
-
-#if defined(SHEEN) && defined(REFLECTION)
-    /**
-    * Special thanks to @romainguy for all the support :-)
-    * Analytical approximation of the pre-filtered DFG terms for the cloth shading
-    * model. This approximation is based on the Estevez & Kulla distribution term
-    * ("Charlie" sheen) and the Neubelt visibility term. See brdf.fs for more
-    * details.
-    */
-    vec2 getCharlieSheenAnalyticalBRDFLookup_RomainGuy(float NoV, float roughness) {
-        const vec3 c0 = vec3(0.95, 1250.0, 0.0095);
-        const vec4 c1 = vec4(0.04, 0.2, 0.3, 0.2);
-
-        float a = 1.0 - NoV;
-        float b = 1.0 - roughness;
-
-        float n = pow(c1.x + a, 64.0);
-        float e = b - c0.x;
-        float g = exp2(-(e * e) * c0.y);
-        float f = b + c1.y;
-        float a2 = a * a;
-        float a3 = a2 * a;
-        float c = n * g + c1.z * (a + c1.w) * roughness + f * f * a3 * a3 * a2;
-        float r = min(c, 18.0);
-
-        return vec2(r, r * c0.z);
-    }
-
-    vec3 getSheenReflectanceFromBRDFLookup(const vec3 reflectance0, float NdotV, float sheenAlphaG) {
-        vec2 environmentSheenBrdf = getCharlieSheenAnalyticalBRDFLookup_RomainGuy(NdotV, sheenAlphaG);
-        vec3 reflectance = reflectance0 * environmentSheenBrdf.x + environmentSheenBrdf.y;
-
-        return reflectance;
-    }
-#endif
-
-// Schlick's approximation for R0 (Fresnel Reflectance Values)
-// Keep for references
-// vec3 getR0fromAirToSurfaceIOR(vec3 ior1) {
-//     return getR0fromIOR(ior1, vec3(1.0));
-// }
-
-// vec3 getR0fromIOR(vec3 ior1, vec3 ior2) {
-//     vec3 t = (ior1 - ior2) / (ior1 + ior2);
-//     return t * t;
-// }
-
-// vec3 getIORfromAirToSurfaceR0(vec3 f0) {
-//     vec3 s = sqrt(f0);
-//     return (1.0 + s) / (1.0 - s);
-// }
-
-// f0 Remapping due to layers
-// vec3 getR0RemappedForClearCoat(vec3 f0, vec3 clearCoatF0) {
-//     vec3 iorBase = getIORfromAirToSurfaceR0(f0);
-//     vec3 clearCoatIor = getIORfromAirToSurfaceR0(clearCoatF0);
-//     return getR0fromIOR(iorBase, clearCoatIor);
-// }
-
-#ifdef CLEARCOAT
-    // Knowing ior clear coat is fix for the material
-    // Solving iorbase = 1 + sqrt(fo) / (1 - sqrt(fo)) and f0base = square((iorbase - iorclearcoat) / (iorbase - iorclearcoat))
-    // provide f0base = square(A + B * sqrt(fo)) / (B + A * sqrt(fo))
-    // where A = 1 - iorclearcoat
-    // and   B = 1 + iorclearcoat
-    vec3 getR0RemappedForClearCoat(vec3 f0) {
-        #ifdef CLEARCOAT_DEFAULTIOR
-            #ifdef MOBILE
-                return saturate(f0 * (f0 * 0.526868 + 0.529324) - 0.0482256);
-            #else
-                return saturate(f0 * (f0 * (0.941892 - 0.263008 * f0) + 0.346479) - 0.0285998);
-            #endif
-        #else
-            vec3 s = sqrt(f0);
-            vec3 t = (vClearCoatRefractionParams.z + vClearCoatRefractionParams.w * s) / (vClearCoatRefractionParams.w + vClearCoatRefractionParams.z * s);
-            return t * t;
-        #endif
-    }
-#endif
-
-// From Microfacet Models for Refraction through Rough Surfaces, Walter et al. 2007
-// Keep for references
-// float smithVisibilityG1_TrowbridgeReitzGGX(float dot, float alphaG)
-// {
-//     float tanSquared = (1.0 - dot * dot) / (dot * dot);
-//     return 2.0 / (1.0 + sqrt(1.0 + alphaG * alphaG * tanSquared));
-// }
-
-// float smithVisibility_TrowbridgeReitzGGX_Walter(float NdotL, float NdotV, float alphaG)
-// {
-//     float visibility = smithVisibilityG1_TrowbridgeReitzGGX(NdotL, alphaG) * smithVisibilityG1_TrowbridgeReitzGGX(NdotV, alphaG);
-//     visibility /= (4.0 * NdotL * NdotV); // Cook Torance Denominator  integrated in visibility to avoid issues when visibility function changes.
-//     return visibility;
-// }
-
-// From smithVisibilityG1_TrowbridgeReitzGGX * dot / dot to cancel the cook
-// torrance denominator :-)
-float smithVisibilityG1_TrowbridgeReitzGGXFast(float dot, float alphaG)
-{
-    #ifdef MOBILE
-        // Appply simplification as all squared root terms are below 1 and squared
-        return 1.0 / (dot + alphaG + (1.0 - alphaG) * dot ));
-    #else
-        float alphaSquared = alphaG * alphaG;
-        return 1.0 / (dot + sqrt(alphaSquared + (1.0 - alphaSquared) * dot * dot));
-    #endif
-}
-
-float smithVisibility_TrowbridgeReitzGGXFast(float NdotL, float NdotV, float alphaG)
-{
-    float visibility = smithVisibilityG1_TrowbridgeReitzGGXFast(NdotL, alphaG) * smithVisibilityG1_TrowbridgeReitzGGXFast(NdotV, alphaG);
-    // No Cook Torance Denominator as it is canceled out in the previous form
-    return visibility;
-}
-
-float visibility_Kelemen(float VdotH) {
-    // Simplified form integration the cook torrance denminator.
-    // Expanded is nl * nv / vh2 which factor with 1 / (4 * nl * nv)
-    // giving 1 / (4 * vh2))
-    return 0.25 / (VdotH * VdotH); 
-}
-
-// https://knarkowicz.wordpress.com/2018/01/04/cloth-shading/
-// https://blog.selfshadow.com/publications/s2017-shading-course/imageworks/s2017_pbs_imageworks_sheen.pdf
-// http://www.cs.utah.edu/~premoze/dbrdf/dBRDF.pdf
-float visibility_Ashikhmin(float NdotL, float NdotV)
-{
-    return 1. / (4. * (NdotL + NdotV - NdotL * NdotV));
-}
-
-float normalDistributionFunction_CharlieSheen(float NdotH, float alphaG)
-{
-    float invR = 1. / alphaG;
-    float cos2h = NdotH * NdotH;
-    float sin2h = 1. - cos2h;
-    return (2. + invR) * pow(sin2h, invR * .5) / (2. * PI);
-}
-
-// Trowbridge-Reitz (GGX)
-// Generalised Trowbridge-Reitz with gamma power=2.0
-float normalDistributionFunction_TrowbridgeReitzGGX(float NdotH, float alphaG)
-{
-    // Note: alphaG is average slope (gradient) of the normals in slope-space.
-    // It is also the (trigonometric) tangent of the median distribution value, i.e. 50% of normals have
-    // a tangent (gradient) closer to the macrosurface than this slope.
-    float a2 = square(alphaG);
-    float d = NdotH * NdotH * (a2 - 1.0) + 1.0;
-    return a2 / (PI * d * d);
-}
-
-// Aniso parameter remapping
-// https://blog.selfshadow.com/publications/s2017-shading-course/imageworks/s2017_pbs_imageworks_slides_v2.pdf page 24
-vec2 getAnisotropicRoughness(float alphaG, float anisotropy) {
-    float alphaT = max(alphaG * (1.0 + anisotropy), MINIMUMVARIANCE);
-    float alphaB = max(alphaG * (1.0 - anisotropy), MINIMUMVARIANCE);
-    return vec2(alphaT, alphaB);
-}
-
-// Aniso Bent Normals
-// Mc Alley https://www.gdcvault.com/play/1022235/Rendering-the-World-of-Far 
-vec3 getAnisotropicBentNormals(const vec3 T, const vec3 B, const vec3 N, const vec3 V, float anisotropy) {
-    vec3 anisotropicFrameDirection = anisotropy >= 0.0 ? B : T;
-    vec3 anisotropicFrameTangent = cross(normalize(anisotropicFrameDirection), V);
-    vec3 anisotropicFrameNormal = cross(anisotropicFrameTangent, anisotropicFrameDirection);
-    vec3 anisotropicNormal = normalize(mix(N, anisotropicFrameNormal, abs(anisotropy)));
-    return anisotropicNormal;
-
-    // should we also do http://advances.realtimerendering.com/s2018/Siggraph%202018%20HDRP%20talk_with%20notes.pdf page 80 ?
-}
-
-// GGX Distribution Anisotropic
-// https://blog.selfshadow.com/publications/s2012-shading-course/burley/s2012_pbs_disney_brdf_notes_v3.pdf Addenda
-float normalDistributionFunction_BurleyGGX_Anisotropic(float NdotH, float TdotH, float BdotH, const vec2 alphaTB) {
-    float a2 = alphaTB.x * alphaTB.y;
-    vec3 v = vec3(alphaTB.y * TdotH, alphaTB.x  * BdotH, a2 * NdotH);
-    float v2 = dot(v, v);
-    float w2 = a2 / v2;
-    return a2 * w2 * w2 * RECIPROCAL_PI;
-}
-
-// GGX Mask/Shadowing Isotropic 
-// Heitz http://jcgt.org/published/0003/02/03/paper.pdf
-// https://twvideo01.ubm-us.net/o1/vault/gdc2017/Presentations/Hammon_Earl_PBR_Diffuse_Lighting.pdf
-float smithVisibility_GGXCorrelated(float NdotL, float NdotV, float alphaG) {
-    #ifdef MOBILE
-        // Appply simplification as all squared root terms are below 1 and squared
-        float GGXV = NdotL * (NdotV * (1.0 - alphaG) + alphaG);
-        float GGXL = NdotV * (NdotL * (1.0 - alphaG) + alphaG);
-        return 0.5 / (GGXV + GGXL);
-    #else
-        float a2 = alphaG * alphaG;
-        float GGXV = NdotL * sqrt(NdotV * (NdotV - a2 * NdotV) + a2);
-        float GGXL = NdotV * sqrt(NdotL * (NdotL - a2 * NdotL) + a2);
-        return 0.5 / (GGXV + GGXL);
-    #endif
-}
-
-// GGX Mask/Shadowing Anisotropic 
-// Heitz http://jcgt.org/published/0003/02/03/paper.pdf
-float smithVisibility_GGXCorrelated_Anisotropic(float NdotL, float NdotV, float TdotV, float BdotV, float TdotL, float BdotL, const vec2 alphaTB) {
-    float lambdaV = NdotL * length(vec3(alphaTB.x * TdotV, alphaTB.y * BdotV, NdotV));
-    float lambdaL = NdotV * length(vec3(alphaTB.x * TdotL, alphaTB.y * BdotL, NdotL));
-    float v = 0.5 / (lambdaV + lambdaL);
-    return v;
-}
-
-vec3 fresnelSchlickGGX(float VdotH, vec3 reflectance0, vec3 reflectance90)
-{
-    return reflectance0 + (reflectance90 - reflectance0) * pow5(1.0 - VdotH);
-}
-
-float fresnelSchlickGGX(float VdotH, float reflectance0, float reflectance90)
-{
-    return reflectance0 + (reflectance90 - reflectance0) * pow5(1.0 - VdotH);
-}
-
-// From beer lambert law I1/I0 = e −α′lc
-// c is considered included in alpha
-// https://blog.selfshadow.com/publications/s2017-shading-course/drobot/s2017_pbs_multilayered.pdf page 47
-// where L on a thin constant size layer can be (d * ((NdotLRefract + NdotVRefract) / (NdotLRefract * NdotVRefract))
-vec3 cocaLambert(float NdotVRefract, float NdotLRefract, vec3 alpha, float thickness) {
-    return exp(alpha * -(thickness * ((NdotLRefract + NdotVRefract) / (NdotLRefract * NdotVRefract))));
-}
-// From beerLambert Solves what alpha should be for a given resutlt at a known distance.
-vec3 computeColorAtDistanceInMedia(vec3 color, float distance) {
-    return -log(color) / distance;
-}
-
-// Disney diffuse term
-// https://blog.selfshadow.com/publications/s2012-shading-course/burley/s2012_pbs_disney_brdf_notes_v3.pdf
-// Page 14
-float computeDiffuseTerm(float NdotL, float NdotV, float VdotH, float roughness) {
-    // Diffuse fresnel falloff as per Disney principled BRDF, and in the spirit of
-    // of general coupled diffuse/specular models e.g. Ashikhmin Shirley.
-    float diffuseFresnelNV = pow5(saturateEps(1.0 - NdotL));
-    float diffuseFresnelNL = pow5(saturateEps(1.0 - NdotV));
-    float diffuseFresnel90 = 0.5 + 2.0 * VdotH * VdotH * roughness;
-    float fresnel =
-        (1.0 + (diffuseFresnel90 - 1.0) * diffuseFresnelNL) *
-        (1.0 + (diffuseFresnel90 - 1.0) * diffuseFresnelNV);
-
-    return fresnel / PI;
-}
-
-// Cook Torance Specular computation.
-vec3 computeSpecularTerm(float NdotH, float NdotL, float NdotV, float VdotH, float roughness, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor) {
-    roughness = max(roughness, geometricRoughnessFactor);
-    float alphaG = convertRoughnessToAverageSlope(roughness);
-
-    float distribution = normalDistributionFunction_TrowbridgeReitzGGX(NdotH, alphaG);
-
-    #ifdef BRDF_V_HEIGHT_CORRELATED
-        float visibility = smithVisibility_GGXCorrelated(NdotL, NdotV, alphaG);
-    #else
-        float visibility = smithVisibility_TrowbridgeReitzGGXFast(NdotL, NdotV, alphaG);
-    #endif
-
-    float specTerm = max(0., visibility * distribution);
-
-    vec3 fresnel = fresnelSchlickGGX(VdotH, reflectance0, reflectance90);
-    return fresnel * specTerm;
-}
-
-#ifdef SHEEN
-    vec3 computeSheenTerm(float NdotH, float NdotL, float NdotV, float VdotH, float roughness, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor) {
-        roughness = max(roughness, geometricRoughnessFactor);
-        float alphaG = convertRoughnessToAverageSlope(roughness);
-
-        float distribution = normalDistributionFunction_CharlieSheen(NdotH, alphaG);
-        float visibility = visibility_Ashikhmin(NdotL, NdotV);
-
-        float specTerm = max(0., visibility * distribution);
-
-        vec3 fresnel = fresnelSchlickGGX(VdotH, reflectance0, reflectance90);
-        return vec3(specTerm);
-    }
-#endif
-
-#ifdef ANISOTROPIC
-    vec3 computeAnisotropicSpecularTerm(float NdotH, float NdotL, float NdotV, float VdotH, float TdotH, float BdotH, float TdotV, float BdotV, float TdotL, float BdotL, float roughness, float anisotropy, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor) {
-        float alphaG = convertRoughnessToAverageSlope(roughness);
-        vec2 alphaTB = getAnisotropicRoughness(alphaG, anisotropy);
-        alphaTB = max(alphaTB, geometricRoughnessFactor * geometricRoughnessFactor);
-
-        float distribution = normalDistributionFunction_BurleyGGX_Anisotropic(NdotH, TdotH, BdotH, alphaTB);
-        float visibility = smithVisibility_GGXCorrelated_Anisotropic(NdotL, NdotV, TdotV, BdotV, TdotL, BdotL, alphaTB);
-        float specTerm = max(0., visibility * distribution);
-
-        vec3 fresnel = fresnelSchlickGGX(VdotH, reflectance0, reflectance90);
-        return fresnel * specTerm;
-    }
-#endif
-
-#ifdef CLEARCOAT
-    vec2 computeClearCoatTerm(float NdotH, float VdotH, float clearCoatRoughness, float geometricRoughnessFactor, float clearCoatIntensity) {
-        clearCoatRoughness = max(clearCoatRoughness, geometricRoughnessFactor);
-        float alphaG = convertRoughnessToAverageSlope(clearCoatRoughness);
-
-        float distribution = normalDistributionFunction_TrowbridgeReitzGGX(NdotH, alphaG);
-        float visibility = visibility_Kelemen(VdotH);
-        float clearCoatTerm = max(0., visibility * distribution);
-
-        float fresnel = fresnelSchlickGGX(VdotH, vClearCoatRefractionParams.x, CLEARCOATREFLECTANCE90);
-        fresnel *= clearCoatIntensity;
-        
-        return vec2(fresnel * clearCoatTerm, 1.0 - fresnel);
-    }
-
-    vec3 computeClearCoatAbsorption(float NdotVRefract, float NdotLRefract, vec3 clearCoatColor, float clearCoatThickness, float clearCoatIntensity) {
-        vec3 clearCoatAbsorption = mix(vec3(1.0),
-            cocaLambert(NdotVRefract, NdotLRefract, clearCoatColor, clearCoatThickness),
-            clearCoatIntensity);
-        return clearCoatAbsorption;
-    }
-#endif
-
-#if defined(REFLECTION) || defined(REFRACTION)
-    float getLodFromAlphaG(float cubeMapDimensionPixels, float microsurfaceAverageSlope) {
-        float microsurfaceAverageSlopeTexels = microsurfaceAverageSlope * cubeMapDimensionPixels;
-        float lod = log2(microsurfaceAverageSlopeTexels);
-        return lod;
-    }
-#endif
-
-#if defined(ENVIRONMENTBRDF) && defined(RADIANCEOCCLUSION)
-    float environmentRadianceOcclusion(float ambientOcclusion, float NdotVUnclamped) {
-        // Best balanced (implementation time vs result vs perf) analytical environment specular occlusion found.
-        // http://research.tri-ace.com/Data/cedec2011_RealtimePBR_Implementation_e.pptx
-        float temp = NdotVUnclamped + ambientOcclusion;
-        return saturate(square(temp) - 1.0 + ambientOcclusion);
-    }
-#endif
-
-#if defined(ENVIRONMENTBRDF) && defined(HORIZONOCCLUSION)
-    float environmentHorizonOcclusion(vec3 view, vec3 normal) {
-        // http://marmosetco.tumblr.com/post/81245981087
-        vec3 reflection = reflect(view, normal);
-        float temp = saturate(1.0 + 1.1 * dot(reflection, normal));
-        return square(temp);
-    }
-#endif
-
-// ___________________________________________________________________________________
-//
-// LEGACY
-// ___________________________________________________________________________________
-
-#ifdef MICROSURFACEAUTOMATIC
-    float computeDefaultMicroSurface(float microSurface, vec3 reflectivityColor)
-    {
-        const float kReflectivityNoAlphaWorkflow_SmoothnessMax = 0.95;
-
-        float reflectivityLuminance = getLuminance(reflectivityColor);
-        float reflectivityLuma = sqrt(reflectivityLuminance);
-        microSurface = reflectivityLuma * kReflectivityNoAlphaWorkflow_SmoothnessMax;
-
-        return microSurface;
-    }
-#endif
-
-#if defined(LODINREFLECTIONALPHA) || defined(LODINREFRACTIONALPHA)
-    // To enable 8 bit textures to be used we need to pack and unpack the LOD
-    //inverse alpha is used to work around low-alpha bugs in Edge and Firefox
-    #define UNPACK_LOD(x) (1.0 - x) * 255.0
-
-    float getLodFromAlphaG(float cubeMapDimensionPixels, float alphaG, float NdotV) {
-        float microsurfaceAverageSlope = alphaG;
-
-        // Compensate for solid angle change between half-vector measure (Blinn-Phong) and reflected-vector measure (Phong):
-        //  dWr = 4*cos(theta)*dWh,
-        // where dWr = solid angle (delta omega) in environment incident radiance (reflection-vector) measure;
-        // where dWh = solid angle (delta omega) in microfacet normal (half-vector) measure;
-        // so the relationship is proportional to cosine theta = NdotV.
-        // The constant factor of four is handled elsewhere as part of the scale/offset filter parameters.
-        microsurfaceAverageSlope *= sqrt(abs(NdotV));
-
-        return getLodFromAlphaG(cubeMapDimensionPixels, microsurfaceAverageSlope);
-    }
-#endif

+ 101 - 0
src/Shaders/ShadersInclude/pbrHelperFunctions.fx

@@ -0,0 +1,101 @@
+// Constants
+#define RECIPROCAL_PI2 0.15915494
+#define RECIPROCAL_PI 0.31830988618
+
+// AlphaG epsilon to avoid numerical issues
+#define MINIMUMVARIANCE 0.0005
+
+float convertRoughnessToAverageSlope(float roughness)
+{
+    // Calculate AlphaG as square of roughness; add epsilon to avoid numerical issues
+    return square(roughness) + MINIMUMVARIANCE;
+}
+
+float fresnelGrazingReflectance(float reflectance0) {
+    // For typical incident reflectance range (between 4% to 100%) set the grazing reflectance to 100% for typical fresnel effect.
+    // For very low reflectance range on highly diffuse objects (below 4%), incrementally reduce grazing reflecance to 0%.
+    float reflectance90 = saturate(reflectance0 * 25.0);
+    return reflectance90;
+}
+
+vec2 getAARoughnessFactors(vec3 normalVector) {
+    #ifdef SPECULARAA
+        vec3 nDfdx = dFdx(normalVector.xyz);
+        vec3 nDfdy = dFdy(normalVector.xyz);
+        float slopeSquare = max(dot(nDfdx, nDfdx), dot(nDfdy, nDfdy));
+
+        // Vive analytical lights roughness factor.
+        float geometricRoughnessFactor = pow(saturate(slopeSquare), 0.333);
+
+        // Adapt linear roughness (alphaG) to geometric curvature of the current pixel.
+        float geometricAlphaGFactor = sqrt(slopeSquare);
+        // BJS factor.
+        geometricAlphaGFactor *= 0.75;
+
+        return vec2(geometricRoughnessFactor, geometricAlphaGFactor);
+    #else
+        return vec2(0.);
+    #endif
+}
+
+#ifdef ANISOTROPIC
+    // Aniso parameter remapping
+    // https://blog.selfshadow.com/publications/s2017-shading-course/imageworks/s2017_pbs_imageworks_slides_v2.pdf page 24
+    vec2 getAnisotropicRoughness(float alphaG, float anisotropy) {
+        float alphaT = max(alphaG * (1.0 + anisotropy), MINIMUMVARIANCE);
+        float alphaB = max(alphaG * (1.0 - anisotropy), MINIMUMVARIANCE);
+        return vec2(alphaT, alphaB);
+    }
+
+    // Aniso Bent Normals
+    // Mc Alley https://www.gdcvault.com/play/1022235/Rendering-the-World-of-Far 
+    vec3 getAnisotropicBentNormals(const vec3 T, const vec3 B, const vec3 N, const vec3 V, float anisotropy) {
+        vec3 anisotropicFrameDirection = anisotropy >= 0.0 ? B : T;
+        vec3 anisotropicFrameTangent = cross(normalize(anisotropicFrameDirection), V);
+        vec3 anisotropicFrameNormal = cross(anisotropicFrameTangent, anisotropicFrameDirection);
+        vec3 anisotropicNormal = normalize(mix(N, anisotropicFrameNormal, abs(anisotropy)));
+        return anisotropicNormal;
+
+        // should we also do http://advances.realtimerendering.com/s2018/Siggraph%202018%20HDRP%20talk_with%20notes.pdf page 80 ?
+    }
+#endif
+
+#ifdef CLEARCOAT
+    // From beer lambert law I1/I0 = e −α′lc
+    // c is considered included in alpha
+    // https://blog.selfshadow.com/publications/s2017-shading-course/drobot/s2017_pbs_multilayered.pdf page 47
+    // where L on a thin constant size layer can be (d * ((NdotLRefract + NdotVRefract) / (NdotLRefract * NdotVRefract))
+    vec3 cocaLambert(float NdotVRefract, float NdotLRefract, vec3 alpha, float thickness) {
+        return exp(alpha * -(thickness * ((NdotLRefract + NdotVRefract) / (NdotLRefract * NdotVRefract))));
+    }
+
+    // From beerLambert Solves what alpha should be for a given resutlt at a known distance.
+    vec3 computeColorAtDistanceInMedia(vec3 color, float distance) {
+        return -log(color) / distance;
+    }
+
+    vec3 computeClearCoatAbsorption(float NdotVRefract, float NdotLRefract, vec3 clearCoatColor, float clearCoatThickness, float clearCoatIntensity) {
+        vec3 clearCoatAbsorption = mix(vec3(1.0),
+            cocaLambert(NdotVRefract, NdotLRefract, clearCoatColor, clearCoatThickness),
+            clearCoatIntensity);
+        return clearCoatAbsorption;
+    }
+#endif
+
+// ___________________________________________________________________________________
+//
+// LEGACY
+// ___________________________________________________________________________________
+
+#ifdef MICROSURFACEAUTOMATIC
+    float computeDefaultMicroSurface(float microSurface, vec3 reflectivityColor)
+    {
+        const float kReflectivityNoAlphaWorkflow_SmoothnessMax = 0.95;
+
+        float reflectivityLuminance = getLuminance(reflectivityColor);
+        float reflectivityLuma = sqrt(reflectivityLuminance);
+        microSurface = reflectivityLuma * kReflectivityNoAlphaWorkflow_SmoothnessMax;
+
+        return microSurface;
+    }
+#endif

+ 50 - 0
src/Shaders/ShadersInclude/pbrIBLFunctions.fx

@@ -0,0 +1,50 @@
+#if defined(REFLECTION) || defined(REFRACTION)
+    float getLodFromAlphaG(float cubeMapDimensionPixels, float microsurfaceAverageSlope) {
+        float microsurfaceAverageSlopeTexels = microsurfaceAverageSlope * cubeMapDimensionPixels;
+        float lod = log2(microsurfaceAverageSlopeTexels);
+        return lod;
+    }
+#endif
+
+#if defined(ENVIRONMENTBRDF) && defined(RADIANCEOCCLUSION)
+    float environmentRadianceOcclusion(float ambientOcclusion, float NdotVUnclamped) {
+        // Best balanced (implementation time vs result vs perf) analytical environment specular occlusion found.
+        // http://research.tri-ace.com/Data/cedec2011_RealtimePBR_Implementation_e.pptx
+        float temp = NdotVUnclamped + ambientOcclusion;
+        return saturate(square(temp) - 1.0 + ambientOcclusion);
+    }
+#endif
+
+#if defined(ENVIRONMENTBRDF) && defined(HORIZONOCCLUSION)
+    float environmentHorizonOcclusion(vec3 view, vec3 normal) {
+        // http://marmosetco.tumblr.com/post/81245981087
+        vec3 reflection = reflect(view, normal);
+        float temp = saturate(1.0 + 1.1 * dot(reflection, normal));
+        return square(temp);
+    }
+#endif
+
+// ___________________________________________________________________________________
+//
+// LEGACY
+// ___________________________________________________________________________________
+
+#if defined(LODINREFLECTIONALPHA) || defined(LODINREFRACTIONALPHA)
+    // To enable 8 bit textures to be used we need to pack and unpack the LOD
+    //inverse alpha is used to work around low-alpha bugs in Edge and Firefox
+    #define UNPACK_LOD(x) (1.0 - x) * 255.0
+
+    float getLodFromAlphaG(float cubeMapDimensionPixels, float alphaG, float NdotV) {
+        float microsurfaceAverageSlope = alphaG;
+
+        // Compensate for solid angle change between half-vector measure (Blinn-Phong) and reflected-vector measure (Phong):
+        //  dWr = 4*cos(theta)*dWh,
+        // where dWr = solid angle (delta omega) in environment incident radiance (reflection-vector) measure;
+        // where dWh = solid angle (delta omega) in microfacet normal (half-vector) measure;
+        // so the relationship is proportional to cosine theta = NdotV.
+        // The constant factor of four is handled elsewhere as part of the scale/offset filter parameters.
+        microsurfaceAverageSlope *= sqrt(abs(NdotV));
+
+        return getLodFromAlphaG(cubeMapDimensionPixels, microsurfaceAverageSlope);
+    }
+#endif

+ 0 - 87
src/Shaders/ShadersInclude/pbrLightingFunctions.fx

@@ -1,87 +0,0 @@
-// Light Results
-struct lightingInfo
-{
-    vec3 diffuse;
-    #ifdef SPECULARTERM
-        vec3 specular;
-    #endif
-    #ifdef CLEARCOAT
-        // xyz contains the clearcoat color.
-        // w contains the 1 - clearcoat fresnel to ease the energy conservation computation.
-        vec4 clearCoat;
-    #endif
-    #ifdef SHEEN
-        vec3 sheen;
-    #endif
-};
-
-vec3 computeHemisphericDiffuseLighting(preLightingInfo info, vec3 lightColor, vec3 groundColor) {
-    return mix(groundColor, lightColor, info.NdotL);
-}
-
-vec3 computeDiffuseLighting(preLightingInfo info, vec3 lightColor) {
-    float diffuseTerm = computeDiffuseTerm(info.NdotL, info.NdotV, info.VdotH, info.roughness);
-    return diffuseTerm * info.attenuation * info.NdotL * lightColor;
-}
-
-vec3 computeSpecularLighting(preLightingInfo info, vec3 N, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor, vec3 lightColor) {
-    float NdotH = saturateEps(dot(N, info.H));
-
-    vec3 specTerm = computeSpecularTerm(NdotH, info.NdotL, info.NdotV, info.VdotH, info.roughness, reflectance0, reflectance90, geometricRoughnessFactor);
-    return specTerm * info.attenuation * info.NdotL * lightColor;
-}
-
-#ifdef ANISOTROPIC
-    vec3 computeAnisotropicSpecularLighting(preLightingInfo info, vec3 V, vec3 N, vec3 T, vec3 B, float anisotropy, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor, vec3 lightColor) {
-        float NdotH = saturateEps(dot(N, info.H));
-
-        float TdotH = dot(T, info.H);
-        float BdotH = dot(B, info.H);
-
-        float TdotV = dot(T, V);
-        float BdotV = dot(B, V);
-        float TdotL = dot(T, info.L);
-        float BdotL = dot(B, info.L);
-
-        vec3 specTerm = computeAnisotropicSpecularTerm(NdotH, info.NdotL, info.NdotV, info.VdotH, TdotH, BdotH, TdotV, BdotV, TdotL, BdotL, info.roughness, anisotropy, reflectance0, reflectance90, geometricRoughnessFactor);
-        return specTerm * info.attenuation * info.NdotL * lightColor;
-    }
-#endif
-
-#ifdef CLEARCOAT
-    vec4 computeClearCoatLighting(preLightingInfo info, vec3 Ncc, float geometricRoughnessFactor, float clearCoatIntensity, vec3 lightColor) {
-        float NccdotL = saturateEps(dot(Ncc, info.L));
-        float NccdotH = saturateEps(dot(Ncc, info.H));
-
-        vec2 clearCoatTerm = computeClearCoatTerm(NccdotH, info.VdotH, info.roughness, geometricRoughnessFactor, clearCoatIntensity);
-
-        vec4 result = vec4(0.);
-        result.rgb = clearCoatTerm.x * info.attenuation * NccdotL * lightColor;
-        result.a = clearCoatTerm.y;
-        return result;
-    }
-
-    vec3 computeClearCoatLightingAbsorption(float NdotVRefract, vec3 L, vec3 Ncc, vec3 clearCoatColor, float clearCoatThickness, float clearCoatIntensity) {
-        vec3 LRefract = -refract(L, Ncc, vClearCoatRefractionParams.y);
-        float NdotLRefract = saturateEps(dot(Ncc, LRefract));
-
-        vec3 absorption = computeClearCoatAbsorption(NdotVRefract, NdotLRefract, clearCoatColor, clearCoatThickness, clearCoatIntensity);
-        return absorption;
-    }
-#endif
-
-#ifdef SHEEN
-    vec3 computeSheenLighting(preLightingInfo info, vec3 N, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor, vec3 lightColor) {
-        float NdotH = saturateEps(dot(N, info.H));
-
-        vec3 specTerm = computeSheenTerm(NdotH, info.NdotL, info.NdotV, info.VdotH, info.roughness, reflectance0, reflectance90, geometricRoughnessFactor);
-        return specTerm * info.attenuation * info.NdotL * lightColor;
-    }
-#endif
-
-vec3 computeProjectionTextureDiffuseLighting(sampler2D projectionLightSampler, mat4 textureProjectionMatrix){
-	vec4 strq = textureProjectionMatrix * vec4(vPositionW, 1.0);
-	strq /= strq.w;
-	vec3 textureColor = texture2D(projectionLightSampler, strq.xy).rgb;
-	return toLinearSpace(textureColor);
-}

+ 21 - 257
src/Shaders/pbr.fragment.fx

@@ -12,279 +12,43 @@
 
 precision highp float;
 
-#include<__decl__pbrFragment>
-
-uniform vec4 vEyePosition;
-uniform vec3 vAmbientColor;
-uniform vec4 vCameraInfos;
-
-// Input
-varying vec3 vPositionW;
-
-#if DEBUGMODE > 0
-    uniform vec2 vDebugMode;
-    varying vec4 vClipSpacePosition;
-#endif
-
-#ifdef MAINUV1
-    varying vec2 vMainUV1;
-#endif 
-
-#ifdef MAINUV2 
-    varying vec2 vMainUV2;
-#endif 
-
-#ifdef NORMAL
-    varying vec3 vNormalW;
-    #if defined(USESPHERICALFROMREFLECTIONMAP) && defined(USESPHERICALINVERTEX)
-        varying vec3 vEnvironmentIrradiance;
-    #endif
-#endif
-
-#ifdef VERTEXCOLOR
-varying vec4 vColor;
-#endif
-
-// Lights
-#include<__decl__lightFragment>[0..maxSimultaneousLights]
-
-// Samplers
-#ifdef ALBEDO
-    #if ALBEDODIRECTUV == 1
-        #define vAlbedoUV vMainUV1
-    #elif ALBEDODIRECTUV == 2
-        #define vAlbedoUV vMainUV2
-    #else
-        varying vec2 vAlbedoUV;
-    #endif
-    uniform sampler2D albedoSampler;
-#endif
-
-#ifdef AMBIENT
-    #if AMBIENTDIRECTUV == 1
-        #define vAmbientUV vMainUV1
-    #elif AMBIENTDIRECTUV == 2
-        #define vAmbientUV vMainUV2
-    #else
-        varying vec2 vAmbientUV;
-    #endif
-    uniform sampler2D ambientSampler;
-#endif
-
-#ifdef OPACITY
-    #if OPACITYDIRECTUV == 1
-        #define vOpacityUV vMainUV1
-    #elif OPACITYDIRECTUV == 2
-        #define vOpacityUV vMainUV2
-    #else
-        varying vec2 vOpacityUV;
-    #endif
-    uniform sampler2D opacitySampler;
-#endif
-
-#ifdef EMISSIVE
-    #if EMISSIVEDIRECTUV == 1
-        #define vEmissiveUV vMainUV1
-    #elif EMISSIVEDIRECTUV == 2
-        #define vEmissiveUV vMainUV2
-    #else
-        varying vec2 vEmissiveUV;
-    #endif
-    uniform sampler2D emissiveSampler;
-#endif
-
-#ifdef LIGHTMAP
-    #if LIGHTMAPDIRECTUV == 1
-        #define vLightmapUV vMainUV1
-    #elif LIGHTMAPDIRECTUV == 2
-        #define vLightmapUV vMainUV2
-    #else
-        varying vec2 vLightmapUV;
-    #endif
-    uniform sampler2D lightmapSampler;
-#endif
-
-#ifdef REFLECTIVITY
-    #if REFLECTIVITYDIRECTUV == 1
-        #define vReflectivityUV vMainUV1
-    #elif REFLECTIVITYDIRECTUV == 2
-        #define vReflectivityUV vMainUV2
-    #else
-        varying vec2 vReflectivityUV;
-    #endif
-    uniform sampler2D reflectivitySampler;
-#endif
-
-#ifdef MICROSURFACEMAP
-    #if MICROSURFACEMAPDIRECTUV == 1
-        #define vMicroSurfaceSamplerUV vMainUV1
-    #elif MICROSURFACEMAPDIRECTUV == 2
-        #define vMicroSurfaceSamplerUV vMainUV2
-    #else
-        varying vec2 vMicroSurfaceSamplerUV;
-    #endif
-    uniform sampler2D microSurfaceSampler;
-#endif
-
-#ifdef CLEARCOAT
-    #ifdef CLEARCOAT_TEXTURE
-        #if CLEARCOAT_TEXTUREDIRECTUV == 1
-            #define vClearCoatUV vMainUV1
-        #elif CLEARCOAT_TEXTUREDIRECTUV == 2
-            #define vClearCoatUV vMainUV2
-        #else
-            varying vec2 vClearCoatUV;
-        #endif
-        uniform sampler2D clearCoatSampler;
-    #endif
-
-    #ifdef CLEARCOAT_BUMP
-        #if CLEARCOAT_BUMPDIRECTUV == 1
-            #define vClearCoatBumpUV vMainUV1
-        #elif CLEARCOAT_BUMPDIRECTUV == 2
-            #define vClearCoatBumpUV vMainUV2
-        #else
-            varying vec2 vClearCoatBumpUV;
-        #endif
-        uniform sampler2D clearCoatBumpSampler;
-    #endif
-
-    #ifdef CLEARCOAT_TINT_TEXTURE
-        #if CLEARCOAT_TINT_TEXTUREDIRECTUV == 1
-            #define vClearCoatTintUV vMainUV1
-        #elif CLEARCOAT_TINT_TEXTUREDIRECTUV == 2
-            #define vClearCoatTintUV vMainUV2
-        #else
-            varying vec2 vClearCoatTintUV;
-        #endif
-        uniform sampler2D clearCoatTintSampler;
-    #endif
-#endif
-
-#ifdef SHEEN
-    #ifdef SHEEN_TEXTURE
-        #if SHEEN_TEXTUREDIRECTUV == 1
-            #define vSheenUV vMainUV1
-        #elif SHEEN_TEXTUREDIRECTUV == 2
-            #define vSheenUV vMainUV2
-        #else
-            varying vec2 vSheenUV;
-        #endif
-        uniform sampler2D sheenSampler;
-    #endif
-#endif
-
-#ifdef ANISOTROPIC
-    #ifdef ANISOTROPIC_TEXTURE
-        #if ANISOTROPIC_TEXTUREDIRECTUV == 1
-            #define vAnisotropyUV vMainUV1
-        #elif ANISOTROPIC_TEXTUREDIRECTUV == 2
-            #define vAnisotropyUV vMainUV2
-        #else
-            varying vec2 vAnisotropyUV;
-        #endif
-        uniform sampler2D anisotropySampler;
-    #endif
-#endif
-
-// Refraction
-#ifdef REFRACTION
-    #ifdef REFRACTIONMAP_3D
-        #define sampleRefraction(s, c) textureCube(s, c)
-        
-        uniform samplerCube refractionSampler;
-
-        #ifdef LODBASEDMICROSFURACE
-            #define sampleRefractionLod(s, c, l) textureCubeLodEXT(s, c, l)
-        #else
-            uniform samplerCube refractionSamplerLow;
-            uniform samplerCube refractionSamplerHigh;
-        #endif
-    #else
-        #define sampleRefraction(s, c) texture2D(s, c)
-        
-        uniform sampler2D refractionSampler;
-
-        #ifdef LODBASEDMICROSFURACE
-            #define sampleRefractionLod(s, c, l) texture2DLodEXT(s, c, l)
-        #else
-            uniform samplerCube refractionSamplerLow;
-            uniform samplerCube refractionSamplerHigh;
-        #endif
-    #endif
-#endif
-
-// Reflection
-#ifdef REFLECTION
-    #ifdef REFLECTIONMAP_3D
-        #define sampleReflection(s, c) textureCube(s, c)
-
-        uniform samplerCube reflectionSampler;
-        
-        #ifdef LODBASEDMICROSFURACE
-            #define sampleReflectionLod(s, c, l) textureCubeLodEXT(s, c, l)
-        #else
-            uniform samplerCube reflectionSamplerLow;
-            uniform samplerCube reflectionSamplerHigh;
-        #endif
-    #else
-        #define sampleReflection(s, c) texture2D(s, c)
-
-        uniform sampler2D reflectionSampler;
-
-        #ifdef LODBASEDMICROSFURACE
-            #define sampleReflectionLod(s, c, l) texture2DLodEXT(s, c, l)
-        #else
-            uniform samplerCube reflectionSamplerLow;
-            uniform samplerCube reflectionSamplerHigh;
-        #endif
-    #endif
-
-    #ifdef REFLECTIONMAP_SKYBOX
-        varying vec3 vPositionUVW;
-    #else
-        #if defined(REFLECTIONMAP_EQUIRECTANGULAR_FIXED) || defined(REFLECTIONMAP_MIRROREDEQUIRECTANGULAR_FIXED)
-            varying vec3 vDirectionW;
-        #endif
-    #endif
-
-    #include<reflectionFunction>
-#endif
-
-#ifdef ENVIRONMENTBRDF
-    uniform sampler2D environmentBrdfSampler;
-#endif
-
 // Forces linear space for image processing
 #ifndef FROMLINEARSPACE
     #define FROMLINEARSPACE;
 #endif
 
+// Declaration
+#include<__decl__pbrFragment>
+#include<pbrFragmentExtraDeclaration>
+#include<__decl__lightFragment>[0..maxSimultaneousLights]
+#include<pbrFragmentSamplersDeclaration>
 #include<imageProcessingDeclaration>
+#include<clipPlaneFragmentDeclaration>
+#include<logDepthDeclaration>
+#include<fogFragmentDeclaration>
 
+// Helper Functions
 #include<helperFunctions>
-
+#include<pbrHelperFunctions>
 #include<imageProcessingFunctions>
-
-// PBR
 #include<shadowsFragmentFunctions>
-#include<pbrFunctions>
 #include<harmonicsFunctions>
-#include<pbrPreLightingFunctions>
-#include<pbrFalloffLightingFunctions>
-#include<pbrLightingFunctions>
-
+#include<pbrDirectLightingSetupFunctions>
+#include<pbrDirectLightingFalloffFunctions>
+#include<pbrBRDFFunctions>
+#include<pbrDirectLightingFunctions>
+#include<pbrIBLFunctions>
 #include<bumpFragmentFunctions>
-#include<clipPlaneFragmentDeclaration>
-#include<logDepthDeclaration>
 
-// Fog
-#include<fogFragmentDeclaration>
+#ifdef REFLECTION
+    #include<reflectionFunction>
+#endif
 
+// _____________________________ MAIN FUNCTION ____________________________
 void main(void) {
-#include<clipPlaneFragment>
 
-// _______________________________________________________________________________
+    #include<clipPlaneFragment>
+
 // _____________________________ Geometry Information ____________________________
     vec3 viewDirectionW = normalize(vEyePosition.xyz - vPositionW);