Explorar el Código

MeshDepthMaterial: Compute depth manually rather than using gl_FragCoord.z

Some platforms compute gl_FragCoord at a lower precision which makes the manually computed value better for depth-based postprocessing effects.

The shader precisions that implementations report through the getShaderPrecisionFormat API are not reliable in practice, so the manually computed value is always used rather than trying to enable it conditionally on those platforms which have various shader precisions.

WebGL 2.0 should in principle compute gl_FragCoord at a higher precision, but this may also be affected by driver bugs on some platforms.

Improvement from this patch can be seen for example on iPad with A10 processor / iPadOS 13.3.1, when using depth based postprocessing effects on a scene with a high far/near plane ratio.
Olli Etuaho hace 5 años
padre
commit
fb7edb9315

+ 7 - 2
src/renderers/shaders/ShaderLib/depth_frag.glsl.js

@@ -13,6 +13,8 @@ export default /* glsl */`
 #include <logdepthbuf_pars_fragment>
 #include <clipping_planes_pars_fragment>
 
+varying vec2 vHighPrecisionZW;
+
 void main() {
 
 	#include <clipping_planes_fragment>
@@ -31,13 +33,16 @@ void main() {
 
 	#include <logdepthbuf_fragment>
 
+	// Higher precision equivalent of gl_FragCoord.z. This assumes depthRange has been left to its default values.
+	float fragCoordZ = 0.5 * vHighPrecisionZW[0] / vHighPrecisionZW[1] + 0.5;
+
 	#if DEPTH_PACKING == 3200
 
-		gl_FragColor = vec4( vec3( 1.0 - gl_FragCoord.z ), opacity );
+		gl_FragColor = vec4( vec3( 1.0 - fragCoordZ ), opacity );
 
 	#elif DEPTH_PACKING == 3201
 
-		gl_FragColor = packDepthToRGBA( gl_FragCoord.z );
+		gl_FragColor = packDepthToRGBA( fragCoordZ );
 
 	#endif
 

+ 7 - 0
src/renderers/shaders/ShaderLib/depth_vert.glsl.js

@@ -7,6 +7,11 @@ export default /* glsl */`
 #include <logdepthbuf_pars_vertex>
 #include <clipping_planes_pars_vertex>
 
+// This is used for computing an equivalent of gl_FragCoord.z that is as high precision as possible.
+// Some platforms compute gl_FragCoord at a lower precision which makes the manually computed value better for
+// depth-based postprocessing effects. Reproduced on iPad with A10 processor / iPadOS 13.3.1.
+varying vec2 vHighPrecisionZW;
+
 void main() {
 
 	#include <uv_vertex>
@@ -29,5 +34,7 @@ void main() {
 	#include <logdepthbuf_vertex>
 	#include <clipping_planes_vertex>
 
+	vHighPrecisionZW = gl_Position.zw;
+
 }
 `;