Răsfoiți Sursa

Merge pull request #21202 from mrdoob/glfrontfacing

ShaderChunk: Workaround for Adreno GPUs gl_FrontFacing bug.
Mr.doob 4 ani în urmă
părinte
comite
7168cd0cec

+ 2 - 2
src/renderers/shaders/ShaderChunk/bumpmap_pars_fragment.glsl.js

@@ -22,7 +22,7 @@ export default /* glsl */`
 
 	}
 
-	vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy ) {
+	vec3 perturbNormalArb( vec3 surf_pos, vec3 surf_norm, vec2 dHdxy, bool isFrontFacing ) {
 
 		// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988
 
@@ -35,7 +35,7 @@ export default /* glsl */`
 
 		float fDet = dot( vSigmaX, R1 );
 
-		fDet *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );
+		fDet *= ( float( isFrontFacing ) * 2.0 - 1.0 );
 
 		vec3 vGrad = sign( fDet ) * ( dHdxy.x * R1 + dHdxy.y * R2 );
 		return normalize( abs( fDet ) * surf_norm - vGrad );

+ 1 - 1
src/renderers/shaders/ShaderChunk/clearcoat_normal_fragment_maps.glsl.js

@@ -10,7 +10,7 @@ export default /* glsl */`
 
 	#else
 
-		clearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN );
+		clearcoatNormal = perturbNormal2Arb( - vViewPosition, clearcoatNormal, clearcoatMapN, isFrontFacing );
 
 	#endif
 

+ 18 - 4
src/renderers/shaders/ShaderChunk/normal_fragment_begin.glsl.js

@@ -1,19 +1,33 @@
 export default /* glsl */`
+bool isFrontFacing = true;
+
 #ifdef FLAT_SHADED
 
-	// Workaround for Adreno/Nexus5 not able able to do dFdx( vViewPosition ) ...
+	// Workaround for Adreno GPUs not able to do dFdx( vViewPosition )
 
 	vec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );
 	vec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );
 	vec3 normal = normalize( cross( fdx, fdy ) );
 
+	isFrontFacing = dot( vec3( 0, 0, 1 ), normal ) > 0.0;
+
 #else
 
 	vec3 normal = normalize( vNormal );
 
 	#ifdef DOUBLE_SIDED
 
-		normal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );
+		// Workaround for Adreno GPUs not able to do dFdx( vViewPosition )
+
+		vec3 fdx = vec3( dFdx( vViewPosition.x ), dFdx( vViewPosition.y ), dFdx( vViewPosition.z ) );
+		vec3 fdy = vec3( dFdy( vViewPosition.x ), dFdy( vViewPosition.y ), dFdy( vViewPosition.z ) );
+
+		// Workaround for Adreno GPUs broken gl_FrontFacing implementation
+		// https://stackoverflow.com/a/32621243
+
+		isFrontFacing = dot( normal, normalize( cross( fdx, fdy ) ) ) > 0.0;
+
+		normal = normal * ( float( isFrontFacing ) * 2.0 - 1.0 );
 
 	#endif
 
@@ -24,8 +38,8 @@ export default /* glsl */`
 
 		#ifdef DOUBLE_SIDED
 
-			tangent = tangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );
-			bitangent = bitangent * ( float( gl_FrontFacing ) * 2.0 - 1.0 );
+			tangent = tangent * ( float( isFrontFacing ) * 2.0 - 1.0 );
+			bitangent = bitangent * ( float( isFrontFacing ) * 2.0 - 1.0 );
 
 		#endif
 

+ 4 - 2
src/renderers/shaders/ShaderChunk/normal_fragment_maps.glsl.js

@@ -12,6 +12,8 @@ export default /* glsl */`
 
 	#ifdef DOUBLE_SIDED
 
+		// We can't compute isFrontFacing if the model doesn't have normals
+
 		normal = normal * ( float( gl_FrontFacing ) * 2.0 - 1.0 );
 
 	#endif
@@ -29,13 +31,13 @@ export default /* glsl */`
 
 	#else
 
-		normal = perturbNormal2Arb( -vViewPosition, normal, mapN );
+		normal = perturbNormal2Arb( -vViewPosition, normal, mapN, isFrontFacing );
 
 	#endif
 
 #elif defined( USE_BUMPMAP )
 
-	normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd() );
+	normal = perturbNormalArb( -vViewPosition, normal, dHdxy_fwd(), isFrontFacing );
 
 #endif
 `;

+ 2 - 2
src/renderers/shaders/ShaderChunk/normalmap_pars_fragment.glsl.js

@@ -17,7 +17,7 @@ export default /* glsl */`
 	// Per-Pixel Tangent Space Normal Mapping
 	// http://hacksoflife.blogspot.ch/2009/11/per-pixel-tangent-space-normal-mapping.html
 
-	vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN ) {
+	vec3 perturbNormal2Arb( vec3 eye_pos, vec3 surf_norm, vec3 mapN, bool isFrontFacing ) {
 
 		// Workaround for Adreno 3XX dFd*( vec3 ) bug. See #9988
 
@@ -34,7 +34,7 @@ export default /* glsl */`
 
 		mat3 tsn = mat3( S, T, N );
 
-		mapN.xy *= ( float( gl_FrontFacing ) * 2.0 - 1.0 );
+		mapN.xy *= ( float( isFrontFacing ) * 2.0 - 1.0 );
 
 		return normalize( tsn * mapN );