Direct3D: Add a fixed function fog test

Stefan Dösinger stefandoesinger at gmx.at
Wed Mar 14 15:32:43 CDT 2007


-------------- next part --------------
From 5e39aaa3a82048e03c616ac67e3b14a5d9b6eeee Mon Sep 17 00:00:00 2001
From: Stefan Doesinger <stefan at codeweavers.com>
Date: Wed, 14 Mar 2007 18:04:56 +0100
Subject: [PATCH] Direct3D: Add a fixed function fog test

These tests confirm the fog rules I figured out by looking at some old
d3d7 games for ddraw, d3d8 and d3d9. Should serve as a start for adding
shader fog tests.

Also updates the comments in dlls/wined3d/state.c
---
 dlls/d3d8/tests/visual.c  |  135 ++++++++++++++++++++++++++++++++++++++++++++
 dlls/d3d9/tests/visual.c  |  137 +++++++++++++++++++++++++++++++++++++++++++++
 dlls/ddraw/tests/visual.c |  128 ++++++++++++++++++++++++++++++++++++++++++
 dlls/wined3d/state.c      |   25 +++++++-
 4 files changed, 421 insertions(+), 4 deletions(-)

diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c
index 961cab0..b8833f2 100644
--- a/dlls/d3d8/tests/visual.c
+++ b/dlls/d3d8/tests/visual.c
@@ -307,6 +307,140 @@ static void clear_test(IDirect3DDevice8 *device)
     ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
 }
 
+struct sVertex {
+    float x, y, z;
+    DWORD diffuse;
+    DWORD specular;
+};
+
+struct sVertexT {
+    float x, y, z, rhw;
+    DWORD diffuse;
+    DWORD specular;
+};
+
+static void fog_test(IDirect3DDevice8 *device)
+{
+    HRESULT hr;
+    DWORD color;
+    float start = 0.0, end = 1.0;
+
+    /* Gets full z based fog with linear fog, no fog with specular color */
+    struct sVertex unstransformed_1[] = {
+        {-1,    -1,   0.1,          0xFFFF0000,     0xFF000000  },
+        {-1,     0,   0.1,          0xFFFF0000,     0xFF000000  },
+        { 0,     0,   0.1,          0xFFFF0000,     0xFF000000  },
+        { 0,    -1,   0.1,          0xFFFF0000,     0xFF000000  },
+    };
+    /* Ok, I am too lazy to deal with transform matrices */
+    struct sVertex unstransformed_2[] = {
+        {-1,     0,   1.0,          0xFFFF0000,     0xFF000000  },
+        {-1,     1,   1.0,          0xFFFF0000,     0xFF000000  },
+        { 0,     1,   1.0,          0xFFFF0000,     0xFF000000  },
+        { 0,     0,   1.0,          0xFFFF0000,     0xFF000000  },
+    };
+    /* Untransformed ones. Give them a different diffuse color to make the test look
+     * nicer. It also makes making sure that they are drawn correctly easier.
+     */
+    struct sVertexT transformed_1[] = {
+        {320,    0,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {640,    0,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {640,  240,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {320,  240,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+    };
+    struct sVertexT transformed_2[] = {
+        {320,  240,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {640,  240,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {640,  480,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {320,  480,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+    };
+    WORD Indices[] = {0, 1, 2, 2, 3, 0};
+
+    hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
+    ok(hr == D3D_OK, "IDirect3DDevice8_Clear returned %s\n", DXGetErrorString8(hr));
+
+    /* Setup initial states: No lighting, fog on, fog color */
+    hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LIGHTING, FALSE);
+    ok(hr == D3D_OK, "Turning off lighting returned %s\n", DXGetErrorString8(hr));
+    hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
+    ok(hr == D3D_OK, "Turning on fog calculations returned %s\n", DXGetErrorString8(hr));
+    hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
+    ok(hr == D3D_OK, "Turning on fog calculations returned %s\n", DXGetErrorString8(hr));
+
+    /* First test: Both table fog and vertex fog off */
+    hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
+    ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString8(hr));
+    hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
+    ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString8(hr));
+
+    /* Start = 0, end = 1. Should be default, but set them */
+    hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
+    ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString8(hr));
+    hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
+    ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString8(hr));
+
+    if(IDirect3DDevice8_BeginScene(device) == D3D_OK)
+    {
+        hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
+        ok( hr == D3D_OK, "SetVertexShader returned %s\n", DXGetErrorString8(hr));
+        /* Untransformed, vertex fog = NONE, table fog = NONE: Read the fog weighting from the specular color */
+        hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
+                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_1,
+                                                     sizeof(unstransformed_1[0]));
+        ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString8(hr));
+
+        /* That makes it use the Z value */
+        hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
+        ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString8(hr));
+        /* Untransformed, vertex fog != none (or table fog != none):
+         * Use the Z value as input into the equation
+         */
+        hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
+                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_2,
+                                                     sizeof(unstransformed_1[0]));
+        ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString8(hr));
+
+        /* transformed verts */
+        hr = IDirect3DDevice8_SetVertexShader(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
+        ok( hr == D3D_OK, "SetVertexShader returned %s\n", DXGetErrorString8(hr));
+        /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
+        hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
+                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
+                                                     sizeof(transformed_1[0]));
+        ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString8(hr));
+
+        hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
+        ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %s\n", DXGetErrorString8(hr));
+        /* Transformed, table fog != none, vertex anything: Use Z value as input to the fog
+         * equation
+         */
+        hr = IDirect3DDevice8_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
+                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_2,
+                                                     sizeof(transformed_2[0]));
+
+        hr = IDirect3DDevice8_EndScene(device);
+        ok(hr == D3D_OK, "EndScene returned %s\n", DXGetErrorString8(hr));
+    }
+    else
+    {
+        ok(FALSE, "BeginScene failed\n");
+    }
+
+    IDirect3DDevice8_Present(device, NULL, NULL, NULL, NULL);
+    color = getPixelColor(device, 160, 360);
+    ok(color == 0x00FF0000, "Untransformed vertex with no table or vertex fog has color %08x\n", color);
+    color = getPixelColor(device, 160, 120);
+    ok(color == 0x0000FF00, "Untransformed vertex with linear vertex fog has color %08x\n", color);
+    color = getPixelColor(device, 480, 120);
+    ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
+    color = getPixelColor(device, 480, 360);
+    ok(color == 0x0000FF00, "Transformed vertex with linear table fog has color %08x\n", color);
+
+    /* Turn off the fog master switch to avoid confusing other tests */
+    hr = IDirect3DDevice8_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
+    ok(hr == D3D_OK, "Turning off fog calculations returned %s\n", DXGetErrorString8(hr));
+}
+
 START_TEST(visual)
 {
     IDirect3DDevice8 *device_ptr;
@@ -357,6 +491,7 @@ START_TEST(visual)
     /* Now run the real test */
     lighting_test(device_ptr);
     clear_test(device_ptr);
+    fog_test(device_ptr);
 
 cleanup:
     if(device_ptr) IDirect3DDevice8_Release(device_ptr);
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index d1d39b1..67729db 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -412,6 +412,142 @@ static void test_mova(IDirect3DDevice9 *device)
     IDirect3DVertexShader9_Release(mova_shader);
 }
 
+struct sVertex {
+    float x, y, z;
+    DWORD diffuse;
+    DWORD specular;
+};
+
+struct sVertexT {
+    float x, y, z, rhw;
+    DWORD diffuse;
+    DWORD specular;
+};
+
+static void fog_test(IDirect3DDevice9 *device)
+{
+    HRESULT hr;
+    DWORD color;
+    float start = 0.0, end = 1.0;
+
+    /* Gets full z based fog with linear fog, no fog with specular color */
+    struct sVertex unstransformed_1[] = {
+        {-1,    -1,   0.1,          0xFFFF0000,     0xFF000000  },
+        {-1,     0,   0.1,          0xFFFF0000,     0xFF000000  },
+        { 0,     0,   0.1,          0xFFFF0000,     0xFF000000  },
+        { 0,    -1,   0.1,          0xFFFF0000,     0xFF000000  },
+    };
+    /* Ok, I am too lazy to deal with transform matrices */
+    struct sVertex unstransformed_2[] = {
+        {-1,     0,   1.0,          0xFFFF0000,     0xFF000000  },
+        {-1,     1,   1.0,          0xFFFF0000,     0xFF000000  },
+        { 0,     1,   1.0,          0xFFFF0000,     0xFF000000  },
+        { 0,     0,   1.0,          0xFFFF0000,     0xFF000000  },
+    };
+    /* Untransformed ones. Give them a different diffuse color to make the test look
+     * nicer. It also makes making sure that they are drawn correctly easier.
+     */
+    struct sVertexT transformed_1[] = {
+        {320,    0,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {640,    0,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {640,  240,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {320,  240,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+    };
+    struct sVertexT transformed_2[] = {
+        {320,  240,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {640,  240,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {640,  480,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {320,  480,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+    };
+    WORD Indices[] = {0, 1, 2, 2, 3, 0};
+
+    hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
+    ok(hr == D3D_OK, "IDirect3DDevice9_Clear returned %s\n", DXGetErrorString9(hr));
+
+    /* Setup initial states: No lighting, fog on, fog color */
+    hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LIGHTING, FALSE);
+    ok(hr == D3D_OK, "Turning off lighting returned %s\n", DXGetErrorString9(hr));
+    hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, TRUE);
+    ok(hr == D3D_OK, "Turning on fog calculations returned %s\n", DXGetErrorString9(hr));
+    hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGCOLOR, 0xFF00FF00 /* A nice green */);
+    ok(hr == D3D_OK, "Turning on fog calculations returned %s\n", DXGetErrorString9(hr));
+
+    /* First test: Both table fog and vertex fog off */
+    hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_NONE);
+    ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString9(hr));
+    hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_NONE);
+    ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString9(hr));
+
+    /* Start = 0, end = 1. Should be default, but set them */
+    hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGSTART, *((DWORD *) &start));
+    ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
+    hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGEND, *((DWORD *) &end));
+    ok(hr == D3D_OK, "Setting fog start returned %s\n", DXGetErrorString9(hr));
+
+    if(IDirect3DDevice9_BeginScene(device) == D3D_OK)
+    {
+        hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
+        ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
+        /* Untransformed, vertex fog = NONE, table fog = NONE: Read the fog weighting from the specular color */
+        hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
+                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_1,
+                                                     sizeof(unstransformed_1[0]));
+        ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
+
+        /* That makes it use the Z value */
+        hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGVERTEXMODE, D3DFOG_LINEAR);
+        ok(hr == D3D_OK, "Turning off table fog returned %s\n", DXGetErrorString9(hr));
+        /* Untransformed, vertex fog != none (or table fog != none):
+         * Use the Z value as input into the equation
+         */
+        hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
+                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, unstransformed_2,
+                                                     sizeof(unstransformed_1[0]));
+        ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
+
+        /* transformed verts */
+        hr = IDirect3DDevice9_SetFVF(device, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR);
+        ok( hr == D3D_OK, "SetFVF returned %s\n", DXGetErrorString9(hr));
+        /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
+        hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
+                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_1,
+                                                     sizeof(transformed_1[0]));
+        ok(hr == D3D_OK, "DrawIndexedPrimitiveUP returned %s\n", DXGetErrorString9(hr));
+
+        hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGTABLEMODE, D3DFOG_LINEAR);
+        ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %s\n", DXGetErrorString9(hr));
+        /* Transformed, table fog != none, vertex anything: Use Z value as input to the fog
+         * equation
+         */
+        hr = IDirect3DDevice9_DrawIndexedPrimitiveUP(device, D3DPT_TRIANGLELIST, 0 /* MinIndex */, 4 /* NumVerts */,
+                                                     2 /*PrimCount */, Indices, D3DFMT_INDEX16, transformed_2,
+                                                     sizeof(transformed_2[0]));
+
+        hr = IDirect3DDevice9_EndScene(device);
+        ok(hr == D3D_OK, "EndScene returned %s\n", DXGetErrorString9(hr));
+    }
+    else
+    {
+        ok(FALSE, "BeginScene failed\n");
+    }
+
+    IDirect3DDevice9_Present(device, NULL, NULL, NULL, NULL);
+    color = getPixelColor(device, 160, 360);
+    ok(color == 0x00FF0000, "Untransformed vertex with no table or vertex fog has color %08x\n", color);
+    color = getPixelColor(device, 160, 120);
+    ok(color == 0x0000FF00, "Untransformed vertex with linear vertex fog has color %08x\n", color);
+    color = getPixelColor(device, 480, 120);
+    ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
+    color = getPixelColor(device, 480, 360);
+    ok(color == 0x0000FF00, "Transformed vertex with linear table fog has color %08x\n", color);
+
+    /* Turn off the fog master switch to avoid confusing other tests */
+    hr = IDirect3DDevice9_SetRenderState(device, D3DRS_FOGENABLE, FALSE);
+    ok(hr == D3D_OK, "Turning off fog calculations returned %s\n", DXGetErrorString9(hr));
+
+    IDirect3DDevice9_SetVertexDeclaration(device, NULL);
+}
+
 START_TEST(visual)
 {
     IDirect3DDevice9 *device_ptr;
@@ -465,6 +601,7 @@ START_TEST(visual)
     /* Now execute the real tests */
     lighting_test(device_ptr);
     clear_test(device_ptr);
+    fog_test(device_ptr);
 
     if (caps.VertexShaderVersion >= D3DVS_VERSION(2, 0))
     {
diff --git a/dlls/ddraw/tests/visual.c b/dlls/ddraw/tests/visual.c
index f79586c..e970a9f 100644
--- a/dlls/ddraw/tests/visual.c
+++ b/dlls/ddraw/tests/visual.c
@@ -347,6 +347,133 @@ static void clear_test(IDirect3DDevice7 *device)
     ok(color == 0x00ffffff, "Clear rectangle 4(neg, neg) has color %08x\n", color);
 }
 
+struct sVertex {
+    float x, y, z;
+    DWORD diffuse;
+    DWORD specular;
+};
+
+struct sVertexT {
+    float x, y, z, rhw;
+    DWORD diffuse;
+    DWORD specular;
+};
+
+static void fog_test(IDirect3DDevice7 *device)
+{
+    HRESULT hr;
+    DWORD color;
+    float start = 0.0, end = 1.0;
+
+    /* Gets full z based fog with linear fog, no fog with specular color */
+    struct sVertex unstransformed_1[] = {
+        {-1,    -1,   0.1,          0xFFFF0000,     0xFF000000  },
+        {-1,     0,   0.1,          0xFFFF0000,     0xFF000000  },
+        { 0,     0,   0.1,          0xFFFF0000,     0xFF000000  },
+        { 0,    -1,   0.1,          0xFFFF0000,     0xFF000000  },
+    };
+    /* Ok, I am too lazy to deal with transform matrices */
+    struct sVertex unstransformed_2[] = {
+        {-1,     0,   1.0,          0xFFFF0000,     0xFF000000  },
+        {-1,     1,   1.0,          0xFFFF0000,     0xFF000000  },
+        { 0,     1,   1.0,          0xFFFF0000,     0xFF000000  },
+        { 0,     0,   1.0,          0xFFFF0000,     0xFF000000  },
+    };
+    /* Untransformed ones. Give them a different diffuse color to make the test look
+     * nicer. It also makes making sure that they are drawn correctly easier.
+     */
+    struct sVertexT transformed_1[] = {
+        {320,    0,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {640,    0,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {640,  240,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {320,  240,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+    };
+    struct sVertexT transformed_2[] = {
+        {320,  240,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {640,  240,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {640,  480,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+        {320,  480,   1.0,  1.0,    0xFFFFFF00,     0xFF000000  },
+    };
+    WORD Indices[] = {0, 1, 2, 2, 3, 0};
+
+    hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffff00ff, 0.0, 0);
+    ok(hr == D3D_OK, "IDirect3DDevice7_Clear returned %08x\n", hr);
+
+    /* Setup initial states: No lighting, fog on, fog color */
+    hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LIGHTING, FALSE);
+    ok(hr == D3D_OK, "Turning off lighting returned %08x\n", hr);
+    hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, TRUE);
+    ok(hr == D3D_OK, "Turning on fog calculations returned %08x\n", hr);
+    hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGCOLOR, 0xFF00FF00 /* A nice green */);
+    ok(hr == D3D_OK, "Turning on fog calculations returned %08x\n", hr);
+
+    /* First test: Both table fog and vertex fog off */
+    hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_NONE);
+    ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
+    hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_NONE);
+    ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
+
+    /* Start = 0, end = 1. Should be default, but set them */
+    hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGSTART, *((DWORD *) &start));
+    ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
+    hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGEND, *((DWORD *) &end));
+    ok(hr == D3D_OK, "Setting fog start returned %08x\n", hr);
+
+    if(IDirect3DDevice7_BeginScene(device) == D3D_OK)
+    {
+        /* Untransformed, vertex fog = NONE, table fog = NONE: Read the fog weighting from the specular color */
+        hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
+                                                   unstransformed_1, 4, Indices, 6, 0);
+        ok(hr == D3D_OK, "DrawIndexedPrimitive returned %08x\n", hr);
+
+        /* That makes it use the Z value */
+        hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGVERTEXMODE, D3DFOG_LINEAR);
+        ok(hr == D3D_OK, "Turning off table fog returned %08x\n", hr);
+        /* Untransformed, vertex fog != none (or table fog != none):
+         * Use the Z value as input into the equation
+         */
+        hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_XYZ | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
+                                                   unstransformed_2, 4, Indices, 6, 0);
+        ok(hr == D3D_OK, "DrawIndexedPrimitive returned %08x\n", hr);
+
+        /* transformed verts */
+        ok( hr == D3D_OK, "SetFVF returned %08x\n", hr);
+        /* Transformed, vertex fog != NONE, pixel fog == NONE: Use specular color alpha component */
+        hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
+                                                   transformed_1, 4, Indices, 6, 0);
+        ok(hr == D3D_OK, "DrawIndexedPrimitive returned %08x\n", hr);
+
+        hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGTABLEMODE, D3DFOG_LINEAR);
+        ok( hr == D3D_OK, "Setting fog table mode to D3DFOG_LINEAR returned %08x\n", hr);
+        /* Transformed, table fog != none, vertex anything: Use Z value as input to the fog
+         * equation
+         */
+        hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_SPECULAR,
+                                                   transformed_2, 4, Indices, 6, 0);
+        ok(hr == D3D_OK, "DrawIndexedPrimitive returned %08x\n", hr);
+
+        hr = IDirect3DDevice7_EndScene(device);
+        ok(hr == D3D_OK, "EndScene returned %08x\n", hr);
+    }
+    else
+    {
+        ok(FALSE, "BeginScene failed\n");
+    }
+
+    color = getPixelColor(device, 160, 360);
+    ok(color == 0x00FF0000, "Untransformed vertex with no table or vertex fog has color %08x\n", color);
+    color = getPixelColor(device, 160, 120);
+    ok(color == 0x0000FF00, "Untransformed vertex with linear vertex fog has color %08x\n", color);
+    color = getPixelColor(device, 480, 120);
+    ok(color == 0x00FFFF00, "Transformed vertex with linear vertex fog has color %08x\n", color);
+    color = getPixelColor(device, 480, 360);
+    ok(color == 0x0000FF00, "Transformed vertex with linear table fog has color %08x\n", color);
+
+    /* Turn off the fog master switch to avoid confusing other tests */
+    hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
+    ok(hr == D3D_OK, "Turning off fog calculations returned %08x\n", hr);
+}
+
 START_TEST(visual)
 {
     HRESULT hr;
@@ -389,6 +516,7 @@ START_TEST(visual)
     /* Now run the tests */
     lighting_test(Direct3DDevice);
     clear_test(Direct3DDevice);
+    fog_test(Direct3DDevice);
 
 cleanup:
     releaseObjects();
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 9bb34a0..2a567b8 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -708,7 +708,26 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo
     tmpvalue.d = stateblock->renderState[WINED3DRS_FOGEND];
     fogend = tmpvalue.f;
 
-    /* Activate when vertex shaders are in the state table */
+    /* Fog Rules:
+     *
+     * With fixed function vertex processing, Direct3D knows 2 different fog input sources.
+     * It can use the Z value of the vertex, or the alpha component of the specular color.
+     * This depends on the fog vertex, fog table and the vertex declaration. If the Z value
+     * is used, fogstart, fogend and the equation type are used, otherwise linear fog with
+     * start = 255, end = 0 is used. Obviously the msdn is not very clear on that.
+     *
+     * FOGTABLEMODE != NONE:
+     *  The Z value is used, with the equation specified, no matter what vertex type.
+     *
+     * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, untransformed:
+     *  Per vertex fog is calculated using the specified fog equation and the parameters
+     *
+     * FOGTABLEMODE == NONE, FOGVERTEXMODE != NONE, transformed, OR
+     * FOGTABLEMODE == NONE, FOGVERTEXMODE == NONE, untransformed:
+     *  Linear fog with start = 255.0, end = 0.0, input comes from the specular color
+     *
+     * Vertex shaders work in a simmilar way, but need more testing
+     */
     if (use_vs(stateblock->wineD3DDevice)
             && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->usesFog) {
         glFogi(GL_FOG_MODE, GL_LINEAR);
@@ -728,9 +747,7 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo
         context->last_was_foggy_shader = FALSE;
 
         switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
-            /* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
-             * If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
-             */
+            /* If processed vertices are used, fall through to the NONE case */
             case WINED3DFOG_EXP:  {
                 if(!context->last_was_rhw) {
                     glFogi(GL_FOG_MODE, GL_EXP);
-- 
1.4.4.3



More information about the wine-patches mailing list