[PATCH v2 5/6] wined3d: Fix specular lighting calculation.

Matteo Bruni mbruni at codeweavers.com
Sun May 7 13:32:37 CDT 2017


Signed-off-by: Matteo Bruni <mbruni at codeweavers.com>
---
For bug 41827.

v2: Use non-zero attenuation in the d3d8 and d3d9 tests, change the
clear color to make it plain obvious if drawing for some reason fails.

 dlls/d3d8/tests/visual.c   | 61 +++++++++++++++++++++++++++++++++-------------
 dlls/d3d9/tests/visual.c   | 61 +++++++++++++++++++++++++++++++++-------------
 dlls/ddraw/tests/ddraw2.c  | 49 ++++++++++++++++++++++++++++---------
 dlls/ddraw/tests/ddraw4.c  | 51 +++++++++++++++++++++++++++++---------
 dlls/ddraw/tests/ddraw7.c  | 59 ++++++++++++++++++++++++++++++++------------
 dlls/wined3d/glsl_shader.c | 50 +++++++++++++++----------------------
 6 files changed, 227 insertions(+), 104 deletions(-)

diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c
index 14eb6ea..5ff96d4 100644
--- a/dlls/d3d8/tests/visual.c
+++ b/dlls/d3d8/tests/visual.c
@@ -543,6 +543,18 @@ static void test_specular_lighting(void)
         1.2f,
         0.0f,
         0.0f, 0.0f, 1.0f,
+    },
+    point_side =
+    {
+        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},
+        {-1.1f, 0.0f, 1.1f},
+        {0.0f, 0.0f, 0.0f},
+        100.0f,
+        0.0f,
+        0.0f, 0.0f, 1.0f,
     };
     static const struct expected_color
     {
@@ -632,30 +644,45 @@ static void test_specular_lighting(void)
         {160, 360, 0x00000000},
         {320, 360, 0x005a5a5a},
         {480, 360, 0x00000000},
+    },
+    expected_point_side[] =
+    {
+        {160, 120, 0x00000000},
+        {320, 120, 0x00000000},
+        {480, 120, 0x00000000},
+        {160, 240, 0x00000000},
+        {320, 240, 0x00000000},
+        {480, 240, 0x00000000},
+        {160, 360, 0x00000000},
+        {320, 360, 0x00000000},
+        {480, 360, 0x00000000},
     };
     static const struct
     {
         const D3DLIGHT8 *light;
         BOOL local_viewer;
+        float specular_power;
         const struct expected_color *expected;
         unsigned int expected_count;
     }
     tests[] =
     {
-        {&directional, FALSE, expected_directional,
+        {&directional, FALSE, 30.0f, expected_directional,
                 sizeof(expected_directional) / sizeof(expected_directional[0])},
-        {&directional, TRUE, expected_directional_local,
+        {&directional, TRUE, 30.0f, expected_directional_local,
                 sizeof(expected_directional_local) / sizeof(expected_directional_local[0])},
-        {&point, FALSE, expected_point,
+        {&point, FALSE, 30.0f, expected_point,
                 sizeof(expected_point) / sizeof(expected_point[0])},
-        {&point, TRUE, expected_point_local,
+        {&point, TRUE, 30.0f, expected_point_local,
                 sizeof(expected_point_local) / sizeof(expected_point_local[0])},
-        {&spot, FALSE, expected_spot,
+        {&spot, FALSE, 30.0f, expected_spot,
                 sizeof(expected_spot) / sizeof(expected_spot[0])},
-        {&spot, TRUE, expected_spot_local,
+        {&spot, TRUE, 30.0f, expected_spot_local,
                 sizeof(expected_spot_local) / sizeof(expected_spot_local[0])},
-        {&point_range, FALSE, expected_point_range,
+        {&point_range, FALSE, 30.0f, expected_point_range,
                 sizeof(expected_point_range) / sizeof(expected_point_range[0])},
+        {&point_side, TRUE, 0.0f, expected_point_side,
+                sizeof(expected_point_side) / sizeof(expected_point_side[0])},
     };
     IDirect3DDevice8 *device;
     D3DMATERIAL8 material;
@@ -724,15 +751,6 @@ static void test_specular_lighting(void)
     hr = IDirect3DDevice8_SetVertexShader(device, fvf);
     ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
 
-    memset(&material, 0, sizeof(material));
-    material.Specular.r = 1.0f;
-    material.Specular.g = 1.0f;
-    material.Specular.b = 1.0f;
-    material.Specular.a = 1.0f;
-    material.Power = 30.0f;
-    hr = IDirect3DDevice8_SetMaterial(device, &material);
-    ok(SUCCEEDED(hr), "Failed to set material, hr %#x.\n", hr);
-
     hr = IDirect3DDevice8_LightEnable(device, 0, TRUE);
     ok(SUCCEEDED(hr), "Failed to enable light 0, hr %#x.\n", hr);
     hr = IDirect3DDevice8_SetRenderState(device, D3DRS_SPECULARENABLE, TRUE);
@@ -746,7 +764,16 @@ static void test_specular_lighting(void)
         hr = IDirect3DDevice8_SetRenderState(device, D3DRS_LOCALVIEWER, tests[i].local_viewer);
         ok(SUCCEEDED(hr), "Failed to set local viewer state, hr %#x.\n", hr);
 
-        hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
+        memset(&material, 0, sizeof(material));
+        material.Specular.r = 1.0f;
+        material.Specular.g = 1.0f;
+        material.Specular.b = 1.0f;
+        material.Specular.a = 1.0f;
+        material.Power = tests[i].specular_power;
+        hr = IDirect3DDevice8_SetMaterial(device, &material);
+        ok(SUCCEEDED(hr), "Failed to set material, hr %#x.\n", hr);
+
+        hr = IDirect3DDevice8_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
         ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
 
         hr = IDirect3DDevice8_BeginScene(device);
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index 25aa35b..c8a6a1f 100644
--- a/dlls/d3d9/tests/visual.c
+++ b/dlls/d3d9/tests/visual.c
@@ -634,6 +634,18 @@ static void test_specular_lighting(void)
         1.2f,
         0.0f,
         0.0f, 0.0f, 1.0f,
+    },
+    point_side =
+    {
+        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},
+        {-1.1f, 0.0f, 1.1f},
+        {0.0f, 0.0f, 0.0f},
+        100.0f,
+        0.0f,
+        0.0f, 0.0f, 1.0f,
     };
     static const struct expected_color
     {
@@ -723,30 +735,45 @@ static void test_specular_lighting(void)
         {160, 360, 0x00000000},
         {320, 360, 0x005a5a5a},
         {480, 360, 0x00000000},
+    },
+    expected_point_side[] =
+    {
+        {160, 120, 0x00000000},
+        {320, 120, 0x00000000},
+        {480, 120, 0x00000000},
+        {160, 240, 0x00000000},
+        {320, 240, 0x00000000},
+        {480, 240, 0x00000000},
+        {160, 360, 0x00000000},
+        {320, 360, 0x00000000},
+        {480, 360, 0x00000000},
     };
     static const struct
     {
         const D3DLIGHT9 *light;
         BOOL local_viewer;
+        float specular_power;
         const struct expected_color *expected;
         unsigned int expected_count;
     }
     tests[] =
     {
-        {&directional, FALSE, expected_directional,
+        {&directional, FALSE, 30.0f, expected_directional,
                 sizeof(expected_directional) / sizeof(expected_directional[0])},
-        {&directional, TRUE, expected_directional_local,
+        {&directional, TRUE, 30.0f, expected_directional_local,
                 sizeof(expected_directional_local) / sizeof(expected_directional_local[0])},
-        {&point, FALSE, expected_point,
+        {&point, FALSE, 30.0f, expected_point,
                 sizeof(expected_point) / sizeof(expected_point[0])},
-        {&point, TRUE, expected_point_local,
+        {&point, TRUE, 30.0f, expected_point_local,
                 sizeof(expected_point_local) / sizeof(expected_point_local[0])},
-        {&spot, FALSE, expected_spot,
+        {&spot, FALSE, 30.0f, expected_spot,
                 sizeof(expected_spot) / sizeof(expected_spot[0])},
-        {&spot, TRUE, expected_spot_local,
+        {&spot, TRUE, 30.0f, expected_spot_local,
                 sizeof(expected_spot_local) / sizeof(expected_spot_local[0])},
-        {&point_range, FALSE, expected_point_range,
+        {&point_range, FALSE, 30.0f, expected_point_range,
                 sizeof(expected_point_range) / sizeof(expected_point_range[0])},
+        {&point_side, TRUE, 0.0f, expected_point_side,
+                sizeof(expected_point_side) / sizeof(expected_point_side[0])},
     };
     IDirect3DDevice9 *device;
     D3DMATERIAL9 material;
@@ -815,15 +842,6 @@ static void test_specular_lighting(void)
     hr = IDirect3DDevice9_SetFVF(device, fvf);
     ok(SUCCEEDED(hr), "Failed to set FVF, hr %#x.\n", hr);
 
-    memset(&material, 0, sizeof(material));
-    material.Specular.r = 1.0f;
-    material.Specular.g = 1.0f;
-    material.Specular.b = 1.0f;
-    material.Specular.a = 1.0f;
-    material.Power = 30.0f;
-    hr = IDirect3DDevice9_SetMaterial(device, &material);
-    ok(SUCCEEDED(hr), "Failed to set material, hr %#x.\n", hr);
-
     hr = IDirect3DDevice9_LightEnable(device, 0, TRUE);
     ok(SUCCEEDED(hr), "Failed to enable light 0, hr %#x.\n", hr);
     hr = IDirect3DDevice9_SetRenderState(device, D3DRS_SPECULARENABLE, TRUE);
@@ -837,7 +855,16 @@ static void test_specular_lighting(void)
         hr = IDirect3DDevice9_SetRenderState(device, D3DRS_LOCALVIEWER, tests[i].local_viewer);
         ok(SUCCEEDED(hr), "Failed to set local viewer state, hr %#x.\n", hr);
 
-        hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xffffffff, 0.0, 0);
+        memset(&material, 0, sizeof(material));
+        material.Specular.r = 1.0f;
+        material.Specular.g = 1.0f;
+        material.Specular.b = 1.0f;
+        material.Specular.a = 1.0f;
+        material.Power = tests[i].specular_power;
+        hr = IDirect3DDevice9_SetMaterial(device, &material);
+        ok(SUCCEEDED(hr), "Failed to set material, hr %#x.\n", hr);
+
+        hr = IDirect3DDevice9_Clear(device, 0, NULL, D3DCLEAR_TARGET, 0xff00ff00, 0.0, 0);
         ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
 
         hr = IDirect3DDevice9_BeginScene(device);
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index f81a296..f81be7f 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -7090,6 +7090,17 @@ static void test_specular_lighting(void)
         {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
         {{0.5f}, {0.0f}, {-1.0f}},
         {{0.0f}, {0.0f}, {0.0f}},
+    },
+    point_side =
+    {
+        sizeof(D3DLIGHT2),
+        D3DLIGHT_POINT,
+        {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
+        {{-1.1f}, {0.0f}, {1.1f}},
+        {{0.0f}, {0.0f}, {0.0f}},
+        100.0f,
+        0.0f,
+        1.0f, 0.0f, 0.0f,
     };
     static const struct expected_color
     {
@@ -7143,23 +7154,38 @@ static void test_specular_lighting(void)
         {160, 360, 0x00050505},
         {320, 360, 0x002c2c2c},
         {480, 360, 0x006e6e6e},
+    },
+    expected_point_side[] =
+    {
+        {160, 120, 0x00000000},
+        {320, 120, 0x00000000},
+        {480, 120, 0x00000000},
+        {160, 240, 0x00000000},
+        {320, 240, 0x00000000},
+        {480, 240, 0x00000000},
+        {160, 360, 0x00000000},
+        {320, 360, 0x00000000},
+        {480, 360, 0x00000000},
     };
     static const struct
     {
         D3DLIGHT2 *light;
+        float specular_power;
         const struct expected_color *expected;
         unsigned int expected_count;
     }
     tests[] =
     {
-        {&directional, expected_directional_local,
+        {&directional, 30.0f, expected_directional_local,
                 sizeof(expected_directional_local) / sizeof(expected_directional_local[0])},
-        {&point, expected_point_local,
+        {&point, 30.0f, expected_point_local,
                 sizeof(expected_point_local) / sizeof(expected_point_local[0])},
-        {&spot, expected_spot_local,
+        {&spot, 30.0f, expected_spot_local,
                 sizeof(expected_spot_local) / sizeof(expected_spot_local[0])},
-        {&parallelpoint, expected_parallelpoint,
+        {&parallelpoint, 30.0f, expected_parallelpoint,
                 sizeof(expected_parallelpoint) / sizeof(expected_parallelpoint[0])},
+        {&point_side, 0.0f, expected_point_side,
+                sizeof(expected_point_side) / sizeof(expected_point_side[0])},
     };
     IDirect3D2 *d3d;
     IDirect3DDevice2 *device;
@@ -7242,12 +7268,6 @@ static void test_specular_lighting(void)
     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);
@@ -7262,6 +7282,12 @@ static void test_specular_lighting(void)
         hr = IDirect3DLight_SetLight(light, (D3DLIGHT *)tests[i].light);
         ok(SUCCEEDED(hr), "Failed to set light, hr %#x.\n", hr);
 
+        material = create_specular_material(device, 1.0f, 1.0f, 1.0f, 1.0f, tests[i].specular_power);
+        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 = IDirect3DViewport2_Clear(viewport, 1, &clear_rect, D3DCLEAR_TARGET);
         ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
 
@@ -7283,12 +7309,13 @@ static void test_specular_lighting(void)
                     tests[i].expected[j].color, tests[i].expected[j].x,
                     tests[i].expected[j].y, color, i);
         }
+
+        destroy_material(material);
     }
 
     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);
diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c
index f25b327..47b94f7 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -4145,6 +4145,17 @@ static void test_specular_lighting(void)
         {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
         {{0.5f}, {0.0f}, {-1.0f}},
         {{0.0f}, {0.0f}, {0.0f}},
+    },
+    point_side =
+    {
+        sizeof(D3DLIGHT2),
+        D3DLIGHT_POINT,
+        {{1.0f}, {1.0f}, {1.0f}, {0.0f}},
+        {{-1.1f}, {0.0f}, {1.1f}},
+        {{0.0f}, {0.0f}, {0.0f}},
+        100.0f,
+        0.0f,
+        1.0f, 0.0f, 0.0f,
     };
     static const struct expected_color
     {
@@ -4198,11 +4209,24 @@ static void test_specular_lighting(void)
         {160, 360, 0x00050505},
         {320, 360, 0x002c2c2c},
         {480, 360, 0x006e6e6e},
+    },
+    expected_point_side[] =
+    {
+        {160, 120, 0x00000000},
+        {320, 120, 0x00000000},
+        {480, 120, 0x00000000},
+        {160, 240, 0x00000000},
+        {320, 240, 0x00000000},
+        {480, 240, 0x00000000},
+        {160, 360, 0x00000000},
+        {320, 360, 0x00000000},
+        {480, 360, 0x00000000},
     };
     static const struct
     {
         D3DLIGHT2 *light;
         BOOL local_viewer;
+        float specular_power;
         const struct expected_color *expected;
         unsigned int expected_count;
     }
@@ -4210,16 +4234,18 @@ static void test_specular_lighting(void)
     {
         /* D3DRENDERSTATE_LOCALVIEWER does not exist in D3D < 7 (the behavior is
          * the one you get on newer D3D versions with it set as TRUE). */
-        {&directional, FALSE, expected_directional,
+        {&directional, FALSE, 30.0f, expected_directional,
                 sizeof(expected_directional) / sizeof(expected_directional[0])},
-        {&directional, TRUE, expected_directional,
+        {&directional, TRUE, 30.0f, expected_directional,
                 sizeof(expected_directional) / sizeof(expected_directional[0])},
-        {&point, TRUE, expected_point,
+        {&point, TRUE, 30.0f, expected_point,
                 sizeof(expected_point) / sizeof(expected_point[0])},
-        {&spot, TRUE, expected_spot,
+        {&spot, TRUE, 30.0f, expected_spot,
                 sizeof(expected_spot) / sizeof(expected_spot[0])},
-        {&parallelpoint, TRUE, expected_parallelpoint,
+        {&parallelpoint, TRUE, 30.0f, expected_parallelpoint,
                 sizeof(expected_parallelpoint) / sizeof(expected_parallelpoint[0])},
+        {&point_side, TRUE, 0.0f, expected_point_side,
+                sizeof(expected_point_side) / sizeof(expected_point_side[0])},
     };
     IDirect3D3 *d3d;
     IDirect3DDevice3 *device;
@@ -4298,12 +4324,6 @@ static void test_specular_lighting(void)
     hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
     ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
 
-    material = create_specular_material(device, 1.0f, 1.0f, 1.0f, 1.0f, 30.0f);
-    hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
-    ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
-    hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
-    ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
-
     hr = IDirect3D3_CreateLight(d3d, &light, NULL);
     ok(SUCCEEDED(hr), "Failed to create a light object, hr %#x.\n", hr);
     hr = IDirect3DViewport3_AddLight(viewport, light);
@@ -4321,6 +4341,12 @@ static void test_specular_lighting(void)
         hr = IDirect3DDevice3_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
         ok(SUCCEEDED(hr), "Failed to set local viewer state, hr %#x.\n", hr);
 
+        material = create_specular_material(device, 1.0f, 1.0f, 1.0f, 1.0f, tests[i].specular_power);
+        hr = IDirect3DMaterial3_GetHandle(material, device, &mat_handle);
+        ok(SUCCEEDED(hr), "Failed to get material handle, hr %#x.\n", hr);
+        hr = IDirect3DDevice3_SetLightState(device, D3DLIGHTSTATE_MATERIAL, mat_handle);
+        ok(SUCCEEDED(hr), "Failed to set material state, hr %#x.\n", hr);
+
         hr = IDirect3DViewport3_Clear2(viewport, 1, &clear_rect, D3DCLEAR_TARGET, 0xffffffff, 0.0f, 0);
         ok(SUCCEEDED(hr), "Failed to clear viewport, hr %#x.\n", hr);
 
@@ -4342,12 +4368,13 @@ static void test_specular_lighting(void)
                     tests[i].expected[j].color, tests[i].expected[j].x,
                     tests[i].expected[j].y, color, i);
         }
+
+        destroy_material(material);
     }
 
     hr = IDirect3DViewport3_DeleteLight(viewport, light);
     ok(SUCCEEDED(hr), "Failed to remove a light from the viewport, hr %#x.\n", hr);
     IDirect3DLight_Release(light);
-    destroy_material(material);
     IDirect3DViewport3_Release(viewport);
     IDirectDrawSurface4_Release(rt);
     refcount = IDirect3DDevice3_Release(device);
diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c
index 354e872..00c7919 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -3818,6 +3818,18 @@ static void test_specular_lighting(void)
         1.2f,
         0.0f,
         0.0f, 0.0f, 1.0f,
+    },
+    point_side =
+    {
+        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}},
+        {{-1.1f}, {0.0f}, {1.1f}},
+        {{0.0f}, {0.0f}, {0.0f}},
+        100.0f,
+        0.0f,
+        1.0f, 0.0f, 0.0f,
     };
     static const struct expected_color
     {
@@ -3907,30 +3919,45 @@ static void test_specular_lighting(void)
         {160, 360, 0x00000000},
         {320, 360, 0x005a5a5a},
         {480, 360, 0x00000000},
+    },
+    expected_point_side[] =
+    {
+        {160, 120, 0x00000000},
+        {320, 120, 0x00000000},
+        {480, 120, 0x00000000},
+        {160, 240, 0x00000000},
+        {320, 240, 0x00000000},
+        {480, 240, 0x00000000},
+        {160, 360, 0x00000000},
+        {320, 360, 0x00000000},
+        {480, 360, 0x00000000},
     };
     static const struct
     {
         D3DLIGHT7 *light;
         BOOL local_viewer;
+        float specular_power;
         const struct expected_color *expected;
         unsigned int expected_count;
     }
     tests[] =
     {
-        {&directional, FALSE, expected_directional,
+        {&directional, FALSE, 30.0f, expected_directional,
                 sizeof(expected_directional) / sizeof(expected_directional[0])},
-        {&directional, TRUE, expected_directional_local,
+        {&directional, TRUE, 30.0f, expected_directional_local,
                 sizeof(expected_directional_local) / sizeof(expected_directional_local[0])},
-        {&point, FALSE, expected_point,
+        {&point, FALSE, 30.0f, expected_point,
                 sizeof(expected_point) / sizeof(expected_point[0])},
-        {&point, TRUE, expected_point_local,
+        {&point, TRUE, 30.0f, expected_point_local,
                 sizeof(expected_point_local) / sizeof(expected_point_local[0])},
-        {&spot, FALSE, expected_spot,
+        {&spot, FALSE, 30.0f, expected_spot,
                 sizeof(expected_spot) / sizeof(expected_spot[0])},
-        {&spot, TRUE, expected_spot_local,
+        {&spot, TRUE, 30.0f, expected_spot_local,
                 sizeof(expected_spot_local) / sizeof(expected_spot_local[0])},
-        {&point_range, FALSE, expected_point_range,
+        {&point_range, FALSE, 30.0f, expected_point_range,
                 sizeof(expected_point_range) / sizeof(expected_point_range[0])},
+        {&point_side, TRUE, 0.0f, expected_point_side,
+                sizeof(expected_point_side) / sizeof(expected_point_side[0])},
     };
     IDirect3DDevice7 *device;
     IDirectDrawSurface7 *rt;
@@ -3998,15 +4025,6 @@ static void test_specular_lighting(void)
     hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_FOGENABLE, FALSE);
     ok(SUCCEEDED(hr), "Failed to disable fog, hr %#x.\n", hr);
 
-    memset(&material, 0, sizeof(material));
-    U1(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);
@@ -4020,6 +4038,15 @@ static void test_specular_lighting(void)
         hr = IDirect3DDevice7_SetRenderState(device, D3DRENDERSTATE_LOCALVIEWER, tests[i].local_viewer);
         ok(SUCCEEDED(hr), "Failed to set local viewer state, hr %#x.\n", hr);
 
+        memset(&material, 0, sizeof(material));
+        U1(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 = tests[i].specular_power;
+        hr = IDirect3DDevice7_SetMaterial(device, &material);
+        ok(SUCCEEDED(hr), "Failed to set material, 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);
 
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index e6cbf1b..dfbe46d 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -7672,6 +7672,19 @@ static const char *shader_glsl_ffp_mcs(enum wined3d_material_color_source mcs, c
     }
 }
 
+static void shader_glsl_ffp_vertex_lighting_footer(struct wined3d_string_buffer *buffer,
+        const struct wined3d_ffp_vs_settings *settings, unsigned int idx)
+{
+    shader_addline(buffer, "diffuse += clamp(dot(dir, normal), 0.0, 1.0)"
+            " * ffp_light[%u].diffuse.xyz * att;\n", idx);
+    if (settings->localviewer)
+        shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
+    else
+        shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, -1.0)));\n");
+    shader_addline(buffer, "if (dot(dir, normal) > 0.0 && t > 0.0) specular +="
+            " pow(t, ffp_material.shininess) * ffp_light[%u].specular * att;\n", idx);
+}
+
 static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer,
         const struct wined3d_ffp_vs_settings *settings, BOOL legacy_lighting)
 {
@@ -7724,14 +7737,7 @@ static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer
             continue;
         }
         shader_addline(buffer, "dir = normalize(dir);\n");
-        shader_addline(buffer, "diffuse += (clamp(dot(dir, normal), 0.0, 1.0)"
-                " * ffp_light[%u].diffuse.xyz) * att;\n", idx);
-        if (settings->localviewer)
-            shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
-        else
-            shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, -1.0)));\n");
-        shader_addline(buffer, "if (t > 0.0) specular += (pow(t, ffp_material.shininess)"
-                " * ffp_light[%u].specular) * att;\n", idx);
+        shader_glsl_ffp_vertex_lighting_footer(buffer, settings, i);
         if (!legacy_lighting)
             shader_addline(buffer, "}\n");
     }
@@ -7773,14 +7779,7 @@ static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer
                 shader_addline(buffer, "}\n");
             continue;
         }
-        shader_addline(buffer, "diffuse += (clamp(dot(dir, normal), 0.0, 1.0)"
-                " * ffp_light[%u].diffuse.xyz) * att;\n", idx);
-        if (settings->localviewer)
-            shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
-        else
-            shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, -1.0)));\n");
-        shader_addline(buffer, "if (t > 0.0) specular += (pow(t, ffp_material.shininess)"
-                " * ffp_light[%u].specular) * att;\n", idx);
+        shader_glsl_ffp_vertex_lighting_footer(buffer, settings, i);
         if (!legacy_lighting)
             shader_addline(buffer, "}\n");
     }
@@ -7790,17 +7789,9 @@ static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer
         shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz;\n", idx);
         if (!settings->normal)
             continue;
+        shader_addline(buffer, "att = 1.0;\n");
         shader_addline(buffer, "dir = normalize(ffp_light[%u].direction.xyz);\n", idx);
-        shader_addline(buffer, "diffuse += clamp(dot(dir, normal), 0.0, 1.0)"
-                " * ffp_light[%u].diffuse.xyz;\n", idx);
-        /* TODO: In the non-local viewer case the halfvector is constant
-         * and could be precomputed and stored in a uniform. */
-        if (settings->localviewer)
-            shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
-        else
-            shader_addline(buffer, "t = dot(normal, normalize(dir + vec3(0.0, 0.0, -1.0)));\n");
-        shader_addline(buffer, "if (t > 0.0) specular += pow(t, ffp_material.shininess)"
-                " * ffp_light[%u].specular;\n", idx);
+        shader_glsl_ffp_vertex_lighting_footer(buffer, settings, i);
     }
 
     for (i = 0; i < settings->parallel_point_light_count; ++i, ++idx)
@@ -7808,12 +7799,9 @@ static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer
         shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz;\n", idx);
         if (!settings->normal)
             continue;
+        shader_addline(buffer, "att = 1.0;\n");
         shader_addline(buffer, "dir = normalize(ffp_light[%u].position.xyz);\n", idx);
-        shader_addline(buffer, "diffuse += clamp(dot(dir, normal), 0.0, 1.0)"
-                " * ffp_light[%u].diffuse.xyz;\n", idx);
-        shader_addline(buffer, "t = dot(normal, normalize(dir - normalize(ec_pos.xyz)));\n");
-        shader_addline(buffer, "if (t > 0.0) specular += pow(t, ffp_material.shininess)"
-                " * ffp_light[%u].specular;\n", idx);
+        shader_glsl_ffp_vertex_lighting_footer(buffer, settings, i);
     }
 
     shader_addline(buffer, "ffp_varying_diffuse.xyz = %s.xyz * ambient + %s.xyz * diffuse + %s.xyz;\n",
-- 
2.10.2




More information about the wine-patches mailing list