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

//========= Copyright © 1996-2005, Valve Corporation, All rights reserved. ============//
//
// Purpose: Responsible for drawing the scene
//
// $NoKeywords: $
//=============================================================================//
#include "cbase.h"
#include "view.h"
#include "iviewrender.h"
#include "view_shared.h"
#include "ivieweffects.h"
#include "iinput.h"
#include "model_types.h"
#include "clientsideeffects.h"
#include "particlemgr.h"
#include "viewrender.h"
#include "iclientmode.h"
#include "voice_status.h"
#include "radio_status.h"
#include "glow_overlay.h"
#include "materialsystem/imesh.h"
#include "materialsystem/itexture.h"
#include "materialsystem/imaterial.h"
#include "materialsystem/imaterialvar.h"
#include "materialsystem/imaterialsystemhardwareconfig.h"
#include "detailobjectsystem.h"
#include "tier0/vprof.h"
#include "engine/IEngineTrace.h"
#include "engine/ivmodelinfo.h"
#include "view_scene.h"
#include "particles_ez.h"
#include "engine/IStaticPropMgr.h"
#include "engine/ivdebugoverlay.h"
#include "cs_view_scene.h"
#include "c_cs_player.h"
#include "cs_gamerules.h"
#include "shake.h"
#include "precache_register.h"
#include "engine/IEngineSound.h"
#include <vgui/ISurface.h>
#include "hltvreplaysystem.h"
// NOTE: This has to be the last file included!
#include "tier0/memdbgon.h"
PRECACHE_REGISTER_BEGIN( GLOBAL, PrecacheCSViewScene )
PRECACHE( MATERIAL, "effects/overlaysmoke" )
PRECACHE( MATERIAL, "effects/flashbang" )
PRECACHE( MATERIAL, "effects/flashbang_white" )
PRECACHE( MATERIAL, "effects/nightvision" )
PRECACHE_REGISTER_END()
static CCSViewRender g_ViewRender;
IViewRender *GetViewRenderInstance()
{
return &g_ViewRender;
}
CCSViewRender::CCSViewRender()
{
m_pFlashTexture = NULL;
}
void CCSViewRender::Init( void )
{
CViewRender::Init();
}
void CCSViewRender::PerformNightVisionEffect( const CViewSetup &view )
{
C_CSPlayer *pPlayer = C_CSPlayer::GetLocalCSPlayer();
if ( !pPlayer )
return;
if (pPlayer->GetObserverMode() == OBS_MODE_IN_EYE)
{
CBaseEntity *target = pPlayer->GetObserverTarget();
if (target && target->IsPlayer())
{
pPlayer = (C_CSPlayer *)target;
}
}
if ( pPlayer && pPlayer->m_flNightVisionAlpha > 0 )
{
IMaterial *pMaterial = materials->FindMaterial( "effects/nightvision", TEXTURE_GROUP_CLIENT_EFFECTS, true );
if ( pMaterial )
{
int iMaxValue = 255;
byte overlaycolor[4] = { 0, 255, 0, 255 };
UpdateScreenEffectTexture( 0, view.x, view.y, view.width, view.height );
if ( pPlayer->m_bNightVisionOn )
{
pPlayer->m_flNightVisionAlpha += 15;
pPlayer->m_flNightVisionAlpha = MIN( pPlayer->m_flNightVisionAlpha, iMaxValue );
}
else
{
pPlayer->m_flNightVisionAlpha -= 40;
pPlayer->m_flNightVisionAlpha = MAX( pPlayer->m_flNightVisionAlpha, 0 );
}
overlaycolor[3] = pPlayer->m_flNightVisionAlpha;
render->ViewDrawFade( overlaycolor, pMaterial );
CMatRenderContextPtr pRenderContext( materials );
pRenderContext->DrawScreenSpaceQuad( pMaterial );
render->ViewDrawFade( overlaycolor, pMaterial );
pRenderContext->DrawScreenSpaceQuad( pMaterial );
}
}
}
//Adrian - Super Nifty Flashbang Effect(tm)
// this does the burn in for the flashbang effect.
void CCSViewRender::PerformFlashbangEffect( const CViewSetup &view )
{
C_CSPlayer *pLocalPlayer = C_CSPlayer::GetLocalCSPlayer();
if ( pLocalPlayer == NULL )
return;
C_CSPlayer *pFlashBangPlayer = pLocalPlayer;
//bool bReduceEffect = false;
float flAlphaScale = 1.0f;
if ( pLocalPlayer->GetObserverMode() != OBS_MODE_NONE )
{
// If spectating, use values from target
CBaseEntity *pTarget = pLocalPlayer->GetObserverTarget();
if ( pTarget )
{
C_CSPlayer *pPlayerTmp = ToCSPlayer(pTarget);
if ( pPlayerTmp )
{
pFlashBangPlayer = pPlayerTmp;
}
}
// reduce the effect
if ( pLocalPlayer->GetObserverMode() == OBS_MODE_IN_EYE && CanSeeSpectatorOnlyTools() )
{
// Reduce alpha.
// Note: the logic to reduce the duration of the effect is done when the effect is started (RecvProxy_FlashTime).
flAlphaScale = 0.6f;
}
else if ( pLocalPlayer->GetObserverMode() == OBS_MODE_FIXED || pLocalPlayer->GetObserverMode() == OBS_MODE_ROAMING )
{
// Reduce alpha.
// Note: the logic to reduce the duration of the effect is done when the effect is started (RecvProxy_FlashTime).
flAlphaScale = 0.2f;
}
else if ( pLocalPlayer->GetObserverMode() != OBS_MODE_IN_EYE )
{
// Reduce alpha.
// Note: the logic to reduce the duration of the effect is done when the effect is started (RecvProxy_FlashTime).
flAlphaScale = 0.6f;
}
}
if ( !pFlashBangPlayer->IsFlashBangActive() || CSGameRules()->IsIntermission() )
{
if ( !pLocalPlayer->m_bFlashDspHasBeenCleared )
{
CLocalPlayerFilter filter;
enginesound->SetPlayerDSP( filter, 0, true );
pLocalPlayer->m_bFlashDspHasBeenCleared = true;
}
return;
}
// bandaid to insure that flashbang dsp effect doesn't continue on indefinitely
if( pFlashBangPlayer->GetFlashTimeElapsed() > 1.6f && !pLocalPlayer->m_bFlashDspHasBeenCleared )
{
CLocalPlayerFilter filter;
enginesound->SetPlayerDSP( filter, 0, true );
pLocalPlayer->m_bFlashDspHasBeenCleared = true;
}
byte overlaycolor[4] = { 255, 255, 255, 255 };
// draw the screenshot overlay portion of the flashbang effect
IMaterial *pMaterial = materials->FindMaterial( "effects/flashbang", TEXTURE_GROUP_CLIENT_EFFECTS, true );
if ( pMaterial )
{
// This is for handling split screen where we could potentially enter this function more than once a frame.
// 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.
static float lastTimeGrabbed = 0.0f;
if ( gpGlobals->curtime == lastTimeGrabbed )
{
pLocalPlayer->m_bFlashScreenshotHasBeenGrabbed = true;
pFlashBangPlayer->m_bFlashScreenshotHasBeenGrabbed = true;
}
if ( !pFlashBangPlayer->m_bFlashScreenshotHasBeenGrabbed )
{
CMatRenderContextPtr pRenderContext( materials );
int nScreenWidth, nScreenHeight;
pRenderContext->GetRenderTargetDimensions( nScreenWidth, nScreenHeight );
// update m_pFlashTexture
lastTimeGrabbed = gpGlobals->curtime;
bool foundVar;
IMaterialVar* m_BaseTextureVar = pMaterial->FindVar( "$basetexture", &foundVar, false );
m_pFlashTexture = GetFullFrameFrameBufferTexture( 1 );
// When grabbing the texture for the super imposed frame, we grab the whole buffer, not just the viewport.
// We were having issues with trying to grab only the right side of the buffer for the second player in split screen.
Rect_t srcRect;
srcRect.x = 0;
srcRect.y = 0;
srcRect.width = nScreenWidth;
srcRect.height = nScreenHeight;
m_BaseTextureVar->SetTextureValue( m_pFlashTexture );
pRenderContext->CopyRenderTargetToTextureEx( m_pFlashTexture, 0, &srcRect, NULL );
pRenderContext->SetFrameBufferCopyTexture( m_pFlashTexture );
pFlashBangPlayer->m_bFlashScreenshotHasBeenGrabbed = true;
pLocalPlayer->m_bFlashScreenshotHasBeenGrabbed = true;
}
if ( !CanSeeSpectatorOnlyTools() )
{
overlaycolor[0] = overlaycolor[1] = overlaycolor[2] = pFlashBangPlayer->m_flFlashScreenshotAlpha * flAlphaScale;
if ( m_pFlashTexture != NULL )
{
static int NUM_AFTER_IMAGE_PASSES = 4;
for ( int pass = 0; pass < NUM_AFTER_IMAGE_PASSES; ++pass )
{
render->ViewDrawFade( overlaycolor, pMaterial, false );
}
}
}
}
// draw pure white overlay part of the flashbang effect.
pMaterial = materials->FindMaterial( "effects/flashbang_white", TEXTURE_GROUP_CLIENT_EFFECTS, true );
if ( pMaterial )
{
overlaycolor[0] = overlaycolor[1] = overlaycolor[2] = pFlashBangPlayer->m_flFlashOverlayAlpha * flAlphaScale;
render->ViewDrawFade( overlaycolor, pMaterial );
}
}
#ifdef _DEBUG
//These are the outer ranges of the smoke overlay volume, at which there is 0% overlay.
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." );
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." );
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." );
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." );
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." );
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." );
#define cl_smoke_origin_height cl_smoke_origin_height_cv.GetFloat()
#define cl_smoke_torus_ring_radius cl_smoke_torus_ring_radius_cv.GetFloat()
#define cl_smoke_torus_ring_subradius cl_smoke_torus_ring_subradius_cv.GetFloat()
#define cl_smoke_edge_feather cl_smoke_edge_feather_cv.GetFloat()
#define cl_smoke_lower_speed cl_smoke_lower_speed_cv.GetFloat()
#else
#define cl_smoke_origin_height 68.0f
#define cl_smoke_torus_ring_radius 61.0f
#define cl_smoke_torus_ring_subradius 88.0f
#define cl_smoke_edge_feather 21.0f
#define cl_smoke_lower_speed 4.5f
#endif
//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.
#define cl_smoke_must_be_at_least_this_close_to_have_any_effect (cl_smoke_torus_ring_radius + cl_smoke_torus_ring_subradius)
void DrawCappedTorus( Vector vecOrigin, float flRadiusA, float flRadiusB, Color colWireColor, float flDuration )
{
// 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
Vector vecPointA, vecPointB, vecPointC;
vecPointA.Init();
vecPointB.Init();
vecPointC.Init();
int i = 0;
int j = 0;
bool bTri = true;
for ( int n=0; n<1643; n++ )
{
bTri ? i++ : j++;
bTri = !bTri;
float phi = i * 6.28318f / 41.0f;
float theta = j * 6.28318f / 20.0f;
Vector vecTorusNode;
vecTorusNode.Init( cos(phi) * ( flRadiusA + cos(theta) * flRadiusB ),
sin(phi) * ( flRadiusA + cos(theta) * flRadiusB ),
sin(theta) * flRadiusB );
vecTorusNode += vecOrigin;
vecPointC = vecPointB;
vecPointB = vecPointA;
vecPointA = vecTorusNode;
if ( cos(theta) < 0 )
{
vecPointA.x = vecOrigin.x;
vecPointA.y = vecOrigin.y;
vecPointA.z = ( vecPointA.z > vecOrigin.z ) ? ( vecOrigin.z + flRadiusB ) : ( vecOrigin.z - flRadiusB );
if ( vecPointA.x == vecPointB.x && vecPointA.y == vecPointB.y )
continue;
}
if ( n > 1 )
debugoverlay->AddLineOverlay( vecPointB, vecPointA, colWireColor.r(), colWireColor.g(), colWireColor.b(), false, flDuration );
//triangulate
//if ( n > 2 )
//{
// if ( !bTri )
// {
// debugoverlay->AddTriangleOverlay( vecPointA, vecPointB, vecPointC, 255, 255, 255, 10, false, flDuration );
// }
// else
// {
// debugoverlay->AddTriangleOverlay( vecPointC, vecPointB, vecPointA, 255, 255, 255, 10, false, flDuration );
// }
//}
}
}
//-----------------------------------------------------------------------------
// Purpose: Renders pre-viewmodel smoke screen
//-----------------------------------------------------------------------------
#include "c_cs_player.h" // for clientSmokeGrenadeRecord_t
extern CUtlVector<EHANDLE> g_SmokeGrenadeHandles;
void CCSViewRender::RenderSmokeOverlay( bool bPreViewModel )
{
if ( bPreViewModel )
{
// update the overlay
//Assume we have no smoke overlay
float flOptimalSmokeOverlayAlpha = 0;
if ( g_SmokeGrenadeHandles.Count() > 0 )
{
Vector vecPlayerEyePos = MainViewOrigin(GET_ACTIVE_SPLITSCREEN_SLOT());
Vector vecClosestVecToSmoke;
int iClosestSmokeIndex = -1;
float flTempSmokeDistance = cl_smoke_must_be_at_least_this_close_to_have_any_effect;
#ifdef _DEBUG
if ( cl_show_smoke_overlay_thresholds.GetBool() )
flTempSmokeDistance = 2000.0f;
#endif
// we need to find the closest smoke to prevent a latter grenade in the list lifting the opacity of a potentially closer one
for( int it=0; it < g_SmokeGrenadeHandles.Count(); it++ )
{
CBaseCSGrenadeProjectile *pGrenade = static_cast< CBaseCSGrenadeProjectile* >( g_SmokeGrenadeHandles[it].Get() );
if ( !pGrenade )
continue;
Vector toGrenade = ( pGrenade->GetAbsOrigin() + Vector( 0, 0, cl_smoke_origin_height) ) - vecPlayerEyePos;
if ( toGrenade.Length() < flTempSmokeDistance )
{
//save the new closest smoke
flTempSmokeDistance = toGrenade.Length();
iClosestSmokeIndex = it;
//remember its vector
vecClosestVecToSmoke = toGrenade;
}
}
//only continue if we actually found a close-enough smoke
if ( iClosestSmokeIndex != -1 )
{
Vector vecSmokePos = Vector( 0, 0, 0 );
CBaseCSGrenadeProjectile *pGrenade = static_cast< CBaseCSGrenadeProjectile* >( g_SmokeGrenadeHandles[iClosestSmokeIndex].Get() );
if ( pGrenade )
vecSmokePos = pGrenade->GetAbsOrigin();
//draw debug visualization
#ifdef _DEBUG
if ( cl_show_smoke_overlay_thresholds.GetBool() )
{
Vector vecSmokeVisualOrigin = vecSmokePos + Vector( 0, 0, cl_smoke_origin_height );
//draw inner threshold
DrawCappedTorus( vecSmokeVisualOrigin, cl_smoke_torus_ring_radius, cl_smoke_torus_ring_subradius - cl_smoke_edge_feather, Color( 200, 0, 0 ), gpGlobals->frametime );
//draw outer threshold
DrawCappedTorus( vecSmokeVisualOrigin, cl_smoke_torus_ring_radius, cl_smoke_torus_ring_subradius, Color( 100, 0, 0 ), gpGlobals->frametime );
}
#endif
//linear interpolation between two capped torusoids
//are we within the Z axis bounds?
if ( abs( vecClosestVecToSmoke.z ) < cl_smoke_torus_ring_subradius )
{
float flvecClosestVecToSmokeLength2D = vecClosestVecToSmoke.Length2D();
//are we within the cylindrical cap-space on the XY axis?
if ( flvecClosestVecToSmokeLength2D < cl_smoke_torus_ring_radius )
{
//if so we can just use z delta
flOptimalSmokeOverlayAlpha = ( cl_smoke_torus_ring_subradius - abs( vecClosestVecToSmoke.z ) ) / cl_smoke_edge_feather;
#ifdef _DEBUG
if ( cl_show_smoke_overlay_thresholds.GetBool() )
{
//draw the closest point on the inner torusoid threshold
Vector vecSmokeVisualOrigin = vecSmokePos + Vector( 0, 0, cl_smoke_origin_height );
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 );
debugoverlay->AddBoxOverlay( vecClosestPoint + vecSmokeVisualOrigin, Vector( -1, -1, -1 ), Vector( 1, 1, 1 ), QAngle( 0, 0, 0 ), 0, 200, 0, 255, gpGlobals->frametime );
//line to eyes
//debugoverlay->AddLineOverlay( vecPlayerEyePos, vecClosestPoint + vecSmokeVisualOrigin, 0,200,0, false, gpGlobals->frametime );
}
#endif
}
else if ( flvecClosestVecToSmokeLength2D < cl_smoke_torus_ring_radius + cl_smoke_torus_ring_subradius )
{
//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
Vector vecRingPosOnSmokePlane = Vector( vecClosestVecToSmoke.x, vecClosestVecToSmoke.y, 0 ).Normalized() * cl_smoke_torus_ring_radius;
#ifdef _DEBUG
if ( cl_show_smoke_overlay_thresholds.GetBool() )
{
//draw the closest point on the inner torusoid threshold
Vector vecRingPosToInnerSurface = ( vecClosestVecToSmoke - vecRingPosOnSmokePlane ).Normalized() * ( cl_smoke_torus_ring_subradius - cl_smoke_edge_feather );
Vector vecSmokeVisualOrigin = vecSmokePos + Vector( 0, 0, cl_smoke_origin_height );
debugoverlay->AddBoxOverlay( vecSmokeVisualOrigin - vecRingPosOnSmokePlane - vecRingPosToInnerSurface, Vector( -1, -1, -1 ), Vector( 1, 1, 1 ), QAngle( 0, 0, 0 ), 0, 200, 0, 255, gpGlobals->frametime );
//line to eyes
//debugoverlay->AddLineOverlay( vecPlayerEyePos, vecSmokeVisualOrigin - vecRingPosOnSmokePlane - vecRingPosToInnerSurface, 0,200,0, false, gpGlobals->frametime );
}
#endif
//and check the distance value
float flDistanceToClosestRingPoint = ( vecClosestVecToSmoke - vecRingPosOnSmokePlane ).Length();
if ( flDistanceToClosestRingPoint < cl_smoke_torus_ring_subradius )
{
flOptimalSmokeOverlayAlpha = ( cl_smoke_torus_ring_subradius - flDistanceToClosestRingPoint ) / cl_smoke_edge_feather;
}
}
//clamp to 0-1 range
flOptimalSmokeOverlayAlpha = clamp( flOptimalSmokeOverlayAlpha, 0.0f, 1.0f );
}
#ifdef _DEBUG
if ( cl_show_smoke_overlay_thresholds.GetBool() )
{
debugoverlay->AddTextOverlay(vecPlayerEyePos, gpGlobals->frametime, "Overlay: %f", flOptimalSmokeOverlayAlpha );
}
#endif
}
}
//alpha can instantly increase, but decreases to the ideal at a constant rate.
if ( flOptimalSmokeOverlayAlpha < m_flSmokeOverlayAmount )
{
flOptimalSmokeOverlayAlpha = Approach( flOptimalSmokeOverlayAlpha, m_flSmokeOverlayAmount, gpGlobals->frametime * cl_smoke_lower_speed );
}
m_flSmokeOverlayAmount = flOptimalSmokeOverlayAlpha;
}
if ( m_flSmokeOverlayAmount <= 0 )
{
return;
}
else
{
IMaterial *pMaterial = materials->FindMaterial( "effects/overlaysmoke", TEXTURE_GROUP_CLIENT_EFFECTS, true );
if ( pMaterial )
{
byte overlaycolor[4] = { 90, 90, 90, (byte)( m_flSmokeOverlayAmount * ( bPreViewModel ? 255 : 128 ) ) };
render->ViewDrawFade( overlaycolor, pMaterial );
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Renders extra 2D effects in derived classes while the 2D view is on the stack
//-----------------------------------------------------------------------------
void CCSViewRender::Render2DEffectsPreHUD( const CViewSetup &view )
{
PerformNightVisionEffect( view ); // this needs to come before the HUD is drawn, or it will wash the HUD out
}
//-----------------------------------------------------------------------------
// Purpose: Renders extra 2D effects in derived classes while the 2D view is on the stack
//-----------------------------------------------------------------------------
void CCSViewRender::Render2DEffectsPostHUD( const CViewSetup &view )
{
PerformFlashbangEffect( view );
float flFade = g_HltvReplaySystem.GetReplayVideoFadeAmount();
// replay camera post-process
if ( g_HltvReplaySystem.WantsReplayEffect() )
{
// demo playback uses full-screen quad to fade in/out. Hltv replay uses the pixel shader here.
CMatRenderContextPtr pRenderContext( materials );
int x, y, w, h;
pRenderContext->GetViewport( x, y, w, h );
if ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() < 95 ) // bail if ps30 is unsupported
return;
UpdateScreenEffectTexture( 0, view.x, view.y, view.width, view.height, false );
// overlay
IMaterial *pMatReplay = materials->FindMaterial( "dev/replay", TEXTURE_GROUP_OTHER, true );
if ( pMatReplay )
{
IMaterialVar* pVar = pMatReplay->FindVar( "$c0_x", NULL );
pVar->SetFloatValue( 1.0f / w );
pVar = pMatReplay->FindVar( "$c0_y", NULL );
pVar->SetFloatValue( 1.0f / h );
pVar = pMatReplay->FindVar( "$c0_z", NULL );
pVar->SetFloatValue( gpGlobals->realtime );
pVar = pMatReplay->FindVar( "$c0_w", NULL );
pVar->SetFloatValue( flFade );
//if( flFade > 0 && g_HltvReplaySystem.GetHltvReplayDelay() ) Msg( "%.2f dev/replay fade %.2f\n", Plat_FloatTime(), flFade ); // replayfade
pRenderContext->DrawScreenSpaceRectangle( pMatReplay, x, y, w, h, 0, 0, w-1, h-1, w, h );
}
}
else if ( flFade > 0 )
{
//Msg( "%.2f simple fade %.2f\n", Plat_FloatTime(), flFade ); // replayfade
float flFadeAdj = flFade;// sinf( flFade * ( M_PI * .5f ) );
CMatRenderContextPtr pRenderContext( materials );
int x, y, w, h;
pRenderContext->GetViewport( x, y, w, h );
//bars
if ( IMaterial *pMatFade = materials->FindMaterial( "dev/replay_bars", TEXTURE_GROUP_OTHER, true ) )
{
if ( IMaterialVar* pVar = pMatFade->FindVar( "$alpha", NULL ) )
{
pVar->SetFloatValue( flFadeAdj );
pRenderContext->DrawScreenSpaceRectangle( pMatFade, 0, 0, w, h, 0, 0, 0, 0, 1, 1 );
}
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Renders voice feedback and other sprites attached to players
// Input : none
//-----------------------------------------------------------------------------
void CCSViewRender::RenderPlayerSprites()
{
CViewRender::RenderPlayerSprites();
RadioManager()->DrawHeadLabels();
}