You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1232 lines
41 KiB
1232 lines
41 KiB
/*==========================================================================;
|
|
*
|
|
* Copyright (C) 1995 Microsoft Corporation. All Rights Reserved.
|
|
*
|
|
* File: rgblt.cpp
|
|
* Content: Direct3D lighting
|
|
*
|
|
***************************************************************************/
|
|
|
|
#include "pch.cpp"
|
|
#pragma hdrstop
|
|
|
|
#include "light.h"
|
|
#include "drawprim.hpp"
|
|
|
|
extern "C"
|
|
{
|
|
void Directional2(LPD3DFE_PROCESSVERTICES pv,
|
|
D3DI_LIGHT *light,
|
|
D3DLIGHTINGELEMENT *in);
|
|
void PointSpot2(LPD3DFE_PROCESSVERTICES pv,
|
|
D3DI_LIGHT *light,
|
|
D3DLIGHTINGELEMENT *in);
|
|
void Directional1C(LPD3DFE_PROCESSVERTICES pv,
|
|
D3DI_LIGHT *light,
|
|
D3DLIGHTINGELEMENT *in);
|
|
void PointSpot1C(LPD3DFE_PROCESSVERTICES pv,
|
|
D3DI_LIGHT *light,
|
|
D3DLIGHTINGELEMENT *in);
|
|
void PointSpotXCRamp(LPD3DFE_PROCESSVERTICES pv,
|
|
D3DI_LIGHT *light,
|
|
D3DLIGHTINGELEMENT *in);
|
|
|
|
//#define _USE_ASM_
|
|
#ifdef _X86_
|
|
#ifdef _USE_ASM_
|
|
|
|
void Directional2P5S(LPD3DFE_PROCESSVERTICES pv,
|
|
D3DI_LIGHT *light,
|
|
D3DLIGHTINGELEMENT *in);
|
|
void Directional2P5(LPD3DFE_PROCESSVERTICES pv,
|
|
D3DI_LIGHT *light,
|
|
D3DLIGHTINGELEMENT *in);
|
|
|
|
#endif _X86_
|
|
#endif _USE_ASM_
|
|
}
|
|
|
|
static LIGHT_VERTEX_FUNC_TABLE lightVertexTable =
|
|
{
|
|
Directional1C,
|
|
Directional2,
|
|
PointSpot1C,
|
|
PointSpot2,
|
|
PointSpot1C,
|
|
PointSpot2
|
|
};
|
|
|
|
HRESULT D3DFE_InitRGBLighting(LPDIRECT3DDEVICEI lpDevI)
|
|
{
|
|
LIST_INITIALIZE(&lpDevI->specular_tables);
|
|
lpDevI->specular_table = NULL;
|
|
|
|
LIST_INITIALIZE(&lpDevI->materials);
|
|
|
|
STATESET_INIT(lpDevI->lightstate_overrides);
|
|
lpDevI->lightVertexFuncTable = &lightVertexTable;
|
|
|
|
lpDevI->lighting.activeLights = NULL;
|
|
|
|
return (D3D_OK);
|
|
}
|
|
|
|
void D3DFE_DestroyRGBLighting(LPDIRECT3DDEVICEI lpDevI)
|
|
{
|
|
SpecularTable *spec;
|
|
SpecularTable *spec_next;
|
|
|
|
for (spec = LIST_FIRST(&lpDevI->specular_tables); spec; spec = spec_next)
|
|
{
|
|
spec_next = LIST_NEXT(spec,list);
|
|
D3DFree(spec);
|
|
}
|
|
|
|
while (LIST_FIRST(&lpDevI->materials))
|
|
{
|
|
LPD3DFE_MATERIAL lpMat;
|
|
lpMat = LIST_FIRST(&lpDevI->materials);
|
|
LIST_DELETE(lpMat, link);
|
|
D3DFree(lpMat);
|
|
}
|
|
}
|
|
|
|
HRESULT D3DHEL_ApplyFog(D3DFE_LIGHTING* driver, int count, D3DLIGHTDATA* data)
|
|
{
|
|
D3DTLVERTEX *v;
|
|
size_t v_size;
|
|
D3DVALUE fog_start = driver->fog_start;
|
|
D3DVALUE fog_end = driver->fog_end;
|
|
D3DVALUE fog_length = RLDDIFInvert16(fog_end - fog_start);
|
|
int i;
|
|
|
|
v = (D3DTLVERTEX*)data->lpOut;
|
|
v_size = data->dwOutSize;
|
|
|
|
for (i = count; i; i--)
|
|
{
|
|
D3DVALUE w;
|
|
int f;
|
|
if ((v->rhw < D3DVAL(1)) && (v->rhw > 0))
|
|
w = RLDDIFInvert24(v->rhw);
|
|
else
|
|
w = v->rhw;
|
|
if (w < fog_start)
|
|
f = 255;
|
|
else if (w >= fog_end)
|
|
f = 0;
|
|
else
|
|
f = VALTOFXP(DECPREC(RLDDIFMul16(fog_end - w, fog_length), 8), 8);
|
|
if (f > 255) f = 255;
|
|
if (f < 0) f = 0;
|
|
v->specular = RGBA_SETALPHA(v->specular, f);
|
|
v = (D3DTLVERTEX*)((char*)v + v_size);
|
|
}
|
|
return D3D_OK;
|
|
}
|
|
|
|
static void inverseRotateVector(D3DVECTOR* d,
|
|
D3DVECTOR* v, D3DMATRIXI* M)
|
|
{
|
|
D3DVALUE vx = v->x;
|
|
D3DVALUE vy = v->y;
|
|
D3DVALUE vz = v->z;
|
|
d->x = RLDDIFMul16(vx, M->_11) + RLDDIFMul16(vy, M->_12) + RLDDIFMul16(vz, M->_13);
|
|
d->y = RLDDIFMul16(vx, M->_21) + RLDDIFMul16(vy, M->_22) + RLDDIFMul16(vz, M->_23);
|
|
d->z = RLDDIFMul16(vx, M->_31) + RLDDIFMul16(vy, M->_32) + RLDDIFMul16(vz, M->_33);
|
|
}
|
|
|
|
static void inverseTransformVector(D3DVECTOR* d,
|
|
D3DVECTOR* v, D3DMATRIXI* M)
|
|
{
|
|
D3DVALUE vx = v->x;
|
|
D3DVALUE vy = v->y;
|
|
D3DVALUE vz = v->z;
|
|
vx -= M->_41; vy -= M->_42; vz -= M->_43;
|
|
d->x = RLDDIFMul16(vx, M->_11) + RLDDIFMul16(vy, M->_12) + RLDDIFMul16(vz, M->_13);
|
|
d->y = RLDDIFMul16(vx, M->_21) + RLDDIFMul16(vy, M->_22) + RLDDIFMul16(vz, M->_23);
|
|
d->z = RLDDIFMul16(vx, M->_31) + RLDDIFMul16(vy, M->_32) + RLDDIFMul16(vz, M->_33);
|
|
}
|
|
|
|
/*
|
|
* Every time the world matrix is modified the lighting vectors have to
|
|
* change to match the model space of the new data to be rendered
|
|
*/
|
|
|
|
#define SMALLISH (1e-2)
|
|
#define ONEISH(v) (fabs(v - 1.0f) < SMALLISH)
|
|
|
|
static int getMatrixScale(D3DMATRIXI* m, D3DVECTOR* s)
|
|
{
|
|
s->x = (m->_11 * m->_11 + m->_12 * m->_12 + m->_13 * m->_13);
|
|
s->y = (m->_21 * m->_21 + m->_22 * m->_22 + m->_23 * m->_23);
|
|
s->z = (m->_31 * m->_31 + m->_32 * m->_32 + m->_33 * m->_33);
|
|
|
|
if (ONEISH(s->x) && ONEISH(s->y) && ONEISH(s->z))
|
|
return FALSE;
|
|
else
|
|
{
|
|
s->x = (D3DVALUE)(1.0f / s->x);
|
|
s->y = (D3DVALUE)(1.0f / s->y);
|
|
s->z = (D3DVALUE)(1.0f / s->z);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
static int
|
|
getMatrixScale2(D3DMATRIXI *m, D3DVECTOR *s)
|
|
{
|
|
float det;
|
|
|
|
s->x = (float)sqrt(m->_11*m->_11 + m->_12*m->_12 + m->_13*m->_13);
|
|
s->y = (float)sqrt(m->_21*m->_21 + m->_22*m->_22 + m->_23*m->_23);
|
|
s->z = (float)sqrt(m->_31*m->_31 + m->_32*m->_32 + m->_33*m->_33);
|
|
|
|
if (ONEISH(s->x) && ONEISH(s->y) && ONEISH(s->z))
|
|
{
|
|
return FALSE;
|
|
}
|
|
else
|
|
{
|
|
det = m->_11*(m->_22*m->_33 - m->_23*m->_32)
|
|
- m->_12*(m->_21*m->_33 - m->_23*m->_31)
|
|
+ m->_13*(m->_21*m->_32 - m->_22*m->_31);
|
|
|
|
if (det<0.0)
|
|
{
|
|
s->x = (-s->x);
|
|
s->y = (-s->y);
|
|
s->z = (-s->z);
|
|
}
|
|
|
|
// prevent 0 scales from sneaking through
|
|
if (fabs(s->x) < 0.0001)
|
|
s->x = 0.0001f;
|
|
if (fabs(s->y) < 0.0001)
|
|
s->y = 0.0001f;
|
|
if (fabs(s->z) < 0.0001)
|
|
s->z = 0.0001f;
|
|
|
|
return TRUE;
|
|
}
|
|
} // end of getMatrixScale2()
|
|
|
|
//-----------------------------------------------------------------------
|
|
// Every time the world matrix is modified or lights data is changed the
|
|
// lighting vectors have to change to match the model space of the new data
|
|
// to be rendered.
|
|
// Every time light data is changed or material data is changed or lighting
|
|
// state is changed, some pre-computed lighting values sould be updated
|
|
//
|
|
void D3DFE_UpdateLights(LPDIRECT3DDEVICEI lpDevI)
|
|
{
|
|
D3DFE_LIGHTING& LIGHTING = lpDevI->lighting;
|
|
D3DI_LIGHT *light = LIGHTING.activeLights;
|
|
D3DVECTOR t;
|
|
D3DMATRIXI *world;
|
|
D3DMATRIXI *camera;
|
|
D3DMATERIAL *mat;
|
|
D3DVECTOR cameraModel;
|
|
D3DVECTOR cameraWorld;
|
|
D3DVECTOR cameraModelNorm; // Normalized
|
|
D3DVECTOR scale1;
|
|
D3DVECTOR scale2;
|
|
D3DVECTOR oneOverScale;
|
|
BOOL cameraModelNormComputed = FALSE;
|
|
BOOL scale1Computed = FALSE; // For light 1
|
|
BOOL scale2Computed = FALSE; // For light 2
|
|
BOOL need_scale1;
|
|
BOOL need_scale2;
|
|
BOOL specular; // TRUE, if specular component sould be computed
|
|
|
|
|
|
if (lpDevI->dwFEFlags & D3DFE_NEED_TRANSFORM_LIGHTS)
|
|
{
|
|
D3DVECTOR t;
|
|
|
|
world = &lpDevI->transform.world;
|
|
camera = &lpDevI->transform.view;
|
|
t.x = -camera->_41;
|
|
t.y = -camera->_42;
|
|
t.z = -camera->_43;
|
|
|
|
// transform the eye into world coords.
|
|
inverseRotateVector(&cameraWorld, &t, camera);
|
|
|
|
// now transform eye into model space
|
|
inverseTransformVector(&cameraModel, &cameraWorld, world);
|
|
}
|
|
|
|
if (lpDevI->dwFEFlags & (D3DFE_MATERIAL_DIRTY | D3DFE_LIGHTS_DIRTY))
|
|
{
|
|
mat = &LIGHTING.material;
|
|
if (lpDevI->specular_table &&
|
|
lpDevI->rstates[D3DRENDERSTATE_SPECULARENABLE])
|
|
{
|
|
specular = TRUE;
|
|
lpDevI->dwFEFlags |= D3DFE_COMPUTESPECULAR;
|
|
}
|
|
else
|
|
{
|
|
specular = FALSE;
|
|
lpDevI->dwFEFlags &= ~D3DFE_COMPUTESPECULAR;
|
|
}
|
|
|
|
LIGHTING.materialAlpha = FTOI(D3DVAL(255) * mat->diffuse.a);
|
|
if (LIGHTING.materialAlpha < 0)
|
|
LIGHTING.materialAlpha = 0;
|
|
else
|
|
if (LIGHTING.materialAlpha > 255)
|
|
LIGHTING.materialAlpha = 255 << 24;
|
|
else LIGHTING.materialAlpha <<= 24;
|
|
|
|
LIGHTING.currentSpecTable = lpDevI->specular_table->table;
|
|
|
|
if (!(lpDevI->dwDeviceFlags & D3DDEV_RAMP))
|
|
{
|
|
LIGHTING.diffuse0.r = LIGHTING.ambient_red * mat->ambient.r +
|
|
mat->emissive.r * D3DVAL(255);
|
|
LIGHTING.diffuse0.g = LIGHTING.ambient_green * mat->ambient.g +
|
|
mat->emissive.g * D3DVAL(255);
|
|
LIGHTING.diffuse0.b = LIGHTING.ambient_blue * mat->ambient.b +
|
|
mat->emissive.b * D3DVAL(255);
|
|
}
|
|
}
|
|
|
|
while (light)
|
|
{
|
|
if (lpDevI->dwFEFlags & D3DFE_NEED_TRANSFORM_LIGHTS)
|
|
{
|
|
if (light->type != D3DLIGHT_DIRECTIONAL)
|
|
{
|
|
// Transform light position to the model space
|
|
t.x = light->position.x - world->_41;
|
|
t.y = light->position.y - world->_42;
|
|
t.z = light->position.z - world->_43;
|
|
inverseRotateVector(&light->model_position, &t, world);
|
|
}
|
|
|
|
if (light->version == 1)
|
|
{
|
|
if (!scale1Computed)
|
|
{
|
|
need_scale1 = getMatrixScale(world, &scale1);
|
|
scale1Computed = TRUE;
|
|
}
|
|
if (!need_scale1)
|
|
light->flags |= D3DLIGHTI_UNIT_SCALE;
|
|
else
|
|
{
|
|
if (light->type != D3DLIGHT_DIRECTIONAL)
|
|
{
|
|
light->model_position.x *= scale1.x;
|
|
light->model_position.y *= scale1.y;
|
|
light->model_position.z *= scale1.z;
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (!scale2Computed)
|
|
{
|
|
need_scale2 = getMatrixScale2(world, &scale2);
|
|
scale2Computed = TRUE;
|
|
}
|
|
if (!need_scale2)
|
|
light->flags |= D3DLIGHTI_UNIT_SCALE;
|
|
else
|
|
{
|
|
light->model_scale.x = scale2.x;
|
|
light->model_scale.y = scale2.y;
|
|
light->model_scale.z = scale2.z;
|
|
oneOverScale.x = D3DVAL(1)/scale2.x;
|
|
oneOverScale.y = D3DVAL(1)/scale2.y;
|
|
oneOverScale.z = D3DVAL(1)/scale2.z;
|
|
light->flags &= ~D3DLIGHTI_UNIT_SCALE;
|
|
}
|
|
}
|
|
|
|
if (light->type != D3DLIGHT_POINT)
|
|
{
|
|
if (light->type == D3DLIGHT_PARALLELPOINT)
|
|
{
|
|
light->model_direction = light->model_position;
|
|
}
|
|
else
|
|
{
|
|
// Transform light direction to the model space
|
|
inverseRotateVector(&light->model_direction,
|
|
&light->direction, world);
|
|
VecNeg(light->model_direction, light->model_direction);
|
|
}
|
|
if (light->version != 1 && need_scale2)
|
|
{
|
|
// apply scale here before normalizing
|
|
light->model_direction.x *= oneOverScale.x;
|
|
light->model_direction.y *= oneOverScale.y;
|
|
light->model_direction.z *= oneOverScale.z;
|
|
}
|
|
if (need_scale1 || need_scale2 ||
|
|
light->type == D3DLIGHT_PARALLELPOINT)
|
|
VecNormalizeFast(light->model_direction);
|
|
}
|
|
|
|
if (light->version == 1)
|
|
{
|
|
if (!cameraModelNormComputed)
|
|
{
|
|
VecNormalizeFast2(cameraModel, cameraModelNorm);
|
|
cameraModelNormComputed = TRUE;
|
|
}
|
|
|
|
if (light->type == D3DLIGHT_DIRECTIONAL)
|
|
{
|
|
t = light->model_direction;
|
|
}
|
|
else
|
|
{
|
|
t = light->model_position;
|
|
}
|
|
// calc halfway vector
|
|
VecNormalizeFast(t);
|
|
VecAdd(t, cameraModelNorm, light->halfway);
|
|
VecNormalizeFast(light->halfway);
|
|
}
|
|
else
|
|
{
|
|
// We want to compare cameraWorld position with the light to
|
|
// see if they match
|
|
if (fabs(light->position.x-cameraWorld.x) < 0.0001 &&
|
|
fabs(light->position.y-cameraWorld.y) < 0.0001 &&
|
|
fabs(light->position.z-cameraWorld.z) < 0.0001)
|
|
{
|
|
light->flags |= D3DLIGHTI_LIGHT_AT_EYE;
|
|
}
|
|
else
|
|
{
|
|
light->flags &= ~D3DLIGHTI_LIGHT_AT_EYE;
|
|
}
|
|
|
|
// store location of eye in model space
|
|
if (light->flags & D3DLIGHTI_UNIT_SCALE)
|
|
{
|
|
light->model_eye = cameraModel;
|
|
}
|
|
else
|
|
{
|
|
light->model_eye.x = cameraModel.x * oneOverScale.x;
|
|
light->model_eye.y = cameraModel.y * oneOverScale.y;
|
|
light->model_eye.z = cameraModel.z * oneOverScale.z;
|
|
if (light->type == D3DLIGHT_POINT ||
|
|
light->type == D3DLIGHT_SPOT)
|
|
{
|
|
light->model_position.x *= oneOverScale.x;
|
|
light->model_position.y *= oneOverScale.y;
|
|
light->model_position.z *= oneOverScale.z;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if (lpDevI->dwFEFlags & (D3DFE_MATERIAL_DIRTY | D3DFE_LIGHTS_DIRTY))
|
|
{
|
|
if (!(lpDevI->dwDeviceFlags & D3DDEV_RAMP))
|
|
{
|
|
light->local_diffR = D3DVAL(255) * mat->diffuse.r * light->red;
|
|
light->local_diffG = D3DVAL(255) * mat->diffuse.g * light->green;
|
|
light->local_diffB = D3DVAL(255) * mat->diffuse.b * light->blue;
|
|
|
|
light->local_specR = D3DVAL(255) * mat->specular.r * light->red;
|
|
light->local_specG = D3DVAL(255) * mat->specular.g * light->green;
|
|
light->local_specB = D3DVAL(255) * mat->specular.b * light->blue;
|
|
}
|
|
else
|
|
{
|
|
light->local_diffR = light->shade;
|
|
light->local_specR = light->shade;
|
|
}
|
|
|
|
if (specular && !(light->flags & D3DLIGHT_NO_SPECULAR))
|
|
light->flags |= D3DLIGHTI_COMPUTE_SPECULAR;
|
|
else
|
|
light->flags &= ~D3DLIGHTI_COMPUTE_SPECULAR;
|
|
}
|
|
|
|
if (lpDevI->dwFEFlags & D3DFE_LIGHTS_DIRTY)
|
|
{
|
|
light->lightVertexFunc = NULL;
|
|
if (light->version == 1)
|
|
{
|
|
switch (light->type)
|
|
{
|
|
case D3DLIGHT_PARALLELPOINT:
|
|
case D3DLIGHT_DIRECTIONAL:
|
|
light->lightVertexFunc =
|
|
lpDevI->lightVertexFuncTable->directional1;
|
|
break;
|
|
case D3DLIGHT_POINT:
|
|
if (lpDevI->dwDeviceFlags & D3DDEV_RAMP)
|
|
{
|
|
light->lightVertexFunc = PointSpotXCRamp;
|
|
}
|
|
else
|
|
{
|
|
light->lightVertexFunc =
|
|
lpDevI->lightVertexFuncTable->point1;
|
|
}
|
|
break;
|
|
case D3DLIGHT_SPOT:
|
|
if (lpDevI->dwDeviceFlags & D3DDEV_RAMP)
|
|
{
|
|
light->lightVertexFunc = PointSpotXCRamp;
|
|
}
|
|
else
|
|
{
|
|
light->lightVertexFunc =
|
|
lpDevI->lightVertexFuncTable->spot1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
switch (light->type)
|
|
{
|
|
case D3DLIGHT_PARALLELPOINT:
|
|
case D3DLIGHT_DIRECTIONAL:
|
|
{
|
|
#ifdef _X86_
|
|
#ifdef _USE_ASM_
|
|
if (light->flags & D3DLIGHTI_UNIT_SCALE &&
|
|
!(lpDevI->dwDeviceFlags & D3DDEV_RAMP) &&
|
|
!(lpDevI->dwFEFlags & D3DFE_COLORVERTEX))
|
|
{
|
|
if (light->flags & D3DLIGHTI_COMPUTE_SPECULAR)
|
|
light->lightVertexFunc = Directional2P5S;
|
|
else
|
|
light->lightVertexFunc = Directional2P5;
|
|
}
|
|
else
|
|
#endif _USE_ASM_
|
|
#endif // _X86_
|
|
light->lightVertexFunc =
|
|
lpDevI->lightVertexFuncTable->directional2;
|
|
break;
|
|
}
|
|
case D3DLIGHT_POINT:
|
|
if (lpDevI->dwDeviceFlags & D3DDEV_RAMP)
|
|
{
|
|
light->lightVertexFunc = PointSpotXCRamp;
|
|
}
|
|
else
|
|
{
|
|
light->lightVertexFunc =
|
|
lpDevI->lightVertexFuncTable->point2;
|
|
}
|
|
break;
|
|
case D3DLIGHT_SPOT:
|
|
if (lpDevI->dwDeviceFlags & D3DDEV_RAMP)
|
|
{
|
|
light->lightVertexFunc = PointSpotXCRamp;
|
|
}
|
|
else
|
|
{
|
|
light->lightVertexFunc =
|
|
lpDevI->lightVertexFuncTable->spot2;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
light = light->next;
|
|
}
|
|
|
|
lpDevI->dwFEFlags &= ~(D3DFE_MATERIAL_DIRTY |
|
|
D3DFE_NEED_TRANSFORM_LIGHTS |
|
|
D3DFE_LIGHTS_DIRTY);
|
|
} // end of updateLights()
|
|
//---------------------------------------------------------------------
|
|
inline D3DVALUE COMPUTE_DOT_POW(D3DFE_LIGHTING *ldrv, D3DVALUE dot)
|
|
{
|
|
ldrv->specularComputed = TRUE;
|
|
if (dot < 1.0f)
|
|
{
|
|
int indx;
|
|
float v;
|
|
dot *= 255.0f;
|
|
indx = (int)dot;
|
|
dot -= indx;
|
|
v = ldrv->currentSpecTable[indx];
|
|
return v + (ldrv->currentSpecTable[indx+1] - v)*dot;
|
|
}
|
|
else
|
|
return 1.0f;
|
|
}
|
|
//---------------------------------------------------------------------
|
|
inline void COMPUTE_SPECULAR(LPD3DFE_PROCESSVERTICES pv,
|
|
D3DVALUE dot,
|
|
D3DI_LIGHT *light)
|
|
{
|
|
D3DFE_LIGHTING &ldrv = pv->lighting;
|
|
if (FLOAT_CMP_POS(dot, >=, ldrv.specThreshold))
|
|
{
|
|
D3DVALUE power;
|
|
power = COMPUTE_DOT_POW(&ldrv, dot);
|
|
if (pv->dwDeviceFlags & D3DDEV_RAMP)
|
|
{
|
|
ldrv.specular.r += light->shade * power;
|
|
}
|
|
else
|
|
if (!(pv->dwFlags & D3DPV_COLORVERTEXS))
|
|
{
|
|
ldrv.specular.r += light->local_specR * power;
|
|
ldrv.specular.g += light->local_specG * power;
|
|
ldrv.specular.b += light->local_specB * power;
|
|
}
|
|
else
|
|
{
|
|
ldrv.specular.r += light->red * ldrv.vertexSpecular.r * power;
|
|
ldrv.specular.g += light->green * ldrv.vertexSpecular.g * power;
|
|
ldrv.specular.b += light->blue * ldrv.vertexSpecular.b * power;
|
|
}
|
|
}
|
|
}
|
|
//---------------------------------------------------------------------
|
|
inline void COMPUTE_SPECULAR_ATT(LPD3DFE_PROCESSVERTICES pv,
|
|
D3DVALUE dot,
|
|
D3DI_LIGHT *light,
|
|
D3DVALUE att)
|
|
{
|
|
D3DFE_LIGHTING &ldrv = pv->lighting;
|
|
if (FLOAT_CMP_POS(dot, >=, ldrv.specThreshold))
|
|
{
|
|
D3DVALUE power;
|
|
power = COMPUTE_DOT_POW(&ldrv, dot);
|
|
power *= att;
|
|
if (pv->dwDeviceFlags & D3DDEV_RAMP)
|
|
{
|
|
ldrv.specular.r += light->shade * power;
|
|
}
|
|
else
|
|
if (!(pv->dwFlags & D3DPV_COLORVERTEXS))
|
|
{
|
|
ldrv.specular.r += light->local_specR * power;
|
|
ldrv.specular.g += light->local_specG * power;
|
|
ldrv.specular.b += light->local_specB * power;
|
|
}
|
|
else
|
|
{
|
|
ldrv.specular.r += light->red * ldrv.vertexSpecular.r * power;
|
|
ldrv.specular.g += light->green * ldrv.vertexSpecular.g * power;
|
|
ldrv.specular.b += light->blue * ldrv.vertexSpecular.b * power;
|
|
}
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
void Directional2(LPD3DFE_PROCESSVERTICES pv,
|
|
D3DI_LIGHT *light,
|
|
D3DLIGHTINGELEMENT *in)
|
|
{
|
|
D3DFE_LIGHTING &ldrv = pv->lighting;
|
|
D3DVALUE dot;
|
|
dot = VecDot(light->model_direction, in->dvNormal);
|
|
if (FLOAT_GTZ(dot))
|
|
{
|
|
if (pv->dwDeviceFlags & D3DDEV_RAMP)
|
|
{
|
|
ldrv.diffuse.r += light->shade * dot;
|
|
}
|
|
else
|
|
if (!(pv->dwFlags & D3DPV_COLORVERTEX))
|
|
{
|
|
ldrv.diffuse.r += light->local_diffR * dot;
|
|
ldrv.diffuse.g += light->local_diffG * dot;
|
|
ldrv.diffuse.b += light->local_diffB * dot;
|
|
}
|
|
else
|
|
{
|
|
ldrv.diffuse.r += light->red * ldrv.vertexDiffuse.r * dot;
|
|
ldrv.diffuse.g += light->green * ldrv.vertexDiffuse.g * dot;
|
|
ldrv.diffuse.b += light->blue * ldrv.vertexDiffuse.b * dot;
|
|
}
|
|
|
|
if (light->flags & D3DLIGHTI_COMPUTE_SPECULAR)
|
|
{
|
|
D3DVECTOR h; // halfway vector
|
|
D3DVECTOR eye; // incident vector ie vector from eye
|
|
// calc incident vector
|
|
if (light->flags & D3DLIGHTI_UNIT_SCALE)
|
|
{
|
|
VecSub(in->dvPosition, light->model_eye, eye);
|
|
}
|
|
else
|
|
{
|
|
// note that model_eye has already been divided by scale
|
|
// in setup
|
|
eye.x = in->dvPosition.x*light->model_scale.x -
|
|
light->model_eye.x;
|
|
eye.y = in->dvPosition.y*light->model_scale.y -
|
|
light->model_eye.y;
|
|
eye.z = in->dvPosition.z*light->model_scale.z -
|
|
light->model_eye.z;
|
|
}
|
|
// normalize
|
|
VecNormalizeFast(eye);
|
|
|
|
// calc halfway vector
|
|
VecSub(light->model_direction, eye, h);
|
|
|
|
dot = VecDot(h, in->dvNormal);
|
|
|
|
if (FLOAT_GTZ(dot))
|
|
{
|
|
dot *= ISQRTF(VecLenSq(h));
|
|
COMPUTE_SPECULAR(pv, dot, light);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
void PointSpot2(LPD3DFE_PROCESSVERTICES pv,
|
|
D3DI_LIGHT *light,
|
|
D3DLIGHTINGELEMENT *in)
|
|
{
|
|
D3DFE_LIGHTING &ldrv = pv->lighting;
|
|
D3DVALUE dot;
|
|
D3DVALUE dist; // Distance from light to the vertex
|
|
D3DVALUE dist2;
|
|
D3DVECTOR d; // Direction to light
|
|
D3DVALUE att;
|
|
|
|
if (light->flags & D3DLIGHTI_UNIT_SCALE)
|
|
{
|
|
VecSub(light->model_position, in->dvPosition, d);
|
|
}
|
|
else
|
|
{
|
|
d.x = light->model_position.x - in->dvPosition.x * light->model_scale.x;
|
|
d.y = light->model_position.y - in->dvPosition.y * light->model_scale.y;
|
|
d.z = light->model_position.z - in->dvPosition.z * light->model_scale.z;
|
|
}
|
|
|
|
// early out if out of range or exactly on the vertex
|
|
dist2 = d.x*d.x + d.y*d.y + d.z*d.z;
|
|
if (FLOAT_CMP_POS(dist2, >=, light->range_squared) || FLOAT_EQZ(dist2))
|
|
return;
|
|
|
|
// Calc dot product of light dir with normal. Note that since we
|
|
// didn't normalize the direction the result is scaled by the distance.
|
|
dot = VecDot(d, in->dvNormal);
|
|
|
|
if (FLOAT_GTZ(dot))
|
|
{
|
|
// ok, so now we actually need the real dist
|
|
dist = SQRTF(dist2);
|
|
|
|
// calc attenuation
|
|
att = 0.0f;
|
|
if (light->flags & D3DLIGHTI_ATT0_IS_NONZERO)
|
|
{
|
|
att += light->attenuation0;
|
|
}
|
|
if (light->flags & (D3DLIGHTI_ATT1_IS_NONZERO | D3DLIGHTI_ATT2_IS_NONZERO))
|
|
{
|
|
float att1 = (light->range - dist) / light->range;
|
|
|
|
if (light->flags & D3DLIGHTI_ATT1_IS_NONZERO)
|
|
{
|
|
att += light->attenuation1 * att1;
|
|
}
|
|
if (light->flags & D3DLIGHTI_ATT2_IS_NONZERO)
|
|
{
|
|
att += light->attenuation2 * att1 * att1;
|
|
}
|
|
}
|
|
|
|
dist = D3DVAL(1)/dist;
|
|
|
|
if (light->type == D3DLIGHT_SPOT)
|
|
{
|
|
D3DVALUE cone_dot;
|
|
// Calc dot product of direction to light with light direction to
|
|
// be compared anganst the cone angles to see if we are in the light.
|
|
// Note that cone_dot is still scaled by dist
|
|
cone_dot = VecDot(d, light->model_direction);
|
|
|
|
cone_dot*= dist; // Normalizing
|
|
if (FLOAT_CMP_POS(cone_dot, <=, light->cos_phi_by_2))
|
|
return;
|
|
|
|
// modify att if in the region between phi and theta
|
|
if (FLOAT_CMP_POS(cone_dot, <, light->cos_theta_by_2))
|
|
{
|
|
D3DVALUE val;
|
|
val = (cone_dot - light->cos_phi_by_2) * light->inv_theta_minus_phi;
|
|
if (!(light->flags & D3DLIGHTI_LINEAR_FALLOFF))
|
|
{
|
|
val = POWF(val, light->falloff);
|
|
}
|
|
att *= val;
|
|
}
|
|
}
|
|
|
|
dot *= dist*att;
|
|
|
|
if (pv->dwDeviceFlags & D3DDEV_RAMP)
|
|
{
|
|
ldrv.diffuse.r += light->shade * dot;
|
|
}
|
|
else
|
|
if (!(pv->dwFlags & D3DPV_COLORVERTEX))
|
|
{
|
|
ldrv.diffuse.r += light->local_diffR * dot;
|
|
ldrv.diffuse.g += light->local_diffG * dot;
|
|
ldrv.diffuse.b += light->local_diffB * dot;
|
|
}
|
|
else
|
|
{
|
|
ldrv.diffuse.r += light->red * ldrv.vertexDiffuse.r * dot;
|
|
ldrv.diffuse.g += light->green * ldrv.vertexDiffuse.g * dot;
|
|
ldrv.diffuse.b += light->blue * ldrv.vertexDiffuse.b * dot;
|
|
}
|
|
|
|
if (light->flags & D3DLIGHTI_COMPUTE_SPECULAR)
|
|
{
|
|
D3DVECTOR eye;
|
|
D3DVECTOR h;
|
|
// normalize light direction
|
|
d.x *= dist;
|
|
d.y *= dist;
|
|
d.z *= dist;
|
|
|
|
if (light->flags & D3DLIGHTI_LIGHT_AT_EYE)
|
|
{
|
|
h = d;
|
|
}
|
|
else
|
|
{
|
|
// calc incident vector
|
|
if (light->flags & D3DLIGHTI_UNIT_SCALE)
|
|
{
|
|
VecSub(in->dvPosition, light->model_eye, eye);
|
|
}
|
|
else
|
|
{
|
|
// note that model_eye has already been divided by scale in setup
|
|
eye.x = in->dvPosition.x*light->model_scale.x -
|
|
light->model_eye.x;
|
|
eye.y = in->dvPosition.y*light->model_scale.y -
|
|
light->model_eye.y;
|
|
eye.z = in->dvPosition.z*light->model_scale.z -
|
|
light->model_eye.z;
|
|
}
|
|
// normalize
|
|
VecNormalizeFast(eye);
|
|
|
|
// calc halfway vector
|
|
VecSub(d, eye, h);
|
|
VecNormalizeFast(h);
|
|
}
|
|
dot = VecDot(h, in->dvNormal);
|
|
|
|
COMPUTE_SPECULAR_ATT(pv, dot, light, att);
|
|
}
|
|
}
|
|
} // end of Point2()
|
|
//-------------------------------------------------------------------------
|
|
void Directional1C(LPD3DFE_PROCESSVERTICES pv,
|
|
D3DI_LIGHT *light,
|
|
D3DLIGHTINGELEMENT *in)
|
|
{
|
|
D3DFE_LIGHTING &ldrv = pv->lighting;
|
|
D3DVALUE dot;
|
|
dot = VecDot(light->model_direction, in->dvNormal);
|
|
if (FLOAT_GTZ(dot))
|
|
{
|
|
if (pv->dwDeviceFlags & D3DDEV_RAMP)
|
|
{
|
|
ldrv.diffuse.r += light->shade * dot;
|
|
}
|
|
else
|
|
{
|
|
ldrv.diffuse.r += light->local_diffR * dot;
|
|
ldrv.diffuse.g += light->local_diffG * dot;
|
|
ldrv.diffuse.b += light->local_diffB * dot;
|
|
}
|
|
if (light->flags & D3DLIGHTI_COMPUTE_SPECULAR)
|
|
{
|
|
dot = VecDot(light->halfway, in->dvNormal);
|
|
COMPUTE_SPECULAR(pv, dot, light);
|
|
}
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
void PointSpot1C(LPD3DFE_PROCESSVERTICES pv,
|
|
D3DI_LIGHT *light,
|
|
D3DLIGHTINGELEMENT *in)
|
|
{
|
|
D3DFE_LIGHTING &ldrv = pv->lighting;
|
|
D3DVECTOR d;
|
|
D3DVALUE dot;
|
|
VecSub(light->model_position, in->dvPosition, d);
|
|
dot = VecDot(d, in->dvNormal);
|
|
if (FLOAT_GTZ(dot))
|
|
{
|
|
D3DVALUE dist2;
|
|
D3DVALUE dist;
|
|
D3DVALUE att;
|
|
D3DVALUE big = D3DVAL(1000); // if 1/att < 0.001 do not compute color
|
|
|
|
dist2 = VecDot(d, d);
|
|
if (FLOAT_EQZ(dist2))
|
|
return;
|
|
dist = SQRTF(dist2);
|
|
att = light->attenuation0 +
|
|
light->attenuation1 * dist +
|
|
light->attenuation2 * dist2;
|
|
|
|
if (FLOAT_CMP_POS(att, >, big))
|
|
return;
|
|
|
|
if (FLOAT_CMP_PONE(att, >))
|
|
att *= dist;
|
|
else
|
|
att = dist;
|
|
att = D3DVAL(1) / att;
|
|
if (light->type == D3DLIGHT_SPOT)
|
|
{
|
|
D3DVALUE cone_dot;
|
|
// Calc dot product of direction to light with light direction to
|
|
// be compared anganst the cone angles to see if we are in the light.
|
|
// Note that cone_dot is still scaled by dist
|
|
cone_dot = VecDot(d, light->model_direction);
|
|
cone_dot /= dist;
|
|
|
|
if (FLOAT_CMP_POS(cone_dot, <=, light->cos_phi_by_2))
|
|
return;
|
|
|
|
if (FLOAT_CMP_POS(cone_dot, <, light->cos_theta_by_2))
|
|
{
|
|
att *= D3DVAL(1)-(light->cos_theta_by_2-cone_dot)*light->falloff;
|
|
}
|
|
}
|
|
|
|
dot *= att;
|
|
|
|
if (pv->dwDeviceFlags & D3DDEV_RAMP)
|
|
{
|
|
ldrv.diffuse.r += light->shade * dot;
|
|
}
|
|
else
|
|
{
|
|
ldrv.diffuse.r += light->local_diffR * dot;
|
|
ldrv.diffuse.g += light->local_diffG * dot;
|
|
ldrv.diffuse.b += light->local_diffB * dot;
|
|
}
|
|
|
|
if (light->flags & D3DLIGHTI_COMPUTE_SPECULAR)
|
|
{
|
|
dot = VecDot(light->halfway, in->dvNormal);
|
|
COMPUTE_SPECULAR_ATT(pv, dot, light, att);
|
|
}
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
void PointSpotXCRamp(LPD3DFE_PROCESSVERTICES pv,
|
|
D3DI_LIGHT *light,
|
|
D3DLIGHTINGELEMENT *in)
|
|
{
|
|
D3DFE_LIGHTING &ldrv = pv->lighting;
|
|
D3DVECTOR d;
|
|
D3DVALUE dot;
|
|
VecSub(light->model_position, in->dvPosition, d);
|
|
dot = VecDot(d, in->dvNormal);
|
|
if (FLOAT_GTZ(dot))
|
|
{
|
|
D3DVALUE dist2;
|
|
D3DVALUE dist;
|
|
D3DVALUE att;
|
|
D3DVALUE big = D3DVAL(1000); // if 1/att < 0.001 do not compute color
|
|
|
|
dist2 = VecDot(d, d);
|
|
if (FLOAT_EQZ(dist2))
|
|
return;
|
|
dist = SQRTF(dist2);
|
|
if (light->version == 1)
|
|
{
|
|
att = light->attenuation0 +
|
|
light->attenuation1 * dist +
|
|
light->attenuation2 * dist2;
|
|
|
|
if (FLOAT_CMP_PONE(att, >))
|
|
att *= dist;
|
|
else
|
|
att = dist;
|
|
att = D3DVAL(1) / att;
|
|
}
|
|
else
|
|
{
|
|
// dist is normalized to light range
|
|
float att1 = (light->range-dist)/light->range;
|
|
att = light->attenuation0 +
|
|
light->attenuation1 * att1 +
|
|
light->attenuation2 * att1*att1;
|
|
}
|
|
|
|
if (light->type == D3DLIGHT_SPOT)
|
|
{
|
|
D3DVALUE cone_dot;
|
|
// Calc dot product of direction to light with light direction to
|
|
// be compared anganst the cone angles to see if we are in the light.
|
|
// Note that cone_dot is still scaled by dist
|
|
cone_dot = VecDot(d, light->model_direction);
|
|
cone_dot /= dist;
|
|
|
|
if (FLOAT_CMP_POS(cone_dot, <=, light->cos_phi_by_2))
|
|
return;
|
|
|
|
if (FLOAT_CMP_POS(cone_dot, <, light->cos_theta_by_2))
|
|
{
|
|
att *= D3DVAL(1)-(light->cos_theta_by_2-cone_dot)*light->falloff;
|
|
}
|
|
}
|
|
|
|
dot *= att;
|
|
|
|
if (pv->dwDeviceFlags & D3DDEV_RAMP)
|
|
{
|
|
ldrv.diffuse.r += light->shade * dot;
|
|
}
|
|
else
|
|
{
|
|
ldrv.diffuse.r += light->local_diffR * dot;
|
|
ldrv.diffuse.g += light->local_diffG * dot;
|
|
ldrv.diffuse.b += light->local_diffB * dot;
|
|
}
|
|
|
|
if (light->version == 1)
|
|
{
|
|
// no attenuation of specular for ramp for version == 1
|
|
att = 1.0F;
|
|
}
|
|
if (light->flags & D3DLIGHTI_COMPUTE_SPECULAR)
|
|
{
|
|
dot = VecDot(light->halfway, in->dvNormal);
|
|
COMPUTE_SPECULAR_ATT(pv, dot, light, att);
|
|
}
|
|
}
|
|
}
|
|
//-------------------------------------------------------------------------
|
|
SpecularTable* CreateSpecularTable(D3DVALUE power)
|
|
{
|
|
SpecularTable* spec;
|
|
int i;
|
|
float delta = 1.0f/255.0f;
|
|
float v;
|
|
|
|
D3DMalloc((void**)&spec, sizeof(SpecularTable));
|
|
|
|
if (spec == NULL)
|
|
return NULL;
|
|
|
|
spec->power = power;
|
|
|
|
v = 0.0f;
|
|
for (i = 0; i < 256; i++)
|
|
{
|
|
spec->table[i] = powf(v, power);
|
|
v += delta;
|
|
}
|
|
|
|
for (; i < 260; i++)
|
|
spec->table[i] = 1.0f;
|
|
|
|
return spec;
|
|
}
|
|
|
|
HRESULT SetMaterial(LPDIRECT3DDEVICEI lpDevI, D3DMATERIALHANDLE hMat)
|
|
{
|
|
LPD3DFE_MATERIAL lpMat;
|
|
lpMat = (LPD3DFE_MATERIAL) ULongToPtr(hMat);
|
|
|
|
if (!lpMat)
|
|
{
|
|
lpDevI->lighting.hMat = NULL;
|
|
return D3D_OK;
|
|
}
|
|
|
|
#if DBG
|
|
// check for non-null bogus material handle
|
|
TRY
|
|
{
|
|
if (IsBadReadPtr(lpMat,sizeof(D3DFE_MATERIAL)) || (lpMat->mat.dwSize!=sizeof(D3DMATERIAL))) {
|
|
D3D_ERR( "SetLightState: Invalid Material handle" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
}
|
|
EXCEPT( EXCEPTION_EXECUTE_HANDLER )
|
|
{
|
|
D3D_ERR( "Exception encountered validating SetLightState material handle" );
|
|
return DDERR_INVALIDPARAMS;
|
|
}
|
|
#endif
|
|
|
|
D3DFE_LIGHTING& LIGHTING = lpDevI->lighting;
|
|
LIGHTING.material = lpMat->mat;
|
|
LIGHTING.hMat = hMat;
|
|
lpDevI->dwFEFlags |= D3DFE_MATERIAL_DIRTY;
|
|
|
|
if (lpMat->mat.power > D3DVAL(0.001))
|
|
{
|
|
SpecularTable* spec;
|
|
|
|
for (spec = LIST_FIRST(&lpDevI->specular_tables);
|
|
spec;
|
|
spec = LIST_NEXT(spec,list))
|
|
{
|
|
if (spec->power == lpMat->mat.power)
|
|
break;
|
|
}
|
|
if (spec == NULL)
|
|
{
|
|
spec = CreateSpecularTable(lpMat->mat.power);
|
|
if (spec == NULL)
|
|
return DDERR_INVALIDPARAMS;
|
|
LIST_INSERT_ROOT(&lpDevI->specular_tables, spec, list);
|
|
}
|
|
lpDevI->specular_table = spec;
|
|
LIGHTING.specThreshold = D3DVAL(pow(0.001, 1.0/lpMat->mat.power));
|
|
}
|
|
else
|
|
lpDevI->specular_table = NULL;
|
|
|
|
return D3D_OK;
|
|
}
|
|
|
|
/*
|
|
* Instruction emulation.
|
|
*/
|
|
HRESULT D3DHELInst_D3DOP_STATELIGHT(LPDIRECT3DDEVICEI lpDevI, DWORD dwCount,
|
|
LPD3DSTATE lpLset)
|
|
{
|
|
DWORD i;
|
|
|
|
for (i = 0; i < dwCount; i++)
|
|
{
|
|
DWORD type = (DWORD) lpLset[i].dlstLightStateType;
|
|
HRESULT hr = D3D_OK;
|
|
|
|
D3D_INFO(9, "HEL D3DOP_STATELIGHT: state = %d", type);
|
|
if (IS_OVERRIDE(type))
|
|
{
|
|
DWORD override = GET_OVERRIDE(type);
|
|
if (lpLset[i].dwArg[0])
|
|
{
|
|
D3D_INFO(9, "HEL D3DOP_STATELIGHT: setting override for state %d",
|
|
override);
|
|
STATESET_SET(lpDevI->lightstate_overrides, override);
|
|
}
|
|
else
|
|
{
|
|
D3D_INFO(9, "HEL D3DOP_STATELIGHT: clearing override for state %d",
|
|
override);
|
|
STATESET_CLEAR(lpDevI->lightstate_overrides, override);
|
|
}
|
|
continue;
|
|
}
|
|
|
|
if (STATESET_ISSET(lpDevI->lightstate_overrides, type))
|
|
{
|
|
D3D_INFO(9, "HEL D3DOP_STATELIGHT: state %d is overridden, ignoring",
|
|
type);
|
|
continue;
|
|
}
|
|
|
|
D3DFE_LIGHTING& LIGHTING = lpDevI->lighting;
|
|
switch (type)
|
|
{
|
|
case D3DLIGHTSTATE_MATERIAL:
|
|
{
|
|
D3D_INFO(6, "in HEL D3DOP_STATELIGHT. D3DLIGHTSTATE_MATERIAL found");
|
|
D3DMATERIALHANDLE hMat = (D3DMATERIALHANDLE)lpLset[i].dwArg[0];
|
|
if (hMat != lpDevI->lighting.hMat)
|
|
{
|
|
hr = SetMaterial(lpDevI, hMat);
|
|
if (hr != D3D_OK)
|
|
return hr;
|
|
// Update ramp rasterizer if necessary
|
|
if(lpDevI->pfnRampService != NULL)
|
|
{
|
|
hr = CallRampService(lpDevI, RAMP_SERVICE_SETLIGHTSTATE,
|
|
(DWORD)type, &(lpLset[i].dvArg[0]), TRUE);
|
|
if (hr != D3D_OK)
|
|
return hr;
|
|
}
|
|
}
|
|
continue;
|
|
}
|
|
case D3DLIGHTSTATE_AMBIENT:
|
|
{
|
|
DWORD color = lpLset[i].dwArg[0];
|
|
D3D_INFO(6, "in HEL D3DOP_STATELIGHT. D3DLIGHTSTATE_AMBIENT found");
|
|
|
|
LIGHTING.ambient_red = D3DVAL(RGBA_GETRED(color));
|
|
LIGHTING.ambient_green = D3DVAL(RGBA_GETGREEN(color));
|
|
LIGHTING.ambient_blue = D3DVAL(RGBA_GETBLUE(color));
|
|
LIGHTING.ambient_save = lpLset[i].dwArg[0];
|
|
lpDevI->dwFEFlags |= D3DFE_MATERIAL_DIRTY;
|
|
break;
|
|
}
|
|
case D3DLIGHTSTATE_FOGMODE:
|
|
D3D_INFO(6, "in HEL D3DOP_STATELIGHT. D3DLIGHTSTATE_FOG_MODE found");
|
|
LIGHTING.fog_mode = (D3DFOGMODE)lpLset[i].dwArg[0];
|
|
SetFogFlags(lpDevI);
|
|
break;
|
|
case D3DLIGHTSTATE_FOGSTART:
|
|
D3D_INFO(6, "in HEL D3DOP_STATELIGHT. D3DLIGHTSTATE_FOG_START found");
|
|
LIGHTING.fog_start = lpLset[i].dvArg[0];
|
|
if (lpDevI->dwFEFlags & D3DFE_FOGENABLED)
|
|
lpDevI->dwFEFlags |= D3DFE_FOG_DIRTY;
|
|
break;
|
|
case D3DLIGHTSTATE_FOGEND:
|
|
D3D_INFO(6, "in HEL D3DOP_STATELIGHT. D3DLIGHTSTATE_FOG_END found");
|
|
LIGHTING.fog_end = lpLset[i].dvArg[0];
|
|
if (lpDevI->dwFEFlags & D3DFE_FOGENABLED)
|
|
lpDevI->dwFEFlags |= D3DFE_FOG_DIRTY;
|
|
break;
|
|
case D3DLIGHTSTATE_FOGDENSITY:
|
|
D3D_INFO(6, "in HEL D3DOP_STATELIGHT. D3DLIGHTSTATE_FOG_DENSITY found");
|
|
LIGHTING.fog_density = lpLset[i].dvArg[0];
|
|
if (lpDevI->dwFEFlags & D3DFE_FOGENABLED)
|
|
lpDevI->dwFEFlags |= D3DFE_FOG_DIRTY;
|
|
break;
|
|
case D3DLIGHTSTATE_COLORMODEL:
|
|
D3D_INFO(6, "in HEL D3DOP_STATELIGHT. D3DLIGHTSTATE_COLORMODEL found");
|
|
LIGHTING.color_model = (D3DCOLORMODEL)lpLset[i].dwArg[0];
|
|
break;
|
|
case D3DLIGHTSTATE_COLORVERTEX:
|
|
D3D_INFO(6, "in HEL D3DOP_STATELIGHT. D3DLIGHTSTATE_COLORVERTEX found");
|
|
if (lpLset[i].dwArg[0])
|
|
lpDevI->dwFEFlags |= D3DFE_COLORVERTEX;
|
|
else
|
|
lpDevI->dwFEFlags &= ~D3DFE_COLORVERTEX;
|
|
break;
|
|
|
|
default:
|
|
D3D_WARN(1, "in HEL D3DOP_STATELIGHT. Invalid state type %d",
|
|
lpLset[i].dlstLightStateType);
|
|
return (DDERR_INVALIDPARAMS);
|
|
}
|
|
|
|
// Update ramp rasterizer if necessary
|
|
hr = CallRampService(lpDevI, RAMP_SERVICE_SETLIGHTSTATE,
|
|
(DWORD) type, &(lpLset[i].dvArg[0]));
|
|
if (hr != D3D_OK)
|
|
{
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
return (D3D_OK);
|
|
}
|