diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c index 4f7f9550003..b31590ae199 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 59e3427760e..b9a0e2ef854 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 94a45cf2490..15392d8a95d 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 0bf357d7768..e4c819d2590 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 f308c403583..d433b537a21 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; };