Commit 287093e2 authored by Matteo Bruni's avatar Matteo Bruni Committed by Alexandre Julliard

ddraw/tests: Add a ddraw7 specular lighting test.

parent 67bdfd3d
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include "wine/test.h" #include "wine/test.h"
#include <limits.h> #include <limits.h>
#include <math.h>
#include "d3d.h" #include "d3d.h"
static HRESULT (WINAPI *pDirectDrawCreateEx)(GUID *guid, void **ddraw, REFIID iid, IUnknown *outer_unknown); static HRESULT (WINAPI *pDirectDrawCreateEx)(GUID *guid, void **ddraw, REFIID iid, IUnknown *outer_unknown);
...@@ -3618,6 +3619,300 @@ static void test_lighting(void) ...@@ -3618,6 +3619,300 @@ static void test_lighting(void)
DestroyWindow(window); DestroyWindow(window);
} }
static void test_specular_lighting(void)
{
static const unsigned int vertices_side = 5;
const unsigned int indices_count = (vertices_side - 1) * (vertices_side - 1) * 2 * 3;
static const DWORD fvf = D3DFVF_XYZ | D3DFVF_NORMAL;
static D3DMATRIX mat =
{
1.0f, 0.0f, 0.0f, 0.0f,
0.0f, 1.0f, 0.0f, 0.0f,
0.0f, 0.0f, 1.0f, 0.0f,
0.0f, 0.0f, 0.0f, 1.0f,
};
static D3DLIGHT7 directional =
{
D3DLIGHT_DIRECTIONAL,
{{0.0f}, {0.0f}, {0.0f}, {0.0f}},
{{1.0f}, {1.0f}, {1.0f}, {0.0f}},
{{0.0f}, {0.0f}, {0.0f}, {0.0f}},
{{0.0f}, {0.0f}, {0.0f}},
{{0.0f}, {0.0f}, {1.0f}},
},
point =
{
D3DLIGHT_POINT,
{{0.0f}, {0.0f}, {0.0f}, {0.0f}},
{{1.0f}, {1.0f}, {1.0f}, {0.0f}},
{{0.0f}, {0.0f}, {0.0f}, {0.0f}},
{{0.0f}, {0.0f}, {0.0f}},
{{0.0f}, {0.0f}, {0.0f}},
100.0f,
0.0f,
0.0f, 0.0f, 1.0f,
},
spot =
{
D3DLIGHT_SPOT,
{{0.0f}, {0.0f}, {0.0f}, {0.0f}},
{{1.0f}, {1.0f}, {1.0f}, {0.0f}},
{{0.0f}, {0.0f}, {0.0f}, {0.0f}},
{{0.0f}, {0.0f}, {0.0f}},
{{0.0f}, {0.0f}, {1.0f}},
100.0f,
1.0f,
0.0f, 0.0f, 1.0f,
M_PI / 12.0f, M_PI / 3.0f
},
/* The chosen range value makes the test fail when using a manhattan
* distance metric vs the correct euclidean distance. */
point_range =
{
D3DLIGHT_POINT,
{{0.0f}, {0.0f}, {0.0f}, {0.0f}},
{{1.0f}, {1.0f}, {1.0f}, {0.0f}},
{{0.0f}, {0.0f}, {0.0f}, {0.0f}},
{{0.0f}, {0.0f}, {0.0f}},
{{0.0f}, {0.0f}, {0.0f}},
1.2f,
0.0f,
0.0f, 0.0f, 1.0f,
};
static const struct expected_color
{
unsigned int x, y;
D3DCOLOR color;
}
expected_directional[] =
{
{160, 120, 0x00ffffff},
{320, 120, 0x00ffffff},
{480, 120, 0x00ffffff},
{160, 240, 0x00ffffff},
{320, 240, 0x00ffffff},
{480, 240, 0x00ffffff},
{160, 360, 0x00ffffff},
{320, 360, 0x00ffffff},
{480, 360, 0x00ffffff},
},
expected_directional_local[] =
{
{160, 120, 0x003c3c3c},
{320, 120, 0x00717171},
{480, 120, 0x003c3c3c},
{160, 240, 0x00717171},
{320, 240, 0x00ffffff},
{480, 240, 0x00717171},
{160, 360, 0x003c3c3c},
{320, 360, 0x00717171},
{480, 360, 0x003c3c3c},
},
expected_point[] =
{
{160, 120, 0x00282828},
{320, 120, 0x005a5a5a},
{480, 120, 0x00282828},
{160, 240, 0x005a5a5a},
{320, 240, 0x00ffffff},
{480, 240, 0x005a5a5a},
{160, 360, 0x00282828},
{320, 360, 0x005a5a5a},
{480, 360, 0x00282828},
},
expected_point_local[] =
{
{160, 120, 0x00000000},
{320, 120, 0x00070707},
{480, 120, 0x00000000},
{160, 240, 0x00070707},
{320, 240, 0x00ffffff},
{480, 240, 0x00070707},
{160, 360, 0x00000000},
{320, 360, 0x00070707},
{480, 360, 0x00000000},
},
expected_spot[] =
{
{160, 120, 0x00000000},
{320, 120, 0x00141414},
{480, 120, 0x00000000},
{160, 240, 0x00141414},
{320, 240, 0x00ffffff},
{480, 240, 0x00141414},
{160, 360, 0x00000000},
{320, 360, 0x00141414},
{480, 360, 0x00000000},
},
expected_spot_local[] =
{
{160, 120, 0x00000000},
{320, 120, 0x00020202},
{480, 120, 0x00000000},
{160, 240, 0x00020202},
{320, 240, 0x00ffffff},
{480, 240, 0x00020202},
{160, 360, 0x00000000},
{320, 360, 0x00020202},
{480, 360, 0x00000000},
},
expected_point_range[] =
{
{160, 120, 0x00000000},
{320, 120, 0x005a5a5a},
{480, 120, 0x00000000},
{160, 240, 0x005a5a5a},
{320, 240, 0x00ffffff},
{480, 240, 0x005a5a5a},
{160, 360, 0x00000000},
{320, 360, 0x005a5a5a},
{480, 360, 0x00000000},
};
static const struct
{
D3DLIGHT7 *light;
BOOL local_viewer;
const struct expected_color *expected;
unsigned int expected_count;
}
tests[] =
{
{&directional, FALSE, expected_directional,
sizeof(expected_directional) / sizeof(expected_directional[0])},
{&directional, TRUE, expected_directional_local,
sizeof(expected_directional_local) / sizeof(expected_directional_local[0])},
{&point, FALSE, expected_point,
sizeof(expected_point) / sizeof(expected_point[0])},
{&point, TRUE, expected_point_local,
sizeof(expected_point_local) / sizeof(expected_point_local[0])},
{&spot, FALSE, expected_spot,
sizeof(expected_spot) / sizeof(expected_spot[0])},
{&spot, TRUE, expected_spot_local,
sizeof(expected_spot_local) / sizeof(expected_spot_local[0])},
{&point_range, FALSE, expected_point_range,
sizeof(expected_point_range) / sizeof(expected_point_range[0])},
};
IDirect3DDevice7 *device;
IDirectDrawSurface7 *rt;
D3DMATERIAL7 material;
D3DCOLOR color;
ULONG refcount;
HWND window;
HRESULT hr;
unsigned int i, j, x, y;
struct
{
struct vec3 position;
struct vec3 normal;
} *quad;
WORD *indices;
quad = HeapAlloc(GetProcessHeap(), 0, vertices_side * vertices_side * sizeof(*quad));
indices = HeapAlloc(GetProcessHeap(), 0, indices_count * sizeof(*indices));
for (i = 0, y = 0; y < vertices_side; ++y)
{
for (x = 0; x < vertices_side; ++x)
{
quad[i].position.x = x * 2.0f / (vertices_side - 1) - 1.0f;
quad[i].position.y = y * 2.0f / (vertices_side - 1) - 1.0f;
quad[i].position.z = 1.0f;
quad[i].normal.x = 0.0f;
quad[i].normal.y = 0.0f;
quad[i++].normal.z = -1.0f;
}
}
for (i = 0, y = 0; y < (vertices_side - 1); ++y)
{
for (x = 0; x < (vertices_side - 1); ++x)
{
indices[i++] = y * vertices_side + x + 1;
indices[i++] = y * vertices_side + x;
indices[i++] = (y + 1) * vertices_side + x;
indices[i++] = y * vertices_side + x + 1;
indices[i++] = (y + 1) * vertices_side + x;
indices[i++] = (y + 1) * vertices_side + x + 1;
}
}
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_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
hr = IDirect3DDevice7_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
memset(&material, 0, sizeof(material));
U(U2(material).specular).r = 1.0f;
U2(U2(material).specular).g = 1.0f;
U3(U2(material).specular).b = 1.0f;
U4(U2(material).specular).a = 1.0f;
U4(material).power = 30.0f;
hr = IDirect3DDevice7_SetMaterial(device, &material);
ok(SUCCEEDED(hr), "Failed to set material, hr %#x.\n", hr);
hr = IDirect3DDevice7_LightEnable(device, 0, TRUE);
ok(SUCCEEDED(hr), "Failed to enable light 0, hr %#x.\n", hr);
hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_SPECULARENABLE, TRUE);
ok(SUCCEEDED(hr), "Failed to enable specular lighting, hr %#x.\n", hr);
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
{
hr = IDirect3DDevice7_SetLight(device, 0, tests[i].light);
ok(SUCCEEDED(hr), "Failed to set light parameters, hr %#x.\n", hr);
hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
ok(SUCCEEDED(hr), "Failed to set local viewer state, hr %#x.\n", hr);
hr = IDirect3DDevice7_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
hr = IDirect3DDevice7_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice7_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, fvf, quad,
vertices_side * vertices_side, indices, indices_count, 0);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice7_EndScene(device);
ok(SUCCEEDED(hr), "Failed to end scene, hr %#x.\n", hr);
for (j = 0; j < tests[i].expected_count; ++j)
{
color = get_surface_color(rt, tests[i].expected[j].x, tests[i].expected[j].y);
ok(compare_color(color, tests[i].expected[j].color, 1),
"Expected color 0x%08x at location (%u, %u), got 0x%08x, case %u.\n",
tests[i].expected[j].color, tests[i].expected[j].x,
tests[i].expected[j].y, color, i);
}
}
IDirectDrawSurface7_Release(rt);
refcount = IDirect3DDevice7_Release(device);
ok(!refcount, "Device has %u references left.\n", refcount);
DestroyWindow(window);
HeapFree(GetProcessHeap(), 0, indices);
HeapFree(GetProcessHeap(), 0, quad);
}
static void test_clear_rect_count(void) static void test_clear_rect_count(void)
{ {
IDirectDrawSurface7 *rt; IDirectDrawSurface7 *rt;
...@@ -9297,6 +9592,7 @@ START_TEST(ddraw7) ...@@ -9297,6 +9592,7 @@ START_TEST(ddraw7)
test_coop_level_multi_window(); test_coop_level_multi_window();
test_draw_strided(); test_draw_strided();
test_lighting(); test_lighting();
test_specular_lighting();
test_clear_rect_count(); test_clear_rect_count();
test_coop_level_versions(); test_coop_level_versions();
test_fog_special(); test_fog_special();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment