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.

241 lines
7.7 KiB

  1. //========= Copyright � 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Sunlight shadow control entity.
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "c_baseplayer.h"
  9. #ifdef INFESTED_DLL
  10. #include "c_asw_marine.h"
  11. #endif
  12. // memdbgon must be the last include file in a .cpp file!!!
  13. #include "tier0/memdbgon.h"
  14. ConVar cl_sunlight_ortho_size("cl_sunlight_ortho_size", "0.0", FCVAR_CHEAT, "Set to values greater than 0 for ortho view render projections.");
  15. ConVar cl_sunlight_depthbias( "cl_sunlight_depthbias", "0.02" );
  16. //------------------------------------------------------------------------------
  17. // Purpose : Sunlights shadow control entity
  18. //------------------------------------------------------------------------------
  19. class C_SunlightShadowControl : public C_BaseEntity
  20. {
  21. public:
  22. DECLARE_CLASS( C_SunlightShadowControl, C_BaseEntity );
  23. DECLARE_CLIENTCLASS();
  24. virtual ~C_SunlightShadowControl();
  25. void OnDataChanged( DataUpdateType_t updateType );
  26. void Spawn();
  27. bool ShouldDraw();
  28. void ClientThink();
  29. private:
  30. Vector m_shadowDirection;
  31. bool m_bEnabled;
  32. char m_TextureName[ MAX_PATH ];
  33. CTextureReference m_SpotlightTexture;
  34. color32 m_LightColor;
  35. Vector m_CurrentLinearFloatLightColor;
  36. float m_flCurrentLinearFloatLightAlpha;
  37. float m_flColorTransitionTime;
  38. float m_flSunDistance;
  39. float m_flFOV;
  40. float m_flNearZ;
  41. float m_flNorthOffset;
  42. bool m_bEnableShadows;
  43. bool m_bOldEnableShadows;
  44. static ClientShadowHandle_t m_LocalFlashlightHandle;
  45. };
  46. ClientShadowHandle_t C_SunlightShadowControl::m_LocalFlashlightHandle = CLIENTSHADOW_INVALID_HANDLE;
  47. IMPLEMENT_CLIENTCLASS_DT(C_SunlightShadowControl, DT_SunlightShadowControl, CSunlightShadowControl)
  48. RecvPropVector(RECVINFO(m_shadowDirection)),
  49. RecvPropBool(RECVINFO(m_bEnabled)),
  50. RecvPropString(RECVINFO(m_TextureName)),
  51. RecvPropInt(RECVINFO(m_LightColor), 0, RecvProxy_Int32ToColor32),
  52. RecvPropFloat(RECVINFO(m_flColorTransitionTime)),
  53. RecvPropFloat(RECVINFO(m_flSunDistance)),
  54. RecvPropFloat(RECVINFO(m_flFOV)),
  55. RecvPropFloat(RECVINFO(m_flNearZ)),
  56. RecvPropFloat(RECVINFO(m_flNorthOffset)),
  57. RecvPropBool(RECVINFO(m_bEnableShadows)),
  58. END_RECV_TABLE()
  59. C_SunlightShadowControl::~C_SunlightShadowControl()
  60. {
  61. if ( m_LocalFlashlightHandle != CLIENTSHADOW_INVALID_HANDLE )
  62. {
  63. g_pClientShadowMgr->DestroyFlashlight( m_LocalFlashlightHandle );
  64. m_LocalFlashlightHandle = CLIENTSHADOW_INVALID_HANDLE;
  65. }
  66. }
  67. void C_SunlightShadowControl::OnDataChanged( DataUpdateType_t updateType )
  68. {
  69. if ( updateType == DATA_UPDATE_CREATED )
  70. {
  71. m_SpotlightTexture.Init( m_TextureName, TEXTURE_GROUP_OTHER, true );
  72. }
  73. BaseClass::OnDataChanged( updateType );
  74. }
  75. void C_SunlightShadowControl::Spawn()
  76. {
  77. BaseClass::Spawn();
  78. m_bOldEnableShadows = m_bEnableShadows;
  79. SetNextClientThink( CLIENT_THINK_ALWAYS );
  80. }
  81. //------------------------------------------------------------------------------
  82. // We don't draw...
  83. //------------------------------------------------------------------------------
  84. bool C_SunlightShadowControl::ShouldDraw()
  85. {
  86. return false;
  87. }
  88. void C_SunlightShadowControl::ClientThink()
  89. {
  90. VPROF("C_SunlightShadowControl::ClientThink");
  91. if ( m_bEnabled )
  92. {
  93. Vector vLinearFloatLightColor( m_LightColor.r, m_LightColor.g, m_LightColor.b );
  94. float flLinearFloatLightAlpha = m_LightColor.a;
  95. if ( m_CurrentLinearFloatLightColor != vLinearFloatLightColor || m_flCurrentLinearFloatLightAlpha != flLinearFloatLightAlpha )
  96. {
  97. float flColorTransitionSpeed = gpGlobals->frametime * m_flColorTransitionTime * 255.0f;
  98. m_CurrentLinearFloatLightColor.x = Approach( vLinearFloatLightColor.x, m_CurrentLinearFloatLightColor.x, flColorTransitionSpeed );
  99. m_CurrentLinearFloatLightColor.y = Approach( vLinearFloatLightColor.y, m_CurrentLinearFloatLightColor.y, flColorTransitionSpeed );
  100. m_CurrentLinearFloatLightColor.z = Approach( vLinearFloatLightColor.z, m_CurrentLinearFloatLightColor.z, flColorTransitionSpeed );
  101. m_flCurrentLinearFloatLightAlpha = Approach( flLinearFloatLightAlpha, m_flCurrentLinearFloatLightAlpha, flColorTransitionSpeed );
  102. }
  103. FlashlightState_t state;
  104. Vector vDirection = m_shadowDirection;
  105. VectorNormalize( vDirection );
  106. QAngle angView;
  107. engine->GetViewAngles( angView );
  108. //Vector vViewUp = Vector( 0.0f, 1.0f, 0.0f );
  109. Vector vSunDirection2D = vDirection;
  110. vSunDirection2D.z = 0.0f;
  111. HACK_GETLOCALPLAYER_GUARD( "C_SunlightShadowControl::ClientThink" );
  112. #ifdef INFESTED_DLL // shine sun on your current marine, rather than the player entity
  113. C_ASW_Marine *pMarine = C_ASW_Marine::GetLocalMarine();
  114. if ( !pMarine )
  115. return;
  116. Vector vPos = ( pMarine->GetAbsOrigin() + vSunDirection2D * m_flNorthOffset ) - vDirection * m_flSunDistance;
  117. #else
  118. if ( !C_BasePlayer::GetLocalPlayer() )
  119. return;
  120. Vector vPos = ( C_BasePlayer::GetLocalPlayer()->GetAbsOrigin() + vSunDirection2D * m_flNorthOffset ) - vDirection * m_flSunDistance;
  121. #endif
  122. QAngle angAngles;
  123. VectorAngles( vDirection, angAngles );
  124. Vector vForward, vRight, vUp;
  125. AngleVectors( angAngles, &vForward, &vRight, &vUp );
  126. state.m_fHorizontalFOVDegrees = m_flFOV;
  127. state.m_fVerticalFOVDegrees = m_flFOV;
  128. state.m_vecLightOrigin = vPos;
  129. BasisToQuaternion( vForward, vRight, vUp, state.m_quatOrientation );
  130. state.m_fQuadraticAtten = 0.0f;
  131. state.m_fLinearAtten = m_flSunDistance / 2.0f;
  132. state.m_fConstantAtten = 0.0f;
  133. state.m_FarZAtten = m_flSunDistance + 300.0f;
  134. state.m_Color[0] = m_CurrentLinearFloatLightColor.x * ( 1.0f / 255.0f ) * m_flCurrentLinearFloatLightAlpha;
  135. state.m_Color[1] = m_CurrentLinearFloatLightColor.y * ( 1.0f / 255.0f ) * m_flCurrentLinearFloatLightAlpha;
  136. state.m_Color[2] = m_CurrentLinearFloatLightColor.z * ( 1.0f / 255.0f ) * m_flCurrentLinearFloatLightAlpha;
  137. state.m_Color[3] = 0.0f; // fixme: need to make ambient work m_flAmbient;
  138. state.m_NearZ = fpmax( 4.0f, m_flSunDistance - m_flNearZ );
  139. state.m_FarZ = m_flSunDistance + 300.0f;
  140. float flOrthoSize = cl_sunlight_ortho_size.GetFloat();
  141. if ( flOrthoSize > 0 )
  142. {
  143. state.m_bOrtho = true;
  144. state.m_fOrthoLeft = -flOrthoSize;
  145. state.m_fOrthoTop = -flOrthoSize;
  146. state.m_fOrthoRight = flOrthoSize;
  147. state.m_fOrthoBottom = flOrthoSize;
  148. }
  149. else
  150. {
  151. state.m_bOrtho = false;
  152. }
  153. state.m_flShadowSlopeScaleDepthBias = 2;
  154. state.m_flShadowDepthBias = cl_sunlight_depthbias.GetFloat();
  155. state.m_bEnableShadows = m_bEnableShadows;
  156. state.m_pSpotlightTexture = m_SpotlightTexture;
  157. state.m_pProjectedMaterial = NULL;
  158. state.m_nSpotlightTextureFrame = 0;
  159. extern ConVar r_flashlightdepthres;
  160. state.m_flShadowMapResolution = r_flashlightdepthres.GetFloat();
  161. state.m_nShadowQuality = 1; // Allow entity to affect shadow quality
  162. state.m_bShadowHighRes = true;
  163. if ( m_bOldEnableShadows != m_bEnableShadows )
  164. {
  165. // If they change the shadow enable/disable, we need to make a new handle
  166. if ( m_LocalFlashlightHandle != CLIENTSHADOW_INVALID_HANDLE )
  167. {
  168. g_pClientShadowMgr->DestroyFlashlight( m_LocalFlashlightHandle );
  169. m_LocalFlashlightHandle = CLIENTSHADOW_INVALID_HANDLE;
  170. }
  171. m_bOldEnableShadows = m_bEnableShadows;
  172. }
  173. if( m_LocalFlashlightHandle == CLIENTSHADOW_INVALID_HANDLE )
  174. {
  175. m_LocalFlashlightHandle = g_pClientShadowMgr->CreateFlashlight( state );
  176. }
  177. else
  178. {
  179. g_pClientShadowMgr->UpdateFlashlightState( m_LocalFlashlightHandle, state );
  180. #ifndef INFESTED_DLL
  181. #ifndef LINUX
  182. #pragma message("TODO: rebuild sunlight projected texture after sunlight control changes.")
  183. #endif
  184. g_pClientShadowMgr->UpdateProjectedTexture( m_LocalFlashlightHandle, true );
  185. #endif
  186. }
  187. }
  188. else if ( m_LocalFlashlightHandle != CLIENTSHADOW_INVALID_HANDLE )
  189. {
  190. g_pClientShadowMgr->DestroyFlashlight( m_LocalFlashlightHandle );
  191. m_LocalFlashlightHandle = CLIENTSHADOW_INVALID_HANDLE;
  192. }
  193. BaseClass::ClientThink();
  194. }