[PATCH 1/2] wined3d: Compute fog factor in process_vertices_strided().

Paul Gofman gofmanp at gmail.com
Mon Jun 10 05:11:49 CDT 2019


Signed-off-by: Paul Gofman <gofmanp at gmail.com>
---
 dlls/wined3d/device.c          | 127 +++++++++++++++++++++++++--------
 dlls/wined3d/wined3d_private.h |  13 ++++
 2 files changed, 111 insertions(+), 29 deletions(-)

diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index 0f9485aa6a..3d4914eb6a 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -58,16 +58,21 @@ struct lights_settings
     struct wined3d_color ambient_light;
     struct wined3d_matrix modelview_matrix;
     struct wined3d_matrix_3x3 normal_matrix;
+    struct wined3d_vec4 position_transformed;
+
+    float fog_start, fog_end, fog_density;
 
     uint32_t point_light_count          : 8;
     uint32_t spot_light_count           : 8;
     uint32_t directional_light_count    : 8;
     uint32_t parallel_point_light_count : 8;
-
+    uint32_t lighting                   : 1;
     uint32_t legacy_lighting            : 1;
     uint32_t normalise                  : 1;
     uint32_t localviewer                : 1;
-    uint32_t padding                    : 29;
+    uint32_t fog_coord_mode             : 2;
+    uint32_t fog_mode                   : 2;
+    uint32_t padding                    : 24;
 };
 
 /* Define the default light parameters as specified by MSDN. */
@@ -3269,7 +3274,7 @@ static void wined3d_color_rgb_mul_add(struct wined3d_color *dst, const struct wi
 }
 
 static void init_transformed_lights(struct lights_settings *ls,
-        const struct wined3d_state *state, BOOL legacy_lighting)
+        const struct wined3d_state *state, BOOL legacy_lighting, BOOL compute_lighting)
 {
     const struct wined3d_light_info *lights[WINED3D_MAX_SOFTWARE_ACTIVE_LIGHTS];
     const struct wined3d_light_info *light_info;
@@ -3280,15 +3285,30 @@ static void init_transformed_lights(struct lights_settings *ls,
 
     memset(ls, 0, sizeof(*ls));
 
-    wined3d_color_from_d3dcolor(&ls->ambient_light, state->render_states[WINED3D_RS_AMBIENT]);
-    ls->legacy_lighting = !!legacy_lighting;
-    ls->normalise = !!state->render_states[WINED3D_RS_NORMALIZENORMALS];
-    ls->localviewer = !!state->render_states[WINED3D_RS_LOCALVIEWER];
+    ls->lighting = !!compute_lighting;
+    ls->fog_mode = state->render_states[WINED3D_RS_FOGVERTEXMODE];
+    ls->fog_coord_mode = state->render_states[WINED3D_RS_RANGEFOGENABLE]
+            ? WINED3D_FFP_VS_FOG_RANGE : WINED3D_FFP_VS_FOG_DEPTH;
+    ls->fog_start = wined3d_get_float_state(state, WINED3D_RS_FOGSTART);
+    ls->fog_end = wined3d_get_float_state(state, WINED3D_RS_FOGEND);
+    ls->fog_density = wined3d_get_float_state(state, WINED3D_RS_FOGDENSITY);
+
+    if (ls->fog_mode == WINED3D_FOG_NONE && !compute_lighting)
+        return;
 
     multiply_matrix(&ls->modelview_matrix, &state->transforms[WINED3D_TS_VIEW],
             &state->transforms[WINED3D_TS_WORLD_MATRIX(0)]);
+
+    if (!compute_lighting)
+        return;
+
     compute_normal_matrix(&ls->normal_matrix._11, legacy_lighting, &ls->modelview_matrix);
 
+    wined3d_color_from_d3dcolor(&ls->ambient_light, state->render_states[WINED3D_RS_AMBIENT]);
+    ls->legacy_lighting = !!legacy_lighting;
+    ls->normalise = !!state->render_states[WINED3D_RS_NORMALIZENORMALS];
+    ls->localviewer = !!state->render_states[WINED3D_RS_LOCALVIEWER];
+
     for (i = 0, index = 0; i < LIGHTMAP_SIZE && index < ARRAY_SIZE(lights); ++i)
     {
         LIST_FOR_EACH_ENTRY(light_info, &state->light_state.light_map[i], struct wined3d_light_info, entry)
@@ -3430,21 +3450,28 @@ static void update_light_diffuse_specular(struct wined3d_color *diffuse, struct
         wined3d_color_rgb_mul_add(specular, &light->specular, att * powf(t, material_shininess));
 }
 
+static void light_set_vertex_data(struct lights_settings *ls,
+        const struct wined3d_vec4 *position)
+{
+    if (ls->fog_mode == WINED3D_FOG_NONE && !ls->lighting)
+        return;
+
+    wined3d_vec4_transform(&ls->position_transformed, position, &ls->modelview_matrix);
+    wined3d_vec3_scale((struct wined3d_vec3 *)&ls->position_transformed, 1.0f / ls->position_transformed.w);
+}
+
 static void compute_light(struct wined3d_color *ambient, struct wined3d_color *diffuse,
-        struct wined3d_color *specular, const struct lights_settings *ls, const struct wined3d_vec3 *normal,
-        const struct wined3d_vec4 *position, float material_shininess)
+        struct wined3d_color *specular, struct lights_settings *ls, const struct wined3d_vec3 *normal,
+        float material_shininess)
 {
     struct wined3d_vec3 position_transformed_normalised;
     struct wined3d_vec3 normal_transformed = {0.0f};
-    struct wined3d_vec4 position_transformed;
     const struct light_transformed *light;
     struct wined3d_vec3 dir, dst;
     unsigned int i, index;
     float att;
 
-    wined3d_vec4_transform(&position_transformed, position, &ls->modelview_matrix);
-    wined3d_vec3_scale((struct wined3d_vec3 *)&position_transformed, 1.0f / position_transformed.w);
-    position_transformed_normalised = *(const struct wined3d_vec3 *)&position_transformed;
+    position_transformed_normalised = *(const struct wined3d_vec3 *)&ls->position_transformed;
     wined3d_vec3_normalise(&position_transformed_normalised);
 
     if (normal)
@@ -3472,9 +3499,9 @@ static void compute_light(struct wined3d_color *ambient, struct wined3d_color *d
     for (i = 0; i < ls->point_light_count; ++i, ++index)
     {
         light = &ls->lights[index];
-        dir.x = light->position.x - position_transformed.x;
-        dir.y = light->position.y - position_transformed.y;
-        dir.z = light->position.z - position_transformed.z;
+        dir.x = light->position.x - ls->position_transformed.x;
+        dir.y = light->position.y - ls->position_transformed.y;
+        dir.z = light->position.z - ls->position_transformed.z;
 
         dst.z = wined3d_vec3_dot(&dir, &dir);
         dst.y = sqrtf(dst.z);
@@ -3510,9 +3537,9 @@ static void compute_light(struct wined3d_color *ambient, struct wined3d_color *d
 
         light = &ls->lights[index];
 
-        dir.x = light->position.x - position_transformed.x;
-        dir.y = light->position.y - position_transformed.y;
-        dir.z = light->position.z - position_transformed.z;
+        dir.x = light->position.x - ls->position_transformed.x;
+        dir.y = light->position.y - ls->position_transformed.y;
+        dir.z = light->position.z - ls->position_transformed.z;
 
         dst.z = wined3d_vec3_dot(&dir, &dir);
         dst.y = sqrtf(dst.z);
@@ -3563,6 +3590,46 @@ static void compute_light(struct wined3d_color *ambient, struct wined3d_color *d
     }
 }
 
+static float wined3d_calculate_fog_factor(float fog_coord, const struct lights_settings *ls)
+{
+    switch (ls->fog_mode)
+    {
+        case WINED3D_FOG_NONE:
+            return fog_coord;
+        case WINED3D_FOG_LINEAR:
+            return (ls->fog_end - fog_coord) / (ls->fog_end - ls->fog_start);
+        case WINED3D_FOG_EXP:
+            return expf(-fog_coord * ls->fog_density);
+        case WINED3D_FOG_EXP2:
+            return expf(-fog_coord * fog_coord * ls->fog_density * ls->fog_density);
+    }
+}
+
+static void update_fog_factor(float *fog_factor, struct lights_settings *ls)
+{
+    float fog_coord;
+
+    if (ls->fog_mode == WINED3D_FOG_NONE)
+        return;
+
+    switch (ls->fog_coord_mode)
+    {
+        case WINED3D_FFP_VS_FOG_RANGE:
+            fog_coord = sqrtf(wined3d_vec3_dot((const struct wined3d_vec3 *)&ls->position_transformed,
+                    (const struct wined3d_vec3 *)&ls->position_transformed));
+            break;
+
+        case WINED3D_FFP_VS_FOG_DEPTH:
+            fog_coord = fabsf(ls->position_transformed.z);
+            break;
+
+        default:
+            ERR("Unhandled fog coordinate mode %#x.\n", ls->fog_coord_mode);
+            return;
+    }
+    *fog_factor = wined3d_calculate_fog_factor(fog_coord, ls);
+}
+
 /* Context activation is done by the caller. */
 #define copy_and_next(dest, src, size) memcpy(dest, src, size); dest += (size)
 static HRESULT process_vertices_strided(const struct wined3d_device *device, DWORD dwDestIndex, DWORD dwCount,
@@ -3661,17 +3728,24 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO
     output_colour_format = wined3d_get_format(device->adapter, WINED3DFMT_B8G8R8A8_UNORM, 0);
     material_specular_state_colour = state->render_states[WINED3D_RS_SPECULARENABLE]
             ? &state->material.specular : &black;
-    if (lighting)
-        init_transformed_lights(&ls, state,
-                device->adapter->d3d_info.wined3d_creation_flags & WINED3D_LEGACY_FFP_LIGHTING);
+    init_transformed_lights(&ls, state, device->adapter->d3d_info.wined3d_creation_flags
+            & WINED3D_LEGACY_FFP_LIGHTING, lighting);
 
     for (i = 0; i < dwCount; ++i)
     {
         const struct wined3d_stream_info_element *position_element = &stream_info->elements[WINED3D_FFP_POSITION];
         const float *p = (const float *)&position_element->data.addr[i * position_element->stride];
         struct wined3d_color ambient, diffuse, specular;
+        struct wined3d_vec4 position;
         unsigned int tex_index;
 
+        position.x = p[0];
+        position.y = p[1];
+        position.z = p[2];
+        position.w = 1.0f;
+
+        light_set_vertex_data(&ls, &position);
+
         if ( ((dst_fvf & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZ ) ||
              ((dst_fvf & WINED3DFVF_POSITION_MASK) == WINED3DFVF_XYZRHW ) ) {
             /* The position first */
@@ -3783,14 +3857,8 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO
         if (lighting)
         {
             const struct wined3d_stream_info_element *element;
-            struct wined3d_vec4 position;
             struct wined3d_vec3 *normal;
 
-            position.x = p[0];
-            position.y = p[1];
-            position.z = p[2];
-            position.w = 1.0f;
-
             if (stream_info->use_map & (1u << WINED3D_FFP_NORMAL))
             {
                 element = &stream_info->elements[WINED3D_FFP_NORMAL];
@@ -3800,7 +3868,7 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO
             {
                 normal = NULL;
             }
-            compute_light(&ambient, &diffuse, &specular, &ls, normal, &position,
+            compute_light(&ambient, &diffuse, &specular, &ls, normal,
                     state->render_states[WINED3D_RS_SPECULARENABLE] ? state->material.power : 0.0f);
         }
 
@@ -3853,6 +3921,7 @@ static HRESULT process_vertices_strided(const struct wined3d_device *device, DWO
             {
                 specular_colour = material_specular;
             }
+            update_fog_factor(&specular_colour.a, &ls);
             wined3d_color_clamp(&specular_colour, &specular_colour, 0.0f, 1.0f);
             *((DWORD *)dest_ptr) = wined3d_format_convert_from_float(output_colour_format, &specular_colour);
             dest_ptr += sizeof(DWORD);
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index 6dcb0693c5..68ef9e13dd 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -4945,6 +4945,19 @@ static inline void context_release(struct wined3d_context *context)
     context->device->adapter->adapter_ops->adapter_release_context(context);
 }
 
+static inline float wined3d_get_float_state(const struct wined3d_state *state, enum wined3d_render_state rs)
+{
+    union
+    {
+        DWORD d;
+        float f;
+    }
+    tmpvalue;
+
+    tmpvalue.d = state->render_states[rs];
+    return tmpvalue.f;
+}
+
 /* The WNDCLASS-Name for the fake window which we use to retrieve the GL capabilities */
 #define WINED3D_OPENGL_WINDOW_CLASS_NAME "WineD3D_OpenGL"
 
-- 
2.21.0




More information about the wine-devel mailing list