Commit 76b7cac7 authored by Stefan Dösinger's avatar Stefan Dösinger Committed by Alexandre Julliard

wined3d: Light parameter fixes.

parent fb1469c4
......@@ -218,6 +218,65 @@ static void LightTest(void)
/* Light 23 has not been set */
rc = IDirect3DDevice7_GetLightEnable(lpD3DDevice, 23, &bEnabled );
ok(rc==DDERR_INVALIDPARAMS, "GetLightEnable returned: %x\n", rc);
/* Set some lights with invalid parameters */
memset(&light, 0, sizeof(D3DLIGHT7));
light.dltType = 0;
U1(light.dcvDiffuse).r = 1.f;
U2(light.dcvDiffuse).g = 1.f;
U3(light.dcvDiffuse).b = 1.f;
U3(light.dvDirection).z = 1.f;
rc = IDirect3DDevice7_SetLight(lpD3DDevice, 100, &light);
ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
memset(&light, 0, sizeof(D3DLIGHT7));
light.dltType = 12345;
U1(light.dcvDiffuse).r = 1.f;
U2(light.dcvDiffuse).g = 1.f;
U3(light.dcvDiffuse).b = 1.f;
U3(light.dvDirection).z = 1.f;
rc = IDirect3DDevice7_SetLight(lpD3DDevice, 101, &light);
ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
rc = IDirect3DDevice7_SetLight(lpD3DDevice, 102, NULL);
ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
memset(&light, 0, sizeof(D3DLIGHT7));
light.dltType = D3DLIGHT_SPOT;
U1(light.dcvDiffuse).r = 1.f;
U2(light.dcvDiffuse).g = 1.f;
U3(light.dcvDiffuse).b = 1.f;
U3(light.dvDirection).z = 1.f;
U3(light.dvAttenuation0) = -1.0 / 0.0; /* -INFINITY */
rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
U3(light.dvAttenuation0) = -1.0;
rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
ok(rc==DDERR_INVALIDPARAMS, "SetLight returned: %x\n", rc);
U3(light.dvAttenuation0) = 0.0;
rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
U3(light.dvAttenuation0) = 1.0;
rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
U3(light.dvAttenuation0) = 1.0 / 0.0; /* +INFINITY */
rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
U3(light.dvAttenuation0) = 0.0 / 0.0; /* NaN */
rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
/* Directional light ignores attenuation */
light.dltType = D3DLIGHT_DIRECTIONAL;
U3(light.dvAttenuation0) = -1.0;
rc = IDirect3DDevice7_SetLight(lpD3DDevice, 103, &light);
ok(rc==D3D_OK, "SetLight returned: %x\n", rc);
}
static void ProcessVerticesTest(void)
......
......@@ -2199,6 +2199,37 @@ static HRESULT WINAPI IWineD3DDeviceImpl_SetLight(IWineD3DDevice *iface, DWORD I
IWineD3DDeviceImpl *This = (IWineD3DDeviceImpl *)iface;
TRACE("(%p) : Idx(%d), pLight(%p). Hash index is %d\n", This, Index, pLight, Hi);
/* Check the parameter range. Need for speed most wanted sets junk lights which confuse
* the gl driver.
*/
if(!pLight) {
WARN("Light pointer = NULL, returning WINED3DERR_INVALIDCALL\n");
return WINED3DERR_INVALIDCALL;
}
switch(pLight->Type) {
case WINED3DLIGHT_POINT:
case WINED3DLIGHT_SPOT:
case WINED3DLIGHT_PARALLELPOINT:
case WINED3DLIGHT_GLSPOT:
/* Incorrect attenuation values can cause the gl driver to crash. Happens with Need for speed
* most wanted
*/
if(pLight->Attenuation0 < 0.0 || pLight->Attenuation1 < 0.0 || pLight->Attenuation2 < 0.0) {
WARN("Attenuation is negative, returning WINED3DERR_INVALIDCALL\n");
return WINED3DERR_INVALIDCALL;
}
break;
case WINED3DLIGHT_DIRECTIONAL:
/* Ignores attenuation */
break;
default:
WARN("Light type out of range, returning WINED3DERR_INVALIDCALL\n");
return WINED3DERR_INVALIDCALL;
}
LIST_FOR_EACH(e, &This->updateStateBlock->lightMap[Hi]) {
object = LIST_ENTRY(e, PLIGHTINFOEL, entry);
if(object->OriginalIndex == Index) break;
......
......@@ -2981,21 +2981,16 @@ static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContex
glLightfv(GL_LIGHT0 + Index, GL_AMBIENT, colRGBA);
checkGLcall("glLightfv");
/* Attenuation - Are these right? guessing... */
glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
checkGLcall("glLightf");
glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
checkGLcall("glLightf");
if ((lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range) >= FLT_MIN) {
quad_att = 1.4/(lightInfo->OriginalParms.Range *lightInfo->OriginalParms.Range);
} else {
quad_att = 0; /* 0 or MAX? (0 seems to be ok) */
}
if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
checkGLcall("glLightf");
/* Do not assign attenuation values for lights that do not use them. D3D apps are free to pass any junk,
* but gl drivers use them and may crash due to bad Attenuation values. Need for Speed most wanted sets
* Attenuation0 to NaN and crashes in the gl lib
*/
switch (lightInfo->OriginalParms.Type) {
case WINED3DLIGHT_POINT:
......@@ -3004,6 +2999,14 @@ static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContex
checkGLcall("glLightfv");
glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
checkGLcall("glLightf");
/* Attenuation - Are these right? guessing... */
glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
checkGLcall("glLightf");
glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
checkGLcall("glLightf");
if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
checkGLcall("glLightf");
/* FIXME: Range */
break;
......@@ -3018,6 +3021,14 @@ static void light(DWORD state, IWineD3DStateBlockImpl *stateblock, WineD3DContex
checkGLcall("glLightf");
glLightf(GL_LIGHT0 + Index, GL_SPOT_CUTOFF, lightInfo->cutoff);
checkGLcall("glLightf");
/* Attenuation - Are these right? guessing... */
glLightf(GL_LIGHT0 + Index, GL_CONSTANT_ATTENUATION, lightInfo->OriginalParms.Attenuation0);
checkGLcall("glLightf");
glLightf(GL_LIGHT0 + Index, GL_LINEAR_ATTENUATION, lightInfo->OriginalParms.Attenuation1);
checkGLcall("glLightf");
if (quad_att < lightInfo->OriginalParms.Attenuation2) quad_att = lightInfo->OriginalParms.Attenuation2;
glLightf(GL_LIGHT0 + Index, GL_QUADRATIC_ATTENUATION, quad_att);
checkGLcall("glLightf");
/* FIXME: Range */
break;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment