//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: Responsible for drawing the scene
//
//===========================================================================//
# 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 "glow_overlay.h"
# include "materialsystem/imesh.h"
# include "materialsystem/itexture.h"
# include "materialsystem/imaterial.h"
# include "materialsystem/imaterialvar.h"
# include "materialsystem/imaterialsystem.h"
# include "detailobjectsystem.h"
# include "tier0/vprof.h"
# include "tier1/mempool.h"
# include "vstdlib/jobthread.h"
# include "datacache/imdlcache.h"
# include "engine/IEngineTrace.h"
# include "engine/ivmodelinfo.h"
# include "tier0/icommandline.h"
# include "view_scene.h"
# include "particles_ez.h"
# include "engine/IStaticPropMgr.h"
# include "engine/ivdebugoverlay.h"
# include "c_pixel_visibility.h"
# include "clienteffectprecachesystem.h"
# include "c_rope.h"
# include "c_effects.h"
# include "smoke_fog_overlay.h"
# include "materialsystem/imaterialsystemhardwareconfig.h"
# include "VGuiMatSurface/IMatSystemSurface.h"
# include "vgui_int.h"
# include "ienginevgui.h"
# include "ScreenSpaceEffects.h"
# include "toolframework_client.h"
# include "c_func_reflective_glass.h"
# include "KeyValues.h"
# include "renderparm.h"
# include "studio_stats.h"
# include "con_nprint.h"
# include "clientmode_shared.h"
# include "sourcevr/isourcevirtualreality.h"
# include "client_virtualreality.h"
# ifdef PORTAL
//#include "C_Portal_Player.h"
# include "portal_render_targets.h"
# include "PortalRender.h"
# endif
# if defined( HL2_CLIENT_DLL ) || defined( CSTRIKE_DLL )
# define USE_MONITORS
# endif
# include "rendertexture.h"
# include "viewpostprocess.h"
# include "viewdebug.h"
# if defined USES_ECON_ITEMS
# include "econ_wearable.h"
# endif
# ifdef USE_MONITORS
# include "c_point_camera.h"
# endif // USE_MONITORS
// Projective textures
# include "C_Env_Projected_Texture.h"
// memdbgon must be the last include file in a .cpp file!!!
# include "tier0/memdbgon.h"
static void testfreezeframe_f ( void )
{
view - > FreezeFrame ( 3.0 ) ;
}
static ConCommand test_freezeframe ( " test_freezeframe " , testfreezeframe_f , " Test the freeze frame code. " , FCVAR_CHEAT ) ;
//-----------------------------------------------------------------------------
static ConVar r_visocclusion ( " r_visocclusion " , " 0 " , FCVAR_CHEAT ) ;
extern ConVar r_flashlightdepthtexture ;
extern ConVar vcollide_wireframe ;
extern ConVar mat_motion_blur_enabled ;
extern ConVar r_depthoverlay ;
extern ConVar mat_viewportscale ;
extern ConVar mat_viewportupscale ;
extern bool g_bDumpRenderTargets ;
//-----------------------------------------------------------------------------
// Convars related to controlling rendering
//-----------------------------------------------------------------------------
static ConVar cl_maxrenderable_dist ( " cl_maxrenderable_dist " , " 3000 " , FCVAR_CHEAT , " Max distance from the camera at which things will be rendered " ) ;
ConVar r_entityclips ( " r_entityclips " , " 1 " ) ; //FIXME: Nvidia drivers before 81.94 on cards that support user clip planes will have problems with this, require driver update? Detect and disable?
// Matches the version in the engine
static ConVar r_drawopaqueworld ( " r_drawopaqueworld " , " 1 " , FCVAR_CHEAT ) ;
static ConVar r_drawtranslucentworld ( " r_drawtranslucentworld " , " 1 " , FCVAR_CHEAT ) ;
static ConVar r_3dsky ( " r_3dsky " , " 1 " , 0 , " Enable the rendering of 3d sky boxes " ) ;
static ConVar r_skybox ( " r_skybox " , " 1 " , FCVAR_CHEAT , " Enable the rendering of sky boxes " ) ;
# ifdef TF_CLIENT_DLL
ConVar r_drawviewmodel ( " r_drawviewmodel " , " 1 " , FCVAR_ARCHIVE ) ;
# else
ConVar r_drawviewmodel ( " r_drawviewmodel " , " 1 " , FCVAR_CHEAT ) ;
# endif
static ConVar r_drawtranslucentrenderables ( " r_drawtranslucentrenderables " , " 1 " , FCVAR_CHEAT ) ;
static ConVar r_drawopaquerenderables ( " r_drawopaquerenderables " , " 1 " , FCVAR_CHEAT ) ;
static ConVar r_threaded_renderables ( " r_threaded_renderables " , " 0 " ) ;
// FIXME: This is not static because we needed to turn it off for TF2 playtests
ConVar r_DrawDetailProps ( " r_DrawDetailProps " , " 1 " , FCVAR_NONE , " 0=Off, 1=Normal, 2=Wireframe " ) ;
ConVar r_worldlistcache ( " r_worldlistcache " , " 1 " ) ;
//-----------------------------------------------------------------------------
// Convars related to fog color
//-----------------------------------------------------------------------------
static ConVar fog_override ( " fog_override " , " 0 " , FCVAR_CHEAT ) ;
// set any of these to use the maps fog
static ConVar fog_start ( " fog_start " , " -1 " , FCVAR_CHEAT ) ;
static ConVar fog_end ( " fog_end " , " -1 " , FCVAR_CHEAT ) ;
static ConVar fog_color ( " fog_color " , " -1 -1 -1 " , FCVAR_CHEAT ) ;
static ConVar fog_enable ( " fog_enable " , " 1 " , FCVAR_CHEAT ) ;
static ConVar fog_startskybox ( " fog_startskybox " , " -1 " , FCVAR_CHEAT ) ;
static ConVar fog_endskybox ( " fog_endskybox " , " -1 " , FCVAR_CHEAT ) ;
static ConVar fog_maxdensityskybox ( " fog_maxdensityskybox " , " -1 " , FCVAR_CHEAT ) ;
static ConVar fog_colorskybox ( " fog_colorskybox " , " -1 -1 -1 " , FCVAR_CHEAT ) ;
static ConVar fog_enableskybox ( " fog_enableskybox " , " 1 " , FCVAR_CHEAT ) ;
static ConVar fog_maxdensity ( " fog_maxdensity " , " -1 " , FCVAR_CHEAT ) ;
//-----------------------------------------------------------------------------
// Water-related convars
//-----------------------------------------------------------------------------
static ConVar r_debugcheapwater ( " r_debugcheapwater " , " 0 " , FCVAR_CHEAT ) ;
# ifndef _X360
static ConVar r_waterforceexpensive ( " r_waterforceexpensive " , " 0 " , FCVAR_ARCHIVE ) ;
# endif
static ConVar r_waterforcereflectentities ( " r_waterforcereflectentities " , " 0 " ) ;
static ConVar r_WaterDrawRefraction ( " r_WaterDrawRefraction " , " 1 " , 0 , " Enable water refraction " ) ;
static ConVar r_WaterDrawReflection ( " r_WaterDrawReflection " , " 1 " , 0 , " Enable water reflection " ) ;
static ConVar r_ForceWaterLeaf ( " r_ForceWaterLeaf " , " 1 " , 0 , " Enable for optimization to water - considers view in leaf under water for purposes of culling " ) ;
static ConVar mat_drawwater ( " mat_drawwater " , " 1 " , FCVAR_CHEAT ) ;
static ConVar mat_clipz ( " mat_clipz " , " 1 " ) ;
//-----------------------------------------------------------------------------
// Other convars
//-----------------------------------------------------------------------------
static ConVar r_screenfademinsize ( " r_screenfademinsize " , " 0 " ) ;
static ConVar r_screenfademaxsize ( " r_screenfademaxsize " , " 0 " ) ;
static ConVar cl_drawmonitors ( " cl_drawmonitors " , " 1 " ) ;
static ConVar r_eyewaterepsilon ( " r_eyewaterepsilon " , " 10.0f " , FCVAR_CHEAT ) ;
# ifdef TF_CLIENT_DLL
static ConVar pyro_dof ( " pyro_dof " , " 1 " , FCVAR_ARCHIVE ) ;
# endif
extern ConVar cl_leveloverview ;
extern ConVar localplayer_visionflags ;
//-----------------------------------------------------------------------------
// Globals
//-----------------------------------------------------------------------------
static Vector g_vecCurrentRenderOrigin ( 0 , 0 , 0 ) ;
static QAngle g_vecCurrentRenderAngles ( 0 , 0 , 0 ) ;
static Vector g_vecCurrentVForward ( 0 , 0 , 0 ) , g_vecCurrentVRight ( 0 , 0 , 0 ) , g_vecCurrentVUp ( 0 , 0 , 0 ) ;
static VMatrix g_matCurrentCamInverse ;
bool s_bCanAccessCurrentView = false ;
IntroData_t * g_pIntroData = NULL ;
static bool g_bRenderingView = false ; // For debugging...
static int g_CurrentViewID = VIEW_NONE ;
bool g_bRenderingScreenshot = false ;
# define FREEZECAM_SNAPSHOT_FADE_SPEED 340
float g_flFreezeFlash = 0.0f ;
//-----------------------------------------------------------------------------
CON_COMMAND ( r_cheapwaterstart , " " )
{
if ( args . ArgC ( ) = = 2 )
{
float dist = atof ( args [ 1 ] ) ;
view - > SetCheapWaterStartDistance ( dist ) ;
}
else
{
float start , end ;
view - > GetWaterLODParams ( start , end ) ;
Warning ( " r_cheapwaterstart: %f \n " , start ) ;
}
}
CON_COMMAND ( r_cheapwaterend , " " )
{
if ( args . ArgC ( ) = = 2 )
{
float dist = atof ( args [ 1 ] ) ;
view - > SetCheapWaterEndDistance ( dist ) ;
}
else
{
float start , end ;
view - > GetWaterLODParams ( start , end ) ;
Warning ( " r_cheapwaterend: %f \n " , end ) ;
}
}
//-----------------------------------------------------------------------------
// Describes a pruned set of leaves to be rendered this view. Reference counted
// because potentially shared by a number of views
//-----------------------------------------------------------------------------
struct ClientWorldListInfo_t : public CRefCounted1 < WorldListInfo_t >
{
ClientWorldListInfo_t ( )
{
memset ( ( WorldListInfo_t * ) this , 0 , sizeof ( WorldListInfo_t ) ) ;
m_pActualLeafIndex = NULL ;
m_bPooledAlloc = false ;
}
// Allocate a list intended for pruning
static ClientWorldListInfo_t * AllocPooled ( const ClientWorldListInfo_t & exemplar ) ;
// Because we remap leaves to eliminate unused leaves, we need a remap
// when drawing translucent surfaces, which requires the *original* leaf index
// using m_pActualLeafMap[ remapped leaf index ] == actual leaf index
LeafIndex_t * m_pActualLeafIndex ;
private :
virtual bool OnFinalRelease ( ) ;
bool m_bPooledAlloc ;
static CObjectPool < ClientWorldListInfo_t > gm_Pool ;
} ;
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CWorldListCache
{
public :
CWorldListCache ( )
{
}
void Flush ( )
{
for ( int i = m_Entries . FirstInorder ( ) ; i ! = m_Entries . InvalidIndex ( ) ; i = m_Entries . NextInorder ( i ) )
{
delete m_Entries [ i ] ;
}
m_Entries . RemoveAll ( ) ;
}
bool Find ( const CViewSetup & viewSetup , IWorldRenderList * * ppList , ClientWorldListInfo_t * * ppListInfo )
{
Entry_t lookup ( viewSetup ) ;
int i = m_Entries . Find ( & lookup ) ;
if ( i ! = m_Entries . InvalidIndex ( ) )
{
Entry_t * pEntry = m_Entries [ i ] ;
* ppList = InlineAddRef ( pEntry - > pList ) ;
* ppListInfo = InlineAddRef ( pEntry - > pListInfo ) ;
return true ;
}
return false ;
}
void Add ( const CViewSetup & viewSetup , IWorldRenderList * pList , ClientWorldListInfo_t * pListInfo )
{
m_Entries . Insert ( new Entry_t ( viewSetup , pList , pListInfo ) ) ;
}
private :
struct Entry_t
{
Entry_t ( const CViewSetup & viewSetup , IWorldRenderList * pList = NULL , ClientWorldListInfo_t * pListInfo = NULL ) :
pList ( ( pList ) ? InlineAddRef ( pList ) : NULL ) ,
pListInfo ( ( pListInfo ) ? InlineAddRef ( pListInfo ) : NULL )
{
// @NOTE (toml 8/18/2006): because doing memcmp, need to fill all of the fields and the padding!
memset ( & m_bOrtho , 0 , offsetof ( Entry_t , pList ) - offsetof ( Entry_t , m_bOrtho ) ) ;
m_bOrtho = viewSetup . m_bOrtho ;
m_OrthoLeft = viewSetup . m_OrthoLeft ;
m_OrthoTop = viewSetup . m_OrthoTop ;
m_OrthoRight = viewSetup . m_OrthoRight ;
m_OrthoBottom = viewSetup . m_OrthoBottom ;
fov = viewSetup . fov ;
origin = viewSetup . origin ;
angles = viewSetup . angles ;
zNear = viewSetup . zNear ;
zFar = viewSetup . zFar ;
m_flAspectRatio = viewSetup . m_flAspectRatio ;
m_bOffCenter = viewSetup . m_bOffCenter ;
m_flOffCenterTop = viewSetup . m_flOffCenterTop ;
m_flOffCenterBottom = viewSetup . m_flOffCenterBottom ;
m_flOffCenterLeft = viewSetup . m_flOffCenterLeft ;
m_flOffCenterRight = viewSetup . m_flOffCenterRight ;
}
~ Entry_t ( )
{
if ( pList )
pList - > Release ( ) ;
if ( pListInfo )
pListInfo - > Release ( ) ;
}
// The fields from CViewSetup that would actually affect the list
float m_OrthoLeft ;
float m_OrthoTop ;
float m_OrthoRight ;
float m_OrthoBottom ;
float fov ;
Vector origin ;
QAngle angles ;
float zNear ;
float zFar ;
float m_flAspectRatio ;
float m_flOffCenterTop ;
float m_flOffCenterBottom ;
float m_flOffCenterLeft ;
float m_flOffCenterRight ;
bool m_bOrtho ;
bool m_bOffCenter ;
IWorldRenderList * pList ;
ClientWorldListInfo_t * pListInfo ;
} ;
class CEntryComparator
{
public :
CEntryComparator ( int ) { }
bool operator ! ( ) const { return false ; }
bool operator ( ) ( const Entry_t * lhs , const Entry_t * rhs ) const
{
return ( memcmp ( lhs , rhs , sizeof ( Entry_t ) - ( sizeof ( Entry_t ) - offsetof ( Entry_t , pList ) ) ) < 0 ) ;
}
} ;
CUtlRBTree < Entry_t * , unsigned short , CEntryComparator > m_Entries ;
} ;
CWorldListCache g_WorldListCache ;
//-----------------------------------------------------------------------------
// Standard 3d skybox view
//-----------------------------------------------------------------------------
class CSkyboxView : public CRendering3dView
{
DECLARE_CLASS ( CSkyboxView , CRendering3dView ) ;
public :
CSkyboxView ( CViewRender * pMainView ) :
CRendering3dView ( pMainView ) ,
m_pSky3dParams ( NULL )
{
}
bool Setup ( const CViewSetup & view , int * pClearFlags , SkyboxVisibility_t * pSkyboxVisible ) ;
void Draw ( ) ;
protected :
# ifdef PORTAL
virtual bool ShouldDrawPortals ( ) { return false ; }
# endif
virtual SkyboxVisibility_t ComputeSkyboxVisibility ( ) ;
bool GetSkyboxFogEnable ( ) ;
void Enable3dSkyboxFog ( void ) ;
void DrawInternal ( view_id_t iSkyBoxViewID , bool bInvokePreAndPostRender , ITexture * pRenderTarget , ITexture * pDepthTarget ) ;
sky3dparams_t * PreRender3dSkyboxWorld ( SkyboxVisibility_t nSkyboxVisible ) ;
sky3dparams_t * m_pSky3dParams ;
} ;
//-----------------------------------------------------------------------------
// 3d skybox view when drawing portals
//-----------------------------------------------------------------------------
# ifdef PORTAL
class CPortalSkyboxView : public CSkyboxView
{
DECLARE_CLASS ( CPortalSkyboxView , CSkyboxView ) ;
public :
CPortalSkyboxView ( CViewRender * pMainView ) :
CSkyboxView ( pMainView ) ,
m_pRenderTarget ( NULL )
{ }
bool Setup ( const CViewSetup & view , int * pClearFlags , SkyboxVisibility_t * pSkyboxVisible , ITexture * pRenderTarget = NULL ) ;
//Skybox drawing through portals with workarounds to fix area bits, position/scaling, view id's..........
void Draw ( ) ;
private :
virtual SkyboxVisibility_t ComputeSkyboxVisibility ( ) ;
ITexture * m_pRenderTarget ;
} ;
# endif
//-----------------------------------------------------------------------------
// Shadow depth texture
//-----------------------------------------------------------------------------
class CShadowDepthView : public CRendering3dView
{
DECLARE_CLASS ( CShadowDepthView , CRendering3dView ) ;
public :
CShadowDepthView ( CViewRender * pMainView ) : CRendering3dView ( pMainView ) { }
void Setup ( const CViewSetup & shadowViewIn , ITexture * pRenderTarget , ITexture * pDepthTexture ) ;
void Draw ( ) ;
private :
ITexture * m_pRenderTarget ;
ITexture * m_pDepthTexture ;
} ;
//-----------------------------------------------------------------------------
// Freeze frame. Redraws the frame at which it was enabled.
//-----------------------------------------------------------------------------
class CFreezeFrameView : public CRendering3dView
{
DECLARE_CLASS ( CFreezeFrameView , CRendering3dView ) ;
public :
CFreezeFrameView ( CViewRender * pMainView ) : CRendering3dView ( pMainView ) { }
void Setup ( const CViewSetup & view ) ;
void Draw ( ) ;
private :
CMaterialReference m_pFreezeFrame ;
CMaterialReference m_TranslucentSingleColor ;
} ;
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
class CBaseWorldView : public CRendering3dView
{
DECLARE_CLASS ( CBaseWorldView , CRendering3dView ) ;
protected :
CBaseWorldView ( CViewRender * pMainView ) : CRendering3dView ( pMainView ) { }
virtual bool AdjustView ( float waterHeight ) ;
void DrawSetup ( float waterHeight , int flags , float waterZAdjust , int iForceViewLeaf = - 1 ) ;
void DrawExecute ( float waterHeight , view_id_t viewID , float waterZAdjust ) ;
virtual void PushView ( float waterHeight ) ;
virtual void PopView ( ) ;
void SSAO_DepthPass ( ) ;
void DrawDepthOfField ( ) ;
} ;
//-----------------------------------------------------------------------------
// Draws the scene when there's no water or only cheap water
//-----------------------------------------------------------------------------
class CSimpleWorldView : public CBaseWorldView
{
DECLARE_CLASS ( CSimpleWorldView , CBaseWorldView ) ;
public :
CSimpleWorldView ( CViewRender * pMainView ) : CBaseWorldView ( pMainView ) { }
void Setup ( const CViewSetup & view , int nClearFlags , bool bDrawSkybox , const VisibleFogVolumeInfo_t & fogInfo , const WaterRenderInfo_t & info , ViewCustomVisibility_t * pCustomVisibility = NULL ) ;
void Draw ( ) ;
private :
VisibleFogVolumeInfo_t m_fogInfo ;
} ;
//-----------------------------------------------------------------------------
// Base class for scenes with water
//-----------------------------------------------------------------------------
class CBaseWaterView : public CBaseWorldView
{
DECLARE_CLASS ( CBaseWaterView , CBaseWorldView ) ;
public :
CBaseWaterView ( CViewRender * pMainView ) :
CBaseWorldView ( pMainView ) ,
m_SoftwareIntersectionView ( pMainView )
{ }
// void Setup( const CViewSetup &, const WaterRenderInfo_t& info );
protected :
void CalcWaterEyeAdjustments ( const VisibleFogVolumeInfo_t & fogInfo , float & newWaterHeight , float & waterZAdjust , bool bSoftwareUserClipPlane ) ;
class CSoftwareIntersectionView : public CBaseWorldView
{
DECLARE_CLASS ( CSoftwareIntersectionView , CBaseWorldView ) ;
public :
CSoftwareIntersectionView ( CViewRender * pMainView ) : CBaseWorldView ( pMainView ) { }
void Setup ( bool bAboveWater ) ;
void Draw ( ) ;
private :
CBaseWaterView * GetOuter ( ) { return GET_OUTER ( CBaseWaterView , m_SoftwareIntersectionView ) ; }
} ;
friend class CSoftwareIntersectionView ;
CSoftwareIntersectionView m_SoftwareIntersectionView ;
WaterRenderInfo_t m_waterInfo ;
float m_waterHeight ;
float m_waterZAdjust ;
bool m_bSoftwareUserClipPlane ;
VisibleFogVolumeInfo_t m_fogInfo ;
} ;
//-----------------------------------------------------------------------------
// Scenes above water
//-----------------------------------------------------------------------------
class CAboveWaterView : public CBaseWaterView
{
DECLARE_CLASS ( CAboveWaterView , CBaseWaterView ) ;
public :
CAboveWaterView ( CViewRender * pMainView ) :
CBaseWaterView ( pMainView ) ,
m_ReflectionView ( pMainView ) ,
m_RefractionView ( pMainView ) ,
m_IntersectionView ( pMainView )
{ }
void Setup ( const CViewSetup & view , bool bDrawSkybox , const VisibleFogVolumeInfo_t & fogInfo , const WaterRenderInfo_t & waterInfo ) ;
void Draw ( ) ;
class CReflectionView : public CBaseWorldView
{
DECLARE_CLASS ( CReflectionView , CBaseWorldView ) ;
public :
CReflectionView ( CViewRender * pMainView ) : CBaseWorldView ( pMainView ) { }
void Setup ( bool bReflectEntities ) ;
void Draw ( ) ;
private :
CAboveWaterView * GetOuter ( ) { return GET_OUTER ( CAboveWaterView , m_ReflectionView ) ; }
} ;
class CRefractionView : public CBaseWorldView
{
DECLARE_CLASS ( CRefractionView , CBaseWorldView ) ;
public :
CRefractionView ( CViewRender * pMainView ) : CBaseWorldView ( pMainView ) { }
void Setup ( ) ;
void Draw ( ) ;
private :
CAboveWaterView * GetOuter ( ) { return GET_OUTER ( CAboveWaterView , m_RefractionView ) ; }
} ;
class CIntersectionView : public CBaseWorldView
{
DECLARE_CLASS ( CIntersectionView , CBaseWorldView ) ;
public :
CIntersectionView ( CViewRender * pMainView ) : CBaseWorldView ( pMainView ) { }
void Setup ( ) ;
void Draw ( ) ;
private :
CAboveWaterView * GetOuter ( ) { return GET_OUTER ( CAboveWaterView , m_IntersectionView ) ; }
} ;
friend class CRefractionView ;
friend class CReflectionView ;
friend class CIntersectionView ;
bool m_bViewIntersectsWater ;
CReflectionView m_ReflectionView ;
CRefractionView m_RefractionView ;
CIntersectionView m_IntersectionView ;
} ;
//-----------------------------------------------------------------------------
// Scenes below water
//-----------------------------------------------------------------------------
class CUnderWaterView : public CBaseWaterView
{
DECLARE_CLASS ( CUnderWaterView , CBaseWaterView ) ;
public :
CUnderWaterView ( CViewRender * pMainView ) :
CBaseWaterView ( pMainView ) ,
m_RefractionView ( pMainView )
{ }
void Setup ( const CViewSetup & view , bool bDrawSkybox , const VisibleFogVolumeInfo_t & fogInfo , const WaterRenderInfo_t & info ) ;
void Draw ( ) ;
class CRefractionView : public CBaseWorldView
{
DECLARE_CLASS ( CRefractionView , CBaseWorldView ) ;
public :
CRefractionView ( CViewRender * pMainView ) : CBaseWorldView ( pMainView ) { }
void Setup ( ) ;
void Draw ( ) ;
private :
CUnderWaterView * GetOuter ( ) { return GET_OUTER ( CUnderWaterView , m_RefractionView ) ; }
} ;
friend class CRefractionView ;
bool m_bDrawSkybox ; // @MULTICORE (toml 8/17/2006): remove after setup hoisted
CRefractionView m_RefractionView ;
} ;
//-----------------------------------------------------------------------------
// Scenes containing reflective glass
//-----------------------------------------------------------------------------
class CReflectiveGlassView : public CSimpleWorldView
{
DECLARE_CLASS ( CReflectiveGlassView , CSimpleWorldView ) ;
public :
CReflectiveGlassView ( CViewRender * pMainView ) : BaseClass ( pMainView )
{
}
virtual bool AdjustView ( float flWaterHeight ) ;
virtual void PushView ( float waterHeight ) ;
virtual void PopView ( ) ;
void Setup ( const CViewSetup & view , int nClearFlags , bool bDrawSkybox , const VisibleFogVolumeInfo_t & fogInfo , const WaterRenderInfo_t & waterInfo , const cplane_t & reflectionPlane ) ;
void Draw ( ) ;
cplane_t m_ReflectionPlane ;
} ;
class CRefractiveGlassView : public CSimpleWorldView
{
DECLARE_CLASS ( CRefractiveGlassView , CSimpleWorldView ) ;
public :
CRefractiveGlassView ( CViewRender * pMainView ) : BaseClass ( pMainView )
{
}
virtual bool AdjustView ( float flWaterHeight ) ;
virtual void PushView ( float waterHeight ) ;
virtual void PopView ( ) ;
void Setup ( const CViewSetup & view , int nClearFlags , bool bDrawSkybox , const VisibleFogVolumeInfo_t & fogInfo , const WaterRenderInfo_t & waterInfo , const cplane_t & reflectionPlane ) ;
void Draw ( ) ;
cplane_t m_ReflectionPlane ;
} ;
//-----------------------------------------------------------------------------
// Computes draw flags for the engine to build its world surface lists
//-----------------------------------------------------------------------------
static inline unsigned long BuildEngineDrawWorldListFlags ( unsigned nDrawFlags )
{
unsigned long nEngineFlags = 0 ;
if ( nDrawFlags & DF_DRAWSKYBOX )
{
nEngineFlags | = DRAWWORLDLISTS_DRAW_SKYBOX ;
}
if ( nDrawFlags & DF_RENDER_ABOVEWATER )
{
nEngineFlags | = DRAWWORLDLISTS_DRAW_STRICTLYABOVEWATER ;
nEngineFlags | = DRAWWORLDLISTS_DRAW_INTERSECTSWATER ;
}
if ( nDrawFlags & DF_RENDER_UNDERWATER )
{
nEngineFlags | = DRAWWORLDLISTS_DRAW_STRICTLYUNDERWATER ;
nEngineFlags | = DRAWWORLDLISTS_DRAW_INTERSECTSWATER ;
}
if ( nDrawFlags & DF_RENDER_WATER )
{
nEngineFlags | = DRAWWORLDLISTS_DRAW_WATERSURFACE ;
}
if ( nDrawFlags & DF_CLIP_SKYBOX )
{
nEngineFlags | = DRAWWORLDLISTS_DRAW_CLIPSKYBOX ;
}
if ( nDrawFlags & DF_SHADOW_DEPTH_MAP )
{
nEngineFlags | = DRAWWORLDLISTS_DRAW_SHADOWDEPTH ;
}
if ( nDrawFlags & DF_RENDER_REFRACTION )
{
nEngineFlags | = DRAWWORLDLISTS_DRAW_REFRACTION ;
}
if ( nDrawFlags & DF_RENDER_REFLECTION )
{
nEngineFlags | = DRAWWORLDLISTS_DRAW_REFLECTION ;
}
if ( nDrawFlags & DF_SSAO_DEPTH_PASS )
{
nEngineFlags | = DRAWWORLDLISTS_DRAW_SSAO | DRAWWORLDLISTS_DRAW_STRICTLYUNDERWATER | DRAWWORLDLISTS_DRAW_INTERSECTSWATER | DRAWWORLDLISTS_DRAW_STRICTLYABOVEWATER ;
nEngineFlags & = ~ ( DRAWWORLDLISTS_DRAW_WATERSURFACE | DRAWWORLDLISTS_DRAW_REFRACTION | DRAWWORLDLISTS_DRAW_REFLECTION ) ;
}
return nEngineFlags ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
static void SetClearColorToFogColor ( )
{
unsigned char ucFogColor [ 3 ] ;
CMatRenderContextPtr pRenderContext ( materials ) ;
pRenderContext - > GetFogColor ( ucFogColor ) ;
if ( g_pMaterialSystemHardwareConfig - > GetHDRType ( ) = = HDR_TYPE_INTEGER )
{
// @MULTICORE (toml 8/16/2006): Find a way to not do this twice in eye above water case
float scale = LinearToGammaFullRange ( pRenderContext - > GetToneMappingScaleLinear ( ) . x ) ;
ucFogColor [ 0 ] * = scale ;
ucFogColor [ 1 ] * = scale ;
ucFogColor [ 2 ] * = scale ;
}
pRenderContext - > ClearColor4ub ( ucFogColor [ 0 ] , ucFogColor [ 1 ] , ucFogColor [ 2 ] , 255 ) ;
}
//-----------------------------------------------------------------------------
// Precache of necessary materials
//-----------------------------------------------------------------------------
# ifdef HL2_CLIENT_DLL
CLIENTEFFECT_REGISTER_BEGIN ( PrecacheViewRender )
CLIENTEFFECT_MATERIAL ( " scripted/intro_screenspaceeffect " )
CLIENTEFFECT_REGISTER_END ( )
# endif
CLIENTEFFECT_REGISTER_BEGIN ( PrecachePostProcessingEffects )
CLIENTEFFECT_MATERIAL ( " dev/blurfiltery_and_add_nohdr " )
CLIENTEFFECT_MATERIAL ( " dev/blurfilterx " )
CLIENTEFFECT_MATERIAL ( " dev/blurfilterx_nohdr " )
CLIENTEFFECT_MATERIAL ( " dev/blurfiltery " )
CLIENTEFFECT_MATERIAL ( " dev/blurfiltery_nohdr " )
CLIENTEFFECT_MATERIAL ( " dev/bloomadd " )
CLIENTEFFECT_MATERIAL ( " dev/downsample " )
# ifdef CSTRIKE_DLL
CLIENTEFFECT_MATERIAL ( " dev/downsample_non_hdr_cstrike " )
# else
CLIENTEFFECT_MATERIAL ( " dev/downsample_non_hdr " )
# endif
CLIENTEFFECT_MATERIAL ( " dev/no_pixel_write " )
CLIENTEFFECT_MATERIAL ( " dev/lumcompare " )
CLIENTEFFECT_MATERIAL ( " dev/floattoscreen_combine " )
CLIENTEFFECT_MATERIAL ( " dev/copyfullframefb_vanilla " )
CLIENTEFFECT_MATERIAL ( " dev/copyfullframefb " )
CLIENTEFFECT_MATERIAL ( " dev/engine_post " )
CLIENTEFFECT_MATERIAL ( " dev/motion_blur " )
CLIENTEFFECT_MATERIAL ( " dev/upscale " )
# ifdef TF_CLIENT_DLL
CLIENTEFFECT_MATERIAL ( " dev/pyro_blur_filter_y " )
CLIENTEFFECT_MATERIAL ( " dev/pyro_blur_filter_x " )
CLIENTEFFECT_MATERIAL ( " dev/pyro_dof " )
CLIENTEFFECT_MATERIAL ( " dev/pyro_vignette_border " )
CLIENTEFFECT_MATERIAL ( " dev/pyro_vignette " )
CLIENTEFFECT_MATERIAL ( " dev/pyro_post " )
# endif
CLIENTEFFECT_REGISTER_END_CONDITIONAL ( engine - > GetDXSupportLevel ( ) > = 90 )
//-----------------------------------------------------------------------------
// Accessors to return the current view being rendered
//-----------------------------------------------------------------------------
const Vector & CurrentViewOrigin ( )
{
Assert ( s_bCanAccessCurrentView ) ;
return g_vecCurrentRenderOrigin ;
}
const QAngle & CurrentViewAngles ( )
{
Assert ( s_bCanAccessCurrentView ) ;
return g_vecCurrentRenderAngles ;
}
const Vector & CurrentViewForward ( )
{
Assert ( s_bCanAccessCurrentView ) ;
return g_vecCurrentVForward ;
}
const Vector & CurrentViewRight ( )
{
Assert ( s_bCanAccessCurrentView ) ;
return g_vecCurrentVRight ;
}
const Vector & CurrentViewUp ( )
{
Assert ( s_bCanAccessCurrentView ) ;
return g_vecCurrentVUp ;
}
const VMatrix & CurrentWorldToViewMatrix ( )
{
Assert ( s_bCanAccessCurrentView ) ;
return g_matCurrentCamInverse ;
}
//-----------------------------------------------------------------------------
// Methods to set the current view/guard access to view parameters
//-----------------------------------------------------------------------------
void AllowCurrentViewAccess ( bool allow )
{
s_bCanAccessCurrentView = allow ;
}
bool IsCurrentViewAccessAllowed ( )
{
return s_bCanAccessCurrentView ;
}
void SetupCurrentView ( const Vector & vecOrigin , const QAngle & angles , view_id_t viewID )
{
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " %s " , __FUNCTION__ ) ;
// Store off view origin and angles
g_vecCurrentRenderOrigin = vecOrigin ;
g_vecCurrentRenderAngles = angles ;
// Compute the world->main camera transform
ComputeCameraVariables ( vecOrigin , angles ,
& g_vecCurrentVForward , & g_vecCurrentVRight , & g_vecCurrentVUp , & g_matCurrentCamInverse ) ;
g_CurrentViewID = viewID ;
s_bCanAccessCurrentView = true ;
// Cache off fade distances
float flScreenFadeMinSize , flScreenFadeMaxSize ;
view - > GetScreenFadeDistances ( & flScreenFadeMinSize , & flScreenFadeMaxSize ) ;
modelinfo - > SetViewScreenFadeRange ( flScreenFadeMinSize , flScreenFadeMaxSize ) ;
CMatRenderContextPtr pRenderContext ( materials ) ;
# ifdef PORTAL
if ( g_pPortalRender - > GetViewRecursionLevel ( ) = = 0 )
{
pRenderContext - > SetIntRenderingParameter ( INT_RENDERPARM_WRITE_DEPTH_TO_DESTALPHA , ( ( viewID = = VIEW_MAIN ) | | ( viewID = = VIEW_3DSKY ) ) ? 1 : 0 ) ;
}
# else
pRenderContext - > SetIntRenderingParameter ( INT_RENDERPARM_WRITE_DEPTH_TO_DESTALPHA , ( ( viewID = = VIEW_MAIN ) | | ( viewID = = VIEW_3DSKY ) ) ? 1 : 0 ) ;
# endif
}
view_id_t CurrentViewID ( )
{
Assert ( g_CurrentViewID ! = VIEW_ILLEGAL ) ;
return ( view_id_t ) g_CurrentViewID ;
}
//-----------------------------------------------------------------------------
// Purpose: Portal views are considered 'Main' views. This function tests a view id
// against all view ids used by portal renderables, as well as the main view.
//-----------------------------------------------------------------------------
bool IsMainView ( view_id_t id )
{
# if defined(PORTAL)
return ( ( id = = VIEW_MAIN ) | | g_pPortalRender - > IsPortalViewID ( id ) ) ;
# else
return ( id = = VIEW_MAIN ) ;
# endif
}
void FinishCurrentView ( )
{
s_bCanAccessCurrentView = false ;
}
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
void CSimpleRenderExecutor : : AddView ( CRendering3dView * pView )
{
CBase3dView * pPrevRenderer = m_pMainView - > SetActiveRenderer ( pView ) ;
pView - > Draw ( ) ;
m_pMainView - > SetActiveRenderer ( pPrevRenderer ) ;
}
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CViewRender : : CViewRender ( )
: m_SimpleExecutor ( this )
{
m_flCheapWaterStartDistance = 0.0f ;
m_flCheapWaterEndDistance = 0.1f ;
m_BaseDrawFlags = 0 ;
m_pActiveRenderer = NULL ;
m_pCurrentlyDrawingEntity = NULL ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
inline bool CViewRender : : ShouldDrawEntities ( void )
{
return ( ! m_pDrawEntities | | ( m_pDrawEntities - > GetInt ( ) ! = 0 ) ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Check all conditions which would prevent drawing the view model
// Input : drawViewmodel -
// *viewmodel -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CViewRender : : ShouldDrawViewModel ( bool bDrawViewmodel )
{
if ( ! bDrawViewmodel )
return false ;
if ( ! r_drawviewmodel . GetBool ( ) )
return false ;
if ( C_BasePlayer : : ShouldDrawLocalPlayer ( ) )
return false ;
if ( ! ShouldDrawEntities ( ) )
return false ;
if ( render - > GetViewEntity ( ) > gpGlobals - > maxClients )
return false ;
return true ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
bool CViewRender : : UpdateRefractIfNeededByList ( CUtlVector < IClientRenderable * > & list )
{
int nCount = list . Count ( ) ;
for ( int i = 0 ; i < nCount ; + + i )
{
IClientUnknown * pUnk = list [ i ] - > GetIClientUnknown ( ) ;
Assert ( pUnk ) ;
IClientRenderable * pRenderable = pUnk - > GetClientRenderable ( ) ;
Assert ( pRenderable ) ;
if ( pRenderable - > UsesPowerOfTwoFrameBufferTexture ( ) )
{
UpdateRefractTexture ( ) ;
return true ;
}
}
return false ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CViewRender : : DrawRenderablesInList ( CUtlVector < IClientRenderable * > & list , int flags )
{
Assert ( m_pCurrentlyDrawingEntity = = NULL ) ;
int nCount = list . Count ( ) ;
for ( int i = 0 ; i < nCount ; + + i )
{
IClientUnknown * pUnk = list [ i ] - > GetIClientUnknown ( ) ;
Assert ( pUnk ) ;
IClientRenderable * pRenderable = pUnk - > GetClientRenderable ( ) ;
Assert ( pRenderable ) ;
// Non-view models wanting to render in view model list...
if ( pRenderable - > ShouldDraw ( ) )
{
m_pCurrentlyDrawingEntity = pUnk - > GetBaseEntity ( ) ;
pRenderable - > DrawModel ( STUDIO_RENDER | flags ) ;
}
}
m_pCurrentlyDrawingEntity = NULL ;
}
//-----------------------------------------------------------------------------
// Purpose: Actually draw the view model
// Input : drawViewModel -
//-----------------------------------------------------------------------------
void CViewRender : : DrawViewModels ( const CViewSetup & view , bool drawViewmodel )
{
VPROF ( " CViewRender::DrawViewModel " ) ;
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " %s " , __FUNCTION__ ) ;
# ifdef PORTAL //in portal, we'd like a copy of the front buffer without the gun in it for use with the depth doubler
g_pPortalRender - > UpdateDepthDoublerTexture ( view ) ;
# endif
bool bShouldDrawPlayerViewModel = ShouldDrawViewModel ( drawViewmodel ) ;
bool bShouldDrawToolViewModels = ToolsEnabled ( ) ;
CMatRenderContextPtr pRenderContext ( materials ) ;
PIXEVENT ( pRenderContext , " DrawViewModels " ) ;
// Restore the matrices
pRenderContext - > MatrixMode ( MATERIAL_PROJECTION ) ;
pRenderContext - > PushMatrix ( ) ;
CViewSetup viewModelSetup ( view ) ;
viewModelSetup . zNear = view . zNearViewmodel ;
viewModelSetup . zFar = view . zFarViewmodel ;
viewModelSetup . fov = view . fovViewmodel ;
viewModelSetup . m_flAspectRatio = engine - > GetScreenAspectRatio ( ) ;
ITexture * pRTColor = NULL ;
ITexture * pRTDepth = NULL ;
if ( view . m_eStereoEye ! = STEREO_EYE_MONO )
{
pRTColor = g_pSourceVR - > GetRenderTarget ( ( ISourceVirtualReality : : VREye ) ( view . m_eStereoEye - 1 ) , ISourceVirtualReality : : RT_Color ) ;
pRTDepth = g_pSourceVR - > GetRenderTarget ( ( ISourceVirtualReality : : VREye ) ( view . m_eStereoEye - 1 ) , ISourceVirtualReality : : RT_Depth ) ;
}
render - > Push3DView ( viewModelSetup , 0 , pRTColor , GetFrustum ( ) , pRTDepth ) ;
# ifdef PORTAL //the depth range hack doesn't work well enough for the portal mod (and messing with the depth hack values makes some models draw incorrectly)
//step up to a full depth clear if we're extremely close to a portal (in a portal environment)
extern bool LocalPlayerIsCloseToPortal ( void ) ; //defined in C_Portal_Player.cpp, abstracting to a single bool function to remove explicit dependence on c_portal_player.h/cpp, you can define the function as a "return true" in other build configurations at the cost of some perf
bool bUseDepthHack = ! LocalPlayerIsCloseToPortal ( ) ;
if ( ! bUseDepthHack )
pRenderContext - > ClearBuffers ( false , true , false ) ;
# else
const bool bUseDepthHack = true ;
# endif
// FIXME: Add code to read the current depth range
float depthmin = 0.0f ;
float depthmax = 1.0f ;
// HACK HACK: Munge the depth range to prevent view model from poking into walls, etc.
// Force clipped down range
if ( bUseDepthHack )
pRenderContext - > DepthRange ( 0.0f , 0.1f ) ;
if ( bShouldDrawPlayerViewModel | | bShouldDrawToolViewModels )
{
CUtlVector < IClientRenderable * > opaqueViewModelList ( 32 ) ;
CUtlVector < IClientRenderable * > translucentViewModelList ( 32 ) ;
ClientLeafSystem ( ) - > CollateViewModelRenderables ( opaqueViewModelList , translucentViewModelList ) ;
if ( ToolsEnabled ( ) & & ( ! bShouldDrawPlayerViewModel | | ! bShouldDrawToolViewModels ) )
{
int nOpaque = opaqueViewModelList . Count ( ) ;
for ( int i = nOpaque - 1 ; i > = 0 ; - - i )
{
IClientRenderable * pRenderable = opaqueViewModelList [ i ] ;
bool bEntity = pRenderable - > GetIClientUnknown ( ) - > GetBaseEntity ( ) ;
if ( ( bEntity & & ! bShouldDrawPlayerViewModel ) | | ( ! bEntity & & ! bShouldDrawToolViewModels ) )
{
opaqueViewModelList . FastRemove ( i ) ;
}
}
int nTranslucent = translucentViewModelList . Count ( ) ;
for ( int i = nTranslucent - 1 ; i > = 0 ; - - i )
{
IClientRenderable * pRenderable = translucentViewModelList [ i ] ;
bool bEntity = pRenderable - > GetIClientUnknown ( ) - > GetBaseEntity ( ) ;
if ( ( bEntity & & ! bShouldDrawPlayerViewModel ) | | ( ! bEntity & & ! bShouldDrawToolViewModels ) )
{
translucentViewModelList . FastRemove ( i ) ;
}
}
}
if ( ! UpdateRefractIfNeededByList ( opaqueViewModelList ) )
{
UpdateRefractIfNeededByList ( translucentViewModelList ) ;
}
DrawRenderablesInList ( opaqueViewModelList ) ;
DrawRenderablesInList ( translucentViewModelList , STUDIO_TRANSPARENCY ) ;
}
// Reset the depth range to the original values
if ( bUseDepthHack )
pRenderContext - > DepthRange ( depthmin , depthmax ) ;
render - > PopView ( GetFrustum ( ) ) ;
// Restore the matrices
pRenderContext - > MatrixMode ( MATERIAL_PROJECTION ) ;
pRenderContext - > PopMatrix ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CViewRender : : ShouldDrawBrushModels ( void )
{
if ( m_pDrawBrushModels & & ! m_pDrawBrushModels - > GetInt ( ) )
return false ;
return true ;
}
//-----------------------------------------------------------------------------
// Purpose: Performs screen space effects, if any
//-----------------------------------------------------------------------------
void CViewRender : : PerformScreenSpaceEffects ( int x , int y , int w , int h )
{
VPROF ( " CViewRender::PerformScreenSpaceEffects() " ) ;
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " %s " , __FUNCTION__ ) ;
// FIXME: Screen-space effects are busted in the editor
if ( engine - > IsHammerRunning ( ) )
return ;
g_pScreenSpaceEffects - > RenderEffects ( x , y , w , h ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Sets the screen space effect material (can't be done during rendering)
//-----------------------------------------------------------------------------
void CViewRender : : SetScreenOverlayMaterial ( IMaterial * pMaterial )
{
m_ScreenOverlayMaterial . Init ( pMaterial ) ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
IMaterial * CViewRender : : GetScreenOverlayMaterial ( )
{
return m_ScreenOverlayMaterial ;
}
//-----------------------------------------------------------------------------
// Purpose: Performs screen space effects, if any
//-----------------------------------------------------------------------------
void CViewRender : : PerformScreenOverlay ( int x , int y , int w , int h )
{
VPROF ( " CViewRender::PerformScreenOverlay() " ) ;
if ( m_ScreenOverlayMaterial )
{
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " %s " , __FUNCTION__ ) ;
if ( m_ScreenOverlayMaterial - > NeedsFullFrameBufferTexture ( ) )
{
// FIXME: check with multi/sub-rect renders. Should this be 0,0,w,h instead?
DrawScreenEffectMaterial ( m_ScreenOverlayMaterial , x , y , w , h ) ;
}
else if ( m_ScreenOverlayMaterial - > NeedsPowerOfTwoFrameBufferTexture ( ) )
{
// First copy the FB off to the offscreen texture
UpdateRefractTexture ( x , y , w , h , true ) ;
// Now draw the entire screen using the material...
CMatRenderContextPtr pRenderContext ( materials ) ;
ITexture * pTexture = GetPowerOfTwoFrameBufferTexture ( ) ;
int sw = pTexture - > GetActualWidth ( ) ;
int sh = pTexture - > GetActualHeight ( ) ;
// Note - don't offset by x,y - already done by the viewport.
pRenderContext - > DrawScreenSpaceRectangle ( m_ScreenOverlayMaterial , 0 , 0 , w , h ,
0 , 0 , sw - 1 , sh - 1 , sw , sh ) ;
}
else
{
byte color [ 4 ] = { 255 , 255 , 255 , 255 } ;
render - > ViewDrawFade ( color , m_ScreenOverlayMaterial ) ;
}
}
}
void CViewRender : : DrawUnderwaterOverlay ( void )
{
IMaterial * pOverlayMat = m_UnderWaterOverlayMaterial ;
if ( pOverlayMat )
{
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " %s " , __FUNCTION__ ) ;
CMatRenderContextPtr pRenderContext ( materials ) ;
int x , y , w , h ;
pRenderContext - > GetViewport ( x , y , w , h ) ;
if ( pOverlayMat - > NeedsFullFrameBufferTexture ( ) )
{
// FIXME: check with multi/sub-rect renders. Should this be 0,0,w,h instead?
DrawScreenEffectMaterial ( pOverlayMat , x , y , w , h ) ;
}
else if ( pOverlayMat - > NeedsPowerOfTwoFrameBufferTexture ( ) )
{
// First copy the FB off to the offscreen texture
UpdateRefractTexture ( x , y , w , h , true ) ;
// Now draw the entire screen using the material...
CMatRenderContextPtr pRenderContext ( materials ) ;
ITexture * pTexture = GetPowerOfTwoFrameBufferTexture ( ) ;
int sw = pTexture - > GetActualWidth ( ) ;
int sh = pTexture - > GetActualHeight ( ) ;
// Note - don't offset by x,y - already done by the viewport.
pRenderContext - > DrawScreenSpaceRectangle ( pOverlayMat , 0 , 0 , w , h ,
0 , 0 , sw - 1 , sh - 1 , sw , sh ) ;
}
else
{
// Note - don't offset by x,y - already done by the viewport.
// FIXME: actually test this code path.
pRenderContext - > DrawScreenSpaceRectangle ( pOverlayMat , 0 , 0 , w , h ,
0 , 0 , 1 , 1 , 1 , 1 ) ;
}
}
}
//-----------------------------------------------------------------------------
// Purpose: Returns the min/max fade distances
//-----------------------------------------------------------------------------
void CViewRender : : GetScreenFadeDistances ( float * min , float * max )
{
if ( min )
{
* min = r_screenfademinsize . GetFloat ( ) ;
}
if ( max )
{
* max = r_screenfademaxsize . GetFloat ( ) ;
}
}
C_BaseEntity * CViewRender : : GetCurrentlyDrawingEntity ( )
{
return m_pCurrentlyDrawingEntity ;
}
void CViewRender : : SetCurrentlyDrawingEntity ( C_BaseEntity * pEnt )
{
m_pCurrentlyDrawingEntity = pEnt ;
}
bool CViewRender : : UpdateShadowDepthTexture ( ITexture * pRenderTarget , ITexture * pDepthTexture , const CViewSetup & shadowViewIn )
{
VPROF_INCREMENT_COUNTER ( " shadow depth textures rendered " , 1 ) ;
CMatRenderContextPtr pRenderContext ( materials ) ;
char szPIXEventName [ 128 ] ;
sprintf ( szPIXEventName , " UpdateShadowDepthTexture (%s) " , pDepthTexture - > GetName ( ) ) ;
PIXEVENT ( pRenderContext , szPIXEventName ) ;
CRefPtr < CShadowDepthView > pShadowDepthView = new CShadowDepthView ( this ) ;
pShadowDepthView - > Setup ( shadowViewIn , pRenderTarget , pDepthTexture ) ;
AddViewToScene ( pShadowDepthView ) ;
return true ;
}
//-----------------------------------------------------------------------------
// Purpose: Renders world and all entities, etc.
//-----------------------------------------------------------------------------
void CViewRender : : ViewDrawScene ( bool bDrew3dSkybox , SkyboxVisibility_t nSkyboxVisible , const CViewSetup & view ,
int nClearFlags , view_id_t viewID , bool bDrawViewModel , int baseDrawFlags , ViewCustomVisibility_t * pCustomVisibility )
{
VPROF ( " CViewRender::ViewDrawScene " ) ;
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " %s " , __FUNCTION__ ) ;
// this allows the refract texture to be updated once per *scene* on 360
// (e.g. once for a monitor scene and once for the main scene)
g_viewscene_refractUpdateFrame = gpGlobals - > framecount - 1 ;
g_pClientShadowMgr - > PreRender ( ) ;
// Shadowed flashlights supported on ps_2_b and up...
if ( r_flashlightdepthtexture . GetBool ( ) & & ( viewID = = VIEW_MAIN ) )
{
g_pClientShadowMgr - > ComputeShadowDepthTextures ( view ) ;
}
m_BaseDrawFlags = baseDrawFlags ;
SetupCurrentView ( view . origin , view . angles , viewID ) ;
// Invoke pre-render methods
IGameSystem : : PreRenderAllSystems ( ) ;
// Start view
unsigned int visFlags ;
SetupVis ( view , visFlags , pCustomVisibility ) ;
if ( ! bDrew3dSkybox & &
( nSkyboxVisible = = SKYBOX_NOT_VISIBLE ) & & ( visFlags & IVRenderView : : VIEW_SETUP_VIS_EX_RETURN_FLAGS_USES_RADIAL_VIS ) )
{
// This covers the case where we don't see a 3dskybox, yet radial vis is clipping
// the far plane. Need to clear to fog color in this case.
nClearFlags | = VIEW_CLEAR_COLOR ;
SetClearColorToFogColor ( ) ;
}
bool drawSkybox = r_skybox . GetBool ( ) ;
if ( bDrew3dSkybox | | ( nSkyboxVisible = = SKYBOX_NOT_VISIBLE ) )
{
drawSkybox = false ;
}
ParticleMgr ( ) - > IncrementFrameCode ( ) ;
DrawWorldAndEntities ( drawSkybox , view , nClearFlags , pCustomVisibility ) ;
// Disable fog for the rest of the stuff
DisableFog ( ) ;
// UNDONE: Don't do this with masked brush models, they should probably be in a separate list
// render->DrawMaskEntities()
// Here are the overlays...
CGlowOverlay : : DrawOverlays ( view . m_bCacheFullSceneState ) ;
// issue the pixel visibility tests
if ( IsMainView ( CurrentViewID ( ) ) )
{
PixelVisibility_EndCurrentView ( ) ;
}
// Draw rain..
DrawPrecipitation ( ) ;
// Make sure sound doesn't stutter
engine - > Sound_ExtraUpdate ( ) ;
// Debugging info goes over the top
CDebugViewRender : : Draw3DDebuggingInfo ( view ) ;
// Draw client side effects
// NOTE: These are not sorted against the rest of the frame
clienteffects - > DrawEffects ( gpGlobals - > frametime ) ;
// Mark the frame as locked down for client fx additions
SetFXCreationAllowed ( false ) ;
// Invoke post-render methods
IGameSystem : : PostRenderAllSystems ( ) ;
FinishCurrentView ( ) ;
// Free shadow depth textures for use in future view
if ( r_flashlightdepthtexture . GetBool ( ) )
{
g_pClientShadowMgr - > UnlockAllShadowDepthTextures ( ) ;
}
}
void CheckAndTransitionColor ( float flPercent , float * pColor , float * pLerpToColor )
{
if ( pLerpToColor [ 0 ] ! = pColor [ 0 ] | | pLerpToColor [ 1 ] ! = pColor [ 1 ] | | pLerpToColor [ 2 ] ! = pColor [ 2 ] )
{
float flDestColor [ 3 ] ;
flDestColor [ 0 ] = pLerpToColor [ 0 ] ;
flDestColor [ 1 ] = pLerpToColor [ 1 ] ;
flDestColor [ 2 ] = pLerpToColor [ 2 ] ;
pColor [ 0 ] = FLerp ( pColor [ 0 ] , flDestColor [ 0 ] , flPercent ) ;
pColor [ 1 ] = FLerp ( pColor [ 1 ] , flDestColor [ 1 ] , flPercent ) ;
pColor [ 2 ] = FLerp ( pColor [ 2 ] , flDestColor [ 2 ] , flPercent ) ;
}
else
{
pColor [ 0 ] = pLerpToColor [ 0 ] ;
pColor [ 1 ] = pLerpToColor [ 1 ] ;
pColor [ 2 ] = pLerpToColor [ 2 ] ;
}
}
static void GetFogColorTransition ( fogparams_t * pFogParams , float * pColorPrimary , float * pColorSecondary )
{
if ( ! pFogParams )
return ;
if ( pFogParams - > lerptime > = gpGlobals - > curtime )
{
float flPercent = 1.0f - ( ( pFogParams - > lerptime - gpGlobals - > curtime ) / pFogParams - > duration ) ;
float flPrimaryColorLerp [ 3 ] = { ( float ) pFogParams - > colorPrimaryLerpTo . GetR ( ) , ( float ) pFogParams - > colorPrimaryLerpTo . GetG ( ) , ( float ) pFogParams - > colorPrimaryLerpTo . GetB ( ) } ;
float flSecondaryColorLerp [ 3 ] = { ( float ) pFogParams - > colorSecondaryLerpTo . GetR ( ) , ( float ) pFogParams - > colorSecondaryLerpTo . GetG ( ) , ( float ) pFogParams - > colorSecondaryLerpTo . GetB ( ) } ;
CheckAndTransitionColor ( flPercent , pColorPrimary , flPrimaryColorLerp ) ;
CheckAndTransitionColor ( flPercent , pColorSecondary , flSecondaryColorLerp ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Returns the fog color to use in rendering the current frame.
//-----------------------------------------------------------------------------
static void GetFogColor ( fogparams_t * pFogParams , float * pColor )
{
C_BasePlayer * pbp = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( ! pbp | | ! pFogParams )
return ;
const char * fogColorString = fog_color . GetString ( ) ;
if ( fog_override . GetInt ( ) & & fogColorString )
{
sscanf ( fogColorString , " %f%f%f " , pColor , pColor + 1 , pColor + 2 ) ;
}
else
{
float flPrimaryColor [ 3 ] = { ( float ) pFogParams - > colorPrimary . GetR ( ) , ( float ) pFogParams - > colorPrimary . GetG ( ) , ( float ) pFogParams - > colorPrimary . GetB ( ) } ;
float flSecondaryColor [ 3 ] = { ( float ) pFogParams - > colorSecondary . GetR ( ) , ( float ) pFogParams - > colorSecondary . GetG ( ) , ( float ) pFogParams - > colorSecondary . GetB ( ) } ;
GetFogColorTransition ( pFogParams , flPrimaryColor , flSecondaryColor ) ;
if ( pFogParams - > blend )
{
//
// Blend between two fog colors based on viewing angle.
// The secondary fog color is at 180 degrees to the primary fog color.
//
Vector forward ;
pbp - > EyeVectors ( & forward , NULL , NULL ) ;
Vector vNormalized = pFogParams - > dirPrimary ;
VectorNormalize ( vNormalized ) ;
pFogParams - > dirPrimary = vNormalized ;
float flBlendFactor = 0.5 * forward . Dot ( pFogParams - > dirPrimary ) + 0.5 ;
// FIXME: convert to linear colorspace
pColor [ 0 ] = flPrimaryColor [ 0 ] * flBlendFactor + flSecondaryColor [ 0 ] * ( 1 - flBlendFactor ) ;
pColor [ 1 ] = flPrimaryColor [ 1 ] * flBlendFactor + flSecondaryColor [ 1 ] * ( 1 - flBlendFactor ) ;
pColor [ 2 ] = flPrimaryColor [ 2 ] * flBlendFactor + flSecondaryColor [ 2 ] * ( 1 - flBlendFactor ) ;
}
else
{
pColor [ 0 ] = flPrimaryColor [ 0 ] ;
pColor [ 1 ] = flPrimaryColor [ 1 ] ;
pColor [ 2 ] = flPrimaryColor [ 2 ] ;
}
}
VectorScale ( pColor , 1.0f / 255.0f , pColor ) ;
}
static float GetFogStart ( fogparams_t * pFogParams )
{
if ( ! pFogParams )
return 0.0f ;
if ( fog_override . GetInt ( ) )
{
if ( fog_start . GetFloat ( ) = = - 1.0f )
{
return pFogParams - > start ;
}
else
{
return fog_start . GetFloat ( ) ;
}
}
else
{
if ( pFogParams - > lerptime > gpGlobals - > curtime )
{
if ( pFogParams - > start ! = pFogParams - > startLerpTo )
{
if ( pFogParams - > lerptime > gpGlobals - > curtime )
{
float flPercent = 1.0f - ( ( pFogParams - > lerptime - gpGlobals - > curtime ) / pFogParams - > duration ) ;
return FLerp ( pFogParams - > start , pFogParams - > startLerpTo , flPercent ) ;
}
else
{
if ( pFogParams - > start ! = pFogParams - > startLerpTo )
{
pFogParams - > start = pFogParams - > startLerpTo ;
}
}
}
}
return pFogParams - > start ;
}
}
static float GetFogEnd ( fogparams_t * pFogParams )
{
if ( ! pFogParams )
return 0.0f ;
if ( fog_override . GetInt ( ) )
{
if ( fog_end . GetFloat ( ) = = - 1.0f )
{
return pFogParams - > end ;
}
else
{
return fog_end . GetFloat ( ) ;
}
}
else
{
if ( pFogParams - > lerptime > gpGlobals - > curtime )
{
if ( pFogParams - > end ! = pFogParams - > endLerpTo )
{
if ( pFogParams - > lerptime > gpGlobals - > curtime )
{
float flPercent = 1.0f - ( ( pFogParams - > lerptime - gpGlobals - > curtime ) / pFogParams - > duration ) ;
return FLerp ( pFogParams - > end , pFogParams - > endLerpTo , flPercent ) ;
}
else
{
if ( pFogParams - > end ! = pFogParams - > endLerpTo )
{
pFogParams - > end = pFogParams - > endLerpTo ;
}
}
}
}
return pFogParams - > end ;
}
}
static bool GetFogEnable ( fogparams_t * pFogParams )
{
if ( cl_leveloverview . GetFloat ( ) > 0 )
return false ;
// Ask the clientmode
if ( g_pClientMode - > ShouldDrawFog ( ) = = false )
return false ;
if ( fog_override . GetInt ( ) )
{
if ( fog_enable . GetInt ( ) )
{
return true ;
}
else
{
return false ;
}
}
else
{
if ( pFogParams )
return pFogParams - > enable ! = false ;
return false ;
}
}
static float GetFogMaxDensity ( fogparams_t * pFogParams )
{
if ( ! pFogParams )
return 1.0f ;
if ( cl_leveloverview . GetFloat ( ) > 0 )
return 1.0f ;
// Ask the clientmode
if ( ! g_pClientMode - > ShouldDrawFog ( ) )
return 1.0f ;
if ( fog_override . GetInt ( ) )
{
if ( fog_maxdensity . GetFloat ( ) = = - 1.0f )
return pFogParams - > maxdensity ;
else
return fog_maxdensity . GetFloat ( ) ;
}
else
return pFogParams - > maxdensity ;
}
//-----------------------------------------------------------------------------
// Purpose: Returns the skybox fog color to use in rendering the current frame.
//-----------------------------------------------------------------------------
static void GetSkyboxFogColor ( float * pColor )
{
C_BasePlayer * pbp = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( ! pbp )
{
return ;
}
CPlayerLocalData * local = & pbp - > m_Local ;
const char * fogColorString = fog_colorskybox . GetString ( ) ;
if ( fog_override . GetInt ( ) & & fogColorString )
{
sscanf ( fogColorString , " %f%f%f " , pColor , pColor + 1 , pColor + 2 ) ;
}
else
{
if ( local - > m_skybox3d . fog . blend )
{
//
// Blend between two fog colors based on viewing angle.
// The secondary fog color is at 180 degrees to the primary fog color.
//
Vector forward ;
pbp - > EyeVectors ( & forward , NULL , NULL ) ;
Vector vNormalized = local - > m_skybox3d . fog . dirPrimary ;
VectorNormalize ( vNormalized ) ;
local - > m_skybox3d . fog . dirPrimary = vNormalized ;
float flBlendFactor = 0.5 * forward . Dot ( local - > m_skybox3d . fog . dirPrimary ) + 0.5 ;
// FIXME: convert to linear colorspace
pColor [ 0 ] = local - > m_skybox3d . fog . colorPrimary . GetR ( ) * flBlendFactor + local - > m_skybox3d . fog . colorSecondary . GetR ( ) * ( 1 - flBlendFactor ) ;
pColor [ 1 ] = local - > m_skybox3d . fog . colorPrimary . GetG ( ) * flBlendFactor + local - > m_skybox3d . fog . colorSecondary . GetG ( ) * ( 1 - flBlendFactor ) ;
pColor [ 2 ] = local - > m_skybox3d . fog . colorPrimary . GetB ( ) * flBlendFactor + local - > m_skybox3d . fog . colorSecondary . GetB ( ) * ( 1 - flBlendFactor ) ;
}
else
{
pColor [ 0 ] = local - > m_skybox3d . fog . colorPrimary . GetR ( ) ;
pColor [ 1 ] = local - > m_skybox3d . fog . colorPrimary . GetG ( ) ;
pColor [ 2 ] = local - > m_skybox3d . fog . colorPrimary . GetB ( ) ;
}
}
VectorScale ( pColor , 1.0f / 255.0f , pColor ) ;
}
static float GetSkyboxFogStart ( void )
{
C_BasePlayer * pbp = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( ! pbp )
{
return 0.0f ;
}
CPlayerLocalData * local = & pbp - > m_Local ;
if ( fog_override . GetInt ( ) )
{
if ( fog_startskybox . GetFloat ( ) = = - 1.0f )
{
return local - > m_skybox3d . fog . start ;
}
else
{
return fog_startskybox . GetFloat ( ) ;
}
}
else
{
return local - > m_skybox3d . fog . start ;
}
}
static float GetSkyboxFogEnd ( void )
{
C_BasePlayer * pbp = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( ! pbp )
{
return 0.0f ;
}
CPlayerLocalData * local = & pbp - > m_Local ;
if ( fog_override . GetInt ( ) )
{
if ( fog_endskybox . GetFloat ( ) = = - 1.0f )
{
return local - > m_skybox3d . fog . end ;
}
else
{
return fog_endskybox . GetFloat ( ) ;
}
}
else
{
return local - > m_skybox3d . fog . end ;
}
}
static float GetSkyboxFogMaxDensity ( )
{
C_BasePlayer * pbp = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( ! pbp )
return 1.0f ;
CPlayerLocalData * local = & pbp - > m_Local ;
if ( cl_leveloverview . GetFloat ( ) > 0 )
return 1.0f ;
// Ask the clientmode
if ( ! g_pClientMode - > ShouldDrawFog ( ) )
return 1.0f ;
if ( fog_override . GetInt ( ) )
{
if ( fog_maxdensityskybox . GetFloat ( ) = = - 1.0f )
return local - > m_skybox3d . fog . maxdensity ;
else
return fog_maxdensityskybox . GetFloat ( ) ;
}
else
return local - > m_skybox3d . fog . maxdensity ;
}
void CViewRender : : DisableFog ( void )
{
VPROF ( " CViewRander::DisableFog() " ) ;
CMatRenderContextPtr pRenderContext ( materials ) ;
pRenderContext - > FogMode ( MATERIAL_FOG_NONE ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CViewRender : : SetupVis ( const CViewSetup & view , unsigned int & visFlags , ViewCustomVisibility_t * pCustomVisibility )
{
VPROF ( " CViewRender::SetupVis " ) ;
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " %s " , __FUNCTION__ ) ;
if ( pCustomVisibility & & pCustomVisibility - > m_nNumVisOrigins )
{
// Pass array or vis origins to merge
render - > ViewSetupVisEx ( ShouldForceNoVis ( ) , pCustomVisibility - > m_nNumVisOrigins , pCustomVisibility - > m_rgVisOrigins , visFlags ) ;
}
else
{
// Use render origin as vis origin by default
render - > ViewSetupVisEx ( ShouldForceNoVis ( ) , 1 , & view . origin , visFlags ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Renders voice feedback and other sprites attached to players
// Input : none
//-----------------------------------------------------------------------------
void CViewRender : : RenderPlayerSprites ( )
{
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " %s " , __FUNCTION__ ) ;
GetClientVoiceMgr ( ) - > DrawHeadLabels ( ) ;
}
//-----------------------------------------------------------------------------
// Sets up, cleans up the main 3D view
//-----------------------------------------------------------------------------
void CViewRender : : SetupMain3DView ( const CViewSetup & view , int & nClearFlags )
{
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " %s " , __FUNCTION__ ) ;
// FIXME: I really want these fields removed from CViewSetup
// and passed in as independent flags
// Clear the color here if requested.
int nDepthStencilFlags = nClearFlags & ( VIEW_CLEAR_DEPTH | VIEW_CLEAR_STENCIL ) ;
nClearFlags & = ~ ( nDepthStencilFlags ) ; // Clear these flags
if ( nClearFlags & VIEW_CLEAR_COLOR )
{
nClearFlags | = nDepthStencilFlags ; // Add them back in if we're clearing color
}
// If we are using HDR, we render to the HDR full frame buffer texture
// instead of whatever was previously the render target
if ( g_pMaterialSystemHardwareConfig - > GetHDRType ( ) = = HDR_TYPE_FLOAT )
{
render - > Push3DView ( view , nClearFlags , GetFullFrameFrameBufferTexture ( 0 ) , GetFrustum ( ) ) ;
}
else
{
ITexture * pRTColor = NULL ;
ITexture * pRTDepth = NULL ;
if ( view . m_eStereoEye ! = STEREO_EYE_MONO )
{
pRTColor = g_pSourceVR - > GetRenderTarget ( ( ISourceVirtualReality : : VREye ) ( view . m_eStereoEye - 1 ) , ISourceVirtualReality : : RT_Color ) ;
pRTDepth = g_pSourceVR - > GetRenderTarget ( ( ISourceVirtualReality : : VREye ) ( view . m_eStereoEye - 1 ) , ISourceVirtualReality : : RT_Depth ) ;
}
render - > Push3DView ( view , nClearFlags , pRTColor , GetFrustum ( ) , pRTDepth ) ;
}
// If we didn't clear the depth here, we'll need to clear it later
nClearFlags ^ = nDepthStencilFlags ; // Toggle these bits
if ( nClearFlags & VIEW_CLEAR_COLOR )
{
// If we cleared the color here, we don't need to clear it later
nClearFlags & = ~ ( VIEW_CLEAR_COLOR | VIEW_CLEAR_FULL_TARGET ) ;
}
}
void CViewRender : : CleanupMain3DView ( const CViewSetup & view )
{
render - > PopView ( GetFrustum ( ) ) ;
}
//-----------------------------------------------------------------------------
// Queues up an overlay rendering
//-----------------------------------------------------------------------------
void CViewRender : : QueueOverlayRenderView ( const CViewSetup & view , int nClearFlags , int whatToDraw )
{
// Can't have 2 in a single scene
Assert ( ! m_bDrawOverlay ) ;
m_bDrawOverlay = true ;
m_OverlayViewSetup = view ;
m_OverlayClearFlags = nClearFlags ;
m_OverlayDrawFlags = whatToDraw ;
}
//-----------------------------------------------------------------------------
// Purpose: Force the view to freeze on the next frame for the specified time
//-----------------------------------------------------------------------------
void CViewRender : : FreezeFrame ( float flFreezeTime )
{
if ( flFreezeTime = = 0 )
{
m_flFreezeFrameUntil = 0 ;
for ( int i = 0 ; i < STEREO_EYE_MAX ; i + + )
{
m_rbTakeFreezeFrame [ i ] = false ;
}
}
else
{
if ( m_flFreezeFrameUntil > gpGlobals - > curtime )
{
m_flFreezeFrameUntil + = flFreezeTime ;
}
else
{
m_flFreezeFrameUntil = gpGlobals - > curtime + flFreezeTime ;
for ( int i = GetFirstEye ( ) ; i < = GetLastEye ( ) ; i + + )
{
m_rbTakeFreezeFrame [ i ] = true ;
}
}
}
}
const char * COM_GetModDirectory ( ) ;
//-----------------------------------------------------------------------------
// Purpose: This renders the entire 3D view and the in-game hud/viewmodel
// Input : &view -
// whatToDraw -
//-----------------------------------------------------------------------------
// This renders the entire 3D view.
void CViewRender : : RenderView ( const CViewSetup & view , int nClearFlags , int whatToDraw )
{
m_UnderWaterOverlayMaterial . Shutdown ( ) ; // underwater view will set
m_CurrentView = view ;
C_BaseAnimating : : AutoAllowBoneAccess boneaccess ( true , true ) ;
VPROF ( " CViewRender::RenderView " ) ;
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " %s " , __FUNCTION__ ) ;
// Don't want TF2 running less than DX 8
if ( g_pMaterialSystemHardwareConfig - > GetDXSupportLevel ( ) < 80 )
{
// We know they were running at least 8.0 when the game started...we check the
// value in ClientDLL_Init()...so they must be messing with their DirectX settings.
if ( ( Q_stricmp ( COM_GetModDirectory ( ) , " tf " ) = = 0 ) | | ( Q_stricmp ( COM_GetModDirectory ( ) , " tf_beta " ) = = 0 ) )
{
static bool bFirstTime = true ;
if ( bFirstTime )
{
bFirstTime = false ;
Msg ( " This game has a minimum requirement of DirectX 8.0 to run properly. \n " ) ;
}
return ;
}
}
CMatRenderContextPtr pRenderContext ( materials ) ;
ITexture * saveRenderTarget = pRenderContext - > GetRenderTarget ( ) ;
pRenderContext . SafeRelease ( ) ; // don't want to hold for long periods in case in a locking active share thread mode
if ( ! m_rbTakeFreezeFrame [ view . m_eStereoEye ] & & m_flFreezeFrameUntil > gpGlobals - > curtime )
{
CRefPtr < CFreezeFrameView > pFreezeFrameView = new CFreezeFrameView ( this ) ;
pFreezeFrameView - > Setup ( view ) ;
AddViewToScene ( pFreezeFrameView ) ;
g_bRenderingView = true ;
s_bCanAccessCurrentView = true ;
}
else
{
g_flFreezeFlash = 0.0f ;
g_pClientShadowMgr - > AdvanceFrame ( ) ;
# ifdef USE_MONITORS
if ( cl_drawmonitors . GetBool ( ) & &
( g_pMaterialSystemHardwareConfig - > GetDXSupportLevel ( ) > = 70 ) & &
( ( whatToDraw & RENDERVIEW_SUPPRESSMONITORRENDERING ) = = 0 ) )
{
CViewSetup viewMiddle = GetView ( STEREO_EYE_MONO ) ;
DrawMonitors ( viewMiddle ) ;
}
# endif
g_bRenderingView = true ;
// Must be first
render - > SceneBegin ( ) ;
pRenderContext . GetFrom ( materials ) ;
pRenderContext - > TurnOnToneMapping ( ) ;
pRenderContext . SafeRelease ( ) ;
// clear happens here probably
SetupMain3DView ( view , nClearFlags ) ;
bool bDrew3dSkybox = false ;
SkyboxVisibility_t nSkyboxVisible = SKYBOX_NOT_VISIBLE ;
// if the 3d skybox world is drawn, then don't draw the normal skybox
CSkyboxView * pSkyView = new CSkyboxView ( this ) ;
if ( ( bDrew3dSkybox = pSkyView - > Setup ( view , & nClearFlags , & nSkyboxVisible ) ) ! = false )
{
AddViewToScene ( pSkyView ) ;
}
SafeRelease ( pSkyView ) ;
// Force it to clear the framebuffer if they're in solid space.
if ( ( nClearFlags & VIEW_CLEAR_COLOR ) = = 0 )
{
if ( enginetrace - > GetPointContents ( view . origin ) = = CONTENTS_SOLID )
{
nClearFlags | = VIEW_CLEAR_COLOR ;
}
}
// Render world and all entities, particles, etc.
if ( ! g_pIntroData )
{
ViewDrawScene ( bDrew3dSkybox , nSkyboxVisible , view , nClearFlags , VIEW_MAIN , whatToDraw & RENDERVIEW_DRAWVIEWMODEL ) ;
}
else
{
ViewDrawScene_Intro ( view , nClearFlags , * g_pIntroData ) ;
}
// We can still use the 'current view' stuff set up in ViewDrawScene
s_bCanAccessCurrentView = true ;
engine - > DrawPortals ( ) ;
DisableFog ( ) ;
// Finish scene
render - > SceneEnd ( ) ;
// Draw lightsources if enabled
render - > DrawLights ( ) ;
RenderPlayerSprites ( ) ;
// Image-space motion blur
if ( ! building_cubemaps . GetBool ( ) & & view . m_bDoBloomAndToneMapping ) // We probably should use a different view. variable here
{
if ( ( mat_motion_blur_enabled . GetInt ( ) ) & & ( g_pMaterialSystemHardwareConfig - > GetDXSupportLevel ( ) > = 90 ) )
{
pRenderContext . GetFrom ( materials ) ;
{
PIXEVENT ( pRenderContext , " DoImageSpaceMotionBlur " ) ;
DoImageSpaceMotionBlur ( view , view . x , view . y , view . width , view . height ) ;
}
pRenderContext . SafeRelease ( ) ;
}
}
GetClientModeNormal ( ) - > DoPostScreenSpaceEffects ( & view ) ;
// Now actually draw the viewmodel
DrawViewModels ( view , whatToDraw & RENDERVIEW_DRAWVIEWMODEL ) ;
DrawUnderwaterOverlay ( ) ;
PixelVisibility_EndScene ( ) ;
// Draw fade over entire screen if needed
byte color [ 4 ] ;
bool blend ;
vieweffects - > GetFadeParams ( & color [ 0 ] , & color [ 1 ] , & color [ 2 ] , & color [ 3 ] , & blend ) ;
// Draw an overlay to make it even harder to see inside smoke particle systems.
DrawSmokeFogOverlay ( ) ;
// Overlay screen fade on entire screen
IMaterial * pMaterial = blend ? m_ModulateSingleColor : m_TranslucentSingleColor ;
render - > ViewDrawFade ( color , pMaterial ) ;
PerformScreenOverlay ( view . x , view . y , view . width , view . height ) ;
// Prevent sound stutter if going slow
engine - > Sound_ExtraUpdate ( ) ;
if ( ! building_cubemaps . GetBool ( ) & & view . m_bDoBloomAndToneMapping )
{
pRenderContext . GetFrom ( materials ) ;
{
PIXEVENT ( pRenderContext , " DoEnginePostProcessing " ) ;
bool bFlashlightIsOn = false ;
C_BasePlayer * pLocal = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( pLocal )
{
bFlashlightIsOn = pLocal - > IsEffectActive ( EF_DIMLIGHT ) ;
}
DoEnginePostProcessing ( view . x , view . y , view . width , view . height , bFlashlightIsOn ) ;
}
pRenderContext . SafeRelease ( ) ;
}
// And here are the screen-space effects
if ( IsPC ( ) )
{
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " GrabPreColorCorrectedFrame " ) ;
// Grab the pre-color corrected frame for editing purposes
engine - > GrabPreColorCorrectedFrame ( view . x , view . y , view . width , view . height ) ;
}
PerformScreenSpaceEffects ( 0 , 0 , view . width , view . height ) ;
if ( g_pMaterialSystemHardwareConfig - > GetHDRType ( ) = = HDR_TYPE_INTEGER )
{
pRenderContext . GetFrom ( materials ) ;
pRenderContext - > SetToneMappingScaleLinear ( Vector ( 1 , 1 , 1 ) ) ;
pRenderContext . SafeRelease ( ) ;
}
CleanupMain3DView ( view ) ;
if ( m_rbTakeFreezeFrame [ view . m_eStereoEye ] )
{
Rect_t rect ;
rect . x = view . x ;
rect . y = view . y ;
rect . width = view . width ;
rect . height = view . height ;
pRenderContext = materials - > GetRenderContext ( ) ;
if ( IsX360 ( ) )
{
// 360 doesn't create the Fullscreen texture
pRenderContext - > CopyRenderTargetToTextureEx ( GetFullFrameFrameBufferTexture ( 1 ) , 0 , & rect , & rect ) ;
}
else
{
pRenderContext - > CopyRenderTargetToTextureEx ( GetFullscreenTexture ( ) , 0 , & rect , & rect ) ;
}
pRenderContext . SafeRelease ( ) ;
m_rbTakeFreezeFrame [ view . m_eStereoEye ] = false ;
}
pRenderContext = materials - > GetRenderContext ( ) ;
pRenderContext - > SetRenderTarget ( saveRenderTarget ) ;
pRenderContext . SafeRelease ( ) ;
// Draw the overlay
if ( m_bDrawOverlay )
{
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " DrawOverlay " ) ;
// This allows us to be ok if there are nested overlay views
CViewSetup currentView = m_CurrentView ;
CViewSetup tempView = m_OverlayViewSetup ;
tempView . fov = ScaleFOVByWidthRatio ( tempView . fov , tempView . m_flAspectRatio / ( 4.0f / 3.0f ) ) ;
tempView . m_bDoBloomAndToneMapping = false ; // FIXME: Hack to get Mark up and running
m_bDrawOverlay = false ;
RenderView ( tempView , m_OverlayClearFlags , m_OverlayDrawFlags ) ;
m_CurrentView = currentView ;
}
}
if ( mat_viewportupscale . GetBool ( ) & & mat_viewportscale . GetFloat ( ) < 1.0f )
{
CMatRenderContextPtr pRenderContext ( materials ) ;
ITexture * pFullFrameFB1 = materials - > FindTexture ( " _rt_FullFrameFB1 " , TEXTURE_GROUP_RENDER_TARGET ) ;
IMaterial * pCopyMaterial = materials - > FindMaterial ( " dev/upscale " , TEXTURE_GROUP_OTHER ) ;
pCopyMaterial - > IncrementReferenceCount ( ) ;
Rect_t DownscaleRect , UpscaleRect ;
DownscaleRect . x = view . x ;
DownscaleRect . y = view . y ;
DownscaleRect . width = view . width ;
DownscaleRect . height = view . height ;
UpscaleRect . x = view . m_nUnscaledX ;
UpscaleRect . y = view . m_nUnscaledY ;
UpscaleRect . width = view . m_nUnscaledWidth ;
UpscaleRect . height = view . m_nUnscaledHeight ;
pRenderContext - > CopyRenderTargetToTextureEx ( pFullFrameFB1 , 0 , & DownscaleRect , & DownscaleRect ) ;
pRenderContext - > DrawScreenSpaceRectangle ( pCopyMaterial , UpscaleRect . x , UpscaleRect . y , UpscaleRect . width , UpscaleRect . height ,
DownscaleRect . x , DownscaleRect . y , DownscaleRect . x + DownscaleRect . width - 1 , DownscaleRect . y + DownscaleRect . height - 1 ,
pFullFrameFB1 - > GetActualWidth ( ) , pFullFrameFB1 - > GetActualHeight ( ) ) ;
pCopyMaterial - > DecrementReferenceCount ( ) ;
}
// if we're in VR mode we might need to override the render target
if ( UseVR ( ) )
{
saveRenderTarget = g_pSourceVR - > GetRenderTarget ( ( ISourceVirtualReality : : VREye ) ( view . m_eStereoEye - 1 ) , ISourceVirtualReality : : RT_Color ) ;
}
// Draw the 2D graphics
render - > Push2DView ( view , 0 , saveRenderTarget , GetFrustum ( ) ) ;
Render2DEffectsPreHUD ( view ) ;
if ( whatToDraw & RENDERVIEW_DRAWHUD )
{
VPROF_BUDGET ( " VGui_DrawHud " , VPROF_BUDGETGROUP_OTHER_VGUI ) ;
int viewWidth = view . m_nUnscaledWidth ;
int viewHeight = view . m_nUnscaledHeight ;
int viewActualWidth = view . m_nUnscaledWidth ;
int viewActualHeight = view . m_nUnscaledHeight ;
int viewX = view . m_nUnscaledX ;
int viewY = view . m_nUnscaledY ;
int viewFramebufferX = 0 ;
int viewFramebufferY = 0 ;
int viewFramebufferWidth = viewWidth ;
int viewFramebufferHeight = viewHeight ;
bool bClear = false ;
bool bPaintMainMenu = false ;
ITexture * pTexture = NULL ;
if ( UseVR ( ) )
{
if ( g_ClientVirtualReality . ShouldRenderHUDInWorld ( ) )
{
pTexture = materials - > FindTexture ( " _rt_gui " , NULL , false ) ;
if ( pTexture )
{
bPaintMainMenu = true ;
bClear = true ;
viewX = 0 ;
viewY = 0 ;
viewActualWidth = pTexture - > GetActualWidth ( ) ;
viewActualHeight = pTexture - > GetActualHeight ( ) ;
vgui : : surface ( ) - > GetScreenSize ( viewWidth , viewHeight ) ;
viewFramebufferX = 0 ;
if ( view . m_eStereoEye = = STEREO_EYE_RIGHT & & ! saveRenderTarget )
viewFramebufferX = viewFramebufferWidth ;
viewFramebufferY = 0 ;
}
}
else
{
viewFramebufferX = view . m_eStereoEye = = STEREO_EYE_RIGHT ? viewWidth : 0 ;
viewFramebufferY = 0 ;
}
}
// Get the render context out of materials to avoid some debug stuff.
// WARNING THIS REQUIRES THE .SafeRelease below or it'll never release the ref
pRenderContext = materials - > GetRenderContext ( ) ;
// clear depth in the backbuffer before we push the render target
if ( bClear )
{
pRenderContext - > ClearBuffers ( false , true , true ) ;
}
// constrain where VGUI can render to the view
pRenderContext - > PushRenderTargetAndViewport ( pTexture , NULL , viewX , viewY , viewActualWidth , viewActualHeight ) ;
// If drawing off-screen, force alpha for that pass
if ( pTexture )
{
pRenderContext - > OverrideAlphaWriteEnable ( true , true ) ;
}
// let vgui know where to render stuff for the forced-to-framebuffer panels
if ( UseVR ( ) )
{
g_pMatSystemSurface - > SetFullscreenViewportAndRenderTarget ( viewFramebufferX , viewFramebufferY , viewFramebufferWidth , viewFramebufferHeight , saveRenderTarget ) ;
}
// clear the render target if we need to
if ( bClear )
{
pRenderContext - > ClearColor4ub ( 0 , 0 , 0 , 0 ) ;
pRenderContext - > ClearBuffers ( true , false ) ;
}
pRenderContext . SafeRelease ( ) ;
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " VGui_DrawHud " , __FUNCTION__ ) ;
// paint the vgui screen
VGui_PreRender ( ) ;
// Make sure the client .dll root panel is at the proper point before doing the "SolveTraverse" calls
vgui : : VPANEL root = enginevgui - > GetPanel ( PANEL_CLIENTDLL ) ;
if ( root ! = 0 )
{
vgui : : ipanel ( ) - > SetSize ( root , viewWidth , viewHeight ) ;
}
// Same for client .dll tools
root = enginevgui - > GetPanel ( PANEL_CLIENTDLL_TOOLS ) ;
if ( root ! = 0 )
{
vgui : : ipanel ( ) - > SetSize ( root , viewWidth , viewHeight ) ;
}
// The crosshair, etc. needs to get at the current setup stuff
AllowCurrentViewAccess ( true ) ;
// Draw the in-game stuff based on the actual viewport being used
render - > VGui_Paint ( PAINT_INGAMEPANELS ) ;
// maybe paint the main menu and cursor too if we're in stereo hud mode
if ( bPaintMainMenu )
render - > VGui_Paint ( PAINT_UIPANELS | PAINT_CURSOR ) ;
AllowCurrentViewAccess ( false ) ;
VGui_PostRender ( ) ;
g_pClientMode - > PostRenderVGui ( ) ;
pRenderContext = materials - > GetRenderContext ( ) ;
if ( pTexture )
{
pRenderContext - > OverrideAlphaWriteEnable ( false , true ) ;
}
pRenderContext - > PopRenderTargetAndViewport ( ) ;
if ( UseVR ( ) )
{
// figure out if we really want to draw the HUD based on freeze cam
C_BasePlayer * pPlayer = C_BasePlayer : : GetLocalPlayer ( ) ;
bool bInFreezeCam = ( pPlayer & & pPlayer - > GetObserverMode ( ) = = OBS_MODE_FREEZECAM ) ;
// draw the HUD after the view model so its "I'm closer" depth queues work right.
if ( ! bInFreezeCam & & g_ClientVirtualReality . ShouldRenderHUDInWorld ( ) )
{
// Now we've rendered the HUD to its texture, actually get it on the screen.
// Since we're drawing it as a 3D object, we need correctly set up frustum, etc.
int ClearFlags = 0 ;
SetupMain3DView ( view , ClearFlags ) ;
// TODO - a bit of a shonky test - basically trying to catch the main menu, the briefing screen, the loadout screen, etc.
bool bTranslucent = ! g_pMatSystemSurface - > IsCursorVisible ( ) ;
g_ClientVirtualReality . RenderHUDQuad ( g_pClientMode - > ShouldBlackoutAroundHUD ( ) , bTranslucent ) ;
CleanupMain3DView ( view ) ;
}
}
pRenderContext - > Flush ( ) ;
pRenderContext . SafeRelease ( ) ;
}
CDebugViewRender : : Draw2DDebuggingInfo ( view ) ;
Render2DEffectsPostHUD ( view ) ;
g_bRenderingView = false ;
// We can no longer use the 'current view' stuff set up in ViewDrawScene
s_bCanAccessCurrentView = false ;
if ( IsPC ( ) )
{
CDebugViewRender : : GenerateOverdrawForTesting ( ) ;
}
render - > PopView ( GetFrustum ( ) ) ;
g_WorldListCache . Flush ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Renders extra 2D effects in derived classes while the 2D view is on the stack
//-----------------------------------------------------------------------------
void CViewRender : : Render2DEffectsPreHUD ( const CViewSetup & view )
{
}
//-----------------------------------------------------------------------------
// Purpose: Renders extra 2D effects in derived classes while the 2D view is on the stack
//-----------------------------------------------------------------------------
void CViewRender : : Render2DEffectsPostHUD ( const CViewSetup & view )
{
}
//-----------------------------------------------------------------------------
//
// NOTE: Below here is all of the stuff that needs to be done for water rendering
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Determines what kind of water we're going to use
//-----------------------------------------------------------------------------
void CViewRender : : DetermineWaterRenderInfo ( const VisibleFogVolumeInfo_t & fogVolumeInfo , WaterRenderInfo_t & info )
{
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " %s " , __FUNCTION__ ) ;
// By default, assume cheap water (even if there's no water in the scene!)
info . m_bCheapWater = true ;
info . m_bRefract = false ;
info . m_bReflect = false ;
info . m_bReflectEntities = false ;
info . m_bDrawWaterSurface = false ;
info . m_bOpaqueWater = true ;
IMaterial * pWaterMaterial = fogVolumeInfo . m_pFogVolumeMaterial ;
if ( ( fogVolumeInfo . m_nVisibleFogVolume = = - 1 ) | | ! pWaterMaterial )
return ;
// Use cheap water if mat_drawwater is set
info . m_bDrawWaterSurface = mat_drawwater . GetBool ( ) ;
if ( ! info . m_bDrawWaterSurface )
{
info . m_bOpaqueWater = false ;
return ;
}
# ifdef _X360
bool bForceExpensive = false ;
# else
bool bForceExpensive = r_waterforceexpensive . GetBool ( ) ;
# endif
bool bForceReflectEntities = r_waterforcereflectentities . GetBool ( ) ;
# ifdef PORTAL
switch ( g_pPortalRender - > ShouldForceCheaperWaterLevel ( ) )
{
case 0 : //force cheap water
info . m_bCheapWater = true ;
return ;
case 1 : //downgrade level to "simple reflection"
bForceExpensive = false ;
case 2 : //downgrade level to "reflect world"
bForceReflectEntities = false ;
default :
break ;
} ;
# endif
// Determine if the water surface is opaque or not
info . m_bOpaqueWater = ! pWaterMaterial - > IsTranslucent ( ) ;
// DX level 70 can't handle anything but cheap water
if ( engine - > GetDXSupportLevel ( ) < 80 )
return ;
bool bForceCheap = false ;
// The material can override the default settings though
IMaterialVar * pForceCheapVar = pWaterMaterial - > FindVar ( " $forcecheap " , NULL , false ) ;
IMaterialVar * pForceExpensiveVar = pWaterMaterial - > FindVar ( " $forceexpensive " , NULL , false ) ;
if ( pForceCheapVar & & pForceCheapVar - > IsDefined ( ) )
{
bForceCheap = ( pForceCheapVar - > GetIntValueFast ( ) ! = 0 ) ;
if ( bForceCheap )
{
bForceExpensive = false ;
}
}
if ( ! bForceCheap & & pForceExpensiveVar & & pForceExpensiveVar - > IsDefined ( ) )
{
bForceExpensive = bForceExpensive | | ( pForceExpensiveVar - > GetIntValueFast ( ) ! = 0 ) ;
}
bool bDebugCheapWater = r_debugcheapwater . GetBool ( ) ;
if ( bDebugCheapWater )
{
Msg ( " Water material: %s dist to water: %f \n forcecheap: %s forceexpensive: %s \n " ,
pWaterMaterial - > GetName ( ) , fogVolumeInfo . m_flDistanceToWater ,
bForceCheap ? " true " : " false " , bForceExpensive ? " true " : " false " ) ;
}
// Unless expensive water is active, reflections are off.
bool bLocalReflection ;
# ifdef _X360
if ( ! r_WaterDrawReflection . GetBool ( ) )
# else
if ( ! bForceExpensive | | ! r_WaterDrawReflection . GetBool ( ) )
# endif
{
bLocalReflection = false ;
}
else
{
IMaterialVar * pReflectTextureVar = pWaterMaterial - > FindVar ( " $reflecttexture " , NULL , false ) ;
bLocalReflection = pReflectTextureVar & & ( pReflectTextureVar - > GetType ( ) = = MATERIAL_VAR_TYPE_TEXTURE ) ;
}
// Brian says FIXME: I disabled cheap water LOD when local specular is specified.
// There are very few places that appear to actually
// take advantage of it (places where water is in the PVS, but outside of LOD range).
// It was 2 hours before code lock, and I had the choice of either doubling fill-rate everywhere
// by making cheap water lod actually work (the water LOD wasn't actually rendering!!!)
// or to just always render the reflection + refraction if there's a local specular specified.
// Note that water LOD *does* work with refract-only water
// Gary says: I'm reverting this change so that water LOD works on dx9 for ep2.
// Check if the water is out of the cheap water LOD range; if so, use cheap water
# ifdef _X360
if ( ! bForceExpensive & & ( bForceCheap | | ( fogVolumeInfo . m_flDistanceToWater > = m_flCheapWaterEndDistance ) ) )
{
return ;
}
# else
if ( ( ( fogVolumeInfo . m_flDistanceToWater > = m_flCheapWaterEndDistance ) & & ! bLocalReflection ) | | bForceCheap )
return ;
# endif
// Get the material that is for the water surface that is visible and check to see
// what render targets need to be rendered, if any.
if ( ! r_WaterDrawRefraction . GetBool ( ) )
{
info . m_bRefract = false ;
}
else
{
IMaterialVar * pRefractTextureVar = pWaterMaterial - > FindVar ( " $refracttexture " , NULL , false ) ;
info . m_bRefract = pRefractTextureVar & & ( pRefractTextureVar - > GetType ( ) = = MATERIAL_VAR_TYPE_TEXTURE ) ;
// Refractive water can be seen through
if ( info . m_bRefract )
{
info . m_bOpaqueWater = false ;
}
}
info . m_bReflect = bLocalReflection ;
if ( info . m_bReflect )
{
if ( bForceReflectEntities )
{
info . m_bReflectEntities = true ;
}
else
{
IMaterialVar * pReflectEntitiesVar = pWaterMaterial - > FindVar ( " $reflectentities " , NULL , false ) ;
info . m_bReflectEntities = pReflectEntitiesVar & & ( pReflectEntitiesVar - > GetIntValueFast ( ) ! = 0 ) ;
}
}
info . m_bCheapWater = ! info . m_bReflect & & ! info . m_bRefract ;
if ( bDebugCheapWater )
{
Warning ( " refract: %s reflect: %s \n " , info . m_bRefract ? " true " : " false " , info . m_bReflect ? " true " : " false " ) ;
}
}
//-----------------------------------------------------------------------------
// Draws the world and all entities
//-----------------------------------------------------------------------------
void CViewRender : : DrawWorldAndEntities ( bool bDrawSkybox , const CViewSetup & viewIn , int nClearFlags , ViewCustomVisibility_t * pCustomVisibility )
{
MDLCACHE_CRITICAL_SECTION ( ) ;
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " %s " , __FUNCTION__ ) ;
VisibleFogVolumeInfo_t fogVolumeInfo ;
# ifdef PORTAL //in portal, we can't use the fog volume for the camera since it's almost never in the same fog volume as what's in front of the portal
if ( g_pPortalRender - > GetViewRecursionLevel ( ) = = 0 )
{
render - > GetVisibleFogVolume ( viewIn . origin , & fogVolumeInfo ) ;
}
else
{
render - > GetVisibleFogVolume ( g_pPortalRender - > GetExitPortalFogOrigin ( ) , & fogVolumeInfo ) ;
}
# else
render - > GetVisibleFogVolume ( viewIn . origin , & fogVolumeInfo ) ;
# endif
WaterRenderInfo_t info ;
DetermineWaterRenderInfo ( fogVolumeInfo , info ) ;
if ( info . m_bCheapWater )
{
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " bCheapWater " ) ;
cplane_t glassReflectionPlane ;
if ( IsReflectiveGlassInView ( viewIn , glassReflectionPlane ) )
{
CRefPtr < CReflectiveGlassView > pGlassReflectionView = new CReflectiveGlassView ( this ) ;
pGlassReflectionView - > Setup ( viewIn , VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR , bDrawSkybox , fogVolumeInfo , info , glassReflectionPlane ) ;
AddViewToScene ( pGlassReflectionView ) ;
CRefPtr < CRefractiveGlassView > pGlassRefractionView = new CRefractiveGlassView ( this ) ;
pGlassRefractionView - > Setup ( viewIn , VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR , bDrawSkybox , fogVolumeInfo , info , glassReflectionPlane ) ;
AddViewToScene ( pGlassRefractionView ) ;
}
CRefPtr < CSimpleWorldView > pNoWaterView = new CSimpleWorldView ( this ) ;
pNoWaterView - > Setup ( viewIn , nClearFlags , bDrawSkybox , fogVolumeInfo , info , pCustomVisibility ) ;
AddViewToScene ( pNoWaterView ) ;
return ;
}
Assert ( ! pCustomVisibility ) ;
// Blat out the visible fog leaf if we're not going to use it
if ( ! r_ForceWaterLeaf . GetBool ( ) )
{
fogVolumeInfo . m_nVisibleFogVolumeLeaf = - 1 ;
}
// We can see water of some sort
if ( ! fogVolumeInfo . m_bEyeInFogVolume )
{
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " CAboveWaterView " ) ;
CRefPtr < CAboveWaterView > pAboveWaterView = new CAboveWaterView ( this ) ;
pAboveWaterView - > Setup ( viewIn , bDrawSkybox , fogVolumeInfo , info ) ;
AddViewToScene ( pAboveWaterView ) ;
}
else
{
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " CUnderWaterView " ) ;
CRefPtr < CUnderWaterView > pUnderWaterView = new CUnderWaterView ( this ) ;
pUnderWaterView - > Setup ( viewIn , bDrawSkybox , fogVolumeInfo , info ) ;
AddViewToScene ( pUnderWaterView ) ;
}
}
//-----------------------------------------------------------------------------
// Pushes a water render target
//-----------------------------------------------------------------------------
static Vector SavedLinearLightMapScale ( - 1 , - 1 , - 1 ) ; // x<0 = no saved scale
static void SetLightmapScaleForWater ( void )
{
if ( g_pMaterialSystemHardwareConfig - > GetHDRType ( ) = = HDR_TYPE_INTEGER )
{
CMatRenderContextPtr pRenderContext ( materials ) ;
SavedLinearLightMapScale = pRenderContext - > GetToneMappingScaleLinear ( ) ;
Vector t25 = SavedLinearLightMapScale ;
t25 * = 0.25 ;
pRenderContext - > SetToneMappingScaleLinear ( t25 ) ;
}
}
//-----------------------------------------------------------------------------
// Returns true if the view plane intersects the water
//-----------------------------------------------------------------------------
bool DoesViewPlaneIntersectWater ( float waterZ , int leafWaterDataID )
{
if ( leafWaterDataID = = - 1 )
return false ;
# ifdef PORTAL //when rendering portal views point/plane intersections just don't cut it.
if ( g_pPortalRender - > GetViewRecursionLevel ( ) ! = 0 )
return g_pPortalRender - > DoesExitPortalViewIntersectWaterPlane ( waterZ , leafWaterDataID ) ;
# endif
CMatRenderContextPtr pRenderContext ( materials ) ;
VMatrix viewMatrix , projectionMatrix , viewProjectionMatrix , inverseViewProjectionMatrix ;
pRenderContext - > GetMatrix ( MATERIAL_VIEW , & viewMatrix ) ;
pRenderContext - > GetMatrix ( MATERIAL_PROJECTION , & projectionMatrix ) ;
MatrixMultiply ( projectionMatrix , viewMatrix , viewProjectionMatrix ) ;
MatrixInverseGeneral ( viewProjectionMatrix , inverseViewProjectionMatrix ) ;
Vector mins , maxs ;
ClearBounds ( mins , maxs ) ;
Vector testPoint [ 4 ] ;
testPoint [ 0 ] . Init ( - 1.0f , - 1.0f , 0.0f ) ;
testPoint [ 1 ] . Init ( - 1.0f , 1.0f , 0.0f ) ;
testPoint [ 2 ] . Init ( 1.0f , - 1.0f , 0.0f ) ;
testPoint [ 3 ] . Init ( 1.0f , 1.0f , 0.0f ) ;
int i ;
bool bAbove = false ;
bool bBelow = false ;
float fudge = 7.0f ;
for ( i = 0 ; i < 4 ; i + + )
{
Vector worldPos ;
Vector3DMultiplyPositionProjective ( inverseViewProjectionMatrix , testPoint [ i ] , worldPos ) ;
AddPointToBounds ( worldPos , mins , maxs ) ;
// Warning( "viewplanez: %f waterZ: %f\n", worldPos.z, waterZ );
if ( worldPos . z + fudge > waterZ )
{
bAbove = true ;
}
if ( worldPos . z - fudge < waterZ )
{
bBelow = true ;
}
}
// early out if the near plane doesn't cross the z plane of the water.
if ( ! ( bAbove & & bBelow ) )
return false ;
Vector vecFudge ( fudge , fudge , fudge ) ;
mins - = vecFudge ;
maxs + = vecFudge ;
// the near plane does cross the z value for the visible water volume. Call into
// the engine to find out if the near plane intersects the water volume.
return render - > DoesBoxIntersectWaterVolume ( mins , maxs , leafWaterDataID ) ;
}
# ifdef PORTAL
//-----------------------------------------------------------------------------
// Purpose: Draw the scene during another draw scene call. We must draw our portals
// after opaques but before translucents, so this ViewDrawScene resets the view
// and doesn't flag the rendering as ended when it ends.
// Input : bDrawSkybox - do we draw the skybox
// &view - the camera view to render from
// nClearFlags - how to clear the buffer
//-----------------------------------------------------------------------------
void CViewRender : : ViewDrawScene_PortalStencil ( const CViewSetup & viewIn , ViewCustomVisibility_t * pCustomVisibility )
{
VPROF ( " CViewRender::ViewDrawScene_PortalStencil " ) ;
CViewSetup view ( viewIn ) ;
// Record old view stats
Vector vecOldOrigin = CurrentViewOrigin ( ) ;
QAngle vecOldAngles = CurrentViewAngles ( ) ;
int iCurrentViewID = g_CurrentViewID ;
bool bDrew3dSkybox = false ;
SkyboxVisibility_t nSkyboxVisible = SKYBOX_NOT_VISIBLE ;
int iClearFlags = 0 ;
Draw3dSkyboxworld_Portal ( view , iClearFlags , bDrew3dSkybox , nSkyboxVisible ) ;
bool drawSkybox = r_skybox . GetBool ( ) ;
if ( bDrew3dSkybox | | ( nSkyboxVisible = = SKYBOX_NOT_VISIBLE ) )
{
drawSkybox = false ;
}
//generate unique view ID's for each stencil view
view_id_t iNewViewID = ( view_id_t ) g_pPortalRender - > GetCurrentViewId ( ) ;
SetupCurrentView ( view . origin , view . angles , ( view_id_t ) iNewViewID ) ;
// update vis data
unsigned int visFlags ;
SetupVis ( view , visFlags , pCustomVisibility ) ;
VisibleFogVolumeInfo_t fogInfo ;
if ( g_pPortalRender - > GetViewRecursionLevel ( ) = = 0 )
{
render - > GetVisibleFogVolume ( view . origin , & fogInfo ) ;
}
else
{
render - > GetVisibleFogVolume ( g_pPortalRender - > GetExitPortalFogOrigin ( ) , & fogInfo ) ;
}
WaterRenderInfo_t waterInfo ;
DetermineWaterRenderInfo ( fogInfo , waterInfo ) ;
if ( waterInfo . m_bCheapWater )
{
cplane_t glassReflectionPlane ;
if ( IsReflectiveGlassInView ( viewIn , glassReflectionPlane ) )
{
CRefPtr < CReflectiveGlassView > pGlassReflectionView = new CReflectiveGlassView ( this ) ;
pGlassReflectionView - > Setup ( viewIn , VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR | VIEW_CLEAR_OBEY_STENCIL , drawSkybox , fogInfo , waterInfo , glassReflectionPlane ) ;
AddViewToScene ( pGlassReflectionView ) ;
CRefPtr < CRefractiveGlassView > pGlassRefractionView = new CRefractiveGlassView ( this ) ;
pGlassRefractionView - > Setup ( viewIn , VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR | VIEW_CLEAR_OBEY_STENCIL , drawSkybox , fogInfo , waterInfo , glassReflectionPlane ) ;
AddViewToScene ( pGlassRefractionView ) ;
}
CSimpleWorldView * pClientView = new CSimpleWorldView ( this ) ;
pClientView - > Setup ( view , VIEW_CLEAR_OBEY_STENCIL , drawSkybox , fogInfo , waterInfo , pCustomVisibility ) ;
AddViewToScene ( pClientView ) ;
SafeRelease ( pClientView ) ;
}
else
{
// We can see water of some sort
if ( ! fogInfo . m_bEyeInFogVolume )
{
CRefPtr < CAboveWaterView > pAboveWaterView = new CAboveWaterView ( this ) ;
pAboveWaterView - > Setup ( viewIn , drawSkybox , fogInfo , waterInfo ) ;
AddViewToScene ( pAboveWaterView ) ;
}
else
{
CRefPtr < CUnderWaterView > pUnderWaterView = new CUnderWaterView ( this ) ;
pUnderWaterView - > Setup ( viewIn , drawSkybox , fogInfo , waterInfo ) ;
AddViewToScene ( pUnderWaterView ) ;
}
}
// Disable fog for the rest of the stuff
DisableFog ( ) ;
CGlowOverlay : : DrawOverlays ( view . m_bCacheFullSceneState ) ;
// Draw rain..
DrawPrecipitation ( ) ;
//prerender version only
// issue the pixel visibility tests
PixelVisibility_EndCurrentView ( ) ;
// Make sure sound doesn't stutter
engine - > Sound_ExtraUpdate ( ) ;
// Debugging info goes over the top
CDebugViewRender : : Draw3DDebuggingInfo ( view ) ;
// Return to the previous view
SetupCurrentView ( vecOldOrigin , vecOldAngles , ( view_id_t ) iCurrentViewID ) ;
g_CurrentViewID = iCurrentViewID ; //just in case the cast to view_id_t screwed up the id #
}
void CViewRender : : Draw3dSkyboxworld_Portal ( const CViewSetup & view , int & nClearFlags , bool & bDrew3dSkybox , SkyboxVisibility_t & nSkyboxVisible , ITexture * pRenderTarget )
{
CRefPtr < CPortalSkyboxView > pSkyView = new CPortalSkyboxView ( this ) ;
if ( ( bDrew3dSkybox = pSkyView - > Setup ( view , & nClearFlags , & nSkyboxVisible , pRenderTarget ) ) = = true )
{
AddViewToScene ( pSkyView ) ;
}
}
# endif //PORTAL
//-----------------------------------------------------------------------------
// Methods related to controlling the cheap water distance
//-----------------------------------------------------------------------------
void CViewRender : : SetCheapWaterStartDistance ( float flCheapWaterStartDistance )
{
m_flCheapWaterStartDistance = flCheapWaterStartDistance ;
}
void CViewRender : : SetCheapWaterEndDistance ( float flCheapWaterEndDistance )
{
m_flCheapWaterEndDistance = flCheapWaterEndDistance ;
}
void CViewRender : : GetWaterLODParams ( float & flCheapWaterStartDistance , float & flCheapWaterEndDistance )
{
flCheapWaterStartDistance = m_flCheapWaterStartDistance ;
flCheapWaterEndDistance = m_flCheapWaterEndDistance ;
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : &view -
// &introData -
//-----------------------------------------------------------------------------
void CViewRender : : ViewDrawScene_Intro ( const CViewSetup & view , int nClearFlags , const IntroData_t & introData )
{
VPROF ( " CViewRender::ViewDrawScene " ) ;
CMatRenderContextPtr pRenderContext ( materials ) ;
// this allows the refract texture to be updated once per *scene* on 360
// (e.g. once for a monitor scene and once for the main scene)
g_viewscene_refractUpdateFrame = gpGlobals - > framecount - 1 ;
// -----------------------------------------------------------------------
// Set the clear color to black since we are going to be adding up things
// in the frame buffer.
// -----------------------------------------------------------------------
// Clear alpha to 255 so that masking with the vortigaunts (0) works properly.
pRenderContext - > ClearColor4ub ( 0 , 0 , 0 , 255 ) ;
// -----------------------------------------------------------------------
// Draw the primary scene and copy it to the first framebuffer texture
// -----------------------------------------------------------------------
unsigned int visFlags ;
// NOTE: We only increment this once since time doesn't move forward.
ParticleMgr ( ) - > IncrementFrameCode ( ) ;
if ( introData . m_bDrawPrimary )
{
CViewSetup playerView ( view ) ;
playerView . origin = introData . m_vecCameraView ;
playerView . angles = introData . m_vecCameraViewAngles ;
if ( introData . m_playerViewFOV )
{
playerView . fov = ScaleFOVByWidthRatio ( introData . m_playerViewFOV , engine - > GetScreenAspectRatio ( ) / ( 4.0f / 3.0f ) ) ;
}
g_pClientShadowMgr - > PreRender ( ) ;
// Shadowed flashlights supported on ps_2_b and up...
if ( r_flashlightdepthtexture . GetBool ( ) )
{
g_pClientShadowMgr - > ComputeShadowDepthTextures ( playerView ) ;
}
SetupCurrentView ( playerView . origin , playerView . angles , VIEW_INTRO_PLAYER ) ;
// Invoke pre-render methods
IGameSystem : : PreRenderAllSystems ( ) ;
// Start view, clear frame/z buffer if necessary
SetupVis ( playerView , visFlags ) ;
render - > Push3DView ( playerView , VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH , NULL , GetFrustum ( ) ) ;
DrawWorldAndEntities ( true /* drawSkybox */ , playerView , VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH ) ;
render - > PopView ( GetFrustum ( ) ) ;
// Free shadow depth textures for use in future view
if ( r_flashlightdepthtexture . GetBool ( ) )
{
g_pClientShadowMgr - > UnlockAllShadowDepthTextures ( ) ;
}
}
else
{
pRenderContext - > ClearBuffers ( true , true ) ;
}
Rect_t actualRect ;
UpdateScreenEffectTexture ( 0 , view . x , view . y , view . width , view . height , false , & actualRect ) ;
g_pClientShadowMgr - > PreRender ( ) ;
// Shadowed flashlights supported on ps_2_b and up...
if ( r_flashlightdepthtexture . GetBool ( ) )
{
g_pClientShadowMgr - > ComputeShadowDepthTextures ( view ) ;
}
// -----------------------------------------------------------------------
// Draw the secondary scene and copy it to the second framebuffer texture
// -----------------------------------------------------------------------
SetupCurrentView ( view . origin , view . angles , VIEW_INTRO_CAMERA ) ;
// Invoke pre-render methods
IGameSystem : : PreRenderAllSystems ( ) ;
// Start view, clear frame/z buffer if necessary
SetupVis ( view , visFlags ) ;
// Clear alpha to 255 so that masking with the vortigaunts (0) works properly.
pRenderContext - > ClearColor4ub ( 0 , 0 , 0 , 255 ) ;
DrawWorldAndEntities ( true /* drawSkybox */ , view , VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH ) ;
UpdateScreenEffectTexture ( 1 , view . x , view . y , view . width , view . height ) ;
// -----------------------------------------------------------------------
// Draw quads on the screen for each screenspace pass.
// -----------------------------------------------------------------------
// Find the material that we use to render the overlays
IMaterial * pOverlayMaterial = materials - > FindMaterial ( " scripted/intro_screenspaceeffect " , TEXTURE_GROUP_OTHER ) ;
IMaterialVar * pModeVar = pOverlayMaterial - > FindVar ( " $mode " , NULL ) ;
IMaterialVar * pAlphaVar = pOverlayMaterial - > FindVar ( " $alpha " , NULL ) ;
pRenderContext - > ClearBuffers ( true , true ) ;
pRenderContext - > MatrixMode ( MATERIAL_VIEW ) ;
pRenderContext - > PushMatrix ( ) ;
pRenderContext - > LoadIdentity ( ) ;
pRenderContext - > MatrixMode ( MATERIAL_PROJECTION ) ;
pRenderContext - > PushMatrix ( ) ;
pRenderContext - > LoadIdentity ( ) ;
int passID ;
for ( passID = 0 ; passID < introData . m_Passes . Count ( ) ; passID + + )
{
const IntroDataBlendPass_t & pass = introData . m_Passes [ passID ] ;
if ( pass . m_Alpha = = 0 )
continue ;
// Pick one of the blend modes for the material.
if ( pass . m_BlendMode > = 0 & & pass . m_BlendMode < = 9 )
{
pModeVar - > SetIntValue ( pass . m_BlendMode ) ;
}
else
{
Assert ( 0 ) ;
}
// Set the alpha value for the material.
pAlphaVar - > SetFloatValue ( pass . m_Alpha ) ;
// Draw a quad for this pass.
ITexture * pTexture = GetFullFrameFrameBufferTexture ( 0 ) ;
pRenderContext - > DrawScreenSpaceRectangle ( pOverlayMaterial , 0 , 0 , view . width , view . height ,
actualRect . x , actualRect . y , actualRect . x + actualRect . width - 1 , actualRect . y + actualRect . height - 1 ,
pTexture - > GetActualWidth ( ) , pTexture - > GetActualHeight ( ) ) ;
}
pRenderContext - > MatrixMode ( MATERIAL_VIEW ) ;
pRenderContext - > PopMatrix ( ) ;
pRenderContext - > MatrixMode ( MATERIAL_PROJECTION ) ;
pRenderContext - > PopMatrix ( ) ;
// Draw the starfield
// FIXME
// blur?
// Disable fog for the rest of the stuff
DisableFog ( ) ;
// Here are the overlays...
CGlowOverlay : : DrawOverlays ( view . m_bCacheFullSceneState ) ;
// issue the pixel visibility tests
PixelVisibility_EndCurrentView ( ) ;
// And here are the screen-space effects
PerformScreenSpaceEffects ( 0 , 0 , view . width , view . height ) ;
// Make sure sound doesn't stutter
engine - > Sound_ExtraUpdate ( ) ;
// Debugging info goes over the top
CDebugViewRender : : Draw3DDebuggingInfo ( view ) ;
// Let the particle manager simulate things that haven't been simulated.
ParticleMgr ( ) - > PostRender ( ) ;
FinishCurrentView ( ) ;
// Free shadow depth textures for use in future view
if ( r_flashlightdepthtexture . GetBool ( ) )
{
g_pClientShadowMgr - > UnlockAllShadowDepthTextures ( ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Sets up scene and renders camera view
// Input : cameraNum -
// &cameraView
// *localPlayer -
// x -
// y -
// width -
// height -
// highend -
// Output : Returns true on success, false on failure.
//-----------------------------------------------------------------------------
bool CViewRender : : DrawOneMonitor ( ITexture * pRenderTarget , int cameraNum , C_PointCamera * pCameraEnt ,
const CViewSetup & cameraView , C_BasePlayer * localPlayer , int x , int y , int width , int height )
{
# ifdef USE_MONITORS
VPROF_INCREMENT_COUNTER ( " cameras rendered " , 1 ) ;
// Setup fog state for the camera.
fogparams_t oldFogParams ;
float flOldZFar = 0.0f ;
bool fogEnabled = pCameraEnt - > IsFogEnabled ( ) ;
CViewSetup monitorView = cameraView ;
fogparams_t * pFogParams = NULL ;
if ( fogEnabled )
{
if ( ! localPlayer )
return false ;
pFogParams = localPlayer - > GetFogParams ( ) ;
// Save old fog data.
oldFogParams = * pFogParams ;
flOldZFar = cameraView . zFar ;
pFogParams - > enable = true ;
pFogParams - > start = pCameraEnt - > GetFogStart ( ) ;
pFogParams - > end = pCameraEnt - > GetFogEnd ( ) ;
pFogParams - > farz = pCameraEnt - > GetFogEnd ( ) ;
pFogParams - > maxdensity = pCameraEnt - > GetFogMaxDensity ( ) ;
unsigned char r , g , b ;
pCameraEnt - > GetFogColor ( r , g , b ) ;
pFogParams - > colorPrimary . SetR ( r ) ;
pFogParams - > colorPrimary . SetG ( g ) ;
pFogParams - > colorPrimary . SetB ( b ) ;
monitorView . zFar = pCameraEnt - > GetFogEnd ( ) ;
}
monitorView . width = width ;
monitorView . height = height ;
monitorView . x = x ;
monitorView . y = y ;
monitorView . origin = pCameraEnt - > GetAbsOrigin ( ) ;
monitorView . angles = pCameraEnt - > GetAbsAngles ( ) ;
monitorView . fov = pCameraEnt - > GetFOV ( ) ;
monitorView . m_bOrtho = false ;
monitorView . m_flAspectRatio = pCameraEnt - > UseScreenAspectRatio ( ) ? 0.0f : 1.0f ;
monitorView . m_bViewToProjectionOverride = false ;
// @MULTICORE (toml 8/11/2006): this should be a renderer....
Frustum frustum ;
render - > Push3DView ( monitorView , VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR , pRenderTarget , ( VPlane * ) frustum ) ;
ViewDrawScene ( false , SKYBOX_2DSKYBOX_VISIBLE , monitorView , 0 , VIEW_MONITOR ) ;
render - > PopView ( frustum ) ;
// Reset the world fog parameters.
if ( fogEnabled )
{
if ( pFogParams )
{
* pFogParams = oldFogParams ;
}
monitorView . zFar = flOldZFar ;
}
# endif // USE_MONITORS
return true ;
}
void CViewRender : : DrawMonitors ( const CViewSetup & cameraView )
{
# ifdef PORTAL
g_pPortalRender - > DrawPortalsToTextures ( this , cameraView ) ;
# endif
# ifdef USE_MONITORS
// Early out if no cameras
C_PointCamera * pCameraEnt = GetPointCameraList ( ) ;
if ( ! pCameraEnt )
return ;
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " %s " , __FUNCTION__ ) ;
# ifdef _DEBUG
g_bRenderingCameraView = true ;
# endif
// FIXME: this should check for the ability to do a render target maybe instead.
// FIXME: shouldn't have to truck through all of the visible entities for this!!!!
ITexture * pCameraTarget = GetCameraTexture ( ) ;
int width = pCameraTarget - > GetActualWidth ( ) ;
int height = pCameraTarget - > GetActualHeight ( ) ;
C_BasePlayer * player = C_BasePlayer : : GetLocalPlayer ( ) ;
int cameraNum ;
for ( cameraNum = 0 ; pCameraEnt ! = NULL ; pCameraEnt = pCameraEnt - > m_pNext )
{
if ( ! pCameraEnt - > IsActive ( ) | | pCameraEnt - > IsDormant ( ) )
continue ;
if ( ! DrawOneMonitor ( pCameraTarget , cameraNum , pCameraEnt , cameraView , player , 0 , 0 , width , height ) )
continue ;
+ + cameraNum ;
}
if ( IsX360 ( ) & & cameraNum > 0 )
{
// resolve render target to system memory texture
// resolving *after* all monitors drawn to ensure a single blit using fastest resolve path
CMatRenderContextPtr pRenderContext ( materials ) ;
pRenderContext - > PushRenderTargetAndViewport ( pCameraTarget ) ;
pRenderContext - > CopyRenderTargetToTextureEx ( pCameraTarget , 0 , NULL , NULL ) ;
pRenderContext - > PopRenderTargetAndViewport ( ) ;
}
# ifdef _DEBUG
g_bRenderingCameraView = false ;
# endif
# endif // USE_MONITORS
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
ClientWorldListInfo_t * ClientWorldListInfo_t : : AllocPooled ( const ClientWorldListInfo_t & exemplar )
{
size_t nBytes = AlignValue ( ( exemplar . m_LeafCount * ( ( sizeof ( LeafIndex_t ) * 2 ) + sizeof ( LeafFogVolume_t ) ) ) , 4096 ) ;
ClientWorldListInfo_t * pResult = gm_Pool . GetObject ( ) ;
byte * pMemory = ( byte * ) pResult - > m_pLeafList ;
if ( pMemory )
{
// Previously allocated, add a reference. Otherwise comes out of GetObject as a new object with a refcount of 1
pResult - > AddRef ( ) ;
}
if ( ! pMemory | | _msize ( pMemory ) < nBytes )
{
pMemory = ( byte * ) realloc ( pMemory , nBytes ) ;
}
pResult - > m_pLeafList = ( LeafIndex_t * ) pMemory ;
pResult - > m_pLeafFogVolume = ( LeafFogVolume_t * ) ( pMemory + exemplar . m_LeafCount * sizeof ( LeafIndex_t ) ) ;
pResult - > m_pActualLeafIndex = ( LeafIndex_t * ) ( ( byte * ) ( pResult - > m_pLeafFogVolume ) + exemplar . m_LeafCount * sizeof ( LeafFogVolume_t ) ) ;
pResult - > m_bPooledAlloc = true ;
return pResult ;
}
bool ClientWorldListInfo_t : : OnFinalRelease ( )
{
if ( m_bPooledAlloc )
{
Assert ( m_pLeafList ) ;
gm_Pool . PutObject ( this ) ;
return false ;
}
return true ;
}
//-----------------------------------------------------------------------------
// Constructor
//-----------------------------------------------------------------------------
CBase3dView : : CBase3dView ( CViewRender * pMainView ) :
m_pMainView ( pMainView ) ,
m_Frustum ( pMainView - > m_Frustum )
{
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : *pEnt -
// Output : int
//-----------------------------------------------------------------------------
VPlane * CBase3dView : : GetFrustum ( )
{
// The frustum is only valid while in a RenderView call.
// @MULTICORE (toml 8/11/2006): reimplement this when ready -- Assert(g_bRenderingView || g_bRenderingCameraView || g_bRenderingScreenshot);
return m_Frustum ;
}
CObjectPool < ClientWorldListInfo_t > ClientWorldListInfo_t : : gm_Pool ;
//-----------------------------------------------------------------------------
// Base class for 3d views
//-----------------------------------------------------------------------------
CRendering3dView : : CRendering3dView ( CViewRender * pMainView ) :
CBase3dView ( pMainView ) ,
m_pWorldRenderList ( NULL ) ,
m_pRenderablesList ( NULL ) ,
m_pWorldListInfo ( NULL ) ,
m_pCustomVisibility ( NULL ) ,
m_DrawFlags ( 0 ) ,
m_ClearFlags ( 0 )
{
}
//-----------------------------------------------------------------------------
// Sort entities in a back-to-front ordering
//-----------------------------------------------------------------------------
void CRendering3dView : : Setup ( const CViewSetup & setup )
{
// @MULTICORE (toml 8/15/2006): don't reset if parameters don't require it. For now, just reset
memcpy ( static_cast < CViewSetup * > ( this ) , & setup , sizeof ( setup ) ) ;
ReleaseLists ( ) ;
m_pRenderablesList = new CClientRenderablesList ;
m_pCustomVisibility = NULL ;
}
//-----------------------------------------------------------------------------
// Sort entities in a back-to-front ordering
//-----------------------------------------------------------------------------
void CRendering3dView : : ReleaseLists ( )
{
SafeRelease ( m_pWorldRenderList ) ;
SafeRelease ( m_pRenderablesList ) ;
SafeRelease ( m_pWorldListInfo ) ;
m_pCustomVisibility = NULL ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CRendering3dView : : SetupRenderablesList ( int viewID )
{
VPROF ( " CViewRender::SetupRenderablesList " ) ;
// Clear the list.
int i ;
for ( i = 0 ; i < RENDER_GROUP_COUNT ; i + + )
{
m_pRenderablesList - > m_RenderGroupCounts [ i ] = 0 ;
}
// Now collate the entities in the leaves.
if ( m_pMainView - > ShouldDrawEntities ( ) )
{
// Precache information used commonly in CollateRenderables
SetupRenderInfo_t setupInfo ;
setupInfo . m_pWorldListInfo = m_pWorldListInfo ;
setupInfo . m_nRenderFrame = m_pMainView - > BuildRenderablesListsNumber ( ) ; // only one incremented?
setupInfo . m_nDetailBuildFrame = m_pMainView - > BuildWorldListsNumber ( ) ; //
setupInfo . m_pRenderList = m_pRenderablesList ;
setupInfo . m_bDrawDetailObjects = g_pClientMode - > ShouldDrawDetailObjects ( ) & & r_DrawDetailProps . GetInt ( ) ;
setupInfo . m_bDrawTranslucentObjects = ( viewID ! = VIEW_SHADOW_DEPTH_TEXTURE ) ;
setupInfo . m_vecRenderOrigin = origin ;
setupInfo . m_vecRenderForward = CurrentViewForward ( ) ;
float fMaxDist = cl_maxrenderable_dist . GetFloat ( ) ;
// Shadowing light typically has a smaller farz than cl_maxrenderable_dist
setupInfo . m_flRenderDistSq = ( viewID = = VIEW_SHADOW_DEPTH_TEXTURE ) ? MIN ( zFar , fMaxDist ) : fMaxDist ;
setupInfo . m_flRenderDistSq * = setupInfo . m_flRenderDistSq ;
ClientLeafSystem ( ) - > BuildRenderablesList ( setupInfo ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Builds lists of things to render in the world, called once per view
//-----------------------------------------------------------------------------
void CRendering3dView : : UpdateRenderablesOpacity ( )
{
// Compute the prop opacity based on the view position and fov zoom scale
float flFactor = 1.0f ;
C_BasePlayer * pLocal = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( pLocal )
{
flFactor = pLocal - > GetFOVDistanceAdjustFactor ( ) ;
}
if ( cl_leveloverview . GetFloat ( ) > 0 )
{
// disable prop fading
flFactor = - 1 ;
}
// When zoomed in, tweak the opacity to stay visible from further away
staticpropmgr - > ComputePropOpacity ( origin , flFactor ) ;
// Build a list of detail props to render
DetailObjectSystem ( ) - > BuildDetailObjectRenderLists ( origin ) ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
// Kinda awkward...three optional parameters at the end...
void CRendering3dView : : BuildWorldRenderLists ( bool bDrawEntities , int iForceViewLeaf /* = -1 */ ,
bool bUseCacheIfEnabled /* = true */ , bool bShadowDepth /* = false */ , float * pReflectionWaterHeight /*= NULL*/ )
{
VPROF_BUDGET ( " BuildWorldRenderLists " , VPROF_BUDGETGROUP_WORLD_RENDERING ) ;
// @MULTICORE (toml 8/18/2006): to address....
extern void UpdateClientRenderableInPVSStatus ( ) ;
UpdateClientRenderableInPVSStatus ( ) ;
Assert ( ! m_pWorldRenderList & & ! m_pWorldListInfo ) ;
m_pMainView - > IncWorldListsNumber ( ) ;
// Override vis data if specified this render, otherwise use default behavior with NULL
VisOverrideData_t * pVisData = ( m_pCustomVisibility & & m_pCustomVisibility - > m_VisData . m_fDistToAreaPortalTolerance ! = FLT_MAX ) ? & m_pCustomVisibility - > m_VisData : NULL ;
bool bUseCache = ( bUseCacheIfEnabled & & r_worldlistcache . GetBool ( ) ) ;
if ( ! bUseCache | | pVisData | | ! g_WorldListCache . Find ( * this , & m_pWorldRenderList , & m_pWorldListInfo ) )
{
// @MULTICORE (toml 8/18/2006): when make parallel, will have to change caching to be atomic, where follow ons receive a pointer to a list that is not yet built
m_pWorldRenderList = render - > CreateWorldList ( ) ;
m_pWorldListInfo = new ClientWorldListInfo_t ;
render - > BuildWorldLists ( m_pWorldRenderList , m_pWorldListInfo ,
( m_pCustomVisibility ) ? m_pCustomVisibility - > m_iForceViewLeaf : iForceViewLeaf ,
pVisData , bShadowDepth , pReflectionWaterHeight ) ;
if ( bUseCache & & ! pVisData )
{
g_WorldListCache . Add ( * this , m_pWorldRenderList , m_pWorldListInfo ) ;
}
}
if ( bDrawEntities )
{
UpdateRenderablesOpacity ( ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Computes the actual world list info based on the render flags
//-----------------------------------------------------------------------------
void CRendering3dView : : PruneWorldListInfo ( )
{
// Drawing everything? Just return the world list info as-is
int nWaterDrawFlags = m_DrawFlags & ( DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER ) ;
if ( nWaterDrawFlags = = ( DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER ) )
{
return ;
}
ClientWorldListInfo_t * pNewInfo ;
// Only allocate memory if actually will draw something
if ( m_pWorldListInfo - > m_LeafCount > 0 & & nWaterDrawFlags )
{
pNewInfo = ClientWorldListInfo_t : : AllocPooled ( * m_pWorldListInfo ) ;
}
else
{
pNewInfo = new ClientWorldListInfo_t ;
}
pNewInfo - > m_ViewFogVolume = m_pWorldListInfo - > m_ViewFogVolume ;
pNewInfo - > m_LeafCount = 0 ;
// Not drawing anything? Then don't bother with renderable lists
if ( nWaterDrawFlags ! = 0 )
{
// Create a sub-list based on the actual leaves being rendered
bool bRenderingUnderwater = ( nWaterDrawFlags & DF_RENDER_UNDERWATER ) ! = 0 ;
for ( int i = 0 ; i < m_pWorldListInfo - > m_LeafCount ; + + i )
{
bool bLeafIsUnderwater = ( m_pWorldListInfo - > m_pLeafFogVolume [ i ] ! = - 1 ) ;
if ( bRenderingUnderwater = = bLeafIsUnderwater )
{
pNewInfo - > m_pLeafList [ pNewInfo - > m_LeafCount ] = m_pWorldListInfo - > m_pLeafList [ i ] ;
pNewInfo - > m_pLeafFogVolume [ pNewInfo - > m_LeafCount ] = m_pWorldListInfo - > m_pLeafFogVolume [ i ] ;
pNewInfo - > m_pActualLeafIndex [ pNewInfo - > m_LeafCount ] = i ;
+ + pNewInfo - > m_LeafCount ;
}
}
}
m_pWorldListInfo - > Release ( ) ;
m_pWorldListInfo = pNewInfo ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
static inline void UpdateBrushModelLightmap ( IClientRenderable * pEnt )
{
model_t * pModel = ( model_t * ) pEnt - > GetModel ( ) ;
render - > UpdateBrushModelLightmap ( pModel , pEnt ) ;
}
void CRendering3dView : : BuildRenderableRenderLists ( int viewID )
{
MDLCACHE_CRITICAL_SECTION ( ) ;
if ( viewID ! = VIEW_SHADOW_DEPTH_TEXTURE )
{
render - > BeginUpdateLightmaps ( ) ;
}
m_pMainView - > IncRenderablesListsNumber ( ) ;
ClientWorldListInfo_t & info = * m_pWorldListInfo ;
// For better sorting, find out the leaf *nearest* to the camera
// and render translucent objects as if they are in that leaf.
if ( m_pMainView - > ShouldDrawEntities ( ) & & ( viewID ! = VIEW_SHADOW_DEPTH_TEXTURE ) )
{
ClientLeafSystem ( ) - > ComputeTranslucentRenderLeaf (
info . m_LeafCount , info . m_pLeafList , info . m_pLeafFogVolume , m_pMainView - > BuildRenderablesListsNumber ( ) , viewID ) ;
}
SetupRenderablesList ( viewID ) ;
if ( viewID = = VIEW_MAIN )
{
StudioStats_FindClosestEntity ( m_pRenderablesList ) ;
}
if ( viewID ! = VIEW_SHADOW_DEPTH_TEXTURE )
{
// update lightmap on brush models if necessary
CClientRenderablesList : : CEntry * pEntities = m_pRenderablesList - > m_RenderGroups [ RENDER_GROUP_OPAQUE_BRUSH ] ;
int nOpaque = m_pRenderablesList - > m_RenderGroupCounts [ RENDER_GROUP_OPAQUE_BRUSH ] ;
int i ;
for ( i = 0 ; i < nOpaque ; + + i )
{
Assert ( pEntities [ i ] . m_TwoPass = = 0 ) ;
UpdateBrushModelLightmap ( pEntities [ i ] . m_pRenderable ) ;
}
// update lightmap on brush models if necessary
pEntities = m_pRenderablesList - > m_RenderGroups [ RENDER_GROUP_TRANSLUCENT_ENTITY ] ;
int nTranslucent = m_pRenderablesList - > m_RenderGroupCounts [ RENDER_GROUP_TRANSLUCENT_ENTITY ] ;
for ( i = 0 ; i < nTranslucent ; + + i )
{
const model_t * pModel = pEntities [ i ] . m_pRenderable - > GetModel ( ) ;
if ( pModel )
{
int nModelType = modelinfo - > GetModelType ( pModel ) ;
if ( nModelType = = mod_brush )
{
UpdateBrushModelLightmap ( pEntities [ i ] . m_pRenderable ) ;
}
}
}
render - > EndUpdateLightmaps ( ) ;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CRendering3dView : : DrawWorld ( float waterZAdjust )
{
VPROF_INCREMENT_COUNTER ( " RenderWorld " , 1 ) ;
VPROF_BUDGET ( " DrawWorld " , VPROF_BUDGETGROUP_WORLD_RENDERING ) ;
if ( ! r_drawopaqueworld . GetBool ( ) )
{
return ;
}
unsigned long engineFlags = BuildEngineDrawWorldListFlags ( m_DrawFlags ) ;
render - > DrawWorldLists ( m_pWorldRenderList , engineFlags , waterZAdjust ) ;
}
CMaterialReference g_material_WriteZ ; //init'ed on by CViewRender::Init()
//-----------------------------------------------------------------------------
// Fakes per-entity clip planes on cards that don't support user clip planes.
// Achieves the effect by drawing an invisible box that writes to the depth buffer
// around the clipped area. It's not perfect, but better than nothing.
//-----------------------------------------------------------------------------
static void DrawClippedDepthBox ( IClientRenderable * pEnt , float * pClipPlane )
{
//#define DEBUG_DRAWCLIPPEDDEPTHBOX //uncomment to draw the depth box as a colorful box
static const int iQuads [ 6 ] [ 5 ] = { { 0 , 4 , 6 , 2 , 0 } , //always an extra copy of first index at end to make some algorithms simpler
{ 3 , 7 , 5 , 1 , 3 } ,
{ 1 , 5 , 4 , 0 , 1 } ,
{ 2 , 6 , 7 , 3 , 2 } ,
{ 0 , 2 , 3 , 1 , 0 } ,
{ 5 , 7 , 6 , 4 , 5 } } ;
static const int iLines [ 12 ] [ 2 ] = { { 0 , 1 } ,
{ 0 , 2 } ,
{ 0 , 4 } ,
{ 1 , 3 } ,
{ 1 , 5 } ,
{ 2 , 3 } ,
{ 2 , 6 } ,
{ 3 , 7 } ,
{ 4 , 6 } ,
{ 4 , 5 } ,
{ 5 , 7 } ,
{ 6 , 7 } } ;
# ifdef DEBUG_DRAWCLIPPEDDEPTHBOX
static const float fColors [ 6 ] [ 3 ] = { { 1.0f , 0.0f , 0.0f } ,
{ 0.0f , 1.0f , 1.0f } ,
{ 0.0f , 1.0f , 0.0f } ,
{ 1.0f , 0.0f , 1.0f } ,
{ 0.0f , 0.0f , 1.0f } ,
{ 1.0f , 1.0f , 0.0f } } ;
# endif
Vector vNormal = * ( Vector * ) pClipPlane ;
float fPlaneDist = pClipPlane [ 3 ] ;
Vector vMins , vMaxs ;
pEnt - > GetRenderBounds ( vMins , vMaxs ) ;
Vector vOrigin = pEnt - > GetRenderOrigin ( ) ;
QAngle qAngles = pEnt - > GetRenderAngles ( ) ;
Vector vForward , vUp , vRight ;
AngleVectors ( qAngles , & vForward , & vRight , & vUp ) ;
Vector vPoints [ 8 ] ;
vPoints [ 0 ] = vOrigin + ( vForward * vMins . x ) + ( vRight * vMins . y ) + ( vUp * vMins . z ) ;
vPoints [ 1 ] = vOrigin + ( vForward * vMaxs . x ) + ( vRight * vMins . y ) + ( vUp * vMins . z ) ;
vPoints [ 2 ] = vOrigin + ( vForward * vMins . x ) + ( vRight * vMaxs . y ) + ( vUp * vMins . z ) ;
vPoints [ 3 ] = vOrigin + ( vForward * vMaxs . x ) + ( vRight * vMaxs . y ) + ( vUp * vMins . z ) ;
vPoints [ 4 ] = vOrigin + ( vForward * vMins . x ) + ( vRight * vMins . y ) + ( vUp * vMaxs . z ) ;
vPoints [ 5 ] = vOrigin + ( vForward * vMaxs . x ) + ( vRight * vMins . y ) + ( vUp * vMaxs . z ) ;
vPoints [ 6 ] = vOrigin + ( vForward * vMins . x ) + ( vRight * vMaxs . y ) + ( vUp * vMaxs . z ) ;
vPoints [ 7 ] = vOrigin + ( vForward * vMaxs . x ) + ( vRight * vMaxs . y ) + ( vUp * vMaxs . z ) ;
int iClipped [ 8 ] ;
float fDists [ 8 ] ;
for ( int i = 0 ; i ! = 8 ; + + i )
{
fDists [ i ] = vPoints [ i ] . Dot ( vNormal ) - fPlaneDist ;
iClipped [ i ] = ( fDists [ i ] > 0.0f ) ? 1 : 0 ;
}
Vector vSplitPoints [ 8 ] [ 8 ] ; //obviously there are only 12 lines, not 64 lines or 64 split points, but the indexing is way easier like this
int iLineStates [ 8 ] [ 8 ] ; //0 = unclipped, 2 = wholly clipped, 3 = first point clipped, 4 = second point clipped
//categorize lines and generate split points where needed
for ( int i = 0 ; i ! = 12 ; + + i )
{
const int * pPoints = iLines [ i ] ;
int iLineState = ( iClipped [ pPoints [ 0 ] ] + iClipped [ pPoints [ 1 ] ] ) ;
if ( iLineState ! = 1 ) //either both points are clipped, or neither are clipped
{
iLineStates [ pPoints [ 0 ] ] [ pPoints [ 1 ] ] =
iLineStates [ pPoints [ 1 ] ] [ pPoints [ 0 ] ] =
iLineState ;
}
else
{
//one point is clipped, the other is not
if ( iClipped [ pPoints [ 0 ] ] = = 1 )
{
//first point was clipped, index 1 has the negative distance
float fInvTotalDist = 1.0f / ( fDists [ pPoints [ 0 ] ] - fDists [ pPoints [ 1 ] ] ) ;
vSplitPoints [ pPoints [ 0 ] ] [ pPoints [ 1 ] ] =
vSplitPoints [ pPoints [ 1 ] ] [ pPoints [ 0 ] ] =
( vPoints [ pPoints [ 1 ] ] * ( fDists [ pPoints [ 0 ] ] * fInvTotalDist ) ) - ( vPoints [ pPoints [ 0 ] ] * ( fDists [ pPoints [ 1 ] ] * fInvTotalDist ) ) ;
Assert ( fabs ( vNormal . Dot ( vSplitPoints [ pPoints [ 0 ] ] [ pPoints [ 1 ] ] ) - fPlaneDist ) < 0.01f ) ;
iLineStates [ pPoints [ 0 ] ] [ pPoints [ 1 ] ] = 3 ;
iLineStates [ pPoints [ 1 ] ] [ pPoints [ 0 ] ] = 4 ;
}
else
{
//second point was clipped, index 0 has the negative distance
float fInvTotalDist = 1.0f / ( fDists [ pPoints [ 1 ] ] - fDists [ pPoints [ 0 ] ] ) ;
vSplitPoints [ pPoints [ 0 ] ] [ pPoints [ 1 ] ] =
vSplitPoints [ pPoints [ 1 ] ] [ pPoints [ 0 ] ] =
( vPoints [ pPoints [ 0 ] ] * ( fDists [ pPoints [ 1 ] ] * fInvTotalDist ) ) - ( vPoints [ pPoints [ 1 ] ] * ( fDists [ pPoints [ 0 ] ] * fInvTotalDist ) ) ;
Assert ( fabs ( vNormal . Dot ( vSplitPoints [ pPoints [ 0 ] ] [ pPoints [ 1 ] ] ) - fPlaneDist ) < 0.01f ) ;
iLineStates [ pPoints [ 0 ] ] [ pPoints [ 1 ] ] = 4 ;
iLineStates [ pPoints [ 1 ] ] [ pPoints [ 0 ] ] = 3 ;
}
}
}
CMatRenderContextPtr pRenderContext ( materials ) ;
# ifdef DEBUG_DRAWCLIPPEDDEPTHBOX
pRenderContext - > Bind ( materials - > FindMaterial ( " debug/debugvertexcolor " , TEXTURE_GROUP_OTHER ) , NULL ) ;
# else
pRenderContext - > Bind ( g_material_WriteZ , NULL ) ;
# endif
CMeshBuilder meshBuilder ;
IMesh * pMesh = pRenderContext - > GetDynamicMesh ( false ) ;
meshBuilder . Begin ( pMesh , MATERIAL_TRIANGLES , 18 ) ; //6 sides, possible one cut per side. Any side is capable of having 3 tri's. Lots of padding for things that aren't possible
//going to draw as a collection of triangles, arranged as a triangle fan on each side
for ( int i = 0 ; i ! = 6 ; + + i )
{
const int * pPoints = iQuads [ i ] ;
//can't start the fan on a wholly clipped line, so seek to one that isn't
int j = 0 ;
do
{
if ( iLineStates [ pPoints [ j ] ] [ pPoints [ j + 1 ] ] ! = 2 ) //at least part of this line will be drawn
break ;
+ + j ;
} while ( j ! = 3 ) ;
if ( j = = 3 ) //not enough lines to even form a triangle
continue ;
float * pStartPoint = 0 ;
float * pTriangleFanPoints [ 4 ] ; //at most, one of our fans will have 5 points total, with the first point being stored separately as pStartPoint
int iTriangleFanPointCount = 1 ; //the switch below creates the first for sure
//figure out how to start the fan
switch ( iLineStates [ pPoints [ j ] ] [ pPoints [ j + 1 ] ] )
{
case 0 : //uncut
pStartPoint = & vPoints [ pPoints [ j ] ] . x ;
pTriangleFanPoints [ 0 ] = & vPoints [ pPoints [ j + 1 ] ] . x ;
break ;
case 4 : //second index was clipped
pStartPoint = & vPoints [ pPoints [ j ] ] . x ;
pTriangleFanPoints [ 0 ] = & vSplitPoints [ pPoints [ j ] ] [ pPoints [ j + 1 ] ] . x ;
break ;
case 3 : //first index was clipped
pStartPoint = & vSplitPoints [ pPoints [ j ] ] [ pPoints [ j + 1 ] ] . x ;
pTriangleFanPoints [ 0 ] = & vPoints [ pPoints [ j + 1 ] ] . x ;
break ;
default :
Assert ( false ) ;
break ;
} ;
for ( + + j ; j ! = 3 ; + + j ) //add end points for the rest of the indices, we're assembling a triangle fan
{
switch ( iLineStates [ pPoints [ j ] ] [ pPoints [ j + 1 ] ] )
{
case 0 : //uncut line, normal endpoint
pTriangleFanPoints [ iTriangleFanPointCount ] = & vPoints [ pPoints [ j + 1 ] ] . x ;
+ + iTriangleFanPointCount ;
break ;
case 2 : //wholly cut line, no endpoint
break ;
case 3 : //first point is clipped, normal endpoint
//special case, adds start and end point
pTriangleFanPoints [ iTriangleFanPointCount ] = & vSplitPoints [ pPoints [ j ] ] [ pPoints [ j + 1 ] ] . x ;
+ + iTriangleFanPointCount ;
pTriangleFanPoints [ iTriangleFanPointCount ] = & vPoints [ pPoints [ j + 1 ] ] . x ;
+ + iTriangleFanPointCount ;
break ;
case 4 : //second point is clipped
pTriangleFanPoints [ iTriangleFanPointCount ] = & vSplitPoints [ pPoints [ j ] ] [ pPoints [ j + 1 ] ] . x ;
+ + iTriangleFanPointCount ;
break ;
default :
Assert ( false ) ;
break ;
} ;
}
//special case endpoints, half-clipped lines have a connecting line between them and the next line (first line in this case)
switch ( iLineStates [ pPoints [ j ] ] [ pPoints [ j + 1 ] ] )
{
case 3 :
case 4 :
pTriangleFanPoints [ iTriangleFanPointCount ] = & vSplitPoints [ pPoints [ j ] ] [ pPoints [ j + 1 ] ] . x ;
+ + iTriangleFanPointCount ;
break ;
} ;
Assert ( iTriangleFanPointCount < = 4 ) ;
//add the fan to the mesh
int iLoopStop = iTriangleFanPointCount - 1 ;
for ( int k = 0 ; k ! = iLoopStop ; + + k )
{
meshBuilder . Position3fv ( pStartPoint ) ;
# ifdef DEBUG_DRAWCLIPPEDDEPTHBOX
float fHalfColors [ 3 ] = { fColors [ i ] [ 0 ] * 0.5f , fColors [ i ] [ 1 ] * 0.5f , fColors [ i ] [ 2 ] * 0.5f } ;
meshBuilder . Color3fv ( fHalfColors ) ;
# endif
meshBuilder . AdvanceVertex ( ) ;
meshBuilder . Position3fv ( pTriangleFanPoints [ k ] ) ;
# ifdef DEBUG_DRAWCLIPPEDDEPTHBOX
meshBuilder . Color3fv ( fColors [ i ] ) ;
# endif
meshBuilder . AdvanceVertex ( ) ;
meshBuilder . Position3fv ( pTriangleFanPoints [ k + 1 ] ) ;
# ifdef DEBUG_DRAWCLIPPEDDEPTHBOX
meshBuilder . Color3fv ( fColors [ i ] ) ;
# endif
meshBuilder . AdvanceVertex ( ) ;
}
}
meshBuilder . End ( ) ;
pMesh - > Draw ( ) ;
pRenderContext - > Flush ( false ) ;
}
//-----------------------------------------------------------------------------
// Draws all opaque renderables in leaves that were rendered
//-----------------------------------------------------------------------------
static inline void DrawOpaqueRenderable ( IClientRenderable * pEnt , bool bTwoPass , ERenderDepthMode DepthMode , int nDefaultFlags = 0 )
{
tmZone ( TELEMETRY_LEVEL0 , TMZF_NONE , " %s " , __FUNCTION__ ) ;
float color [ 3 ] ;
pEnt - > GetColorModulation ( color ) ;
render - > SetColorModulation ( color ) ;
int flags = nDefaultFlags | STUDIO_RENDER ;
if ( bTwoPass )
{
flags | = STUDIO_TWOPASS ;
}
if ( DepthMode = = DEPTH_MODE_SHADOW )
{
flags | = STUDIO_SHADOWDEPTHTEXTURE ;
}
else if ( DepthMode = = DEPTH_MODE_SSA0 )
{
flags | = STUDIO_SSAODEPTHTEXTURE ;
}
float * pRenderClipPlane = NULL ;
if ( r_entityclips . GetBool ( ) )
pRenderClipPlane = pEnt - > GetRenderClipPlane ( ) ;
if ( pRenderClipPlane )
{
CMatRenderContextPtr pRenderContext ( materials ) ;
if ( ! materials - > UsingFastClipping ( ) ) //do NOT change the fast clip plane mid-scene, depth problems result. Regular user clip planes are fine though
pRenderContext - > PushCustomClipPlane ( pRenderClipPlane ) ;
else
DrawClippedDepthBox ( pEnt , pRenderClipPlane ) ;
Assert ( view - > GetCurrentlyDrawingEntity ( ) = = NULL ) ;
view - > SetCurrentlyDrawingEntity ( pEnt - > GetIClientUnknown ( ) - > GetBaseEntity ( ) ) ;
pEnt - > DrawModel ( flags ) ;
view - > SetCurrentlyDrawingEntity ( NULL ) ;
if ( pRenderClipPlane & & ! materials - > UsingFastClipping ( ) )
pRenderContext - > PopCustomClipPlane ( ) ;
}
else
{
Assert ( view - > GetCurrentlyDrawingEntity ( ) = = NULL ) ;
view - > SetCurrentlyDrawingEntity ( pEnt - > GetIClientUnknown ( ) - > GetBaseEntity ( ) ) ;
pEnt - > DrawModel ( flags ) ;
view - > SetCurrentlyDrawingEntity ( NULL ) ;
}
}
//-------------------------------------
ConVar r_drawopaquestaticpropslast ( " r_drawopaquestaticpropslast " , " 0 " , 0 , " Whether opaque static props are rendered after non-npcs " ) ;
# define DEBUG_BUCKETS 0
# if DEBUG_BUCKETS
ConVar r_drawopaque_old ( " r_drawopaque_old " , " 0 " , 0 , " Whether old unbucketed technique is used " ) ;
ConVar r_drawopaquesbucket ( " r_drawopaquesbucket " , " 0 " , FCVAR_CHEAT , " Draw only specific bucket: positive - props, negative - ents " ) ;
ConVar r_drawopaquesbucket_stats ( " r_drawopaquesbucket_stats " , " 0 " , FCVAR_CHEAT , " Draw distribution of props/ents in the buckets " ) ;
# endif
static void SetupBonesOnBaseAnimating ( C_BaseAnimating * & pBaseAnimating )
{
pBaseAnimating - > SetupBones ( NULL , - 1 , - 1 , gpGlobals - > curtime ) ;
}
static void DrawOpaqueRenderables_DrawBrushModels ( CClientRenderablesList : : CEntry * pEntitiesBegin , CClientRenderablesList : : CEntry * pEntitiesEnd , ERenderDepthMode DepthMode )
{
for ( CClientRenderablesList : : CEntry * itEntity = pEntitiesBegin ; itEntity < pEntitiesEnd ; + + itEntity )
{
Assert ( ! itEntity - > m_TwoPass ) ;
DrawOpaqueRenderable ( itEntity - > m_pRenderable , false , DepthMode ) ;
}
}
static void DrawOpaqueRenderables_DrawStaticProps ( CClientRenderablesList : : CEntry * pEntitiesBegin , CClientRenderablesList : : CEntry * pEntitiesEnd , ERenderDepthMode DepthMode )
{
if ( pEntitiesEnd = = pEntitiesBegin )
return ;
float one [ 4 ] = { 1.0f , 1.0f , 1.0f , 1.0f } ;
render - > SetColorModulation ( one ) ;
render - > SetBlend ( 1.0f ) ;
const int MAX_STATICS_PER_BATCH = 512 ;
IClientRenderable * pStatics [ MAX_STATICS_PER_BATCH ] ;
int numScheduled = 0 , numAvailable = MAX_STATICS_PER_BATCH ;
for ( CClientRenderablesList : : CEntry * itEntity = pEntitiesBegin ; itEntity < pEntitiesEnd ; + + itEntity )
{
if ( itEntity - > m_pRenderable )
/**/ ;
else
continue ;
if ( g_pStudioStatsEntity ! = NULL & & g_CurrentViewID = = VIEW_MAIN & & itEntity - > m_pRenderable = = g_pStudioStatsEntity )
{
DrawOpaqueRenderable ( itEntity - > m_pRenderable , false , DepthMode , STUDIO_GENERATE_STATS ) ;
continue ;
}
pStatics [ numScheduled + + ] = itEntity - > m_pRenderable ;
if ( - - numAvailable > 0 )
continue ; // place a hint for compiler to predict more common case in the loop
staticpropmgr - > DrawStaticProps ( pStatics , numScheduled , DepthMode , vcollide_wireframe . GetBool ( ) ) ;
numScheduled = 0 ;
numAvailable = MAX_STATICS_PER_BATCH ;
}
if ( numScheduled )
staticpropmgr - > DrawStaticProps ( pStatics , numScheduled , DepthMode , vcollide_wireframe . GetBool ( ) ) ;
}
static void DrawOpaqueRenderables_Range ( CClientRenderablesList : : CEntry * pEntitiesBegin , CClientRenderablesList : : CEntry * pEntitiesEnd , ERenderDepthMode DepthMode )
{
for ( CClientRenderablesList : : CEntry * itEntity = pEntitiesBegin ; itEntity < pEntitiesEnd ; + + itEntity )
{
if ( itEntity - > m_pRenderable )
DrawOpaqueRenderable ( itEntity - > m_pRenderable , ( itEntity - > m_TwoPass ! = 0 ) , DepthMode ) ;
}
}
void CRendering3dView : : DrawOpaqueRenderables ( ERenderDepthMode DepthMode )
{
VPROF_BUDGET ( " CViewRender::DrawOpaqueRenderables " , " DrawOpaqueRenderables " ) ;
if ( ! r_drawopaquerenderables . GetBool ( ) )
return ;
if ( ! m_pMainView - > ShouldDrawEntities ( ) )
return ;
render - > SetBlend ( 1 ) ;
//
// Prepare to iterate over all leaves that were visible, and draw opaque things in them.
//
RopeManager ( ) - > ResetRenderCache ( ) ;
g_pParticleSystemMgr - > ResetRenderCache ( ) ;
//bool const bDrawopaquestaticpropslast = r_drawopaquestaticpropslast.GetBool();
//
// First do the brush models
//
{
CClientRenderablesList : : CEntry * pEntitiesBegin , * pEntitiesEnd ;
pEntitiesBegin = m_pRenderablesList - > m_RenderGroups [ RENDER_GROUP_OPAQUE_BRUSH ] ;
pEntitiesEnd = pEntitiesBegin + m_pRenderablesList - > m_RenderGroupCounts [ RENDER_GROUP_OPAQUE_BRUSH ] ;
DrawOpaqueRenderables_DrawBrushModels ( pEntitiesBegin , pEntitiesEnd , DepthMode ) ;
}
# if DEBUG_BUCKETS
{
con_nprint_s nxPrn = { 0 } ;
nxPrn . index = 16 ;
nxPrn . time_to_live = - 1 ;
nxPrn . color [ 0 ] = 0.9f , nxPrn . color [ 1 ] = 1.0f , nxPrn . color [ 2 ] = 0.9f ;
nxPrn . fixed_width_font = true ;
engine - > Con_NXPrintf ( & nxPrn , " Draw Opaque Technique : NEW " ) ;
if ( r_drawopaque_old . GetBool ( ) )
{
engine - > Con_NXPrintf ( & nxPrn , " Draw Opaque Technique : OLD " ) ;
// now the static props
{
for ( int bucket = RENDER_GROUP_CFG_NUM_OPAQUE_ENT_BUCKETS - 1 ; bucket - - > 0 ; )
{
CClientRenderablesList : : CEntry
* const pEntitiesBegin = m_pRenderablesList - > m_RenderGroups [ RENDER_GROUP_OPAQUE_STATIC_HUGE + 2 * bucket ] ,
* const pEntitiesEnd = pEntitiesBegin + m_pRenderablesList - > m_RenderGroupCounts [ RENDER_GROUP_OPAQUE_STATIC_HUGE + 2 * bucket ] ;
DrawOpaqueRenderables_DrawStaticProps ( pEntitiesBegin , pEntitiesEnd , bShadowDepth ) ;
}
}
// now the other opaque entities
for ( int bucket = RENDER_GROUP_CFG_NUM_OPAQUE_ENT_BUCKETS - 1 ; bucket - - > 0 ; )
{
CClientRenderablesList : : CEntry
* const pEntitiesBegin = m_pRenderablesList - > m_RenderGroups [ RENDER_GROUP_OPAQUE_ENTITY_HUGE + 2 * bucket ] ,
* const pEntitiesEnd = pEntitiesBegin + m_pRenderablesList - > m_RenderGroupCounts [ RENDER_GROUP_OPAQUE_ENTITY_HUGE + 2 * bucket ] ;
DrawOpaqueRenderables_Range ( pEntitiesBegin , pEntitiesEnd , bShadowDepth ) ;
}
//
// Ropes and particles
//
RopeManager ( ) - > DrawRenderCache ( bShadowDepth ) ;
g_pParticleSystemMgr - > DrawRenderCache ( bShadowDepth ) ;
return ;
}
}
# endif
//
// Sort everything that's not a static prop
//
int numOpaqueEnts = 0 ;
for ( int bucket = 0 ; bucket < RENDER_GROUP_CFG_NUM_OPAQUE_ENT_BUCKETS ; + + bucket )
numOpaqueEnts + = m_pRenderablesList - > m_RenderGroupCounts [ RENDER_GROUP_OPAQUE_ENTITY_HUGE + 2 * bucket ] ;
CUtlVector < C_BaseAnimating * > arrBoneSetupNpcsLast ( ( C_BaseAnimating * * ) _alloca ( numOpaqueEnts * sizeof ( C_BaseAnimating * ) ) , numOpaqueEnts , numOpaqueEnts ) ;
CUtlVector < CClientRenderablesList : : CEntry > arrRenderEntsNpcsFirst ( ( CClientRenderablesList : : CEntry * ) _alloca ( numOpaqueEnts * sizeof ( CClientRenderablesList : : CEntry ) ) , numOpaqueEnts , numOpaqueEnts ) ;
int numNpcs = 0 , numNonNpcsAnimating = 0 ;
for ( int bucket = 0 ; bucket < RENDER_GROUP_CFG_NUM_OPAQUE_ENT_BUCKETS ; + + bucket )
{
for ( CClientRenderablesList : : CEntry
* const pEntitiesBegin = m_pRenderablesList - > m_RenderGroups [ RENDER_GROUP_OPAQUE_ENTITY_HUGE + 2 * bucket ] ,
* const pEntitiesEnd = pEntitiesBegin + m_pRenderablesList - > m_RenderGroupCounts [ RENDER_GROUP_OPAQUE_ENTITY_HUGE + 2 * bucket ] ,
* itEntity = pEntitiesBegin ; itEntity < pEntitiesEnd ; + + itEntity )
{
C_BaseEntity * pEntity = itEntity - > m_pRenderable ? itEntity - > m_pRenderable - > GetIClientUnknown ( ) - > GetBaseEntity ( ) : NULL ;
if ( pEntity )
{
if ( pEntity - > IsNPC ( ) )
{
C_BaseAnimating * pba = assert_cast < C_BaseAnimating * > ( pEntity ) ;
arrRenderEntsNpcsFirst [ numNpcs + + ] = * itEntity ;
arrBoneSetupNpcsLast [ numOpaqueEnts - numNpcs ] = pba ;
itEntity - > m_pRenderable = NULL ; // We will render NPCs separately
itEntity - > m_RenderHandle = NULL ;
continue ;
}
else if ( pEntity - > GetBaseAnimating ( ) )
{
C_BaseAnimating * pba = assert_cast < C_BaseAnimating * > ( pEntity ) ;
arrBoneSetupNpcsLast [ numNonNpcsAnimating + + ] = pba ;
// fall through
}
}
}
}
if ( r_threaded_renderables . GetBool ( ) )
{
ParallelProcess ( " BoneSetupNpcsLast " , arrBoneSetupNpcsLast . Base ( ) + numOpaqueEnts - numNpcs , numNpcs , & SetupBonesOnBaseAnimating ) ;
ParallelProcess ( " BoneSetupNpcsLast NonNPCs " , arrBoneSetupNpcsLast . Base ( ) , numNonNpcsAnimating , & SetupBonesOnBaseAnimating ) ;
}
//
// Draw static props + opaque entities from the biggest bucket to the smallest
//
{
CClientRenderablesList : : CEntry * pEnts [ RENDER_GROUP_CFG_NUM_OPAQUE_ENT_BUCKETS ] [ 2 ] ;
CClientRenderablesList : : CEntry * pProps [ RENDER_GROUP_CFG_NUM_OPAQUE_ENT_BUCKETS ] [ 2 ] ;
for ( int bucket = 0 ; bucket < RENDER_GROUP_CFG_NUM_OPAQUE_ENT_BUCKETS ; + + bucket )
{
pEnts [ bucket ] [ 0 ] = m_pRenderablesList - > m_RenderGroups [ RENDER_GROUP_OPAQUE_ENTITY_HUGE + 2 * bucket ] ;
pEnts [ bucket ] [ 1 ] = pEnts [ bucket ] [ 0 ] + m_pRenderablesList - > m_RenderGroupCounts [ RENDER_GROUP_OPAQUE_ENTITY_HUGE + 2 * bucket ] ;
pProps [ bucket ] [ 0 ] = m_pRenderablesList - > m_RenderGroups [ RENDER_GROUP_OPAQUE_STATIC_HUGE + 2 * bucket ] ;
pProps [ bucket ] [ 1 ] = pProps [ bucket ] [ 0 ] + m_pRenderablesList - > m_RenderGroupCounts [ RENDER_GROUP_OPAQUE_STATIC_HUGE + 2 * bucket ] ;
// Render sequence debugging
# if DEBUG_BUCKETS
if ( r_drawopaquesbucket_stats . GetBool ( ) )
{
con_nprint_s nxPrn = { 0 } ;
nxPrn . index = 20 + bucket * 3 ;
nxPrn . time_to_live = - 1 ;
nxPrn . color [ 0 ] = 0.9f , nxPrn . color [ 1 ] = 1.0f , nxPrn . color [ 2 ] = 0.9f ;
nxPrn . fixed_width_font = true ;
if ( bDrawopaquestaticpropslast )
engine - > Con_NXPrintf ( & nxPrn , " [ %2d ] Ents : %3d " , bucket + 1 , pEnts [ bucket ] [ 1 ] - pEnts [ bucket ] [ 0 ] ) ,
+ + nxPrn . index ,
engine - > Con_NXPrintf ( & nxPrn , " [ %2d ] Props: %3d " , bucket + 1 , pProps [ bucket ] [ 1 ] - pProps [ bucket ] [ 0 ] ) ;
else
engine - > Con_NXPrintf ( & nxPrn , " [ %2d ] Props: %3d " , bucket + 1 , pProps [ bucket ] [ 1 ] - pProps [ bucket ] [ 0 ] ) ,
+ + nxPrn . index ,
engine - > Con_NXPrintf ( & nxPrn , " [ %2d ] Ents : %3d " , bucket + 1 , pEnts [ bucket ] [ 1 ] - pEnts [ bucket ] [ 0 ] ) ;
}
# endif
}
# if DEBUG_BUCKETS
if ( int iBucket = r_drawopaquesbucket . GetInt ( ) )
{
if ( iBucket > 0 & & iBucket < = RENDER_GROUP_CFG_NUM_OPAQUE_ENT_BUCKETS )
{
DrawOpaqueRenderables_Range ( pEnts [ iBucket - 1 ] [ 0 ] , pEnts [ iBucket - 1 ] [ 1 ] , bShadowDepth ) ;
}
if ( iBucket < 0 & & iBucket > = - RENDER_GROUP_CFG_NUM_OPAQUE_ENT_BUCKETS )
{
DrawOpaqueRenderables_DrawStaticProps ( pProps [ - 1 - iBucket ] [ 0 ] , pProps [ - 1 - iBucket ] [ 1 ] , bShadowDepth ) ;
}
}
else
# endif
for ( int bucket = 0 ; bucket < RENDER_GROUP_CFG_NUM_OPAQUE_ENT_BUCKETS ; + + bucket )
{
// PVS-Studio pointed out that the two sides of the if/else were identical. Fixing
// this long-broken behavior would change rendering, so I fixed the code but
// commented out the new behavior. Uncomment the if statement and else block
// when needed.
//if ( bDrawopaquestaticpropslast )
{
DrawOpaqueRenderables_Range ( pEnts [ bucket ] [ 0 ] , pEnts [ bucket ] [ 1 ] , DepthMode ) ;
DrawOpaqueRenderables_DrawStaticProps ( pProps [ bucket ] [ 0 ] , pProps [ bucket ] [ 1 ] , DepthMode ) ;
}
/*else
{
DrawOpaqueRenderables_DrawStaticProps ( pProps [ bucket ] [ 0 ] , pProps [ bucket ] [ 1 ] , DepthMode ) ;
DrawOpaqueRenderables_Range ( pEnts [ bucket ] [ 0 ] , pEnts [ bucket ] [ 1 ] , DepthMode ) ;
} */
}
}
//
// Draw NPCs now
//
DrawOpaqueRenderables_Range ( arrRenderEntsNpcsFirst . Base ( ) , arrRenderEntsNpcsFirst . Base ( ) + numNpcs , DepthMode ) ;
//
// Ropes and particles
//
RopeManager ( ) - > DrawRenderCache ( DepthMode ) ;
g_pParticleSystemMgr - > DrawRenderCache ( DepthMode ) ;
}
//-----------------------------------------------------------------------------
// Renders all translucent world + detail objects in a particular set of leaves
//-----------------------------------------------------------------------------
void CRendering3dView : : DrawTranslucentWorldInLeaves ( bool bShadowDepth )
{
VPROF_BUDGET ( " CViewRender::DrawTranslucentWorldInLeaves " , VPROF_BUDGETGROUP_WORLD_RENDERING ) ;
const ClientWorldListInfo_t & info = * m_pWorldListInfo ;
for ( int iCurLeafIndex = info . m_LeafCount - 1 ; iCurLeafIndex > = 0 ; iCurLeafIndex - - )
{
int nActualLeafIndex = info . m_pActualLeafIndex ? info . m_pActualLeafIndex [ iCurLeafIndex ] : iCurLeafIndex ;
Assert ( nActualLeafIndex ! = INVALID_LEAF_INDEX ) ;
if ( render - > LeafContainsTranslucentSurfaces ( m_pWorldRenderList , nActualLeafIndex , m_DrawFlags ) )
{
// Now draw the surfaces in this leaf
render - > DrawTranslucentSurfaces ( m_pWorldRenderList , nActualLeafIndex , m_DrawFlags , bShadowDepth ) ;
}
}
}
//-----------------------------------------------------------------------------
// Renders all translucent world + detail objects in a particular set of leaves
//-----------------------------------------------------------------------------
void CRendering3dView : : DrawTranslucentWorldAndDetailPropsInLeaves ( int iCurLeafIndex , int iFinalLeafIndex , int nEngineDrawFlags , int & nDetailLeafCount , LeafIndex_t * pDetailLeafList , bool bShadowDepth )
{
VPROF_BUDGET ( " CViewRender::DrawTranslucentWorldAndDetailPropsInLeaves " , VPROF_BUDGETGROUP_WORLD_RENDERING ) ;
const ClientWorldListInfo_t & info = * m_pWorldListInfo ;
for ( ; iCurLeafIndex > = iFinalLeafIndex ; iCurLeafIndex - - )
{
int nActualLeafIndex = info . m_pActualLeafIndex ? info . m_pActualLeafIndex [ iCurLeafIndex ] : iCurLeafIndex ;
Assert ( nActualLeafIndex ! = INVALID_LEAF_INDEX ) ;
if ( render - > LeafContainsTranslucentSurfaces ( m_pWorldRenderList , nActualLeafIndex , nEngineDrawFlags ) )
{
// First draw any queued-up detail props from previously visited leaves
DetailObjectSystem ( ) - > RenderTranslucentDetailObjects ( CurrentViewOrigin ( ) , CurrentViewForward ( ) , CurrentViewRight ( ) , CurrentViewUp ( ) , nDetailLeafCount , pDetailLeafList ) ;
nDetailLeafCount = 0 ;
// Now draw the surfaces in this leaf
render - > DrawTranslucentSurfaces ( m_pWorldRenderList , nActualLeafIndex , nEngineDrawFlags , bShadowDepth ) ;
}
// Queue up detail props that existed in this leaf
if ( ClientLeafSystem ( ) - > ShouldDrawDetailObjectsInLeaf ( info . m_pLeafList [ iCurLeafIndex ] , m_pMainView - > BuildWorldListsNumber ( ) ) )
{
pDetailLeafList [ nDetailLeafCount ] = info . m_pLeafList [ iCurLeafIndex ] ;
+ + nDetailLeafCount ;
}
}
}
//-----------------------------------------------------------------------------
// Renders all translucent entities in the render list
//-----------------------------------------------------------------------------
static inline void DrawTranslucentRenderable ( IClientRenderable * pEnt , bool twoPass , bool bShadowDepth , bool bIgnoreDepth )
{
// Determine blending amount and tell engine
float blend = ( float ) ( pEnt - > GetFxBlend ( ) / 255.0f ) ;
// Totally gone
if ( blend < = 0.0f )
return ;
if ( pEnt - > IgnoresZBuffer ( ) ! = bIgnoreDepth )
return ;
// Tell engine
render - > SetBlend ( blend ) ;
float color [ 3 ] ;
pEnt - > GetColorModulation ( color ) ;
render - > SetColorModulation ( color ) ;
int flags = STUDIO_RENDER | STUDIO_TRANSPARENCY ;
if ( twoPass )
flags | = STUDIO_TWOPASS ;
if ( bShadowDepth )
flags | = STUDIO_SHADOWDEPTHTEXTURE ;
float * pRenderClipPlane = NULL ;
if ( r_entityclips . GetBool ( ) )
pRenderClipPlane = pEnt - > GetRenderClipPlane ( ) ;
if ( pRenderClipPlane )
{
CMatRenderContextPtr pRenderContext ( materials ) ;
if ( ! materials - > UsingFastClipping ( ) ) //do NOT change the fast clip plane mid-scene, depth problems result. Regular user clip planes are fine though
pRenderContext - > PushCustomClipPlane ( pRenderClipPlane ) ;
else
DrawClippedDepthBox ( pEnt , pRenderClipPlane ) ;
Assert ( view - > GetCurrentlyDrawingEntity ( ) = = NULL ) ;
view - > SetCurrentlyDrawingEntity ( pEnt - > GetIClientUnknown ( ) - > GetBaseEntity ( ) ) ;
pEnt - > DrawModel ( flags ) ;
view - > SetCurrentlyDrawingEntity ( NULL ) ;
if ( pRenderClipPlane & & ! materials - > UsingFastClipping ( ) )
pRenderContext - > PopCustomClipPlane ( ) ;
}
else
{
Assert ( view - > GetCurrentlyDrawingEntity ( ) = = NULL ) ;
view - > SetCurrentlyDrawingEntity ( pEnt - > GetIClientUnknown ( ) - > GetBaseEntity ( ) ) ;
pEnt - > DrawModel ( flags ) ;
view - > SetCurrentlyDrawingEntity ( NULL ) ;
}
}
//-----------------------------------------------------------------------------
// Renders all translucent entities in the render list
//-----------------------------------------------------------------------------
void CRendering3dView : : DrawTranslucentRenderablesNoWorld ( bool bInSkybox )
{
VPROF ( " CViewRender::DrawTranslucentRenderablesNoWorld " ) ;
if ( ! m_pMainView - > ShouldDrawEntities ( ) | | ! r_drawtranslucentrenderables . GetBool ( ) )
return ;
// Draw the particle singletons.
DrawParticleSingletons ( bInSkybox ) ;
bool bShadowDepth = ( m_DrawFlags & ( DF_SHADOW_DEPTH_MAP | DF_SSAO_DEPTH_PASS ) ) ! = 0 ;
CClientRenderablesList : : CEntry * pEntities = m_pRenderablesList - > m_RenderGroups [ RENDER_GROUP_TRANSLUCENT_ENTITY ] ;
int iCurTranslucentEntity = m_pRenderablesList - > m_RenderGroupCounts [ RENDER_GROUP_TRANSLUCENT_ENTITY ] - 1 ;
while ( iCurTranslucentEntity > = 0 )
{
IClientRenderable * pRenderable = pEntities [ iCurTranslucentEntity ] . m_pRenderable ;
if ( pRenderable - > UsesPowerOfTwoFrameBufferTexture ( ) )
{
UpdateRefractTexture ( ) ;
}
if ( pRenderable - > UsesFullFrameBufferTexture ( ) )
{
UpdateScreenEffectTexture ( ) ;
}
DrawTranslucentRenderable ( pRenderable , pEntities [ iCurTranslucentEntity ] . m_TwoPass ! = 0 , bShadowDepth , false ) ;
- - iCurTranslucentEntity ;
}
// Reset the blend state.
render - > SetBlend ( 1 ) ;
}
//-----------------------------------------------------------------------------
// Renders all translucent entities in the render list that ignore the Z buffer
//-----------------------------------------------------------------------------
void CRendering3dView : : DrawNoZBufferTranslucentRenderables ( void )
{
VPROF ( " CViewRender::DrawNoZBufferTranslucentRenderables " ) ;
if ( ! m_pMainView - > ShouldDrawEntities ( ) | | ! r_drawtranslucentrenderables . GetBool ( ) )
return ;
bool bShadowDepth = ( m_DrawFlags & ( DF_SHADOW_DEPTH_MAP | DF_SSAO_DEPTH_PASS ) ) ! = 0 ;
CClientRenderablesList : : CEntry * pEntities = m_pRenderablesList - > m_RenderGroups [ RENDER_GROUP_TRANSLUCENT_ENTITY ] ;
int iCurTranslucentEntity = m_pRenderablesList - > m_RenderGroupCounts [ RENDER_GROUP_TRANSLUCENT_ENTITY ] - 1 ;
while ( iCurTranslucentEntity > = 0 )
{
IClientRenderable * pRenderable = pEntities [ iCurTranslucentEntity ] . m_pRenderable ;
if ( pRenderable - > UsesPowerOfTwoFrameBufferTexture ( ) )
{
UpdateRefractTexture ( ) ;
}
if ( pRenderable - > UsesFullFrameBufferTexture ( ) )
{
UpdateScreenEffectTexture ( ) ;
}
DrawTranslucentRenderable ( pRenderable , pEntities [ iCurTranslucentEntity ] . m_TwoPass ! = 0 , bShadowDepth , true ) ;
- - iCurTranslucentEntity ;
}
// Reset the blend state.
render - > SetBlend ( 1 ) ;
}
//-----------------------------------------------------------------------------
// Renders all translucent world, entities, and detail objects in a particular set of leaves
//-----------------------------------------------------------------------------
void CRendering3dView : : DrawTranslucentRenderables ( bool bInSkybox , bool bShadowDepth )
{
const ClientWorldListInfo_t & info = * m_pWorldListInfo ;
# ifdef PORTAL //if we're in the portal mod, we need to make a detour so we can render portal views using stencil areas
if ( ShouldDrawPortals ( ) ) //no recursive stencil views during skybox rendering (although we might be drawing a skybox while already in a recursive stencil view)
{
int iDrawFlagsBackup = m_DrawFlags ;
if ( g_pPortalRender - > DrawPortalsUsingStencils ( ( CViewRender * ) m_pMainView ) ) // @MULTICORE (toml 8/10/2006): remove this hack cast
{
m_DrawFlags = iDrawFlagsBackup ;
//reset visibility
unsigned int iVisFlags = 0 ;
m_pMainView - > SetupVis ( * this , iVisFlags , m_pCustomVisibility ) ;
//recreate drawlists (since I can't find an easy way to backup the originals)
{
SafeRelease ( m_pWorldRenderList ) ;
SafeRelease ( m_pWorldListInfo ) ;
BuildWorldRenderLists ( ( ( m_DrawFlags & DF_DRAW_ENTITITES ) ! = 0 ) , m_pCustomVisibility ? m_pCustomVisibility - > m_iForceViewLeaf : - 1 , false ) ;
AssertMsg ( m_DrawFlags & DF_DRAW_ENTITITES , " It shouldn't be possible to get here if this wasn't set, needs special case investigation " ) ;
for ( int i = m_pRenderablesList - > m_RenderGroupCounts [ RENDER_GROUP_TRANSLUCENT_ENTITY ] ; - - i > = 0 ; )
{
m_pRenderablesList - > m_RenderGroups [ RENDER_GROUP_TRANSLUCENT_ENTITY ] [ i ] . m_pRenderable - > ComputeFxBlend ( ) ;
}
}
if ( r_depthoverlay . GetBool ( ) )
{
CMatRenderContextPtr pRenderContext ( materials ) ;
ITexture * pDepthTex = GetFullFrameDepthTexture ( ) ;
IMaterial * pMaterial = materials - > FindMaterial ( " debug/showz " , TEXTURE_GROUP_OTHER , true ) ;
pMaterial - > IncrementReferenceCount ( ) ;
IMaterialVar * BaseTextureVar = pMaterial - > FindVar ( " $basetexture " , NULL , false ) ;
IMaterialVar * pDepthInAlpha = NULL ;
if ( IsPC ( ) )
{
pDepthInAlpha = pMaterial - > FindVar ( " $ALPHADEPTH " , NULL , false ) ;
pDepthInAlpha - > SetIntValue ( 1 ) ;
}
BaseTextureVar - > SetTextureValue ( pDepthTex ) ;
pRenderContext - > OverrideDepthEnable ( true , false ) ; //don't write to depth, or else we'll never see translucents
pRenderContext - > DrawScreenSpaceQuad ( pMaterial ) ;
pRenderContext - > OverrideDepthEnable ( false , true ) ;
pMaterial - > DecrementReferenceCount ( ) ;
}
}
else
{
//done recursing in, time to go back out and do translucents
CMatRenderContextPtr pRenderContext ( materials ) ;
UpdateFullScreenDepthTexture ( ) ;
}
}
# else
{
//opaques generally write depth, and translucents generally don't.
//So immediately after opaques are done is the best time to snap off the depth buffer to a texture.
switch ( g_CurrentViewID )
{
case VIEW_MAIN :
# ifdef _X360
case VIEW_INTRO_CAMERA :
case VIEW_INTRO_PLAYER :
# endif
UpdateFullScreenDepthTexture ( ) ;
break ;
default :
materials - > GetRenderContext ( ) - > SetFullScreenDepthTextureValidityFlag ( false ) ;
break ;
}
}
# endif
if ( ! r_drawtranslucentworld . GetBool ( ) )
{
DrawTranslucentRenderablesNoWorld ( bInSkybox ) ;
return ;
}
VPROF_BUDGET ( " CViewRender::DrawTranslucentRenderables " , " DrawTranslucentRenderables " ) ;
int iPrevLeaf = info . m_LeafCount - 1 ;
int nDetailLeafCount = 0 ;
LeafIndex_t * pDetailLeafList = ( LeafIndex_t * ) stackalloc ( info . m_LeafCount * sizeof ( LeafIndex_t ) ) ;
// bool bDrawUnderWater = (nFlags & DF_RENDER_UNDERWATER) != 0;
// bool bDrawAboveWater = (nFlags & DF_RENDER_ABOVEWATER) != 0;
// bool bDrawWater = (nFlags & DF_RENDER_WATER) != 0;
// bool bClipSkybox = (nFlags & DF_CLIP_SKYBOX ) != 0;
unsigned long nEngineDrawFlags = BuildEngineDrawWorldListFlags ( m_DrawFlags & ~ DF_DRAWSKYBOX ) ;
DetailObjectSystem ( ) - > BeginTranslucentDetailRendering ( ) ;
if ( m_pMainView - > ShouldDrawEntities ( ) & & r_drawtranslucentrenderables . GetBool ( ) )
{
MDLCACHE_CRITICAL_SECTION ( ) ;
// Draw the particle singletons.
DrawParticleSingletons ( bInSkybox ) ;
CClientRenderablesList : : CEntry * pEntities = m_pRenderablesList - > m_RenderGroups [ RENDER_GROUP_TRANSLUCENT_ENTITY ] ;
int iCurTranslucentEntity = m_pRenderablesList - > m_RenderGroupCounts [ RENDER_GROUP_TRANSLUCENT_ENTITY ] - 1 ;
bool bRenderingWaterRenderTargets = m_DrawFlags & ( DF_RENDER_REFRACTION | DF_RENDER_REFLECTION ) ;
while ( iCurTranslucentEntity > = 0 )
{
// Seek the current leaf up to our current translucent-entity leaf.
int iThisLeaf = pEntities [ iCurTranslucentEntity ] . m_iWorldListInfoLeaf ;
// First draw the translucent parts of the world up to and including those in this leaf
DrawTranslucentWorldAndDetailPropsInLeaves ( iPrevLeaf , iThisLeaf , nEngineDrawFlags , nDetailLeafCount , pDetailLeafList , bShadowDepth ) ;
// We're traversing the leaf list backwards to get the appropriate sort ordering (back to front)
iPrevLeaf = iThisLeaf - 1 ;
// Draw all the translucent entities with this leaf.
int nLeaf = info . m_pLeafList [ iThisLeaf ] ;
bool bDrawDetailProps = ClientLeafSystem ( ) - > ShouldDrawDetailObjectsInLeaf ( nLeaf , m_pMainView - > BuildWorldListsNumber ( ) ) ;
if ( bDrawDetailProps )
{
// Draw detail props up to but not including this leaf
Assert ( nDetailLeafCount > 0 ) ;
- - nDetailLeafCount ;
Assert ( pDetailLeafList [ nDetailLeafCount ] = = nLeaf ) ;
DetailObjectSystem ( ) - > RenderTranslucentDetailObjects ( CurrentViewOrigin ( ) , CurrentViewForward ( ) , CurrentViewRight ( ) , CurrentViewUp ( ) , nDetailLeafCount , pDetailLeafList ) ;
// Draw translucent renderables in the leaf interspersed with detail props
for ( ; pEntities [ iCurTranslucentEntity ] . m_iWorldListInfoLeaf = = iThisLeaf & & iCurTranslucentEntity > = 0 ; - - iCurTranslucentEntity )
{
IClientRenderable * pRenderable = pEntities [ iCurTranslucentEntity ] . m_pRenderable ;
// Draw any detail props in this leaf that's farther than the entity
const Vector & vecRenderOrigin = pRenderable - > GetRenderOrigin ( ) ;
DetailObjectSystem ( ) - > RenderTranslucentDetailObjectsInLeaf ( CurrentViewOrigin ( ) , CurrentViewForward ( ) , CurrentViewRight ( ) , CurrentViewUp ( ) , nLeaf , & vecRenderOrigin ) ;
bool bUsesPowerOfTwoFB = pRenderable - > UsesPowerOfTwoFrameBufferTexture ( ) ;
bool bUsesFullFB = pRenderable - > UsesFullFrameBufferTexture ( ) ;
if ( ( bUsesPowerOfTwoFB | | bUsesFullFB ) & & ! bShadowDepth )
{
if ( bRenderingWaterRenderTargets )
{
continue ;
}
CMatRenderContextPtr pRenderContext ( materials ) ;
ITexture * rt = pRenderContext - > GetRenderTarget ( ) ;
if ( rt & & bUsesFullFB )
{
UpdateScreenEffectTexture ( 0 , 0 , 0 , rt - > GetActualWidth ( ) , rt - > GetActualHeight ( ) , true ) ;
}
else if ( bUsesPowerOfTwoFB )
{
UpdateRefractTexture ( ) ;
}
pRenderContext . SafeRelease ( ) ;
}
// Then draw the translucent renderable
DrawTranslucentRenderable ( pRenderable , ( pEntities [ iCurTranslucentEntity ] . m_TwoPass ! = 0 ) , bShadowDepth , false ) ;
}
// Draw all remaining props in this leaf
DetailObjectSystem ( ) - > RenderTranslucentDetailObjectsInLeaf ( CurrentViewOrigin ( ) , CurrentViewForward ( ) , CurrentViewRight ( ) , CurrentViewUp ( ) , nLeaf , NULL ) ;
}
else
{
// Draw queued up detail props (we know that the list of detail leaves won't include this leaf, since ShouldDrawDetailObjectsInLeaf is false)
// Therefore no fixup on nDetailLeafCount is required as in the above section
DetailObjectSystem ( ) - > RenderTranslucentDetailObjects ( CurrentViewOrigin ( ) , CurrentViewForward ( ) , CurrentViewRight ( ) , CurrentViewUp ( ) , nDetailLeafCount , pDetailLeafList ) ;
for ( ; pEntities [ iCurTranslucentEntity ] . m_iWorldListInfoLeaf = = iThisLeaf & & iCurTranslucentEntity > = 0 ; - - iCurTranslucentEntity )
{
IClientRenderable * pRenderable = pEntities [ iCurTranslucentEntity ] . m_pRenderable ;
bool bUsesPowerOfTwoFB = pRenderable - > UsesPowerOfTwoFrameBufferTexture ( ) ;
bool bUsesFullFB = pRenderable - > UsesFullFrameBufferTexture ( ) ;
if ( ( bUsesPowerOfTwoFB | | bUsesFullFB ) & & ! bShadowDepth )
{
if ( bRenderingWaterRenderTargets )
{
continue ;
}
CMatRenderContextPtr pRenderContext ( materials ) ;
ITexture * rt = pRenderContext - > GetRenderTarget ( ) ;
if ( rt )
{
if ( bUsesFullFB )
{
UpdateScreenEffectTexture ( 0 , 0 , 0 , rt - > GetActualWidth ( ) , rt - > GetActualHeight ( ) , true ) ;
}
else if ( bUsesPowerOfTwoFB )
{
UpdateRefractTexture ( 0 , 0 , rt - > GetActualWidth ( ) , rt - > GetActualHeight ( ) ) ;
}
}
else
{
if ( bUsesPowerOfTwoFB )
{
UpdateRefractTexture ( ) ;
}
}
pRenderContext . SafeRelease ( ) ;
}
DrawTranslucentRenderable ( pRenderable , ( pEntities [ iCurTranslucentEntity ] . m_TwoPass ! = 0 ) , bShadowDepth , false ) ;
}
}
nDetailLeafCount = 0 ;
}
}
// Draw the rest of the surfaces in world leaves
DrawTranslucentWorldAndDetailPropsInLeaves ( iPrevLeaf , 0 , nEngineDrawFlags , nDetailLeafCount , pDetailLeafList , bShadowDepth ) ;
// Draw any queued-up detail props from previously visited leaves
DetailObjectSystem ( ) - > RenderTranslucentDetailObjects ( CurrentViewOrigin ( ) , CurrentViewForward ( ) , CurrentViewRight ( ) , CurrentViewUp ( ) , nDetailLeafCount , pDetailLeafList ) ;
// Reset the blend state.
render - > SetBlend ( 1 ) ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CRendering3dView : : EnableWorldFog ( void )
{
VPROF ( " CViewRender::EnableWorldFog " ) ;
CMatRenderContextPtr pRenderContext ( materials ) ;
fogparams_t * pFogParams = NULL ;
C_BasePlayer * pbp = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( pbp )
{
pFogParams = pbp - > GetFogParams ( ) ;
}
if ( GetFogEnable ( pFogParams ) )
{
float fogColor [ 3 ] ;
GetFogColor ( pFogParams , fogColor ) ;
pRenderContext - > FogMode ( MATERIAL_FOG_LINEAR ) ;
pRenderContext - > FogColor3fv ( fogColor ) ;
pRenderContext - > FogStart ( GetFogStart ( pFogParams ) ) ;
pRenderContext - > FogEnd ( GetFogEnd ( pFogParams ) ) ;
pRenderContext - > FogMaxDensity ( GetFogMaxDensity ( pFogParams ) ) ;
}
else
{
pRenderContext - > FogMode ( MATERIAL_FOG_NONE ) ;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
int CRendering3dView : : GetDrawFlags ( )
{
return m_DrawFlags ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CRendering3dView : : SetFogVolumeState ( const VisibleFogVolumeInfo_t & fogInfo , bool bUseHeightFog )
{
render - > SetFogVolumeState ( fogInfo . m_nVisibleFogVolume , bUseHeightFog ) ;
# ifdef PORTAL
//the idea behind fog shifting is this...
//Normal fog simulates the effect of countless tiny particles between your viewpoint and whatever geometry is rendering.
//But, when rendering to a portal view, there's a large space between the virtual camera and the portal exit surface.
//This space isn't supposed to exist, and therefore has none of the tiny particles that make up fog.
//So, we have to shift fog start/end out to align the distances with the portal exit surface instead of the virtual camera to eliminate fog simulation in the non-space
if ( g_pPortalRender - > GetViewRecursionLevel ( ) = = 0 )
return ; //rendering one of the primary views, do nothing
g_pPortalRender - > ShiftFogForExitPortalView ( ) ;
# endif //#ifdef PORTAL
}
//-----------------------------------------------------------------------------
// Standard 3d skybox view
//-----------------------------------------------------------------------------
SkyboxVisibility_t CSkyboxView : : ComputeSkyboxVisibility ( )
{
return engine - > IsSkyboxVisibleFromPoint ( origin ) ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CSkyboxView : : GetSkyboxFogEnable ( )
{
C_BasePlayer * pbp = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( ! pbp )
{
return false ;
}
CPlayerLocalData * local = & pbp - > m_Local ;
if ( fog_override . GetInt ( ) )
{
if ( fog_enableskybox . GetInt ( ) )
{
return true ;
}
else
{
return false ;
}
}
else
{
return ! ! local - > m_skybox3d . fog . enable ;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CSkyboxView : : Enable3dSkyboxFog ( void )
{
C_BasePlayer * pbp = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( ! pbp )
{
return ;
}
CPlayerLocalData * local = & pbp - > m_Local ;
CMatRenderContextPtr pRenderContext ( materials ) ;
if ( GetSkyboxFogEnable ( ) )
{
float fogColor [ 3 ] ;
GetSkyboxFogColor ( fogColor ) ;
float scale = 1.0f ;
if ( local - > m_skybox3d . scale > 0.0f )
{
scale = 1.0f / local - > m_skybox3d . scale ;
}
pRenderContext - > FogMode ( MATERIAL_FOG_LINEAR ) ;
pRenderContext - > FogColor3fv ( fogColor ) ;
pRenderContext - > FogStart ( GetSkyboxFogStart ( ) * scale ) ;
pRenderContext - > FogEnd ( GetSkyboxFogEnd ( ) * scale ) ;
pRenderContext - > FogMaxDensity ( GetSkyboxFogMaxDensity ( ) ) ;
}
else
{
pRenderContext - > FogMode ( MATERIAL_FOG_NONE ) ;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
sky3dparams_t * CSkyboxView : : PreRender3dSkyboxWorld ( SkyboxVisibility_t nSkyboxVisible )
{
if ( ( nSkyboxVisible ! = SKYBOX_3DSKYBOX_VISIBLE ) & & r_3dsky . GetInt ( ) ! = 2 )
return NULL ;
// render the 3D skybox
if ( ! r_3dsky . GetInt ( ) )
return NULL ;
C_BasePlayer * pbp = C_BasePlayer : : GetLocalPlayer ( ) ;
// No local player object yet...
if ( ! pbp )
return NULL ;
CPlayerLocalData * local = & pbp - > m_Local ;
if ( local - > m_skybox3d . area = = 255 )
return NULL ;
return & local - > m_skybox3d ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CSkyboxView : : DrawInternal ( view_id_t iSkyBoxViewID , bool bInvokePreAndPostRender , ITexture * pRenderTarget , ITexture * pDepthTarget )
{
unsigned char * * areabits = render - > GetAreaBits ( ) ;
unsigned char * savebits ;
unsigned char tmpbits [ 32 ] ;
savebits = * areabits ;
memset ( tmpbits , 0 , sizeof ( tmpbits ) ) ;
// set the sky area bit
tmpbits [ m_pSky3dParams - > area > > 3 ] | = 1 < < ( m_pSky3dParams - > area & 7 ) ;
* areabits = tmpbits ;
// if you can get really close to the skybox geometry it's possible that you'll be able to clip into it
// with this near plane. If so, move it in a bit. It's at 2.0 to give us more precision. That means you
// need to keep the eye position at least 2 * scale away from the geometry in the skybox
zNear = 2.0 ;
zFar = MAX_TRACE_LENGTH ;
// scale origin by sky scale
if ( m_pSky3dParams - > scale > 0 )
{
float scale = 1.0f / m_pSky3dParams - > scale ;
VectorScale ( origin , scale , origin ) ;
}
Enable3dSkyboxFog ( ) ;
VectorAdd ( origin , m_pSky3dParams - > origin , origin ) ;
// BUGBUG: Fix this!!! We shouldn't need to call setup vis for the sky if we're connecting
// the areas. We'd have to mark all the clusters in the skybox area in the PVS of any
// cluster with sky. Then we could just connect the areas to do our vis.
//m_bOverrideVisOrigin could hose us here, so call direct
render - > ViewSetupVis ( false , 1 , & m_pSky3dParams - > origin . Get ( ) ) ;
render - > Push3DView ( ( * this ) , m_ClearFlags , pRenderTarget , GetFrustum ( ) , pDepthTarget ) ;
// Store off view origin and angles
SetupCurrentView ( origin , angles , iSkyBoxViewID ) ;
# if defined( _X360 )
CMatRenderContextPtr pRenderContext ( materials ) ;
pRenderContext - > PushVertexShaderGPRAllocation ( 32 ) ;
pRenderContext . SafeRelease ( ) ;
# endif
// Invoke pre-render methods
if ( bInvokePreAndPostRender )
{
IGameSystem : : PreRenderAllSystems ( ) ;
}
render - > BeginUpdateLightmaps ( ) ;
BuildWorldRenderLists ( true , true , - 1 ) ;
BuildRenderableRenderLists ( iSkyBoxViewID ) ;
render - > EndUpdateLightmaps ( ) ;
g_pClientShadowMgr - > ComputeShadowTextures ( ( * this ) , m_pWorldListInfo - > m_LeafCount , m_pWorldListInfo - > m_pLeafList ) ;
DrawWorld ( 0.0f ) ;
// Iterate over all leaves and render objects in those leaves
DrawOpaqueRenderables ( DEPTH_MODE_NORMAL ) ;
// Iterate over all leaves and render objects in those leaves
DrawTranslucentRenderables ( true , false ) ;
DrawNoZBufferTranslucentRenderables ( ) ;
m_pMainView - > DisableFog ( ) ;
CGlowOverlay : : UpdateSkyOverlays ( zFar , m_bCacheFullSceneState ) ;
PixelVisibility_EndCurrentView ( ) ;
// restore old area bits
* areabits = savebits ;
// Invoke post-render methods
if ( bInvokePreAndPostRender )
{
IGameSystem : : PostRenderAllSystems ( ) ;
FinishCurrentView ( ) ;
}
render - > PopView ( GetFrustum ( ) ) ;
# if defined( _X360 )
pRenderContext . GetFrom ( materials ) ;
pRenderContext - > PopVertexShaderGPRAllocation ( ) ;
# endif
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CSkyboxView : : Setup ( const CViewSetup & view , int * pClearFlags , SkyboxVisibility_t * pSkyboxVisible )
{
BaseClass : : Setup ( view ) ;
// The skybox might not be visible from here
* pSkyboxVisible = ComputeSkyboxVisibility ( ) ;
m_pSky3dParams = PreRender3dSkyboxWorld ( * pSkyboxVisible ) ;
if ( ! m_pSky3dParams )
{
return false ;
}
// At this point, we've cleared everything we need to clear
// The next path will need to clear depth, though.
m_ClearFlags = * pClearFlags ;
* pClearFlags & = ~ ( VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH | VIEW_CLEAR_STENCIL | VIEW_CLEAR_FULL_TARGET ) ;
* pClearFlags | = VIEW_CLEAR_DEPTH ; // Need to clear depth after rednering the skybox
m_DrawFlags = DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER | DF_RENDER_WATER ;
if ( r_skybox . GetBool ( ) )
{
m_DrawFlags | = DF_DRAWSKYBOX ;
}
return true ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CSkyboxView : : Draw ( )
{
VPROF_BUDGET ( " CViewRender::Draw3dSkyboxworld " , " 3D Skybox " ) ;
ITexture * pRTColor = NULL ;
ITexture * pRTDepth = NULL ;
if ( m_eStereoEye ! = STEREO_EYE_MONO )
{
pRTColor = g_pSourceVR - > GetRenderTarget ( ( ISourceVirtualReality : : VREye ) ( m_eStereoEye - 1 ) , ISourceVirtualReality : : RT_Color ) ;
pRTDepth = g_pSourceVR - > GetRenderTarget ( ( ISourceVirtualReality : : VREye ) ( m_eStereoEye - 1 ) , ISourceVirtualReality : : RT_Depth ) ;
}
DrawInternal ( VIEW_3DSKY , true , pRTColor , pRTDepth ) ;
}
# ifdef PORTAL
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
bool CPortalSkyboxView : : Setup ( const CViewSetup & view , int * pClearFlags , SkyboxVisibility_t * pSkyboxVisible , ITexture * pRenderTarget )
{
if ( ! BaseClass : : Setup ( view , pClearFlags , pSkyboxVisible ) )
return false ;
m_pRenderTarget = pRenderTarget ;
return true ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
SkyboxVisibility_t CPortalSkyboxView : : ComputeSkyboxVisibility ( )
{
return g_pPortalRender - > IsSkyboxVisibleFromExitPortal ( ) ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CPortalSkyboxView : : Draw ( )
{
AssertMsg ( ( g_pPortalRender - > GetViewRecursionLevel ( ) ! = 0 ) & & g_pPortalRender - > IsRenderingPortal ( ) , " This is designed for through-portal views. Use the regular skybox drawing code for primary views " ) ;
VPROF_BUDGET ( " CViewRender::Draw3dSkyboxworld_Portal " , " 3D Skybox (portal view) " ) ;
int iCurrentViewID = g_CurrentViewID ;
Frustum FrustumBackup ;
memcpy ( FrustumBackup , GetFrustum ( ) , sizeof ( Frustum ) ) ;
CMatRenderContextPtr pRenderContext ( materials ) ;
bool bClippingEnabled = pRenderContext - > EnableClipping ( false ) ;
//NOTE: doesn't magically map to VIEW_3DSKY at (0,0) like PORTAL_VIEWID maps to VIEW_MAIN
view_id_t iSkyBoxViewID = ( view_id_t ) g_pPortalRender - > GetCurrentSkyboxViewId ( ) ;
bool bInvokePreAndPostRender = ( g_pPortalRender - > ShouldUseStencilsToRenderPortals ( ) = = false ) ;
DrawInternal ( iSkyBoxViewID , bInvokePreAndPostRender , m_pRenderTarget , NULL ) ;
pRenderContext - > EnableClipping ( bClippingEnabled ) ;
memcpy ( GetFrustum ( ) , FrustumBackup , sizeof ( Frustum ) ) ;
render - > OverrideViewFrustum ( FrustumBackup ) ;
g_CurrentViewID = iCurrentViewID ;
}
# endif // PORTAL
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CShadowDepthView : : Setup ( const CViewSetup & shadowViewIn , ITexture * pRenderTarget , ITexture * pDepthTexture )
{
BaseClass : : Setup ( shadowViewIn ) ;
m_pRenderTarget = pRenderTarget ;
m_pDepthTexture = pDepthTexture ;
}
bool DrawingShadowDepthView ( void ) //for easy externing
{
return ( CurrentViewID ( ) = = VIEW_SHADOW_DEPTH_TEXTURE ) ;
}
bool DrawingMainView ( ) //for easy externing
{
return ( CurrentViewID ( ) = = VIEW_MAIN ) ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CShadowDepthView : : Draw ( )
{
VPROF_BUDGET ( " CShadowDepthView::Draw " , VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING ) ;
// Start view
unsigned int visFlags ;
m_pMainView - > SetupVis ( ( * this ) , visFlags ) ; // @MULTICORE (toml 8/9/2006): Portal problem, not sending custom vis down
CMatRenderContextPtr pRenderContext ( materials ) ;
pRenderContext - > ClearColor3ub ( 0xFF , 0xFF , 0xFF ) ;
# if defined( _X360 )
pRenderContext - > PushVertexShaderGPRAllocation ( 112 ) ; //almost all work is done in vertex shaders for depth rendering, max out their threads
# endif
pRenderContext . SafeRelease ( ) ;
if ( IsPC ( ) )
{
render - > Push3DView ( ( * this ) , VIEW_CLEAR_DEPTH , m_pRenderTarget , GetFrustum ( ) , m_pDepthTexture ) ;
}
else if ( IsX360 ( ) )
{
//for the 360, the dummy render target has a separate depth buffer which we Resolve() from afterward
render - > Push3DView ( ( * this ) , VIEW_CLEAR_DEPTH , m_pRenderTarget , GetFrustum ( ) ) ;
}
SetupCurrentView ( origin , angles , VIEW_SHADOW_DEPTH_TEXTURE ) ;
MDLCACHE_CRITICAL_SECTION ( ) ;
{
VPROF_BUDGET ( " BuildWorldRenderLists " , VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING ) ;
BuildWorldRenderLists ( true , - 1 , true , true ) ; // @MULTICORE (toml 8/9/2006): Portal problem, not sending custom vis down
}
{
VPROF_BUDGET ( " BuildRenderableRenderLists " , VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING ) ;
BuildRenderableRenderLists ( CurrentViewID ( ) ) ;
}
engine - > Sound_ExtraUpdate ( ) ; // Make sure sound doesn't stutter
m_DrawFlags = m_pMainView - > GetBaseDrawFlags ( ) | DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER | DF_SHADOW_DEPTH_MAP ; // Don't draw water surface...
{
VPROF_BUDGET ( " DrawWorld " , VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING ) ;
DrawWorld ( 0.0f ) ;
}
// Draw opaque and translucent renderables with appropriate override materials
// OVERRIDE_DEPTH_WRITE is OK with a NULL material pointer
modelrender - > ForcedMaterialOverride ( NULL , OVERRIDE_DEPTH_WRITE ) ;
{
VPROF_BUDGET ( " DrawOpaqueRenderables " , VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING ) ;
DrawOpaqueRenderables ( DEPTH_MODE_SHADOW ) ;
}
modelrender - > ForcedMaterialOverride ( 0 ) ;
m_DrawFlags = 0 ;
pRenderContext . GetFrom ( materials ) ;
if ( IsX360 ( ) )
{
//Resolve() the depth texture here. Before the pop so the copy will recognize that the resolutions are the same
pRenderContext - > CopyRenderTargetToTextureEx ( m_pDepthTexture , - 1 , NULL , NULL ) ;
}
render - > PopView ( GetFrustum ( ) ) ;
# if defined( _X360 )
pRenderContext - > PopVertexShaderGPRAllocation ( ) ;
# endif
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CFreezeFrameView : : Setup ( const CViewSetup & shadowViewIn )
{
BaseClass : : Setup ( shadowViewIn ) ;
KeyValues * pVMTKeyValues = new KeyValues ( " UnlitGeneric " ) ;
pVMTKeyValues - > SetString ( " $basetexture " , IsX360 ( ) ? " _rt_FullFrameFB1 " : " _rt_FullScreen " ) ;
pVMTKeyValues - > SetInt ( " $nocull " , 1 ) ;
pVMTKeyValues - > SetInt ( " $nofog " , 1 ) ;
pVMTKeyValues - > SetInt ( " $ignorez " , 1 ) ;
m_pFreezeFrame . Init ( " FreezeFrame_FullScreen " , TEXTURE_GROUP_OTHER , pVMTKeyValues ) ;
m_pFreezeFrame - > Refresh ( ) ;
m_TranslucentSingleColor . Init ( " debug/debugtranslucentsinglecolor " , TEXTURE_GROUP_OTHER ) ;
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void CFreezeFrameView : : Draw ( void )
{
CMatRenderContextPtr pRenderContext ( materials ) ;
# if defined( _X360 )
pRenderContext - > PushVertexShaderGPRAllocation ( 16 ) ; //max out pixel shader threads
# endif
// we might only need half of the texture if we're rendering in stereo
int nTexX0 = 0 , nTexY0 = 0 ;
int nTexX1 = width , nTexY1 = height ;
int nTexWidth = width , nTexHeight = height ;
switch ( m_eStereoEye )
{
case STEREO_EYE_LEFT :
nTexX1 = width ;
nTexWidth * = 2 ;
break ;
case STEREO_EYE_RIGHT :
nTexX0 = width ;
nTexX1 = width * 2 ;
nTexWidth * = 2 ;
break ;
}
pRenderContext - > DrawScreenSpaceRectangle ( m_pFreezeFrame , x , y , width , height ,
nTexX0 , nTexY0 , nTexX1 - 1 , nTexY1 - 1 , nTexWidth , nTexHeight ) ;
//Fake a fade during freezeframe view.
if ( g_flFreezeFlash > = gpGlobals - > curtime & & engine - > IsTakingScreenshot ( ) = = false )
{
// Overlay screen fade on entire screen
IMaterial * pMaterial = m_TranslucentSingleColor ;
int iFadeAlpha = FREEZECAM_SNAPSHOT_FADE_SPEED * ( g_flFreezeFlash - gpGlobals - > curtime ) ;
iFadeAlpha = MIN ( iFadeAlpha , 255 ) ;
iFadeAlpha = MAX ( 0 , iFadeAlpha ) ;
pMaterial - > AlphaModulate ( iFadeAlpha * ( 1.0f / 255.0f ) ) ;
pMaterial - > ColorModulate ( 1.0f , 1.0f , 1.0f ) ;
pMaterial - > SetMaterialVarFlag ( MATERIAL_VAR_IGNOREZ , true ) ;
pRenderContext - > DrawScreenSpaceRectangle ( pMaterial , x , y , width , height , 0 , 0 , width - 1 , height - 1 , width , height ) ;
}
# if defined( _X360 )
pRenderContext - > PopVertexShaderGPRAllocation ( ) ;
# endif
}
//-----------------------------------------------------------------------------
// Pops a water render target
//-----------------------------------------------------------------------------
bool CBaseWorldView : : AdjustView ( float waterHeight )
{
if ( m_DrawFlags & DF_RENDER_REFRACTION )
{
ITexture * pTexture = GetWaterRefractionTexture ( ) ;
// Use the aspect ratio of the main view! So, don't recompute it here
x = y = 0 ;
width = pTexture - > GetActualWidth ( ) ;
height = pTexture - > GetActualHeight ( ) ;
return true ;
}
if ( m_DrawFlags & DF_RENDER_REFLECTION )
{
ITexture * pTexture = GetWaterReflectionTexture ( ) ;
// If the main view is overriding the projection matrix (for Stereo or
// some other nefarious purpose) make sure to include any Y offset in
// the custom projection matrix in our reflected overridden projection
// matrix.
if ( m_bViewToProjectionOverride )
{
m_ViewToProjection [ 1 ] [ 2 ] = - m_ViewToProjection [ 1 ] [ 2 ] ;
}
// Use the aspect ratio of the main view! So, don't recompute it here
x = y = 0 ;
width = pTexture - > GetActualWidth ( ) ;
height = pTexture - > GetActualHeight ( ) ;
angles [ 0 ] = - angles [ 0 ] ;
angles [ 2 ] = - angles [ 2 ] ;
origin [ 2 ] - = 2.0f * ( origin [ 2 ] - ( waterHeight ) ) ;
return true ;
}
return false ;
}
//-----------------------------------------------------------------------------
// Pops a water render target
//-----------------------------------------------------------------------------
void CBaseWorldView : : PushView ( float waterHeight )
{
float spread = 2.0f ;
if ( m_DrawFlags & DF_FUDGE_UP )
{
waterHeight + = spread ;
}
else
{
waterHeight - = spread ;
}
MaterialHeightClipMode_t clipMode = MATERIAL_HEIGHTCLIPMODE_DISABLE ;
if ( ( m_DrawFlags & DF_CLIP_Z ) & & mat_clipz . GetBool ( ) )
{
if ( m_DrawFlags & DF_CLIP_BELOW )
{
clipMode = MATERIAL_HEIGHTCLIPMODE_RENDER_ABOVE_HEIGHT ;
}
else
{
clipMode = MATERIAL_HEIGHTCLIPMODE_RENDER_BELOW_HEIGHT ;
}
}
CMatRenderContextPtr pRenderContext ( materials ) ;
if ( m_DrawFlags & DF_RENDER_REFRACTION )
{
pRenderContext - > SetFogZ ( waterHeight ) ;
pRenderContext - > SetHeightClipZ ( waterHeight ) ;
pRenderContext - > SetHeightClipMode ( clipMode ) ;
// Have to re-set up the view since we reset the size
render - > Push3DView ( * this , m_ClearFlags , GetWaterRefractionTexture ( ) , GetFrustum ( ) ) ;
return ;
}
if ( m_DrawFlags & DF_RENDER_REFLECTION )
{
ITexture * pTexture = GetWaterReflectionTexture ( ) ;
pRenderContext - > SetFogZ ( waterHeight ) ;
bool bSoftwareUserClipPlane = g_pMaterialSystemHardwareConfig - > UseFastClipping ( ) ;
if ( bSoftwareUserClipPlane & & ( origin [ 2 ] > waterHeight - r_eyewaterepsilon . GetFloat ( ) ) )
{
waterHeight = origin [ 2 ] + r_eyewaterepsilon . GetFloat ( ) ;
}
pRenderContext - > SetHeightClipZ ( waterHeight ) ;
pRenderContext - > SetHeightClipMode ( clipMode ) ;
render - > Push3DView ( * this , m_ClearFlags , pTexture , GetFrustum ( ) ) ;
SetLightmapScaleForWater ( ) ;
return ;
}
if ( m_ClearFlags & ( VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR | VIEW_CLEAR_STENCIL ) )
{
if ( m_ClearFlags & VIEW_CLEAR_OBEY_STENCIL )
{
pRenderContext - > ClearBuffersObeyStencil ( m_ClearFlags & VIEW_CLEAR_COLOR , m_ClearFlags & VIEW_CLEAR_DEPTH ) ;
}
else
{
pRenderContext - > ClearBuffers ( m_ClearFlags & VIEW_CLEAR_COLOR , m_ClearFlags & VIEW_CLEAR_DEPTH , m_ClearFlags & VIEW_CLEAR_STENCIL ) ;
}
}
pRenderContext - > SetHeightClipMode ( clipMode ) ;
if ( clipMode ! = MATERIAL_HEIGHTCLIPMODE_DISABLE )
{
pRenderContext - > SetHeightClipZ ( waterHeight ) ;
}
}
//-----------------------------------------------------------------------------
// Pops a water render target
//-----------------------------------------------------------------------------
void CBaseWorldView : : PopView ( )
{
CMatRenderContextPtr pRenderContext ( materials ) ;
pRenderContext - > SetHeightClipMode ( MATERIAL_HEIGHTCLIPMODE_DISABLE ) ;
if ( m_DrawFlags & ( DF_RENDER_REFRACTION | DF_RENDER_REFLECTION ) )
{
if ( IsX360 ( ) )
{
// these renders paths used their surfaces, so blit their results
if ( m_DrawFlags & DF_RENDER_REFRACTION )
{
pRenderContext - > CopyRenderTargetToTextureEx ( GetWaterRefractionTexture ( ) , NULL , NULL ) ;
}
if ( m_DrawFlags & DF_RENDER_REFLECTION )
{
pRenderContext - > CopyRenderTargetToTextureEx ( GetWaterReflectionTexture ( ) , NULL , NULL ) ;
}
}
render - > PopView ( GetFrustum ( ) ) ;
if ( SavedLinearLightMapScale . x > = 0 )
{
pRenderContext - > SetToneMappingScaleLinear ( SavedLinearLightMapScale ) ;
SavedLinearLightMapScale . x = - 1 ;
}
}
}
//-----------------------------------------------------------------------------
// Draws the world + entities
//-----------------------------------------------------------------------------
void CBaseWorldView : : DrawSetup ( float waterHeight , int nSetupFlags , float waterZAdjust , int iForceViewLeaf )
{
int savedViewID = g_CurrentViewID ;
g_CurrentViewID = VIEW_ILLEGAL ;
bool bViewChanged = AdjustView ( waterHeight ) ;
if ( bViewChanged )
{
render - > Push3DView ( * this , 0 , NULL , GetFrustum ( ) ) ;
}
render - > BeginUpdateLightmaps ( ) ;
bool bDrawEntities = ( nSetupFlags & DF_DRAW_ENTITITES ) ! = 0 ;
bool bDrawReflection = ( nSetupFlags & DF_RENDER_REFLECTION ) ! = 0 ;
BuildWorldRenderLists ( bDrawEntities , iForceViewLeaf , true , false , bDrawReflection ? & waterHeight : NULL ) ;
PruneWorldListInfo ( ) ;
if ( bDrawEntities )
{
BuildRenderableRenderLists ( savedViewID ) ;
}
render - > EndUpdateLightmaps ( ) ;
if ( bViewChanged )
{
render - > PopView ( GetFrustum ( ) ) ;
}
# ifdef TF_CLIENT_DLL
bool bVisionOverride = ( localplayer_visionflags . GetInt ( ) & ( 0x01 ) ) ; // Pyro-vision Goggles
if ( savedViewID = = VIEW_MAIN & & bVisionOverride & & pyro_dof . GetBool ( ) )
{
SSAO_DepthPass ( ) ;
}
# endif
g_CurrentViewID = savedViewID ;
}
void MaybeInvalidateLocalPlayerAnimation ( )
{
C_BasePlayer * pPlayer = C_BasePlayer : : GetLocalPlayer ( ) ;
if ( ( pPlayer ! = NULL ) & & pPlayer - > InFirstPersonView ( ) )
{
// We sometimes need different animation for the main view versus the shadow rendering,
// so we need to reset the cache to ensure this actually happens.
pPlayer - > InvalidateBoneCache ( ) ;
C_BaseCombatWeapon * pWeapon = pPlayer - > GetActiveWeapon ( ) ;
if ( pWeapon ! = NULL )
{
pWeapon - > InvalidateBoneCache ( ) ;
}
# if defined USES_ECON_ITEMS
// ...and all the things you're wearing/holding/etc
int NumWearables = pPlayer - > GetNumWearables ( ) ;
for ( int i = 0 ; i < NumWearables ; + + i )
{
CEconWearable * pItem = pPlayer - > GetWearable ( i ) ;
if ( pItem ! = NULL )
{
pItem - > InvalidateBoneCache ( ) ;
}
}
# endif // USES_ECON_ITEMS
}
}
void CBaseWorldView : : DrawExecute ( float waterHeight , view_id_t viewID , float waterZAdjust )
{
int savedViewID = g_CurrentViewID ;
// @MULTICORE (toml 8/16/2006): rethink how, where, and when this is done...
g_CurrentViewID = VIEW_SHADOW_DEPTH_TEXTURE ;
MaybeInvalidateLocalPlayerAnimation ( ) ;
g_pClientShadowMgr - > ComputeShadowTextures ( * this , m_pWorldListInfo - > m_LeafCount , m_pWorldListInfo - > m_pLeafList ) ;
MaybeInvalidateLocalPlayerAnimation ( ) ;
// Make sure sound doesn't stutter
engine - > Sound_ExtraUpdate ( ) ;
g_CurrentViewID = viewID ;
// Update our render view flags.
int iDrawFlagsBackup = m_DrawFlags ;
m_DrawFlags | = m_pMainView - > GetBaseDrawFlags ( ) ;
PushView ( waterHeight ) ;
CMatRenderContextPtr pRenderContext ( materials ) ;
# if defined( _X360 )
pRenderContext - > PushVertexShaderGPRAllocation ( 32 ) ;
# endif
ITexture * pSaveFrameBufferCopyTexture = pRenderContext - > GetFrameBufferCopyTexture ( 0 ) ;
if ( engine - > GetDXSupportLevel ( ) > = 80 )
{
pRenderContext - > SetFrameBufferCopyTexture ( GetPowerOfTwoFrameBufferTexture ( ) ) ;
}
pRenderContext . SafeRelease ( ) ;
ERenderDepthMode DepthMode = DEPTH_MODE_NORMAL ;
if ( m_DrawFlags & DF_DRAW_ENTITITES )
{
DrawWorld ( waterZAdjust ) ;
DrawOpaqueRenderables ( DepthMode ) ;
# ifdef TF_CLIENT_DLL
bool bVisionOverride = ( localplayer_visionflags . GetInt ( ) & ( 0x01 ) ) ; // Pyro-vision Goggles
if ( g_CurrentViewID = = VIEW_MAIN & & bVisionOverride & & pyro_dof . GetBool ( ) ) // Pyro-vision Goggles
{
DrawDepthOfField ( ) ;
}
# endif
DrawTranslucentRenderables ( false , false ) ;
DrawNoZBufferTranslucentRenderables ( ) ;
}
else
{
DrawWorld ( waterZAdjust ) ;
# ifdef TF_CLIENT_DLL
bool bVisionOverride = ( localplayer_visionflags . GetInt ( ) & ( 0x01 ) ) ; // Pyro-vision Goggles
if ( g_CurrentViewID = = VIEW_MAIN & & bVisionOverride & & pyro_dof . GetBool ( ) ) // Pyro-vision Goggles
{
DrawDepthOfField ( ) ;
}
# endif
// Draw translucent world brushes only, no entities
DrawTranslucentWorldInLeaves ( false ) ;
}
// issue the pixel visibility tests for sub-views
if ( ! IsMainView ( CurrentViewID ( ) ) & & CurrentViewID ( ) ! = VIEW_INTRO_CAMERA )
{
PixelVisibility_EndCurrentView ( ) ;
}
pRenderContext . GetFrom ( materials ) ;
pRenderContext - > SetFrameBufferCopyTexture ( pSaveFrameBufferCopyTexture ) ;
PopView ( ) ;
m_DrawFlags = iDrawFlagsBackup ;
g_CurrentViewID = savedViewID ;
# if defined( _X360 )
pRenderContext - > PopVertexShaderGPRAllocation ( ) ;
# endif
}
void CBaseWorldView : : SSAO_DepthPass ( )
{
if ( ! g_pMaterialSystemHardwareConfig - > SupportsPixelShaders_2_0 ( ) )
{
return ;
}
# if 1
VPROF_BUDGET ( " CSimpleWorldView::SSAO_DepthPass " , VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING ) ;
int savedViewID = g_CurrentViewID ;
g_CurrentViewID = VIEW_SSAO ;
ITexture * pSSAO = materials - > FindTexture ( " _rt_ResolvedFullFrameDepth " , TEXTURE_GROUP_RENDER_TARGET ) ;
CMatRenderContextPtr pRenderContext ( materials ) ;
pRenderContext - > ClearColor4ub ( 255 , 255 , 255 , 255 ) ;
# if defined( _X360 )
Assert ( 0 ) ; // rebalance this if we ever use this on 360
pRenderContext - > PushVertexShaderGPRAllocation ( 112 ) ; //almost all work is done in vertex shaders for depth rendering, max out their threads
# endif
pRenderContext . SafeRelease ( ) ;
if ( IsPC ( ) )
{
render - > Push3DView ( ( * this ) , VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR , pSSAO , GetFrustum ( ) ) ;
}
else if ( IsX360 ( ) )
{
render - > Push3DView ( ( * this ) , VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR , pSSAO , GetFrustum ( ) ) ;
}
MDLCACHE_CRITICAL_SECTION ( ) ;
engine - > Sound_ExtraUpdate ( ) ; // Make sure sound doesn't stutter
m_DrawFlags | = DF_SSAO_DEPTH_PASS ;
{
VPROF_BUDGET ( " DrawWorld " , VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING ) ;
DrawWorld ( 0.0f ) ;
}
// Draw opaque and translucent renderables with appropriate override materials
// OVERRIDE_SSAO_DEPTH_WRITE is OK with a NULL material pointer
modelrender - > ForcedMaterialOverride ( NULL , OVERRIDE_SSAO_DEPTH_WRITE ) ;
{
VPROF_BUDGET ( " DrawOpaqueRenderables " , VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING ) ;
DrawOpaqueRenderables ( DEPTH_MODE_SSA0 ) ;
}
#if 0
if ( m_bRenderFlashlightDepthTranslucents | | r_flashlightdepth_drawtranslucents . GetBool ( ) )
{
VPROF_BUDGET ( " DrawTranslucentRenderables " , VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING ) ;
DrawTranslucentRenderables ( false , true ) ;
}
# endif
modelrender - > ForcedMaterialOverride ( 0 ) ;
m_DrawFlags & = ~ DF_SSAO_DEPTH_PASS ;
pRenderContext . GetFrom ( materials ) ;
if ( IsX360 ( ) )
{
//Resolve() the depth texture here. Before the pop so the copy will recognize that the resolutions are the same
pRenderContext - > CopyRenderTargetToTextureEx ( NULL , - 1 , NULL , NULL ) ;
}
render - > PopView ( GetFrustum ( ) ) ;
# if defined( _X360 )
pRenderContext - > PopVertexShaderGPRAllocation ( ) ;
# endif
pRenderContext . SafeRelease ( ) ;
g_CurrentViewID = savedViewID ;
# endif
}
void CBaseWorldView : : DrawDepthOfField ( )
{
if ( ! g_pMaterialSystemHardwareConfig - > SupportsPixelShaders_2_0 ( ) )
{
return ;
}
CMatRenderContextPtr pRenderContext ( materials ) ;
ITexture * pSmallFB0 = materials - > FindTexture ( " _rt_smallfb0 " , TEXTURE_GROUP_RENDER_TARGET ) ;
ITexture * pSmallFB1 = materials - > FindTexture ( " _rt_smallfb1 " , TEXTURE_GROUP_RENDER_TARGET ) ;
Rect_t DestRect ;
int w = pSmallFB0 - > GetActualWidth ( ) ;
int h = pSmallFB0 - > GetActualHeight ( ) ;
DestRect . x = 0 ;
DestRect . y = 0 ;
DestRect . width = w ;
DestRect . height = h ;
pRenderContext - > CopyRenderTargetToTextureEx ( pSmallFB0 , 0 , NULL , & DestRect ) ;
IMaterial * pPyroBlurXMaterial = materials - > FindMaterial ( " dev/pyro_blur_filter_x " , TEXTURE_GROUP_OTHER ) ;
IMaterial * pPyroBlurYMaterial = materials - > FindMaterial ( " dev/pyro_blur_filter_y " , TEXTURE_GROUP_OTHER ) ;
pRenderContext - > PushRenderTargetAndViewport ( pSmallFB1 , 0 , 0 , w , h ) ;
pRenderContext - > DrawScreenSpaceRectangle ( pPyroBlurYMaterial , 0 , 0 , w , h , 0 , 0 , w - 1 , h - 1 , w , h ) ;
pRenderContext - > PopRenderTargetAndViewport ( ) ;
pRenderContext - > PushRenderTargetAndViewport ( pSmallFB0 , 0 , 0 , w , h ) ;
pRenderContext - > DrawScreenSpaceRectangle ( pPyroBlurXMaterial , 0 , 0 , w , h , 0 , 0 , w - 1 , h - 1 , w , h ) ;
pRenderContext - > PopRenderTargetAndViewport ( ) ;
IMaterial * pPyroDepthOfFieldMaterial = materials - > FindMaterial ( " dev/pyro_dof " , TEXTURE_GROUP_OTHER ) ;
pRenderContext - > DrawScreenSpaceRectangle ( pPyroDepthOfFieldMaterial , x , y , width , height , 0 , 0 , width - 1 , height - 1 , width , height ) ;
}
//-----------------------------------------------------------------------------
// Draws the scene when there's no water or only cheap water
//-----------------------------------------------------------------------------
void CSimpleWorldView : : Setup ( const CViewSetup & view , int nClearFlags , bool bDrawSkybox , const VisibleFogVolumeInfo_t & fogInfo , const WaterRenderInfo_t & waterInfo , ViewCustomVisibility_t * pCustomVisibility )
{
BaseClass : : Setup ( view ) ;
m_ClearFlags = nClearFlags ;
m_DrawFlags = DF_DRAW_ENTITITES ;
if ( ! waterInfo . m_bOpaqueWater )
{
m_DrawFlags | = DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER ;
}
else
{
bool bViewIntersectsWater = DoesViewPlaneIntersectWater ( fogInfo . m_flWaterHeight , fogInfo . m_nVisibleFogVolume ) ;
if ( bViewIntersectsWater )
{
// have to draw both sides if we can see both.
m_DrawFlags | = DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER ;
}
else if ( fogInfo . m_bEyeInFogVolume )
{
m_DrawFlags | = DF_RENDER_UNDERWATER ;
}
else
{
m_DrawFlags | = DF_RENDER_ABOVEWATER ;
}
}
if ( waterInfo . m_bDrawWaterSurface )
{
m_DrawFlags | = DF_RENDER_WATER ;
}
if ( ! fogInfo . m_bEyeInFogVolume & & bDrawSkybox )
{
m_DrawFlags | = DF_DRAWSKYBOX ;
}
m_pCustomVisibility = pCustomVisibility ;
m_fogInfo = fogInfo ;
}
//-----------------------------------------------------------------------------
// Draws the scene when there's no water or only cheap water
//-----------------------------------------------------------------------------
void CSimpleWorldView : : Draw ( )
{
VPROF ( " CViewRender::ViewDrawScene_NoWater " ) ;
CMatRenderContextPtr pRenderContext ( materials ) ;
PIXEVENT ( pRenderContext , " CSimpleWorldView::Draw " ) ;
# if defined( _X360 )
pRenderContext - > PushVertexShaderGPRAllocation ( 32 ) ; //lean toward pixel shader threads
# endif
pRenderContext . SafeRelease ( ) ;
DrawSetup ( 0 , m_DrawFlags , 0 ) ;
if ( ! m_fogInfo . m_bEyeInFogVolume )
{
EnableWorldFog ( ) ;
}
else
{
m_ClearFlags | = VIEW_CLEAR_COLOR ;
SetFogVolumeState ( m_fogInfo , false ) ;
pRenderContext . GetFrom ( materials ) ;
unsigned char ucFogColor [ 3 ] ;
pRenderContext - > GetFogColor ( ucFogColor ) ;
pRenderContext - > ClearColor4ub ( ucFogColor [ 0 ] , ucFogColor [ 1 ] , ucFogColor [ 2 ] , 255 ) ;
}
pRenderContext . SafeRelease ( ) ;
DrawExecute ( 0 , CurrentViewID ( ) , 0 ) ;
pRenderContext . GetFrom ( materials ) ;
pRenderContext - > ClearColor4ub ( 0 , 0 , 0 , 255 ) ;
# if defined( _X360 )
pRenderContext - > PopVertexShaderGPRAllocation ( ) ;
# endif
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CBaseWaterView : : CalcWaterEyeAdjustments ( const VisibleFogVolumeInfo_t & fogInfo ,
float & newWaterHeight , float & waterZAdjust , bool bSoftwareUserClipPlane )
{
if ( ! bSoftwareUserClipPlane )
{
newWaterHeight = fogInfo . m_flWaterHeight ;
waterZAdjust = 0.0f ;
return ;
}
newWaterHeight = fogInfo . m_flWaterHeight ;
float eyeToWaterZDelta = origin [ 2 ] - fogInfo . m_flWaterHeight ;
float epsilon = r_eyewaterepsilon . GetFloat ( ) ;
waterZAdjust = 0.0f ;
if ( fabs ( eyeToWaterZDelta ) < epsilon )
{
if ( eyeToWaterZDelta > 0 )
{
newWaterHeight = origin [ 2 ] - epsilon ;
}
else
{
newWaterHeight = origin [ 2 ] + epsilon ;
}
waterZAdjust = newWaterHeight - fogInfo . m_flWaterHeight ;
}
// Warning( "view.origin[2]: %f newWaterHeight: %f fogInfo.m_flWaterHeight: %f waterZAdjust: %f\n",
// ( float )view.origin[2], newWaterHeight, fogInfo.m_flWaterHeight, waterZAdjust );
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CBaseWaterView : : CSoftwareIntersectionView : : Setup ( bool bAboveWater )
{
BaseClass : : Setup ( * GetOuter ( ) ) ;
m_DrawFlags = 0 ;
m_DrawFlags = ( bAboveWater ) ? DF_RENDER_UNDERWATER : DF_RENDER_ABOVEWATER ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CBaseWaterView : : CSoftwareIntersectionView : : Draw ( )
{
DrawSetup ( GetOuter ( ) - > m_waterHeight , m_DrawFlags , GetOuter ( ) - > m_waterZAdjust ) ;
DrawExecute ( GetOuter ( ) - > m_waterHeight , CurrentViewID ( ) , GetOuter ( ) - > m_waterZAdjust ) ;
}
//-----------------------------------------------------------------------------
// Draws the scene when the view point is above the level of the water
//-----------------------------------------------------------------------------
void CAboveWaterView : : Setup ( const CViewSetup & view , bool bDrawSkybox , const VisibleFogVolumeInfo_t & fogInfo , const WaterRenderInfo_t & waterInfo )
{
BaseClass : : Setup ( view ) ;
m_bSoftwareUserClipPlane = g_pMaterialSystemHardwareConfig - > UseFastClipping ( ) ;
CalcWaterEyeAdjustments ( fogInfo , m_waterHeight , m_waterZAdjust , m_bSoftwareUserClipPlane ) ;
// BROKEN STUFF!
if ( m_waterZAdjust = = 0.0f )
{
m_bSoftwareUserClipPlane = false ;
}
m_DrawFlags = DF_RENDER_ABOVEWATER | DF_DRAW_ENTITITES ;
m_ClearFlags = VIEW_CLEAR_DEPTH ;
# ifdef PORTAL
if ( g_pPortalRender - > ShouldObeyStencilForClears ( ) )
m_ClearFlags | = VIEW_CLEAR_OBEY_STENCIL ;
# endif
if ( bDrawSkybox )
{
m_DrawFlags | = DF_DRAWSKYBOX ;
}
if ( waterInfo . m_bDrawWaterSurface )
{
m_DrawFlags | = DF_RENDER_WATER ;
}
if ( ! waterInfo . m_bRefract & & ! waterInfo . m_bOpaqueWater )
{
m_DrawFlags | = DF_RENDER_UNDERWATER ;
}
m_fogInfo = fogInfo ;
m_waterInfo = waterInfo ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CAboveWaterView : : Draw ( )
{
VPROF ( " CViewRender::ViewDrawScene_EyeAboveWater " ) ;
// eye is outside of water
CMatRenderContextPtr pRenderContext ( materials ) ;
// render the reflection
if ( m_waterInfo . m_bReflect )
{
m_ReflectionView . Setup ( m_waterInfo . m_bReflectEntities ) ;
m_pMainView - > AddViewToScene ( & m_ReflectionView ) ;
}
bool bViewIntersectsWater = false ;
// render refraction
if ( m_waterInfo . m_bRefract )
{
m_RefractionView . Setup ( ) ;
m_pMainView - > AddViewToScene ( & m_RefractionView ) ;
if ( ! m_bSoftwareUserClipPlane )
{
bViewIntersectsWater = DoesViewPlaneIntersectWater ( m_fogInfo . m_flWaterHeight , m_fogInfo . m_nVisibleFogVolume ) ;
}
}
else if ( ! ( m_DrawFlags & DF_DRAWSKYBOX ) )
{
m_ClearFlags | = VIEW_CLEAR_COLOR ;
}
# ifdef PORTAL
if ( g_pPortalRender - > ShouldObeyStencilForClears ( ) )
m_ClearFlags | = VIEW_CLEAR_OBEY_STENCIL ;
# endif
// NOTE!!!!! YOU CAN ONLY DO THIS IF YOU HAVE HARDWARE USER CLIP PLANES!!!!!!
bool bHardwareUserClipPlanes = ! g_pMaterialSystemHardwareConfig - > UseFastClipping ( ) ;
if ( bViewIntersectsWater & & bHardwareUserClipPlanes )
{
// This is necessary to keep the non-water fogged world from drawing underwater in
// the case where we want to partially see into the water.
m_DrawFlags | = DF_CLIP_Z | DF_CLIP_BELOW ;
}
// render the world
DrawSetup ( m_waterHeight , m_DrawFlags , m_waterZAdjust ) ;
EnableWorldFog ( ) ;
DrawExecute ( m_waterHeight , CurrentViewID ( ) , m_waterZAdjust ) ;
if ( m_waterInfo . m_bRefract )
{
if ( m_bSoftwareUserClipPlane )
{
m_SoftwareIntersectionView . Setup ( true ) ;
m_SoftwareIntersectionView . Draw ( ) ;
}
else if ( bViewIntersectsWater )
{
m_IntersectionView . Setup ( ) ;
m_pMainView - > AddViewToScene ( & m_IntersectionView ) ;
}
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CAboveWaterView : : CReflectionView : : Setup ( bool bReflectEntities )
{
BaseClass : : Setup ( * GetOuter ( ) ) ;
m_ClearFlags = VIEW_CLEAR_DEPTH ;
// NOTE: Clearing the color is unnecessary since we're drawing the skybox
// and dest-alpha is never used in the reflection
m_DrawFlags = DF_RENDER_REFLECTION | DF_CLIP_Z | DF_CLIP_BELOW |
DF_RENDER_ABOVEWATER ;
// NOTE: This will cause us to draw the 2d skybox in the reflection
// (which we want to do instead of drawing the 3d skybox)
m_DrawFlags | = DF_DRAWSKYBOX ;
if ( bReflectEntities )
{
m_DrawFlags | = DF_DRAW_ENTITITES ;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CAboveWaterView : : CReflectionView : : Draw ( )
{
# ifdef PORTAL
g_pPortalRender - > WaterRenderingHandler_PreReflection ( ) ;
# endif
// Store off view origin and angles and set the new view
int nSaveViewID = CurrentViewID ( ) ;
SetupCurrentView ( origin , angles , VIEW_REFLECTION ) ;
// Disable occlusion visualization in reflection
bool bVisOcclusion = r_visocclusion . GetInt ( ) ;
r_visocclusion . SetValue ( 0 ) ;
DrawSetup ( GetOuter ( ) - > m_fogInfo . m_flWaterHeight , m_DrawFlags , 0.0f , GetOuter ( ) - > m_fogInfo . m_nVisibleFogVolumeLeaf ) ;
EnableWorldFog ( ) ;
DrawExecute ( GetOuter ( ) - > m_fogInfo . m_flWaterHeight , VIEW_REFLECTION , 0.0f ) ;
r_visocclusion . SetValue ( bVisOcclusion ) ;
# ifdef PORTAL
// deal with stencil
g_pPortalRender - > WaterRenderingHandler_PostReflection ( ) ;
# endif
// finish off the view and restore the previous view.
SetupCurrentView ( origin , angles , ( view_id_t ) nSaveViewID ) ;
// This is here for multithreading
CMatRenderContextPtr pRenderContext ( materials ) ;
pRenderContext - > Flush ( ) ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CAboveWaterView : : CRefractionView : : Setup ( )
{
BaseClass : : Setup ( * GetOuter ( ) ) ;
m_ClearFlags = VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH ;
m_DrawFlags = DF_RENDER_REFRACTION | DF_CLIP_Z |
DF_RENDER_UNDERWATER | DF_FUDGE_UP |
DF_DRAW_ENTITITES ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CAboveWaterView : : CRefractionView : : Draw ( )
{
# ifdef PORTAL
g_pPortalRender - > WaterRenderingHandler_PreRefraction ( ) ;
# endif
// Store off view origin and angles and set the new view
int nSaveViewID = CurrentViewID ( ) ;
SetupCurrentView ( origin , angles , VIEW_REFRACTION ) ;
DrawSetup ( GetOuter ( ) - > m_waterHeight , m_DrawFlags , GetOuter ( ) - > m_waterZAdjust ) ;
SetFogVolumeState ( GetOuter ( ) - > m_fogInfo , true ) ;
SetClearColorToFogColor ( ) ;
DrawExecute ( GetOuter ( ) - > m_waterHeight , VIEW_REFRACTION , GetOuter ( ) - > m_waterZAdjust ) ;
# ifdef PORTAL
// deal with stencil
g_pPortalRender - > WaterRenderingHandler_PostRefraction ( ) ;
# endif
// finish off the view. restore the previous view.
SetupCurrentView ( origin , angles , ( view_id_t ) nSaveViewID ) ;
// This is here for multithreading
CMatRenderContextPtr pRenderContext ( materials ) ;
pRenderContext - > ClearColor4ub ( 0 , 0 , 0 , 255 ) ;
pRenderContext - > Flush ( ) ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CAboveWaterView : : CIntersectionView : : Setup ( )
{
BaseClass : : Setup ( * GetOuter ( ) ) ;
m_DrawFlags = DF_RENDER_UNDERWATER | DF_CLIP_Z | DF_DRAW_ENTITITES ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CAboveWaterView : : CIntersectionView : : Draw ( )
{
DrawSetup ( GetOuter ( ) - > m_fogInfo . m_flWaterHeight , m_DrawFlags , 0 ) ;
SetFogVolumeState ( GetOuter ( ) - > m_fogInfo , true ) ;
SetClearColorToFogColor ( ) ;
DrawExecute ( GetOuter ( ) - > m_fogInfo . m_flWaterHeight , VIEW_NONE , 0 ) ;
CMatRenderContextPtr pRenderContext ( materials ) ;
pRenderContext - > ClearColor4ub ( 0 , 0 , 0 , 255 ) ;
}
//-----------------------------------------------------------------------------
// Draws the scene when the view point is under the level of the water
//-----------------------------------------------------------------------------
void CUnderWaterView : : Setup ( const CViewSetup & view , bool bDrawSkybox , const VisibleFogVolumeInfo_t & fogInfo , const WaterRenderInfo_t & waterInfo )
{
BaseClass : : Setup ( view ) ;
m_bSoftwareUserClipPlane = g_pMaterialSystemHardwareConfig - > UseFastClipping ( ) ;
CalcWaterEyeAdjustments ( fogInfo , m_waterHeight , m_waterZAdjust , m_bSoftwareUserClipPlane ) ;
IMaterial * pWaterMaterial = fogInfo . m_pFogVolumeMaterial ;
if ( engine - > GetDXSupportLevel ( ) > = 90 ) // screen voerlays underwater are a dx9 feature
{
IMaterialVar * pScreenOverlayVar = pWaterMaterial - > FindVar ( " $underwateroverlay " , NULL , false ) ;
if ( pScreenOverlayVar & & ( pScreenOverlayVar - > IsDefined ( ) ) )
{
char const * pOverlayName = pScreenOverlayVar - > GetStringValue ( ) ;
if ( pOverlayName [ 0 ] ! = ' 0 ' ) // fixme!!!
{
IMaterial * pOverlayMaterial = materials - > FindMaterial ( pOverlayName , TEXTURE_GROUP_OTHER ) ;
m_pMainView - > SetWaterOverlayMaterial ( pOverlayMaterial ) ;
}
}
}
// NOTE: We're not drawing the 2d skybox under water since it's assumed to not be visible.
// render the world underwater
// Clear the color to get the appropriate underwater fog color
m_DrawFlags = DF_FUDGE_UP | DF_RENDER_UNDERWATER | DF_DRAW_ENTITITES ;
m_ClearFlags = VIEW_CLEAR_DEPTH ;
if ( ! m_bSoftwareUserClipPlane )
{
m_DrawFlags | = DF_CLIP_Z ;
}
if ( waterInfo . m_bDrawWaterSurface )
{
m_DrawFlags | = DF_RENDER_WATER ;
}
if ( ! waterInfo . m_bRefract & & ! waterInfo . m_bOpaqueWater )
{
m_DrawFlags | = DF_RENDER_ABOVEWATER ;
}
m_fogInfo = fogInfo ;
m_waterInfo = waterInfo ;
m_bDrawSkybox = bDrawSkybox ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CUnderWaterView : : Draw ( )
{
// FIXME: The 3d skybox shouldn't be drawn when the eye is under water
VPROF ( " CViewRender::ViewDrawScene_EyeUnderWater " ) ;
CMatRenderContextPtr pRenderContext ( materials ) ;
// render refraction (out of water)
if ( m_waterInfo . m_bRefract )
{
m_RefractionView . Setup ( ) ;
m_pMainView - > AddViewToScene ( & m_RefractionView ) ;
}
if ( ! m_waterInfo . m_bRefract )
{
SetFogVolumeState ( m_fogInfo , true ) ;
unsigned char ucFogColor [ 3 ] ;
pRenderContext - > GetFogColor ( ucFogColor ) ;
pRenderContext - > ClearColor4ub ( ucFogColor [ 0 ] , ucFogColor [ 1 ] , ucFogColor [ 2 ] , 255 ) ;
}
DrawSetup ( m_waterHeight , m_DrawFlags , m_waterZAdjust ) ;
SetFogVolumeState ( m_fogInfo , false ) ;
DrawExecute ( m_waterHeight , CurrentViewID ( ) , m_waterZAdjust ) ;
m_ClearFlags = 0 ;
if ( m_waterZAdjust ! = 0.0f & & m_bSoftwareUserClipPlane & & m_waterInfo . m_bRefract )
{
m_SoftwareIntersectionView . Setup ( false ) ;
m_SoftwareIntersectionView . Draw ( ) ;
}
pRenderContext - > ClearColor4ub ( 0 , 0 , 0 , 255 ) ;
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CUnderWaterView : : CRefractionView : : Setup ( )
{
BaseClass : : Setup ( * GetOuter ( ) ) ;
// NOTE: Refraction renders into the back buffer, over the top of the 3D skybox
// It is then blitted out into the refraction target. This is so that
// we only have to set up 3d sky vis once, and only render it once also!
m_DrawFlags = DF_CLIP_Z |
DF_CLIP_BELOW | DF_RENDER_ABOVEWATER |
DF_DRAW_ENTITITES ;
m_ClearFlags = VIEW_CLEAR_DEPTH ;
if ( GetOuter ( ) - > m_bDrawSkybox )
{
m_ClearFlags | = VIEW_CLEAR_COLOR ;
m_DrawFlags | = DF_DRAWSKYBOX | DF_CLIP_SKYBOX ;
}
}
//-----------------------------------------------------------------------------
//
//-----------------------------------------------------------------------------
void CUnderWaterView : : CRefractionView : : Draw ( )
{
CMatRenderContextPtr pRenderContext ( materials ) ;
SetFogVolumeState ( GetOuter ( ) - > m_fogInfo , true ) ;
unsigned char ucFogColor [ 3 ] ;
pRenderContext - > GetFogColor ( ucFogColor ) ;
pRenderContext - > ClearColor4ub ( ucFogColor [ 0 ] , ucFogColor [ 1 ] , ucFogColor [ 2 ] , 255 ) ;
DrawSetup ( GetOuter ( ) - > m_waterHeight , m_DrawFlags , GetOuter ( ) - > m_waterZAdjust ) ;
EnableWorldFog ( ) ;
DrawExecute ( GetOuter ( ) - > m_waterHeight , VIEW_REFRACTION , GetOuter ( ) - > m_waterZAdjust ) ;
Rect_t srcRect ;
srcRect . x = x ;
srcRect . y = y ;
srcRect . width = width ;
srcRect . height = height ;
// Optionally write the rendered image to a debug texture
if ( g_bDumpRenderTargets )
{
DumpTGAofRenderTarget ( width , height , " WaterRefract " ) ;
}
ITexture * pTexture = GetWaterRefractionTexture ( ) ;
pRenderContext - > CopyRenderTargetToTextureEx ( pTexture , 0 , & srcRect , NULL ) ;
}
//-----------------------------------------------------------------------------
//
// Reflective glass view starts here
//
//-----------------------------------------------------------------------------
//-----------------------------------------------------------------------------
// Draws the scene when the view contains reflective glass
//-----------------------------------------------------------------------------
void CReflectiveGlassView : : Setup ( const CViewSetup & view , int nClearFlags , bool bDrawSkybox ,
const VisibleFogVolumeInfo_t & fogInfo , const WaterRenderInfo_t & waterInfo , const cplane_t & reflectionPlane )
{
BaseClass : : Setup ( view , nClearFlags , bDrawSkybox , fogInfo , waterInfo , NULL ) ;
m_ReflectionPlane = reflectionPlane ;
}
bool CReflectiveGlassView : : AdjustView ( float flWaterHeight )
{
ITexture * pTexture = GetWaterReflectionTexture ( ) ;
// Use the aspect ratio of the main view! So, don't recompute it here
x = y = 0 ;
width = pTexture - > GetActualWidth ( ) ;
height = pTexture - > GetActualHeight ( ) ;
// Reflect the camera origin + vectors around the reflection plane
float flDist = DotProduct ( origin , m_ReflectionPlane . normal ) - m_ReflectionPlane . dist ;
VectorMA ( origin , - 2.0f * flDist , m_ReflectionPlane . normal , origin ) ;
Vector vecForward , vecUp ;
AngleVectors ( angles , & vecForward , NULL , & vecUp ) ;
float flDot = DotProduct ( vecForward , m_ReflectionPlane . normal ) ;
VectorMA ( vecForward , - 2.0f * flDot , m_ReflectionPlane . normal , vecForward ) ;
flDot = DotProduct ( vecUp , m_ReflectionPlane . normal ) ;
VectorMA ( vecUp , - 2.0f * flDot , m_ReflectionPlane . normal , vecUp ) ;
VectorAngles ( vecForward , vecUp , angles ) ;
return true ;
}
void CReflectiveGlassView : : PushView ( float waterHeight )
{
render - > Push3DView ( * this , m_ClearFlags , GetWaterReflectionTexture ( ) , GetFrustum ( ) ) ;
Vector4D plane ;
VectorCopy ( m_ReflectionPlane . normal , plane . AsVector3D ( ) ) ;
plane . w = m_ReflectionPlane . dist + 0.1f ;
CMatRenderContextPtr pRenderContext ( materials ) ;
pRenderContext - > PushCustomClipPlane ( plane . Base ( ) ) ;
}
void CReflectiveGlassView : : PopView ( )
{
CMatRenderContextPtr pRenderContext ( materials ) ;
pRenderContext - > PopCustomClipPlane ( ) ;
render - > PopView ( GetFrustum ( ) ) ;
}
//-----------------------------------------------------------------------------
// Renders reflective or refractive parts of glass
//-----------------------------------------------------------------------------
void CReflectiveGlassView : : Draw ( )
{
VPROF ( " CReflectiveGlassView::Draw " ) ;
CMatRenderContextPtr pRenderContext ( materials ) ;
PIXEVENT ( pRenderContext , " CReflectiveGlassView::Draw " ) ;
// Disable occlusion visualization in reflection
bool bVisOcclusion = r_visocclusion . GetInt ( ) ;
r_visocclusion . SetValue ( 0 ) ;
BaseClass : : Draw ( ) ;
r_visocclusion . SetValue ( bVisOcclusion ) ;
pRenderContext - > ClearColor4ub ( 0 , 0 , 0 , 255 ) ;
pRenderContext - > Flush ( ) ;
}
//-----------------------------------------------------------------------------
// Draws the scene when the view contains reflective glass
//-----------------------------------------------------------------------------
void CRefractiveGlassView : : Setup ( const CViewSetup & view , int nClearFlags , bool bDrawSkybox ,
const VisibleFogVolumeInfo_t & fogInfo , const WaterRenderInfo_t & waterInfo , const cplane_t & reflectionPlane )
{
BaseClass : : Setup ( view , nClearFlags , bDrawSkybox , fogInfo , waterInfo , NULL ) ;
m_ReflectionPlane = reflectionPlane ;
}
bool CRefractiveGlassView : : AdjustView ( float flWaterHeight )
{
ITexture * pTexture = GetWaterRefractionTexture ( ) ;
// Use the aspect ratio of the main view! So, don't recompute it here
x = y = 0 ;
width = pTexture - > GetActualWidth ( ) ;
height = pTexture - > GetActualHeight ( ) ;
return true ;
}
void CRefractiveGlassView : : PushView ( float waterHeight )
{
render - > Push3DView ( * this , m_ClearFlags , GetWaterRefractionTexture ( ) , GetFrustum ( ) ) ;
Vector4D plane ;
VectorMultiply ( m_ReflectionPlane . normal , - 1 , plane . AsVector3D ( ) ) ;
plane . w = - m_ReflectionPlane . dist + 0.1f ;
CMatRenderContextPtr pRenderContext ( materials ) ;
pRenderContext - > PushCustomClipPlane ( plane . Base ( ) ) ;
}
void CRefractiveGlassView : : PopView ( )
{
CMatRenderContextPtr pRenderContext ( materials ) ;
pRenderContext - > PopCustomClipPlane ( ) ;
render - > PopView ( GetFrustum ( ) ) ;
}
//-----------------------------------------------------------------------------
// Renders reflective or refractive parts of glass
//-----------------------------------------------------------------------------
void CRefractiveGlassView : : Draw ( )
{
VPROF ( " CRefractiveGlassView::Draw " ) ;
CMatRenderContextPtr pRenderContext ( materials ) ;
PIXEVENT ( pRenderContext , " CRefractiveGlassView::Draw " ) ;
BaseClass : : Draw ( ) ;
pRenderContext - > ClearColor4ub ( 0 , 0 , 0 , 255 ) ;
pRenderContext - > Flush ( ) ;
}