mirror of
git://source.winehq.org/git/wine.git
synced 2024-09-16 05:16:27 +00:00
wined3d: Correct vertex fog for transformed vertices and correctly
handle non-vertex, non-table fog.
This commit is contained in:
parent
cc06ed3d53
commit
5c3c5903a5
|
@ -3750,7 +3750,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D
|
|||
|
||||
case WINED3DRS_FOGENABLE :
|
||||
{
|
||||
if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] != D3DFOG_NONE*/) {
|
||||
if (Value) {
|
||||
glEnable(GL_FOG);
|
||||
checkGLcall("glEnable GL_FOG");
|
||||
} else {
|
||||
|
@ -3781,21 +3781,112 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D
|
|||
break;
|
||||
|
||||
case WINED3DRS_FOGTABLEMODE :
|
||||
case WINED3DRS_FOGVERTEXMODE :
|
||||
{
|
||||
glHint(GL_FOG_HINT, GL_NICEST);
|
||||
switch (Value) {
|
||||
case D3DFOG_NONE: {
|
||||
if(This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == D3DFOG_NONE) {
|
||||
glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
|
||||
/* 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." */
|
||||
if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
|
||||
glHint(GL_FOG_HINT, GL_FASTEST);
|
||||
checkGLcall("glHint(GL_FOG_HINT, GL_FASTEST)");
|
||||
switch (This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]) {
|
||||
/* Processed vertices have their fog factor stored in the specular value. Fall too the none case.
|
||||
* If we are drawing untransformed vertices atm, d3ddevice_set_ortho will update the fog
|
||||
*/
|
||||
case D3DFOG_EXP: {
|
||||
if(!This->last_was_rhw) {
|
||||
glFogi(GL_FOG_MODE, GL_EXP);
|
||||
checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
|
||||
if(GL_SUPPORT(EXT_FOG_COORD)) {
|
||||
glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH);
|
||||
checkGLcall("glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH");
|
||||
IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
|
||||
IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
case D3DFOG_EXP2: {
|
||||
if(!This->last_was_rhw) {
|
||||
glFogi(GL_FOG_MODE, GL_EXP2);
|
||||
checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
|
||||
if(GL_SUPPORT(EXT_FOG_COORD)) {
|
||||
glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH);
|
||||
checkGLcall("glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH");
|
||||
IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
|
||||
IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
case D3DFOG_LINEAR: {
|
||||
if(!This->last_was_rhw) {
|
||||
glFogi(GL_FOG_MODE, GL_LINEAR);
|
||||
checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
|
||||
if(GL_SUPPORT(EXT_FOG_COORD)) {
|
||||
glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH);
|
||||
checkGLcall("glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH");
|
||||
IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
|
||||
IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
case D3DFOG_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
|
||||
*/
|
||||
if(GL_SUPPORT(EXT_FOG_COORD)) {
|
||||
glFogi(GL_FOG_COORD_SRC, GL_FOG_COORD);
|
||||
checkGLcall("glFogi(GL_FOG_COORD_SRC, GL_FOG_COORD)\n");
|
||||
glFogi(GL_FOG_MODE, GL_LINEAR);
|
||||
checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
|
||||
glFogf(GL_FOG_START, (float) 0xff);
|
||||
checkGLcall("glFogfv GL_FOG_START");
|
||||
glFogf(GL_FOG_END, 0.0);
|
||||
checkGLcall("glFogfv GL_FOG_END");
|
||||
} else {
|
||||
/* Disable GL fog, handle this in software in drawStridedSlow */
|
||||
glDisable(GL_FOG);
|
||||
checkGLcall("glDisable(GL_FOG)");
|
||||
}
|
||||
break;
|
||||
}
|
||||
default: FIXME("Unexpected WINED3DRS_FOGVERTEXMODE %ld\n", This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE]);
|
||||
}
|
||||
} else {
|
||||
glHint(GL_FOG_HINT, GL_NICEST);
|
||||
checkGLcall("glHint(GL_FOG_HINT, GL_NICEST)");
|
||||
switch (This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]) {
|
||||
case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP);
|
||||
checkGLcall("glFogi(GL_FOG_MODE, GL_EXP");
|
||||
if(GL_SUPPORT(EXT_FOG_COORD)) {
|
||||
glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH);
|
||||
checkGLcall("glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH");
|
||||
IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
|
||||
IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
|
||||
}
|
||||
break;
|
||||
case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2);
|
||||
checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2");
|
||||
if(GL_SUPPORT(EXT_FOG_COORD)) {
|
||||
glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH);
|
||||
checkGLcall("glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH");
|
||||
IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
|
||||
IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
|
||||
}
|
||||
break;
|
||||
case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR);
|
||||
checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR");
|
||||
if(GL_SUPPORT(EXT_FOG_COORD)) {
|
||||
glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH);
|
||||
checkGLcall("glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH");
|
||||
IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
|
||||
IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
|
||||
}
|
||||
break;
|
||||
case D3DFOG_NONE: /* Won't happen */
|
||||
default: FIXME("Unexpected WINED3DRS_FOGTABLEMODE %ld\n", This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
|
||||
}
|
||||
/* Otherwise leave the vertex fog value */
|
||||
break;
|
||||
}
|
||||
case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
|
||||
case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
|
||||
case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
|
||||
default:
|
||||
FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
|
||||
}
|
||||
if (GL_SUPPORT(NV_FOG_DISTANCE)) {
|
||||
glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
|
||||
|
@ -3803,26 +3894,6 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetRenderState(IWineD3DDevice *iface, D
|
|||
}
|
||||
break;
|
||||
|
||||
case WINED3DRS_FOGVERTEXMODE :
|
||||
{
|
||||
glHint(GL_FOG_HINT, GL_FASTEST);
|
||||
/* 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." */
|
||||
if(This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
|
||||
switch (Value) {
|
||||
case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP"); break;
|
||||
case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); checkGLcall("glFogi(GL_FOG_MODE, GL_EXP2"); break;
|
||||
case D3DFOG_NONE:
|
||||
case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR"); break;
|
||||
default:
|
||||
FIXME("Unsupported Value(%lu) for WINED3DRS_FOGTABLEMODE!\n", Value);
|
||||
}
|
||||
if (GL_SUPPORT(NV_FOG_DISTANCE)) {
|
||||
glFogi(GL_FOG_DISTANCE_MODE_NV, This->stateBlock->renderState[WINED3DRS_RANGEFOGENABLE] ? GL_EYE_RADIAL_NV : GL_EYE_PLANE_ABSOLUTE_NV);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case WINED3DRS_FOGSTART :
|
||||
{
|
||||
tmpvalue.d = Value;
|
||||
|
|
|
@ -218,8 +218,30 @@ void d3ddevice_set_ortho(IWineD3DDeviceImpl *This) {
|
|||
glMultMatrixf(invymat);
|
||||
checkGLcall("glMultMatrixf(invymat)");
|
||||
}
|
||||
}
|
||||
|
||||
/* Vertex fog on transformed vertices? Use the calculated fog factor stored in the specular color */
|
||||
if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != D3DFOG_NONE) {
|
||||
if(GL_SUPPORT(EXT_FOG_COORD)) {
|
||||
glFogi(GL_FOG_COORD_SRC, GL_FOG_COORD);
|
||||
checkGLcall("glFogi(GL_FOG_COORD_SRC, GL_FOG_COORD)");
|
||||
glFogi(GL_FOG_MODE, GL_LINEAR);
|
||||
checkGLcall("glFogi(GL_FOG_MODE, GL_LINEAR)");
|
||||
/* The dx fog range in this case is fixed to 0 - 255,
|
||||
* but in GL it still depends on the fog start and end (according to the ext)
|
||||
* Use this to turn around the fog as it's needed. That prevents some
|
||||
* calculations during drawing :-)
|
||||
*/
|
||||
glFogf(GL_FOG_START, (float) 0xff);
|
||||
checkGLcall("glFogfv GL_FOG_END");
|
||||
glFogf(GL_FOG_END, 0.0);
|
||||
checkGLcall("glFogfv GL_FOG_START");
|
||||
} else {
|
||||
/* Disable GL fog, handle this in software in drawStridedSlow */
|
||||
glDisable(GL_FOG);
|
||||
checkGLcall("glDisable(GL_FOG)");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Setup views - Transformed & lit if RHW, else untransformed.
|
||||
Only unlit if Normals are supplied
|
||||
|
@ -240,6 +262,7 @@ static BOOL primitiveInitState(IWineD3DDevice *iface, BOOL vtx_transformed, BOOL
|
|||
|
||||
if (!useVS && vtx_transformed) {
|
||||
d3ddevice_set_ortho(This);
|
||||
|
||||
} else {
|
||||
|
||||
/* Untransformed, so relies on the view and projection matrices */
|
||||
|
@ -311,6 +334,23 @@ static BOOL primitiveInitState(IWineD3DDevice *iface, BOOL vtx_transformed, BOOL
|
|||
This->proj_valid = FALSE;
|
||||
}
|
||||
This->last_was_rhw = FALSE;
|
||||
|
||||
/* Restore fogging */
|
||||
if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] && This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] != D3DFOG_NONE) {
|
||||
if(GL_SUPPORT(EXT_FOG_COORD)) {
|
||||
glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH);
|
||||
checkGLcall("glFogi(GL_FOG_COORD_SRC, GL_FRAGMENT_DEPTH)\n");
|
||||
/* Reapply the fog range */
|
||||
IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGSTART, This->stateBlock->renderState[WINED3DRS_FOGSTART]);
|
||||
IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGEND, This->stateBlock->renderState[WINED3DRS_FOGEND]);
|
||||
/* Restore the fog mode */
|
||||
IWineD3DDevice_SetRenderState(iface, WINED3DRS_FOGTABLEMODE, This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]);
|
||||
} else {
|
||||
/* Enable GL_FOG again because we disabled it above */
|
||||
glEnable(GL_FOG);
|
||||
checkGLcall("glEnable(GL_FOG)");
|
||||
}
|
||||
}
|
||||
}
|
||||
return isLightingOn;
|
||||
}
|
||||
|
@ -1489,6 +1529,22 @@ static void drawStridedSlow(IWineD3DDevice *iface, WineDirect3DVertexStridedData
|
|||
|
||||
/* Specular ------------------------------- */
|
||||
if (sd->u.s.specular.lpData != NULL) {
|
||||
/* special case where the fog density is stored in the diffuse alpha channel */
|
||||
if(This->stateBlock->renderState[WINED3DRS_FOGENABLE] &&
|
||||
(This->stateBlock->renderState[WINED3DRS_FOGVERTEXMODE] == D3DFOG_NONE || sd->u.s.position.dwType == D3DDECLTYPE_FLOAT4 )&&
|
||||
This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE] == D3DFOG_NONE) {
|
||||
if(GL_SUPPORT(EXT_FOG_COORD)) {
|
||||
GL_EXTCALL(glFogCoordfEXT(specularColor >> 24));
|
||||
} else {
|
||||
static BOOL warned = FALSE;
|
||||
if(!warned) {
|
||||
/* TODO: Use the fog table code from old ddraw */
|
||||
FIXME("Implement fog for transformed vertices in software\n");
|
||||
warned = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
VTRACE(("glSecondaryColor4ub: r,g,b=%lu,%lu,%lu\n",
|
||||
D3DCOLOR_B_R(specularColor),
|
||||
D3DCOLOR_B_G(specularColor),
|
||||
|
|
|
@ -646,6 +646,12 @@ typedef GLvoid* (APIENTRY * PGLFNMAPBUFFERARBPROC) (GLenum target, GLenum access
|
|||
typedef GLboolean (APIENTRY * PGLFNUNMAPBUFFERARBPROC) (GLenum target);
|
||||
typedef void (APIENTRY * PGLFNGETBUFFERPARAMETERIVARBPROC) (GLenum target, GLenum pname, GLint *params);
|
||||
typedef void (APIENTRY * PGLFNGETBUFFERPOINTERVARBPROC) (GLenum target, GLenum pname, GLvoid* *params);
|
||||
/* GL_EXT_fog_coord */
|
||||
typedef void (APIENTRY * PGLFNGLFOGCOORDFEXTPROC) (GLfloat intesity);
|
||||
typedef void (APIENTRY * PGLFNGLFOGCOORDFVEXTPROC) (GLfloat intesity);
|
||||
typedef void (APIENTRY * PGLFNGLFOGCOORDDEXTPROC) (GLfloat intesity);
|
||||
typedef void (APIENTRY * PGLFNGLFOGCOORDDVEXTPROC) (GLfloat intesity);
|
||||
typedef void (APIENTRY * PGLFNGLFOGCOORDPOINTEREXTPROC) (GLenum type, GLsizei stride, GLvoid *data);
|
||||
/* GL_ARB_shader_objects (GLSL) */
|
||||
#ifndef GL_ARB_shader_objects
|
||||
#define GL_ARB_shader_objects 1
|
||||
|
@ -1424,6 +1430,11 @@ typedef enum _GL_SupportedExt {
|
|||
USE_GL_FUNC(PGLFNGETBUFFERPOINTERVARBPROC, glGetBufferPointervARB); \
|
||||
/** EXT Extensions **/ \
|
||||
/* GL_EXT_fog_coord */ \
|
||||
USE_GL_FUNC(PGLFNGLFOGCOORDFEXTPROC, glFogCoordfEXT); \
|
||||
USE_GL_FUNC(PGLFNGLFOGCOORDFVEXTPROC, glFogCoordfvEXT); \
|
||||
USE_GL_FUNC(PGLFNGLFOGCOORDDEXTPROC, glFogCoorddEXT); \
|
||||
USE_GL_FUNC(PGLFNGLFOGCOORDDVEXTPROC, glFogCoordvEXT); \
|
||||
USE_GL_FUNC(PGLFNGLFOGCOORDPOINTEREXTPROC, glFogCoordPointerEXT); \
|
||||
/* GL_EXT_framebuffer_object */ \
|
||||
USE_GL_FUNC(PGLFNGLISRENDERBUFFEREXTPROC, glIsRenderbufferEXT); \
|
||||
USE_GL_FUNC(PGLFNGLBINDRENDERBUFFEREXTPROC, glBindRenderbufferEXT); \
|
||||
|
|
Loading…
Reference in a new issue