wined3d: Get rid of last_was_foggy_shader & friends.

The fog settings do not depend on wether the shader writes to oFog or not,
instead they depend on the FOGVERTEXMODE and FOGTABLEMODE settings, and if a
vertex shader is bound at all.

It works the same way as with the fixed function, and having a vertex shader
is the same as using pretransformed vertices, just that the fog coord comes
from the shader instead of the specular color:

FOGTABLEMODE != NONE: The Z coord is used, oFog is ignored
FOGTABLEMODE == NONE, with VS: oFog is used
FOGTABLEMODE == NONE, no VS, XYZ: Z is used
FOGTABLEMODE == NONE, no VS, XYZRHW: diffuse color is used
This commit is contained in:
Stefan Dösinger 2009-01-16 15:09:18 +01:00 committed by Alexandre Julliard
parent 3c3272dc41
commit 50109aa969
5 changed files with 88 additions and 92 deletions

View File

@ -1536,9 +1536,15 @@ static void fog_with_shader_test(IDirect3DDevice9 *device)
/* As the red and green component are the result of blending use 5% tolerance on the expected value */
color = getPixelColor(device, 128, 240);
ok(color_match(color, test_data[i].color[j], 13),
"fog vs%i ps%i fvm%i ftm%i %d: got color %08x, expected %08x +-5%%\n",
test_data[i].vshader, test_data[i].pshader, test_data[i].vfog, test_data[i].tfog, j, color, test_data[i].color[j]);
if(test_data[i].vshader == 1 && test_data[i].tfog == 0 && color != test_data[i].color[j]) {
todo_wine ok(color_match(color, test_data[i].color[j], 13),
"fog vs%i ps%i fvm%i ftm%i %d: got color %08x, expected %08x +-5%%(todo)\n",
test_data[i].vshader, test_data[i].pshader, test_data[i].vfog, test_data[i].tfog, j, color, test_data[i].color[j]);
} else {
ok(color_match(color, test_data[i].color[j], 13),
"fog vs%i ps%i fvm%i ftm%i %d: got color %08x, expected %08x +-5%%\n",
test_data[i].vshader, test_data[i].pshader, test_data[i].vfog, test_data[i].tfog, j, color, test_data[i].color[j]);
}
}
}

View File

@ -3052,22 +3052,17 @@ static void state_arbfp_fog(DWORD state, IWineD3DStateBlockImpl *stateblock, Win
if(!stateblock->renderState[WINED3DRS_FOGENABLE]) return;
if(use_vs(stateblock)
&& ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
FIXME("vertex shader with table fog used\n");
}
context->last_was_foggy_shader = TRUE;
new_source = FOGSOURCE_VS;
} else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
context->last_was_foggy_shader = FALSE;
if(stateblock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || context->last_was_rhw) {
new_source = FOGSOURCE_COORD;
if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
if(use_vs(stateblock)) {
new_source = FOGSOURCE_VS;
} else {
new_source = FOGSOURCE_FFP;
if(stateblock->renderState[WINED3DRS_FOGVERTEXMODE] == WINED3DFOG_NONE || context->last_was_rhw) {
new_source = FOGSOURCE_COORD;
} else {
new_source = FOGSOURCE_FFP;
}
}
} else {
context->last_was_foggy_shader = FALSE;
new_source = FOGSOURCE_FFP;
}
if(new_source != context->fog_source) {

View File

@ -1019,75 +1019,72 @@ void state_fog_fragpart(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3D
* and 2) disables the fog computation (in either the fixed function or programmable
* rasterizer) if using a vertex program.
*
* D3D shaders can provide an explicit fog coordinate. This fog coordinate is used with
* D3DRS_FOGTABLEMODE==D3DFOG_NONE. The FOGVERTEXMODE is ignored, d3d always uses linear
* fog with start=1.0 and end=0.0 in this case. This is similar to fog coordinates in
* the specular color, a vertex shader counts as pretransformed geometry in this case.
* There are some GL differences between specular fog coords and vertex shaders though.
*
* With table fog the vertex shader fog coordinate is ignored.
*
* If a fogtablemode and a fogvertexmode are specified, table fog is applied (with or
* without shaders).
*/
if (use_vs(stateblock) && ((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog) {
if( stateblock->renderState[WINED3DRS_FOGTABLEMODE] != WINED3DFOG_NONE ) {
FIXME("vertex shader with table fog used\n");
} else {
/* Set fog computation in the rasterizer to pass through the value (just blend it) */
glFogi(GL_FOG_MODE, GL_LINEAR);
checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
}
context->last_was_foggy_shader = TRUE;
new_source = FOGSOURCE_VS;
}
/* DX 7 sdk: "If both render states(vertex and table fog) are set to valid modes,
* the system will apply only pixel(=table) fog effects."
*/
else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
context->last_was_foggy_shader = FALSE;
if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
if(use_vs(stateblock)) {
glFogi(GL_FOG_MODE, GL_LINEAR);
checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
new_source = FOGSOURCE_VS;
} else {
switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
/* If processed vertices are used, fall through to the NONE case */
case WINED3DFOG_EXP:
if(!context->last_was_rhw) {
glFogi(GL_FOG_MODE, GL_EXP);
checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
new_source = FOGSOURCE_FFP;
break;
}
/* drop through */
switch (stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
/* If processed vertices are used, fall through to the NONE case */
case WINED3DFOG_EXP:
if(!context->last_was_rhw) {
glFogi(GL_FOG_MODE, GL_EXP);
checkGLcall("glFogi(GL_FOG_MODE, GL_EXP)");
new_source = FOGSOURCE_FFP;
break;
}
/* drop through */
case WINED3DFOG_EXP2:
if(!context->last_was_rhw) {
glFogi(GL_FOG_MODE, GL_EXP2);
checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
new_source = FOGSOURCE_FFP;
break;
}
/* drop through */
case WINED3DFOG_EXP2:
if(!context->last_was_rhw) {
glFogi(GL_FOG_MODE, GL_EXP2);
checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2)");
new_source = FOGSOURCE_FFP;
break;
}
/* drop through */
case WINED3DFOG_LINEAR:
if(!context->last_was_rhw) {
glFogi(GL_FOG_MODE, GL_LINEAR);
checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
new_source = FOGSOURCE_FFP;
break;
}
/* drop through */
case WINED3DFOG_LINEAR:
if(!context->last_was_rhw) {
case WINED3DFOG_NONE:
/* Both are none? According to msdn the alpha channel of the specular
* color contains a fog factor. Set it in drawStridedSlow.
* Same happens with Vertexfog on transformed vertices
*/
new_source = FOGSOURCE_COORD;
glFogi(GL_FOG_MODE, GL_LINEAR);
checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
new_source = FOGSOURCE_FFP;
break;
}
/* drop through */
case WINED3DFOG_NONE:
/* Both are none? According to msdn the alpha channel of the specular
* color contains a fog factor. Set it in drawStridedSlow.
* Same happens with Vertexfog on transformed vertices
*/
new_source = FOGSOURCE_COORD;
glFogi(GL_FOG_MODE, GL_LINEAR);
checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
break;
default:
FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
new_source = FOGSOURCE_FFP; /* Make the compiler happy */
default:
FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %d\n", stateblock->renderState[WINED3DRS_FOGVERTEXMODE]);
new_source = FOGSOURCE_FFP; /* Make the compiler happy */
}
}
} else {
glHint(GL_FOG_HINT, GL_NICEST);
checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
context->last_was_foggy_shader = FALSE;
new_source = FOGSOURCE_FFP;
switch (stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {
@ -4331,15 +4328,6 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W
IWineD3DDeviceImpl *device = stateblock->wineD3DDevice;
BOOL wasrhw = context->last_was_rhw;
if (useVertexShaderFunction)
{
if(((IWineD3DVertexShaderImpl *)stateblock->vertexShader)->baseShader.reg_maps.fog != context->last_was_foggy_shader) {
updateFog = TRUE;
}
} else if(context->last_was_foggy_shader) {
updateFog = TRUE;
}
transformed = device->strided_streams.position_transformed;
if(transformed != context->last_was_rhw && !useVertexShaderFunction) {
updateFog = TRUE;
@ -4405,8 +4393,11 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W
state_colormat(STATE_RENDER(WINED3DRS_COLORVERTEX), stateblock, context);
}
if(context->last_was_vshader && !isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
if(context->last_was_vshader) {
updateFog = TRUE;
if(!isStateDirty(context, STATE_RENDER(WINED3DRS_CLIPPLANEENABLE))) {
state_clipping(STATE_RENDER(WINED3DRS_CLIPPLANEENABLE), stateblock, context);
}
}
if(!isStateDirty(context, STATE_RENDER(WINED3DRS_NORMALIZENORMALS))) {
state_normalize(STATE_RENDER(WINED3DRS_NORMALIZENORMALS), stateblock, context);
@ -4440,6 +4431,7 @@ static void vertexdeclaration(DWORD state, IWineD3DStateBlockImpl *stateblock, W
transform_world(STATE_TRANSFORM(WINED3DTS_WORLDMATRIX(0)), stateblock, context);
}
}
updateFog = TRUE;
}
}

View File

@ -2096,17 +2096,21 @@ void gen_ffp_frag_op(IWineD3DStateBlockImpl *stateblock, struct ffp_frag_setting
if(stateblock->renderState[WINED3DRS_FOGENABLE] == FALSE) {
settings->fog = FOG_OFF;
} else if(stateblock->renderState[WINED3DRS_FOGTABLEMODE] == WINED3DFOG_NONE) {
switch(stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
case WINED3DFOG_NONE:
case WINED3DFOG_LINEAR:
settings->fog = FOG_LINEAR;
break;
case WINED3DFOG_EXP:
settings->fog = FOG_EXP;
break;
case WINED3DFOG_EXP2:
settings->fog = FOG_EXP2;
break;
if(use_vs(stateblock) || ((IWineD3DVertexDeclarationImpl *) stateblock->vertexDecl)->position_transformed) {
settings->fog = FOG_LINEAR;
} else {
switch(stateblock->renderState[WINED3DRS_FOGVERTEXMODE]) {
case WINED3DFOG_NONE:
case WINED3DFOG_LINEAR:
settings->fog = FOG_LINEAR;
break;
case WINED3DFOG_EXP:
settings->fog = FOG_EXP;
break;
case WINED3DFOG_EXP2:
settings->fog = FOG_EXP2;
break;
}
}
} else {
switch(stateblock->renderState[WINED3DRS_FOGTABLEMODE]) {

View File

@ -802,7 +802,6 @@ struct WineD3DContext {
WORD last_was_rhw : 1; /* true iff last draw_primitive was in xyzrhw mode */
WORD last_was_pshader : 1;
WORD last_was_vshader : 1;
WORD last_was_foggy_shader : 1;
WORD namedArraysLoaded : 1;
WORD numberedArraysLoaded : 1;
WORD last_was_blit : 1;
@ -811,7 +810,7 @@ struct WineD3DContext {
WORD isPBuffer : 1;
WORD fog_enabled : 1;
WORD num_untracked_materials : 2; /* Max value 2 */
WORD padding : 2;
WORD padding : 3;
BYTE texShaderBumpMap; /* MAX_TEXTURES, 8 */
BYTE lastWasPow2Texture; /* MAX_TEXTURES, 8 */
DWORD numbered_array_mask;