diff options
Diffstat (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp')
| -rw-r--r-- | Source/Core/VideoCommon/VertexShaderGen.cpp | 56 |
1 files changed, 38 insertions, 18 deletions
diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index aa69550bd8..a42f090716 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -399,28 +399,43 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da out.Write("o.colors_1 = color1;\n"); } - // write the true depth value, if the game uses depth textures pixel shaders will override with - // the correct values - // if not early z culling will improve speed - if (g_ActiveConfig.backend_info.bSupportsClipControl) + // Write the true depth value. If the game uses depth textures, then the pixel shader will + // override it with the correct values if not then early z culling will improve speed. + if (g_ActiveConfig.backend_info.bSupportsDepthClamp) { + // If we can disable the incorrect depth clipping planes using depth clamping, then we can do + // our own depth clipping and calculate the depth range before the perspective divide. + + // Since we're adjusting z for the depth range before the perspective divide, we have to do our + // own clipping. We want to clip so that -w <= z <= 0, which matches the console -1..0 range. + out.Write("o.clipDist0 = o.pos.z + o.pos.w;\n"); // Near: z < -w + out.Write("o.clipDist1 = -o.pos.z;\n"); // Far: z > 0 + + // Adjust z for the depth range. We're using an equation which incorperates a depth inversion, + // so we can map the console -1..0 range to the 0..1 range used in the depth buffer. + // We have to handle the depth range in the vertex shader instead of after the perspective + // divide, because some games will use a depth range larger than what is allowed by the + // graphics API. These large depth ranges will still be clipped to the 0..1 range, so these + // games effectively add a depth bias to the values written to the depth buffer. + out.Write("o.pos.z = o.pos.w * " I_PIXELCENTERCORRECTION ".w - " + "o.pos.z * " I_PIXELCENTERCORRECTION ".z;\n"); + } + else + { + // If we can't disable the incorrect depth clipping planes, then we need to rely on the + // graphics API to handle the depth range after the perspective divide. This can result in + // inaccurate depth values due to the missing depth bias, but that can be least corrected by + // overriding depth values in the pixel shader. We still need to take care of the reversed depth + // though, so we do that here. out.Write("o.pos.z = -o.pos.z;\n"); } - else // OGL + + if (!g_ActiveConfig.backend_info.bSupportsClipControl) { - // this results in a scale from -1..0 to -1..1 after perspective - // divide - out.Write("o.pos.z = o.pos.z * -2.0 - o.pos.w;\n"); - - // the next steps of the OGL pipeline are: - // (x_c,y_c,z_c,w_c) = o.pos //switch to OGL spec terminology - // clipping to -w_c <= (x_c,y_c,z_c) <= w_c - // (x_d,y_d,z_d) = (x_c,y_c,z_c)/w_c//perspective divide - // z_w = (f-n)/2*z_d + (n+f)/2 - // z_w now contains the value to go to the 0..1 depth buffer - - // trying to get the correct semantic while not using glDepthRange - // seems to get rather complicated + // If the graphics API doesn't support a depth range of 0..1, then we need to map z to + // the -1..1 range. Unfortunately we have to use a substraction, which is a lossy floating-point + // operation that can introduce a round-trip error. + out.Write("o.pos.z = o.pos.z * 2.0 - o.pos.w;\n"); } // The console GPU places the pixel center at 7/12 in screen space unless @@ -453,6 +468,11 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da out.Write("colors_1 = o.colors_1;\n"); } + if (g_ActiveConfig.backend_info.bSupportsDepthClamp) + { + out.Write("gl_ClipDistance[0] = o.clipDist0;\n"); + out.Write("gl_ClipDistance[1] = o.clipDist1;\n"); + } out.Write("gl_Position = o.pos;\n"); } else // D3D |
