Counter Strike : Global Offensive Source Code
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

1261 lines
38 KiB

  1. //===== Copyright (c) Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //==================================================================//
  8. #include "render_pch.h"
  9. #include "client.h"
  10. #include "sound.h"
  11. #include "debug_leafvis.h"
  12. #include "cdll_int.h"
  13. #include "enginestats.h"
  14. #include "ivrenderview.h"
  15. #include "studio.h"
  16. #include "l_studio.h"
  17. #include "r_areaportal.h"
  18. #include "materialsystem/materialsystem_config.h"
  19. #include "materialsystem/itexture.h"
  20. #include "cdll_engine_int.h"
  21. #include "materialsystem/imaterialsystemhardwareconfig.h"
  22. #include "istudiorender.h"
  23. #include "staticpropmgr.h"
  24. #include "tier0/vprof.h"
  25. #include "IOcclusionSystem.h"
  26. #include "con_nprint.h"
  27. #include "debugoverlay.h"
  28. #include "demo.h"
  29. #include "ivideomode.h"
  30. #include "sys_dll.h"
  31. #include "collisionutils.h"
  32. #include "tier1/utlstack.h"
  33. #include "r_decal.h"
  34. #include "cl_main.h"
  35. #include "paint.h"
  36. // memdbgon must be the last include file in a .cpp file!!!
  37. #include "tier0/memdbgon.h"
  38. #ifndef _X360
  39. extern ConVar r_waterforceexpensive;
  40. #endif
  41. ConVar r_aspectratio( "r_aspectratio", "0" );
  42. ConVar r_dynamiclighting( "r_dynamiclighting", "1", FCVAR_CHEAT );
  43. extern ConVar building_cubemaps;
  44. extern float scr_demo_override_fov;
  45. extern colorVec R_LightPoint (Vector& p);
  46. CEngineStats g_EngineStats;
  47. //-----------------------------------------------------------------------------
  48. // view origin
  49. //-----------------------------------------------------------------------------
  50. extern Vector g_CurrentViewOrigin, g_CurrentViewForward, g_CurrentViewRight, g_CurrentViewUp;
  51. extern Vector g_MainViewOrigin[ MAX_SPLITSCREEN_CLIENTS ];
  52. extern Vector g_MainViewForward[ MAX_SPLITSCREEN_CLIENTS ];
  53. extern Vector g_MainViewRight[ MAX_SPLITSCREEN_CLIENTS ];
  54. extern Vector g_MainViewUp[ MAX_SPLITSCREEN_CLIENTS ];
  55. bool g_bCanAccessCurrentView = false;
  56. int d_lightstyleframe[256];
  57. CUtlVector<LightmapUpdateInfo_t> g_LightmapUpdateList;
  58. CUtlVector<LightmapTransformInfo_t> g_LightmapTransformList;
  59. void ProjectPointOnPlane( Vector& dst, const Vector& p, const Vector& normal )
  60. {
  61. float d;
  62. Vector n;
  63. float inv_denom;
  64. inv_denom = 1.0F / DotProduct( normal, normal );
  65. d = DotProduct( normal, p ) * inv_denom;
  66. n[0] = normal[0] * inv_denom;
  67. n[1] = normal[1] * inv_denom;
  68. n[2] = normal[2] * inv_denom;
  69. dst[0] = p[0] - d * n[0];
  70. dst[1] = p[1] - d * n[1];
  71. dst[2] = p[2] - d * n[2];
  72. }
  73. /*
  74. ** assumes "src" is normalized
  75. */
  76. void PerpendicularVector( Vector& dst, const Vector& src )
  77. {
  78. int pos;
  79. int i;
  80. float minelem = 1.0F;
  81. Vector tempvec;
  82. /*
  83. ** find the smallest magnitude axially aligned vector
  84. */
  85. for ( pos = 0, i = 0; i < 3; i++ )
  86. {
  87. if ( fabs( src[i] ) < minelem )
  88. {
  89. pos = i;
  90. minelem = fabs( src[i] );
  91. }
  92. }
  93. tempvec[0] = tempvec[1] = tempvec[2] = 0.0F;
  94. tempvec[pos] = 1.0F;
  95. /*
  96. ** project the point onto the plane defined by src
  97. */
  98. ProjectPointOnPlane( dst, tempvec, src );
  99. /*
  100. ** normalize the result
  101. */
  102. VectorNormalize( dst );
  103. }
  104. //-----------------------------------------------------------------------------
  105. // Returns the PHYSICAL aspect ratio of the screen (not the pixel aspect ratio)
  106. //-----------------------------------------------------------------------------
  107. float GetScreenAspect( int viewportWidth, int viewportHeight )
  108. {
  109. // use the override if set
  110. if ( r_aspectratio.GetFloat() > 0.0f )
  111. return r_aspectratio.GetFloat();
  112. const AspectRatioInfo_t &aspectRatioInfo = materials->GetAspectRatioInfo();
  113. // just use the viewport size, but we have to convert from pixels to real-world "size".
  114. return ( viewportHeight != 0 ) ? ( aspectRatioInfo.m_flFrameBuffertoPhysicalScalar * ( ( float )viewportWidth / ( float )viewportHeight ) ) : 1.0f;
  115. }
  116. /*
  117. ====================
  118. CalcFov
  119. ====================
  120. */
  121. void R_DrawScreenRect( float left, float top, float right, float bottom )
  122. {
  123. CMatRenderContextPtr pRenderContext( materials );
  124. pRenderContext->MatrixMode( MATERIAL_VIEW );
  125. pRenderContext->PushMatrix();
  126. pRenderContext->LoadIdentity();
  127. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  128. pRenderContext->PushMatrix();
  129. pRenderContext->LoadIdentity();
  130. IMaterial *pMaterial = materials->FindMaterial( "debug/debugportals", TEXTURE_GROUP_OTHER );
  131. IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, pMaterial );
  132. CMeshBuilder builder;
  133. builder.Begin( pMesh, MATERIAL_LINE_LOOP, 4 );
  134. Vector v1( left, bottom, 0.5 );
  135. Vector v2( left, top, 0.5 );
  136. Vector v3( right, top, 0.5 );
  137. Vector v4( right, bottom, 0.5 );
  138. builder.Position3fv( v1.Base() ); builder.AdvanceVertex();
  139. builder.Position3fv( v2.Base() ); builder.AdvanceVertex();
  140. builder.Position3fv( v3.Base() ); builder.AdvanceVertex();
  141. builder.Position3fv( v4.Base() ); builder.AdvanceVertex();
  142. builder.End( false, true );
  143. pRenderContext->MatrixMode( MATERIAL_VIEW );
  144. pRenderContext->PopMatrix();
  145. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  146. pRenderContext->PopMatrix();
  147. }
  148. void R_DrawPortals()
  149. {
  150. // Draw the portals.
  151. if( !r_DrawPortals.GetInt() )
  152. return;
  153. IMaterial *pMaterial = materials->FindMaterial( "debug/debugportals", TEXTURE_GROUP_OTHER );
  154. CMatRenderContextPtr pRenderContext( materials );
  155. IMesh *pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, pMaterial );
  156. worldbrushdata_t *pBrushData = host_state.worldbrush;
  157. for( int i=0; i < pBrushData->m_nAreaPortals; i++ )
  158. {
  159. dareaportal_t *pAreaPortal = &pBrushData->m_pAreaPortals[i];
  160. if( !R_IsAreaVisible( pAreaPortal->otherarea ) )
  161. continue;
  162. CMeshBuilder builder;
  163. builder.Begin( pMesh, MATERIAL_LINES, pAreaPortal->m_nClipPortalVerts );
  164. for( int j=0; j < pAreaPortal->m_nClipPortalVerts; j++ )
  165. {
  166. unsigned short iVert;
  167. iVert = pAreaPortal->m_FirstClipPortalVert + j;
  168. builder.Position3f( VectorExpand( pBrushData->m_pClipPortalVerts[iVert] ) );
  169. builder.Color4f( 0, 0, 0, 1 );
  170. builder.AdvanceVertex();
  171. iVert = pAreaPortal->m_FirstClipPortalVert + (j+1) % pAreaPortal->m_nClipPortalVerts;
  172. builder.Position3f( VectorExpand( pBrushData->m_pClipPortalVerts[iVert] ) );
  173. builder.Color4f( 0, 0, 0, 1 );
  174. builder.AdvanceVertex();
  175. }
  176. builder.End( false, true );
  177. }
  178. // Draw the clip rectangles.
  179. for( int i=0; i < g_PortalRects.Count(); i++ )
  180. {
  181. CPortalRect *pRect = &g_PortalRects[i];
  182. R_DrawScreenRect( pRect->left, pRect->top, pRect->right, pRect->bottom );
  183. }
  184. g_PortalRects.Purge();
  185. }
  186. //-----------------------------------------------------------------------------
  187. //
  188. // Loose collection of functions related to rendering the world in a particular view
  189. //
  190. //-----------------------------------------------------------------------------
  191. class CRender : public IRender
  192. {
  193. public:
  194. CRender();
  195. void FrameBegin( void );
  196. void FrameEnd( void );
  197. void ViewSetupVis( bool novis, int numorigins, const Vector origin[] );
  198. void ViewSetupVisEx( bool novis, int numorigins, const Vector origin[], unsigned int &returnFlags );
  199. void ViewEnd( void );
  200. void ViewDrawFade( byte *color, IMaterial* pMaterial, bool mapFullTextureToScreen = true );
  201. IWorldRenderList * CreateWorldList();
  202. #if defined(_PS3)
  203. IWorldRenderList * CreateWorldList_PS3( int viewID );
  204. void BuildWorldLists_PS3_Epilogue( IWorldRenderList *pList, WorldListInfo_t* pInfo, bool bShadowDepth );
  205. int GetDrawFlags( void );
  206. int GetBuildViewID( void );
  207. bool IsSPUBuildWRJobsOn( void );
  208. void CacheFrustumData( Frustum_t *pFrustum, Frustum_t *pAreaFrustum, void *pRenderAreaBits, int numArea, bool bViewerInSolidSpace );
  209. #else
  210. void BuildWorldLists_Epilogue( IWorldRenderList *pList, WorldListInfo_t* pInfo, bool bShadowDepth );
  211. #endif
  212. void BuildWorldLists( IWorldRenderList *pList, WorldListInfo_t* pInfo, int iForceViewLeaf, const VisOverrideData_t* pVisData, bool bShadowDepth, float *pWaterReflectionHeight );
  213. void DrawWorldLists( IMatRenderContext *pRenderContext, IWorldRenderList *pList, unsigned long flags, float waterZAdjust );
  214. void DrawSceneBegin( void );
  215. void DrawSceneEnd( void );
  216. // utility functions
  217. void ExtractMatrices( void );
  218. void ExtractFrustumPlanes( Frustum frustumPlanes );
  219. void OrthoExtractFrustumPlanes( Frustum frustumPlanes );
  220. void OverrideViewFrustum( Frustum custom );
  221. void SetViewport( int x, int y, int w, int h );
  222. // UNDONE: these are temporary functions that will end up on the other
  223. // side of this interface
  224. const Vector &ViewOrigin( ) { return CurrentView().origin; }
  225. const QAngle &ViewAngles( ) { return CurrentView().angles; }
  226. const CViewSetup &ViewGetCurrent( void ) { return CurrentView(); }
  227. const VMatrix &ViewMatrix( void );
  228. const VMatrix &WorldToScreenMatrix( void );
  229. float GetFramerate( void ) { return m_framerate; }
  230. virtual float GetZNear( void ) { return m_zNear; }
  231. virtual float GetZFar( void ) { return m_zFar; }
  232. // Query current fov and view model fov
  233. float GetFov( void ) { return CurrentView().fov; };
  234. float GetFovY( void ) { return m_yFOV; };
  235. float GetFovViewmodel( void ) { return CurrentView().fovViewmodel; };
  236. virtual bool ClipTransform( const Vector& point, Vector* pClip );
  237. virtual bool ScreenTransform( const Vector& point, Vector* pScreen );
  238. virtual void Push3DView( IMatRenderContext *pRenderContext, const CViewSetup &view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes );
  239. virtual void Push3DView( IMatRenderContext *pRenderContext, const CViewSetup &view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes, ITexture* pDepthTexture );
  240. virtual void Push2DView( IMatRenderContext *pRenderContext, const CViewSetup &view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes );
  241. virtual void PopView( IMatRenderContext *pRenderContext, Frustum frustumPlanes );
  242. virtual void SetMainView( const Vector &vecOrigin, const QAngle &angles );
  243. virtual void UpdateBrushModelLightmap( model_t *model, IClientRenderable *Renderable );
  244. virtual void BeginUpdateLightmaps( void );
  245. virtual void EndUpdateLightmaps( void );
  246. virtual bool InLightmapUpdate( void ) const;
  247. private:
  248. // Called when a particular view becomes active
  249. void OnViewActive( Frustum frustumPlanes );
  250. // Clear the view (assumes the render target has already been pushed)
  251. void ClearView( IMatRenderContext *pRenderContext, CViewSetup &view, int nFlags, ITexture* pRenderTarget, ITexture* pDepthTexture = NULL );
  252. const CViewSetup &CurrentView() const { return m_ViewStack.Top().m_View; }
  253. CViewSetup &CurrentView() { return m_ViewStack.Top().m_View; }
  254. // Stack of view info
  255. struct ViewStack_t
  256. {
  257. CViewSetup m_View;
  258. // matrices
  259. VMatrix m_matrixView;
  260. VMatrix m_matrixProjection;
  261. VMatrix m_matrixWorldToScreen;
  262. bool m_bIs2DView;
  263. bool m_bNoDraw;
  264. };
  265. // Y field of view, calculated from X FOV and screen aspect ratio.
  266. float m_yFOV;
  267. // timing
  268. double m_frameStartTime;
  269. float m_framerate;
  270. float m_zNear;
  271. float m_zFar;
  272. // matrices
  273. VMatrix m_matrixView;
  274. VMatrix m_matrixProjection;
  275. VMatrix m_matrixWorldToScreen;
  276. CUtlStack< ViewStack_t > m_ViewStack;
  277. int m_iLightmapUpdateDepth;
  278. };
  279. //-----------------------------------------------------------------------------
  280. // Singleton
  281. //-----------------------------------------------------------------------------
  282. static CRender gRender;
  283. IRender *g_EngineRenderer = &gRender;
  284. //-----------------------------------------------------------------------------
  285. // Called when the engine is about to begin rendering for any reason
  286. //-----------------------------------------------------------------------------
  287. CRender::CRender()
  288. {
  289. // Make sure the stack isn't empty
  290. int i = m_ViewStack.Push();
  291. memset( &m_ViewStack[i], 0, sizeof( CViewSetup ) );
  292. m_ViewStack[i].m_bIs2DView = true;
  293. m_iLightmapUpdateDepth = 0;
  294. }
  295. //-----------------------------------------------------------------------------
  296. // Called when the engine is about to begin rendering for any reason
  297. //-----------------------------------------------------------------------------
  298. void CRender::FrameBegin( void )
  299. {
  300. if ( host_state.worldmodel )
  301. {
  302. // This has to be before R_AnimateLight because it uses it to
  303. // set the frame number of changed lightstyles
  304. // FIXME: Why isn't this being done in DrawSceneBegin
  305. // or some other client-side simulation of state?
  306. r_framecount++;
  307. if ( g_RendererInLevel )
  308. {
  309. R_AnimateLight ();
  310. R_PushDlights();
  311. }
  312. if (!r_norefresh.GetInt())
  313. {
  314. m_frameStartTime = Sys_FloatTime ();
  315. }
  316. g_LightmapTransformList.RemoveAll();
  317. int index = g_LightmapTransformList.AddToTail();
  318. g_LightmapTransformList[index].pModel = host_state.worldmodel;
  319. SetIdentityMatrix( g_LightmapTransformList[index].xform );
  320. }
  321. UpdateStudioRenderConfig();
  322. g_pStudioRender->BeginFrame();
  323. }
  324. #ifndef _CERT
  325. static void PrintRenderedFaceInfoCallback( int nTopN, IStudioRender::FacesRenderedInfo_t *pFaces, int nTotalFaces )
  326. {
  327. if ( nTopN > 0 )
  328. {
  329. con_nprint_s printdesc;
  330. printdesc.time_to_live = -1;
  331. printdesc.color[0] = printdesc.color[1] = printdesc.color[2] = 1.0f;
  332. printdesc.fixed_width_font = false;
  333. printdesc.index = 1;
  334. Con_NXPrintf( &printdesc, "%d total faces in scene", nTotalFaces );
  335. ++ printdesc.index;
  336. Con_NXPrintf( &printdesc, "Printing %d top offending models", nTopN );
  337. ++ printdesc.index;
  338. Con_NXPrintf( &printdesc, "%50s%15s%15s%15s", "Model Name", "# Renders", "Total Tris", "Avg Tris" );
  339. for ( int i = 0; i < nTopN; ++ i )
  340. {
  341. ++ printdesc.index;
  342. Con_NXPrintf( &printdesc, "%50s%15d%15d%15d", pFaces[i].pStudioHdr->name, pFaces[i].nRenderCount, pFaces[i].nFaceCount, ( int )( ( float )pFaces[i].nFaceCount / ( float )pFaces[i].nRenderCount ) );
  343. }
  344. }
  345. }
  346. #endif // !_CERT
  347. //-----------------------------------------------------------------------------
  348. // Called when the engine has finished rendering
  349. //-----------------------------------------------------------------------------
  350. void CRender::FrameEnd( void )
  351. {
  352. // A debugging overlay that renders all raycasts.
  353. // Why, or why is this being done here instead of
  354. // where all the other debug overlays are being done in the client DLL?
  355. EngineTraceRenderRayCasts();
  356. m_framerate = GetBaseLocalClient().GetFrameTime();
  357. if ( m_framerate > 0 )
  358. {
  359. m_framerate = 1 / m_framerate;
  360. }
  361. g_pStudioRender->EndFrame();
  362. #ifndef _CERT
  363. g_pStudioRender->GatherRenderedFaceInfo( PrintRenderedFaceInfoCallback );
  364. #endif // !_CERT
  365. g_LightmapTransformList.RemoveAll();
  366. }
  367. const VMatrix &CRender::ViewMatrix( )
  368. {
  369. // If we aren't in a valid view, then use the last value cached off into the global variable instead
  370. if ( m_ViewStack.Count() > 1 )
  371. {
  372. return m_ViewStack.Top().m_matrixView;
  373. }
  374. return m_matrixView;
  375. }
  376. const VMatrix &CRender::WorldToScreenMatrix( void )
  377. {
  378. // If we aren't in a valid view, then use the last value cached off into the global variable instead
  379. if ( m_ViewStack.Count() > 1 )
  380. {
  381. return m_ViewStack.Top().m_matrixWorldToScreen;
  382. }
  383. return m_matrixWorldToScreen;
  384. }
  385. void CRender::ViewSetupVis( bool novis, int numorigins, const Vector origin[] )
  386. {
  387. unsigned int returnFlags = 0;
  388. ViewSetupVisEx( novis, numorigins, origin, returnFlags );
  389. }
  390. void CRender::ViewSetupVisEx( bool novis, int numorigins, const Vector origin[], unsigned int &returnFlags )
  391. {
  392. Map_VisSetup( host_state.worldmodel, numorigins, origin, novis, returnFlags );
  393. }
  394. //-----------------------------------------------------------------------------
  395. // Called when a particular view becomes active
  396. //-----------------------------------------------------------------------------
  397. void CRender::OnViewActive( Frustum frustumPlanes )
  398. {
  399. const CViewSetup &view = CurrentView();
  400. m_yFOV = CalcFovY( view.fov, view.m_flAspectRatio );
  401. // build the transformation matrix for the given view angles
  402. VectorCopy( view.origin, g_CurrentViewOrigin );
  403. AngleVectors( view.angles, &g_CurrentViewForward, &g_CurrentViewRight, &g_CurrentViewUp );
  404. // g_CurrentViewUp = -g_CurrentViewUp;
  405. g_bCanAccessCurrentView = true;
  406. if ( frustumPlanes )
  407. {
  408. if ( view.m_bOrtho )
  409. {
  410. OrthoExtractFrustumPlanes( frustumPlanes );
  411. }
  412. else
  413. {
  414. ExtractFrustumPlanes( frustumPlanes );
  415. }
  416. OcclusionSystem()->SetView( view.origin, view.fov, m_matrixView, m_matrixProjection, frustumPlanes[ FRUSTUM_NEARZ ] );
  417. }
  418. if ( !m_ViewStack.Top().m_bNoDraw )
  419. {
  420. R_SceneBegin( );
  421. }
  422. // debug, build leaf volume
  423. // NOTE: This is pretty hacky, but I want the leaf based on the main view. The skybox view is reseting
  424. // the g_LeafVis here because it is global. This need to be resolved more correctly some other way!
  425. if ( VectorCompare( MainViewOrigin(), view.origin ) )
  426. {
  427. LeafVisBuild( view.origin );
  428. }
  429. }
  430. //-----------------------------------------------------------------------------
  431. // Clear the view (assumes the render target has already been pushed)
  432. //-----------------------------------------------------------------------------
  433. void CRender::ClearView( IMatRenderContext *pRenderContext, CViewSetup &view, int nFlags, ITexture* pRenderTarget, ITexture* pDepthTexture /* = NULL */ )
  434. {
  435. bool bClearColor = (nFlags & VIEW_CLEAR_COLOR) != 0;
  436. bool bClearDepth = (nFlags & VIEW_CLEAR_DEPTH) != 0;
  437. bool bClearStencil = (nFlags & VIEW_CLEAR_STENCIL) != 0;
  438. bool bForceClearWholeRenderTarget = (nFlags & VIEW_CLEAR_FULL_TARGET) != 0;
  439. bool bObeyStencil = (nFlags & VIEW_CLEAR_OBEY_STENCIL) != 0;
  440. // Handle an initial clear request if asked for
  441. if ( !bClearColor && !bClearDepth && !bClearStencil )
  442. return;
  443. if ( !bForceClearWholeRenderTarget )
  444. {
  445. if( bObeyStencil )
  446. {
  447. pRenderContext->ClearBuffersObeyStencil( bClearColor, bClearDepth );
  448. }
  449. else
  450. {
  451. pRenderContext->ClearBuffers( bClearColor, bClearDepth, bClearStencil );
  452. }
  453. }
  454. else
  455. {
  456. // Get the render target dimensions
  457. int nWidth, nHeight;
  458. if ( pRenderTarget )
  459. {
  460. nWidth = pRenderTarget->GetActualWidth();
  461. nHeight = pRenderTarget->GetActualHeight();
  462. }
  463. else
  464. {
  465. materials->GetBackBufferDimensions( nWidth, nHeight );
  466. }
  467. pRenderContext->PushRenderTargetAndViewport( pRenderTarget, pDepthTexture, 0, 0, nWidth, nHeight );
  468. if( bObeyStencil )
  469. {
  470. pRenderContext->ClearBuffersObeyStencil( bClearColor, bClearDepth );
  471. }
  472. else
  473. {
  474. pRenderContext->ClearBuffers( bClearColor, bClearDepth, bClearStencil );
  475. }
  476. pRenderContext->PopRenderTargetAndViewport( );
  477. }
  478. }
  479. //-----------------------------------------------------------------------------
  480. // Push, pop views
  481. //-----------------------------------------------------------------------------
  482. void CRender::Push3DView( IMatRenderContext *pRenderContext, const CViewSetup &view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes )
  483. {
  484. Push3DView( pRenderContext, view, nFlags, pRenderTarget, frustumPlanes, NULL );
  485. }
  486. // Flip y, screen y goes down
  487. static VMatrix g_ProjectionToOffset( 0.5f, 0.0f, 0.0f, 0.5f,
  488. 0.0f, -0.5f, 0.0f, 0.5f,
  489. 0.0f, 0.0f, 1.0f, 0.0f,
  490. 0.0f, 0.0f, 0.0f, 1.0f );
  491. // NOTE: Screen coordinates go from 0->w, 0->h
  492. void ComputeWorldToScreenMatrix( VMatrix *pWorldToScreen, const VMatrix &worldToProjection, const CViewSetup &viewSetup )
  493. {
  494. // First need to transform -1 -> 1 to 0 -> 1 in x and y
  495. // Then transform from 0->1 to x->w+x in x, and 0->1 to y->y+h in y.
  496. VMatrix offsetToPixels( viewSetup.width, 0.0f, 0.0f, viewSetup.x,
  497. 0.0f, viewSetup.height, 0.0f, viewSetup.y,
  498. 0.0f, 0.0f, 1.0f, 0.0f,
  499. 0.0f, 0.0f, 0.0f, 1.0f );
  500. VMatrix projectionToPixels;
  501. MatrixMultiply( offsetToPixels, g_ProjectionToOffset, projectionToPixels );
  502. MatrixMultiply( projectionToPixels, worldToProjection, *pWorldToScreen );
  503. }
  504. //-----------------------------------------------------------------------------
  505. // Push, pop views
  506. //-----------------------------------------------------------------------------
  507. void CRender::Push3DView( IMatRenderContext *pRenderContext, const CViewSetup &view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes, ITexture* pDepthTexture )
  508. {
  509. Assert( !IsX360() || (pDepthTexture == NULL) ); //Don't render to a depth texture on the 360. Instead, render using a normal depth buffer and use IDirect3DDevice9::Resolve()
  510. int i = m_ViewStack.Push( );
  511. m_ViewStack[i].m_View = view;
  512. m_ViewStack[i].m_bIs2DView = false;
  513. m_ViewStack[i].m_bNoDraw = ( ( nFlags & VIEW_NO_DRAW ) != 0 );
  514. CViewSetup &topView = m_ViewStack[i].m_View;
  515. // Compute aspect ratio if asked for
  516. if ( topView.m_flAspectRatio == 0.0f )
  517. {
  518. topView.m_flAspectRatio = (topView.height != 0) ? ( (float)topView.width / (float)topView.height ) : 1.0f;
  519. }
  520. ViewStack_t &viewStack = m_ViewStack.Top();
  521. topView.m_flAspectRatio = topView.ComputeViewMatrices( &viewStack.m_matrixView,
  522. &viewStack.m_matrixProjection, &viewStack.m_matrixWorldToScreen );
  523. m_zNear = topView.zNear;
  524. m_zFar = topView.zFar; // cache this for queries
  525. ExtractMatrices();
  526. if ( !m_ViewStack[i].m_bNoDraw )
  527. {
  528. if ( !pRenderTarget )
  529. {
  530. pRenderTarget = pRenderContext->GetRenderTarget();
  531. }
  532. // Push render target and viewport
  533. pRenderContext->PushRenderTargetAndViewport( pRenderTarget, pDepthTexture, topView.x, topView.y, topView.width, topView.height );
  534. // Handle an initial clear request if asked for
  535. ClearView( pRenderContext, topView, nFlags, pRenderTarget, pDepthTexture );
  536. pRenderContext->DepthRange( 0, 1 );
  537. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  538. pRenderContext->PushMatrix();
  539. pRenderContext->LoadMatrix( m_matrixProjection );
  540. pRenderContext->MatrixMode( MATERIAL_VIEW );
  541. pRenderContext->PushMatrix();
  542. pRenderContext->LoadMatrix( m_matrixView );
  543. pRenderContext->MatrixMode( MATERIAL_MODEL );
  544. pRenderContext->PushMatrix();
  545. OnViewActive( frustumPlanes );
  546. }
  547. }
  548. void CRender::Push2DView( IMatRenderContext *pRenderContext, const CViewSetup &view, int nFlags, ITexture* pRenderTarget, Frustum frustumPlanes )
  549. {
  550. int i = m_ViewStack.Push( );
  551. m_ViewStack[i].m_View = view;
  552. m_ViewStack[i].m_bIs2DView = true;
  553. m_ViewStack[i].m_bNoDraw = ( ( nFlags & VIEW_NO_DRAW ) != 0 );
  554. m_ViewStack[i].m_matrixView = m_matrixView;
  555. m_ViewStack[i].m_matrixProjection = m_matrixProjection;
  556. m_ViewStack[i].m_matrixWorldToScreen = m_matrixWorldToScreen;
  557. CViewSetup &topView = m_ViewStack[i].m_View;
  558. g_bCanAccessCurrentView = false;
  559. if ( !pRenderTarget )
  560. {
  561. pRenderTarget = pRenderContext->GetRenderTarget();
  562. }
  563. // Push render target and viewport
  564. pRenderContext->PushRenderTargetAndViewport( pRenderTarget, topView.x, topView.y, topView.width, topView.height );
  565. // Handle an initial clear request if asked for
  566. ClearView( pRenderContext, topView, nFlags, pRenderTarget );
  567. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  568. pRenderContext->PushMatrix();
  569. pRenderContext->LoadIdentity();
  570. pRenderContext->Scale( 1, -1, 1 );
  571. pRenderContext->Ortho( 0, 0, topView.width, topView.height, -99999, 99999 );
  572. pRenderContext->MatrixMode( MATERIAL_VIEW );
  573. pRenderContext->PushMatrix();
  574. pRenderContext->LoadIdentity();
  575. pRenderContext->MatrixMode( MATERIAL_MODEL );
  576. pRenderContext->PushMatrix();
  577. pRenderContext->LoadIdentity();
  578. }
  579. void CRender::PopView( IMatRenderContext *pRenderContext, Frustum frustumPlanes )
  580. {
  581. if ( !m_ViewStack.Top().m_bNoDraw )
  582. {
  583. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  584. pRenderContext->PopMatrix();
  585. pRenderContext->MatrixMode( MATERIAL_VIEW );
  586. pRenderContext->PopMatrix();
  587. pRenderContext->MatrixMode( MATERIAL_MODEL );
  588. pRenderContext->PopMatrix();
  589. pRenderContext->PopRenderTargetAndViewport( );
  590. }
  591. bool bReset = ( m_ViewStack.Count() > 1 ) ? true : false;
  592. m_ViewStack.Pop();
  593. // Don't pop off the very last view
  594. g_bCanAccessCurrentView = false;
  595. if ( bReset )
  596. {
  597. if ( !m_ViewStack.Top().m_bIs2DView )
  598. {
  599. ExtractMatrices();
  600. m_zNear = m_ViewStack.Top().m_View.zNear;
  601. m_zFar = m_ViewStack.Top().m_View.zFar;
  602. OnViewActive( frustumPlanes );
  603. }
  604. }
  605. }
  606. //-----------------------------------------------------------------------------
  607. // Sets the main 3D view (for console commands, sound, etc.)
  608. //-----------------------------------------------------------------------------
  609. void CRender::SetMainView( const Vector &vecOrigin, const QAngle &angles )
  610. {
  611. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  612. int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
  613. VectorCopy( vecOrigin, g_MainViewOrigin[ nSlot ] );
  614. AngleVectors( angles, &g_MainViewForward[ nSlot ], &g_MainViewRight[ nSlot ], &g_MainViewUp[ nSlot ] );
  615. }
  616. void CRender::BeginUpdateLightmaps( void )
  617. {
  618. if ( ++m_iLightmapUpdateDepth == 1)
  619. {
  620. Assert( g_LightmapUpdateList.Count() == 0 );
  621. materials->BeginUpdateLightmaps();
  622. }
  623. }
  624. void CRender::UpdateBrushModelLightmap( model_t *model, IClientRenderable *pRenderable )
  625. {
  626. AssertOnce( m_iLightmapUpdateDepth );
  627. if( !r_drawbrushmodels.GetBool() || !m_iLightmapUpdateDepth )
  628. return;
  629. R_MarkDlightsOnBrushModel( model, pRenderable );
  630. bool bLightingChanged = Mod_NeedsLightstyleUpdate( model );
  631. if ( (model->flags & MODELFLAG_HAS_DLIGHT) || bLightingChanged )
  632. {
  633. int transformIndex = g_LightmapTransformList.AddToTail();
  634. LightmapTransformInfo_t &transform = g_LightmapTransformList[transformIndex];
  635. transform.pModel = model;
  636. AngleMatrix( pRenderable->GetRenderAngles(), pRenderable->GetRenderOrigin(), transform.xform );
  637. SurfaceHandle_t surfID = SurfaceHandleFromIndex( model->brush.firstmodelsurface, model->brush.pShared );
  638. bool bLight = false;
  639. for (int i=0 ; i<model->brush.nummodelsurfaces ; i++, surfID++)
  640. {
  641. if ( MSurf_Flags(surfID) & (SURFDRAW_HASDLIGHT|SURFDRAW_HASLIGHTSYTLES) )
  642. {
  643. R_CheckForLightmapUpdates( surfID, transformIndex );
  644. if ( MSurf_Flags(surfID) & SURFDRAW_HASDLIGHT )
  645. {
  646. bLight = true;
  647. }
  648. }
  649. }
  650. if ( !bLight )
  651. {
  652. model->flags &= ~MODELFLAG_HAS_DLIGHT; // don't need to check again unless a dlight hits us
  653. }
  654. }
  655. if ( bLightingChanged )
  656. {
  657. model->brush.nLightstyleLastComputedFrame = r_framecount;
  658. }
  659. }
  660. void CRender::EndUpdateLightmaps( void )
  661. {
  662. Assert( m_iLightmapUpdateDepth > 0 );
  663. if ( --m_iLightmapUpdateDepth == 0 )
  664. {
  665. VPROF_BUDGET( "EndUpdateLightmaps", VPROF_BUDGETGROUP_DLIGHT_RENDERING );
  666. if ( g_LightmapUpdateList.Count() && r_dynamiclighting.GetBool() && !r_unloadlightmaps.GetBool() )
  667. {
  668. VPROF_("R_BuildLightmapUpdateList", 1, VPROF_BUDGETGROUP_DLIGHT_RENDERING, false, 0);
  669. R_BuildLightmapUpdateList();
  670. }
  671. {
  672. VPROF_("materials_EndUpdateLightmaps", 1, VPROF_BUDGETGROUP_DLIGHT_RENDERING, false, 0);
  673. materials->EndUpdateLightmaps();
  674. }
  675. {
  676. g_LightmapUpdateList.RemoveAll();
  677. VPROF_("lightmap_RemoveAll", 1, VPROF_BUDGETGROUP_DLIGHT_RENDERING, false, 0);
  678. }
  679. }
  680. }
  681. bool CRender::InLightmapUpdate( void ) const
  682. {
  683. return ( m_iLightmapUpdateDepth != 0 );
  684. }
  685. //-----------------------------------------------------------------------------
  686. // Compute the scene coordinates of a point in 3D
  687. //-----------------------------------------------------------------------------
  688. bool CRender::ClipTransform( const Vector& point, Vector* pClip )
  689. {
  690. // UNDONE: Clean this up some, handle off-screen vertices
  691. float w;
  692. const VMatrix &worldToScreen = g_EngineRenderer->WorldToScreenMatrix();
  693. pClip->x = worldToScreen[0][0] * point[0] + worldToScreen[0][1] * point[1] + worldToScreen[0][2] * point[2] + worldToScreen[0][3];
  694. pClip->y = worldToScreen[1][0] * point[0] + worldToScreen[1][1] * point[1] + worldToScreen[1][2] * point[2] + worldToScreen[1][3];
  695. // z = worldToScreen[2][0] * point[0] + worldToScreen[2][1] * point[1] + worldToScreen[2][2] * point[2] + worldToScreen[2][3];
  696. w = worldToScreen[3][0] * point[0] + worldToScreen[3][1] * point[1] + worldToScreen[3][2] * point[2] + worldToScreen[3][3];
  697. // Just so we have something valid here
  698. pClip->z = 0.0f;
  699. bool behind;
  700. if( w < 0.001f )
  701. {
  702. behind = true;
  703. pClip->x *= 100000;
  704. pClip->y *= 100000;
  705. }
  706. else
  707. {
  708. behind = false;
  709. float invw = 1.0f / w;
  710. pClip->x *= invw;
  711. pClip->y *= invw;
  712. }
  713. return behind;
  714. }
  715. //-----------------------------------------------------------------------------
  716. // Purpose: Given a point, return the screen position in pixels
  717. //-----------------------------------------------------------------------------
  718. bool CRender::ScreenTransform( const Vector& point, Vector* pScreen )
  719. {
  720. bool retval = ClipTransform( point, pScreen );
  721. pScreen->x = 0.5f * ( pScreen->x + 1.0f ) * CurrentView().width + CurrentView().x;
  722. pScreen->y = 0.5f * ( pScreen->y + 1.0f ) * CurrentView().height + CurrentView().y;
  723. return retval;
  724. }
  725. void CRender::ViewDrawFade( byte *color, IMaterial* pFadeMaterial, bool mapFullTextureToScreen )
  726. {
  727. if ( !color || !color[3] )
  728. return;
  729. if( !pFadeMaterial )
  730. return;
  731. const CViewSetup &view = CurrentView();
  732. CMatRenderContextPtr pRenderContext( materials );
  733. pRenderContext->PushRenderTargetAndViewport();
  734. pRenderContext->Bind( pFadeMaterial );
  735. pFadeMaterial->AlphaModulate( color[3] * ( 1.0f / 255.0f ) );
  736. pFadeMaterial->ColorModulate( color[0] * ( 1.0f / 255.0f ),
  737. color[1] * ( 1.0f / 255.0f ),
  738. color[2] * ( 1.0f / 255.0f ) );
  739. bool bOldIgnoreZ = pFadeMaterial->GetMaterialVarFlag( MATERIAL_VAR_IGNOREZ );
  740. pFadeMaterial->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, true );
  741. int nTexWidth, nTexHeight;
  742. nTexWidth = pFadeMaterial->GetMappingWidth();
  743. nTexHeight = pFadeMaterial->GetMappingHeight();
  744. float flUOffset = 0.5f / nTexWidth;
  745. float flVOffset = 0.5f / nTexHeight;
  746. int width, height;
  747. pRenderContext->GetRenderTargetDimensions( width, height );
  748. pRenderContext->Viewport( 0, 0, width, height );
  749. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  750. pRenderContext->PushMatrix();
  751. pRenderContext->LoadIdentity();
  752. pRenderContext->Scale( 1, -1, 1 );
  753. pRenderContext->Ortho( 0, 0, width, height, -99999, 99999 );
  754. pRenderContext->MatrixMode( MATERIAL_MODEL );
  755. pRenderContext->PushMatrix();
  756. pRenderContext->LoadIdentity();
  757. pRenderContext->MatrixMode( MATERIAL_VIEW );
  758. pRenderContext->PushMatrix();
  759. pRenderContext->LoadIdentity();
  760. IMesh* pMesh = pRenderContext->GetDynamicMesh();
  761. CMeshBuilder meshBuilder;
  762. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  763. // adjusted xys
  764. float x1=view.x-.5;
  765. float x2=view.x+view.width;
  766. float y1=view.y-.5;
  767. float y2=view.y+view.height;
  768. float u1, u2, v1, v2;
  769. if ( mapFullTextureToScreen )
  770. {
  771. // adjust nominal uvs to reflect adjusted xys
  772. u1=FLerp(flUOffset, 1-flUOffset,view.x,view.x+view.width,x1);
  773. u2=FLerp(flUOffset, 1-flUOffset,view.x,view.x+view.width,x2);
  774. v1=FLerp(flVOffset, 1-flVOffset,view.y,view.y+view.height,y1);
  775. v2=FLerp(flVOffset, 1-flVOffset,view.y,view.y+view.height,y2);
  776. }
  777. else
  778. {
  779. // Match up the view port window with a corresponding window in the fade texture.
  780. // This is mainly for split screen support.
  781. u1 = Lerp( x1 / (float)width, flUOffset, 1-flUOffset );
  782. u2 = Lerp( x2 / (float)width, flUOffset, 1-flUOffset );
  783. v1 = Lerp( y1 / (float)height, flVOffset, 1-flVOffset );
  784. v2 = Lerp( y2 / (float)height, flVOffset, 1-flVOffset );
  785. }
  786. for ( int corner=0; corner<4; corner++ )
  787. {
  788. bool left=(corner==0) || (corner==3);
  789. meshBuilder.Position3f( (left) ? x1 : x2, (corner & 2) ? y2 : y1, 0.0f );
  790. meshBuilder.TexCoord2f( 0, (left) ? u1 : u2, (corner & 2) ? v2 : v1 );
  791. meshBuilder.AdvanceVertex();
  792. }
  793. meshBuilder.End();
  794. pMesh->Draw();
  795. pRenderContext->MatrixMode( MATERIAL_MODEL );
  796. pRenderContext->PopMatrix();
  797. pRenderContext->MatrixMode( MATERIAL_VIEW );
  798. pRenderContext->PopMatrix();
  799. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  800. pRenderContext->PopMatrix();
  801. pFadeMaterial->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, bOldIgnoreZ );
  802. pRenderContext->PopRenderTargetAndViewport();
  803. }
  804. void CRender::ExtractFrustumPlanes( Frustum frustumPlanes )
  805. {
  806. const CViewSetup &view = CurrentView();
  807. GeneratePerspectiveFrustum( CurrentViewOrigin(),
  808. CurrentViewForward(), CurrentViewRight(), CurrentViewUp(),
  809. view.zNear, view.zFar, view.fov, m_yFOV, frustumPlanes );
  810. g_Frustum.SetPlanes(frustumPlanes);
  811. }
  812. void CRender::OrthoExtractFrustumPlanes( Frustum frustumPlanes )
  813. {
  814. const CViewSetup &view = CurrentView();
  815. // Setup the near and far planes.
  816. float orgOffset = DotProduct(CurrentViewOrigin(), CurrentViewForward());
  817. frustumPlanes[FRUSTUM_FARZ].m_Normal = -CurrentViewForward();
  818. frustumPlanes[FRUSTUM_FARZ].m_Dist = -view.zFar - orgOffset;
  819. frustumPlanes[FRUSTUM_NEARZ].m_Normal = CurrentViewForward();
  820. frustumPlanes[FRUSTUM_NEARZ].m_Dist = view.zNear + orgOffset;
  821. // Left and right planes...
  822. orgOffset = DotProduct(CurrentViewOrigin(), CurrentViewRight());
  823. frustumPlanes[FRUSTUM_LEFT].m_Normal = CurrentViewRight();
  824. frustumPlanes[FRUSTUM_LEFT].m_Dist = view.m_OrthoLeft + orgOffset;
  825. frustumPlanes[FRUSTUM_RIGHT].m_Normal = -CurrentViewRight();
  826. frustumPlanes[FRUSTUM_RIGHT].m_Dist = -view.m_OrthoRight - orgOffset;
  827. // Top and buttom planes...
  828. orgOffset = DotProduct(CurrentViewOrigin(), CurrentViewUp());
  829. frustumPlanes[FRUSTUM_TOP].m_Normal = CurrentViewUp();
  830. frustumPlanes[FRUSTUM_TOP].m_Dist = view.m_OrthoTop + orgOffset;
  831. frustumPlanes[FRUSTUM_BOTTOM].m_Normal = -CurrentViewUp();
  832. frustumPlanes[FRUSTUM_BOTTOM].m_Dist = -view.m_OrthoBottom - orgOffset;
  833. g_Frustum.SetPlanes( frustumPlanes );
  834. }
  835. void CRender::OverrideViewFrustum( Frustum custom )
  836. {
  837. g_Frustum.SetPlanes( custom );
  838. }
  839. void CRender::ExtractMatrices( void )
  840. {
  841. m_matrixView = m_ViewStack.Top().m_matrixView;
  842. m_matrixProjection = m_ViewStack.Top().m_matrixProjection;
  843. m_matrixWorldToScreen = m_ViewStack.Top().m_matrixWorldToScreen;
  844. }
  845. void CRender::SetViewport( int x, int y, int w, int h )
  846. {
  847. int x2, y2;
  848. int windowWidth = w, windowHeight = h;
  849. CMatRenderContextPtr pRenderContext( materials );
  850. // set the viewport to be out to the size of the render target, unless explicitly told not to
  851. if (!CurrentView().m_bRenderToSubrectOfLargerScreen)
  852. {
  853. pRenderContext->GetRenderTargetDimensions( windowWidth, windowHeight );
  854. }
  855. x2 = (x + w);
  856. y2 = (windowHeight - (y + h));
  857. y = (windowHeight - y);
  858. // fudge around because of frac screen scale
  859. if (x > 0)
  860. x--;
  861. if (x2 < windowWidth)
  862. x2++;
  863. if (y2 < 0)
  864. y2--;
  865. if (y < windowHeight)
  866. y++;
  867. w = x2 - x;
  868. h = y - y2;
  869. pRenderContext->Viewport( x, y2, w, h );
  870. }
  871. void DrawLightmapPage( int lightmapPageID )
  872. {
  873. // assumes that we are already in ortho mode.
  874. int lightmapPageWidth, lightmapPageHeight;
  875. CMatRenderContextPtr pRenderContext( materials );
  876. IMesh* pMesh = pRenderContext->GetDynamicMesh( true, NULL, NULL, g_materialDebugLightmap );
  877. // pRenderContext->Bind( g_materialWireframe );
  878. // IMesh* pMesh = pRenderContext->GetDynamicMesh( g_materialWireframe );
  879. materials->GetLightmapPageSize( lightmapPageID, &lightmapPageWidth, &lightmapPageHeight );
  880. pRenderContext->BindLightmapPage( lightmapPageID );
  881. CMeshBuilder meshBuilder;
  882. meshBuilder.Begin( pMesh, MATERIAL_QUADS, 1 );
  883. int x = 0;
  884. int y = 0;
  885. float s = 1.0f;
  886. float t = 1.0f;
  887. // texcoord 1 is lightmaptexcoord for fixed function.
  888. meshBuilder.TexCoord2f( 1, 0.0f, 0.0f );
  889. meshBuilder.Position3f( x, y, 0.0f );
  890. meshBuilder.AdvanceVertex();
  891. meshBuilder.TexCoord2f( 1, s, 0.0f );
  892. meshBuilder.Position3f( x+lightmapPageWidth, y, 0.0f );
  893. meshBuilder.AdvanceVertex();
  894. meshBuilder.TexCoord2f( 1, s, t );
  895. meshBuilder.Position3f( x+lightmapPageWidth, y+lightmapPageHeight, 0.0f );
  896. meshBuilder.AdvanceVertex();
  897. meshBuilder.TexCoord2f( 1, 0.0f, t );
  898. meshBuilder.Position3f( x, y+lightmapPageHeight, 0.0f );
  899. meshBuilder.AdvanceVertex();
  900. meshBuilder.End();
  901. pMesh->Draw();
  902. }
  903. //hack
  904. extern void DebugDrawLightmapAtCrossHair();
  905. void R_DrawLightmaps( IWorldRenderList *pList, int pageId )
  906. {
  907. #ifdef USE_CONVARS
  908. if ( pageId != -1 )
  909. {
  910. DrawLightmapPage( pageId );
  911. Shader_DrawLightmapPageChains( pList, pageId );
  912. }
  913. #endif
  914. }
  915. void R_CheckForLightingConfigChanges()
  916. {
  917. if ( !materials->CanDownloadTextures() )
  918. return;
  919. UpdateStudioRenderConfig();
  920. UpdateMaterialSystemConfig();
  921. if( MaterialConfigLightingChanged() || g_RebuildLightmaps )
  922. {
  923. ClearMaterialConfigLightingChanged();
  924. DevMsg( "Redownloading all lightmaps\n" );
  925. BuildGammaTable( 2.2f, 2.2f, 0.0f, OVERBRIGHT );
  926. R_RedownloadAllLightmaps();
  927. StaticPropMgr()->RecomputeStaticLighting();
  928. }
  929. }
  930. ConVar r_redownloadallpaintmaps("r_redownloadallpaintmaps", "0", FCVAR_DEVELOPMENTONLY);
  931. void R_CheckForPaintmapChanges()
  932. {
  933. if ( !g_PaintManager.m_bShouldRegister )
  934. return;
  935. if ( !materials->CanDownloadTextures() )
  936. return;
  937. if ( r_redownloadallpaintmaps.GetBool() )
  938. {
  939. R_RedownloadAllPaintmaps();
  940. r_redownloadallpaintmaps.SetValue(0);
  941. return;
  942. }
  943. {
  944. VPROF_BUDGET( "R_CheckForPaintmapChanges", "paint" );
  945. g_PaintManager.UpdatePaintmapTextures();
  946. }
  947. }
  948. void CRender::DrawSceneBegin( void )
  949. {
  950. R_CheckForLightingConfigChanges();
  951. }
  952. void CRender::DrawSceneEnd( void )
  953. {
  954. R_SceneEnd();
  955. LeafVisDraw();
  956. }
  957. IWorldRenderList * CRender::CreateWorldList()
  958. {
  959. return AllocWorldRenderList();
  960. }
  961. #if defined(_PS3)
  962. IWorldRenderList * CRender::CreateWorldList_PS3( int viewID )
  963. {
  964. return AllocWorldRenderList_PS3( viewID );
  965. }
  966. #endif
  967. // JasonM TODO: optimize in the case of shadow depth mapping (i.e. don't update lightmaps)
  968. void CRender::BuildWorldLists( IWorldRenderList *pList, WorldListInfo_t* pInfo, int iForceViewLeaf, const VisOverrideData_t* pVisData, bool bShadowDepth, float *pWaterReflectionHeight )
  969. {
  970. VPROF_INCREMENT_COUNTER( "BuildWorldLists", 1 );
  971. Assert( pList );
  972. Assert( m_iLightmapUpdateDepth > 0 || g_LightmapUpdateList.Count() == 0 );
  973. if ( !bShadowDepth )
  974. {
  975. BeginUpdateLightmaps();
  976. }
  977. R_BuildWorldLists( pList, pInfo, iForceViewLeaf, pVisData, bShadowDepth, pWaterReflectionHeight );
  978. if ( !bShadowDepth )
  979. {
  980. EndUpdateLightmaps();
  981. }
  982. Assert( m_iLightmapUpdateDepth > 0 || g_LightmapUpdateList.Count() == 0 );
  983. }
  984. #if defined(_PS3)
  985. void CRender::BuildWorldLists_PS3_Epilogue( IWorldRenderList *pList, WorldListInfo_t* pInfo, bool bShadowDepth )
  986. {
  987. Assert( pList );
  988. R_BuildWorldLists_PS3_Epilogue( pList, pInfo, bShadowDepth );
  989. }
  990. #else
  991. void CRender::BuildWorldLists_Epilogue( IWorldRenderList *pList, WorldListInfo_t* pInfo, bool bShadowDepth )
  992. {
  993. Assert( pList );
  994. Assert( m_iLightmapUpdateDepth > 0 || g_LightmapUpdateList.Count() == 0 );
  995. if ( !bShadowDepth )
  996. {
  997. BeginUpdateLightmaps();
  998. }
  999. R_BuildWorldLists_Epilogue( pList, pInfo, bShadowDepth );
  1000. if ( !bShadowDepth )
  1001. {
  1002. EndUpdateLightmaps();
  1003. }
  1004. Assert( m_iLightmapUpdateDepth > 0 || g_LightmapUpdateList.Count() == 0 );
  1005. }
  1006. #endif
  1007. void CRender::DrawWorldLists( IMatRenderContext *pRenderContext, IWorldRenderList *pList, unsigned long flags, float flWaterZAdjust )
  1008. {
  1009. Assert( ( flags & DRAWWORLDLISTS_DRAW_SIMPLE_WORLD_MODEL ) || pList );
  1010. R_DrawWorldLists( pRenderContext, pList, flags, flWaterZAdjust );
  1011. }