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.

589 lines
21 KiB

  1. //========= Copyright � 1996-2005, 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 "precache_register.h"
  39. #include "engine/IEngineSound.h"
  40. #include <vgui/ISurface.h>
  41. #include "hltvreplaysystem.h"
  42. // NOTE: This has to be the last file included!
  43. #include "tier0/memdbgon.h"
  44. PRECACHE_REGISTER_BEGIN( GLOBAL, PrecacheCSViewScene )
  45. PRECACHE( MATERIAL, "effects/overlaysmoke" )
  46. PRECACHE( MATERIAL, "effects/flashbang" )
  47. PRECACHE( MATERIAL, "effects/flashbang_white" )
  48. PRECACHE( MATERIAL, "effects/nightvision" )
  49. PRECACHE_REGISTER_END()
  50. static CCSViewRender g_ViewRender;
  51. IViewRender *GetViewRenderInstance()
  52. {
  53. return &g_ViewRender;
  54. }
  55. CCSViewRender::CCSViewRender()
  56. {
  57. m_pFlashTexture = NULL;
  58. }
  59. void CCSViewRender::Init( void )
  60. {
  61. CViewRender::Init();
  62. }
  63. void CCSViewRender::PerformNightVisionEffect( const CViewSetup &view )
  64. {
  65. C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
  66. if ( !pPlayer )
  67. return;
  68. if (pPlayer->GetObserverMode() == OBS_MODE_IN_EYE)
  69. {
  70. CBaseEntity *target = pPlayer->GetObserverTarget();
  71. if (target && target->IsPlayer())
  72. {
  73. pPlayer = (C_CSPlayer *)target;
  74. }
  75. }
  76. if ( pPlayer && pPlayer->m_flNightVisionAlpha > 0 )
  77. {
  78. IMaterial *pMaterial = materials->FindMaterial( "effects/nightvision", TEXTURE_GROUP_CLIENT_EFFECTS, true );
  79. if ( pMaterial )
  80. {
  81. int iMaxValue = 255;
  82. byte overlaycolor[4] = { 0, 255, 0, 255 };
  83. UpdateScreenEffectTexture( 0, view.x, view.y, view.width, view.height );
  84. if ( pPlayer->m_bNightVisionOn )
  85. {
  86. pPlayer->m_flNightVisionAlpha += 15;
  87. pPlayer->m_flNightVisionAlpha = MIN( pPlayer->m_flNightVisionAlpha, iMaxValue );
  88. }
  89. else
  90. {
  91. pPlayer->m_flNightVisionAlpha -= 40;
  92. pPlayer->m_flNightVisionAlpha = MAX( pPlayer->m_flNightVisionAlpha, 0 );
  93. }
  94. overlaycolor[3] = pPlayer->m_flNightVisionAlpha;
  95. render->ViewDrawFade( overlaycolor, pMaterial );
  96. CMatRenderContextPtr pRenderContext( materials );
  97. pRenderContext->DrawScreenSpaceQuad( pMaterial );
  98. render->ViewDrawFade( overlaycolor, pMaterial );
  99. pRenderContext->DrawScreenSpaceQuad( pMaterial );
  100. }
  101. }
  102. }
  103. //Adrian - Super Nifty Flashbang Effect(tm)
  104. // this does the burn in for the flashbang effect.
  105. void CCSViewRender::PerformFlashbangEffect( const CViewSetup &view )
  106. {
  107. C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
  108. if ( pLocalPlayer == NULL )
  109. return;
  110. C_CSPlayer *pFlashBangPlayer = pLocalPlayer;
  111. //bool bReduceEffect = false;
  112. float flAlphaScale = 1.0f;
  113. if ( pLocalPlayer->GetObserverMode() != OBS_MODE_NONE )
  114. {
  115. // If spectating, use values from target
  116. CBaseEntity *pTarget = pLocalPlayer->GetObserverTarget();
  117. if ( pTarget )
  118. {
  119. C_CSPlayer *pPlayerTmp = ToCSPlayer(pTarget);
  120. if ( pPlayerTmp )
  121. {
  122. pFlashBangPlayer = pPlayerTmp;
  123. }
  124. }
  125. // reduce the effect
  126. if ( pLocalPlayer->GetObserverMode() == OBS_MODE_IN_EYE && CanSeeSpectatorOnlyTools() )
  127. {
  128. // Reduce alpha.
  129. // Note: the logic to reduce the duration of the effect is done when the effect is started (RecvProxy_FlashTime).
  130. flAlphaScale = 0.6f;
  131. }
  132. else if ( pLocalPlayer->GetObserverMode() == OBS_MODE_FIXED || pLocalPlayer->GetObserverMode() == OBS_MODE_ROAMING )
  133. {
  134. // Reduce alpha.
  135. // Note: the logic to reduce the duration of the effect is done when the effect is started (RecvProxy_FlashTime).
  136. flAlphaScale = 0.2f;
  137. }
  138. else if ( pLocalPlayer->GetObserverMode() != OBS_MODE_IN_EYE )
  139. {
  140. // Reduce alpha.
  141. // Note: the logic to reduce the duration of the effect is done when the effect is started (RecvProxy_FlashTime).
  142. flAlphaScale = 0.6f;
  143. }
  144. }
  145. if ( !pFlashBangPlayer->IsFlashBangActive() || CSGameRules()->IsIntermission() )
  146. {
  147. if ( !pLocalPlayer->m_bFlashDspHasBeenCleared )
  148. {
  149. CLocalPlayerFilter filter;
  150. enginesound->SetPlayerDSP( filter, 0, true );
  151. pLocalPlayer->m_bFlashDspHasBeenCleared = true;
  152. }
  153. return;
  154. }
  155. // bandaid to insure that flashbang dsp effect doesn't continue on indefinitely
  156. if( pFlashBangPlayer->GetFlashTimeElapsed() > 1.6f && !pLocalPlayer->m_bFlashDspHasBeenCleared )
  157. {
  158. CLocalPlayerFilter filter;
  159. enginesound->SetPlayerDSP( filter, 0, true );
  160. pLocalPlayer->m_bFlashDspHasBeenCleared = true;
  161. }
  162. byte overlaycolor[4] = { 255, 255, 255, 255 };
  163. // draw the screenshot overlay portion of the flashbang effect
  164. IMaterial *pMaterial = materials->FindMaterial( "effects/flashbang", TEXTURE_GROUP_CLIENT_EFFECTS, true );
  165. if ( pMaterial )
  166. {
  167. // This is for handling split screen where we could potentially enter this function more than once a frame.
  168. // Since this bit of code grabs both the left and right viewports of the buffer, it only needs to be done once per frame per flash.
  169. static float lastTimeGrabbed = 0.0f;
  170. if ( gpGlobals->curtime == lastTimeGrabbed )
  171. {
  172. pLocalPlayer->m_bFlashScreenshotHasBeenGrabbed = true;
  173. pFlashBangPlayer->m_bFlashScreenshotHasBeenGrabbed = true;
  174. }
  175. if ( !pFlashBangPlayer->m_bFlashScreenshotHasBeenGrabbed )
  176. {
  177. CMatRenderContextPtr pRenderContext( materials );
  178. int nScreenWidth, nScreenHeight;
  179. pRenderContext->GetRenderTargetDimensions( nScreenWidth, nScreenHeight );
  180. // update m_pFlashTexture
  181. lastTimeGrabbed = gpGlobals->curtime;
  182. bool foundVar;
  183. IMaterialVar* m_BaseTextureVar = pMaterial->FindVar( "$basetexture", &foundVar, false );
  184. m_pFlashTexture = GetFullFrameFrameBufferTexture( 1 );
  185. // When grabbing the texture for the super imposed frame, we grab the whole buffer, not just the viewport.
  186. // We were having issues with trying to grab only the right side of the buffer for the second player in split screen.
  187. Rect_t srcRect;
  188. srcRect.x = 0;
  189. srcRect.y = 0;
  190. srcRect.width = nScreenWidth;
  191. srcRect.height = nScreenHeight;
  192. m_BaseTextureVar->SetTextureValue( m_pFlashTexture );
  193. pRenderContext->CopyRenderTargetToTextureEx( m_pFlashTexture, 0, &srcRect, NULL );
  194. pRenderContext->SetFrameBufferCopyTexture( m_pFlashTexture );
  195. pFlashBangPlayer->m_bFlashScreenshotHasBeenGrabbed = true;
  196. pLocalPlayer->m_bFlashScreenshotHasBeenGrabbed = true;
  197. }
  198. if ( !CanSeeSpectatorOnlyTools() )
  199. {
  200. overlaycolor[0] = overlaycolor[1] = overlaycolor[2] = pFlashBangPlayer->m_flFlashScreenshotAlpha * flAlphaScale;
  201. if ( m_pFlashTexture != NULL )
  202. {
  203. static int NUM_AFTER_IMAGE_PASSES = 4;
  204. for ( int pass = 0; pass < NUM_AFTER_IMAGE_PASSES; ++pass )
  205. {
  206. render->ViewDrawFade( overlaycolor, pMaterial, false );
  207. }
  208. }
  209. }
  210. }
  211. // draw pure white overlay part of the flashbang effect.
  212. pMaterial = materials->FindMaterial( "effects/flashbang_white", TEXTURE_GROUP_CLIENT_EFFECTS, true );
  213. if ( pMaterial )
  214. {
  215. overlaycolor[0] = overlaycolor[1] = overlaycolor[2] = pFlashBangPlayer->m_flFlashOverlayAlpha * flAlphaScale;
  216. render->ViewDrawFade( overlaycolor, pMaterial );
  217. }
  218. }
  219. #ifdef _DEBUG
  220. //These are the outer ranges of the smoke overlay volume, at which there is 0% overlay.
  221. ConVar cl_smoke_origin_height_cv( "cl_smoke_origin_height", "68", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_HIDDEN, "The center of the visible smoke torus is this many units above the origin of the grenade that's on the ground." );
  222. ConVar cl_smoke_torus_ring_radius_cv( "cl_smoke_torus_ring_radius", "61", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_HIDDEN, "The radius of the overall ring of the entire visible smoke volume, measured from the exact local center of the visible cloud." );
  223. ConVar cl_smoke_torus_ring_subradius_cv( "cl_smoke_torus_ring_subradius", "88", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_HIDDEN, "The radius of the extruded circle that follows the main ring and forms the torus shape." );
  224. ConVar cl_smoke_edge_feather_cv( "cl_smoke_edge_feather", "21", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_HIDDEN, "This many units towards the inner threshold and you will hit 100% overlay opacity." );
  225. ConVar cl_smoke_lower_speed_cv( "cl_smoke_lower_speed", "4.5", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_HIDDEN, "How fast the smoke screen overlay clears." );
  226. ConVar cl_show_smoke_overlay_thresholds( "cl_show_smoke_overlay_thresholds", "0", FCVAR_REPLICATED | FCVAR_CHEAT | FCVAR_HIDDEN, "Show visualization of smoke overlay inner and outer thresholds." );
  227. #define cl_smoke_origin_height cl_smoke_origin_height_cv.GetFloat()
  228. #define cl_smoke_torus_ring_radius cl_smoke_torus_ring_radius_cv.GetFloat()
  229. #define cl_smoke_torus_ring_subradius cl_smoke_torus_ring_subradius_cv.GetFloat()
  230. #define cl_smoke_edge_feather cl_smoke_edge_feather_cv.GetFloat()
  231. #define cl_smoke_lower_speed cl_smoke_lower_speed_cv.GetFloat()
  232. #else
  233. #define cl_smoke_origin_height 68.0f
  234. #define cl_smoke_torus_ring_radius 61.0f
  235. #define cl_smoke_torus_ring_subradius 88.0f
  236. #define cl_smoke_edge_feather 21.0f
  237. #define cl_smoke_lower_speed 4.5f
  238. #endif
  239. //If your eyes are less than this distance from the center of the visible smoke torus, we should check exact distance and may need to apply the screen overlay.
  240. #define cl_smoke_must_be_at_least_this_close_to_have_any_effect (cl_smoke_torus_ring_radius + cl_smoke_torus_ring_subradius)
  241. void DrawCappedTorus( Vector vecOrigin, float flRadiusA, float flRadiusB, Color colWireColor, float flDuration )
  242. {
  243. // Draw a debug wireframe 'capped' torus. It's a torus with the middle filled in, like a cheese-boule shape that's meant to match a smoke volume
  244. Vector vecPointA, vecPointB, vecPointC;
  245. vecPointA.Init();
  246. vecPointB.Init();
  247. vecPointC.Init();
  248. int i = 0;
  249. int j = 0;
  250. bool bTri = true;
  251. for ( int n=0; n<1643; n++ )
  252. {
  253. bTri ? i++ : j++;
  254. bTri = !bTri;
  255. float phi = i * 6.28318f / 41.0f;
  256. float theta = j * 6.28318f / 20.0f;
  257. Vector vecTorusNode;
  258. vecTorusNode.Init( cos(phi) * ( flRadiusA + cos(theta) * flRadiusB ),
  259. sin(phi) * ( flRadiusA + cos(theta) * flRadiusB ),
  260. sin(theta) * flRadiusB );
  261. vecTorusNode += vecOrigin;
  262. vecPointC = vecPointB;
  263. vecPointB = vecPointA;
  264. vecPointA = vecTorusNode;
  265. if ( cos(theta) < 0 )
  266. {
  267. vecPointA.x = vecOrigin.x;
  268. vecPointA.y = vecOrigin.y;
  269. vecPointA.z = ( vecPointA.z > vecOrigin.z ) ? ( vecOrigin.z + flRadiusB ) : ( vecOrigin.z - flRadiusB );
  270. if ( vecPointA.x == vecPointB.x && vecPointA.y == vecPointB.y )
  271. continue;
  272. }
  273. if ( n > 1 )
  274. debugoverlay->AddLineOverlay( vecPointB, vecPointA, colWireColor.r(), colWireColor.g(), colWireColor.b(), false, flDuration );
  275. //triangulate
  276. //if ( n > 2 )
  277. //{
  278. // if ( !bTri )
  279. // {
  280. // debugoverlay->AddTriangleOverlay( vecPointA, vecPointB, vecPointC, 255, 255, 255, 10, false, flDuration );
  281. // }
  282. // else
  283. // {
  284. // debugoverlay->AddTriangleOverlay( vecPointC, vecPointB, vecPointA, 255, 255, 255, 10, false, flDuration );
  285. // }
  286. //}
  287. }
  288. }
  289. //-----------------------------------------------------------------------------
  290. // Purpose: Renders pre-viewmodel smoke screen
  291. //-----------------------------------------------------------------------------
  292. #include "c_cs_player.h" // for clientSmokeGrenadeRecord_t
  293. extern CUtlVector<EHANDLE> g_SmokeGrenadeHandles;
  294. void CCSViewRender::RenderSmokeOverlay( bool bPreViewModel )
  295. {
  296. if ( bPreViewModel )
  297. {
  298. // update the overlay
  299. //Assume we have no smoke overlay
  300. float flOptimalSmokeOverlayAlpha = 0;
  301. if ( g_SmokeGrenadeHandles.Count() > 0 )
  302. {
  303. Vector vecPlayerEyePos = MainViewOrigin(GET_ACTIVE_SPLITSCREEN_SLOT());
  304. Vector vecClosestVecToSmoke;
  305. int iClosestSmokeIndex = -1;
  306. float flTempSmokeDistance = cl_smoke_must_be_at_least_this_close_to_have_any_effect;
  307. #ifdef _DEBUG
  308. if ( cl_show_smoke_overlay_thresholds.GetBool() )
  309. flTempSmokeDistance = 2000.0f;
  310. #endif
  311. // we need to find the closest smoke to prevent a latter grenade in the list lifting the opacity of a potentially closer one
  312. for( int it=0; it < g_SmokeGrenadeHandles.Count(); it++ )
  313. {
  314. CBaseCSGrenadeProjectile *pGrenade = static_cast< CBaseCSGrenadeProjectile* >( g_SmokeGrenadeHandles[it].Get() );
  315. if ( !pGrenade )
  316. continue;
  317. Vector toGrenade = ( pGrenade->GetAbsOrigin() + Vector( 0, 0, cl_smoke_origin_height) ) - vecPlayerEyePos;
  318. if ( toGrenade.Length() < flTempSmokeDistance )
  319. {
  320. //save the new closest smoke
  321. flTempSmokeDistance = toGrenade.Length();
  322. iClosestSmokeIndex = it;
  323. //remember its vector
  324. vecClosestVecToSmoke = toGrenade;
  325. }
  326. }
  327. //only continue if we actually found a close-enough smoke
  328. if ( iClosestSmokeIndex != -1 )
  329. {
  330. Vector vecSmokePos = Vector( 0, 0, 0 );
  331. CBaseCSGrenadeProjectile *pGrenade = static_cast< CBaseCSGrenadeProjectile* >( g_SmokeGrenadeHandles[iClosestSmokeIndex].Get() );
  332. if ( pGrenade )
  333. vecSmokePos = pGrenade->GetAbsOrigin();
  334. //draw debug visualization
  335. #ifdef _DEBUG
  336. if ( cl_show_smoke_overlay_thresholds.GetBool() )
  337. {
  338. Vector vecSmokeVisualOrigin = vecSmokePos + Vector( 0, 0, cl_smoke_origin_height );
  339. //draw inner threshold
  340. DrawCappedTorus( vecSmokeVisualOrigin, cl_smoke_torus_ring_radius, cl_smoke_torus_ring_subradius - cl_smoke_edge_feather, Color( 200, 0, 0 ), gpGlobals->frametime );
  341. //draw outer threshold
  342. DrawCappedTorus( vecSmokeVisualOrigin, cl_smoke_torus_ring_radius, cl_smoke_torus_ring_subradius, Color( 100, 0, 0 ), gpGlobals->frametime );
  343. }
  344. #endif
  345. //linear interpolation between two capped torusoids
  346. //are we within the Z axis bounds?
  347. if ( abs( vecClosestVecToSmoke.z ) < cl_smoke_torus_ring_subradius )
  348. {
  349. float flvecClosestVecToSmokeLength2D = vecClosestVecToSmoke.Length2D();
  350. //are we within the cylindrical cap-space on the XY axis?
  351. if ( flvecClosestVecToSmokeLength2D < cl_smoke_torus_ring_radius )
  352. {
  353. //if so we can just use z delta
  354. flOptimalSmokeOverlayAlpha = ( cl_smoke_torus_ring_subradius - abs( vecClosestVecToSmoke.z ) ) / cl_smoke_edge_feather;
  355. #ifdef _DEBUG
  356. if ( cl_show_smoke_overlay_thresholds.GetBool() )
  357. {
  358. //draw the closest point on the inner torusoid threshold
  359. Vector vecSmokeVisualOrigin = vecSmokePos + Vector( 0, 0, cl_smoke_origin_height );
  360. Vector vecClosestPoint = Vector( -vecClosestVecToSmoke.x, -vecClosestVecToSmoke.y, vecClosestVecToSmoke.z < 0 ? cl_smoke_torus_ring_subradius - cl_smoke_edge_feather : -cl_smoke_torus_ring_subradius + cl_smoke_edge_feather );
  361. debugoverlay->AddBoxOverlay( vecClosestPoint + vecSmokeVisualOrigin, Vector( -1, -1, -1 ), Vector( 1, 1, 1 ), QAngle( 0, 0, 0 ), 0, 200, 0, 255, gpGlobals->frametime );
  362. //line to eyes
  363. //debugoverlay->AddLineOverlay( vecPlayerEyePos, vecClosestPoint + vecSmokeVisualOrigin, 0,200,0, false, gpGlobals->frametime );
  364. }
  365. #endif
  366. }
  367. else if ( flvecClosestVecToSmokeLength2D < cl_smoke_torus_ring_radius + cl_smoke_torus_ring_subradius )
  368. {
  369. //are we within the outer possible horizontal range of the torusoid? if so we need the distance to the nearest point on the primary radius
  370. Vector vecRingPosOnSmokePlane = Vector( vecClosestVecToSmoke.x, vecClosestVecToSmoke.y, 0 ).Normalized() * cl_smoke_torus_ring_radius;
  371. #ifdef _DEBUG
  372. if ( cl_show_smoke_overlay_thresholds.GetBool() )
  373. {
  374. //draw the closest point on the inner torusoid threshold
  375. Vector vecRingPosToInnerSurface = ( vecClosestVecToSmoke - vecRingPosOnSmokePlane ).Normalized() * ( cl_smoke_torus_ring_subradius - cl_smoke_edge_feather );
  376. Vector vecSmokeVisualOrigin = vecSmokePos + Vector( 0, 0, cl_smoke_origin_height );
  377. debugoverlay->AddBoxOverlay( vecSmokeVisualOrigin - vecRingPosOnSmokePlane - vecRingPosToInnerSurface, Vector( -1, -1, -1 ), Vector( 1, 1, 1 ), QAngle( 0, 0, 0 ), 0, 200, 0, 255, gpGlobals->frametime );
  378. //line to eyes
  379. //debugoverlay->AddLineOverlay( vecPlayerEyePos, vecSmokeVisualOrigin - vecRingPosOnSmokePlane - vecRingPosToInnerSurface, 0,200,0, false, gpGlobals->frametime );
  380. }
  381. #endif
  382. //and check the distance value
  383. float flDistanceToClosestRingPoint = ( vecClosestVecToSmoke - vecRingPosOnSmokePlane ).Length();
  384. if ( flDistanceToClosestRingPoint < cl_smoke_torus_ring_subradius )
  385. {
  386. flOptimalSmokeOverlayAlpha = ( cl_smoke_torus_ring_subradius - flDistanceToClosestRingPoint ) / cl_smoke_edge_feather;
  387. }
  388. }
  389. //clamp to 0-1 range
  390. flOptimalSmokeOverlayAlpha = clamp( flOptimalSmokeOverlayAlpha, 0.0f, 1.0f );
  391. }
  392. #ifdef _DEBUG
  393. if ( cl_show_smoke_overlay_thresholds.GetBool() )
  394. {
  395. debugoverlay->AddTextOverlay(vecPlayerEyePos, gpGlobals->frametime, "Overlay: %f", flOptimalSmokeOverlayAlpha );
  396. }
  397. #endif
  398. }
  399. }
  400. //alpha can instantly increase, but decreases to the ideal at a constant rate.
  401. if ( flOptimalSmokeOverlayAlpha < m_flSmokeOverlayAmount )
  402. {
  403. flOptimalSmokeOverlayAlpha = Approach( flOptimalSmokeOverlayAlpha, m_flSmokeOverlayAmount, gpGlobals->frametime * cl_smoke_lower_speed );
  404. }
  405. m_flSmokeOverlayAmount = flOptimalSmokeOverlayAlpha;
  406. }
  407. if ( m_flSmokeOverlayAmount <= 0 )
  408. {
  409. return;
  410. }
  411. else
  412. {
  413. IMaterial *pMaterial = materials->FindMaterial( "effects/overlaysmoke", TEXTURE_GROUP_CLIENT_EFFECTS, true );
  414. if ( pMaterial )
  415. {
  416. byte overlaycolor[4] = { 90, 90, 90, (byte)( m_flSmokeOverlayAmount * ( bPreViewModel ? 255 : 128 ) ) };
  417. render->ViewDrawFade( overlaycolor, pMaterial );
  418. }
  419. }
  420. }
  421. //-----------------------------------------------------------------------------
  422. // Purpose: Renders extra 2D effects in derived classes while the 2D view is on the stack
  423. //-----------------------------------------------------------------------------
  424. void CCSViewRender::Render2DEffectsPreHUD( const CViewSetup &view )
  425. {
  426. PerformNightVisionEffect( view ); // this needs to come before the HUD is drawn, or it will wash the HUD out
  427. }
  428. //-----------------------------------------------------------------------------
  429. // Purpose: Renders extra 2D effects in derived classes while the 2D view is on the stack
  430. //-----------------------------------------------------------------------------
  431. void CCSViewRender::Render2DEffectsPostHUD( const CViewSetup &view )
  432. {
  433. PerformFlashbangEffect( view );
  434. float flFade = g_HltvReplaySystem.GetReplayVideoFadeAmount();
  435. // replay camera post-process
  436. if ( g_HltvReplaySystem.WantsReplayEffect() )
  437. {
  438. // demo playback uses full-screen quad to fade in/out. Hltv replay uses the pixel shader here.
  439. CMatRenderContextPtr pRenderContext( materials );
  440. int x, y, w, h;
  441. pRenderContext->GetViewport( x, y, w, h );
  442. if ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() < 95 ) // bail if ps30 is unsupported
  443. return;
  444. UpdateScreenEffectTexture( 0, view.x, view.y, view.width, view.height, false );
  445. // overlay
  446. IMaterial *pMatReplay = materials->FindMaterial( "dev/replay", TEXTURE_GROUP_OTHER, true );
  447. if ( pMatReplay )
  448. {
  449. IMaterialVar* pVar = pMatReplay->FindVar( "$c0_x", NULL );
  450. pVar->SetFloatValue( 1.0f / w );
  451. pVar = pMatReplay->FindVar( "$c0_y", NULL );
  452. pVar->SetFloatValue( 1.0f / h );
  453. pVar = pMatReplay->FindVar( "$c0_z", NULL );
  454. pVar->SetFloatValue( gpGlobals->realtime );
  455. pVar = pMatReplay->FindVar( "$c0_w", NULL );
  456. pVar->SetFloatValue( flFade );
  457. //if( flFade > 0 && g_HltvReplaySystem.GetHltvReplayDelay() ) Msg( "%.2f dev/replay fade %.2f\n", Plat_FloatTime(), flFade ); // replayfade
  458. pRenderContext->DrawScreenSpaceRectangle( pMatReplay, x, y, w, h, 0, 0, w-1, h-1, w, h );
  459. }
  460. }
  461. else if ( flFade > 0 )
  462. {
  463. //Msg( "%.2f simple fade %.2f\n", Plat_FloatTime(), flFade ); // replayfade
  464. float flFadeAdj = flFade;// sinf( flFade * ( M_PI * .5f ) );
  465. CMatRenderContextPtr pRenderContext( materials );
  466. int x, y, w, h;
  467. pRenderContext->GetViewport( x, y, w, h );
  468. //bars
  469. if ( IMaterial *pMatFade = materials->FindMaterial( "dev/replay_bars", TEXTURE_GROUP_OTHER, true ) )
  470. {
  471. if ( IMaterialVar* pVar = pMatFade->FindVar( "$alpha", NULL ) )
  472. {
  473. pVar->SetFloatValue( flFadeAdj );
  474. pRenderContext->DrawScreenSpaceRectangle( pMatFade, 0, 0, w, h, 0, 0, 0, 0, 1, 1 );
  475. }
  476. }
  477. }
  478. }
  479. //-----------------------------------------------------------------------------
  480. // Purpose: Renders voice feedback and other sprites attached to players
  481. // Input : none
  482. //-----------------------------------------------------------------------------
  483. void CCSViewRender::RenderPlayerSprites()
  484. {
  485. CViewRender::RenderPlayerSprites();
  486. RadioManager()->DrawHeadLabels();
  487. }