Skip to content
Snippets Groups Projects
Commit 78a9bf87 authored by Jason Edmeades's avatar Jason Edmeades Committed by Alexandre Julliard
Browse files

Significantly improve the lighting code.

parent ab5063b2
No related branches found
No related tags found
No related merge requests found
...@@ -300,6 +300,10 @@ struct IDirect3DDevice8Impl ...@@ -300,6 +300,10 @@ struct IDirect3DDevice8Impl
STATEBLOCK StateBlock; STATEBLOCK StateBlock;
STATEBLOCK *UpdateStateBlock; STATEBLOCK *UpdateStateBlock;
/* Other required values */
float lightPosn[MAX_ACTIVE_LIGHTS][4];
float lightDirn[MAX_ACTIVE_LIGHTS][4];
/* OpenGL related */ /* OpenGL related */
GLXContext glCtx; GLXContext glCtx;
XVisualInfo *visInfo; XVisualInfo *visInfo;
......
...@@ -23,6 +23,7 @@ ...@@ -23,6 +23,7 @@
#include "winuser.h" #include "winuser.h"
#include "wingdi.h" #include "wingdi.h"
#include "wine/debug.h" #include "wine/debug.h"
#include "math.h"
#include "d3d8_private.h" #include "d3d8_private.h"
...@@ -995,6 +996,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count ...@@ -995,6 +996,7 @@ HRESULT WINAPI IDirect3DDevice8Impl_Clear(LPDIRECT3DDEVICE8 iface, DWORD Count
} }
HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts,CONST D3DMATRIX* lpmatrix) { HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DTRANSFORMSTATETYPE d3dts,CONST D3DMATRIX* lpmatrix) {
ICOM_THIS(IDirect3DDevice8Impl,iface); ICOM_THIS(IDirect3DDevice8Impl,iface);
int k;
/* Most of this routine, comments included copied from ddraw tree initially: */ /* Most of this routine, comments included copied from ddraw tree initially: */
TRACE("(%p) : State=%d\n", This, d3dts); TRACE("(%p) : State=%d\n", This, d3dts);
...@@ -1064,6 +1066,17 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DT ...@@ -1064,6 +1066,17 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetTransform(LPDIRECT3DDEVICE8 iface, D3DT
checkGLcall("glMatrixMode"); checkGLcall("glMatrixMode");
glLoadMatrixf((float *) &This->StateBlock.transforms[D3DTS_VIEW].u.m[0][0]); glLoadMatrixf((float *) &This->StateBlock.transforms[D3DTS_VIEW].u.m[0][0]);
checkGLcall("glLoadMatrixf"); 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]); glMultMatrixf((float *) &This->StateBlock.transforms[D3DTS_WORLDMATRIX(0)].u.m[0][0]);
checkGLcall("glMultMatrixf"); checkGLcall("glMultMatrixf");
...@@ -1165,7 +1178,8 @@ HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMA ...@@ -1165,7 +1178,8 @@ HRESULT WINAPI IDirect3DDevice8Impl_GetMaterial(LPDIRECT3DDEVICE8 iface, D3DMA
HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST D3DLIGHT8* pLight) { HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,CONST D3DLIGHT8* pLight) {
float colRGBA[] = {0.0, 0.0, 0.0, 0.0}; 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); ICOM_THIS(IDirect3DDevice8Impl,iface);
TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight); TRACE("(%p) : Idx(%ld), pLight(%p)\n", This, Index, pLight);
...@@ -1212,52 +1226,80 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD In ...@@ -1212,52 +1226,80 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD In
glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA); glLightfv(GL_LIGHT0+Index, GL_AMBIENT, colRGBA);
checkGLcall("glLightfv"); 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... */ /* Attenuation - Are these right? guessing... */
glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, pLight->Attenuation0); glLightf(GL_LIGHT0+Index, GL_CONSTANT_ATTENUATION, pLight->Attenuation0);
checkGLcall("glLightf"); checkGLcall("glLightf");
glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, pLight->Attenuation1); glLightf(GL_LIGHT0+Index, GL_LINEAR_ATTENUATION, pLight->Attenuation1);
checkGLcall("glLightf"); 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"); checkGLcall("glLightf");
switch (pLight->Type) { switch (pLight->Type) {
case D3DLIGHT_POINT: case D3DLIGHT_POINT:
/* Position */ /* Position */
coords[0] = pLight->Position.x; This->lightPosn[Index][0] = pLight->Position.x;
coords[1] = pLight->Position.y; This->lightPosn[Index][1] = pLight->Position.y;
coords[2] = pLight->Position.z; This->lightPosn[Index][2] = pLight->Position.z;
coords[3] = 1.0; This->lightPosn[Index][3] = 1.0;
glLightfv(GL_LIGHT0+Index, GL_POSITION, coords); glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
checkGLcall("glLightfv"); checkGLcall("glLightfv");
glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, 180);
checkGLcall("glLightf");
/* FIXME: Range */ /* FIXME: Range */
break; break;
case D3DLIGHT_SPOT: case D3DLIGHT_SPOT:
/* Position */ /* Position */
coords[0] = pLight->Position.x; This->lightPosn[Index][0] = pLight->Position.x;
coords[1] = pLight->Position.y; This->lightPosn[Index][1] = pLight->Position.y;
coords[2] = pLight->Position.z; This->lightPosn[Index][2] = pLight->Position.z;
coords[3] = 0.0; This->lightPosn[Index][3] = 1.0;
glLightfv(GL_LIGHT0+Index, GL_POSITION, coords); glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]);
checkGLcall("glLightfv"); checkGLcall("glLightfv");
/* Direction */ /* Direction */
coords[0] = pLight->Direction.x; This->lightDirn[Index][0] = pLight->Direction.x;
coords[1] = pLight->Direction.y; This->lightDirn[Index][1] = pLight->Direction.y;
coords[2] = pLight->Direction.z; This->lightDirn[Index][2] = pLight->Direction.z;
coords[3] = 1.0; This->lightDirn[Index][3] = 1.0;
glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, coords); glLightfv(GL_LIGHT0+Index, GL_SPOT_DIRECTION, &This->lightDirn[Index][0]);
checkGLcall("glLightfv"); 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 */ /* FIXME: Range */
break; break;
case D3DLIGHT_DIRECTIONAL: case D3DLIGHT_DIRECTIONAL:
/* Direction */ /* Direction */
coords[0] = -pLight->Direction.x; This->lightPosn[Index][0] = -pLight->Direction.x;
coords[1] = pLight->Direction.y; This->lightPosn[Index][1] = -pLight->Direction.y;
coords[2] = -pLight->Direction.z; This->lightPosn[Index][2] = -pLight->Direction.z;
coords[3] = 0.0; This->lightPosn[Index][3] = 0.0;
glLightfv(GL_LIGHT0+Index, GL_POSITION, coords); /* Note gl uses w position of 0 for direction! */ glLightfv(GL_LIGHT0+Index, GL_POSITION, &This->lightPosn[Index][0]); /* Note gl uses w position of 0 for direction! */
checkGLcall("glLightfv"); checkGLcall("glLightfv");
glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, 180.0f); glLightf(GL_LIGHT0+Index, GL_SPOT_CUTOFF, 180.0f);
...@@ -1269,7 +1311,9 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD In ...@@ -1269,7 +1311,9 @@ HRESULT WINAPI IDirect3DDevice8Impl_SetLight(LPDIRECT3DDEVICE8 iface, DWORD In
FIXME("Unrecognized light type %d\n", pLight->Type); FIXME("Unrecognized light type %d\n", pLight->Type);
} }
/* FIXME: Falloff, Theta, Phi; */ /* Restore the modelview matrix */
glPopMatrix();
return D3D_OK; return D3D_OK;
} }
HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) { HRESULT WINAPI IDirect3DDevice8Impl_GetLight(LPDIRECT3DDEVICE8 iface, DWORD Index,D3DLIGHT8* pLight) {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment