From c223bd47b9b2a83ed53201964e4912e2faec3d66 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 3 Aug 2016 02:01:36 +0200 Subject: VideoCommon: Implement depth range equation in vertex shader. --- Source/Core/VideoCommon/VertexShaderGen.cpp | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index aa69550bd8..e23be6590c 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -399,14 +399,14 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da out.Write("o.colors_1 = color1;\n"); } + // We have to handle the depth range in the vertex shader, because some games will use a depth range beyond + // the normal depth range of 0..1. + out.Write("o.pos.z = o.pos.w * " I_PIXELCENTERCORRECTION".w + o.pos.z * " I_PIXELCENTERCORRECTION".z;\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) - { - 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 -- cgit v1.2.3 From 159247f4ad51e6b8dc911357ebe8d6327ebd5a37 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Thu, 4 Aug 2016 18:27:12 +0200 Subject: VertexShaderGen: Clamp to the console depth range. This fixes the Mii Channel among others. --- Source/Core/VideoCommon/VertexShaderGen.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index e23be6590c..0863e9f17f 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -403,6 +403,10 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da // the normal depth range of 0..1. out.Write("o.pos.z = o.pos.w * " I_PIXELCENTERCORRECTION".w + o.pos.z * " I_PIXELCENTERCORRECTION".z;\n"); + // We have to clamp to 2^24 - 1 here, because we map our depth range to 0..2^24 to prevent round-trip errors. + // Thus we test for values that will result in 2^24 or higher after the perspective divide. + out.Write("if (o.pos.z / o.pos.w >= 1.0) o.pos.z = 16777215.0 / 16777216.0 * o.pos.w;\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 -- cgit v1.2.3 From b1ed7e80fb689da5a4679e5c178f91391e55a6ff Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Thu, 4 Aug 2016 14:09:35 +0200 Subject: VertexShaderGen: Clip z using user-defined clipping planes. --- Source/Core/VideoCommon/VertexShaderGen.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 0863e9f17f..abb79d90fc 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -399,6 +399,10 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da out.Write("o.colors_1 = color1;\n"); } + // Since we're adjusting z for the depth range before the perspective divide, we have to do our + // own clipping. + out.Write("o.clipDist = o.pos.z + o.pos.w;\n"); + // We have to handle the depth range in the vertex shader, because some games will use a depth range beyond // the normal depth range of 0..1. out.Write("o.pos.z = o.pos.w * " I_PIXELCENTERCORRECTION".w + o.pos.z * " I_PIXELCENTERCORRECTION".z;\n"); @@ -457,6 +461,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da out.Write("colors_1 = o.colors_1;\n"); } + out.Write("gl_ClipDistance[0] = o.clipDist;\n"); out.Write("gl_Position = o.pos;\n"); } else // D3D -- cgit v1.2.3 From e9e81ece6538c6676054dbc0e9d156fcc59801c9 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Wed, 3 Aug 2016 21:54:22 +0200 Subject: VideoBackends: Enable depth clamping. --- Source/Core/VideoCommon/VertexShaderGen.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index abb79d90fc..518c75244c 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -407,10 +407,6 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da // the normal depth range of 0..1. out.Write("o.pos.z = o.pos.w * " I_PIXELCENTERCORRECTION".w + o.pos.z * " I_PIXELCENTERCORRECTION".z;\n"); - // We have to clamp to 2^24 - 1 here, because we map our depth range to 0..2^24 to prevent round-trip errors. - // Thus we test for values that will result in 2^24 or higher after the perspective divide. - out.Write("if (o.pos.z / o.pos.w >= 1.0) o.pos.z = 16777215.0 / 16777216.0 * o.pos.w;\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 -- cgit v1.2.3 From 4582853af48f67047e57b997bf923488bf444931 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Sat, 6 Aug 2016 03:40:45 +0200 Subject: VertexShaderGen: Use reversed depth range. --- Source/Core/VideoCommon/VertexShaderGen.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 518c75244c..9110cbfe99 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -405,7 +405,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da // We have to handle the depth range in the vertex shader, because some games will use a depth range beyond // the normal depth range of 0..1. - out.Write("o.pos.z = o.pos.w * " I_PIXELCENTERCORRECTION".w + o.pos.z * " I_PIXELCENTERCORRECTION".z;\n"); + out.Write("o.pos.z = o.pos.w * " I_PIXELCENTERCORRECTION".w - o.pos.z * " I_PIXELCENTERCORRECTION".z;\n"); // write the true depth value, if the game uses depth textures pixel shaders will override with // the correct values @@ -414,7 +414,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da { // 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"); + 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 -- cgit v1.2.3 From a141e91dd226885fc767d009938ca61a22f86558 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 5 Aug 2016 22:31:34 +0200 Subject: OGL: Check for GL_DEPTH_CLAMP support. It's not available in OpenGL ES and officially it's not supported on OpenGL 3.0/3.1. Fallback to old depth range code if there is no method to disable depth clipping. It's more important to have correct clipping than to have accurate depth values. Inaccurate depth values can be fixed by slow depth. --- Source/Core/VideoCommon/VertexShaderGen.cpp | 24 +++++++++++++++++------- 1 file changed, 17 insertions(+), 7 deletions(-) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 9110cbfe99..85359ac6ee 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -399,13 +399,22 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da out.Write("o.colors_1 = color1;\n"); } - // Since we're adjusting z for the depth range before the perspective divide, we have to do our - // own clipping. - out.Write("o.clipDist = o.pos.z + o.pos.w;\n"); + if (g_ActiveConfig.backend_info.bSupportsDepthClamp) + { + // Since we're adjusting z for the depth range before the perspective divide, we have to do our + // own clipping. + out.Write("o.clipDist = o.pos.z + o.pos.w;\n"); - // We have to handle the depth range in the vertex shader, because some games will use a depth range beyond - // the normal depth range of 0..1. - out.Write("o.pos.z = o.pos.w * " I_PIXELCENTERCORRECTION".w - o.pos.z * " I_PIXELCENTERCORRECTION".z;\n"); + // We have to handle the depth range in the vertex shader, because some games will use a depth range beyond + // the normal depth range of 0..1. + out.Write("o.pos.z = o.pos.w * " I_PIXELCENTERCORRECTION".w - o.pos.z * " I_PIXELCENTERCORRECTION".z;\n"); + } + else + { + // User-defined clipping is not supported, thus we rely on the API to handle the depth range for us. + // We still need to take care of the reversed depth, so we do that here. + out.Write("o.pos.z = -o.pos.z;\n"); + } // write the true depth value, if the game uses depth textures pixel shaders will override with // the correct values @@ -457,7 +466,8 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da out.Write("colors_1 = o.colors_1;\n"); } - out.Write("gl_ClipDistance[0] = o.clipDist;\n"); + if (g_ActiveConfig.backend_info.bSupportsDepthClamp) + out.Write("gl_ClipDistance[0] = o.clipDist;\n"); out.Write("gl_Position = o.pos;\n"); } else // D3D -- cgit v1.2.3 From 94927f360feb1989a7b63ec4d583f45a5767aa3b Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 12 Aug 2016 15:06:26 +0200 Subject: VideoCommon: Add a user-defined far clipping plane. --- Source/Core/VideoCommon/VertexShaderGen.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 85359ac6ee..5d0f838843 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -403,7 +403,8 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da { // Since we're adjusting z for the depth range before the perspective divide, we have to do our // own clipping. - out.Write("o.clipDist = o.pos.z + o.pos.w;\n"); + out.Write("o.clipDist0 = o.pos.z + o.pos.w;\n"); + out.Write("o.clipDist1 = o.pos.w * -o.pos.z;\n"); // We have to handle the depth range in the vertex shader, because some games will use a depth range beyond // the normal depth range of 0..1. @@ -467,7 +468,10 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da } if (g_ActiveConfig.backend_info.bSupportsDepthClamp) - out.Write("gl_ClipDistance[0] = o.clipDist;\n"); + { + 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 -- cgit v1.2.3 From 959d1879e578c1f29e8c95be445fa349b572191d Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 15 Aug 2016 13:07:56 +0200 Subject: VertexShaderGen: Fix far clipping. We should only check whether z > 0, we don't care about w. --- Source/Core/VideoCommon/VertexShaderGen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 5d0f838843..42bd9da319 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -402,9 +402,9 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da if (g_ActiveConfig.backend_info.bSupportsDepthClamp) { // Since we're adjusting z for the depth range before the perspective divide, we have to do our - // own clipping. - out.Write("o.clipDist0 = o.pos.z + o.pos.w;\n"); - out.Write("o.clipDist1 = o.pos.w * -o.pos.z;\n"); + // own clipping. We want to clip so that -w <= z <= 0. + 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 // We have to handle the depth range in the vertex shader, because some games will use a depth range beyond // the normal depth range of 0..1. -- cgit v1.2.3 From 8c1c7fc2da65eea1a8244ce196d94313f7fdfb1b Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Fri, 12 Aug 2016 13:55:35 +0200 Subject: Cosmetics. --- Source/Core/VideoCommon/VertexShaderGen.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 42bd9da319..4603e22d7e 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -406,13 +406,14 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const vertex_shader_uid_da 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 - // We have to handle the depth range in the vertex shader, because some games will use a depth range beyond - // the normal depth range of 0..1. - out.Write("o.pos.z = o.pos.w * " I_PIXELCENTERCORRECTION".w - o.pos.z * " I_PIXELCENTERCORRECTION".z;\n"); + // We have to handle the depth range in the vertex shader, because some games will use a depth + // range beyond the normal depth range of 0..1. + out.Write("o.pos.z = o.pos.w * " I_PIXELCENTERCORRECTION ".w - " + "o.pos.z * " I_PIXELCENTERCORRECTION ".z;\n"); } else { - // User-defined clipping is not supported, thus we rely on the API to handle the depth range for us. + // User-defined clipping is not supported, thus we rely on the API to handle the depth range. // We still need to take care of the reversed depth, so we do that here. out.Write("o.pos.z = -o.pos.z;\n"); } -- cgit v1.2.3 From 7078216b61777ff89350d1bdc66c7c032b0b2296 Mon Sep 17 00:00:00 2001 From: Jules Blok Date: Mon, 15 Aug 2016 15:25:50 +0200 Subject: Improve documentation. --- Source/Core/VideoCommon/VertexShaderGen.cpp | 40 ++++++++++++++--------------- 1 file changed, 20 insertions(+), 20 deletions(-) (limited to 'Source/Core/VideoCommon/VertexShaderGen.cpp') diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 4603e22d7e..a42f090716 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -399,43 +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, 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. + // 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 - // We have to handle the depth range in the vertex shader, because some games will use a depth - // range beyond the normal depth range of 0..1. + // 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 { - // User-defined clipping is not supported, thus we rely on the API to handle the depth range. - // We still need to take care of the reversed depth, so we do that here. + // 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"); } - // 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) { - // this results in a scale from -1..0 to -1..1 after perspective - // divide + // 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 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 } // The console GPU places the pixel center at 7/12 in screen space unless -- cgit v1.2.3