diff --git a/hw/xbox/nv2a/shaders.c b/hw/xbox/nv2a/shaders.c index cafe326e93e..8d2e5125ccd 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,27 @@ 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" + " 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 / %d);\n" + "}\n", + scale); + MString *body = mstring_from_str("void main() {\n"); for (i = 0; i < NV2A_VERTEXSHADER_ATTRIBUTES; i++) { @@ -985,12 +1008,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");