|
|
//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose:
//
//=====================================================================================//
#include "quakedef.h"
#include "gl_model_private.h"
#include "console.h"
#include "cdll_engine_int.h"
#include "gl_cvars.h"
#include "ivrenderview.h"
#include "gl_matsysiface.h"
#include "gl_drawlights.h"
#include "gl_rsurf.h"
#include "r_local.h"
#include "debugoverlay.h"
#include "vgui_baseui_interface.h"
#include "materialsystem/imaterialsystemhardwareconfig.h"
#include "demo.h"
#include "istudiorender.h"
#include "materialsystem/imesh.h"
#include "tier0/vprof.h"
#include "host.h"
#include "view.h"
#include "client.h"
#include "sys.h"
#include "cl_main.h"
#include "l_studio.h"
#include "IOcclusionSystem.h"
#include "cl_demouipanel.h"
#include "mod_vis.h"
#include "ivideomode.h"
#include "gl_shader.h"
#include "gl_rmain.h"
#include "engine/view_sharedv1.h"
#include "ispatialpartitioninternal.h"
#include "toolframework/itoolframework.h"
#include "icommandline.h"
#include "VGuiMatSurface/IMatSystemSurface.h"
#include "sourcevr/isourcevirtualreality.h"
#include "materialsystem/itexture.h"
#include "render.h"
#include "iclientvirtualreality.h"
#if defined( REPLAY_ENABLED )
#include "replay/iclientreplay.h"
#include "replay_internal.h"
#endif
// memdbgon must be the last include file in a .cpp file!!!
#include "tier0/memdbgon.h"
class IClientEntity;
float r_blend; float r_colormod[3] = { 1, 1, 1 }; bool g_bIsBlendingOrModulating = false;
bool g_bIsRenderingVGuiOnly = false;
colorVec R_LightPoint (Vector& p); void R_DrawLightmaps( IWorldRenderList *pList, int pageId ); void R_DrawIdentityBrushModel( IWorldRenderList *pRenderList, model_t *model );
static ConVar mat_color_projection( "mat_color_projection", "0", FCVAR_ARCHIVE );
/*
The view is allowed to move slightly from it's true position for bobbing, but if it exceeds 8 pixels linear distance (spherical, not box), the list of entities sent from the server may not include everything in the pvs, especially when crossing a water boudnary.
*/
extern ConVar r_avglightmap;
/*
================= V_CheckGamma
FIXME: Define this as a change function to the ConVar's below rather than polling it every frame. Note, still need to make sure it gets called very first time through frame loop. ================= */ bool V_CheckGamma( void ) { if ( IsX360() ) return false;
tmZoneFiltered( TELEMETRY_LEVEL0, 50, TMZF_NONE, "%s", __FUNCTION__ );
static int lastLightmap = -1; extern void GL_RebuildLightmaps( void ); // Refresh all lightmaps if r_avglightmap changes
if ( r_avglightmap.GetInt() != lastLightmap ) { lastLightmap = r_avglightmap.GetInt(); GL_RebuildLightmaps(); }
return true; }
//-----------------------------------------------------------------------------
// Purpose: Initializes the view renderer
// Output : void V_Init
//-----------------------------------------------------------------------------
void V_Init( void ) { BuildGammaTable( 2.2f, 2.2f, 0.0f, 2 ); }
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void V_Shutdown( void ) { // TODO, cleanup
}
//-----------------------------------------------------------------------------
// Purpose:
// Input : -
//-----------------------------------------------------------------------------
void V_RenderVGuiOnly_NoSwap() { tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
// Need to clear the screen in this case, cause we're not drawing
// the loading screen.
UpdateMaterialSystemConfig();
if( UseVR() && g_pClientVR ) { g_pClientVR->DrawMainMenu(); } else { CMatRenderContextPtr pRenderContext( materials ); pRenderContext->ClearBuffers( true, true );
EngineVGui()->Paint( (PaintMode_t)(PAINT_UIPANELS | PAINT_CURSOR )); } }
//-----------------------------------------------------------------------------
// Purpose: Renders only vgui (for loading progress) including buffer swapping and vgui simulation
//-----------------------------------------------------------------------------
void V_RenderVGuiOnly( void ) { materials->BeginFrame( host_frametime ); EngineVGui()->Simulate();
g_EngineRenderer->FrameBegin();
toolframework->RenderFrameBegin();
V_RenderVGuiOnly_NoSwap();
toolframework->RenderFrameEnd();
g_EngineRenderer->FrameEnd( ); materials->EndFrame();
Shader_SwapBuffers(); }
void FullViewColorAdjustment( ) { if ( mat_color_projection.GetInt() == 0 ) { return; }
CMatRenderContextPtr pRenderContext( materials );
ITexture *pFullFrameFB1 = materials->FindTexture( "_rt_FullFrameFB1", TEXTURE_GROUP_RENDER_TARGET );
pRenderContext->CopyRenderTargetToTextureEx( pFullFrameFB1, 0, NULL, NULL );
IMaterial *color_correction = materials->FindMaterial( "dev/red_green_projection", TEXTURE_GROUP_OTHER, true ); if ( color_correction ) { color_correction->IncrementReferenceCount(); }
int nViewportX, nViewportY, nViewportWidth, nViewportHeight; pRenderContext->GetViewport( nViewportX, nViewportY, nViewportWidth, nViewportHeight );
pRenderContext->DrawScreenSpaceRectangle( color_correction, 0, 0, nViewportWidth, nViewportHeight, nViewportX, nViewportY, nViewportX + nViewportWidth - 1, nViewportY + nViewportHeight - 1, nViewportWidth, nViewportHeight );
if ( color_correction ) { color_correction->DecrementReferenceCount(); } }
//-----------------------------------------------------------------------------
// Purpose: Render the world
//-----------------------------------------------------------------------------
void V_RenderView( void ) { VPROF( "V_RenderView" ); MDLCACHE_COARSE_LOCK_(g_pMDLCache);
bool bCanRenderWorld = ( host_state.worldmodel != NULL ) && cl.IsActive();
#if defined( REPLAY_ENABLED )
if ( g_pClientReplay && Replay_IsSupportedModAndPlatform() ) { bCanRenderWorld = bCanRenderWorld && g_pClientReplay->ShouldRender(); } #endif
bCanRenderWorld = bCanRenderWorld && toolframework->ShouldGameRenderView();
if ( IsPC() && bCanRenderWorld && g_bTextMode ) { tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "SysSleep()" );
// Sleep to let the other textmode clients get some cycles.
Sys_Sleep( 15 ); bCanRenderWorld = false; }
if ( !bCanRenderWorld ) { // Because we now do a lot of downloading before spawning map, don't render anything world related
// until we are an active client.
V_RenderVGuiOnly_NoSwap(); } else if ( !g_LostVideoMemory ) { // since we know we're going to render the world, check for lightmap updates while it is easy
// to tear down and rebuild
R_CheckForLightingConfigChanges(); // We can get into situations where some other material system app
// is trying to start up; in those cases, we shouldn't render...
vrect_t scr_vrect = videomode->GetClientViewRect(); g_ClientDLL->View_Render( &scr_vrect ); }
FullViewColorAdjustment(); }
void Linefile_Draw( void );
//-----------------------------------------------------------------------------
// Purpose: Expose rendering interface to client .dll
//-----------------------------------------------------------------------------
class CVRenderView : public IVRenderView, public ISpatialLeafEnumerator { public: void TouchLight( dlight_t *light ) { int i; i = light - cl_dlights; if (i >= 0 && i < MAX_DLIGHTS) { r_dlightchanged |= (1 << i); } }
void DrawBrushModel( IClientEntity *baseentity, model_t *model, const Vector& origin, const QAngle& angles, bool bUnused ) { R_DrawBrushModel( baseentity, model, origin, angles, DEPTH_MODE_NORMAL, true, true ); }
virtual void DrawBrushModelEx( IClientEntity *baseentity, model_t *model, const Vector& origin, const QAngle& angles, DrawBrushModelMode_t mode ) { bool bDrawOpaque = ( mode != DBM_DRAW_TRANSLUCENT_ONLY ); bool bDrawTranslucent = ( mode != DBM_DRAW_OPAQUE_ONLY ); R_DrawBrushModel( baseentity, model, origin, angles, DEPTH_MODE_NORMAL, bDrawOpaque, bDrawTranslucent ); }
// Draw brush model shadow
void DrawBrushModelShadow( IClientRenderable *pRenderable ) { R_DrawBrushModelShadow( pRenderable ); }
void DrawIdentityBrushModel( IWorldRenderList *pList, model_t *model ) { R_DrawIdentityBrushModel( pList, model ); }
void Draw3DDebugOverlays( void ) { DrawSavedModelDebugOverlays();
if ( g_pDemoUI ) { g_pDemoUI->DrawDebuggingInfo(); }
if ( g_pDemoUI2 ) { g_pDemoUI2->DrawDebuggingInfo(); }
SpatialPartition()->DrawDebugOverlays();
CDebugOverlay::Draw3DOverlays();
// Render occlusion debugging info
OcclusionSystem()->DrawDebugOverlays(); }
FORCEINLINE void CheckBlend( void ) { g_bIsBlendingOrModulating = ( r_blend != 1.0 ) || ( r_colormod[0] != 1.0 ) || ( r_colormod[1] != 1.0 ) || ( r_colormod[2] != 1.0 );
} void SetBlend( float blend ) { r_blend = blend; CheckBlend(); }
float GetBlend( void ) { return r_blend; }
void SetColorModulation( float const* blend ) { VectorCopy( blend, r_colormod ); CheckBlend(); }
void GetColorModulation( float* blend ) { VectorCopy( r_colormod, blend ); }
void SceneBegin( void ) { g_EngineRenderer->DrawSceneBegin(); }
void SceneEnd( void ) { g_EngineRenderer->DrawSceneEnd(); } void GetVisibleFogVolume( const Vector& vEyePoint, VisibleFogVolumeInfo_t *pInfo ) { R_GetVisibleFogVolume( vEyePoint, pInfo ); } IWorldRenderList * CreateWorldList() { return g_EngineRenderer->CreateWorldList(); }
void BuildWorldLists( IWorldRenderList *pList, WorldListInfo_t* pInfo, int iForceFViewLeaf, const VisOverrideData_t* pVisData, bool bShadowDepth, float *pReflectionWaterHeight ) { g_EngineRenderer->BuildWorldLists( pList, pInfo, iForceFViewLeaf, pVisData, bShadowDepth, pReflectionWaterHeight ); }
void DrawWorldLists( IWorldRenderList *pList, unsigned long flags, float waterZAdjust ) { g_EngineRenderer->DrawWorldLists( pList, flags, waterZAdjust ); }
// Optimization for top view
void DrawTopView( bool enable ) { R_DrawTopView( enable ); }
void TopViewBounds( Vector2D const& mins, Vector2D const& maxs ) { R_TopViewBounds( mins, maxs ); }
void DrawLights( void ) { DrawLightSprites();
#ifdef USE_CONVARS
DrawLightDebuggingInfo(); #endif
}
void DrawMaskEntities( void ) { // UNDONE: Don't do this with masked brush models, they should probably be in a separate list
// R_DrawMaskEntities()
}
void DrawTranslucentSurfaces( IWorldRenderList *pList, int sortIndex, unsigned long flags, bool bShadowDepth ) { Shader_DrawTranslucentSurfaces( pList, sortIndex, flags, bShadowDepth ); }
bool LeafContainsTranslucentSurfaces( IWorldRenderList *pList, int sortIndex, unsigned long flags ) { return Shader_LeafContainsTranslucentSurfaces( pList, sortIndex, flags ); }
void DrawLineFile( void ) { Linefile_Draw(); }
void DrawLightmaps( IWorldRenderList *pList, int pageId ) { R_DrawLightmaps( pList, pageId ); }
void ViewSetupVis( bool novis, int numorigins, const Vector origin[] ) { g_EngineRenderer->ViewSetupVis( novis, numorigins, origin ); }
void ViewSetupVisEx( bool novis, int numorigins, const Vector origin[], unsigned int &returnFlags ) { g_EngineRenderer->ViewSetupVisEx( novis, numorigins, origin, returnFlags ); }
bool AreAnyLeavesVisible( int *leafList, int nLeaves ) { return Map_AreAnyLeavesVisible( *host_state.worldbrush, leafList, nLeaves ); }
// For backward compatibility only!!!
void VguiPaint( void ) { EngineVGui()->BackwardCompatibility_Paint(); }
void VGui_Paint( int mode ) { EngineVGui()->Paint( (PaintMode_t)mode ); }
void ViewDrawFade( byte *color, IMaterial* pFadeMaterial ) { VPROF_BUDGET( "ViewDrawFade", VPROF_BUDGETGROUP_WORLD_RENDERING ); g_EngineRenderer->ViewDrawFade( color, pFadeMaterial ); }
void OLD_SetProjectionMatrix( float fov, float zNear, float zFar ) { // Here to preserve backwards compat
}
void OLD_SetOffCenterProjectionMatrix( float fov, float zNear, float zFar, float flAspectRatio, float flBottom, float flTop, float flLeft, float flRight ) { // Here to preserve backwards compat
}
void OLD_SetProjectionMatrixOrtho( float left, float top, float right, float bottom, float zNear, float zFar ) { // Here to preserve backwards compat
}
colorVec GetLightAtPoint( Vector& pos ) { return R_LightPoint( pos ); }
int GetViewEntity( void ) { return cl.m_nViewEntity; }
float GetFieldOfView( void ) { return g_EngineRenderer->GetFov(); }
unsigned char **GetAreaBits( void ) { return cl.GetAreaBits_BackwardCompatibility(); }
virtual void SetAreaState( unsigned char chAreaBits[MAX_AREA_STATE_BYTES], unsigned char chAreaPortalBits[MAX_AREA_PORTAL_STATE_BYTES] ) { *cl.GetAreaBits_BackwardCompatibility() = 0; // Clear the b/w compatibiltiy thing.
memcpy( cl.m_chAreaBits, chAreaBits, MAX_AREA_STATE_BYTES ); memcpy( cl.m_chAreaPortalBits, chAreaPortalBits, MAX_AREA_PORTAL_STATE_BYTES ); cl.m_bAreaBitsValid = true; }
// World fog for world rendering
void SetFogVolumeState( int fogVolume, bool useHeightFog ) { R_SetFogVolumeState(fogVolume, useHeightFog ); }
virtual void InstallBrushSurfaceRenderer( IBrushRenderer* pBrushRenderer ) { R_InstallBrushRenderOverride( pBrushRenderer ); }
struct BoxIntersectWaterContext_t { bool m_bFoundWaterLeaf; int m_nLeafWaterDataID; }; bool EnumerateLeaf( int leaf, int context ) { BoxIntersectWaterContext_t *pSearchContext = ( BoxIntersectWaterContext_t * )context; mleaf_t *pLeaf = &host_state.worldmodel->brush.pShared->leafs[leaf]; if( pLeaf->leafWaterDataID == pSearchContext->m_nLeafWaterDataID ) { pSearchContext->m_bFoundWaterLeaf = true; // found it . . stop enumeration
return false; } return true; }
bool DoesBoxIntersectWaterVolume( const Vector &mins, const Vector &maxs, int leafWaterDataID ) { BoxIntersectWaterContext_t context; context.m_bFoundWaterLeaf = false; context.m_nLeafWaterDataID = leafWaterDataID; g_pToolBSPTree->EnumerateLeavesInBox( mins, maxs, this, ( int )&context ); return context.m_bFoundWaterLeaf; }
// Push, pop views
virtual void Push3DView( const CViewSetup &view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes ) { g_EngineRenderer->Push3DView( view, nFlags, pRenderTarget, frustumPlanes, NULL ); }
virtual void Push2DView( const CViewSetup &view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes ) { g_EngineRenderer->Push2DView( view, nFlags, pRenderTarget, frustumPlanes ); }
virtual void PopView( Frustum frustumPlanes ) { g_EngineRenderer->PopView( frustumPlanes ); }
virtual void SetMainView( const Vector &vecOrigin, const QAngle &angles ) { g_EngineRenderer->SetMainView( vecOrigin, angles ); }
void OverrideViewFrustum( Frustum custom ) { g_EngineRenderer->OverrideViewFrustum( custom ); }
void DrawBrushModelShadowDepth( IClientEntity *baseentity, model_t *model, const Vector& origin, const QAngle& angles, ERenderDepthMode DepthMode ) { R_DrawBrushModel( baseentity, model, origin, angles, DepthMode, true, true ); }
void UpdateBrushModelLightmap( model_t *model, IClientRenderable *pRenderable ) { g_EngineRenderer->UpdateBrushModelLightmap( model, pRenderable ); } void BeginUpdateLightmaps( void ) { g_EngineRenderer->BeginUpdateLightmaps(); }
void EndUpdateLightmaps( void ) { g_EngineRenderer->EndUpdateLightmaps(); }
virtual void Push3DView( const CViewSetup &view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes, ITexture* pDepthTexture ) { g_EngineRenderer->Push3DView( view, nFlags, pRenderTarget, frustumPlanes, pDepthTexture ); }
void GetMatricesForView( const CViewSetup &view, VMatrix *pWorldToView, VMatrix *pViewToProjection, VMatrix *pWorldToProjection, VMatrix *pWorldToPixels ) { ComputeViewMatrices( pWorldToView, pViewToProjection, pWorldToProjection, view ); ComputeWorldToScreenMatrix( pWorldToPixels, *pWorldToProjection, view ); } };
static CVRenderView s_RenderView; EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CVRenderView, IVRenderView, VENGINE_RENDERVIEW_INTERFACE_VERSION, s_RenderView );
|