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