From 5ce8573624a7fb3dad246f451e0e2b1c811ae07e Mon Sep 17 00:00:00 2001 From: antangelo Date: Sat, 21 Jan 2023 17:16:52 -0500 Subject: [PATCH 1/2] nv2a: Offset vertices to match HW rounding Co-authored-by: Erik Abair --- hw/xbox/nv2a/shaders.c | 26 +++++++++++++++++++++++--- hw/xbox/nv2a/vsh.c | 5 ++--- 2 files changed, 25 insertions(+), 6 deletions(-) diff --git a/hw/xbox/nv2a/shaders.c b/hw/xbox/nv2a/shaders.c index cafe326e93e..a14978046a1 100644 --- a/hw/xbox/nv2a/shaders.c +++ b/hw/xbox/nv2a/shaders.c @@ -753,7 +753,9 @@ GLSL_DEFINE(materialEmissionColor, GLSL_LTCTXA(NV_IGRAPH_XF_LTCTXA_CM_COL) ".xyz } mstring_append(body, - " oPos = invViewport * (tPosition * compositeMat);\n" + " oPos = tPosition * compositeMat;\n" + " oPos.xy = adjust_pixel_center(oPos.xy, oPos.w);\n" + " oPos = invViewport * oPos;\n" " oPos.z = oPos.z * 2.0 - oPos.w;\n"); /* FIXME: Testing */ @@ -857,6 +859,26 @@ GLSL_DEFINE(texMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T3MAT)) } mstring_append(header, "\n"); + mstring_append_fmt(header, "\n" + "vec2 adjust_pixel_center(vec2 screen_pos, float w) {\n" + " if (w == 0.0 || isinf(w)) {\n" + " w = 1.0;\n" + " }\n" + + " screen_pos /= w;\n" + " vec2 pixel = floor(screen_pos);\n" + " vec2 subpixel = screen_pos - pixel;\n" + " vec2 round_down = vec2(lessThan(subpixel, vec2(0.5625)));\n" + + " subpixel -= vec2(0.0625);\n" + + " vec2 bias = vec2(0.002);\n" + " subpixel += mix(bias, -bias, round_down);\n" + + " return w * (pixel + subpixel);\n" + "}\n" + ); + MString *body = mstring_from_str("void main() {\n"); for (i = 0; i < NV2A_VERTEXSHADER_ATTRIBUTES; i++) { @@ -985,12 +1007,10 @@ GLSL_DEFINE(texMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T3MAT)) shade_model_mult, shade_model_mult); - /* Return combined header + source */ mstring_append(header, mstring_get_str(body)); mstring_unref(body); return header; - } static GLuint create_gl_shader(GLenum gl_shader_type, diff --git a/hw/xbox/nv2a/vsh.c b/hw/xbox/nv2a/vsh.c index 0e4cf314bc2..4faeee0105f 100644 --- a/hw/xbox/nv2a/vsh.c +++ b/hw/xbox/nv2a/vsh.c @@ -840,10 +840,9 @@ void vsh_translate(uint16_t version, mstring_append(body, /* the shaders leave the result in screen space, while * opengl expects it in clip space. - * TODO: the pixel-center co-ordinate differences should handled */ - " oPos.x = 2.0 * (oPos.x - surfaceSize.x * 0.5) / surfaceSize.x;\n" - " oPos.y = -2.0 * (oPos.y - surfaceSize.y * 0.5) / surfaceSize.y;\n" + " oPos.xy = 2.0 * adjust_pixel_center(oPos.xy, 1.0) / surfaceSize - vec2(1.0);\n" + " oPos.y *= -1;\n" ); if (z_perspective) { mstring_append(body, " oPos.z = oPos.w;\n"); From 23a70fcd47f85a57bb823cbf23eaa847a6e33a11 Mon Sep 17 00:00:00 2001 From: polymetal0 Date: Sat, 3 Aug 2024 02:39:07 +0200 Subject: [PATCH 2/2] Fix for all scale factors Since screen_pos (and therefore also pixel) are multiplied by the scale factor but the correct subpixel offset is always the same, it was fair to assume that the final subpixel value had to be divided by the scale factor for it to be corrected. Tested on pgraph tests, Fable: TLC and Halo: CE (weapon zoom in). --- hw/xbox/nv2a/shaders.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/hw/xbox/nv2a/shaders.c b/hw/xbox/nv2a/shaders.c index a14978046a1..8d2e5125ccd 100644 --- a/hw/xbox/nv2a/shaders.c +++ b/hw/xbox/nv2a/shaders.c @@ -859,6 +859,7 @@ GLSL_DEFINE(texMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T3MAT)) } mstring_append(header, "\n"); + unsigned int scale = state->surface_scale_factor; mstring_append_fmt(header, "\n" "vec2 adjust_pixel_center(vec2 screen_pos, float w) {\n" " if (w == 0.0 || isinf(w)) {\n" @@ -875,9 +876,9 @@ GLSL_DEFINE(texMat3, GLSL_C_MAT4(NV_IGRAPH_XF_XFCTX_T3MAT)) " vec2 bias = vec2(0.002);\n" " subpixel += mix(bias, -bias, round_down);\n" - " return w * (pixel + subpixel);\n" - "}\n" - ); + " return w * (pixel + subpixel / %d);\n" + "}\n", + scale); MString *body = mstring_from_str("void main() {\n");