Hi, Apply this patch instead, the old patch had some sloppiness error(setting FOGSTART as FOGEND when restoring z-based fog). The problem is corrected in this patch. It also doesn't add a senseless space at the begin of the file and sets the fog to GL_FASTEST for vertex fog and GL_NICEST for table / pixel fog.
ChangeLog: Stefan Dösinger(for CodeWeavers): Correct vertex fog for transformed vertices and correctly handle non-vertex, non-table fog
From nobody Mon Sep 17 00:00:00 2001
From: Stefan Dösinger <[EMAIL PROTECTED]>
Date: Sun Jun 11 17:58:05 2006 +0200
Subject: [PATCH] WineD3D: Fog fixes
---
dlls/wined3d/device.c | 137 ++++++++++++++++++++++++++++++++++-----------
dlls/wined3d/drawprim.c | 58 +++++++++++++++++++
include/wine/wined3d_gl.h | 11 ++++
3 files changed, 172 insertions(+), 34 deletions(-)
3e6bc2ef9c7b54e09f46b3c01f9c1249afaf3c22
diff --git a/dlls/wined3d/device.c b/dlls/wined3d/device.c
index a0b0522..8fb2d58 100644
--- a/dlls/wined3d/device.c
+++ b/dlls/wined3d/device.c
@@ -3767,7 +3767,7 @@ static HRESULT WINAPI IWineD3DDeviceImpl
case WINED3DRS_FOGENABLE :
{
- if (Value/* && This->stateBlock->renderState[WINED3DRS_FOGTABLEMODE]
!= D3DFOG_NONE*/) {
+ if (Value) {
glEnable(GL_FOG);
checkGLcall("glEnable GL_FOG");
} else {
@@ -3798,45 +3798,116 @@ static HRESULT WINAPI IWineD3DDeviceImpl
break;
case WINED3DRS_FOGTABLEMODE :
- {
- 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");
- }
- /* 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);
- }
- }
- 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);
+ 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]);
}
- 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);
+ } 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]);
}
}
+ if (GL_SUPPORT(NV_FOG_DISTANCE)) {
+ glFogi(GL_FOG_DISTANCE_MODE_NV, GL_EYE_PLANE_ABSOLUTE_NV);
+ }
}
break;
diff --git a/dlls/wined3d/drawprim.c b/dlls/wined3d/drawprim.c
index 0164339..6989c10 100644
--- a/dlls/wined3d/drawprim.c
+++ b/dlls/wined3d/drawprim.c
@@ -218,8 +218,30 @@ void d3ddevice_set_ortho(IWineD3DDeviceI
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(IWineD3DD
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(IWineD3DD
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;
}
@@ -1495,6 +1535,22 @@ static void drawStridedSlow(IWineD3DDevi
/* 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 {
+ 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),
diff --git a/include/wine/wined3d_gl.h b/include/wine/wined3d_gl.h
index 50717fc..a865760 100644
--- a/include/wine/wined3d_gl.h
+++ b/include/wine/wined3d_gl.h
@@ -646,6 +646,12 @@ typedef GLvoid* (APIENTRY * PGLFNMAPBUFF
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);
\
--
1.2.4
pgpwGH3HB4iBV.pgp
Description: PGP signature
