Browse Source

Merge pull request #21299 from zeux/degentbn

Replace perturbNormal implementation with a more robust version
Mr.doob 4 years ago
parent
commit
dee35282b7
1 changed files with 10 additions and 9 deletions
  1. 10 9
      src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl.js

+ 10 - 9
src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl.js

@@ -14,8 +14,8 @@ export default /* glsl */`
 
 #if ! defined ( USE_TANGENT ) && ( defined ( TANGENTSPACE_NORMALMAP ) || defined ( USE_CLEARCOAT_NORMALMAP ) )
 
-	// Per-Pixel Tangent Space Normal Mapping
-	// http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html
+	// Normal Mapping Without Precomputed Tangents
+	// http://www.thetenthplanet.de/archives/1180
 
 	vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, float faceDirection ) {
 
@@ -26,17 +26,18 @@ export default /* glsl */`
 		vec2 st0 = dFdx( vUv.st );
 		vec2 st1 = dFdy( vUv.st );
 
-		float scale = sign( st1.t * st0.s - st0.t * st1.s ); // we do not care about the magnitude
+		vec3 N = surf_norm; // normalized
 
-		vec3 S = normalize( ( q0 * st1.t - q1 * st0.t ) * scale );
-		vec3 T = normalize( ( - q0 * st1.s + q1 * st0.s ) * scale );
-		vec3 N = normalize( surf_norm );
+		vec3 q1perp = cross( q1, N );
+		vec3 q0perp = cross( N, q0 );
 
-		mat3 tsn = mat3( S, T, N );
+		vec3 T = q1perp * st0.x + q0perp * st1.x;
+		vec3 B = q1perp * st0.y + q0perp * st1.y;
 
-		mapN.xy *= faceDirection;
+		float det = max( dot( T, T ), dot( B, B ) );
+		float scale = ( det == 0.0 ) ? 0.0 : faceDirection * inversesqrt( det );
 
-		return normalize( tsn * mapN );
+		return normalize( T * ( mapN.x * scale ) + B * ( mapN.y * scale ) + N * mapN.z );
 
 	}