Skip to content

Commit

Permalink
nv2a: Fix pixel center offset problem
Browse files Browse the repository at this point in the history
This addresses the difference in pixel center between OpenGL and the DirectX 8
approach used by the hardware.

Note that the resultant behavior still does not fully match the hardware, where
screen-space pixel coordinates below (x + 0.5625) => x, but it is close enough
to fix issues with surface-target rendering.
  • Loading branch information
abaire committed Apr 27, 2022
1 parent 38d1036 commit 451f7d6
Show file tree
Hide file tree
Showing 4 changed files with 17 additions and 2 deletions.
7 changes: 7 additions & 0 deletions hw/xbox/nv2a/pgraph.c
Expand Up @@ -4074,6 +4074,13 @@ static void pgraph_shader_update_constants(PGRAPHState *pg,
glUniform2f(binding->clip_range_loc, zclip_min, zclip_max);
}

if (binding->gl_viewport_size_loc != -1) {
unsigned int vp_width = pg->surface_binding_dim.width,
vp_height = pg->surface_binding_dim.height;
pgraph_apply_scaling_factor(pg, &vp_width, &vp_height);
glUniform2f(binding->gl_viewport_size_loc, vp_width, vp_height);
}

/* Clipping regions */
for (i = 0; i < 8; i++) {
uint32_t x = pg->regs[NV_PGRAPH_WINDOWCLIPX0 + i * 4];
Expand Down
2 changes: 2 additions & 0 deletions hw/xbox/nv2a/shaders.c
Expand Up @@ -706,6 +706,7 @@ static MString *generate_vertex_shader(const ShaderState state,
"\n"
"uniform vec2 clipRange;\n"
"uniform vec2 surfaceSize;\n"
"uniform vec2 glViewportSize;\n"
"\n"
/* All constants in 1 array declaration */
"uniform vec4 c[" stringify(NV2A_VERTEXSHADER_CONSTANTS) "];\n"
Expand Down Expand Up @@ -1046,6 +1047,7 @@ ShaderBinding* generate_shaders(const ShaderState state)
snprintf(tmp, sizeof(tmp), "c[%d]", i);
ret->vsh_constant_loc[i] = glGetUniformLocation(program, tmp);
}
ret->gl_viewport_size_loc = glGetUniformLocation(program, "glViewportSize");
ret->surface_size_loc = glGetUniformLocation(program, "surfaceSize");
ret->clip_range_loc = glGetUniformLocation(program, "clipRange");
ret->fog_color_loc = glGetUniformLocation(program, "fogColor");
Expand Down
1 change: 1 addition & 0 deletions hw/xbox/nv2a/shaders.h
Expand Up @@ -111,6 +111,7 @@ typedef struct ShaderBinding {
GLint bump_offset_loc[NV2A_MAX_TEXTURES];
GLint tex_scale_loc[NV2A_MAX_TEXTURES];

GLint gl_viewport_size_loc;
GLint surface_size_loc;
GLint clip_range_loc;

Expand Down
9 changes: 7 additions & 2 deletions hw/xbox/nv2a/vsh.c
Expand Up @@ -839,14 +839,14 @@ 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"
);
if (z_perspective) {
mstring_append(body, " oPos.z = oPos.w;\n");
}

mstring_append(body,
/* Map the clip range into clip space so z is clipped correctly.
* Note this makes the values in the depth buffer wrong. This should be
Expand All @@ -869,5 +869,10 @@ void vsh_translate(uint16_t version,
" }\n"
);

/* Fix up the pixel-center difference between OpenGL and DirectX 8
* TODO: This still does not entirely match HW behavior.
* Pixels should be floored below 0.5 + 1/16 = 0.5625
*/
mstring_append(body,
" oPos.xy += (vec2(-1.0f, 1.0f) / glViewportSize.xy) * oPos.w;\n");
}

0 comments on commit 451f7d6

Please sign in to comment.