From c47c32d4a808218866a9e0a744b0cfa37d6ec9cb Mon Sep 17 00:00:00 2001 From: Tony Wasserka Date: Wed, 23 Apr 2014 23:42:28 +0200 Subject: [PATCH] VertexShaderGen: Correct vertex shader output to consider shifted pixel centers. Fixes issue 267. --- Source/Core/VideoCommon/VertexShaderGen.cpp | 8 ++++++++ Source/Core/VideoCommon/VertexShaderManager.cpp | 11 +++++++++++ 2 files changed, 19 insertions(+) diff --git a/Source/Core/VideoCommon/VertexShaderGen.cpp b/Source/Core/VideoCommon/VertexShaderGen.cpp index 239a2945a3..7d0dc878cd 100644 --- a/Source/Core/VideoCommon/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/VertexShaderGen.cpp @@ -419,6 +419,14 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ //seems to get rather complicated } + // The console GPU places the pixel center at 7/12 in screen space unless + // antialiasing is enabled, while D3D and OpenGL place it at 0.5. This results + // in some primitives being placed one pixel too far to the bottom-right, + // which in turn can be critical if it happens for clear quads. + // Hence, we compensate for this pixel center difference so that primitives + // get rasterized correctly. + out.Write("o.pos.xy = o.pos.xy - " I_DEPTHPARAMS".zw;\n"); + if (api_type == API_OPENGL) { // Bit ugly here diff --git a/Source/Core/VideoCommon/VertexShaderManager.cpp b/Source/Core/VideoCommon/VertexShaderManager.cpp index f0e4be9040..b26ee5ccf9 100644 --- a/Source/Core/VideoCommon/VertexShaderManager.cpp +++ b/Source/Core/VideoCommon/VertexShaderManager.cpp @@ -360,6 +360,17 @@ void VertexShaderManager::SetConstants() bViewportChanged = false; constants.depthparams[0] = xfregs.viewport.farZ / 16777216.0f; constants.depthparams[1] = xfregs.viewport.zRange / 16777216.0f; + + // The console GPU places the pixel center at 7/12 unless antialiasing + // is enabled, while D3D and OpenGL place it at 0.5. See the comment + // in VertexShaderGen.cpp for details. + // NOTE: If we ever emulate antialiasing, the sample locations set by + // BP registers 0x01-0x04 need to be considered here. + const float pixel_center_correction = 7.0f / 12.0f - 0.5f; + const float pixel_size_x = 2.f / Renderer::EFBToScaledXf(2.f * xfregs.viewport.wd); + const float pixel_size_y = 2.f / Renderer::EFBToScaledXf(2.f * xfregs.viewport.ht); + constants.depthparams[2] = pixel_center_correction * pixel_size_x; + constants.depthparams[3] = pixel_center_correction * pixel_size_y; dirty = true; // This is so implementation-dependent that we can't have it here. g_renderer->SetViewport();