Team Fortress 2 Source Code as on 22/4/2020
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

615 lines
16 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //=====================================================================================//
  6. #include "quakedef.h"
  7. #include "gl_model_private.h"
  8. #include "console.h"
  9. #include "cdll_engine_int.h"
  10. #include "gl_cvars.h"
  11. #include "ivrenderview.h"
  12. #include "gl_matsysiface.h"
  13. #include "gl_drawlights.h"
  14. #include "gl_rsurf.h"
  15. #include "r_local.h"
  16. #include "debugoverlay.h"
  17. #include "vgui_baseui_interface.h"
  18. #include "materialsystem/imaterialsystemhardwareconfig.h"
  19. #include "demo.h"
  20. #include "istudiorender.h"
  21. #include "materialsystem/imesh.h"
  22. #include "tier0/vprof.h"
  23. #include "host.h"
  24. #include "view.h"
  25. #include "client.h"
  26. #include "sys.h"
  27. #include "cl_main.h"
  28. #include "l_studio.h"
  29. #include "IOcclusionSystem.h"
  30. #include "cl_demouipanel.h"
  31. #include "mod_vis.h"
  32. #include "ivideomode.h"
  33. #include "gl_shader.h"
  34. #include "gl_rmain.h"
  35. #include "engine/view_sharedv1.h"
  36. #include "ispatialpartitioninternal.h"
  37. #include "toolframework/itoolframework.h"
  38. #include "icommandline.h"
  39. #include "VGuiMatSurface/IMatSystemSurface.h"
  40. #include "sourcevr/isourcevirtualreality.h"
  41. #include "materialsystem/itexture.h"
  42. #include "render.h"
  43. #include "iclientvirtualreality.h"
  44. #if defined( REPLAY_ENABLED )
  45. #include "replay/iclientreplay.h"
  46. #include "replay_internal.h"
  47. #endif
  48. // memdbgon must be the last include file in a .cpp file!!!
  49. #include "tier0/memdbgon.h"
  50. class IClientEntity;
  51. float r_blend;
  52. float r_colormod[3] = { 1, 1, 1 };
  53. bool g_bIsBlendingOrModulating = false;
  54. bool g_bIsRenderingVGuiOnly = false;
  55. colorVec R_LightPoint (Vector& p);
  56. void R_DrawLightmaps( IWorldRenderList *pList, int pageId );
  57. void R_DrawIdentityBrushModel( IWorldRenderList *pRenderList, model_t *model );
  58. static ConVar mat_color_projection( "mat_color_projection", "0", FCVAR_ARCHIVE );
  59. /*
  60. The view is allowed to move slightly from it's true position for bobbing,
  61. but if it exceeds 8 pixels linear distance (spherical, not box), the list of
  62. entities sent from the server may not include everything in the pvs, especially
  63. when crossing a water boudnary.
  64. */
  65. extern ConVar r_avglightmap;
  66. /*
  67. =================
  68. V_CheckGamma
  69. FIXME: Define this as a change function to the ConVar's below rather than polling it
  70. every frame. Note, still need to make sure it gets called very first time through frame loop.
  71. =================
  72. */
  73. bool V_CheckGamma( void )
  74. {
  75. if ( IsX360() )
  76. return false;
  77. tmZoneFiltered( TELEMETRY_LEVEL0, 50, TMZF_NONE, "%s", __FUNCTION__ );
  78. static int lastLightmap = -1;
  79. extern void GL_RebuildLightmaps( void );
  80. // Refresh all lightmaps if r_avglightmap changes
  81. if ( r_avglightmap.GetInt() != lastLightmap )
  82. {
  83. lastLightmap = r_avglightmap.GetInt();
  84. GL_RebuildLightmaps();
  85. }
  86. return true;
  87. }
  88. //-----------------------------------------------------------------------------
  89. // Purpose: Initializes the view renderer
  90. // Output : void V_Init
  91. //-----------------------------------------------------------------------------
  92. void V_Init( void )
  93. {
  94. BuildGammaTable( 2.2f, 2.2f, 0.0f, 2 );
  95. }
  96. //-----------------------------------------------------------------------------
  97. // Purpose:
  98. //-----------------------------------------------------------------------------
  99. void V_Shutdown( void )
  100. {
  101. // TODO, cleanup
  102. }
  103. //-----------------------------------------------------------------------------
  104. // Purpose:
  105. // Input : -
  106. //-----------------------------------------------------------------------------
  107. void V_RenderVGuiOnly_NoSwap()
  108. {
  109. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "%s", __FUNCTION__ );
  110. // Need to clear the screen in this case, cause we're not drawing
  111. // the loading screen.
  112. UpdateMaterialSystemConfig();
  113. if( UseVR() && g_pClientVR )
  114. {
  115. g_pClientVR->DrawMainMenu();
  116. }
  117. else
  118. {
  119. CMatRenderContextPtr pRenderContext( materials );
  120. pRenderContext->ClearBuffers( true, true );
  121. EngineVGui()->Paint( (PaintMode_t)(PAINT_UIPANELS | PAINT_CURSOR ));
  122. }
  123. }
  124. //-----------------------------------------------------------------------------
  125. // Purpose: Renders only vgui (for loading progress) including buffer swapping and vgui simulation
  126. //-----------------------------------------------------------------------------
  127. void V_RenderVGuiOnly( void )
  128. {
  129. materials->BeginFrame( host_frametime );
  130. EngineVGui()->Simulate();
  131. g_EngineRenderer->FrameBegin();
  132. toolframework->RenderFrameBegin();
  133. V_RenderVGuiOnly_NoSwap();
  134. toolframework->RenderFrameEnd();
  135. g_EngineRenderer->FrameEnd( );
  136. materials->EndFrame();
  137. Shader_SwapBuffers();
  138. }
  139. void FullViewColorAdjustment( )
  140. {
  141. if ( mat_color_projection.GetInt() == 0 )
  142. {
  143. return;
  144. }
  145. CMatRenderContextPtr pRenderContext( materials );
  146. ITexture *pFullFrameFB1 = materials->FindTexture( "_rt_FullFrameFB1", TEXTURE_GROUP_RENDER_TARGET );
  147. pRenderContext->CopyRenderTargetToTextureEx( pFullFrameFB1, 0, NULL, NULL );
  148. IMaterial *color_correction = materials->FindMaterial( "dev/red_green_projection", TEXTURE_GROUP_OTHER, true );
  149. if ( color_correction )
  150. {
  151. color_correction->IncrementReferenceCount();
  152. }
  153. int nViewportX, nViewportY, nViewportWidth, nViewportHeight;
  154. pRenderContext->GetViewport( nViewportX, nViewportY, nViewportWidth, nViewportHeight );
  155. pRenderContext->DrawScreenSpaceRectangle( color_correction, 0, 0, nViewportWidth, nViewportHeight,
  156. nViewportX, nViewportY,
  157. nViewportX + nViewportWidth - 1, nViewportY + nViewportHeight - 1,
  158. nViewportWidth, nViewportHeight );
  159. if ( color_correction )
  160. {
  161. color_correction->DecrementReferenceCount();
  162. }
  163. }
  164. //-----------------------------------------------------------------------------
  165. // Purpose: Render the world
  166. //-----------------------------------------------------------------------------
  167. void V_RenderView( void )
  168. {
  169. VPROF( "V_RenderView" );
  170. MDLCACHE_COARSE_LOCK_(g_pMDLCache);
  171. bool bCanRenderWorld = ( host_state.worldmodel != NULL ) && cl.IsActive();
  172. #if defined( REPLAY_ENABLED )
  173. if ( g_pClientReplay && Replay_IsSupportedModAndPlatform() )
  174. {
  175. bCanRenderWorld = bCanRenderWorld && g_pClientReplay->ShouldRender();
  176. }
  177. #endif
  178. bCanRenderWorld = bCanRenderWorld && toolframework->ShouldGameRenderView();
  179. if ( IsPC() && bCanRenderWorld && g_bTextMode )
  180. {
  181. tmZone( TELEMETRY_LEVEL0, TMZF_NONE, "SysSleep()" );
  182. // Sleep to let the other textmode clients get some cycles.
  183. Sys_Sleep( 15 );
  184. bCanRenderWorld = false;
  185. }
  186. if ( !bCanRenderWorld )
  187. {
  188. // Because we now do a lot of downloading before spawning map, don't render anything world related
  189. // until we are an active client.
  190. V_RenderVGuiOnly_NoSwap();
  191. }
  192. else if ( !g_LostVideoMemory )
  193. {
  194. // since we know we're going to render the world, check for lightmap updates while it is easy
  195. // to tear down and rebuild
  196. R_CheckForLightingConfigChanges();
  197. // We can get into situations where some other material system app
  198. // is trying to start up; in those cases, we shouldn't render...
  199. vrect_t scr_vrect = videomode->GetClientViewRect();
  200. g_ClientDLL->View_Render( &scr_vrect );
  201. }
  202. FullViewColorAdjustment();
  203. }
  204. void Linefile_Draw( void );
  205. //-----------------------------------------------------------------------------
  206. // Purpose: Expose rendering interface to client .dll
  207. //-----------------------------------------------------------------------------
  208. class CVRenderView : public IVRenderView, public ISpatialLeafEnumerator
  209. {
  210. public:
  211. void TouchLight( dlight_t *light )
  212. {
  213. int i;
  214. i = light - cl_dlights;
  215. if (i >= 0 && i < MAX_DLIGHTS)
  216. {
  217. r_dlightchanged |= (1 << i);
  218. }
  219. }
  220. void DrawBrushModel(
  221. IClientEntity *baseentity,
  222. model_t *model,
  223. const Vector& origin,
  224. const QAngle& angles,
  225. bool bUnused )
  226. {
  227. R_DrawBrushModel( baseentity, model, origin, angles, DEPTH_MODE_NORMAL, true, true );
  228. }
  229. virtual void DrawBrushModelEx( IClientEntity *baseentity, model_t *model, const Vector& origin, const QAngle& angles, DrawBrushModelMode_t mode )
  230. {
  231. bool bDrawOpaque = ( mode != DBM_DRAW_TRANSLUCENT_ONLY );
  232. bool bDrawTranslucent = ( mode != DBM_DRAW_OPAQUE_ONLY );
  233. R_DrawBrushModel( baseentity, model, origin, angles, DEPTH_MODE_NORMAL, bDrawOpaque, bDrawTranslucent );
  234. }
  235. // Draw brush model shadow
  236. void DrawBrushModelShadow( IClientRenderable *pRenderable )
  237. {
  238. R_DrawBrushModelShadow( pRenderable );
  239. }
  240. void DrawIdentityBrushModel( IWorldRenderList *pList, model_t *model )
  241. {
  242. R_DrawIdentityBrushModel( pList, model );
  243. }
  244. void Draw3DDebugOverlays( void )
  245. {
  246. DrawSavedModelDebugOverlays();
  247. if ( g_pDemoUI )
  248. {
  249. g_pDemoUI->DrawDebuggingInfo();
  250. }
  251. if ( g_pDemoUI2 )
  252. {
  253. g_pDemoUI2->DrawDebuggingInfo();
  254. }
  255. SpatialPartition()->DrawDebugOverlays();
  256. CDebugOverlay::Draw3DOverlays();
  257. // Render occlusion debugging info
  258. OcclusionSystem()->DrawDebugOverlays();
  259. }
  260. FORCEINLINE void CheckBlend( void )
  261. {
  262. g_bIsBlendingOrModulating = ( r_blend != 1.0 ) ||
  263. ( r_colormod[0] != 1.0 ) || ( r_colormod[1] != 1.0 ) || ( r_colormod[2] != 1.0 );
  264. }
  265. void SetBlend( float blend )
  266. {
  267. r_blend = blend;
  268. CheckBlend();
  269. }
  270. float GetBlend( void )
  271. {
  272. return r_blend;
  273. }
  274. void SetColorModulation( float const* blend )
  275. {
  276. VectorCopy( blend, r_colormod );
  277. CheckBlend();
  278. }
  279. void GetColorModulation( float* blend )
  280. {
  281. VectorCopy( r_colormod, blend );
  282. }
  283. void SceneBegin( void )
  284. {
  285. g_EngineRenderer->DrawSceneBegin();
  286. }
  287. void SceneEnd( void )
  288. {
  289. g_EngineRenderer->DrawSceneEnd();
  290. }
  291. void GetVisibleFogVolume( const Vector& vEyePoint, VisibleFogVolumeInfo_t *pInfo )
  292. {
  293. R_GetVisibleFogVolume( vEyePoint, pInfo );
  294. }
  295. IWorldRenderList * CreateWorldList()
  296. {
  297. return g_EngineRenderer->CreateWorldList();
  298. }
  299. void BuildWorldLists( IWorldRenderList *pList, WorldListInfo_t* pInfo, int iForceFViewLeaf, const VisOverrideData_t* pVisData, bool bShadowDepth, float *pReflectionWaterHeight )
  300. {
  301. g_EngineRenderer->BuildWorldLists( pList, pInfo, iForceFViewLeaf, pVisData, bShadowDepth, pReflectionWaterHeight );
  302. }
  303. void DrawWorldLists( IWorldRenderList *pList, unsigned long flags, float waterZAdjust )
  304. {
  305. g_EngineRenderer->DrawWorldLists( pList, flags, waterZAdjust );
  306. }
  307. // Optimization for top view
  308. void DrawTopView( bool enable )
  309. {
  310. R_DrawTopView( enable );
  311. }
  312. void TopViewBounds( Vector2D const& mins, Vector2D const& maxs )
  313. {
  314. R_TopViewBounds( mins, maxs );
  315. }
  316. void DrawLights( void )
  317. {
  318. DrawLightSprites();
  319. #ifdef USE_CONVARS
  320. DrawLightDebuggingInfo();
  321. #endif
  322. }
  323. void DrawMaskEntities( void )
  324. {
  325. // UNDONE: Don't do this with masked brush models, they should probably be in a separate list
  326. // R_DrawMaskEntities()
  327. }
  328. void DrawTranslucentSurfaces( IWorldRenderList *pList, int sortIndex, unsigned long flags, bool bShadowDepth )
  329. {
  330. Shader_DrawTranslucentSurfaces( pList, sortIndex, flags, bShadowDepth );
  331. }
  332. bool LeafContainsTranslucentSurfaces( IWorldRenderList *pList, int sortIndex, unsigned long flags )
  333. {
  334. return Shader_LeafContainsTranslucentSurfaces( pList, sortIndex, flags );
  335. }
  336. void DrawLineFile( void )
  337. {
  338. Linefile_Draw();
  339. }
  340. void DrawLightmaps( IWorldRenderList *pList, int pageId )
  341. {
  342. R_DrawLightmaps( pList, pageId );
  343. }
  344. void ViewSetupVis( bool novis, int numorigins, const Vector origin[] )
  345. {
  346. g_EngineRenderer->ViewSetupVis( novis, numorigins, origin );
  347. }
  348. void ViewSetupVisEx( bool novis, int numorigins, const Vector origin[], unsigned int &returnFlags )
  349. {
  350. g_EngineRenderer->ViewSetupVisEx( novis, numorigins, origin, returnFlags );
  351. }
  352. bool AreAnyLeavesVisible( int *leafList, int nLeaves )
  353. {
  354. return Map_AreAnyLeavesVisible( *host_state.worldbrush, leafList, nLeaves );
  355. }
  356. // For backward compatibility only!!!
  357. void VguiPaint( void )
  358. {
  359. EngineVGui()->BackwardCompatibility_Paint();
  360. }
  361. void VGui_Paint( int mode )
  362. {
  363. EngineVGui()->Paint( (PaintMode_t)mode );
  364. }
  365. void ViewDrawFade( byte *color, IMaterial* pFadeMaterial )
  366. {
  367. VPROF_BUDGET( "ViewDrawFade", VPROF_BUDGETGROUP_WORLD_RENDERING );
  368. g_EngineRenderer->ViewDrawFade( color, pFadeMaterial );
  369. }
  370. void OLD_SetProjectionMatrix( float fov, float zNear, float zFar )
  371. {
  372. // Here to preserve backwards compat
  373. }
  374. void OLD_SetOffCenterProjectionMatrix( float fov, float zNear, float zFar, float flAspectRatio,
  375. float flBottom, float flTop, float flLeft, float flRight )
  376. {
  377. // Here to preserve backwards compat
  378. }
  379. void OLD_SetProjectionMatrixOrtho( float left, float top, float right, float bottom, float zNear, float zFar )
  380. {
  381. // Here to preserve backwards compat
  382. }
  383. colorVec GetLightAtPoint( Vector& pos )
  384. {
  385. return R_LightPoint( pos );
  386. }
  387. int GetViewEntity( void )
  388. {
  389. return cl.m_nViewEntity;
  390. }
  391. float GetFieldOfView( void )
  392. {
  393. return g_EngineRenderer->GetFov();
  394. }
  395. unsigned char **GetAreaBits( void )
  396. {
  397. return cl.GetAreaBits_BackwardCompatibility();
  398. }
  399. virtual void SetAreaState(
  400. unsigned char chAreaBits[MAX_AREA_STATE_BYTES],
  401. unsigned char chAreaPortalBits[MAX_AREA_PORTAL_STATE_BYTES] )
  402. {
  403. *cl.GetAreaBits_BackwardCompatibility() = 0; // Clear the b/w compatibiltiy thing.
  404. memcpy( cl.m_chAreaBits, chAreaBits, MAX_AREA_STATE_BYTES );
  405. memcpy( cl.m_chAreaPortalBits, chAreaPortalBits, MAX_AREA_PORTAL_STATE_BYTES );
  406. cl.m_bAreaBitsValid = true;
  407. }
  408. // World fog for world rendering
  409. void SetFogVolumeState( int fogVolume, bool useHeightFog )
  410. {
  411. R_SetFogVolumeState(fogVolume, useHeightFog );
  412. }
  413. virtual void InstallBrushSurfaceRenderer( IBrushRenderer* pBrushRenderer )
  414. {
  415. R_InstallBrushRenderOverride( pBrushRenderer );
  416. }
  417. struct BoxIntersectWaterContext_t
  418. {
  419. bool m_bFoundWaterLeaf;
  420. int m_nLeafWaterDataID;
  421. };
  422. bool EnumerateLeaf( int leaf, int context )
  423. {
  424. BoxIntersectWaterContext_t *pSearchContext = ( BoxIntersectWaterContext_t * )context;
  425. mleaf_t *pLeaf = &host_state.worldmodel->brush.pShared->leafs[leaf];
  426. if( pLeaf->leafWaterDataID == pSearchContext->m_nLeafWaterDataID )
  427. {
  428. pSearchContext->m_bFoundWaterLeaf = true;
  429. // found it . . stop enumeration
  430. return false;
  431. }
  432. return true;
  433. }
  434. bool DoesBoxIntersectWaterVolume( const Vector &mins, const Vector &maxs, int leafWaterDataID )
  435. {
  436. BoxIntersectWaterContext_t context;
  437. context.m_bFoundWaterLeaf = false;
  438. context.m_nLeafWaterDataID = leafWaterDataID;
  439. g_pToolBSPTree->EnumerateLeavesInBox( mins, maxs, this, ( int )&context );
  440. return context.m_bFoundWaterLeaf;
  441. }
  442. // Push, pop views
  443. virtual void Push3DView( const CViewSetup &view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes )
  444. {
  445. g_EngineRenderer->Push3DView( view, nFlags, pRenderTarget, frustumPlanes, NULL );
  446. }
  447. virtual void Push2DView( const CViewSetup &view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes )
  448. {
  449. g_EngineRenderer->Push2DView( view, nFlags, pRenderTarget, frustumPlanes );
  450. }
  451. virtual void PopView( Frustum frustumPlanes )
  452. {
  453. g_EngineRenderer->PopView( frustumPlanes );
  454. }
  455. virtual void SetMainView( const Vector &vecOrigin, const QAngle &angles )
  456. {
  457. g_EngineRenderer->SetMainView( vecOrigin, angles );
  458. }
  459. void OverrideViewFrustum( Frustum custom )
  460. {
  461. g_EngineRenderer->OverrideViewFrustum( custom );
  462. }
  463. void DrawBrushModelShadowDepth(
  464. IClientEntity *baseentity,
  465. model_t *model,
  466. const Vector& origin,
  467. const QAngle& angles,
  468. ERenderDepthMode DepthMode )
  469. {
  470. R_DrawBrushModel( baseentity, model, origin, angles, DepthMode, true, true );
  471. }
  472. void UpdateBrushModelLightmap( model_t *model, IClientRenderable *pRenderable )
  473. {
  474. g_EngineRenderer->UpdateBrushModelLightmap( model, pRenderable );
  475. }
  476. void BeginUpdateLightmaps( void )
  477. {
  478. g_EngineRenderer->BeginUpdateLightmaps();
  479. }
  480. void EndUpdateLightmaps( void )
  481. {
  482. g_EngineRenderer->EndUpdateLightmaps();
  483. }
  484. virtual void Push3DView( const CViewSetup &view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes, ITexture* pDepthTexture )
  485. {
  486. g_EngineRenderer->Push3DView( view, nFlags, pRenderTarget, frustumPlanes, pDepthTexture );
  487. }
  488. void GetMatricesForView( const CViewSetup &view, VMatrix *pWorldToView, VMatrix *pViewToProjection, VMatrix *pWorldToProjection, VMatrix *pWorldToPixels )
  489. {
  490. ComputeViewMatrices( pWorldToView, pViewToProjection, pWorldToProjection, view );
  491. ComputeWorldToScreenMatrix( pWorldToPixels, *pWorldToProjection, view );
  492. }
  493. };
  494. static CVRenderView s_RenderView;
  495. EXPOSE_SINGLE_INTERFACE_GLOBALVAR( CVRenderView, IVRenderView, VENGINE_RENDERVIEW_INTERFACE_VERSION, s_RenderView );