Added fogging for transformed vertices.

This commit is contained in:
Lionel Ulmer 2003-02-12 21:26:05 +00:00 committed by Alexandre Julliard
parent 62ed0ffe00
commit 6238f9a6fb
2 changed files with 75 additions and 28 deletions

View file

@ -689,6 +689,23 @@ static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
return (d*Zproj - c) / (a - b*Zproj);
}
static void build_fog_table(BYTE *fog_table, DWORD fog_color) {
int i;
TRACE(" rebuilding fog table (%06lx)...\n", fog_color & 0x00FFFFFF);
for (i = 0; i < 3; i++) {
BYTE fog_color_component = (fog_color >> (8 * i)) & 0xFF;
DWORD elt;
for (elt = 0; elt < 0x10000; elt++) {
/* We apply the fog transformation and cache the result */
DWORD fog_intensity = elt & 0xFF;
DWORD vertex_color = (elt >> 8) & 0xFF;
fog_table[(i * 0x10000) + elt] = ((fog_intensity * vertex_color) + ((0xFF - fog_intensity) * fog_color_component)) / 0xFF;
}
}
}
static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
BOOLEAN vertex_transformed,
BOOLEAN vertex_lit) {
@ -710,29 +727,44 @@ static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
glThis->transform_state = GL_TRANSFORM_ORTHO;
d3ddevice_set_ortho(This);
}
if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
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);
/* TODO: optimize this to not always reset all the fog stuff on all DrawPrimitive call
if no fogging state change occured */
if (This->state_block.render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
if (vertex_transformed == TRUE) {
glDisable(GL_FOG);
/* Now check if our fog_table still corresponds to the current vertex color.
Element '0x..00' is always the fog color as it corresponds to maximum fog intensity */
if ((glThis->fog_table[0 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 0) & 0xFF)) ||
(glThis->fog_table[1 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 8) & 0xFF)) ||
(glThis->fog_table[2 * 0x10000 + 0x0000] != ((This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1] >> 16) & 0xFF))) {
/* We need to rebuild our fog table.... */
build_fog_table(glThis->fog_table, This->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
}
} else {
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;
}
if (vertex_lit == FALSE) {
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]);
} else {
/* Special case of 'pixel fog' */
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 {
glDisable(GL_FOG);
}
}
} else {
glDisable(GL_FOG);
}
/* Handle the 'no-normal' case */
if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE))
glEnable(GL_LIGHTING);
@ -950,15 +982,21 @@ inline static void handle_specular(STATEBLOCK *sb, DWORD *color, BOOLEAN lighted
/* No else here as we do not know how to handle 'specular' on its own in any case.. */
}
inline static void handle_diffuse_and_specular(STATEBLOCK *sb, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
inline static void handle_diffuse_and_specular(STATEBLOCK *sb, BYTE *fog_table, DWORD *color_d, DWORD *color_s, BOOLEAN lighted) {
if (lighted == TRUE) {
DWORD color = *color_d;
if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
/* Special case where the specular value is used to do fogging. TODO */
/* Special case where the specular value is used to do fogging */
BYTE fog_intensity = *color_s >> 24; /* The alpha value of the specular component is the fog 'intensity' for this vertex */
color &= 0xFF000000; /* Only keep the alpha component */
color |= fog_table[((*color_d >> 0) & 0xFF) << 8 | fog_intensity] << 0;
color |= fog_table[((*color_d >> 8) & 0xFF) << 8 | fog_intensity] << 8;
color |= fog_table[((*color_d >> 16) & 0xFF) << 8 | fog_intensity] << 16;
}
if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
/* Standard specular value in transformed mode. TODO */
}
handle_diffuse_base(sb, color_d);
handle_diffuse_base(sb, &color);
} else {
if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
handle_diffuse(sb, color_d, FALSE);
@ -989,7 +1027,8 @@ static void draw_primitive_strided(IDirect3DDeviceImpl *This,
DWORD dwFlags)
{
BOOLEAN vertex_lighted = (d3dvtVertexType & D3DFVF_NORMAL) == 0;
IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
if (TRACE_ON(ddraw)) {
TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
}
@ -1036,7 +1075,7 @@ static void draw_primitive_strided(IDirect3DDeviceImpl *This,
D3DVALUE *position =
(D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
handle_diffuse_and_specular(&(This->state_block), color_d, color_s, TRUE);
handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, TRUE);
handle_texture(tex_coord);
handle_xyzrhw(position);
@ -1071,7 +1110,7 @@ static void draw_primitive_strided(IDirect3DDeviceImpl *This,
(DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
DWORD *color_s =
(DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
handle_diffuse_and_specular(&(This->state_block), color_d, color_s, vertex_lighted);
handle_diffuse_and_specular(&(This->state_block), glThis->fog_table, color_d, color_s, vertex_lighted);
} else {
if (d3dvtVertexType & D3DFVF_SPECULAR) {
DWORD *color_s =
@ -2294,5 +2333,8 @@ d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfa
apply_render_state(object, &object->state_block);
/* FIXME: do something similar for ligh_state and texture_stage_state */
/* And fill the fog table with the default fog value */
build_fog_table(gl_object->fog_table, object->state_block.render_state[D3DRENDERSTATE_FOGCOLOR - 1]);
return DD_OK;
}

View file

@ -104,6 +104,11 @@ typedef struct IDirect3DDeviceGLImpl
/* The last type of vertex drawn */
GL_TRANSFORM_STATE transform_state;
/* Used to handle fogging faster... */
BYTE fog_table[3 * 0x10000]; /* 3 is for R, G and B
0x10000 is 0xFF for the vertex color and
0xFF for the fog intensity */
Display *display;
Drawable drawable;
} IDirect3DDeviceGLImpl;