Stefan Dösinger : wined3d: Make pixelshaders disable fog properly.

Alexandre Julliard julliard at winehq.org
Fri Dec 19 11:19:13 CST 2008


Module: wine
Branch: master
Commit: 690cbe76ac4f84b67cebe7779a14e23332e271d8
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=690cbe76ac4f84b67cebe7779a14e23332e271d8

Author: Stefan Dösinger <stefan at codeweavers.com>
Date:   Mon Dec 15 19:35:40 2008 +0100

wined3d: Make pixelshaders disable fog properly.

This is a first step towards cleaning up the fog mess. The fog
parameter is added to the pixelshader compile args structure. That way
multiple pshaders are compiled for different fog settings, and the
pixel shader can remove the fog line if fog is not enabled. That way
we don't need special fog start and end settings, and this allows us
to implement EXP and EXP2 fog in the future too.

---

 dlls/wined3d/arb_program_shader.c |   42 +++++++++++++++++++++++++-----------
 dlls/wined3d/glsl_shader.c        |   18 ++++++++++++---
 dlls/wined3d/pixelshader.c        |   26 ++++++++++++++++++++++-
 dlls/wined3d/state.c              |   22 -------------------
 dlls/wined3d/wined3d_private.h    |   15 ++++++++-----
 5 files changed, 77 insertions(+), 46 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 4f7f955..b31590a 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -1905,27 +1905,43 @@ static GLuint shader_arb_generate_pshader(IWineD3DPixelShader *iface, SHADER_BUF
     shader_generate_arb_declarations( (IWineD3DBaseShader*) This, reg_maps, buffer, &GLINFO_LOCATION);
 
     /* We need two variables for fog blending */
-    shader_addline(buffer, "TEMP TMP_FOG;\n");
+    if(args->fog != FOG_OFF) shader_addline(buffer, "TEMP TMP_FOG;\n");
     if (shader_version >= WINED3DPS_VERSION(2,0)) shader_addline(buffer, "TEMP TMP_COLOR;\n");
 
     /* Base Shader Body */
     shader_generate_main( (IWineD3DBaseShader*) This, buffer, reg_maps, function);
 
-    /* calculate fog and blend it
-     * NOTE: state.fog.params.y and state.fog.params.z don't hold fog start s and end e but
-     * -1/(e-s) and e/(e-s) respectively.
-     */
-    shader_addline(buffer, "MAD_SAT TMP_FOG, fragment.fogcoord, state.fog.params.y, state.fog.params.z;\n");
-
-    fragcolor = (shader_version < WINED3DPS_VERSION(2,0)) ? "R0" : "TMP_COLOR";
-
+    if (shader_version < WINED3DPS_VERSION(2,0)) {
+        fragcolor = "R0";
+    } else {
+        fragcolor = "TMP_COLOR";
+    }
     if(args->srgb_correction) {
         arbfp_add_sRGB_correction(buffer, fragcolor, "TMP", "TMP2", "TA", "TB");
     }
-    if (shader_version < WINED3DPS_VERSION(3,0))
-    {
-        shader_addline(buffer, "LRP result.color.rgb, TMP_FOG.x, %s, state.fog.color;\n", fragcolor);
-        shader_addline(buffer, "MOV result.color.a, %s.a;\n", fragcolor);
+    if (shader_version < WINED3DPS_VERSION(3,0)) {
+        /* calculate fog and blend it
+         * NOTE: state.fog.params.y and state.fog.params.z don't hold fog start s and end e but
+         * -1/(e-s) and e/(e-s) respectively.
+         */
+        switch(args->fog) {
+            case FOG_OFF:
+                shader_addline(buffer, "MOV result.color, %s;\n", fragcolor);
+                break;
+            case FOG_LINEAR:
+                shader_addline(buffer, "MAD_SAT TMP_FOG, fragment.fogcoord, state.fog.params.y, state.fog.params.z;\n");
+                shader_addline(buffer, "LRP result.color.rgb, TMP_FOG.x, %s, state.fog.color;\n", fragcolor);
+                shader_addline(buffer, "MOV result.color.a, %s.a;\n", fragcolor);
+                break;
+            case FOG_EXP:
+                FIXME("Implement EXP fog in ARB\n");
+                shader_addline(buffer, "MOV result.color, %s;\n", fragcolor);
+                break;
+            case FOG_EXP2:
+                FIXME("Implement EXP2 fog in ARB\n");
+                shader_addline(buffer, "MOV result.color, %s;\n", fragcolor);
+                break;
+        }
     }
 
     shader_addline(buffer, "END\n");
diff --git a/dlls/wined3d/glsl_shader.c b/dlls/wined3d/glsl_shader.c
index 59e3427..b9a0e2e 100644
--- a/dlls/wined3d/glsl_shader.c
+++ b/dlls/wined3d/glsl_shader.c
@@ -3675,10 +3675,20 @@ static GLuint shader_glsl_generate_pshader(IWineD3DPixelShader *iface, SHADER_BU
      * NOTE: gl_Fog.start and gl_Fog.end don't hold fog start s and end e but
      * -1/(e-s) and e/(e-s) respectively.
      */
-    if (reg_maps->shader_version < WINED3DPS_VERSION(3,0))
-    {
-        shader_addline(buffer, "float Fog = clamp(gl_FogFragCoord * gl_Fog.start + gl_Fog.end, 0.0, 1.0);\n");
-        shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor);
+    if(reg_maps->shader_version < WINED3DPS_VERSION(3,0)) {
+        switch(args->fog) {
+            case FOG_OFF: break;
+            case FOG_LINEAR:
+                shader_addline(buffer, "float Fog = clamp(gl_FogFragCoord * gl_Fog.start + gl_Fog.end, 0.0, 1.0);\n");
+                shader_addline(buffer, "%s.xyz = mix(gl_Fog.color.xyz, %s.xyz, Fog);\n", fragcolor, fragcolor);
+                break;
+            case FOG_EXP:
+                FIXME("Implement EXP fog in glsl\n");
+                break;
+            case FOG_EXP2:
+                FIXME("Implement EXP2 fog in glsl\n");
+                break;
+        }
     }
 
     shader_addline(buffer, "}\n");
diff --git a/dlls/wined3d/pixelshader.c b/dlls/wined3d/pixelshader.c
index 94a45cf..15392d8 100644
--- a/dlls/wined3d/pixelshader.c
+++ b/dlls/wined3d/pixelshader.c
@@ -463,9 +463,9 @@ void find_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWineD3DStateBlockImp
     UINT i, sampler;
     IWineD3DBaseTextureImpl *tex;
 
+    memset(args, 0, sizeof(*args)); /* FIXME: Make sure all bits are set */
     args->srgb_correction = stateblock->renderState[WINED3DRS_SRGBWRITEENABLE] ? 1 : 0;
 
-    memset(args->color_fixup, 0, sizeof(args->color_fixup));
     for(i = 0; i < shader->baseShader.num_sampled_samplers; i++) {
         sampler = shader->baseShader.sampled_samplers[i];
         tex = (IWineD3DBaseTextureImpl *) stateblock->textures[sampler];
@@ -484,8 +484,32 @@ void find_ps_compile_args(IWineD3DPixelShaderImpl *shader, IWineD3DStateBlockImp
         } else {
             args->vp_mode = fixedfunction;
         }
+        args->fog = FOG_OFF;
     } else {
         args->vp_mode = vertexshader;
+        if(stateblock->renderState[WINED3DRS_FOGENABLE]) {
+            switch(stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
+                case WINED3DFOG_NONE:
+                    if(((IWineD3DDeviceImpl *) shader->baseShader.device)->strided_streams.u.s.position_transformed ||
+                         use_vs((IWineD3DDeviceImpl *) shader->baseShader.device)) {
+                        args->fog = FOG_LINEAR;
+                        break;
+                    }
+                    switch(stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
+                        case WINED3DFOG_NONE: /* Drop through */
+                        case WINED3DFOG_LINEAR: args->fog = FOG_LINEAR; break;
+                        case WINED3DFOG_EXP:    args->fog = FOG_EXP;    break;
+                        case WINED3DFOG_EXP2:   args->fog = FOG_EXP2;   break;
+                    }
+                    break;
+
+                case WINED3DFOG_LINEAR: args->fog = FOG_LINEAR; break;
+                case WINED3DFOG_EXP:    args->fog = FOG_EXP;    break;
+                case WINED3DFOG_EXP2:   args->fog = FOG_EXP2;   break;
+            }
+        } else {
+            args->fog = FOG_OFF;
+        }
     }
 }
 
diff --git a/dlls/wined3d/state.c b/dlls/wined3d/state.c
index 0bf357d..e4c819d 100644
--- a/dlls/wined3d/state.c
+++ b/dlls/wined3d/state.c
@@ -911,18 +911,6 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo
         /* No fog? Disable it, and we're done :-) */
         glDisable(GL_FOG);
         checkGLcall("glDisable GL_FOG");
-        if (use_ps(stateblock->wineD3DDevice)
-                && ps_impl->baseShader.reg_maps.shader_version < WINED3DPS_VERSION(3,0))
-        {
-            /* disable fog in the pixel shader
-             * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
-             * -1/(e-s) and e/(e-s) respectively.
-             */
-            glFogf(GL_FOG_START, 0.0f);
-            checkGLcall("glFogf(GL_FOG_START, fogstart)");
-            glFogf(GL_FOG_END, 1.0f);
-            checkGLcall("glFogf(GL_FOG_END, fogend)");
-        }
         return;
     }
 
@@ -1168,16 +1156,6 @@ static void state_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DCo
     } else {
         glDisable(GL_FOG);
         checkGLcall("glDisable GL_FOG");
-        if( use_ps(stateblock->wineD3DDevice) ) {
-            /* disable fog in the pixel shader
-             * NOTE: For pixel shader, GL_FOG_START and GL_FOG_END don't hold fog start s and end e but
-             * -1/(e-s) and e/(e-s) respectively.
-             */
-            glFogf(GL_FOG_START, 0.0f);
-            checkGLcall("glFogf(GL_FOG_START, fogstart)");
-            glFogf(GL_FOG_END, 1.0f);
-            checkGLcall("glFogf(GL_FOG_END, fogend)");
-        }
     }
 }
 
diff --git a/dlls/wined3d/wined3d_private.h b/dlls/wined3d/wined3d_private.h
index f308c40..d433b53 100644
--- a/dlls/wined3d/wined3d_private.h
+++ b/dlls/wined3d/wined3d_private.h
@@ -438,6 +438,13 @@ struct stb_const_desc {
     UINT                    const_num;
 };
 
+enum fogmode {
+    FOG_OFF,
+    FOG_LINEAR,
+    FOG_EXP,
+    FOG_EXP2
+};
+
 /* Stateblock dependent parameters which have to be hardcoded
  * into the shader code
  */
@@ -445,6 +452,7 @@ struct ps_compile_args {
     struct color_fixup_desc     color_fixup[MAX_FRAGMENT_SAMPLERS];
     BOOL                        srgb_correction;
     enum vertexprocessing_mode  vp_mode;
+    enum fogmode                fog;
     /* Projected textures(ps 1.0-1.3) */
     /* Texture types(2D, Cube, 3D) in ps 1.x */
 };
@@ -974,12 +982,7 @@ struct texture_stage_op
 
 struct ffp_frag_settings {
     struct texture_stage_op     op[MAX_TEXTURES];
-    enum {
-        FOG_OFF,
-        FOG_LINEAR,
-        FOG_EXP,
-        FOG_EXP2
-    } fog;
+    enum fogmode fog;
     /* Use an int instead of a char to get dword alignment */
     unsigned int sRGB_write;
 };




More information about the wine-cvs mailing list