Added fogging for transformed vertices.
This commit is contained in:
parent
62ed0ffe00
commit
6238f9a6fb
|
@ -689,6 +689,23 @@ static float ZfromZproj(IDirect3DDeviceImpl *This, D3DVALUE Zproj)
|
||||||
return (d*Zproj - c) / (a - b*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,
|
static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
|
||||||
BOOLEAN vertex_transformed,
|
BOOLEAN vertex_transformed,
|
||||||
BOOLEAN vertex_lit) {
|
BOOLEAN vertex_lit) {
|
||||||
|
@ -710,28 +727,43 @@ static void draw_primitive_handle_GL_state(IDirect3DDeviceImpl *This,
|
||||||
glThis->transform_state = GL_TRANSFORM_ORTHO;
|
glThis->transform_state = GL_TRANSFORM_ORTHO;
|
||||||
d3ddevice_set_ortho(This);
|
d3ddevice_set_ortho(This);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* 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 (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) {
|
if (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1] != D3DFOG_NONE) {
|
||||||
switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
|
switch (This->state_block.render_state[D3DRENDERSTATE_FOGTABLEMODE - 1]) {
|
||||||
case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
|
case D3DFOG_LINEAR: glFogi(GL_FOG_MODE, GL_LINEAR); break;
|
||||||
case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
|
case D3DFOG_EXP: glFogi(GL_FOG_MODE, GL_EXP); break;
|
||||||
case D3DFOG_EXP2: glFogi(GL_FOG_MODE, GL_EXP2); 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]));
|
if (vertex_lit == FALSE) {
|
||||||
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_START, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGSTART - 1]);
|
||||||
glFogf(GL_FOG_END, *(float*)&This->state_block.render_state[D3DRENDERSTATE_FOGEND - 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);
|
glEnable(GL_FOG);
|
||||||
} else
|
} else {
|
||||||
glDisable(GL_FOG);
|
glDisable(GL_FOG);
|
||||||
}
|
}
|
||||||
else
|
}
|
||||||
|
} else {
|
||||||
glDisable(GL_FOG);
|
glDisable(GL_FOG);
|
||||||
|
}
|
||||||
|
|
||||||
/* Handle the 'no-normal' case */
|
/* Handle the 'no-normal' case */
|
||||||
if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE))
|
if ((vertex_lit == FALSE) && (This->state_block.render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE))
|
||||||
|
@ -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.. */
|
/* 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) {
|
if (lighted == TRUE) {
|
||||||
|
DWORD color = *color_d;
|
||||||
if (sb->render_state[D3DRENDERSTATE_FOGENABLE - 1] == TRUE) {
|
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) {
|
if (sb->render_state[D3DRENDERSTATE_SPECULARENABLE - 1] == TRUE) {
|
||||||
/* Standard specular value in transformed mode. TODO */
|
/* Standard specular value in transformed mode. TODO */
|
||||||
}
|
}
|
||||||
handle_diffuse_base(sb, color_d);
|
handle_diffuse_base(sb, &color);
|
||||||
} else {
|
} else {
|
||||||
if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
|
if (sb->render_state[D3DRENDERSTATE_LIGHTING - 1] == TRUE) {
|
||||||
handle_diffuse(sb, color_d, FALSE);
|
handle_diffuse(sb, color_d, FALSE);
|
||||||
|
@ -989,6 +1027,7 @@ static void draw_primitive_strided(IDirect3DDeviceImpl *This,
|
||||||
DWORD dwFlags)
|
DWORD dwFlags)
|
||||||
{
|
{
|
||||||
BOOLEAN vertex_lighted = (d3dvtVertexType & D3DFVF_NORMAL) == 0;
|
BOOLEAN vertex_lighted = (d3dvtVertexType & D3DFVF_NORMAL) == 0;
|
||||||
|
IDirect3DDeviceGLImpl* glThis = (IDirect3DDeviceGLImpl*) This;
|
||||||
|
|
||||||
if (TRACE_ON(ddraw)) {
|
if (TRACE_ON(ddraw)) {
|
||||||
TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
|
TRACE(" Vertex format : "); dump_flexible_vertex(d3dvtVertexType);
|
||||||
|
@ -1036,7 +1075,7 @@ static void draw_primitive_strided(IDirect3DDeviceImpl *This,
|
||||||
D3DVALUE *position =
|
D3DVALUE *position =
|
||||||
(D3DVALUE *) (((char *) lpD3DDrawPrimStrideData->position.lpvData) + i * lpD3DDrawPrimStrideData->position.dwStride);
|
(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_texture(tex_coord);
|
||||||
handle_xyzrhw(position);
|
handle_xyzrhw(position);
|
||||||
|
|
||||||
|
@ -1071,7 +1110,7 @@ static void draw_primitive_strided(IDirect3DDeviceImpl *This,
|
||||||
(DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
|
(DWORD *) (((char *) lpD3DDrawPrimStrideData->diffuse.lpvData) + i * lpD3DDrawPrimStrideData->diffuse.dwStride);
|
||||||
DWORD *color_s =
|
DWORD *color_s =
|
||||||
(DWORD *) (((char *) lpD3DDrawPrimStrideData->specular.lpvData) + i * lpD3DDrawPrimStrideData->specular.dwStride);
|
(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 {
|
} else {
|
||||||
if (d3dvtVertexType & D3DFVF_SPECULAR) {
|
if (d3dvtVertexType & D3DFVF_SPECULAR) {
|
||||||
DWORD *color_s =
|
DWORD *color_s =
|
||||||
|
@ -2294,5 +2333,8 @@ d3ddevice_create(IDirect3DDeviceImpl **obj, IDirect3DImpl *d3d, IDirectDrawSurfa
|
||||||
apply_render_state(object, &object->state_block);
|
apply_render_state(object, &object->state_block);
|
||||||
/* FIXME: do something similar for ligh_state and texture_stage_state */
|
/* 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;
|
return DD_OK;
|
||||||
}
|
}
|
||||||
|
|
|
@ -104,6 +104,11 @@ typedef struct IDirect3DDeviceGLImpl
|
||||||
/* The last type of vertex drawn */
|
/* The last type of vertex drawn */
|
||||||
GL_TRANSFORM_STATE transform_state;
|
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;
|
Display *display;
|
||||||
Drawable drawable;
|
Drawable drawable;
|
||||||
} IDirect3DDeviceGLImpl;
|
} IDirect3DDeviceGLImpl;
|
||||||
|
|
Loading…
Reference in New Issue