[PATCH 2/5] wined3d: Implement legacy light attenuation behavior in the GLSL vertex ffp.

Matteo Bruni mbruni at codeweavers.com
Thu Apr 30 16:22:16 CDT 2015


---
 dlls/wined3d/glsl_shader.c | 66 ++++++++++++++++++++++++++++++++++------------
 1 file changed, 49 insertions(+), 17 deletions(-)

diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 19c3d31..909b158 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -106,6 +106,7 @@ struct shader_glsl_priv {
     struct wine_rb_tree ffp_vertex_shaders;
     struct wine_rb_tree ffp_fragment_shaders;
     BOOL ffp_proj_control;
+    BOOL legacy_lighting;
 };
 
 struct glsl_vs_program
@@ -5404,7 +5405,8 @@ static const char *shader_glsl_ffp_mcs(enum wined3d_material_color_source mcs, c
 }
 
 static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer,
-        const struct wined3d_ffp_vs_settings *settings, const struct wined3d_gl_info *gl_info)
+        const struct wined3d_ffp_vs_settings *settings, const struct wined3d_gl_info *gl_info,
+        BOOL legacy_lighting)
 {
     const char *diffuse, *specular, *emission, *ambient;
     enum wined3d_light_type light_type;
@@ -5438,25 +5440,37 @@ static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer
                 shader_addline(buffer, "dst.z = dot(dir, dir);\n");
                 shader_addline(buffer, "dst.y = sqrt(dst.z);\n");
                 shader_addline(buffer, "dst.x = 1.0;\n");
-                shader_addline(buffer, "if (dst.y <= ffp_light[%u].range)\n{\n", i);
+                if (legacy_lighting)
+                {
+                    shader_addline(buffer, "dst.y = (ffp_light[%u].range - dst.y) / ffp_light[%u].range;\n", i, i);
+                    shader_addline(buffer, "dst.z = dst.y * dst.y;\n");
+                }
+                else
+                {
+                    shader_addline(buffer, "if (dst.y <= ffp_light[%u].range)\n{\n", i);
+                }
                 shader_addline(buffer, "att = dot(dst.xyz, vec3(ffp_light[%u].c_att,"
                         " ffp_light[%u].l_att, ffp_light[%u].q_att));\n", i, i, i);
-                shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz / att;\n", i);
+                if (!legacy_lighting)
+                    shader_addline(buffer, "att = 1.0 / att;");
+                shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz * att;\n", i);
                 if (!settings->normal)
                 {
-                    shader_addline(buffer, "}\n");
+                    if (!legacy_lighting)
+                        shader_addline(buffer, "}\n");
                     break;
                 }
                 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", i);
+                        " * ffp_light[%u].diffuse.xyz) * att;\n", i);
                 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", i);
-                shader_addline(buffer, "}\n");
+                        " * ffp_light[%u].specular) * att;\n", i);
+                if (!legacy_lighting)
+                    shader_addline(buffer, "}\n");
                 break;
 
             case WINED3D_LIGHT_SPOT:
@@ -5464,20 +5478,35 @@ static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer
                 shader_addline(buffer, "dst.z = dot(dir, dir);\n");
                 shader_addline(buffer, "dst.y = sqrt(dst.z);\n");
                 shader_addline(buffer, "dst.x = 1.0;\n");
-                shader_addline(buffer, "if (dst.y <= ffp_light[%u].range)\n{\n", i);
+                if (legacy_lighting)
+                {
+                    shader_addline(buffer, "dst.y = (ffp_light[%u].range - dst.y) / ffp_light[%u].range;\n", i, i);
+                    shader_addline(buffer, "dst.z = dst.y * dst.y;\n");
+                }
+                else
+                {
+                    shader_addline(buffer, "if (dst.y <= ffp_light[%u].range)\n{\n", i);
+                }
                 shader_addline(buffer, "dir = normalize(dir);\n");
                 shader_addline(buffer, "t = dot(-dir, normalize(ffp_light[%u].direction));\n", i);
                 shader_addline(buffer, "if (t > ffp_light[%u].cos_htheta) att = 1.0;\n", i);
                 shader_addline(buffer, "else if (t <= ffp_light[%u].cos_hphi) att = 0.0;\n", i);
                 shader_addline(buffer, "else att = pow((t - ffp_light[%u].cos_hphi)"
-                        " / (ffp_light[%u].cos_htheta - ffp_light[%u].cos_hphi), ffp_light[%u].falloff)"
-                        " / dot(dst.xyz, vec3(ffp_light[%u].c_att,"
-                        " ffp_light[%u].l_att, ffp_light[%u].q_att));\n",
-                        i, i, i, i, i, i, i);
+                        " / (ffp_light[%u].cos_htheta - ffp_light[%u].cos_hphi), ffp_light[%u].falloff);\n",
+                        i, i, i, i);
+                if (legacy_lighting)
+                    shader_addline(buffer, "att *= dot(dst.xyz, vec3(ffp_light[%u].c_att,"
+                            " ffp_light[%u].l_att, ffp_light[%u].q_att));\n",
+                            i, i, i);
+                else
+                    shader_addline(buffer, "att /= dot(dst.xyz, vec3(ffp_light[%u].c_att,"
+                            " ffp_light[%u].l_att, ffp_light[%u].q_att));\n",
+                            i, i, i);
                 shader_addline(buffer, "ambient += ffp_light[%u].ambient.xyz * att;\n", i);
                 if (!settings->normal)
                 {
-                    shader_addline(buffer, "}\n");
+                    if (!legacy_lighting)
+                        shader_addline(buffer, "}\n");
                     break;
                 }
                 shader_addline(buffer, "diffuse += (clamp(dot(dir, normal), 0.0, 1.0)"
@@ -5488,7 +5517,8 @@ static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer
                     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", i);
-                shader_addline(buffer, "}\n");
+                if (!legacy_lighting)
+                    shader_addline(buffer, "}\n");
                 break;
 
             case WINED3D_LIGHT_DIRECTIONAL:
@@ -5523,7 +5553,8 @@ static void shader_glsl_ffp_vertex_lighting(struct wined3d_string_buffer *buffer
 
 /* Context activation is done by the caller. */
 static GLuint shader_glsl_generate_ffp_vertex_shader(struct wined3d_string_buffer *buffer,
-        const struct wined3d_ffp_vs_settings *settings, const struct wined3d_gl_info *gl_info)
+        const struct wined3d_ffp_vs_settings *settings, const struct wined3d_gl_info *gl_info,
+        BOOL legacy_lighting)
 {
     GLuint shader_obj;
     unsigned int i;
@@ -5588,7 +5619,7 @@ static GLuint shader_glsl_generate_ffp_vertex_shader(struct wined3d_string_buffe
     else
         shader_addline(buffer, "vec3 normal = ffp_normal_matrix * gl_Normal;\n");
 
-    shader_glsl_ffp_vertex_lighting(buffer, settings, gl_info);
+    shader_glsl_ffp_vertex_lighting(buffer, settings, gl_info, legacy_lighting);
 
     for (i = 0; i < MAX_TEXTURES; ++i)
     {
@@ -6292,7 +6323,7 @@ static struct glsl_ffp_vertex_shader *shader_glsl_find_ffp_vertex_shader(struct
         return NULL;
 
     shader->desc.settings = *settings;
-    shader->id = shader_glsl_generate_ffp_vertex_shader(&priv->shader_buffer, settings, gl_info);
+    shader->id = shader_glsl_generate_ffp_vertex_shader(&priv->shader_buffer, settings, gl_info, priv->legacy_lighting);
     list_init(&shader->linked_programs);
     if (wine_rb_put(&priv->ffp_vertex_shaders, &shader->desc.settings, &shader->desc.entry) == -1)
         ERR("Failed to insert ffp vertex shader.\n");
@@ -7246,6 +7277,7 @@ static HRESULT shader_glsl_alloc(struct wined3d_device *device, const struct win
     priv->fragment_pipe = fragment_pipe;
     fragment_pipe->get_caps(gl_info, &fragment_caps);
     priv->ffp_proj_control = fragment_caps.wined3d_caps & WINED3D_FRAGMENT_CAP_PROJ_CONTROL;
+    priv->legacy_lighting = device->wined3d->flags & WINED3D_LEGACY_FFP_LIGHTING;
 
     device->vertex_priv = vertex_priv;
     device->fragment_priv = fragment_priv;
-- 
2.0.5




More information about the wine-patches mailing list