From: Stefan Dösinger Subject: [PATCH 1/4] wined3d: Vertex fog uses the absolute eye position z (v3). Message-Id: <1417086756-14596-1-git-send-email-stefan@codeweavers.com> Date: Thu, 27 Nov 2014 12:12:33 +0100 Version 3: Code style fixes. Version 2: Set ZENABLE to D3DZB_FALSE instead of FALSE. 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 3. --- dlls/d3d8/tests/visual.c | 103 +++++++++++++++++++++++++++++++++++++++++++++ dlls/d3d9/tests/visual.c | 103 +++++++++++++++++++++++++++++++++++++++++++++ dlls/ddraw/tests/ddraw7.c | 99 +++++++++++++++++++++++++++++++++++++++++++ dlls/wined3d/glsl_shader.c | 4 +- 4 files changed, 308 insertions(+), 1 deletion(-) diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c index cbede9d..317df5a 100644 --- a/dlls/d3d8/tests/visual.c +++ b/dlls/d3d8/tests/visual.c @@ -5361,6 +5361,108 @@ static void fog_interpolation_test(void) DestroyWindow(window); } +static void test_negative_fixedfunction_fog(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}, + }; + unsigned int i; + static const struct + { + union + { + float f; + DWORD d; + } 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); + + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGSTART, tests[i].start.d); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGEND, tests[i].end.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 +5514,5 @@ START_TEST(visual) add_dirty_rect_test(); test_3dc_formats(); fog_interpolation_test(); + test_negative_fixedfunction_fog(); } diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c index fbab386..6ee19b0 100644 --- a/dlls/d3d9/tests/visual.c +++ b/dlls/d3d9/tests/visual.c @@ -16964,6 +16964,108 @@ static void fog_interpolation_test(void) DestroyWindow(window); } +static void test_negative_fixedfunction_fog(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}, + }; + unsigned int i; + static const struct + { + union + { + float f; + DWORD d; + } 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); + + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, tests[i].start.d); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, tests[i].end.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 +17175,5 @@ START_TEST(visual) test_per_stage_constant(); test_3dc_formats(); fog_interpolation_test(); + test_negative_fixedfunction_fog(); } diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index 9263e1e..647ec82 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -8002,6 +8002,104 @@ 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}, + }; + unsigned int i; + static const struct + { + union + { + float f; + DWORD d; + } 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 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); + + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, tests[i].start.d); + ok(SUCCEEDED(hr), "Failed to set render state, hr %#x.\n", hr); + hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, tests[i].end.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 +8187,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..a71459e 100644 --- a/dlls/wined3d/glsl_shader.c +++ b/dlls/wined3d/glsl_shader.c @@ -5006,8 +5006,10 @@ static GLhandleARB shader_glsl_generate_ffp_vertex_shader(struct wined3d_shader_ 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 + else if (settings->transformed) shader_addline(buffer, "gl_FogFragCoord = ec_pos.z;\n"); + else + shader_addline(buffer, "gl_FogFragCoord = abs(ec_pos.z);\n"); break; default: -- 2.0.4