//========= Copyright Valve Corporation, All rights reserved. ============// // // Purpose: // //============================================================================= #include "cbase.h" #include "shareddefs.h" #include "materialsystem/imesh.h" #include "materialsystem/imaterial.h" #include "view.h" #include "iviewrender.h" #include "view_shared.h" #include "texture_group_names.h" #include "tier0/icommandline.h" // memdbgon must be the last include file in a .cpp file!!! #include "tier0/memdbgon.h" static ConVar mat_slopescaledepthbias_shadowmap( "mat_slopescaledepthbias_shadowmap", "16", FCVAR_CHEAT ); static ConVar mat_depthbias_shadowmap( "mat_depthbias_shadowmap", "0.0005", FCVAR_CHEAT ); //----------------------------------------------------------------------------- // Purpose: //----------------------------------------------------------------------------- class C_EnvProjectedTexture : public C_BaseEntity { DECLARE_CLASS( C_EnvProjectedTexture, C_BaseEntity ); public: DECLARE_CLIENTCLASS(); virtual void OnDataChanged( DataUpdateType_t updateType ); void ShutDownLightHandle( void ); virtual void Simulate(); void UpdateLight( bool bForceUpdate ); C_EnvProjectedTexture(); ~C_EnvProjectedTexture(); private: ClientShadowHandle_t m_LightHandle; EHANDLE m_hTargetEntity; bool m_bState; float m_flLightFOV; bool m_bEnableShadows; bool m_bLightOnlyTarget; bool m_bLightWorld; bool m_bCameraSpace; Vector m_LinearFloatLightColor; float m_flAmbient; float m_flNearZ; float m_flFarZ; char m_SpotlightTextureName[ MAX_PATH ]; int m_nSpotlightTextureFrame; int m_nShadowQuality; }; IMPLEMENT_CLIENTCLASS_DT( C_EnvProjectedTexture, DT_EnvProjectedTexture, CEnvProjectedTexture ) RecvPropEHandle( RECVINFO( m_hTargetEntity ) ), RecvPropBool( RECVINFO( m_bState ) ), RecvPropFloat( RECVINFO( m_flLightFOV ) ), RecvPropBool( RECVINFO( m_bEnableShadows ) ), RecvPropBool( RECVINFO( m_bLightOnlyTarget ) ), RecvPropBool( RECVINFO( m_bLightWorld ) ), RecvPropBool( RECVINFO( m_bCameraSpace ) ), RecvPropVector( RECVINFO( m_LinearFloatLightColor ) ), RecvPropFloat( RECVINFO( m_flAmbient ) ), RecvPropString( RECVINFO( m_SpotlightTextureName ) ), RecvPropInt( RECVINFO( m_nSpotlightTextureFrame ) ), RecvPropFloat( RECVINFO( m_flNearZ ) ), RecvPropFloat( RECVINFO( m_flFarZ ) ), RecvPropInt( RECVINFO( m_nShadowQuality ) ), END_RECV_TABLE() C_EnvProjectedTexture::C_EnvProjectedTexture( void ) { m_LightHandle = CLIENTSHADOW_INVALID_HANDLE; } C_EnvProjectedTexture::~C_EnvProjectedTexture( void ) { ShutDownLightHandle(); } void C_EnvProjectedTexture::ShutDownLightHandle( void ) { // Clear out the light if( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE ) { g_pClientShadowMgr->DestroyFlashlight( m_LightHandle ); m_LightHandle = CLIENTSHADOW_INVALID_HANDLE; } } //----------------------------------------------------------------------------- // Purpose: // Input : updateType - //----------------------------------------------------------------------------- void C_EnvProjectedTexture::OnDataChanged( DataUpdateType_t updateType ) { UpdateLight( true ); BaseClass::OnDataChanged( updateType ); } void C_EnvProjectedTexture::UpdateLight( bool bForceUpdate ) { if ( m_bState == false ) { if ( m_LightHandle != CLIENTSHADOW_INVALID_HANDLE ) { ShutDownLightHandle(); } return; } Vector vForward, vRight, vUp, vPos = GetAbsOrigin(); FlashlightState_t state; if ( m_hTargetEntity != NULL ) { if ( m_bCameraSpace ) { const QAngle &angles = GetLocalAngles(); C_BasePlayer *pPlayer = C_BasePlayer::GetLocalPlayer(); if( pPlayer ) { const QAngle playerAngles = pPlayer->GetAbsAngles(); Vector vPlayerForward, vPlayerRight, vPlayerUp; AngleVectors( playerAngles, &vPlayerForward, &vPlayerRight, &vPlayerUp ); matrix3x4_t mRotMatrix; AngleMatrix( angles, mRotMatrix ); VectorITransform( vPlayerForward, mRotMatrix, vForward ); VectorITransform( vPlayerRight, mRotMatrix, vRight ); VectorITransform( vPlayerUp, mRotMatrix, vUp ); float dist = (m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin()).Length(); vPos = m_hTargetEntity->GetAbsOrigin() - vForward*dist; VectorNormalize( vForward ); VectorNormalize( vRight ); VectorNormalize( vUp ); } } else { vForward = m_hTargetEntity->GetAbsOrigin() - GetAbsOrigin(); VectorNormalize( vForward ); // JasonM - unimplemented Assert (0); //Quaternion q = DirectionToOrientation( dir ); // // JasonM - set up vRight, vUp // // VectorNormalize( vRight ); // VectorNormalize( vUp ); } } else { AngleVectors( GetAbsAngles(), &vForward, &vRight, &vUp ); } state.m_fHorizontalFOVDegrees = m_flLightFOV; state.m_fVerticalFOVDegrees = m_flLightFOV; state.m_vecLightOrigin = vPos; BasisToQuaternion( vForward, vRight, vUp, state.m_quatOrientation ); state.m_fQuadraticAtten = 0.0; state.m_fLinearAtten = 100; state.m_fConstantAtten = 0.0f; state.m_Color[0] = m_LinearFloatLightColor.x; state.m_Color[1] = m_LinearFloatLightColor.y; state.m_Color[2] = m_LinearFloatLightColor.z; state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient; state.m_NearZ = m_flNearZ; state.m_FarZ = m_flFarZ; state.m_flShadowSlopeScaleDepthBias = mat_slopescaledepthbias_shadowmap.GetFloat(); state.m_flShadowDepthBias = mat_depthbias_shadowmap.GetFloat(); state.m_bEnableShadows = m_bEnableShadows; state.m_pSpotlightTexture = materials->FindTexture( m_SpotlightTextureName, TEXTURE_GROUP_OTHER, false ); state.m_nSpotlightTextureFrame = m_nSpotlightTextureFrame; state.m_nShadowQuality = m_nShadowQuality; // Allow entity to affect shadow quality if( m_LightHandle == CLIENTSHADOW_INVALID_HANDLE ) { m_LightHandle = g_pClientShadowMgr->CreateFlashlight( state ); } else { if ( m_hTargetEntity != NULL || bForceUpdate == true ) { g_pClientShadowMgr->UpdateFlashlightState( m_LightHandle, state ); } } if( m_bLightOnlyTarget ) { g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, m_hTargetEntity ); } else { g_pClientShadowMgr->SetFlashlightTarget( m_LightHandle, NULL ); } g_pClientShadowMgr->SetFlashlightLightWorld( m_LightHandle, m_bLightWorld ); if ( bForceUpdate == false ) { g_pClientShadowMgr->UpdateProjectedTexture( m_LightHandle, true ); } } void C_EnvProjectedTexture::Simulate( void ) { UpdateLight( false ); BaseClass::Simulate(); }