sebavan 6 سال پیش
والد
کامیت
1c4391b526

+ 2 - 0
src/Shaders/ShadersInclude/bumpFragment.fx

@@ -12,6 +12,8 @@
 	#else
 		mat3 TBN = cotangent_frame(normalW * normalScale, vPositionW, vBumpUV);
 	#endif
+#elif defined(ANISOTROPIC)
+	mat3 TBN = cotangent_frame(normalW, vPositionW, vMainUV1, vec2(1., 1.));
 #endif
 
 #ifdef PARALLAX

+ 1 - 1
src/Shaders/ShadersInclude/bumpFragmentFunctions.fx

@@ -1,4 +1,4 @@
-#if defined(BUMP) || defined(CLEARCOAT_BUMP)
+#if defined(BUMP) || defined(CLEARCOAT_BUMP) || defined(ANISOTROPIC)
 	#if defined(TANGENT) && defined(NORMAL) 
 		varying mat3 vTBN;
 	#endif

+ 3 - 1
src/Shaders/ShadersInclude/lightFragment.fx

@@ -61,7 +61,9 @@
             #endif
 
             // Specular contribution
-            #ifdef SPECULARTERM
+            #ifdef ANISOTROPIC
+                info.specular = computeAnisotropicSpecularLighting(preInfo, viewDirectionW, normalW, vec3 T, vec3 B, anisotropy, specularEnvironmentR0, specularEnvironmentR90, AARoughnessFactors.x, light{X}.vLightDiffuse.rgb) {
+            #elif defined(SPECULARTERM)
                 info.specular = computeSpecularLighting(preInfo, normalW, specularEnvironmentR0, specularEnvironmentR90, AARoughnessFactors.x, light{X}.vLightDiffuse.rgb);
             #endif
 

+ 47 - 9
src/Shaders/ShadersInclude/pbrFunctions.fx

@@ -1,13 +1,13 @@
 // Constants
 #define RECIPROCAL_PI2 0.15915494
 #define FRESNEL_MAXIMUM_ON_ROUGH 0.25
+// 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
-    const float kMinimumVariance = 0.0005;
-    float alphaG = square(roughness) + kMinimumVariance;
-    return alphaG;
+    return square(roughness) + MINIMUMVARIANCE;
 }
 
 vec2 getAARoughnessFactors(vec3 normalVector) {
@@ -19,10 +19,9 @@ vec2 getAARoughnessFactors(vec3 normalVector) {
         // Vive analytical lights roughness factor.
         float geometricRoughnessFactor = pow(clamp(slopeSquare , 0., 1.), 0.333);
 
-        // BJS factor.
-        float geometricAlphaGFactor = sqrt(slopeSquare);
         // Adapt linear roughness (alphaG) to geometric curvature of the current pixel.
-        // 75% accounts a bit for the bigger tail linked to Gaussian Filtering.
+        float geometricAlphaGFactor = sqrt(slopeSquare);
+        // BJS factor.
         geometricAlphaGFactor *= 0.75;
 
         return vec2(geometricRoughnessFactor, geometricAlphaGFactor);
@@ -32,7 +31,7 @@ vec2 getAARoughnessFactors(vec3 normalVector) {
 }
 
 // From Microfacet Models for Refraction through Rough Surfaces, Walter et al. 2007
-// Kepp for references
+// Keep for references
 // float smithVisibilityG1_TrowbridgeReitzGGX(float dot, float alphaG)
 // {
 //     float tanSquared = (1.0 - dot * dot) / (dot * dot);
@@ -88,6 +87,33 @@ float normalDistributionFunction_TrowbridgeReitzGGX(float NdotH, float alphaG)
     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(at, ab);
+}
+
+// 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 * (1.0 / PI);
+}
+
+// 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 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 fresnelSchlickGGXVec3(float VdotH, vec3 reflectance0, vec3 reflectance90)
 {
     return reflectance0 + (reflectance90 - reflectance0) * pow(1.0 - VdotH, 5.0);
@@ -120,8 +146,7 @@ float computeDiffuseTerm(float NdotL, float NdotV, float VdotH, float roughness)
 }
 
 // Cook Torance Specular computation.
-vec3 computeSpecularTerm(float NdotH, float NdotL, float NdotV, float VdotH, float roughness, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor)
-{
+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);
 
@@ -133,6 +158,19 @@ vec3 computeSpecularTerm(float NdotH, float NdotL, float NdotV, float VdotH, flo
     return fresnel * specTerm;
 }
 
+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(NdotV, NdotL, TdotV, BdotV, TdotL, BdotL, alphaTB);
+    float specTerm = max(0., visibility * distribution);
+
+    vec3 fresnel = fresnelSchlickGGXVec3(VdotH, reflectance0, reflectance90);
+    return fresnel * specTerm;
+}
+
 vec2 computeClearCoatTerm(float NdotH, float VdotH, float clearCoatRoughness, float geometricRoughnessFactor, float clearCoatIntensity) {
     clearCoatRoughness = max(clearCoatRoughness, geometricRoughnessFactor);
     float alphaG = convertRoughnessToAverageSlope(clearCoatRoughness);

+ 21 - 5
src/Shaders/ShadersInclude/pbrLightingFunctions.fx

@@ -21,16 +21,32 @@ vec3 computeDiffuseLighting(preLightingInfo info, vec3 lightColor) {
     return diffuseTerm * info.attenuation * info.NdotL * lightColor;
 }
 
-vec3 computeSpecularLighting(preLightingInfo info, vec3 normal, vec3 reflectance0, vec3 reflectance90, float geometricRoughnessFactor, vec3 lightColor) {
-    float NdotH = clamp(dot(normal, info.H), 0.000000000001, 1.0);
+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);
 
     vec3 specTerm = computeSpecularTerm(NdotH, info.NdotL, info.NdotV, info.VdotH, info.roughness, reflectance0, reflectance90, geometricRoughnessFactor);
     return specTerm * info.attenuation * info.NdotL * lightColor;
 }
 
-vec4 computeClearCoatLighting(preLightingInfo info, vec3 normalClearCoat, float geometricRoughnessFactor, float clearCoatIntensity, vec3 lightColor) {
-    float NccdotL = clamp(dot(normalClearCoat, info.L), 0.00000000001, 1.0);
-    float NccdotH = clamp(dot(normalClearCoat, info.H), 0.000000000001, 1.0);
+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 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);
+
+    computeAnisotropicSpecularTerm(NdotH, info.NdotL, info.NdotV, info.VdotH, TdotH, BdotH, TdotV, BdotV, TdotL, BdotL, info.roughness, anisotropy, reflectance0, reflectance90, geometricRoughnessFactor);
+    vec3 specTerm = computeSpecularTerm(NdotH, info.NdotL, info.NdotV, info.VdotH, info.roughness, reflectance0, reflectance90, geometricRoughnessFactor);
+    return specTerm * info.attenuation * info.NdotL * lightColor;
+}
+
+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);
 
     vec2 clearCoatTerm = computeClearCoatTerm(NccdotH, info.VdotH, info.roughness, geometricRoughnessFactor, clearCoatIntensity);
 

+ 29 - 3
src/Shaders/pbr.fragment.fx

@@ -10,6 +10,8 @@
 #extension GL_EXT_frag_depth : enable
 #endif
 
+#define ANISOTROPIC 
+
 precision highp float;
 
 #include<__decl__pbrFragment>
@@ -455,7 +457,6 @@ void main(void) {
 
     #ifdef SPECULARAA
         // Adapt linear roughness (alphaG) to geometric curvature of the current pixel.
-        // 75% accounts a bit for the bigger tail linked to Gaussian Filtering.
         alphaG += AARoughnessFactors.y;
     #endif
 
@@ -463,6 +464,17 @@ void main(void) {
     #ifdef REFRACTION
         vec4 environmentRefraction = vec4(0., 0., 0., 0.);
 
+        // #ifdef ANISOTROPIC
+        //     float anisotropy = -1.;
+        //     vec3 anisotropicDirection = anisotropy >= 0.0 ? TBN[1] : TBN[0];
+        //     vec3 anisotropicTangent = cross(normalize(anisotropicDirection), normalize(viewDirectionW));
+        //     vec3 anisotropicNormal = cross(anisotropicTangent, anisotropicDirection);
+        //     vec3 bentNormal = normalize(mix(normalW, anisotropicNormal, abs(anisotropy)));
+        //     vec3 reflectionVector = computeReflectionCoords(vec4(vPositionW, 1.0), bentNormal);
+        // #else
+        //     vec3 reflectionVector = normalW;
+        // #endif
+
         vec3 refractionVector = refract(-viewDirectionW, normalW, vRefractionInfos.y);
         #ifdef REFRACTIONMAP_OPPOSITEZ
             refractionVector.z *= -1.0;
@@ -543,8 +555,17 @@ void main(void) {
     #ifdef REFLECTION
         vec4 environmentRadiance = vec4(0., 0., 0., 0.);
         vec3 environmentIrradiance = vec3(0., 0., 0.);
+        #ifdef ANISOTROPIC
+            float anisotropy = 1.;
+            vec3 anisotropicDirection = anisotropy >= 0.0 ? TBN[1] : TBN[0];
+            vec3 anisotropicTangent = cross(normalize(anisotropicDirection), normalize(viewDirectionW));
+            vec3 anisotropicNormal = cross(anisotropicTangent, anisotropicDirection);
+            vec3 bentNormal = normalize(mix(normalW, anisotropicNormal, abs(anisotropy)));
+            vec3 reflectionVector = computeReflectionCoords(vec4(vPositionW, 1.0), bentNormal);
+        #else
+            vec3 reflectionVector = normalW;
+        #endif
 
-        vec3 reflectionVector = computeReflectionCoords(vec4(vPositionW, 1.0), normalW);
         #ifdef REFLECTIONMAP_OPPOSITEZ
             reflectionVector.z *= -1.0;
         #endif
@@ -693,7 +714,6 @@ void main(void) {
 
             #ifdef SPECULARAA
                 // Adapt linear roughness (alphaG) to geometric curvature of the current pixel.
-                // 75% accounts a bit for the bigger tail linked to Gaussian Filtering.
                 clearCoatAlphaG += clearCoatAARoughnessFactors.y;
             #endif
 
@@ -1138,4 +1158,10 @@ void main(void) {
     //gl_FragColor = vec4(eho, eho, eho, 1.0);
 
     //gl_FragColor = vec4(seo * eho, seo * eho, seo * eho, 1.0);
+
+    //gl_FragColor = vec4(normalize(TBN[0]) * 0.5 + 0.5, 1.0);
+
+    //gl_FragColor = vec4(vPositionW * 0.5 + 0.5, 1.0);
+
+    //gl_FragColor = vec4(vMainUV1, 0., 1.0);
 }