Team Fortress 2 Source Code as on 22/4/2020
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.

325 lines
9.8 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Responsible for drawing the scene
  4. //
  5. // $NoKeywords: $
  6. //=============================================================================//
  7. #include "cbase.h"
  8. #include "view.h"
  9. #include "iviewrender.h"
  10. #include "view_shared.h"
  11. #include "ivieweffects.h"
  12. #include "iinput.h"
  13. #include "model_types.h"
  14. #include "clientsideeffects.h"
  15. #include "particlemgr.h"
  16. #include "viewrender.h"
  17. #include "iclientmode.h"
  18. #include "voice_status.h"
  19. #include "radio_status.h"
  20. #include "glow_overlay.h"
  21. #include "materialsystem/imesh.h"
  22. #include "materialsystem/itexture.h"
  23. #include "materialsystem/imaterial.h"
  24. #include "materialsystem/imaterialvar.h"
  25. #include "materialsystem/imaterialsystemhardwareconfig.h"
  26. #include "detailobjectsystem.h"
  27. #include "tier0/vprof.h"
  28. #include "engine/IEngineTrace.h"
  29. #include "engine/ivmodelinfo.h"
  30. #include "view_scene.h"
  31. #include "particles_ez.h"
  32. #include "engine/IStaticPropMgr.h"
  33. #include "engine/ivdebugoverlay.h"
  34. #include "cs_view_scene.h"
  35. #include "c_cs_player.h"
  36. #include "cs_gamerules.h"
  37. #include "shake.h"
  38. #include "clienteffectprecachesystem.h"
  39. #include <vgui/ISurface.h>
  40. CLIENTEFFECT_REGISTER_BEGIN( PrecacheCSViewScene )
  41. CLIENTEFFECT_MATERIAL( "effects/flashbang" )
  42. CLIENTEFFECT_MATERIAL( "effects/flashbang_white" )
  43. CLIENTEFFECT_MATERIAL( "effects/nightvision" )
  44. CLIENTEFFECT_REGISTER_END()
  45. static CCSViewRender g_ViewRender;
  46. CCSViewRender::CCSViewRender()
  47. {
  48. view = ( IViewRender * )&g_ViewRender;
  49. m_pFlashTexture = NULL;
  50. }
  51. struct ConVarFlags
  52. {
  53. const char *name;
  54. int flags;
  55. };
  56. ConVarFlags s_flaggedConVars[] =
  57. {
  58. { "r_screenfademinsize", FCVAR_CHEAT },
  59. { "r_screenfademaxsize", FCVAR_CHEAT },
  60. { "developer", FCVAR_CHEAT },
  61. };
  62. void CCSViewRender::Init( void )
  63. {
  64. for ( int i=0; i<ARRAYSIZE( s_flaggedConVars ); ++i )
  65. {
  66. ConVar *flaggedConVar = cvar->FindVar( s_flaggedConVars[i].name );
  67. if ( flaggedConVar )
  68. {
  69. flaggedConVar->AddFlags( s_flaggedConVars[i].flags );
  70. }
  71. }
  72. CViewRender::Init();
  73. }
  74. //-----------------------------------------------------------------------------
  75. // Purpose: Returns the min/max fade distances
  76. //-----------------------------------------------------------------------------
  77. void CCSViewRender::GetScreenFadeDistances( float *min, float *max )
  78. {
  79. if ( min )
  80. {
  81. *min = 0.0f;
  82. }
  83. if ( max )
  84. {
  85. *max = 0.0f;
  86. }
  87. }
  88. void CCSViewRender::PerformNightVisionEffect( const CViewSetup &view )
  89. {
  90. C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
  91. if ( !pPlayer )
  92. return;
  93. if (pPlayer->GetObserverMode() == OBS_MODE_IN_EYE)
  94. {
  95. CBaseEntity *target = pPlayer->GetObserverTarget();
  96. if (target && target->IsPlayer())
  97. {
  98. pPlayer = (C_CSPlayer *)target;
  99. }
  100. }
  101. if ( pPlayer && pPlayer->m_flNightVisionAlpha > 0 )
  102. {
  103. IMaterial *pMaterial = materials->FindMaterial( "effects/nightvision", TEXTURE_GROUP_CLIENT_EFFECTS, true );
  104. if ( pMaterial )
  105. {
  106. int iMaxValue = 255;
  107. byte overlaycolor[4] = { 0, 255, 0, 255 };
  108. if ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() >= 80 )
  109. {
  110. UpdateScreenEffectTexture( 0, view.x, view.y, view.width, view.height );
  111. }
  112. else
  113. {
  114. // In DX7, use the values CS:goldsrc uses.
  115. iMaxValue = 225;
  116. overlaycolor[0] = overlaycolor[2] = 50 / 2;
  117. overlaycolor[1] = 225 / 2;
  118. }
  119. if ( pPlayer->m_bNightVisionOn )
  120. {
  121. pPlayer->m_flNightVisionAlpha += 15;
  122. pPlayer->m_flNightVisionAlpha = MIN( pPlayer->m_flNightVisionAlpha, iMaxValue );
  123. }
  124. else
  125. {
  126. pPlayer->m_flNightVisionAlpha -= 40;
  127. pPlayer->m_flNightVisionAlpha = MAX( pPlayer->m_flNightVisionAlpha, 0 );
  128. }
  129. overlaycolor[3] = pPlayer->m_flNightVisionAlpha;
  130. render->ViewDrawFade( overlaycolor, pMaterial );
  131. // Only one pass in DX7.
  132. if ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() >= 80 )
  133. {
  134. CMatRenderContextPtr pRenderContext( materials );
  135. pRenderContext->DrawScreenSpaceQuad( pMaterial );
  136. render->ViewDrawFade( overlaycolor, pMaterial );
  137. pRenderContext->DrawScreenSpaceQuad( pMaterial );
  138. }
  139. }
  140. }
  141. }
  142. //Adrian - Super Nifty Flashbang Effect(tm)
  143. // this does the burn in for the flashbang effect.
  144. void CCSViewRender::PerformFlashbangEffect( const CViewSetup &view )
  145. {
  146. C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
  147. if ( pPlayer == NULL )
  148. return;
  149. if ( pPlayer->m_flFlashBangTime < gpGlobals->curtime )
  150. return;
  151. IMaterial *pMaterial = materials->FindMaterial( "effects/flashbang", TEXTURE_GROUP_CLIENT_EFFECTS, true );
  152. if ( !pMaterial )
  153. return;
  154. byte overlaycolor[4] = { 255, 255, 255, 255 };
  155. CMatRenderContextPtr pRenderContext( materials );
  156. if ( pPlayer->m_flFlashAlpha < pPlayer->m_flFlashMaxAlpha )
  157. {
  158. pPlayer->m_flFlashAlpha += 45;
  159. pPlayer->m_flFlashAlpha = MIN( pPlayer->m_flFlashAlpha, pPlayer->m_flFlashMaxAlpha );
  160. overlaycolor[0] = overlaycolor[1] = overlaycolor[2] = pPlayer->m_flFlashAlpha;
  161. m_pFlashTexture = GetFullFrameFrameBufferTexture( 1 );
  162. bool foundVar;
  163. IMaterialVar* m_BaseTextureVar = pMaterial->FindVar( "$basetexture", &foundVar, false );
  164. Rect_t srcRect;
  165. srcRect.x = view.x;
  166. srcRect.y = view.y;
  167. srcRect.width = view.width;
  168. srcRect.height = view.height;
  169. m_BaseTextureVar->SetTextureValue( m_pFlashTexture );
  170. pRenderContext->CopyRenderTargetToTextureEx( m_pFlashTexture, 0, &srcRect, NULL );
  171. pRenderContext->SetFrameBufferCopyTexture( m_pFlashTexture );
  172. render->ViewDrawFade( overlaycolor, pMaterial );
  173. // just do one pass for dxlevel < 80.
  174. if (g_pMaterialSystemHardwareConfig->GetDXSupportLevel() >= 80)
  175. {
  176. pRenderContext->DrawScreenSpaceRectangle( pMaterial, view.x, view.y, view.width, view.height,
  177. 0, 0, m_pFlashTexture->GetActualWidth()-1, m_pFlashTexture->GetActualHeight()-1,
  178. m_pFlashTexture->GetActualWidth(), m_pFlashTexture->GetActualHeight() );
  179. render->ViewDrawFade( overlaycolor, pMaterial );
  180. pRenderContext->DrawScreenSpaceRectangle( pMaterial, view.x, view.y, view.width, view.height,
  181. 0, 0, m_pFlashTexture->GetActualWidth()-1, m_pFlashTexture->GetActualHeight()-1,
  182. m_pFlashTexture->GetActualWidth(), m_pFlashTexture->GetActualHeight() );
  183. }
  184. }
  185. else if ( m_pFlashTexture )
  186. {
  187. float flAlpha = pPlayer->m_flFlashMaxAlpha * (pPlayer->m_flFlashBangTime - gpGlobals->curtime) / pPlayer->m_flFlashDuration;
  188. flAlpha = clamp( flAlpha, 0, pPlayer->m_flFlashMaxAlpha );
  189. overlaycolor[0] = overlaycolor[1] = overlaycolor[2] = flAlpha;
  190. render->ViewDrawFade( overlaycolor, pMaterial );
  191. // just do one pass for dxlevel < 80.
  192. if (g_pMaterialSystemHardwareConfig->GetDXSupportLevel() >= 80)
  193. {
  194. pRenderContext->DrawScreenSpaceRectangle( pMaterial, view.x, view.y, view.width, view.height,
  195. 0, 0, m_pFlashTexture->GetActualWidth()-1, m_pFlashTexture->GetActualHeight()-1,
  196. m_pFlashTexture->GetActualWidth(), m_pFlashTexture->GetActualHeight() );
  197. render->ViewDrawFade( overlaycolor, pMaterial );
  198. pRenderContext->DrawScreenSpaceRectangle( pMaterial, view.x, view.y, view.width, view.height,
  199. 0, 0, m_pFlashTexture->GetActualWidth()-1, m_pFlashTexture->GetActualHeight()-1,
  200. m_pFlashTexture->GetActualWidth(), m_pFlashTexture->GetActualHeight() );
  201. }
  202. }
  203. // this does the pure white overlay part of the flashbang effect.
  204. pMaterial = materials->FindMaterial( "effects/flashbang_white", TEXTURE_GROUP_CLIENT_EFFECTS, true );
  205. if ( !pMaterial )
  206. return;
  207. float flAlpha = 255;
  208. if ( pPlayer->m_flFlashAlpha < pPlayer->m_flFlashMaxAlpha )
  209. {
  210. flAlpha = pPlayer->m_flFlashAlpha;
  211. }
  212. else
  213. {
  214. float flFlashTimeLeft = pPlayer->m_flFlashBangTime - gpGlobals->curtime;
  215. float flAlphaPercentage = 1.0;
  216. const float certainBlindnessTimeThresh = 3.0; // yes this is a magic number, necessary to match CS/CZ flashbang effectiveness cause the rendering system is completely different.
  217. if (flFlashTimeLeft > certainBlindnessTimeThresh)
  218. {
  219. // if we still have enough time of blindness left, make sure the player can't see anything yet.
  220. flAlphaPercentage = 1.0;
  221. }
  222. else
  223. {
  224. // blindness effects shorter than 'certainBlindnessTimeThresh' will start off at less than 255 alpha.
  225. flAlphaPercentage = flFlashTimeLeft / certainBlindnessTimeThresh;
  226. if (g_pMaterialSystemHardwareConfig->GetDXSupportLevel() >= 80)
  227. {
  228. // reduce alpha level quicker with dx 8 support and higher to compensate
  229. // for having the burn-in effect.
  230. flAlphaPercentage *= flAlphaPercentage;
  231. }
  232. }
  233. flAlpha = flAlphaPercentage *= pPlayer->m_flFlashMaxAlpha; // scale a [0..1) value to a [0..MaxAlpha] value for the alpha.
  234. // make sure the alpha is in the range of [0..MaxAlpha]
  235. flAlpha = MAX ( flAlpha, 0 );
  236. flAlpha = MIN ( flAlpha, pPlayer->m_flFlashMaxAlpha);
  237. }
  238. overlaycolor[0] = overlaycolor[1] = overlaycolor[2] = flAlpha;
  239. render->ViewDrawFade( overlaycolor, pMaterial );
  240. }
  241. //-----------------------------------------------------------------------------
  242. // Purpose: Renders extra 2D effects in derived classes while the 2D view is on the stack
  243. //-----------------------------------------------------------------------------
  244. void CCSViewRender::Render2DEffectsPreHUD( const CViewSetup &view )
  245. {
  246. PerformNightVisionEffect( view ); // this needs to come before the HUD is drawn, or it will wash the HUD out
  247. }
  248. //-----------------------------------------------------------------------------
  249. // Purpose: Renders extra 2D effects in derived classes while the 2D view is on the stack
  250. //-----------------------------------------------------------------------------
  251. void CCSViewRender::Render2DEffectsPostHUD( const CViewSetup &view )
  252. {
  253. PerformFlashbangEffect( view );
  254. }
  255. //-----------------------------------------------------------------------------
  256. // Purpose: Renders voice feedback and other sprites attached to players
  257. // Input : none
  258. //-----------------------------------------------------------------------------
  259. void CCSViewRender::RenderPlayerSprites()
  260. {
  261. GetClientVoiceMgr()->SetHeadLabelOffset( 40 );
  262. CViewRender::RenderPlayerSprites();
  263. RadioManager()->DrawHeadLabels();
  264. }