ddraw/tests: Add a ddraw2 specular lighting test.

This commit is contained in:
Matteo Bruni 2015-05-04 23:16:14 +02:00 committed by Alexandre Julliard
parent 6418a489e0
commit 0cc7daebd8
1 changed files with 283 additions and 1 deletions

View File

@ -16,8 +16,10 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define COBJMACROS
#include <math.h>
#define COBJMACROS
#include "wine/test.h"
#include "d3d.h"
@ -342,6 +344,22 @@ static IDirect3DMaterial2 *create_diffuse_material(IDirect3DDevice2 *device, flo
return create_material(device, &mat);
}
static IDirect3DMaterial2 *create_specular_material(IDirect3DDevice2 *device,
float r, float g, float b, float a, float power)
{
D3DMATERIAL mat;
memset(&mat, 0, sizeof(mat));
mat.dwSize = sizeof(mat);
U1(U2(mat).specular).r = r;
U2(U2(mat).specular).g = g;
U3(U2(mat).specular).b = b;
U4(U2(mat).specular).a = a;
U4(mat).power = power;
return create_material(device, &mat);
}
static IDirect3DMaterial2 *create_emissive_material(IDirect3DDevice2 *device, float r, float g, float b, float a)
{
D3DMATERIAL mat;
@ -6656,6 +6674,269 @@ static void test_lighting(void)
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 D3DRECT clear_rect = {{0}, {0}, {640}, {480}};
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 D3DLIGHT2 directional =
{
sizeof(D3DLIGHT2),
D3DLIGHT_DIRECTIONAL,
{{1.0f}, {1.0f}, {1.0f}, {0.0f}},
{{0.0f}, {0.0f}, {0.0f}},
{{0.0f}, {0.0f}, {1.0f}},
},
point =
{
sizeof(D3DLIGHT2),
D3DLIGHT_POINT,
{{1.0f}, {1.0f}, {1.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 =
{
sizeof(D3DLIGHT2),
D3DLIGHT_SPOT,
{{1.0f}, {1.0f}, {1.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
},
parallelpoint =
{
sizeof(D3DLIGHT2),
D3DLIGHT_PARALLELPOINT,
{{1.0f}, {1.0f}, {1.0f}, {0.0f}},
{{0.5f}, {0.0f}, {-1.0f}},
{{0.0f}, {0.0f}, {0.0f}},
};
static const struct expected_color
{
unsigned int x, y;
D3DCOLOR color;
}
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_local[] =
{
{160, 120, 0x00000000},
{320, 120, 0x00090909},
{480, 120, 0x00000000},
{160, 240, 0x00090909},
{320, 240, 0x00fafafa},
{480, 240, 0x00090909},
{160, 360, 0x00000000},
{320, 360, 0x00090909},
{480, 360, 0x00000000},
},
expected_spot_local[] =
{
{160, 120, 0x00000000},
{320, 120, 0x00020202},
{480, 120, 0x00000000},
{160, 240, 0x00020202},
{320, 240, 0x00fafafa},
{480, 240, 0x00020202},
{160, 360, 0x00000000},
{320, 360, 0x00020202},
{480, 360, 0x00000000},
},
expected_parallelpoint[] =
{
{160, 120, 0x00050505},
{320, 120, 0x002c2c2c},
{480, 120, 0x006e6e6e},
{160, 240, 0x00090909},
{320, 240, 0x00717171},
{480, 240, 0x00ffffff},
{160, 360, 0x00050505},
{320, 360, 0x002c2c2c},
{480, 360, 0x006e6e6e},
};
static const struct
{
D3DLIGHT2 *light;
const struct expected_color *expected;
unsigned int expected_count;
}
tests[] =
{
{&directional, expected_directional_local,
sizeof(expected_directional_local) / sizeof(expected_directional_local[0])},
{&point, expected_point_local,
sizeof(expected_point_local) / sizeof(expected_point_local[0])},
{&spot, expected_spot_local,
sizeof(expected_spot_local) / sizeof(expected_spot_local[0])},
{&parallelpoint, expected_parallelpoint,
sizeof(expected_parallelpoint) / sizeof(expected_parallelpoint[0])},
};
IDirect3D2 *d3d;
IDirect3DDevice2 *device;
IDirectDraw2 *ddraw;
IDirectDrawSurface *rt;
IDirect3DViewport2 *viewport;
IDirect3DMaterial2 *material, *background_material;
IDirect3DLight *light;
D3DMATERIALHANDLE mat_handle;
D3DCOLOR color;
ULONG refcount;
HWND window;
HRESULT hr;
unsigned int i, j, x, y;
D3DVERTEX *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)
{
U1(quad[i]).x = x * 2.0f / (vertices_side - 1) - 1.0f;
U2(quad[i]).y = y * 2.0f / (vertices_side - 1) - 1.0f;
U3(quad[i]).z = 1.0f;
U4(quad[i]).nx = 0.0f;
U5(quad[i]).ny = 0.0f;
U6(quad[i]).nz = -1.0f;
U7(quad[i]).tu = 0.0f;
U8(quad[i++]).tv = 0.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);
ddraw = create_ddraw();
ok(!!ddraw, "Failed to create a ddraw object.\n");
if (!(device = create_device(ddraw, window, DDSCL_NORMAL)))
{
skip("Failed to create a 3D device, skipping test.\n");
DestroyWindow(window);
return;
}
hr = IDirect3DDevice2_GetDirect3D(device, &d3d);
ok(SUCCEEDED(hr), "Failed to get D3D interface, hr %#x.\n", hr);
hr = IDirect3DDevice2_GetRenderTarget(device, &rt);
ok(SUCCEEDED(hr), "Failed to get render target, hr %#x.\n", hr);
viewport = create_viewport(device, 0, 0, 640, 480);
hr = IDirect3DDevice2_SetCurrentViewport(device, viewport);
ok(SUCCEEDED(hr), "Failed to set current viewport, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_WORLD, &mat);
ok(SUCCEEDED(hr), "Failed to set world transform, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_VIEW, &mat);
ok(SUCCEEDED(hr), "Failed to set view transform, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetTransform(device, D3DTRANSFORMSTATE_PROJECTION, &mat);
ok(SUCCEEDED(hr), "Failed to set projection transform, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_CLIPPING, FALSE);
ok(SUCCEEDED(hr), "Failed to disable clipping, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_ZENABLE, FALSE);
ok(SUCCEEDED(hr), "Failed to disable z-buffering, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
background_material = create_diffuse_material(device, 1.0f, 1.0f, 1.0f, 1.0f);
viewport_set_background(device, viewport, background_material);
material = create_specular_material(device, 1.0f, 1.0f, 1.0f, 1.0f, 30.0f);
hr = IDirect3DMaterial2_GetHandle(material, device, &mat_handle);
ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
hr = IDirect3DDevice2_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
hr = IDirect3D2_CreateLight(d3d, &light, NULL);
ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
hr = IDirect3DViewport2_AddLight(viewport, light);
ok(SUCCEEDED(hr), "Failed to add a light to the viewport, hr %#x.\n", hr);
hr = IDirect3DDevice2_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)
{
tests[i].light->dwFlags = D3DLIGHT_ACTIVE;
hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)tests[i].light);
ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
hr = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
hr = IDirect3DDevice2_BeginScene(device);
ok(SUCCEEDED(hr), "Failed to begin scene, hr %#x.\n", hr);
hr = IDirect3DDevice2_DrawIndexedPrimitive(device, D3DPT_TRIANGLELIST, D3DVT_VERTEX,
quad, vertices_side * vertices_side, indices, indices_count, 0);
ok(SUCCEEDED(hr), "Failed to draw, hr %#x.\n", hr);
hr = IDirect3DDevice2_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);
}
}
hr = IDirect3DViewport2_DeleteLight(viewport, light);
ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
IDirect3DLight_Release(light);
destroy_material(material);
destroy_material(background_material);
destroy_viewport(device, viewport);
IDirectDrawSurface2_Release(rt);
refcount = IDirect3DDevice2_Release(device);
ok(!refcount, "Device has %u references left.\n", refcount);
IDirect3D2_Release(d3d);
refcount = IDirectDraw2_Release(ddraw);
ok(!refcount, "Ddraw object has %u references left.\n", refcount);
DestroyWindow(window);
HeapFree(GetProcessHeap(), 0, indices);
HeapFree(GetProcessHeap(), 0, quad);
}
static void test_palette_gdi(void)
{
IDirectDrawSurface *surface, *primary;
@ -8221,6 +8502,7 @@ START_TEST(ddraw2)
test_p8_rgb_blit();
test_material();
test_lighting();
test_specular_lighting();
test_palette_gdi();
test_palette_alpha();
test_lost_device();