From fb7edb931589dc63cef94226ba617d7b55293e00 Mon Sep 17 00:00:00 2001 From: Olli Etuaho Date: Tue, 18 Feb 2020 21:59:54 +0200 Subject: [PATCH] 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. --- src/renderers/shaders/ShaderLib/depth_frag.glsl.js | 9 +++++++-- src/renderers/shaders/ShaderLib/depth_vert.glsl.js | 7 +++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/renderers/shaders/ShaderLib/depth_frag.glsl.js b/src/renderers/shaders/ShaderLib/depth_frag.glsl.js index c1a75b1caf9c8a..bfaf55cdd32074 100644 --- a/src/renderers/shaders/ShaderLib/depth_frag.glsl.js +++ b/src/renderers/shaders/ShaderLib/depth_frag.glsl.js @@ -13,6 +13,8 @@ export default /* glsl */` #include #include +varying vec2 vHighPrecisionZW; + void main() { #include @@ -31,13 +33,16 @@ void main() { #include + // 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 diff --git a/src/renderers/shaders/ShaderLib/depth_vert.glsl.js b/src/renderers/shaders/ShaderLib/depth_vert.glsl.js index 4705257b0601cf..5bc70299875dba 100644 --- a/src/renderers/shaders/ShaderLib/depth_vert.glsl.js +++ b/src/renderers/shaders/ShaderLib/depth_vert.glsl.js @@ -7,6 +7,11 @@ export default /* glsl */` #include #include +// 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 @@ -29,5 +34,7 @@ void main() { #include #include + vHighPrecisionZW = gl_Position.zw; + } `;