Files
Jedi-Academy/codemp/win32/win_lighteffects.cpp
2013-04-04 14:32:05 -07:00

908 lines
28 KiB
C++

//
//
// win_lighteffects.cpp
//
// Various lighting effects w/ pixel shaders
//
//
#ifdef VV_LIGHTING
#include "../server/exe_headers.h"
#include "../renderer/tr_local.h"
#include "glw_win_dx8.h"
#include "win_local.h"
#include "win_lighteffects.h"
#include <xgraphics.h>
#include <xgmath.h>
#include "shader_constants.h"
LightEffects::LightEffects()
{
m_pCubeMap = NULL;
m_pBumpMap = NULL;
// m_pSpecularMap = NULL;
m_pFalloffMap = NULL;
m_dwVertexShaderLight = 0L;
m_dwPixelShaderLight = 0L;
// m_dwVertexShaderSpecular_Dynamic = 0L;
// m_dwPixelShaderSpecular_Dynamic = 0L;
// m_dwVertexShaderSpecular_Static = 0L;
// m_dwPixelShaderSpecular_Static = 0L;
m_dwVertexShaderEnvironment = 0L;
// m_dwVertexShaderBump = 0L;
// m_dwPixelShaderBump = 0L;
m_bInLightPhase = false;
m_bInitialized = false;
Initialize();
}
LightEffects::~LightEffects()
{
if( m_pCubeMap )
m_pCubeMap->Release();
m_pCubeMap = NULL;
if(m_pBumpMap)
m_pBumpMap->Release();
m_pBumpMap = NULL;
if(m_pFalloffMap)
m_pFalloffMap->Release();
m_pFalloffMap = NULL;
/*if(m_pSpecularMap)
m_pSpecularMap->Release();
m_pSpecularMap = NULL;*/
if( glw_state->device )
{
glw_state->device->DeleteVertexShader( m_dwVertexShaderLight );
glw_state->device->DeletePixelShader( m_dwPixelShaderLight );
/*glw_state->device->DeleteVertexShader( m_dwVertexShaderSpecular_Dynamic );
glw_state->device->DeletePixelShader( m_dwPixelShaderSpecular_Dynamic );
glw_state->device->DeleteVertexShader( m_dwVertexShaderSpecular_Static );
glw_state->device->DeletePixelShader( m_dwPixelShaderSpecular_Static );*/
glw_state->device->DeleteVertexShader( m_dwVertexShaderEnvironment );
glw_state->device->DeletePixelShader( m_dwPixelShaderBump );
glw_state->device->DeleteVertexShader( m_dwVertexShaderBump );
}
}
void LightEffects::StartLightPhase()
{
m_bInLightPhase = true;
}
void LightEffects::EndLightPhase()
{
m_bInLightPhase = false;
}
bool LightEffects::Initialize()
{
HRESULT hr;
// Create a vertex shader
DWORD dwVertexDecl[] =
{
D3DVSD_STREAM( 0 ),
D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // v0 = Position
D3DVSD_REG( 1, D3DVSDT_FLOAT3 ), // v1 = Normal
D3DVSD_REG( 2, D3DVSDT_FLOAT2 ), // v2 = Base tex coords
D3DVSD_REG( 3, D3DVSDT_FLOAT3 ), // v3 = Tangent space tangent
D3DVSD_END()
};
if(!( CreateVertexShader("D:\\base\\media\\dlight.xvu", dwVertexDecl, &m_dwVertexShaderLight)))
return false;
/*if(!( CreateVertexShader("D:\\base\\media\\specular_dynamic.xvu", dwVertexDecl, &m_dwVertexShaderSpecular_Dynamic)))
return false;
if(!( CreateVertexShader("D:\\base\\media\\specular_static.xvu", dwVertexDecl, &m_dwVertexShaderSpecular_Static)))
return false;*/
DWORD dwVertexDeclBump[] =
{
D3DVSD_STREAM( 0 ),
D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // v0 = Position
D3DVSD_REG( 1, D3DVSDT_FLOAT3 ), // v1 = Normal
D3DVSD_REG( 2, D3DVSDT_FLOAT2 ), // v2 = Base tex coords 0
D3DVSD_REG( 3, D3DVSDT_FLOAT2 ), // v2 = Base tex coords 1
D3DVSD_REG( 4, D3DVSDT_FLOAT3 ), // v4 = Tangent space tangent
D3DVSD_END()
};
if(!( CreateVertexShader("D:\\base\\media\\bump.xvu", dwVertexDeclBump, &m_dwVertexShaderBump)))
return false;
DWORD dwVertexDeclEnv[] =
{
D3DVSD_STREAM( 0 ),
D3DVSD_REG( 0, D3DVSDT_FLOAT3 ), // v0 = Position
D3DVSD_REG( 1, D3DVSDT_FLOAT3 ), // v1 = Normal
D3DVSD_REG( 2, D3DVSDT_D3DCOLOR ), // v2 = Color
D3DVSD_END()
};
if(!( CreateVertexShader("D:\\base\\media\\environment.xvu", dwVertexDeclEnv, &m_dwVertexShaderEnvironment)))
return false;
// Create the pixel shader
if(!(CreatePixelShader("D:\\base\\media\\dlight.xpu", &m_dwPixelShaderLight)))
return false;
/*if(!(CreatePixelShader("D:\\base\\media\\specular_dynamic.xpu", &m_dwPixelShaderSpecular_Dynamic)))
return false;
if(!(CreatePixelShader("D:\\base\\media\\specular_static.xpu", &m_dwPixelShaderSpecular_Static)))
return false;*/
if(!(CreatePixelShader("D:\\base\\media\\bump.xpu", &m_dwPixelShaderBump)))
return false;
hr = D3DXCreateTextureFromFileEx(glw_state->device,
"D:\\base\\media\\defaultbump.dds",
D3DX_DEFAULT,
D3DX_DEFAULT,
0,
0,
D3DFMT_A8R8G8B8,
0,
D3DX_FILTER_LINEAR,
D3DX_FILTER_LINEAR,
0,
NULL,
NULL,
&m_pBumpMap);
if (FAILED(hr))
{
return false;
}
/*hr = D3DXCreateTextureFromFileEx(glw_state->device,
"D:\\base\\media\\diffspec.dds",
D3DX_DEFAULT,
D3DX_DEFAULT,
0,
0,
D3DFMT_A8R8G8B8,
0,
D3DX_FILTER_LINEAR,
D3DX_FILTER_LINEAR,
0,
NULL,
NULL,
&m_pSpecularMap);
if (FAILED(hr))
{
return false;
}*/
// Create the volume falloff texture
UINT width = 32,
height = 32,
depth = 32,
levels = 1;
D3DFORMAT format = D3DFMT_A8;
if (FAILED (hr = glw_state->device->CreateVolumeTexture(width, height, depth,
1, 0, format, D3DPOOL_DEFAULT, &m_pFalloffMap) ) )
{
return false;
}
// Fill the volume texture
D3DVOLUME_DESC desc;
D3DLOCKED_BOX lock;
m_pFalloffMap->GetLevelDesc( 0, &desc );
m_pFalloffMap->LockBox( 0, &lock, 0, 0L );
BYTE* pBits = (BYTE*)lock.pBits;
for( UINT w=0; w<width; w++ )
{
for( UINT v=0; v<height; v++ )
{
for( UINT u=0; u<depth; u++ )
{
FLOAT x = (2.0f*u)/(width-1) - 1.0f; // Ranges from -1 to +1
FLOAT y = (2.0f*v)/(height-1) - 1.0f; // Ranges from -1 to +1
FLOAT z = (2.0f*w)/(depth-1) - 1.0f;
FLOAT distance = (float)(x*x + y*y + z*z);
if (distance == 0)
{
*pBits++ = (BYTE)255;
}
else
{
FLOAT falloff = min(1.0f, max(0.0f, ((1.0f/2.0f)/distance - 1.0f/2.0f)/1.0f ) );
*pBits++ = (BYTE)(255*falloff);
}
}
}
}
DWORD dwPixelSize = XGBytesPerPixelFromFormat( desc.Format );
DWORD dwTextureSize = desc.Width * desc.Height * desc.Depth * dwPixelSize;
BYTE* pSrcBits = new BYTE[ dwTextureSize ];
memcpy( pSrcBits, lock.pBits, dwTextureSize );
XGSwizzleBox( pSrcBits, 0, 0, NULL, lock.pBits,
desc.Width, desc.Height, desc.Depth,
NULL, dwPixelSize );
delete [] pSrcBits;
m_pFalloffMap->UnlockBox( 0 );
// Create the normalization cube map
if(!CreateNormalizationCubeMap( 32, &m_pCubeMap ))
return false;
m_bInitialized = true;
return true;
}
bool LightEffects::RenderDynamicLights()
{
dlight_t *dl;
shaderStage_t *dStage;
vec3_t origin;
byte clipBits[SHADER_MAX_VERTEXES];
glIndex_t hitIndexes[SHADER_MAX_INDEXES];
int numIndexes;
float radius;
int fogging;
vec3_t dist;
vec3_t e1;
vec3_t e2;
vec3_t normal;
float fac;
if(!backEnd.refdef.num_dlights)
return true;
glw_state->device->SetRenderState( D3DRS_LIGHTING, FALSE );
glw_state->device->SetTextureStageState( 1, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP );
glw_state->device->SetTextureStageState( 1, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP );
glw_state->device->SetTextureStageState( 1, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 1, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 1, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSW, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 3, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 3, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
glw_state->device->SetTextureStageState( 3, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
glw_state->device->SetTextureStageState( 3, D3DTSS_MIPFILTER, D3DTEXF_POINT );
glw_state->device->SetTextureStageState( 2, D3DTSS_ALPHAKILL, D3DTALPHAKILL_ENABLE);
glw_state->device->SetTexture(1, m_pBumpMap);
glw_state->device->SetTexture(2, m_pFalloffMap);
glw_state->device->SetTexture(3, m_pCubeMap);
glw_state->device->SetPixelShader(m_dwPixelShaderLight);
glw_state->device->SetVertexShader(m_dwVertexShaderLight);
for(int l = 0; l < backEnd.refdef.num_dlights; l++)
{
if(!(tess.dlightBits & (1 << l)))
continue;
dl = &backEnd.refdef.dlights[l];
if(!dl)
continue;
VectorCopy( dl->transformed, origin );
radius = dl->radius;
int clipall = 63;
for (int i = 0 ; i < tess.numVertexes ; i++)
{
int clip;
VectorSubtract( origin, tess.xyz[i], dist );
clip = 0;
if ( dist[0] < -radius )
{
clip |= 1;
}
else if ( dist[0] > radius )
{
clip |= 2;
}
if ( dist[1] < -radius )
{
clip |= 4;
}
else if ( dist[1] > radius )
{
clip |= 8;
}
if ( dist[2] < -radius )
{
clip |= 16;
}
else if ( dist[2] > radius )
{
clip |= 32;
}
clipBits[i] = clip;
clipall &= clip;
}
if ( clipall )
{
continue; // this surface doesn't have any of this light
}
// build a list of triangles that need light
numIndexes = 0;
for ( i = 0 ; i < tess.numIndexes ; i += 3 )
{
int a, b, c;
a = tess.indexes[i];
b = tess.indexes[i+1];
c = tess.indexes[i+2];
if ( clipBits[a] & clipBits[b] & clipBits[c] )
{
continue; // not lighted
}
VectorSubtract( tess.xyz[a], tess.xyz[b], e1);
VectorSubtract( tess.xyz[c], tess.xyz[b], e2);
CrossProduct(e1,e2,normal);
VectorNormalize(normal);
fac=DotProduct(normal,origin)-DotProduct(normal, tess.xyz[a]);
if (fac >= radius) // out of range
{
continue;
}
// save the indexes
hitIndexes[numIndexes] = tess.indexes[i];
hitIndexes[numIndexes + 1] = tess.indexes[i + 1];
hitIndexes[numIndexes + 2] = tess.indexes[i + 2];
numIndexes += 3;
if (numIndexes>=SHADER_MAX_VERTEXES-3)
{
break; // we are out of space, so we are done :)
}
}
if ( !numIndexes ) {
continue;
}
//don't have fog enabled when we redraw with alpha test, or it will double over
//and screw the tri up -rww
if (r_drawfog->value == 2 &&
tr.world &&
(tess.fogNum == tr.world->globalFog || tess.fogNum == tr.world->numfogs))
{
fogging = qglIsEnabled(GL_FOG);
if (fogging)
{
qglDisable(GL_FOG);
}
}
else
{
fogging = 0;
}
dStage = NULL;
if (tess.shader)
{
int j = 0;
while (j < tess.shader->numUnfoggedPasses)
{
const int blendBits = (GLS_SRCBLEND_BITS+GLS_DSTBLEND_BITS);
if (((tess.shader->stages[j].bundle[0].image && !tess.shader->stages[j].bundle[0].isLightmap && !tess.shader->stages[j].bundle[0].numTexMods && tess.shader->stages[j].bundle[0].tcGen != TCGEN_ENVIRONMENT_MAPPED && tess.shader->stages[j].bundle[0].tcGen != TCGEN_FOG) ||
(tess.shader->stages[j].bundle[1].image && !tess.shader->stages[j].bundle[1].isLightmap && !tess.shader->stages[j].bundle[1].numTexMods && tess.shader->stages[j].bundle[1].tcGen != TCGEN_ENVIRONMENT_MAPPED && tess.shader->stages[j].bundle[1].tcGen != TCGEN_FOG)) &&
(tess.shader->stages[j].stateBits & blendBits) == 0 )
{ //only use non-lightmap opaque stages
dStage = &tess.shader->stages[j];
break;
}
j++;
}
}
if (dStage)
{
GL_SelectTexture( 0 );
GL_State(0);
if (dStage->bundle[0].image && !dStage->bundle[0].isLightmap && !dStage->bundle[0].numTexMods && dStage->bundle[0].tcGen != TCGEN_ENVIRONMENT_MAPPED && dStage->bundle[0].tcGen != TCGEN_FOG)
{
GL_Bind( dStage->bundle[0].image );
}
else
{
GL_Bind( dStage->bundle[1].image );
}
GL_State(GLS_SRCBLEND_ONE | GLS_DSTBLEND_ONE);// | GLS_DEPTHFUNC_EQUAL);
}
else
{
GL_Bind( tr.whiteImage );
GL_State( GLS_SRCBLEND_DST_COLOR | GLS_DSTBLEND_ONE);// | GLS_DEPTHFUNC_EQUAL );
}
glwstate_t::texturexlat_t::iterator inf = glw_state->textureXlat.find(glw_state->currentTexture[0]);
glw_state->device->SetTexture(0, inf->second.mipmap);
D3DXVECTOR4 vecLightRange(1.0f / dl->radius, 0.0f, 0.0f, 0.0f);
glw_state->device->SetVertexShaderConstant(CV_ONE_OVER_LIGHT_RANGE, (void*)&vecLightRange.x, 1);
glw_state->device->SetPixelShaderConstant(CP_DIFFUSE_COLOR, &dl->color[0], 1);
ProcessVertices( (D3DXVECTOR3*)&dl->transformed );
renderObject_Light( numIndexes, hitIndexes );
if (fogging)
{
qglEnable(GL_FOG);
}
}
glw_state->device->SetPixelShader( 0 );
// This is kinda a hack to get the quake renderer to discard
// these textures after they are used here, instead of applying
// them to more geometry
glState.currenttextures[0] = -2;
glState.currenttextures[1] = -2;
glw_state->currentTexture[0] = -2;
glw_state->currentTexture[1] = -2;
glw_state->device->SetTextureStageState( 2, D3DTSS_ALPHAKILL, D3DTALPHAKILL_DISABLE);
return true;
}
//void LightEffects::RenderSpecular()
//{
// glw_state->device->SetRenderState( D3DRS_LIGHTING, FALSE );
// glw_state->device->SetRenderState( D3DRS_FOGENABLE, FALSE );
//
// glwstate_t::texturexlat_t::iterator i = glw_state->textureXlat.find(glw_state->currentTexture[0]);
//
// glw_state->device->SetTexture( 0, i->second.mipmap );
// glw_state->device->SetTexture( 2, m_pSpecularMap );
//
// glw_state->device->SetVertexShaderConstant(CV_CAMERA_DIRECTION, D3DXVECTOR4(tr.viewParms.ori.axis[0][0],
// tr.viewParms.ori.axis[0][1],
// tr.viewParms.ori.axis[0][2],
// 1.0f), 1 );
//
// RenderSpecular_Static();
//
// if(tess.dlightBits)
// RenderSpecular_Dynamic();
//
// glw_state->device->SetPixelShader(0);
//
// // This is kinda a hack to get the quake renderer to discard
// // these textures after they are used here, instead of applying
// // them to more geometry
// glState.currenttextures[0] = -2;
// glState.currenttextures[1] = -2;
// glw_state->currentTexture[0] = -2;
// glw_state->currentTexture[1] = -2;
//}
//
//
//bool LightEffects::RenderSpecular_Dynamic()
//{
// VVdlight_t *dl;
//
// glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP );
// glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP );
// glw_state->device->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
// glw_state->device->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
// glw_state->device->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
// glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
// glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
// glw_state->device->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
// glw_state->device->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
// glw_state->device->SetTextureStageState( 2, D3DTSS_MIPFILTER, D3DTEXF_POINT );
// glw_state->device->SetTextureStageState( 3, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
// glw_state->device->SetTextureStageState( 3, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
// glw_state->device->SetTextureStageState( 3, D3DTSS_ADDRESSW, D3DTADDRESS_CLAMP );
// glw_state->device->SetTextureStageState( 3, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
// glw_state->device->SetTextureStageState( 3, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
//
// glw_state->device->SetTexture( 3, m_pFalloffMap );
//
// glw_state->device->SetPixelShader(m_dwPixelShaderSpecular_Dynamic);
// glw_state->device->SetVertexShader(m_dwVertexShaderSpecular_Dynamic);
//
// for(int i = 0; i < VVLightMan.num_dlights; i++)
// {
// if(!(tess.dlightBits & (1 << i)))
// continue;
//
// dl = &VVLightMan.dlights[i];
//
// D3DXVECTOR4 vecLightRange(1.0f / dl->radius, 0.0f, 0.0f, 0.0f);
// glw_state->device->SetVertexShaderConstant(CV_ONE_OVER_LIGHT_RANGE, (void*)&vecLightRange.x, 1);
//
// ProcessVertices( (D3DXVECTOR3*)&dl->direction, (D3DXVECTOR3*)&dl->transformed );
//
// renderObject_Light(tess.numIndexes, tess.indexes);
// }
//
// glw_state->device->SetTexture( 3, NULL );
//
// return true;
//}
//
//
//bool LightEffects::RenderSpecular_Static()
//{
// glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSU, D3DTADDRESS_WRAP );
// glw_state->device->SetTextureStageState( 0, D3DTSS_ADDRESSV, D3DTADDRESS_WRAP );
// glw_state->device->SetTextureStageState( 0, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
// glw_state->device->SetTextureStageState( 0, D3DTSS_MAGFILTER, D3DTEXF_LINEAR );
// glw_state->device->SetTextureStageState( 0, D3DTSS_MIPFILTER, D3DTEXF_LINEAR );
// glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSU, D3DTADDRESS_CLAMP );
// glw_state->device->SetTextureStageState( 2, D3DTSS_ADDRESSV, D3DTADDRESS_CLAMP );
// glw_state->device->SetTextureStageState( 2, D3DTSS_MINFILTER, D3DTEXF_LINEAR );
// glw_state->device->SetTextureStageState( 2, D3DTSS_MAGFILTER, D3DTEXF_LINEAR);
// glw_state->device->SetTextureStageState( 2, D3DTSS_MIPFILTER, D3DTEXF_NONE );
//
// glw_state->device->SetPixelShader(m_dwPixelShaderSpecular_Static);
// glw_state->device->SetVertexShader(m_dwVertexShaderSpecular_Static);
//
// ProcessVertices( NULL, NULL );
//
// D3DXVECTOR4 vLight;
// if (backEnd.currentEntity && (backEnd.currentEntity->e.hModel||backEnd.currentEntity->e.ghoul2) )
// {
// vLight.x = backEnd.currentEntity->lightDir[0];
// vLight.y = backEnd.currentEntity->lightDir[1];
// vLight.z = backEnd.currentEntity->lightDir[2];
// }
// else
// {
// // These values were taken from the RB_CalcSpecularAlpha default case
// vLight.x = -960.0f;
// vLight.y = 1920.0f;
// vLight.z = 96.0f;
// }
//
// vLight.w = 1.0f;
//
// glw_state->device->SetVertexShaderConstant(CV_LIGHT_DIRECTION, vLight, 1);
//
// renderObject_Light(tess.numIndexes, tess.indexes);
//
// return true;
//}
bool LightEffects::RenderEnvironment()
{
glw_state->device->SetRenderState( D3DRS_LIGHTING, false );
glw_state->device->SetRenderState( D3DRS_FOGENABLE, false );
glw_state->device->SetVertexShaderConstant(CV_CAMERA_DIRECTION, D3DXVECTOR4(backEnd.ori.viewOrigin[0],
backEnd.ori.viewOrigin[1],
backEnd.ori.viewOrigin[2],
1.0f), 1 );
ProcessVertices(NULL);
glw_state->device->SetVertexShader(m_dwVertexShaderEnvironment);
renderObject_Env();
return true;
}
// Renders bump maps without the benefit of dynamic lights
void LightEffects::RenderBump()
{
glw_state->device->SetRenderState( D3DRS_LIGHTING, false );
glw_state->device->SetRenderState( D3DRS_FOGENABLE, false );
glwstate_t::texturexlat_t::iterator i = glw_state->textureXlat.find(glw_state->currentTexture[0]);
glw_state->device->SetTexture( 0, i->second.mipmap );
i = glw_state->textureXlat.find(glw_state->currentTexture[1]);
glw_state->device->SetTexture( 1, i->second.mipmap );
glw_state->device->SetTextureStageState(0, D3DTSS_MAXANISOTROPY, i->second.anisotropy);
glw_state->device->SetTextureStageState(0, D3DTSS_MINFILTER, i->second.minFilter);
glw_state->device->SetTextureStageState(0, D3DTSS_MIPFILTER, i->second.mipFilter);
glw_state->device->SetTextureStageState(0, D3DTSS_MAGFILTER, i->second.magFilter);
glw_state->device->SetTextureStageState(0, D3DTSS_ADDRESSU, i->second.wrapU);
glw_state->device->SetTextureStageState(0, D3DTSS_ADDRESSV, i->second.wrapV);
glw_state->device->SetTextureStageState(1, D3DTSS_MAXANISOTROPY, i->second.anisotropy);
glw_state->device->SetTextureStageState(1, D3DTSS_MINFILTER, i->second.minFilter);
glw_state->device->SetTextureStageState(1, D3DTSS_MIPFILTER, i->second.mipFilter);
glw_state->device->SetTextureStageState(1, D3DTSS_MAGFILTER, i->second.magFilter);
glw_state->device->SetTextureStageState(1, D3DTSS_ADDRESSU, i->second.wrapU);
glw_state->device->SetTextureStageState(1, D3DTSS_ADDRESSV, i->second.wrapV);
glw_state->device->SetRenderState(D3DRS_SPECULARENABLE, true);
glw_state->device->SetPixelShader(m_dwPixelShaderBump);
glw_state->device->SetVertexShader(m_dwVertexShaderBump);
ProcessVertices(NULL);
D3DXVECTOR4 vAmbient, vDiffuse, vLightDir;
if (backEnd.currentEntity && (backEnd.currentEntity->e.hModel||backEnd.currentEntity->e.ghoul2) )
{
if(tess.shader->stages[0].rgbGen == CGEN_LIGHTING_DIFFUSE_ENTITY)
{
vAmbient.x = (backEnd.currentEntity->ambientLight[0] / 255.f) * (backEnd.currentEntity->e.shaderRGBA[0] / 255.0);
vAmbient.y = (backEnd.currentEntity->ambientLight[1] / 255.f) * (backEnd.currentEntity->e.shaderRGBA[1] / 255.0);
vAmbient.z = (backEnd.currentEntity->ambientLight[2] / 255.f) * (backEnd.currentEntity->e.shaderRGBA[2] / 255.0);
}
else
{
vAmbient.x = backEnd.currentEntity->ambientLight[0] / 255.f;
vAmbient.y = backEnd.currentEntity->ambientLight[1] / 255.f;
vAmbient.z = backEnd.currentEntity->ambientLight[2] / 255.f;
}
vDiffuse.x = backEnd.currentEntity->directedLight[0] / 255.f;
vDiffuse.y = backEnd.currentEntity->directedLight[1] / 255.f;
vDiffuse.z = backEnd.currentEntity->directedLight[2] / 255.f;
vLightDir.x = DotProduct( backEnd.currentEntity->lightDir, backEnd.currentEntity->e.axis[0] );
vLightDir.y = DotProduct( backEnd.currentEntity->lightDir, backEnd.currentEntity->e.axis[1] );
vLightDir.z = DotProduct( backEnd.currentEntity->lightDir, backEnd.currentEntity->e.axis[2] );
}
else
{
vec3_t sundir;
sundir[0] = r_sundir_x->value;
sundir[1] = r_sundir_y->value;
sundir[2] = r_sundir_z->value;
VectorNormalize(sundir);
vLightDir.x = sundir[0];//tr.sunDirection[0];
vLightDir.y = sundir[1];//tr.sunDirection[1];
vLightDir.z = sundir[2];//tr.sunDirection[2];
vLightDir.w = 1.0f;
vAmbient.x = tr.sunAmbient[0] / 1.5f;
vAmbient.y = tr.sunAmbient[1] / 1.5f;
vAmbient.z = tr.sunAmbient[2] / 1.5f;
vDiffuse.x = 1.0f;
vDiffuse.y = 1.0f;
vDiffuse.z = 1.0f;
}
glw_state->device->SetPixelShaderConstant(CP_AMBIENT_COLOR, vAmbient, 1);
glw_state->device->SetPixelShaderConstant(CP_DIFFUSE_COLOR, vDiffuse, 1);
glw_state->device->SetVertexShaderConstant(CV_LIGHT_DIRECTION, vLightDir, 1);
glw_state->device->SetVertexShaderConstant(CV_CAMERA_DIRECTION, D3DXVECTOR4(tr.viewParms.ori.axis[0][0],
tr.viewParms.ori.axis[0][1],
tr.viewParms.ori.axis[0][2],
1.0f), 1 );
renderObject_Bump();
glw_state->device->SetPixelShader( 0 );
glw_state->device->SetRenderState(D3DRS_SPECULARENABLE, false);
}
//bool LightEffects::RenderStaticLights()
//{
// VVslight_t *sl;
//
// for(int i = 0; i < tess.numSlights; i++)
// {
// sl = &VVLightMan.slights[tess.slightBits[i]];
//
// D3DXVECTOR4 vecLightRange(1.0f / (sl->radius * 2.0f), sl->radius, 1.0f, 1.0f);
// glw_state->device->SetVertexShaderConstant(CV_ONE_OVER_LIGHT_RANGE, (void*)&vecLightRange.x, 1);
//
// glw_state->device->SetVertexShaderConstant(CV_LIGHT_COLOR, &sl->color[0], 1);
//
// ProcessVertices( NULL, (D3DXVECTOR3*)&sl->origin );
//
// renderObject_Light();
//
// tess.currentPass++;
// }
//
// return true;
//}
void LightEffects::ProcessVertices( D3DXVECTOR3* pPtLightPos )
{
// Just in case, this doesn't always get set
glw_state->device->SetTransform( D3DTS_PROJECTION, glw_state->matrixStack[glw_state->MatrixMode_Projection]->GetTop() );
// Compute the matrix set
XGMATRIX matComposite, matProjectionViewport, matWorld;
// Get the projection viewport matrix the fixed pipeline uses.
// The viewport matrix includes the viewport x,y scale and the
// appropriate z scale.
glw_state->device->GetProjectionViewportMatrix( &matProjectionViewport );
D3DVIEWPORT8 view;
glw_state->device->GetViewport(&view);
// Gotta do this to fix an XDK bug
// GetProjectionViewportMatrix does not seem to reflect the viewport values
// when the viewport is offset
matProjectionViewport._31 += view.X;
matProjectionViewport._32 += view.Y;
XGMatrixMultiply( &matComposite, (XGMATRIX*)glw_state->matrixStack[glwstate_t::MatrixMode_Model]->GetTop(), &matProjectionViewport );
// Transpose and set the composite matrix.
XGMatrixTranspose( &matComposite, &matComposite );
glw_state->device->SetVertexShaderConstant( CV_WORLDVIEWPROJ_0, &matComposite, 4 );
if (pPtLightPos)
glw_state->device->SetVertexShaderConstant( CV_LIGHT_POSITION, pPtLightPos, 1 );
// Set viewport offsets.
float fViewportOffsets[4] = { 0.53125f, 0.53125f, 0.0f, 0.0f };
glw_state->device->SetVertexShaderConstant( CV_VIEWPORT_OFFSETS, &fViewportOffsets, 1 );
// Set common constants
glw_state->device->SetVertexShaderConstant(CV_ONE, D3DXVECTOR4(1.0f, 1.0f, 1.0f, 1.0f), 1);
glw_state->device->SetVertexShaderConstant(CV_HALF, D3DXVECTOR4(0.5f, 0.5f, 0.5f, 0.5f), 1);
}
inline D3DCOLOR VectorToRGBA( const D3DXVECTOR3* v, FLOAT fHeight = 1.0f )
{
D3DCOLOR r = (D3DCOLOR)( ( v->x + 1.0f ) * 127.5f );
D3DCOLOR g = (D3DCOLOR)( ( v->y + 1.0f ) * 127.5f );
D3DCOLOR b = (D3DCOLOR)( ( v->z + 1.0f ) * 127.5f );
D3DCOLOR a = (D3DCOLOR)( 255.0f * fHeight );
return( (a<<24L) + (r<<16L) + (g<<8L) + (b<<0L) );
}
bool LightEffects::CreateNormalizationCubeMap( DWORD dwSize, LPDIRECT3DCUBETEXTURE8* ppCubeMap )
{
HRESULT hr;
// Create the cube map
if( FAILED( hr = glw_state->device->CreateCubeTexture( dwSize, 1, 0, D3DFMT_X8R8G8B8,
D3DPOOL_DEFAULT, ppCubeMap ) ) )
return false;
// Allocate temp space for swizzling the cubemap surfaces
DWORD* pSourceBits = new DWORD[ dwSize * dwSize ];
// Fill all six sides of the cubemap
for( DWORD i=0; i<6; i++ )
{
// Lock the i'th cubemap surface
LPDIRECT3DSURFACE8 pCubeMapFace;
(*ppCubeMap)->GetCubeMapSurface( (D3DCUBEMAP_FACES)i, 0, &pCubeMapFace );
// Write the RGBA-encoded normals to the surface pixels
DWORD* pPixel = pSourceBits;
D3DXVECTOR3 n;
FLOAT w, h;
for( DWORD y = 0; y < dwSize; y++ )
{
h = (FLOAT)y / (FLOAT)(dwSize-1); // 0 to 1
h = ( h * 2.0f ) - 1.0f; // -1 to 1
for( DWORD x = 0; x < dwSize; x++ )
{
w = (FLOAT)x / (FLOAT)(dwSize-1); // 0 to 1
w = ( w * 2.0f ) - 1.0f; // -1 to 1
// Calc the normal for this texel
switch( i )
{
case D3DCUBEMAP_FACE_POSITIVE_X: // +x
n.x = +1.0;
n.y = -h;
n.z = -w;
break;
case D3DCUBEMAP_FACE_NEGATIVE_X: // -x
n.x = -1.0;
n.y = -h;
n.z = +w;
break;
case D3DCUBEMAP_FACE_POSITIVE_Y: // y
n.x = +w;
n.y = +1.0;
n.z = +h;
break;
case D3DCUBEMAP_FACE_NEGATIVE_Y: // -y
n.x = +w;
n.y = -1.0;
n.z = -h;
break;
case D3DCUBEMAP_FACE_POSITIVE_Z: // +z
n.x = +w;
n.y = -h;
n.z = +1.0;
break;
case D3DCUBEMAP_FACE_NEGATIVE_Z: // -z
n.x = -w;
n.y = -h;
n.z = -1.0;
break;
}
// Store the normal as an RGBA color
D3DXVec3Normalize( &n, &n );
*pPixel++ = VectorToRGBA( &n );
}
}
// Swizzle the result into the cubemap face surface
D3DLOCKED_RECT lock;
pCubeMapFace->LockRect( &lock, 0, 0L );
XGSwizzleRect( pSourceBits, 0, NULL, lock.pBits, dwSize, dwSize,
NULL, sizeof(DWORD) );
pCubeMapFace->UnlockRect();
// Release the cubemap face
pCubeMapFace->Release();
}
// Free temp space
if( pSourceBits )
delete [] pSourceBits;
pSourceBits = NULL;
return true;
}
#endif // VV_LIGHTING