Remove the Offset for the Pixel Center + Rename

The pixel center is the same as hardware backends and there is no need for any offset of 1/12.

Also rename pixel center correction to pixel position correction for the rest of the usages.
This commit is contained in:
Patrick Ferry 2024-08-03 13:27:56 +01:00
parent 8a50676b83
commit 34db4f94ce
5 changed files with 18 additions and 47 deletions

View File

@ -86,7 +86,7 @@ struct alignas(16) VertexShaderConstants
std::array<float4, 64> transformmatrices;
std::array<float4, 32> normalmatrices;
std::array<float4, 64> posttransformmatrices;
float4 pixelcentercorrection;
float4 pixelpositioncorrection;
std::array<float, 2> viewport; // .xy
std::array<float, 2> pad2; // .zw

View File

@ -283,7 +283,7 @@ void WriteSwitch(ShaderCode& out, APIType ApiType, std::string_view variable,
#define I_TRANSFORMMATRICES "ctrmtx"
#define I_NORMALMATRICES "cnmtx"
#define I_POSTTRANSFORMMATRICES "cpostmtx"
#define I_PIXELCENTERCORRECTION "cpixelcenter"
#define I_PIXELPOSITIONCORRECTION "cpixelposition"
#define I_VIEWPORT_SIZE "cviewport"
#define I_CACHED_TANGENT "ctangent"
#define I_CACHED_BINORMAL "cbinormal"
@ -305,7 +305,7 @@ static const char s_shader_uniforms[] = "\tuint components;\n"
"\tfloat4 " I_TRANSFORMMATRICES "[64];\n"
"\tfloat4 " I_NORMALMATRICES "[32];\n"
"\tfloat4 " I_POSTTRANSFORMMATRICES "[64];\n"
"\tfloat4 " I_PIXELCENTERCORRECTION ";\n"
"\tfloat4 " I_PIXELPOSITIONCORRECTION ";\n"
"\tfloat2 " I_VIEWPORT_SIZE ";\n"
"\tuint4 xfmem_pack1[8];\n"
"\tfloat4 " I_CACHED_TANGENT ";\n"

View File

@ -438,8 +438,8 @@ float3 load_input_float3_rawtex(uint vtx_offset, uint attr_offset) {{
// 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");
out.Write("o.pos.z = o.pos.w * " I_PIXELPOSITIONCORRECTION ".w - "
"o.pos.z * " I_PIXELPOSITIONCORRECTION ".z;\n");
if (!host_config.backend_clip_control)
{
@ -451,15 +451,7 @@ float3 load_input_float3_rawtex(uint vtx_offset, uint attr_offset) {{
// Correct for negative viewports by mirroring all vertices. We need to negate the height here,
// since the viewport height is already negated by the render backend.
out.Write("o.pos.xy *= sign(" I_PIXELCENTERCORRECTION ".xy * float2(1.0, -1.0));\n");
// 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 - o.pos.w * " I_PIXELCENTERCORRECTION ".xy;\n");
out.Write("o.pos.xy *= sign(" I_PIXELPOSITIONCORRECTION ".xy * float2(1.0, -1.0));\n");
if (vertex_rounding)
{

View File

@ -624,8 +624,8 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho
// 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");
out.Write("o.pos.z = o.pos.w * " I_PIXELPOSITIONCORRECTION ".w - "
"o.pos.z * " I_PIXELPOSITIONCORRECTION ".z;\n");
if (!host_config.backend_clip_control)
{
@ -637,15 +637,7 @@ ShaderCode GenerateVertexShaderCode(APIType api_type, const ShaderHostConfig& ho
// Correct for negative viewports by mirroring all vertices. We need to negate the height here,
// since the viewport height is already negated by the render backend.
out.Write("o.pos.xy *= sign(" I_PIXELCENTERCORRECTION ".xy * float2(1.0, -1.0));\n");
// 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 - o.pos.w * " I_PIXELCENTERCORRECTION ".xy;\n");
out.Write("o.pos.xy *= sign(" I_PIXELPOSITIONCORRECTION ".xy * float2(1.0, -1.0));\n");
if (vertex_rounding)
{

View File

@ -335,27 +335,14 @@ void VertexShaderManager::SetConstants(const std::vector<std::string>& textures,
{
xf_state_manager.ResetViewportChange();
// 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 bool bUseVertexRounding = g_ActiveConfig.UseVertexRounding();
const float viewport_width = bUseVertexRounding ?
(2.f * xfmem.viewport.wd) :
g_framebuffer_manager->EFBToScaledXf(2.f * xfmem.viewport.wd);
const float viewport_height = bUseVertexRounding ?
(2.f * xfmem.viewport.ht) :
g_framebuffer_manager->EFBToScaledXf(2.f * xfmem.viewport.ht);
const float pixel_size_x = 2.f / viewport_width;
const float pixel_size_y = 2.f / viewport_height;
constants.pixelcentercorrection[0] = pixel_center_correction * pixel_size_x;
constants.pixelcentercorrection[1] = pixel_center_correction * pixel_size_y;
constants.pixelpositioncorrection[0] = xfmem.viewport.wd >= 0 ? 1.0f : -1.0f;
constants.pixelpositioncorrection[1] = xfmem.viewport.ht >= 0 ? 1.0f : -1.0f;
// By default we don't change the depth value at all in the vertex shader.
constants.pixelcentercorrection[2] = 1.0f;
constants.pixelcentercorrection[3] = 0.0f;
constants.pixelpositioncorrection[2] = 1.0f;
constants.pixelpositioncorrection[3] = 0.0f;
constants.viewport[0] = (2.f * xfmem.viewport.wd);
constants.viewport[1] = (2.f * xfmem.viewport.ht);
@ -368,19 +355,19 @@ void VertexShaderManager::SetConstants(const std::vector<std::string>& textures,
{
// Sometimes the console also tries to use the reversed-Z trick. We can only do
// that with the expected accuracy if the backend can reverse the depth range.
constants.pixelcentercorrection[2] = fabs(xfmem.viewport.zRange) / 16777215.0f;
constants.pixelpositioncorrection[2] = fabs(xfmem.viewport.zRange) / 16777215.0f;
if (xfmem.viewport.zRange < 0.0f)
constants.pixelcentercorrection[3] = xfmem.viewport.farZ / 16777215.0f;
constants.pixelpositioncorrection[3] = xfmem.viewport.farZ / 16777215.0f;
else
constants.pixelcentercorrection[3] = 1.0f - xfmem.viewport.farZ / 16777215.0f;
constants.pixelpositioncorrection[3] = 1.0f - xfmem.viewport.farZ / 16777215.0f;
}
else
{
// For backends that don't support reversing the depth range we can still render
// cases where the console uses the reversed-Z trick. But we simply can't provide
// the expected accuracy, which might result in z-fighting.
constants.pixelcentercorrection[2] = xfmem.viewport.zRange / 16777215.0f;
constants.pixelcentercorrection[3] = 1.0f - xfmem.viewport.farZ / 16777215.0f;
constants.pixelpositioncorrection[2] = xfmem.viewport.zRange / 16777215.0f;
constants.pixelpositioncorrection[3] = 1.0f - xfmem.viewport.farZ / 16777215.0f;
}
}