diff --git a/dlls/ddraw/d3ddevice/mesa.c b/dlls/ddraw/d3ddevice/mesa.c index 9ed79de59e5..2b71a6b9cce 100644 --- a/dlls/ddraw/d3ddevice/mesa.c +++ b/dlls/ddraw/d3ddevice/mesa.c @@ -673,6 +673,22 @@ static void draw_primitive_start_GL(D3DPRIMITIVETYPE d3dpt) } } +/* This function calculate the Z coordinate from Zproj */ +static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj) +{ + float a,b,c,d; + /* Assume that X = Y = 0 and W = 1 */ + a = This->proj_mat->_33; + b = This->proj_mat->_34; + c = This->proj_mat->_43; + d = This->proj_mat->_44; + /* We have in homogenous coordinates Z' = a * Z + c and W' = b * Z + d + * So in non homogenous coordinates we have Zproj = (a * Z + b) / (c * Z + d) + * And finally Z = (d * Zproj - c) / (a - b * Zproj) + */ + return (d*Zproj - c) / (a - b*Zproj); +} + static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This, BOOLEAN vertex_transformed, BOOLEAN vertex_lit) { @@ -688,17 +704,34 @@ static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This, This->world_mat, This->view_mat, This->proj_mat); glThis->transform_state = GL_TRANSFORM_NORMAL; - if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) - glEnable(GL_FOG); } else if ((vertex_transformed == TRUE) && (glThis->transform_state != GL_TRANSFORM_ORTHO)) { /* Set our orthographic projection */ glThis->transform_state = GL_TRANSFORM_ORTHO; d3ddevice_set_ortho(This); - - /* Remove also fogging... */ - glDisable(GL_FOG); } + if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {glHint(GL_FOG_HINT,GL_NICEST); + if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) { + switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) { + case D3DFOG_LINEAR: glFogi(GL_FOG_MODE,GL_LINEAR); break; + case D3DFOG_EXP: glFogi(GL_FOG_MODE,GL_EXP); break; + case D3DFOG_EXP2: glFogi(GL_FOG_MODE,GL_EXP2); break; + } + glFogf(GL_FOG_START,ZfromZproj(This,*(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1])); + glFogf(GL_FOG_END,ZfromZproj(This,*(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1])); + glEnable(GL_FOG); + } else if ( (This->state_block.render_state[D3DRENDERSTATE_FOGVERTEXMODE - 1] != D3DFOG_NONE) && + (vertex_lit == FALSE) && (vertex_transformed == FALSE) ) { + /* D3DFOG_EXP and D3DFOG_EXP2 are treated as D3DFOG_LINEAR */ + glFogi(GL_FOG_MODE,GL_LINEAR); + glFogf(GL_FOG_START,*(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]); + glFogf(GL_FOG_END,*(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 1]); + glEnable(GL_FOG); + } else + glDisable(GL_FOG); + } + else + glDisable(GL_FOG); /* Handle the 'no-normal' case */ if (vertex_lit == TRUE) diff --git a/dlls/ddraw/mesa.c b/dlls/ddraw/mesa.c index ccf59d1a748..5aff9c24d62 100644 --- a/dlls/ddraw/mesa.c +++ b/dlls/ddraw/mesa.c @@ -83,7 +83,6 @@ GLenum convert_D3D_blendop_to_GL(D3DBLEND dwRenderState) void set_render_state(IDirect3DDeviceImpl* This, D3DRENDERSTATETYPE dwRenderStateType, STATEBLOCK *lpStateBlock) { - IDirect3DDeviceGLImpl *glThis = (IDirect3DDeviceGLImpl *) This; DWORD dwRenderState = lpStateBlock->render_state[dwRenderStateType - 1]; if (TRACE_ON(ddraw)) @@ -304,12 +303,7 @@ void set_render_state(IDirect3DDeviceImpl* This, break; case D3DRENDERSTATE_FOGENABLE: /* 28 */ - if ((dwRenderState == TRUE) && - (glThis->transform_state != GL_TRANSFORM_ORTHO)) { - glEnable(GL_FOG); - } else { - glDisable(GL_FOG); - } + /* Nothing to do here. Only the storage matters :-) */ break; case D3DRENDERSTATE_SPECULARENABLE: /* 29 */ @@ -320,7 +314,7 @@ void set_render_state(IDirect3DDeviceImpl* This, case D3DRENDERSTATE_SUBPIXEL: /* 31 */ case D3DRENDERSTATE_SUBPIXELX: /* 32 */ /* We do not support this anyway, so why protest :-) */ - break; + break; case D3DRENDERSTATE_STIPPLEDALPHA: /* 33 */ if (dwRenderState) @@ -328,15 +322,26 @@ void set_render_state(IDirect3DDeviceImpl* This, break; case D3DRENDERSTATE_FOGCOLOR: { /* 34 */ - GLint color[4]; - color[0] = (dwRenderState >> 16) & 0xFF; - color[1] = (dwRenderState >> 8) & 0xFF; - color[2] = (dwRenderState >> 0) & 0xFF; - color[3] = (dwRenderState >> 24) & 0xFF; - glFogiv(GL_FOG_COLOR, color); + GLfloat color[4]; + color[0] = ((dwRenderState >> 16) & 0xFF)/255.0f; + color[1] = ((dwRenderState >> 8) & 0xFF)/255.0f; + color[2] = ((dwRenderState >> 0) & 0xFF)/255.0f; + color[3] = ((dwRenderState >> 24) & 0xFF)/255.0f; + glFogfv(GL_FOG_COLOR,color); + /* Note: glFogiv does not seem to work */ } break; - + case D3DRENDERSTATE_FOGTABLEMODE: /* 35 */ + case D3DRENDERSTATE_FOGVERTEXMODE: /* 140 */ + case D3DRENDERSTATE_FOGSTART: /* 36 */ + case D3DRENDERSTATE_FOGEND: /* 37 */ + /* Nothing to do here. Only the storage matters :-) */ + break; + + case D3DRENDERSTATE_FOGDENSITY: /* 38 */ + glFogi(GL_FOG_DENSITY,*(float*)&dwRenderState); + break; + case D3DRENDERSTATE_COLORKEYENABLE: /* 41 */ /* This needs to be fixed. */ if (dwRenderState)