Commit 690cbe76 authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

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.
parent 7d92b54a
......@@ -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");
......
......@@ -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");
......
......@@ -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;
}
}
}
......
......@@ -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)");
}
}
}
......
......@@ -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;
};
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment