Browse Source

Fix Pbr Visibility

sebavan 6 years ago
parent
commit
f8e4a4a8d9

+ 9 - 1
src/Shaders/ShadersInclude/helperFunctions.fx

@@ -4,6 +4,14 @@ const float LinearEncodePowerApprox = 2.2;
 const float GammaEncodePowerApprox = 1.0 / LinearEncodePowerApprox;
 const vec3 LuminanceEncodeApprox = vec3(0.2126, 0.7152, 0.0722);
 
+const float Epsilon = 0.0000001;
+
+#define saturate(x)         clamp(x, 0.0, 1.0)
+
+#define absEps(x)           abs(x) + Epsilon
+#define maxEps(x)           max(x, Epsilon)
+#define saturateEps(x)      clamp(x, Epsilon, 1.0)
+
 mat3 transposeMat3(mat3 inMatrix) {
     vec3 i0 = inMatrix[0];
     vec3 i1 = inMatrix[1];
@@ -81,7 +89,7 @@ float dither(vec2 seed, float varianceAmount) {
 const float rgbdMaxRange = 255.0;
 
 vec4 toRGBD(vec3 color) {
-    float maxRGB = max(0.0000001, max(color.r, max(color.g, color.b)));
+    float maxRGB = maxEps(max(color.r, max(color.g, color.b)));
     float D      = max(rgbdMaxRange / maxRGB, 1.);
     D            = clamp(floor(D) / 255.0, 0., 1.);
     // vec3 rgb = color.rgb * (D * (255.0 / rgbdMaxRange));

+ 4 - 4
src/Shaders/ShadersInclude/imageProcessingFunctions.fx

@@ -28,13 +28,13 @@
 		sliceUV.x *= sliceSize;
 		sliceUV.x += sliceInteger * sliceSize;
 
-		sliceUV = clamp(sliceUV, 0., 1.);
+		sliceUV = saturate(sliceUV);
 
 		vec4 slice0Color = texture2D(colorTransform, sliceUV);
 
 		sliceUV.x += sliceSize;
 		
-		sliceUV = clamp(sliceUV, 0., 1.);
+		sliceUV = saturate(sliceUV);
 		vec4 slice1Color = texture2D(colorTransform, sliceUV);
 
 		vec3 result = mix(slice0Color.rgb, slice1Color.rgb, sliceFraction);
@@ -86,7 +86,7 @@
 		color = ACESOutputMat * color;
 
 		// Clamp to [0, 1]
-		color = clamp(color, 0.0, 1.0);
+		color = saturate(color);
 
 		return color;
 	}
@@ -130,7 +130,7 @@ vec4 applyImageProcessing(vec4 result) {
 
 	// Going back to gamma space
 	result.rgb = toGammaSpace(result.rgb);
-	result.rgb = clamp(result.rgb, 0.0, 1.0);
+	result.rgb = saturate(result.rgb);
 
 #ifdef CONTRAST
 	// Contrast

+ 3 - 3
src/Shaders/ShadersInclude/pbrFalloffLightingFunctions.fx

@@ -14,7 +14,7 @@ float computeDistanceLightFalloff_GLTF(float lightDistanceSquared, float inverse
     float lightDistanceFalloff = 1.0 / (max(lightDistanceSquared, minDistanceSquared));
 
     float factor = lightDistanceSquared * inverseSquaredRange;
-    float attenuation = clamp(1.0 - factor * factor, 0., 1.);
+    float attenuation = saturate(1.0 - factor * factor);
     attenuation *= attenuation;
 
     // Smooth attenuation of the falloff defined by the range.
@@ -38,7 +38,7 @@ float computeDirectionalLightFalloff_Standard(vec3 lightDirection, vec3 directio
 {
     float falloff = 0.0;
 
-    float cosAngle = max(0.000000000000001, dot(-lightDirection, directionToLightCenterW));
+    float cosAngle = max(Epsilon, dot(-lightDirection, directionToLightCenterW));
     if (cosAngle >= cosHalfAngle)
     {
         falloff = max(0., pow(cosAngle, exponent));
@@ -72,7 +72,7 @@ float computeDirectionalLightFalloff_GLTF(vec3 lightDirection, vec3 directionToL
     // float lightAngleOffset = -cosOuter * angleScale;
 
     float cd = dot(-lightDirection, directionToLightCenterW);
-    float falloff = clamp(cd * lightAngleScale + lightAngleOffset, 0., 1.);
+    float falloff = saturate(cd * lightAngleScale + lightAngleOffset);
     // smooth the transition
     falloff *= falloff;
     return falloff;

+ 22 - 18
src/Shaders/ShadersInclude/pbrFunctions.fx

@@ -21,7 +21,7 @@ vec2 getAARoughnessFactors(vec3 normalVector) {
         float slopeSquare = max(dot(nDfdx, nDfdx), dot(nDfdy, nDfdy));
 
         // Vive analytical lights roughness factor.
-        float geometricRoughnessFactor = pow(clamp(slopeSquare , 0., 1.), 0.333);
+        float geometricRoughnessFactor = pow(saturate(slopeSquare), 0.333);
 
         // Adapt linear roughness (alphaG) to geometric curvature of the current pixel.
         float geometricAlphaGFactor = sqrt(slopeSquare);
@@ -92,7 +92,7 @@ vec3 getReflectanceFromAnalyticalBRDFLookup_Jones(float VdotN, vec3 reflectance0
 {
     // 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) * pow(clamp(1.0 - VdotN, 0., 1.), 5.0);
+    return reflectance0 + weight * (reflectance90 - reflectance0) * pow(saturate(1.0 - VdotN), 5.0);
 }
 
 vec3 getSheenReflectanceFromBRDFLookup(const vec3 reflectance0, float NdotV, float sheenAlphaG) {
@@ -134,9 +134,9 @@ vec3 getSheenReflectanceFromBRDFLookup(const vec3 reflectance0, float NdotV, flo
     vec3 getR0RemappedForClearCoat(vec3 f0) {
         #ifdef CLEARCOAT_DEFAULTIOR
             #ifdef MOBILE
-                return clamp(f0 * (f0 * 0.526868 + 0.529324) - 0.0482256, 0., 1.);
+                return saturate(f0 * (f0 * 0.526868 + 0.529324) - 0.0482256);
             #else
-                return clamp(f0 * (f0 * (0.941892 - 0.263008 * f0) + 0.346479) - 0.0285998, 0., 1.);
+                return saturate(f0 * (f0 * (0.941892 - 0.263008 * f0) + 0.346479) - 0.0285998);
             #endif
         #else
             vec3 s = sqrt(f0);
@@ -249,7 +249,7 @@ float normalDistributionFunction_BurleyGGX_Anisotropic(float NdotH, float TdotH,
 // 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 NdotV, float NdotL, float alphaG) {
+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);
@@ -257,15 +257,15 @@ float smithVisibility_GGXCorrelated(float NdotV, float NdotL, float alphaG) {
         return 0.5 / (GGXV + GGXL);
     #else
         float a2 = alphaG * alphaG;
-        float GGXV = NdotL * sqrt(NdotV * NdotV * (1.0 - a2) + a2);
-        float GGXL = NdotV * sqrt(NdotL * NdotL * (1.0 - a2) + a2);
+        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 NdotV, float NdotL, float TdotV, float BdotV, float TdotL, float BdotL, const vec2 alphaTB) {
+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);
@@ -300,8 +300,8 @@ vec3 computeColorAtDistanceInMedia(vec3 color, float distance) {
 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 = pow(clamp(1.0 - NdotL, 0.000001, 1.), 5.0);
-    float diffuseFresnelNL = pow(clamp(1.0 - NdotV, 0.000001, 1.), 5.0);
+    float diffuseFresnelNV = pow(saturateEps(1.0 - NdotL), 5.0);
+    float diffuseFresnelNL = pow(saturateEps(1.0 - NdotV), 5.0);
     float diffuseFresnel90 = 0.5 + 2.0 * VdotH * VdotH * roughness;
     float fresnel =
         (1.0 + (diffuseFresnel90 - 1.0) * diffuseFresnelNL) *
@@ -351,7 +351,7 @@ vec3 computeSpecularTerm(float NdotH, float NdotL, float NdotV, float VdotH, flo
         alphaTB = max(alphaTB, geometricRoughnessFactor * geometricRoughnessFactor);
 
         float distribution = normalDistributionFunction_BurleyGGX_Anisotropic(NdotH, TdotH, BdotH, alphaTB);
-        float visibility = smithVisibility_GGXCorrelated_Anisotropic(NdotV, NdotL, TdotV, BdotV, TdotL, BdotL, 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);
@@ -388,7 +388,7 @@ float adjustRoughnessFromLightProperties(float roughness, float lightRadius, flo
         // At small angle this approximation works. 
         float lightRoughness = lightRadius / lightDistance;
         // Distribution can sum.
-        float totalRoughness = clamp(lightRoughness + roughness, 0., 1.);
+        float totalRoughness = saturate(lightRoughness + roughness);
         return totalRoughness;
     #else
         return roughness;
@@ -409,7 +409,7 @@ float computeDefaultMicroSurface(float microSurface, vec3 reflectivityColor)
 // 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 fresnelGrazingReflectance(float reflectance0) {
-    float reflectance90 = clamp(reflectance0 * 25.0, 0.0, 1.0);
+    float reflectance90 = saturate(reflectance0 * 25.0);
     return reflectance90;
 }
 
@@ -417,6 +417,12 @@ float fresnelGrazingReflectance(float reflectance0) {
 //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 microsurfaceAverageSlope) {
+    float microsurfaceAverageSlopeTexels = microsurfaceAverageSlope * cubeMapDimensionPixels;
+    float lod = log2(microsurfaceAverageSlopeTexels);
+    return lod;
+}
+
 float getLodFromAlphaG(float cubeMapDimensionPixels, float alphaG, float NdotV) {
     float microsurfaceAverageSlope = alphaG;
 
@@ -428,21 +434,19 @@ float getLodFromAlphaG(float cubeMapDimensionPixels, float alphaG, float NdotV)
     // The constant factor of four is handled elsewhere as part of the scale/offset filter parameters.
     microsurfaceAverageSlope *= sqrt(abs(NdotV));
 
-    float microsurfaceAverageSlopeTexels = microsurfaceAverageSlope * cubeMapDimensionPixels;
-    float lod = log2(microsurfaceAverageSlopeTexels);
-    return lod;
+    return getLodFromAlphaG(cubeMapDimensionPixels, microsurfaceAverageSlope);
 }
 
 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 clamp(square(temp) - 1.0 + ambientOcclusion, 0.0, 1.0);
+    return saturate(square(temp) - 1.0 + ambientOcclusion);
 }
 
 float environmentHorizonOcclusion(vec3 view, vec3 normal) {
     // http://marmosetco.tumblr.com/post/81245981087
     vec3 reflection = reflect(view, normal);
-    float temp = clamp( 1.0 + 1.1 * dot(reflection, normal), 0.0, 1.0);
+    float temp = saturate(1.0 + 1.1 * dot(reflection, normal));
     return square(temp);
 }

+ 6 - 6
src/Shaders/ShadersInclude/pbrLightingFunctions.fx

@@ -25,7 +25,7 @@ vec3 computeDiffuseLighting(preLightingInfo info, vec3 lightColor) {
 }
 
 vec3 computeSpecularLighting(preLightingInfo info, vec3 N, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor, vec3 lightColor) {
-    float NdotH = clamp(dot(N, info.H), 0.000000000001, 1.0);
+    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;
@@ -33,7 +33,7 @@ vec3 computeSpecularLighting(preLightingInfo info, vec3 N, vec3 reflectance0, ve
 
 #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 = clamp(dot(N, info.H), 0.000000000001, 1.0);
+        float NdotH = saturateEps(dot(N, info.H));
 
         float TdotH = dot(T, info.H);
         float BdotH = dot(B, info.H);
@@ -50,8 +50,8 @@ vec3 computeSpecularLighting(preLightingInfo info, vec3 N, vec3 reflectance0, ve
 
 #ifdef CLEARCOAT
     vec4 computeClearCoatLighting(preLightingInfo info, vec3 Ncc, float geometricRoughnessFactor, float clearCoatIntensity, vec3 lightColor) {
-        float NccdotL = clamp(dot(Ncc, info.L), 0.00000000001, 1.0);
-        float NccdotH = clamp(dot(Ncc, info.H), 0.000000000001, 1.0);
+        float NccdotL = saturateEps(dot(Ncc, info.L));
+        float NccdotH = saturateEps(dot(Ncc, info.H));
 
         vec2 clearCoatTerm = computeClearCoatTerm(NccdotH, info.VdotH, info.roughness, geometricRoughnessFactor, clearCoatIntensity);
 
@@ -63,7 +63,7 @@ vec3 computeSpecularLighting(preLightingInfo info, vec3 N, vec3 reflectance0, ve
 
     vec3 computeClearCoatLightingAbsorption(float NdotVRefract, vec3 L, vec3 Ncc, vec3 clearCoatColor, float clearCoatThickness, float clearCoatIntensity) {
         vec3 LRefract = -refract(L, Ncc, vClearCoatRefractionParams.y);
-        float NdotLRefract = clamp(dot(Ncc, LRefract), 0.00000000001, 1.0);
+        float NdotLRefract = saturateEps(dot(Ncc, LRefract));
 
         vec3 absorption = computeClearCoatAbsorption(NdotVRefract, NdotLRefract, clearCoatColor, clearCoatThickness, clearCoatIntensity);
         return absorption;
@@ -72,7 +72,7 @@ vec3 computeSpecularLighting(preLightingInfo info, vec3 N, vec3 reflectance0, ve
 
 #ifdef SHEEN
     vec3 computeSheenLighting(preLightingInfo info, vec3 N, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor, vec3 lightColor) {
-        float NdotH = clamp(dot(N, info.H), 0.000000000001, 1.0);
+        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;

+ 6 - 6
src/Shaders/ShadersInclude/pbrPreLightingFunctions.fx

@@ -31,8 +31,8 @@ preLightingInfo computePointAndSpotPreLightingInfo(vec4 lightData, vec3 V, vec3
     // Geometry Data.
     result.L = normalize(result.lightOffset);
     result.H = normalize(V + result.L);
-    result.NdotL = clamp(dot(N, result.L), 0.000000000001, 1.0);
-    result.VdotH = clamp(dot(V, result.H), 0.0, 1.0);
+    result.NdotL = saturateEps(dot(N, result.L));
+    result.VdotH = saturate(dot(V, result.H));
 
     return result;
 }
@@ -46,8 +46,8 @@ preLightingInfo computeDirectionalPreLightingInfo(vec4 lightData, vec3 V, vec3 N
     // Geometry Data.
     result.L = normalize(-lightData.xyz);
     result.H = normalize(V + result.L);
-    result.NdotL = clamp(dot(N, result.L), 0.00000000001, 1.0);
-    result.VdotH = clamp(dot(V, result.H), 0.0, 1.0);
+    result.NdotL = saturateEps(dot(N, result.L));
+    result.VdotH = saturate(dot(V, result.H));
 
     return result;
 }
@@ -57,12 +57,12 @@ preLightingInfo computeHemisphericPreLightingInfo(vec4 lightData, vec3 V, vec3 N
 
     // Geometry Data.
     result.NdotL = dot(N, lightData.xyz) * 0.5 + 0.5;
-    result.NdotL = clamp(result.NdotL, 0.000000000001, 1.0);
+    result.NdotL = saturateEps(result.NdotL);
 
     #ifdef SPECULARTERM
         result.L = normalize(lightData.xyz);
         result.H = normalize(V + result.L);
-        result.VdotH = clamp(dot(V, result.H), 0.0, 1.0);
+        result.VdotH = saturate(dot(V, result.H));
     #endif
 
     return result;

+ 15 - 15
src/Shaders/pbr.fragment.fx

@@ -468,7 +468,7 @@ void main(void) {
     #endif
 
     // Adapt microSurface.
-    microSurface = clamp(microSurface, 0., 1.);
+    microSurface = saturate(microSurface);
     // Compute roughness.
     float roughness = 1. - microSurface;
 
@@ -490,7 +490,7 @@ void main(void) {
             vec3 normalForward = faceforward(normalW, -viewDirectionW, normalW);
 
             // Calculate the appropriate linear opacity for the current viewing angle (formally, this quantity is the "directional absorptance").
-            alpha = getReflectanceFromAnalyticalBRDFLookup_Jones(clamp(dot(viewDirectionW, normalForward), 0.0, 1.0), vec3(opacity0), vec3(opacity90), sqrt(microSurface)).x;
+            alpha = getReflectanceFromAnalyticalBRDFLookup_Jones(saturate(dot(viewDirectionW, normalForward)), vec3(opacity0), vec3(opacity90), sqrt(microSurface)).x;
 
             #ifdef ALPHATEST
                 if (alpha < ALPHATESTVALUE)
@@ -506,7 +506,7 @@ void main(void) {
 
     // _____________________________ Compute Geometry info _________________________________
     float NdotVUnclamped = dot(normalW, viewDirectionW);
-    float NdotV = clamp(NdotVUnclamped,0., 1.) + 0.00001;
+    float NdotV = absEps(NdotVUnclamped);
     float alphaG = convertRoughnessToAverageSlope(roughness);
     vec2 AARoughnessFactors = getAARoughnessFactors(normalW.xyz);
 
@@ -560,7 +560,7 @@ void main(void) {
         #ifdef LODINREFRACTIONALPHA
             float refractionLOD = getLodFromAlphaG(vRefractionMicrosurfaceInfos.x, alphaG, NdotVUnclamped);
         #else
-            float refractionLOD = getLodFromAlphaG(vRefractionMicrosurfaceInfos.x, alphaG, 1.0);
+            float refractionLOD = getLodFromAlphaG(vRefractionMicrosurfaceInfos.x, alphaG);
         #endif
 
         #ifdef LODBASEDMICROSFURACE
@@ -586,7 +586,7 @@ void main(void) {
 
             environmentRefraction = sampleRefractionLod(refractionSampler, refractionCoords, requestedRefractionLOD);
         #else
-            float lodRefractionNormalized = clamp(refractionLOD / log2(vRefractionMicrosurfaceInfos.x), 0., 1.);
+            float lodRefractionNormalized = saturate(refractionLOD / log2(vRefractionMicrosurfaceInfos.x));
             float lodRefractionNormalizedDoubled = lodRefractionNormalized * 2.0;
 
             vec4 environmentRefractionMid = sampleRefraction(refractionSampler, refractionCoords);
@@ -646,7 +646,7 @@ void main(void) {
         #if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX)
             float reflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, alphaG, NdotVUnclamped);
         #else
-            float reflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, alphaG, 1.);
+            float reflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, alphaG);
         #endif
 
         #ifdef LODBASEDMICROSFURACE
@@ -672,7 +672,7 @@ void main(void) {
 
             environmentRadiance = sampleReflectionLod(reflectionSampler, reflectionCoords, requestedReflectionLOD);
         #else
-            float lodReflectionNormalized = clamp(reflectionLOD / log2(vReflectionMicrosurfaceInfos.x), 0., 1.);
+            float lodReflectionNormalized = saturate(reflectionLOD / log2(vReflectionMicrosurfaceInfos.x));
             float lodReflectionNormalizedDoubled = lodReflectionNormalized * 2.0;
 
             vec4 environmentSpecularMid = sampleReflection(reflectionSampler, reflectionCoords);
@@ -771,7 +771,7 @@ void main(void) {
             #if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX)
                 float sheenReflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, sheenAlphaG, NdotVUnclamped);
             #else
-                float sheenReflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, sheenAlphaG, 1.);
+                float sheenReflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, sheenAlphaG);
             #endif
 
             #ifdef LODBASEDMICROSFURACE
@@ -779,7 +779,7 @@ void main(void) {
                 sheenReflectionLOD = sheenReflectionLOD * vReflectionMicrosurfaceInfos.y + vReflectionMicrosurfaceInfos.z;
                 environmentSheenRadiance = sampleReflectionLod(reflectionSampler, reflectionCoords, sheenReflectionLOD);
             #else
-                float lodSheenReflectionNormalized = clamp(sheenReflectionLOD / log2(vReflectionMicrosurfaceInfos.x), 0., 1.);
+                float lodSheenReflectionNormalized = saturate(sheenReflectionLOD / log2(vReflectionMicrosurfaceInfos.x));
                 float lodSheenReflectionNormalizedDoubled = lodSheenReflectionNormalized * 2.0;
 
                 vec4 environmentSheenMid = sampleReflection(reflectionSampler, reflectionCoords);
@@ -879,7 +879,7 @@ void main(void) {
 
         // Compute N dot V.
         float clearCoatNdotVUnclamped = dot(clearCoatNormalW, viewDirectionW);
-        float clearCoatNdotV = clamp(clearCoatNdotVUnclamped,0., 1.) + 0.00001;
+        float clearCoatNdotV = absEps(clearCoatNdotVUnclamped);
 
         // Clear Coat Reflection
         #if defined(REFLECTION)
@@ -911,7 +911,7 @@ void main(void) {
             #if defined(LODINREFLECTIONALPHA) && !defined(REFLECTIONMAP_SKYBOX)
                 float clearCoatReflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, clearCoatAlphaG, clearCoatNdotVUnclamped);
             #else
-                float clearCoatReflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, clearCoatAlphaG, 1.);
+                float clearCoatReflectionLOD = getLodFromAlphaG(vReflectionMicrosurfaceInfos.x, clearCoatAlphaG);
             #endif
 
             #ifdef LODBASEDMICROSFURACE
@@ -921,7 +921,7 @@ void main(void) {
 
                 environmentClearCoatRadiance = sampleReflectionLod(reflectionSampler, clearCoatReflectionCoords, requestedClearCoatReflectionLOD);
             #else
-                float lodClearCoatReflectionNormalized = clamp(clearCoatReflectionLOD / log2(vReflectionMicrosurfaceInfos.x), 0., 1.);
+                float lodClearCoatReflectionNormalized = saturate(clearCoatReflectionLOD / log2(vReflectionMicrosurfaceInfos.x));
                 float lodClearCoatReflectionNormalizedDoubled = lodClearCoatReflectionNormalized * 2.0;
 
                 vec4 environmentClearCoatMid = sampleReflection(reflectionSampler, reflectionCoords);
@@ -951,7 +951,7 @@ void main(void) {
             #ifdef CLEARCOAT_TINT
                 // Used later on in the light fragment and ibl.
                 vec3 clearCoatVRefract = -refract(vPositionW, clearCoatNormalW, vClearCoatRefractionParams.y);
-                float clearCoatNdotVRefract = clamp(dot(clearCoatNormalW, clearCoatVRefract), 0.00000000001, 1.0);
+                float clearCoatNdotVRefract = absEps(dot(clearCoatNormalW, clearCoatVRefract));
                 vec3 absorption = vec3(0.);
             #endif
 
@@ -1115,7 +1115,7 @@ void main(void) {
             // TODO. PBR Tinting.
             vec3 mixedAlbedo = surfaceAlbedo;
             float maxChannel = max(max(mixedAlbedo.r, mixedAlbedo.g), mixedAlbedo.b);
-            vec3 tint = clamp(maxChannel * mixedAlbedo, 0.0, 1.0);
+            vec3 tint = saturate(maxChannel * mixedAlbedo);
 
             // Decrease Albedo Contribution
             surfaceAlbedo *= alpha;
@@ -1252,7 +1252,7 @@ void main(void) {
         #endif
 
         #if defined(RADIANCEOVERALPHA) || defined(SPECULAROVERALPHA)
-            alpha = clamp(alpha + luminanceOverAlpha * luminanceOverAlpha, 0., 1.);
+            alpha = saturate(alpha + luminanceOverAlpha * luminanceOverAlpha);
         #endif
     #endif
 #endif