Significantly improve the lighting code.

This commit is contained in:
Jason Edmeades 2002-10-11 23:31:07 +00:00 committed by Alexandre Julliard
parent ab5063b217
commit 78a9bf8709
2 changed files with 71 additions and 23 deletions

View File

@ -300,6 +300,10 @@ struct IDirect3DDevice8Impl
STATEBLOCK StateBlock;
STATEBLOCK *UpdateStateBlock;
/* Other required values */
float lightPosn[MAX_ACTIVE_LIGHTS][4];
float lightDirn[MAX_ACTIVE_LIGHTS][4];
/* OpenGL related */
GLXContext glCtx;
XVisualInfo *visInfo;

View File

@ -23,6 +23,7 @@
#include "winuser.h"
#include "wingdi.h"
#include "wine/debug.h"
#include "math.h"
#include "d3d8_private.h"
@ -995,6 +996,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count
}
HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts,CONST D3DMATRIX* lpmatrix) {
ICOM_THIS(IDirect3DDevice8Impl,iface);
int k;
/* Most of this routine, comments included copied from ddraw tree initially: */
TRACE("(%p) : State=%d\n", This, d3dts);
@ -1064,6 +1066,17 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DT
checkGLcall("glMatrixMode");
glLoadMatrixf((float *) &This->StateBlock.transforms[D3DTS_VIEW].u.m[0][0]);
checkGLcall("glLoadMatrixf");
/* If we are changing the View matrix, reset the light information to the new view */
if (d3dts == D3DTS_VIEW) {
for (k = 0; k < MAX_ACTIVE_LIGHTS; k++) {
glLightfv(GL_LIGHT0 + k, GL_POSITION, &This->lightPosn[k][0]);
checkGLcall("glLightfv posn");
glLightfv(GL_LIGHT0 + k, GL_SPOT_DIRECTION, &This->lightDirn[k][0]);
checkGLcall("glLightfv dirn");
}
}
glMultMatrixf((float *) &This->StateBlock.transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
checkGLcall("glMultMatrixf");
@ -1165,7 +1178,8 @@ HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMA
HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST D3DLIGHT8* pLight) {
float colRGBA[] = {0.0, 0.0, 0.0, 0.0};
float coords[] = {0.0, 0.0, 0.0, 0.0};
float rho;
float quad_att;
ICOM_THIS(IDirect3DDevice8Impl,iface);
TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
@ -1212,52 +1226,80 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD In
glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
checkGLcall("glLightfv");
/* Light settings are affected by the model view in OpenGL, the View transform in direct3d*/
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadMatrixf((float *) &This->StateBlock.transforms[D3DTS_VIEW].u.m[0][0]);
/* Attenuation - Are these right? guessing... */
glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, pLight->Attenuation0);
checkGLcall("glLightf");
glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, pLight->Attenuation1);
checkGLcall("glLightf");
glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, pLight->Attenuation2);
quad_att = 1.4/(pLight->Range*pLight->Range);
if (quad_att < pLight->Attenuation2) quad_att = pLight->Attenuation2;
glLightf(GL_LIGHT0+Index, GL_QUADRATIC_ATTENUATION, quad_att);
checkGLcall("glLightf");
switch (pLight->Type) {
case D3DLIGHT_POINT:
/* Position */
coords[0] = pLight->Position.x;
coords[1] = pLight->Position.y;
coords[2] = pLight->Position.z;
coords[3] = 1.0;
glLightfv(GL_LIGHT0+Index, GL_POSITION, coords);
This->lightPosn[Index][0] = pLight->Position.x;
This->lightPosn[Index][1] = pLight->Position.y;
This->lightPosn[Index][2] = pLight->Position.z;
This->lightPosn[Index][3] = 1.0;
glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
checkGLcall("glLightfv");
glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, 180);
checkGLcall("glLightf");
/* FIXME: Range */
break;
case D3DLIGHT_SPOT:
/* Position */
coords[0] = pLight->Position.x;
coords[1] = pLight->Position.y;
coords[2] = pLight->Position.z;
coords[3] = 0.0;
glLightfv(GL_LIGHT0+Index, GL_POSITION, coords);
This->lightPosn[Index][0] = pLight->Position.x;
This->lightPosn[Index][1] = pLight->Position.y;
This->lightPosn[Index][2] = pLight->Position.z;
This->lightPosn[Index][3] = 1.0;
glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
checkGLcall("glLightfv");
/* Direction */
coords[0] = pLight->Direction.x;
coords[1] = pLight->Direction.y;
coords[2] = pLight->Direction.z;
coords[3] = 1.0;
glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, coords);
This->lightDirn[Index][0] = pLight->Direction.x;
This->lightDirn[Index][1] = pLight->Direction.y;
This->lightDirn[Index][2] = pLight->Direction.z;
This->lightDirn[Index][3] = 1.0;
glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &This->lightDirn[Index][0]);
checkGLcall("glLightfv");
/*
* opengl-ish and d3d-ish spot lights use too different models for the
* light "intensity" as a function of the angle towards the main light direction,
* so we only can approximate very roughly.
* however spot lights are rather rarely used in games (if ever used at all).
* furthermore if still used, probably nobody pays attention to such details.
*/
if (pLight->Falloff == 0) {
rho = 6.28f;
} else {
rho = pLight->Theta + (pLight->Phi - pLight->Theta)/(2*pLight->Falloff);
}
if (rho < 0.0001) rho = 0.0001f;
glLightf(GL_LIGHT0 + Index, GL_SPOT_EXPONENT, -0.3/log(cos(rho/2)));
glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, pLight->Phi*90/M_PI);
/* FIXME: Range */
break;
case D3DLIGHT_DIRECTIONAL:
/* Direction */
coords[0] = -pLight->Direction.x;
coords[1] = pLight->Direction.y;
coords[2] = -pLight->Direction.z;
coords[3] = 0.0;
glLightfv(GL_LIGHT0+Index, GL_POSITION, coords); /* Note gl uses w position of 0 for direction! */
This->lightPosn[Index][0] = -pLight->Direction.x;
This->lightPosn[Index][1] = -pLight->Direction.y;
This->lightPosn[Index][2] = -pLight->Direction.z;
This->lightPosn[Index][3] = 0.0;
glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]); /* Note gl uses w position of 0 for direction! */
checkGLcall("glLightfv");
glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, 180.0f);
@ -1269,7 +1311,9 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD In
FIXME("Unrecognized light type %d\n", pLight->Type);
}
/* FIXME: Falloff, Theta, Phi; */
/* Restore the modelview matrix */
glPopMatrix();
return D3D_OK;
}
HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {