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

Matteo Bruni mbruni at codeweavers.com
Sun Apr 9 14:03:38 CDT 2017


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

I don't really like the shader_glsl_ffp_vertex_lighting_footer name but I
couldn't think of anything nicer...

 dlls/d3d8/tests/visual.c   | 59 +++++++++++++++++++++++++++++++++-------------
 dlls/d3d9/tests/visual.c   | 59 +++++++++++++++++++++++++++++++++-------------
 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, 225 insertions(+), 102 deletions(-)

diff --git a/dlls/d3d8/tests/visual.c b/dlls/d3d8/tests/visual.c
index d314edb..9a1b28c 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, 0.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,6 +764,15 @@ 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);
 
+        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, 0xffffffff, 0.0, 0);
         ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
 
diff --git a/dlls/d3d9/tests/visual.c b/dlls/d3d9/tests/visual.c
index 5f96cc3..700960b 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, 0.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,6 +855,15 @@ 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);
 
+        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, 0xffffffff, 0.0, 0);
         ok(SUCCEEDED(hr), "Failed to clear, hr %#x.\n", hr);
 
diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c
index be950d8..59e073b 100644
--- a/dlls/ddraw/tests/ddraw2.c
+++ b/dlls/ddraw/tests/ddraw2.c
@@ -7104,6 +7104,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
     {
@@ -7157,23 +7168,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;
@@ -7257,12 +7283,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);
@@ -7277,6 +7297,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);
 
@@ -7298,12 +7324,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 2f92a70..90face2 100644
--- a/dlls/ddraw/tests/ddraw4.c
+++ b/dlls/ddraw/tests/ddraw4.c
@@ -4156,6 +4156,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
     {
@@ -4209,11 +4220,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;
     }
@@ -4221,16 +4245,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;
@@ -4310,12 +4336,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);
@@ -4333,6 +4353,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);
 
@@ -4354,12 +4380,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 6a35cb8..c9248cb 100644
--- a/dlls/ddraw/tests/ddraw7.c
+++ b/dlls/ddraw/tests/ddraw7.c
@@ -3829,6 +3829,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
     {
@@ -3918,30 +3930,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;
@@ -4010,15 +4037,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);
@@ -4032,6 +4050,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 c8a970f..7c657bc 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -7624,6 +7624,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)
 {
@@ -7676,14 +7689,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");
     }
@@ -7725,14 +7731,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");
     }
@@ -7742,17 +7741,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)
@@ -7760,12 +7751,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