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.
This commit is contained in:
Stefan Dösinger 2008-12-15 19:35:40 +01:00 committed by Alexandre Julliard
parent 7d92b54a97
commit 690cbe76ac
5 changed files with 77 additions and 46 deletions

View File

@ -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");

View File

@ -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");

View File

@ -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;
}
}
}

View File

@ -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)");
}
}
}

View File

@ -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;
};