Counter Strike : Global Offensive Source Code
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

//========= 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);