diff --git a/GPU/Common/GPUStateUtils.cpp b/GPU/Common/GPUStateUtils.cpp index 4cc1e9678f..09abb56ef9 100644 --- a/GPU/Common/GPUStateUtils.cpp +++ b/GPU/Common/GPUStateUtils.cpp @@ -515,6 +515,10 @@ float FromScaledDepth(float z) { return (z - offset) * depthSliceFactor * 65535.0f; } +float DepthSliceFactor() { + return depthSliceFactor; +} + void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out) { bool throughmode = gstate.isModeThrough(); out.dirtyProj = false; diff --git a/GPU/Common/GPUStateUtils.h b/GPU/Common/GPUStateUtils.h index 210573164b..0dba63b361 100644 --- a/GPU/Common/GPUStateUtils.h +++ b/GPU/Common/GPUStateUtils.h @@ -68,6 +68,7 @@ struct ViewportAndScissor { void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out); float ToScaledDepth(u16 z); float FromScaledDepth(float z); +float DepthSliceFactor(); // These are common to all modern APIs and can be easily converted with a lookup table. enum class BlendFactor : uint8_t { diff --git a/GPU/GLES/FragmentShaderGenerator.cpp b/GPU/GLES/FragmentShaderGenerator.cpp index 9da24000df..911a4d6c4e 100644 --- a/GPU/GLES/FragmentShaderGenerator.cpp +++ b/GPU/GLES/FragmentShaderGenerator.cpp @@ -676,8 +676,16 @@ bool GenerateFragmentShader(const ShaderID &id, char *buffer) { #endif if (gstate_c.Supports(GPU_ROUND_FRAGMENT_DEPTH_TO_16BIT)) { + const double scale = DepthSliceFactor() * 65535.0; + WRITE(p, " highp float z = gl_FragCoord.z;\n"); - WRITE(p, " z = (1.0/65535.0) * floor(z * 65535.0);\n"); + // We center the depth with an offset, but only its fraction matters. + // When (DepthSliceFactor() - 1) is odd, it will be 0.5, otherwise 0. + if (((int)(DepthSliceFactor() - 1.0f) & 1) == 1) { + WRITE(p, " z = (floor((z * %f) - (1.0 / 2.0)) + (1.0 / 2.0)) * (1.0 / %f);\n", scale, scale); + } else { + WRITE(p, " z = floor(z * %f) * (1.0 / %f);\n", scale, scale); + } WRITE(p, " gl_FragDepth = z;\n"); }