From: Stefan Dösinger Subject: [PATCH 1/5] wined3d: Vertex fog uses the absolute eye position z (v2). Message-Id: <1417025335-31649-1-git-send-email-stefan@codeweavers.com> Date: Wed, 26 Nov 2014 19:08:51 +0100 Version 2: Set ZENABLE to D3DZB_FALSE instead of FALSE. This series supersedes 107863-107867. This is written from scratch, but inspired by the patch from Joachim Priesner. The included test tests the absolute minimum necessary to show that the abs() needs to be placed in the fixed function vertex pipeline replacement shader. It ignores vertex and pixel shader behavior. Tests for table fog will be added in patch 4. --- dlls/d3d8/tests/visual.c | 106 +++++++++++++++++++++++++++++++++++++++++++++ dlls/d3d9/tests/visual.c | 106 +++++++++++++++++++++++++++++++++++++++++++++ dlls/ddraw/tests/ddraw7.c | 102 +++++++++++++++++++++++++++++++++++++++++++ dlls/wined3d/glsl_shader.c | 6 +++ 4 files changed, 320 insertions(+) diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c index cbede9d..7c6200e 100644 --- a/dlls/d3d8/tests/visual.c +++ b/dlls/d3d8/tests/visual.c @@ -5361,6 +5361,111 @@ static void fog_interpolation_test(void) DestroyWindow(window); } +static void negative_fixedfunction_fog_test(void) +{ + HRESULT hr; + IDirect3DDevice8 *device; + IDirect3D8 *d3d; + ULONG refcount; + HWND window; + D3DCOLOR color; + static const struct + { + struct vec3 position; + D3DCOLOR diffuse; + } + quad[] = + { + {{-1.0f, -1.0f, -0.5f}, 0xffff0000}, + {{-1.0f, 1.0f, -0.5f}, 0xffff0000}, + {{ 1.0f, -1.0f, -0.5f}, 0xffff0000}, + {{ 1.0f, 1.0f, -0.5f}, 0xffff0000}, + }; + union + { + DWORD d; + float f; + } conv; + unsigned int i; + static const struct + { + float start, end; + DWORD color; + } + tests[] = + { + /* fog_interpolation_test shows that vertex fog evaluates the fog + * equation in the vertex pipeline. Start = -1.0 && end = 0.0 shows + * that the abs happens before the fog equation is evaluated. */ + { 0.0f, 1.0f, 0x00808000}, + {-1.0f, 0.0f, 0x0000ff00}, + }; + static const D3DMATRIX proj_mat = + {{{ + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }}}; + + window = CreateWindowA("static", "d3d8_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, 0, 640, 480, NULL, NULL, NULL, NULL); + d3d = Direct3DCreate8(D3D_SDK_VERSION); + ok(!!d3d, "Failed to create a D3D object.\n"); + + if (!(device = create_device(d3d, window, window, TRUE))) + { + skip("Failed to create a D3D device, skipping tests.\n"); + IDirect3D8_Release(d3d); + DestroyWindow(window); + return; + } + + hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE); + ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGENABLE, TRUE); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGCOLOR, 0x0000ff00); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetTransform(device, D3DTS_PROJECTION, &proj_mat); + ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr); + + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) + { + hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0); + ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr); + + conv.f = tests[i].start; + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGSTART, conv.d); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + conv.f = tests[i].end; + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGEND, conv.d); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice8_BeginScene(device); + ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr); + hr = IDirect3DDevice8_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad)); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + hr = IDirect3DDevice8_EndScene(device); + ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr); + + color = getPixelColor(device, 320, 240); + ok(color_match(color, tests[i].color, 2), "Got unexpected color 0x%08x, case %u.\n", color, i); + hr = IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL); + ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); + } + + refcount = IDirect3DDevice8_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + IDirect3D8_Release(d3d); + DestroyWindow(window); +} + START_TEST(visual) { D3DADAPTER_IDENTIFIER8 identifier; @@ -5412,4 +5517,5 @@ START_TEST(visual) add_dirty_rect_test(); test_3dc_formats(); fog_interpolation_test(); + negative_fixedfunction_fog_test(); } diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index fbab386..069fec1 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -16964,6 +16964,111 @@ static void fog_interpolation_test(void) DestroyWindow(window); } +static void negative_fixedfunction_fog_test(void) +{ + HRESULT hr; + IDirect3DDevice9 *device; + IDirect3D9 *d3d; + ULONG refcount; + HWND window; + D3DCOLOR color; + static const struct + { + struct vec3 position; + D3DCOLOR diffuse; + } + quad[] = + { + {{-1.0f, -1.0f, -0.5f}, 0xffff0000}, + {{-1.0f, 1.0f, -0.5f}, 0xffff0000}, + {{ 1.0f, -1.0f, -0.5f}, 0xffff0000}, + {{ 1.0f, 1.0f, -0.5f}, 0xffff0000}, + }; + union + { + DWORD d; + float f; + } conv; + unsigned int i; + static const struct + { + float start, end; + DWORD color; + } + tests[] = + { + /* fog_interpolation_test shows that vertex fog evaluates the fog + * equation in the vertex pipeline. Start = -1.0 && end = 0.0 shows + * that the abs happens before the fog equation is evaluated. */ + { 0.0f, 1.0f, 0x00808000}, + {-1.0f, 0.0f, 0x0000ff00}, + }; + static const D3DMATRIX proj_mat = + {{{ + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }}}; + + window = CreateWindowA("static", "d3d9_test", WS_OVERLAPPEDWINDOW | WS_VISIBLE, + 0, 0, 640, 480, NULL, NULL, NULL, NULL); + d3d = Direct3DCreate9(D3D_SDK_VERSION); + ok(!!d3d, "Failed to create a D3D object.\n"); + + if (!(device = create_device(d3d, window, window, TRUE))) + { + skip("Failed to create a D3D device, skipping tests.\n"); + IDirect3D9_Release(d3d); + DestroyWindow(window); + return; + } + + hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE); + ok(SUCCEEDED(hr), "Failed to set fvf, hr %#x.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_ZENABLE, D3DZB_FALSE); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0x0000ff00); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice9_SetTransform(device, D3DTS_PROJECTION, &proj_mat); + ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr); + + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) + { + hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0); + ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr); + + conv.f = tests[i].start; + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, conv.d); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + conv.f = tests[i].end; + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, conv.d); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice9_BeginScene(device); + ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr); + hr = IDirect3DDevice9_DrawPrimitiveUP(device, D3DPT_TRIANGLESTRIP, 2, quad, sizeof(*quad)); + ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr); + hr = IDirect3DDevice9_EndScene(device); + ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr); + + color = getPixelColor(device, 320, 240); + ok(color_match(color, tests[i].color, 2), "Got unexpected color 0x%08x, case %u.\n", color, i); + hr = IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL); + ok(SUCCEEDED(hr), "Failed to present, hr %#x.\n", hr); + } + + refcount = IDirect3DDevice9_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + IDirect3D9_Release(d3d); + DestroyWindow(window); +} + START_TEST(visual) { D3DADAPTER_IDENTIFIER9 identifier; @@ -17073,4 +17178,5 @@ START_TEST(visual) test_per_stage_constant(); test_3dc_formats(); fog_interpolation_test(); + negative_fixedfunction_fog_test(); } diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 9263e1e..576196d 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -8002,6 +8002,107 @@ static void fog_interpolation_test(void) DestroyWindow(window); } +static void test_negative_fixedfunction_fog(void) +{ + HRESULT hr; + IDirect3DDevice7 *device; + IDirectDrawSurface7 *rt; + ULONG refcount; + HWND window; + D3DCOLOR color; + static struct + { + struct vec3 position; + D3DCOLOR diffuse; + } + quad[] = + { + {{-1.0f, -1.0f, -0.5f}, 0xffff0000}, + {{-1.0f, 1.0f, -0.5f}, 0xffff0000}, + {{ 1.0f, -1.0f, -0.5f}, 0xffff0000}, + {{ 1.0f, 1.0f, -0.5f}, 0xffff0000}, + }; + union + { + DWORD d; + float f; + } conv; + unsigned int i; + static const struct + { + float start, end; + DWORD color; + } + tests[] = + { + /* test_fog_interpolation shows that vertex fog evaluates the fog + * equation in the vertex pipeline. Start = -1.0 && end = 0.0 shows + * that the abs happens before the fog equation is evaluated. */ + { 0.0f, 1.0f, 0x00808000}, + {-1.0f, 0.0f, 0x0000ff00}, + }; + static D3DMATRIX proj_mat = + { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + }; + + window = CreateWindowA("static", "ddraw_test", WS_OVERLAPPEDWINDOW, + 0, 0, 640, 480, 0, 0, 0, 0); + + if (!(device = create_device(window, DDSCL_NORMAL))) + { + skip("Failed to create a 3D device, skipping test.\n"); + DestroyWindow(window); + return; + } + + hr = IDirect3DDevice7_GetRenderTarget(device, &rt); + ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr); + + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, D3DZB_FALSE); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0x0000ff00); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_LINEAR); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &proj_mat); + ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr); + + for (i = 0; i < sizeof(tests) / sizeof(*tests); i++) + { + hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0x000000ff, 0.0f, 0); + ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr); + + conv.f = tests[i].start; + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, conv.d); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + conv.f = tests[i].end; + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, conv.d); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice7_BeginScene(device); + ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr); + hr = IDirect3DDevice7_DrawPrimitive(device, D3DPT_TRIANGLESTRIP, + D3DFVF_XYZ | D3DFVF_DIFFUSE, quad, 4, 0); + hr = IDirect3DDevice7_EndScene(device); + ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr); + + color = get_surface_color(rt, 0, 240); + ok(compare_color(color, tests[i].color, 2), "Got unexpected color 0x%08x, case %u.\n", color, i); + } + + IDirectDrawSurface7_Release(rt); + refcount = IDirect3DDevice7_Release(device); + ok(!refcount, "Device has %u references left.\n", refcount); + DestroyWindow(window); +} + START_TEST(ddraw7) { HMODULE module = GetModuleHandleA("ddraw.dll"); @@ -8089,4 +8190,5 @@ START_TEST(ddraw7) test_resource_priority(); test_surface_desc_lock(); fog_interpolation_test(); + test_negative_fixedfunction_fog(); } diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c index 98239ef..05a0e8e 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -5004,10 +5004,16 @@ static GLhandleARB shader_glsl_generate_ffp_vertex_shader(struct wined3d_shader_ case WINED3D_FFP_VS_FOG_DEPTH: if (settings->ortho_fog) + { /* Need to undo the [0.0 - 1.0] -> [-1.0 - 1.0] transformation from D3D to GL coordinates. */ shader_addline(buffer, "gl_FogFragCoord = gl_Position.z * 0.5 + 0.5;\n"); + } else + { shader_addline(buffer, "gl_FogFragCoord = ec_pos.z;\n"); + if (!settings->transformed) + shader_addline(buffer, "gl_FogFragCoord = abs(gl_FogFragCoord);\n"); + } break; default: -- 2.0.4