From 27b8f719ca7f26e1edbec6f7e46cc612dce12b41 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Wed, 10 Sep 2008 11:08:10 +0200 Subject: [PATCH] wined3d: Fix the half pixel offset. Turns out the original fix was correct for fixed function, but for the wrong reason. The shader path was already correct. This fixes a regresssion introduced by 932e95c111118b643650d6643e47be0ddb5528a1. --- dlls/wined3d/state.c | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c index 61ccab66d5c..358ad141d8b 100644 --- a/dlls/wined3d/state.c +++ b/dlls/wined3d/state.c @@ -3905,16 +3905,6 @@ static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock divide by the Width/Height, so we need the half range(1.0) to translate by half a pixel. - Note that when rendering offscreen, we need to translate 1 pixel - (2/h in normalized device coordinates) down after doing the flip, - because of the way the viewport transformation works in OpenGL: - (-1,1) in normalized device coordinates corresponds to the upper - left corner of the upper left pixel in the viewport. (-1,-1) - corresponds to lower left corner of the lower left pixel in the - viewport. In other words, the upper left corner of the pixel - *below* the lower left pixel in the viewport. See also section - 2.11.1 "Controlling the Viewport" of the GL 2.1 spec. - The other fun is that d3d's output z range after the transformation is [0;1], but opengl's is [-1;1]. Since the z buffer is in range [0;1] for both, gl scales [-1;1] to [0;1]. This would mean that we end up in [0.5;1] and loose a lot @@ -3922,6 +3912,24 @@ static void transform_projection(DWORD state, IWineD3DStateBlockImpl *stateblock [0;1] to [-1;1], so when gl undoes that we utilize the full z range */ + /* + * Careful with the order of operations here, we're essentially working backwards: + * x = x + 1/w; + * y = (y - 1/h) * flip; + * z = z * 2 - 1; + * + * Becomes: + * glTranslatef(0.0, 0.0, -1.0); + * glScalef(1.0, 1.0, 2.0); + * + * glScalef(1.0, flip, 1.0); + * glTranslatef(1/w, -1/h, 0.0); + * + * This is equivalent to: + * glTranslatef(1/w, -flip/h, -1.0) + * glScalef(1.0, flip, 2.0); + */ + if (stateblock->wineD3DDevice->render_offscreen) { /* D3D texture coordinates are flipped compared to OpenGL ones, so * render everything upside down when rendering offscreen. */ @@ -4517,7 +4525,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W */ if (useVertexShaderFunction) { device->posFixup[1] = device->render_offscreen ? -1.0 : 1.0; - device->posFixup[3] = -1.0 / stateblock->viewport.Height; + device->posFixup[3] = -device->posFixup[1] / stateblock->viewport.Height; } } @@ -4649,7 +4657,7 @@ static void viewport_miscpart(DWORD state, IWineD3DStateBlockImpl *stateblock, W static void viewport_vertexpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContext *context) { stateblock->wineD3DDevice->posFixup[2] = 1.0 / stateblock->viewport.Width; - stateblock->wineD3DDevice->posFixup[3] = -1.0 / stateblock->viewport.Height; + stateblock->wineD3DDevice->posFixup[3] = -stateblock->wineD3DDevice->posFixup[1] / stateblock->viewport.Height; if(!isStateDirty(context, STATE_TRANSFORM(WINED3DTS_PROJECTION))) { transform_projection(STATE_TRANSFORM(WINED3DTS_PROJECTION), stateblock, context); } -- 2.11.4.GIT