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.
366 lines
8.6 KiB
366 lines
8.6 KiB
//========= Copyright © 1996-2010, Valve Corporation, All rights reserved. ============//
|
|
//
|
|
// Purpose: global dynamic light with cascaded shadow mapping
|
|
//
|
|
// $NoKeywords: $
|
|
//=============================================================================//
|
|
|
|
#include "cbase.h"
|
|
#include "lights.h"
|
|
#include "env_cascade_light.h"
|
|
|
|
// memdbgon must be the last include file in a .cpp file!!!
|
|
#include "tier0/memdbgon.h"
|
|
|
|
//#define CsmDbgMsg Msg
|
|
#define CsmDbgMsg(x)
|
|
|
|
ConVar cl_csm_auto_entity( "cl_csm_auto_entity", "1", 0, "" );
|
|
|
|
CCascadeLight *g_pCascadeLight;
|
|
|
|
LINK_ENTITY_TO_CLASS(env_cascade_light, CCascadeLight);
|
|
|
|
BEGIN_DATADESC( CCascadeLight )
|
|
|
|
DEFINE_KEYFIELD( m_bEnabled, FIELD_BOOLEAN, "enabled" ),
|
|
DEFINE_KEYFIELD( m_bStartDisabled, FIELD_BOOLEAN, "StartDisabled" ),
|
|
DEFINE_FIELD( m_LightColor, FIELD_COLOR32 ),
|
|
DEFINE_FIELD( m_LightColorScale, FIELD_INTEGER ),
|
|
|
|
// Inputs
|
|
|
|
DEFINE_INPUTFUNC( FIELD_COLOR32, "LightColor", InputSetLightColor ),
|
|
DEFINE_INPUTFUNC( FIELD_INTEGER, "LightColorScale", InputSetLightColorScale ),
|
|
DEFINE_INPUTFUNC( FIELD_STRING, "SetAngles", InputSetAngles ),
|
|
DEFINE_INPUTFUNC( FIELD_VOID, "Enable", InputEnable ),
|
|
DEFINE_INPUTFUNC( FIELD_VOID, "Disable", InputDisable ),
|
|
|
|
END_DATADESC()
|
|
|
|
IMPLEMENT_SERVERCLASS_ST_NOBASE(CCascadeLight, DT_CascadeLight)
|
|
SendPropVector(SENDINFO(m_shadowDirection), -1, SPROP_NOSCALE ),
|
|
SendPropVector(SENDINFO(m_envLightShadowDirection), -1, SPROP_NOSCALE ),
|
|
SendPropBool(SENDINFO(m_bEnabled) ),
|
|
SendPropBool(SENDINFO(m_bUseLightEnvAngles) ),
|
|
SendPropInt(SENDINFO(m_LightColor), 32, SPROP_UNSIGNED, SendProxy_Color32ToInt32 ),
|
|
SendPropInt(SENDINFO(m_LightColorScale), 32, 0, SendProxy_Int32ToInt32 ),
|
|
SendPropFloat(SENDINFO(m_flMaxShadowDist), 0, SPROP_NOSCALE ),
|
|
END_SEND_TABLE()
|
|
|
|
float CCascadeLight::m_flEnvLightShadowPitch;
|
|
QAngle CCascadeLight::m_EnvLightShadowAngles;
|
|
bool CCascadeLight::m_bEnvLightShadowValid;
|
|
color32 CCascadeLight::m_EnvLightColor;
|
|
int CCascadeLight::m_EnvLightColorScale;
|
|
|
|
CCascadeLight::CCascadeLight() :
|
|
CBaseEntity()
|
|
{
|
|
CsmDbgMsg( "CCascadeLight::CCascadeLight\n" );
|
|
|
|
m_bEnabled = true;
|
|
|
|
color32 tmp = { 255, 255, 255, 1 };
|
|
m_LightColor = tmp;
|
|
|
|
m_LightColorScale = 255;
|
|
|
|
QAngle angles;
|
|
angles.Init( 50, 43, 0 );
|
|
Vector vForward;
|
|
AngleVectors( angles, &vForward );
|
|
m_shadowDirection = vForward;
|
|
//m_shadowDirection.Init( 0.0f, 0.0f, -1.0f );
|
|
|
|
m_envLightShadowDirection = m_shadowDirection;
|
|
m_bUseLightEnvAngles = true;
|
|
|
|
m_flMaxShadowDist = 400.0f;
|
|
|
|
g_pCascadeLight = this;
|
|
}
|
|
|
|
CCascadeLight::~CCascadeLight()
|
|
{
|
|
g_pCascadeLight = NULL;
|
|
|
|
CsmDbgMsg( "CCascadeLight::~CCascadeLight\n" );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Purpose : Send even though we don't have a model
|
|
//------------------------------------------------------------------------------
|
|
int CCascadeLight::UpdateTransmitState()
|
|
{
|
|
// ALWAYS transmit to all clients.
|
|
return SetTransmitState( FL_EDICT_ALWAYS );
|
|
}
|
|
|
|
|
|
bool CCascadeLight::KeyValue( const char *szKeyName, const char *szValue )
|
|
{
|
|
if ( FStrEq( szKeyName, "color" ) )
|
|
{
|
|
/* unused?
|
|
float tmp[4];
|
|
UTIL_StringToFloatArray( tmp, 4, szValue );
|
|
|
|
m_LightColor.SetR( tmp[0] );
|
|
m_LightColor.SetG( tmp[1] );
|
|
m_LightColor.SetB( tmp[2] );
|
|
m_LightColor.SetA( tmp[3] );*/
|
|
}
|
|
else if ( FStrEq( szKeyName, "angles" ) )
|
|
{
|
|
QAngle angles;
|
|
UTIL_StringToVector( angles.Base(), szValue );
|
|
if (angles == vec3_angle)
|
|
{
|
|
angles.Init( 50, 43, 0 );
|
|
}
|
|
Vector vForward;
|
|
AngleVectors( angles, &vForward );
|
|
m_shadowDirection = vForward;
|
|
return true;
|
|
}
|
|
else if ( FStrEq( szKeyName, "uselightenvangles" ) )
|
|
{
|
|
m_bUseLightEnvAngles = ( atoi( szValue ) != 0 );
|
|
return true;
|
|
}
|
|
else if ( FStrEq( szKeyName, "maxshadowdistance" ) )
|
|
{
|
|
m_flMaxShadowDist = atof( szValue );
|
|
return true;
|
|
}
|
|
|
|
return BaseClass::KeyValue( szKeyName, szValue );
|
|
}
|
|
|
|
bool CCascadeLight::GetKeyValue( const char *szKeyName, char *szValue, int iMaxLen )
|
|
{
|
|
if ( FStrEq( szKeyName, "color" ) )
|
|
{
|
|
// path unused?
|
|
Q_snprintf( szValue, iMaxLen, "%d %d %d %d", m_LightColor.GetR(), m_LightColor.GetG(), m_LightColor.GetB(), m_LightColor.GetA() );
|
|
return true;
|
|
}
|
|
return BaseClass::GetKeyValue( szKeyName, szValue, iMaxLen );
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Purpose :
|
|
//------------------------------------------------------------------------------
|
|
void CCascadeLight::Spawn( void )
|
|
{
|
|
Precache();
|
|
SetSolid( SOLID_NONE );
|
|
|
|
if( m_bStartDisabled )
|
|
{
|
|
m_bEnabled = false;
|
|
}
|
|
else
|
|
{
|
|
m_bEnabled = true;
|
|
}
|
|
|
|
if ( m_bEnvLightShadowValid )
|
|
{
|
|
UpdateEnvLight();
|
|
}
|
|
|
|
//SetClassname( "cascadelight" );
|
|
|
|
BaseClass::Spawn();
|
|
}
|
|
|
|
void CCascadeLight::Release( void )
|
|
{
|
|
g_pCascadeLight = NULL;
|
|
}
|
|
|
|
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Purpose :
|
|
//------------------------------------------------------------------------------
|
|
void CCascadeLight::OnActivate()
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Purpose :
|
|
//------------------------------------------------------------------------------
|
|
void CCascadeLight::OnDeactivate()
|
|
{
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Input values
|
|
//------------------------------------------------------------------------------
|
|
void CCascadeLight::InputSetAngles( inputdata_t &inputdata )
|
|
{
|
|
const char *pAngles = inputdata.value.String();
|
|
|
|
QAngle angles;
|
|
UTIL_StringToVector( angles.Base(), pAngles );
|
|
|
|
Vector vTemp;
|
|
AngleVectors( angles, &vTemp );
|
|
m_shadowDirection = vTemp;
|
|
}
|
|
|
|
//------------------------------------------------------------------------------
|
|
// Purpose : Input handlers
|
|
//------------------------------------------------------------------------------
|
|
void CCascadeLight::InputEnable( inputdata_t &inputdata )
|
|
{
|
|
m_bEnabled = true;
|
|
if ( g_pCascadeLight )
|
|
{
|
|
g_pCascadeLight->UpdateEnvLight();
|
|
}
|
|
}
|
|
|
|
void CCascadeLight::InputDisable( inputdata_t &inputdata )
|
|
{
|
|
m_bEnabled = false;
|
|
if ( g_pCascadeLight )
|
|
{
|
|
g_pCascadeLight->UpdateEnvLight();
|
|
}
|
|
}
|
|
|
|
void CCascadeLight::InputSetLightColor( inputdata_t &inputdata )
|
|
{
|
|
m_LightColor = inputdata.value.Color32();
|
|
}
|
|
|
|
void CCascadeLight::InputSetLightColorScale( inputdata_t &inputdata )
|
|
{
|
|
m_LightColorScale = inputdata.value.Int();
|
|
if ( g_pCascadeLight )
|
|
{
|
|
g_pCascadeLight->UpdateEnvLight();
|
|
}
|
|
}
|
|
|
|
void CCascadeLight::SetLightColor( int r, int g, int b, int a )
|
|
{
|
|
m_EnvLightColor.r = r;
|
|
m_EnvLightColor.g = g;
|
|
m_EnvLightColor.b = b;
|
|
|
|
m_EnvLightColor.a = 0; // use light scale as potentially > 255
|
|
|
|
m_EnvLightColorScale = a;
|
|
|
|
if ( g_pCascadeLight )
|
|
{
|
|
g_pCascadeLight->UpdateEnvLight();
|
|
}
|
|
}
|
|
|
|
void CCascadeLight::SetEnabled( bool bEnable )
|
|
{
|
|
m_bEnabled = bEnable;
|
|
}
|
|
|
|
void CCascadeLight::UpdateEnvLight()
|
|
{
|
|
QAngle angles;
|
|
angles.x = -m_flEnvLightShadowPitch;
|
|
angles.y = m_EnvLightShadowAngles.y;
|
|
angles.z = 0;
|
|
|
|
Vector vForward;
|
|
AngleVectors( angles, &vForward );
|
|
m_envLightShadowDirection = vForward;
|
|
|
|
m_LightColor = m_EnvLightColor;
|
|
m_LightColorScale = m_EnvLightColorScale;
|
|
}
|
|
|
|
void CCascadeLight::SetEnvLightShadowPitch( float flPitch )
|
|
{
|
|
m_flEnvLightShadowPitch = flPitch;
|
|
m_bEnvLightShadowValid = true;
|
|
|
|
if ( g_pCascadeLight )
|
|
{
|
|
g_pCascadeLight->UpdateEnvLight();
|
|
}
|
|
}
|
|
|
|
void CCascadeLight::SetEnvLightShadowAngles( const QAngle &angles )
|
|
{
|
|
m_EnvLightShadowAngles = angles;
|
|
m_bEnvLightShadowValid = true;
|
|
|
|
if ( g_pCascadeLight )
|
|
{
|
|
g_pCascadeLight->UpdateEnvLight();
|
|
}
|
|
}
|
|
|
|
class CCSMLightManager : public CAutoGameSystemPerFrame
|
|
{
|
|
public:
|
|
CCSMLightManager()
|
|
{
|
|
}
|
|
|
|
virtual ~CCSMLightManager()
|
|
{
|
|
}
|
|
|
|
virtual void LevelInitPreEntity()
|
|
{
|
|
CsmDbgMsg( "**** LevelInitPreEntity\n" );
|
|
}
|
|
|
|
virtual void LevelInitPostEntity()
|
|
{
|
|
CsmDbgMsg( "**** LevelInitPostEntity\n" );
|
|
|
|
if ( !cl_csm_auto_entity.GetBool() )
|
|
return;
|
|
if ( g_pCascadeLight )
|
|
return;
|
|
|
|
// Create the env_cascade_light automatically for cs:go - this is a hack that will hopefully go away as we add the entity to all of our maps.
|
|
CBaseEntity *entity = dynamic_cast< CBaseEntity * >( CreateEntityByName( "env_cascade_light" ) );
|
|
if (entity)
|
|
{
|
|
entity->Precache();
|
|
entity->KeyValue( "targetname", "cascadelight" );
|
|
DispatchSpawn(entity);
|
|
}
|
|
}
|
|
|
|
virtual void LevelShutdownPreEntity()
|
|
{
|
|
CsmDbgMsg( "**** LevelShutdownPreEntity\n" );
|
|
}
|
|
|
|
virtual void LevelShutdownPostEntity()
|
|
{
|
|
CsmDbgMsg( "**** LevelShutdownPostEntity\n" );
|
|
}
|
|
|
|
virtual void Shutdown()
|
|
{
|
|
CsmDbgMsg( "**** Shutdown\n" );
|
|
}
|
|
};
|
|
|
|
CCSMLightManager g_CSMLightManager;
|
|
|
|
void C_CSM_Server_Status( const CCommand& args )
|
|
{
|
|
Msg( "Entity exists: %u\n", g_pCascadeLight != NULL );
|
|
}
|
|
|
|
static ConCommand cl_csm_server_status("cl_csm_server_status", C_CSM_Server_Status, "Usage:\n cl_csm_server_status\n", 0);
|