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.

9928 lines
313 KiB

  1. //===== Copyright 1996-2005, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose: Responsible for drawing the scene
  4. //
  5. //===========================================================================//
  6. #include "cbase.h"
  7. #include "view.h"
  8. #include "iviewrender.h"
  9. #include "view_shared.h"
  10. #include "ivieweffects.h"
  11. #include "iinput.h"
  12. #include "model_types.h"
  13. #include "clientsideeffects.h"
  14. #include "particlemgr.h"
  15. #include "viewrender.h"
  16. #include "iclientmode.h"
  17. #include "voice_status.h"
  18. #include "glow_overlay.h"
  19. #include "materialsystem/imesh.h"
  20. #include "materialsystem/itexture.h"
  21. #include "materialsystem/imaterial.h"
  22. #include "materialsystem/imaterialvar.h"
  23. #include "materialsystem/imaterialsystem.h"
  24. #include "materialsystem/imaterialsystemhardwareconfig.h"
  25. #include "materialsystem/materialsystem_config.h"
  26. #include "detailobjectsystem.h"
  27. #include "tier0/vprof.h"
  28. #include "tier0/perfstats.h"
  29. #include "tier0/threadtools.h"
  30. #include "tier1/mempool.h"
  31. #include "vstdlib/jobthread.h"
  32. #include "datacache/imdlcache.h"
  33. #include "engine/IEngineTrace.h"
  34. #include "engine/ivmodelinfo.h"
  35. #include "tier0/icommandline.h"
  36. #include "view_scene.h"
  37. #include "particles_ez.h"
  38. #include "engine/IStaticPropMgr.h"
  39. #include "engine/ivdebugoverlay.h"
  40. #include "c_pixel_visibility.h"
  41. #include "precache_register.h"
  42. #include "c_rope.h"
  43. #include "c_effects.h"
  44. #include "smoke_fog_overlay.h"
  45. #include "materialsystem/imaterialsystemhardwareconfig.h"
  46. #include "vgui_int.h"
  47. #include "ienginevgui.h"
  48. #include "ScreenSpaceEffects.h"
  49. #include "toolframework_client.h"
  50. #include "c_func_reflective_glass.h"
  51. #include "keyvalues.h"
  52. #include "renderparm.h"
  53. #include "modelrendersystem.h"
  54. #include "vgui/ISurface.h"
  55. #include "tier0/cache_hints.h"
  56. #include "c_env_cascade_light.h"
  57. #define PARTICLE_USAGE_DEMO // uncomment to get particle bar thing
  58. #ifdef PORTAL
  59. #include "portal_render_targets.h"
  60. #include "portalrender.h"
  61. #endif
  62. #if defined( HL2_CLIENT_DLL ) || defined( CSTRIKE_DLL ) || defined( INFESTED_DLL ) || defined( PORTAL2 )
  63. #define USE_MONITORS
  64. #endif
  65. #include "rendertexture.h"
  66. #include "viewpostprocess.h"
  67. #include "viewdebug.h"
  68. #ifdef USE_MONITORS
  69. #include "c_point_camera.h"
  70. #endif // USE_MONITORS
  71. #ifdef INFESTED_DLL
  72. #include "c_asw_render_targets.h"
  73. #include "clientmode_asw.h"
  74. #endif
  75. // memdbgon must be the last include file in a .cpp file!!!
  76. #include "tier0/memdbgon.h"
  77. static void testfreezeframe_f( void )
  78. {
  79. view->FreezeFrame( 3.0 );
  80. }
  81. static ConCommand test_freezeframe( "test_freezeframe", testfreezeframe_f, "Test the freeze frame code.", FCVAR_CHEAT );
  82. //-----------------------------------------------------------------------------
  83. static ConVar r_visocclusion( "r_visocclusion", "0", FCVAR_CHEAT );
  84. extern ConVar r_flashlightdepthtexture;
  85. extern ConVar vcollide_wireframe;
  86. extern ConVar r_depthoverlay;
  87. extern ConVar r_shadow_deferred;
  88. extern ConVar mat_viewportscale;
  89. extern ConVar mat_viewportupscale;
  90. //-----------------------------------------------------------------------------
  91. // Convars related to controlling rendering
  92. //-----------------------------------------------------------------------------
  93. static ConVar cl_maxrenderable_dist("cl_maxrenderable_dist", "3000", FCVAR_CHEAT, "Max distance from the camera at which things will be rendered" );
  94. 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?
  95. ConVar r_deferopaquefastclipped( "r_deferopaquefastclipped", "1" );
  96. // Matches the version in the engine
  97. static ConVar r_drawopaqueworld( "r_drawopaqueworld", "1", FCVAR_CHEAT );
  98. static ConVar r_drawtranslucentworld( "r_drawtranslucentworld", "1", FCVAR_CHEAT );
  99. static ConVar r_3dsky( "r_3dsky","1", 0, "Enable the rendering of 3d sky boxes" );
  100. static ConVar r_skybox( "r_skybox","1", FCVAR_CHEAT, "Enable the rendering of sky boxes" );
  101. ConVar r_drawviewmodel( "r_drawviewmodel","1", FCVAR_CHEAT );
  102. static ConVar r_drawtranslucentrenderables( "r_drawtranslucentrenderables", "1", FCVAR_CHEAT );
  103. static ConVar r_drawopaquerenderables( "r_drawopaquerenderables", "1", FCVAR_CHEAT );
  104. static ConVar r_flashlightdepth_drawtranslucents( "r_flashlightdepth_drawtranslucents", "0", FCVAR_NONE );
  105. extern ConVar cl_csm_translucent_shadows;
  106. extern ConVar cl_csm_translucent_shadows_using_opaque_path;
  107. ConVar r_flashlightvolumetrics( "r_flashlightvolumetrics", "1" );
  108. // FIXME: This is not static because we needed to turn it off for TF2 playtests
  109. ConVar r_DrawDetailProps( "r_DrawDetailProps", "1",
  110. #if defined( ALLOW_TEXT_MODE )
  111. FCVAR_RELEASE,
  112. #else
  113. FCVAR_DEVELOPMENTONLY,
  114. #endif
  115. "0=Off, 1=Normal, 2=Wireframe"
  116. );
  117. // don't use worldlistcache on PS3 is using SPU buildview jobs
  118. ConVar r_worldlistcache( "r_worldlistcache", IsPS3() ? "0" : "1" );
  119. extern ConVar cl_csm_shadows;
  120. extern ConVar cl_csm_world_shadows;
  121. extern ConVar cl_csm_world_shadows_in_viewmodelcascade;
  122. extern ConVar cl_csm_disable_culling;
  123. extern ConVar cl_csm_rope_shadows;
  124. static ConVar r_drawunderwateroverlay( "r_drawunderwateroverlay", "0", FCVAR_CHEAT | FCVAR_SERVER_CAN_EXECUTE );
  125. static ConVar r_drawscreenoverlay( "r_drawscreenoverlay", "1", FCVAR_CHEAT | FCVAR_SERVER_CAN_EXECUTE );
  126. //-----------------------------------------------------------------------------
  127. // Convars related to fog color
  128. //-----------------------------------------------------------------------------
  129. static void GetFogColor( fogparams_t *pFogParams, float *pColor, bool ignoreOverride = false, bool ignoreHDRColorScale = false );
  130. static float GetFogMaxDensity( fogparams_t *pFogParams, bool ignoreOverride = false );
  131. static bool GetFogEnable( fogparams_t *pFogParams, bool ignoreOverride = false );
  132. static float GetFogStart( fogparams_t *pFogParams, bool ignoreOverride = false );
  133. static float GetFogEnd( fogparams_t *pFogParams, bool ignoreOverride = false );
  134. static float GetSkyboxFogStart( bool ignoreOverride = false );
  135. static float GetSkyboxFogEnd( bool ignoreOverride = false );
  136. static float GetSkyboxFogMaxDensity( bool ignoreOverride = false );
  137. static void GetSkyboxFogColor( float *pColor, bool ignoreOverride = false, bool ignoreHDRColorScale = false );
  138. static void FogOverrideCallback( IConVar *pConVar, char const *pOldString, float flOldValue );
  139. static ConVar fog_override( "fog_override", "0", FCVAR_CHEAT, "Overrides the map's fog settings (-1 populates fog_ vars with map's values)", FogOverrideCallback );
  140. // set any of these to use the maps fog
  141. static ConVar fog_start( "fog_start", "-1", FCVAR_CHEAT );
  142. static ConVar fog_end( "fog_end", "-1", FCVAR_CHEAT );
  143. static ConVar fog_color( "fog_color", "-1 -1 -1", FCVAR_CHEAT );
  144. static ConVar fog_enable( "fog_enable", "1", FCVAR_CHEAT );
  145. static ConVar fog_startskybox( "fog_startskybox", "-1", FCVAR_CHEAT );
  146. static ConVar fog_endskybox( "fog_endskybox", "-1", FCVAR_CHEAT );
  147. static ConVar fog_maxdensityskybox( "fog_maxdensityskybox", "-1", FCVAR_CHEAT );
  148. static ConVar fog_colorskybox( "fog_colorskybox", "-1 -1 -1", FCVAR_CHEAT );
  149. static ConVar fog_enableskybox( "fog_enableskybox", "1", FCVAR_CHEAT );
  150. static ConVar fog_maxdensity( "fog_maxdensity", "-1", FCVAR_CHEAT );
  151. static ConVar fog_hdrcolorscale( "fog_hdrcolorscale", "-1", FCVAR_CHEAT );
  152. static ConVar fog_hdrcolorscaleskybox( "fog_hdrcolorscaleskybox", "-1", FCVAR_CHEAT );
  153. static void FogOverrideCallback( IConVar *pConVar, char const *pOldString, float flOldValue )
  154. {
  155. C_BasePlayer *localPlayer = C_BasePlayer::GetLocalPlayer();
  156. if ( !localPlayer )
  157. return;
  158. ConVarRef var( pConVar );
  159. if ( var.GetInt() == -1 )
  160. {
  161. fogparams_t *pFogParams = localPlayer->GetFogParams();
  162. float fogColor[3];
  163. fog_start.SetValue( GetFogStart( pFogParams, true ) );
  164. fog_end.SetValue( GetFogEnd( pFogParams, true ) );
  165. GetFogColor( pFogParams, fogColor, true, true );
  166. fog_color.SetValue( VarArgs( "%.1f %.1f %.1f", fogColor[0]*255, fogColor[1]*255, fogColor[2]*255 ) );
  167. fog_enable.SetValue( GetFogEnable( pFogParams, true ) );
  168. fog_startskybox.SetValue( GetSkyboxFogStart( true ) );
  169. fog_endskybox.SetValue( GetSkyboxFogEnd( true ) );
  170. fog_maxdensityskybox.SetValue( GetSkyboxFogMaxDensity( true ) );
  171. GetSkyboxFogColor( fogColor, true, true );
  172. fog_colorskybox.SetValue( VarArgs( "%.1f %.1f %.1f", fogColor[0]*255, fogColor[1]*255, fogColor[2]*255 ) );
  173. fog_enableskybox.SetValue( localPlayer->m_Local.m_skybox3d.fog.enable.Get() );
  174. fog_maxdensity.SetValue( GetFogMaxDensity( pFogParams, true ) );
  175. fog_hdrcolorscale.SetValue( pFogParams->HDRColorScale );
  176. fog_hdrcolorscaleskybox.SetValue( localPlayer->m_Local.m_skybox3d.fog.HDRColorScale.Get() );
  177. }
  178. }
  179. //-----------------------------------------------------------------------------
  180. // Water-related convars
  181. //-----------------------------------------------------------------------------
  182. static ConVar r_debugcheapwater( "r_debugcheapwater", "0", FCVAR_CHEAT );
  183. #ifndef _GAMECONSOLE
  184. static ConVar r_waterforceexpensive( "r_waterforceexpensive", "0" );
  185. #endif
  186. static ConVar r_waterforcereflectentities( "r_waterforcereflectentities", "0" );
  187. #if defined( _GAMECONSOLE ) && ( defined( PORTAL2 ) || defined( CSTRIKE15 ) )
  188. // Portal 2 doesn't use refractive water in many places, and where it does, it's too expensive for consoles (and probably low-end PCs as well)
  189. // Just force it off here so as not to mess with high-end PCs
  190. static ConVar r_WaterDrawRefraction( "r_WaterDrawRefraction", IsPS3()? "0" : "1", 0, "Enable water refraction" );
  191. #else
  192. static ConVar r_WaterDrawRefraction( "r_WaterDrawRefraction", "1", 0, "Enable water refraction" );
  193. #endif
  194. static ConVar r_WaterDrawReflection( "r_WaterDrawReflection", "1", 0, "Enable water reflection" );
  195. static ConVar r_ForceWaterLeaf( "r_ForceWaterLeaf", "1", 0, "Enable for optimization to water - considers view in leaf under water for purposes of culling" );
  196. static ConVar mat_drawwater( "mat_drawwater", "1", FCVAR_CHEAT );
  197. static ConVar mat_clipz( "mat_clipz", "1" );
  198. //-----------------------------------------------------------------------------
  199. // Other convars
  200. //-----------------------------------------------------------------------------
  201. static ConVar cl_drawmonitors( "cl_drawmonitors", "1" );
  202. static ConVar r_eyewaterepsilon( "r_eyewaterepsilon", "7.0f", FCVAR_CHEAT );
  203. extern ConVar cl_leveloverview;
  204. ConVar r_fastzreject( "r_fastzreject", "0", 0, "Activate/deactivates a fast z-setting algorithm to take advantage of hardware with fast z reject. Use -1 to default to hardware settings" );
  205. // For CSS15, simpleworldmodel_waterreflections don't work. They were added for Portal 2. If we want, we can look into making them work, until then, we don't enable it.
  206. #if defined( _GAMECONSOLE )
  207. ConVar r_simpleworldmodel_waterreflections_fullscreen( "r_simpleworldmodel_waterreflections_fullscreen", "0" );
  208. ConVar r_simpleworldmodel_drawforrecursionlevel_fullscreen( "r_simpleworldmodel_drawforrecursionlevel_fullscreen", "-1" );
  209. ConVar r_simpleworldmodel_drawbeyonddistance_fullscreen( "r_simpleworldmodel_drawbeyonddistance_fullscreen", "-1" );
  210. ConVar r_simpleworldmodel_waterreflections_splitscreen( "r_simpleworldmodel_waterreflections_splitscreen", "0" );
  211. ConVar r_simpleworldmodel_drawforrecursionlevel_splitscreen( "r_simpleworldmodel_drawforrecursionlevel_splitscreen", "2" );
  212. ConVar r_simpleworldmodel_drawbeyonddistance_splitscreen( "r_simpleworldmodel_drawbeyonddistance_splitscreen", "600" );
  213. ConVar r_simpleworldmodel_waterreflections_pip( "r_simpleworldmodel_waterreflections_pip", "1" );
  214. ConVar r_simpleworldmodel_drawforrecursionlevel_pip( "r_simpleworldmodel_drawforrecursionlevel_pip", "2" );
  215. ConVar r_simpleworldmodel_drawbeyonddistance_pip( "r_simpleworldmodel_drawbeyonddistance_pip", "600" );
  216. #else
  217. ConVar r_simpleworldmodel_waterreflections_fullscreen( "r_simpleworldmodel_waterreflections_fullscreen", "0" );
  218. ConVar r_simpleworldmodel_drawforrecursionlevel_fullscreen( "r_simpleworldmodel_drawforrecursionlevel_fullscreen", "-1" );
  219. ConVar r_simpleworldmodel_drawbeyonddistance_fullscreen( "r_simpleworldmodel_drawbeyonddistance_fullscreen", "-1" );
  220. ConVar r_simpleworldmodel_waterreflections_splitscreen( "r_simpleworldmodel_waterreflections_splitscreen", "0" );
  221. ConVar r_simpleworldmodel_drawforrecursionlevel_splitscreen( "r_simpleworldmodel_drawforrecursionlevel_splitscreen", "-1" );
  222. ConVar r_simpleworldmodel_drawbeyonddistance_splitscreen( "r_simpleworldmodel_drawbeyonddistance_splitscreen", "-1" );
  223. ConVar r_simpleworldmodel_waterreflections_pip( "r_simpleworldmodel_waterreflections_pip", "0" );
  224. ConVar r_simpleworldmodel_drawforrecursionlevel_pip( "r_simpleworldmodel_drawforrecursionlevel_pip", "-1" );
  225. ConVar r_simpleworldmodel_drawbeyonddistance_pip( "r_simpleworldmodel_drawbeyonddistance_pip", "-1" );
  226. #endif
  227. void GetSimpleWorldModelConfiguration( bool &bSimpleWorldModeWaterReflectionOut, int &nSimpleWorldModelRecursionLevelOut, float &flSimpleWorldModelDrawBeyondDistanceOut )
  228. {
  229. // we only load/use the world imposters for multiplayer maps.
  230. if ( GameRules()->IsMultiplayer() || IsPC() )
  231. {
  232. if ( VGui_IsSplitScreen() )
  233. {
  234. if ( VGui_IsSplitScreenPIP() )
  235. {
  236. if ( GET_ACTIVE_SPLITSCREEN_SLOT() == 0 )
  237. {
  238. // We are the main view, so go ahead and use the full screen settings.
  239. // We definitely want to use the fullscreen setting here so that we don't pop when split goes off and on.
  240. bSimpleWorldModeWaterReflectionOut = r_simpleworldmodel_waterreflections_fullscreen.GetBool();
  241. nSimpleWorldModelRecursionLevelOut = r_simpleworldmodel_drawforrecursionlevel_fullscreen.GetInt();
  242. flSimpleWorldModelDrawBeyondDistanceOut = r_simpleworldmodel_drawbeyonddistance_fullscreen.GetFloat();
  243. }
  244. else
  245. {
  246. // We are not the primary view, so we must be PIP.
  247. bSimpleWorldModeWaterReflectionOut = r_simpleworldmodel_waterreflections_pip.GetBool();
  248. nSimpleWorldModelRecursionLevelOut = r_simpleworldmodel_drawforrecursionlevel_pip.GetInt();
  249. flSimpleWorldModelDrawBeyondDistanceOut = r_simpleworldmodel_drawbeyonddistance_pip.GetFloat();
  250. }
  251. }
  252. else
  253. {
  254. // We are one of two splitscreen views.
  255. bSimpleWorldModeWaterReflectionOut = r_simpleworldmodel_waterreflections_splitscreen.GetBool();
  256. nSimpleWorldModelRecursionLevelOut = r_simpleworldmodel_drawforrecursionlevel_splitscreen.GetInt();
  257. flSimpleWorldModelDrawBeyondDistanceOut = r_simpleworldmodel_drawbeyonddistance_splitscreen.GetFloat();
  258. }
  259. }
  260. else
  261. {
  262. // We aren't splitscreen of any sort, so go ahead and use the fullscreen setting.
  263. bSimpleWorldModeWaterReflectionOut = r_simpleworldmodel_waterreflections_fullscreen.GetBool();
  264. nSimpleWorldModelRecursionLevelOut = r_simpleworldmodel_drawforrecursionlevel_fullscreen.GetInt();
  265. flSimpleWorldModelDrawBeyondDistanceOut = r_simpleworldmodel_drawbeyonddistance_fullscreen.GetFloat();
  266. }
  267. }
  268. else
  269. {
  270. // We aren't multiplayer, so set the options that turn it all off.
  271. bSimpleWorldModeWaterReflectionOut = false;
  272. nSimpleWorldModelRecursionLevelOut = -1;
  273. flSimpleWorldModelDrawBeyondDistanceOut = -1.0f;
  274. }
  275. }
  276. //-----------------------------------------------------------------------------
  277. // Globals
  278. //-----------------------------------------------------------------------------
  279. static Vector g_vecCurrentRenderOrigin(0,0,0);
  280. static QAngle g_vecCurrentRenderAngles(0,0,0);
  281. static Vector g_vecCurrentVForward(0,0,0), g_vecCurrentVRight(0,0,0), g_vecCurrentVUp(0,0,0);
  282. static VMatrix g_matCurrentCamInverse;
  283. bool s_bCanAccessCurrentView = false;
  284. IntroData_t *g_pIntroData = NULL;
  285. static bool g_bRenderingView = false; // For debugging...
  286. static int g_CurrentViewID = VIEW_NONE;
  287. bool g_bRenderingScreenshot = false;
  288. #if defined( CSTRIKE15 ) && defined(_PS3)
  289. static ConVar r_PS3_2PassBuildDraw( "r_PS3_2PassBuildDraw", "1" );
  290. static ConVar r_ps3_csm_disableWorldInListenServer( "r_ps3_csm_disableWorldInListenServer", "1" );
  291. CConcurrentViewBuilderPS3 g_viewBuilder;
  292. #define PROLOGUE_PASS_DRAWLISTS g_viewBuilder.SetDrawFlags( m_DrawFlags );
  293. #define EPILOGUE_PASS_DRAWLISTS if( m_pWorldRenderList == NULL )\
  294. {\
  295. m_pWorldRenderList = g_viewBuilder.GetWorldRenderListElement();\
  296. }
  297. #define SYNC_BUILDWORLD_JOB( bShadowDepth ) if( g_viewBuilder.IsSPUBuildRWJobsOn() )\
  298. {\
  299. SNPROF("SyncBuildWorldJob");\
  300. CELL_VERIFY( g_pBuildRenderablesJob->m_pRoot->m_queuePortBuildWorld[ g_viewBuilder.GetBuildViewID() ].sync( 0 ) );\
  301. BuildWorldRenderLists_PS3_Epilogue( bShadowDepth );\
  302. }
  303. #define SYNC_BUILDRENDERABLES_JOB if( g_viewBuilder.IsSPUBuildRWJobsOn() )\
  304. {\
  305. SNPROF("SyncBuildRenderablesJob");\
  306. CELL_VERIFY( g_pBuildRenderablesJob->m_pRoot->m_queuePortBuildRenderables[ g_viewBuilder.GetBuildViewID() ].sync( 0 ) );\
  307. BuildRenderableRenderLists_PS3_Epilogue();\
  308. }
  309. #define BEGIN_2PASS_BUILD_BLOCK if( g_viewBuilder.GetPassFlags() & PASS_BUILDLISTS_PS3 ) {
  310. #define BEGIN_2PASS_DRAW_BLOCK if( g_viewBuilder.GetPassFlags() & PASS_DRAWLISTS_PS3 ) {
  311. #define END_2PASS_BLOCK }
  312. #define PS3_SPUPATH_INVALID( s ) if( g_viewBuilder.IsSPUBuildRWJobsOn() )\
  313. Warning("Rendering path not fully supported in %s or tested on SPU, and SPU jobs are enabled!\n", s);
  314. #else
  315. static ConVar r_2PassBuildDraw( "r_2PassBuildDraw", "1", FCVAR_DEVELOPMENTONLY );
  316. static ConVar r_threaded_buildWRlist( "r_threaded_buildWRlist", "1", FCVAR_DEVELOPMENTONLY, "Threaded BuildWorldList and BuildRenderables list" );
  317. CON_COMMAND_F( toggleThreadedBuildRWList, "toggleThreadedBuildRWList", FCVAR_DEVELOPMENTONLY )
  318. {
  319. bool newValue = !r_threaded_buildWRlist.GetBool();
  320. r_threaded_buildWRlist.SetValue( newValue );
  321. Msg( "r_threaded_buildWRlist = %s\n", newValue? "TRUE":"FALSE" );
  322. }
  323. CConcurrentViewBuilder g_viewBuilder;
  324. #define BEGIN_2PASS_BUILD_BLOCK if( g_viewBuilder.GetPassFlags() & PASS_BUILDLISTS ) {
  325. #define BEGIN_2PASS_DRAW_BLOCK if( g_viewBuilder.GetPassFlags() & PASS_DRAWLISTS ) {
  326. #define END_2PASS_BLOCK }
  327. #define PROLOGUE_PASS_DRAWLISTS
  328. #define EPILOGUE_PASS_DRAWLISTS
  329. #define SYNC_BUILDWORLD_JOB( bShadowDepth ) g_viewBuilder.WaitForBuildWorldListJob();\
  330. if( m_pWorldRenderList == NULL )\
  331. {\
  332. m_pWorldRenderList = g_viewBuilder.GetWorldRenderListElement();\
  333. if ( m_pWorldRenderList )\
  334. InlineAddRef(m_pWorldRenderList);\
  335. }\
  336. if( m_pWorldListInfo == NULL )\
  337. {\
  338. m_pWorldListInfo = g_viewBuilder.GetClientWorldListInfoElement();\
  339. if ( m_pWorldListInfo )\
  340. InlineAddRef(m_pWorldListInfo);\
  341. }\
  342. BuildWorldRenderLists_Epilogue( bShadowDepth );
  343. #define SYNC_BUILDRENDERABLES_JOB( viewID ) g_viewBuilder.WaitForBuildRenderablesListJob();\
  344. if( m_pRenderables == NULL )\
  345. {\
  346. m_pRenderables = g_viewBuilder.GetRenderablesListElement();\
  347. if ( m_pRenderables )\
  348. InlineAddRef(m_pRenderables);\
  349. }\
  350. BuildRenderableRenderLists_Epilogue( viewID );
  351. #define PS3_SPUPATH_INVALID( s )
  352. #endif
  353. static FrustumCache_t s_FrustumCache;
  354. FrustumCache_t *FrustumCache( void )
  355. {
  356. return &s_FrustumCache;
  357. }
  358. #define FREEZECAM_SNAPSHOT_FADE_SPEED 340
  359. float g_flFreezeFlash[ MAX_SPLITSCREEN_PLAYERS ];
  360. //-----------------------------------------------------------------------------
  361. CON_COMMAND( r_cheapwaterstart, "" )
  362. {
  363. if( args.ArgC() == 2 )
  364. {
  365. float dist = atof( args[ 1 ] );
  366. view->SetCheapWaterStartDistance( dist );
  367. }
  368. else
  369. {
  370. float start, end;
  371. view->GetWaterLODParams( start, end );
  372. Warning( "r_cheapwaterstart: %f\n", start );
  373. }
  374. }
  375. CON_COMMAND( r_cheapwaterend, "" )
  376. {
  377. if( args.ArgC() == 2 )
  378. {
  379. float dist = atof( args[ 1 ] );
  380. view->SetCheapWaterEndDistance( dist );
  381. }
  382. else
  383. {
  384. float start, end;
  385. view->GetWaterLODParams( start, end );
  386. Warning( "r_cheapwaterend: %f\n", end );
  387. }
  388. }
  389. #ifdef PORTAL2
  390. struct AperturePhotoViewQueue_t
  391. {
  392. EHANDLE hEnt;
  393. ITexture *pTexture;
  394. int iFailedTries;
  395. };
  396. CUtlVector<AperturePhotoViewQueue_t> g_AperturePhotoQueue;
  397. void Aperture_QueuePhotoView( EHANDLE hPhotoEntity, ITexture *pRenderTarget )
  398. {
  399. if( pRenderTarget == NULL )
  400. return;
  401. AperturePhotoViewQueue_t temp;
  402. temp.hEnt = hPhotoEntity;
  403. temp.pTexture = pRenderTarget;
  404. temp.iFailedTries = 0;
  405. g_AperturePhotoQueue.AddToTail( temp );
  406. }
  407. #endif
  408. static int ComputeSimpleWorldModelDrawFlags()
  409. {
  410. #if defined( PORTAL )
  411. #if 0
  412. // Some spew to track portal distances
  413. static int nLastFrame = -1;
  414. static int nCurrentEntryInFrame = 0;
  415. if ( nLastFrame != gpGlobals->framecount )
  416. {
  417. nLastFrame = gpGlobals->framecount;
  418. nCurrentEntryInFrame = 0;
  419. }
  420. engine->Con_NPrintf( 1 + nCurrentEntryInFrame, "Portal %X distance: %f", g_pPortalRender->GetCurrentViewExitPortal(), g_pPortalRender->GetCurrentPortalDistanceBias() );
  421. ++ nCurrentEntryInFrame;
  422. #endif // 0
  423. bool bSimpleWorldModeWaterReflection;
  424. int nSimpleWorldModelRecursionLevel;
  425. float flSimpleWorldModelDrawBeyondDistance;
  426. GetSimpleWorldModelConfiguration( bSimpleWorldModeWaterReflection, nSimpleWorldModelRecursionLevel, flSimpleWorldModelDrawBeyondDistance );
  427. if ( nSimpleWorldModelRecursionLevel >= 0 && g_pPortalRender->GetViewRecursionLevel() >= nSimpleWorldModelRecursionLevel )
  428. {
  429. return DF_DRAW_SIMPLE_WORLD_MODEL | DF_DRAW_SIMPLE_WORLD_MODEL_WATER | DF_FAST_ENTITY_RENDERING | DF_DRAW_ENTITITES;
  430. }
  431. else
  432. {
  433. if ( flSimpleWorldModelDrawBeyondDistance >= 0.0f )
  434. {
  435. float flDistanceBias = g_pPortalRender->GetCurrentPortalDistanceBias();
  436. if ( flDistanceBias > flSimpleWorldModelDrawBeyondDistance )
  437. {
  438. return DF_DRAW_SIMPLE_WORLD_MODEL | DF_DRAW_SIMPLE_WORLD_MODEL_WATER | DF_FAST_ENTITY_RENDERING | DF_DRAW_ENTITITES;
  439. }
  440. }
  441. }
  442. #endif // PORTAL
  443. return 0;
  444. }
  445. //-----------------------------------------------------------------------------
  446. // Describes a pruned set of leaves to be rendered this view. Reference counted
  447. // because potentially shared by a number of views
  448. //-----------------------------------------------------------------------------
  449. struct ClientWorldListInfo_t : public CRefCounted1<WorldListInfo_t>
  450. {
  451. ClientWorldListInfo_t()
  452. {
  453. memset( (WorldListInfo_t *)this, 0, sizeof(WorldListInfo_t) );
  454. m_pOriginalLeafIndex = NULL;
  455. m_bPooledAlloc = false;
  456. }
  457. #if defined(_PS3)
  458. void Init()
  459. {
  460. memset( (WorldListInfo_t *)this, 0, sizeof(WorldListInfo_t) );
  461. m_pOriginalLeafIndex = NULL;
  462. m_bPooledAlloc = false;
  463. }
  464. #endif
  465. // Allocate a list intended for pruning
  466. static ClientWorldListInfo_t *AllocPooled( const ClientWorldListInfo_t &exemplar );
  467. // Because we remap leaves to eliminate unused leaves, we need a remap
  468. // when drawing translucent surfaces, which requires the *original* leaf index
  469. // using m_pOriginalLeafIndex[ remapped leaf index ] == actual leaf index
  470. uint16 *m_pOriginalLeafIndex;
  471. private:
  472. virtual bool OnFinalRelease();
  473. bool m_bPooledAlloc;
  474. static CObjectPool<ClientWorldListInfo_t> gm_Pool;
  475. };
  476. //-----------------------------------------------------------------------------
  477. //
  478. //-----------------------------------------------------------------------------
  479. class CWorldListCache
  480. {
  481. public:
  482. CWorldListCache()
  483. {
  484. }
  485. void Flush()
  486. {
  487. for ( int i = m_Entries.FirstInorder(); i != m_Entries.InvalidIndex(); i = m_Entries.NextInorder( i ) )
  488. {
  489. delete m_Entries[i];
  490. }
  491. m_Entries.RemoveAll();
  492. }
  493. bool Find( const CViewSetup &viewSetup, VisOverrideData_t *pVisOverrideData, int iForceViewLeaf, IWorldRenderList **ppList, ClientWorldListInfo_t **ppListInfo )
  494. {
  495. Entry_t lookup( viewSetup, pVisOverrideData, iForceViewLeaf );
  496. int i = m_Entries.Find( &lookup );
  497. if ( i != m_Entries.InvalidIndex() )
  498. {
  499. Entry_t *pEntry = m_Entries[i];
  500. *ppList = InlineAddRef( pEntry->pList );
  501. *ppListInfo = InlineAddRef( pEntry->pListInfo );
  502. return true;
  503. }
  504. return false;
  505. }
  506. void Add( const CViewSetup &viewSetup, VisOverrideData_t *pVisOverrideData, int iForceViewLeaf, IWorldRenderList *pList, ClientWorldListInfo_t *pListInfo )
  507. {
  508. m_Entries.Insert( new Entry_t( viewSetup, pVisOverrideData, iForceViewLeaf, pList, pListInfo ) );
  509. }
  510. private:
  511. struct Entry_t
  512. {
  513. Entry_t( const CViewSetup &viewSetup, VisOverrideData_t *pVisOverrideData, int iForceViewLeaf, IWorldRenderList *pList = NULL, ClientWorldListInfo_t *pListInfo = NULL ) :
  514. pList( ( pList ) ? InlineAddRef( pList ) : NULL ),
  515. pListInfo( ( pListInfo ) ? InlineAddRef( pListInfo ) : NULL )
  516. {
  517. // @NOTE (toml 8/18/2006): because doing memcmp, need to fill all of the fields and the padding!
  518. memset( &m_bOrtho, 0, offsetof(Entry_t, pList ) - offsetof(Entry_t, m_bOrtho ) );
  519. m_bOrtho = viewSetup.m_bOrtho;
  520. m_OrthoLeft = viewSetup.m_OrthoLeft;
  521. m_OrthoTop = viewSetup.m_OrthoTop;
  522. m_OrthoRight = viewSetup.m_OrthoRight;
  523. m_OrthoBottom = viewSetup.m_OrthoBottom;
  524. fov = viewSetup.fov;
  525. origin = viewSetup.origin;
  526. angles = viewSetup.angles;
  527. zNear = viewSetup.zNear;
  528. zFar = viewSetup.zFar;
  529. m_flAspectRatio = viewSetup.m_flAspectRatio;
  530. m_bOffCenter = viewSetup.m_bOffCenter;
  531. m_flOffCenterTop = viewSetup.m_flOffCenterTop;
  532. m_flOffCenterBottom = viewSetup.m_flOffCenterBottom;
  533. m_flOffCenterLeft = viewSetup.m_flOffCenterLeft;
  534. m_flOffCenterRight = viewSetup.m_flOffCenterRight;
  535. if ( pVisOverrideData )
  536. {
  537. memcpy( &m_VisOverride, pVisOverrideData, sizeof(m_VisOverride) );
  538. }
  539. else
  540. {
  541. memset( &m_VisOverride, 0, sizeof(m_VisOverride) );
  542. }
  543. m_iForceViewLeaf = iForceViewLeaf;
  544. }
  545. ~Entry_t()
  546. {
  547. if ( pList )
  548. {
  549. pList->Release();
  550. }
  551. if ( pListInfo )
  552. {
  553. pListInfo->Release();
  554. }
  555. }
  556. // The fields from CViewSetup and ViewCustomVisibility_t that would actually affect the list
  557. int m_iForceViewLeaf;
  558. VisOverrideData_t m_VisOverride;
  559. float m_OrthoLeft;
  560. float m_OrthoTop;
  561. float m_OrthoRight;
  562. float m_OrthoBottom;
  563. float fov;
  564. Vector origin;
  565. QAngle angles;
  566. float zNear;
  567. float zFar;
  568. float m_flAspectRatio;
  569. float m_flOffCenterTop;
  570. float m_flOffCenterBottom;
  571. float m_flOffCenterLeft;
  572. float m_flOffCenterRight;
  573. bool m_bOrtho;
  574. bool m_bOffCenter;
  575. IWorldRenderList *pList;
  576. ClientWorldListInfo_t *pListInfo;
  577. };
  578. class CEntryComparator
  579. {
  580. public:
  581. // This class has to be implicitly constructible from int due to Valve's implementation of CUtlRbTree.
  582. // cppcheck-suppress noExplicitConstructor
  583. CEntryComparator( int ) {}
  584. bool operator!() const { return false; }
  585. bool operator()( const Entry_t *lhs, const Entry_t *rhs ) const
  586. {
  587. return ( memcmp( lhs, rhs, sizeof(Entry_t) - ( sizeof(Entry_t) - offsetof(Entry_t, pList ) ) ) < 0 );
  588. }
  589. };
  590. CUtlRBTree<Entry_t *, unsigned short, CEntryComparator> m_Entries;
  591. };
  592. CWorldListCache g_WorldListCache;
  593. //-----------------------------------------------------------------------------
  594. // Standard 3d skybox view
  595. //-----------------------------------------------------------------------------
  596. class CSkyboxView : public CRendering3dView
  597. {
  598. DECLARE_CLASS( CSkyboxView, CRendering3dView );
  599. public:
  600. explicit CSkyboxView(CViewRender *pMainView) :
  601. CRendering3dView( pMainView ),
  602. m_pSky3dParams( NULL )
  603. {
  604. }
  605. bool Setup( const CViewSetup &view, int *pClearFlags, SkyboxVisibility_t *pSkyboxVisible );
  606. void Draw();
  607. protected:
  608. #ifdef PORTAL
  609. virtual bool ShouldDrawPortals() { return false; }
  610. #endif
  611. virtual SkyboxVisibility_t ComputeSkyboxVisibility();
  612. bool GetSkyboxFogEnable();
  613. void Enable3dSkyboxFog( void );
  614. void DrawInternal( view_id_t iSkyBoxViewID = VIEW_3DSKY, bool bInvokePreAndPostRender = true, ITexture *pRenderTarget = NULL );
  615. sky3dparams_t * PreRender3dSkyboxWorld( SkyboxVisibility_t nSkyboxVisible );
  616. sky3dparams_t *m_pSky3dParams;
  617. };
  618. //-----------------------------------------------------------------------------
  619. // 3d skybox view when drawing portals
  620. //-----------------------------------------------------------------------------
  621. #ifdef PORTAL
  622. class CPortalSkyboxView : public CSkyboxView
  623. {
  624. DECLARE_CLASS( CPortalSkyboxView, CSkyboxView );
  625. public:
  626. CPortalSkyboxView(CViewRender *pMainView) :
  627. CSkyboxView( pMainView ),
  628. m_pRenderTarget( NULL )
  629. {}
  630. bool Setup( const CViewSetup &view, int *pClearFlags, SkyboxVisibility_t *pSkyboxVisible, ITexture *pRenderTarget = NULL );
  631. //Skybox drawing through portals with workarounds to fix area bits, position/scaling, view id's..........
  632. void Draw();
  633. private:
  634. virtual SkyboxVisibility_t ComputeSkyboxVisibility();
  635. ITexture *m_pRenderTarget;
  636. };
  637. #endif
  638. //-----------------------------------------------------------------------------
  639. // Shadow depth texture
  640. //-----------------------------------------------------------------------------
  641. class CShadowDepthView : public CRendering3dView
  642. {
  643. DECLARE_CLASS( CShadowDepthView, CRendering3dView );
  644. public:
  645. explicit CShadowDepthView(CViewRender *pMainView) : CRendering3dView( pMainView ), m_bRenderWorldAndObjects( false ), m_bRenderViewModels( false ) {}
  646. void Setup( const CViewSetup &shadowViewIn, ITexture *pRenderTarget, ITexture *pDepthTexture, bool bRenderWorldAndObjects = true, bool bRenderViewModels = false );
  647. void Draw();
  648. private:
  649. ITexture *m_pRenderTarget;
  650. ITexture *m_pDepthTexture;
  651. bool m_bRenderWorldAndObjects;
  652. bool m_bRenderViewModels;
  653. };
  654. //-----------------------------------------------------------------------------
  655. // Freeze frame. Redraws the frame at which it was enabled.
  656. //-----------------------------------------------------------------------------
  657. class CFreezeFrameView : public CRendering3dView
  658. {
  659. DECLARE_CLASS( CFreezeFrameView, CRendering3dView );
  660. public:
  661. explicit CFreezeFrameView(CViewRender *pMainView) : CRendering3dView( pMainView ) {}
  662. void Setup( const CViewSetup &view );
  663. void Draw();
  664. private:
  665. CMaterialReference m_pFreezeFrame;
  666. CMaterialReference m_TranslucentSingleColor;
  667. int m_nSubRect[ 4 ];
  668. int m_nScreenSize[ 2 ];
  669. };
  670. //-----------------------------------------------------------------------------
  671. //
  672. //-----------------------------------------------------------------------------
  673. class CBaseWorldView : public CRendering3dView
  674. {
  675. DECLARE_CLASS( CBaseWorldView, CRendering3dView );
  676. protected:
  677. explicit CBaseWorldView(CViewRender *pMainView) : CRendering3dView( pMainView ) {}
  678. virtual bool AdjustView( float waterHeight );
  679. void DrawSetup( IMatRenderContext *pRenderContext, float waterHeight, int flags, float waterZAdjust, int iForceViewLeaf = -1 );
  680. void DrawExecute( float waterHeight, view_id_t viewID, float waterZAdjust );
  681. virtual void PushView( float waterHeight );
  682. virtual void PopView();
  683. void SSAO_DepthPass();
  684. };
  685. //-----------------------------------------------------------------------------
  686. // Draws the scene when there's no water or only cheap water
  687. //-----------------------------------------------------------------------------
  688. class CSimpleWorldView : public CBaseWorldView
  689. {
  690. DECLARE_CLASS( CSimpleWorldView, CBaseWorldView );
  691. public:
  692. explicit CSimpleWorldView(CViewRender *pMainView) : CBaseWorldView( pMainView ) {}
  693. void Setup( const CViewSetup &view, int nClearFlags, bool bDrawSkybox, const VisibleFogVolumeInfo_t &fogInfo, const WaterRenderInfo_t& info, ViewCustomVisibility_t *pCustomVisibility = NULL );
  694. void Draw();
  695. private:
  696. VisibleFogVolumeInfo_t m_fogInfo;
  697. };
  698. //-----------------------------------------------------------------------------
  699. // Base class for scenes with water
  700. //-----------------------------------------------------------------------------
  701. class CBaseWaterView : public CBaseWorldView
  702. {
  703. DECLARE_CLASS( CBaseWaterView, CBaseWorldView );
  704. public:
  705. explicit CBaseWaterView(CViewRender *pMainView) :
  706. CBaseWorldView( pMainView ),
  707. m_SoftwareIntersectionView( pMainView )
  708. {}
  709. // void Setup( const CViewSetup &, const WaterRenderInfo_t& info );
  710. protected:
  711. void CalcWaterEyeAdjustments( const VisibleFogVolumeInfo_t &fogInfo, float &newWaterHeight, float &waterZAdjust, bool bSoftwareUserClipPlane );
  712. class CSoftwareIntersectionView : public CBaseWorldView
  713. {
  714. DECLARE_CLASS( CSoftwareIntersectionView, CBaseWorldView );
  715. public:
  716. explicit CSoftwareIntersectionView(CViewRender *pMainView) : CBaseWorldView( pMainView ) {}
  717. void Setup( bool bAboveWater );
  718. void Draw();
  719. private:
  720. CBaseWaterView *GetOuter() { return GET_OUTER( CBaseWaterView, m_SoftwareIntersectionView ); }
  721. };
  722. friend class CSoftwareIntersectionView;
  723. CSoftwareIntersectionView m_SoftwareIntersectionView;
  724. WaterRenderInfo_t m_waterInfo;
  725. float m_waterHeight;
  726. float m_waterZAdjust;
  727. bool m_bSoftwareUserClipPlane;
  728. VisibleFogVolumeInfo_t m_fogInfo;
  729. };
  730. //-----------------------------------------------------------------------------
  731. // Scenes above water
  732. //-----------------------------------------------------------------------------
  733. class CAboveWaterView : public CBaseWaterView
  734. {
  735. DECLARE_CLASS( CAboveWaterView, CBaseWaterView );
  736. public:
  737. explicit CAboveWaterView(CViewRender *pMainView) :
  738. CBaseWaterView( pMainView ),
  739. m_ReflectionView( pMainView ),
  740. m_RefractionView( pMainView ),
  741. m_IntersectionView( pMainView )
  742. {}
  743. void Setup( const CViewSetup &view, bool bDrawSkybox, const VisibleFogVolumeInfo_t &fogInfo, const WaterRenderInfo_t& waterInfo, ViewCustomVisibility_t *pCustomVisibility = NULL );
  744. void Draw();
  745. class CReflectionView : public CBaseWorldView
  746. {
  747. DECLARE_CLASS( CReflectionView, CBaseWorldView );
  748. public:
  749. explicit CReflectionView(CViewRender *pMainView) : CBaseWorldView( pMainView ) {}
  750. void Setup( bool bReflectEntities, bool bReflectOnlyMarkedEntities, bool bReflect2DSkybox );
  751. void Draw();
  752. private:
  753. CAboveWaterView *GetOuter() { return GET_OUTER( CAboveWaterView, m_ReflectionView ); }
  754. };
  755. class CRefractionView : public CBaseWorldView
  756. {
  757. DECLARE_CLASS( CRefractionView, CBaseWorldView );
  758. public:
  759. explicit CRefractionView(CViewRender *pMainView) : CBaseWorldView( pMainView ) {}
  760. void Setup();
  761. void Draw();
  762. private:
  763. CAboveWaterView *GetOuter() { return GET_OUTER( CAboveWaterView, m_RefractionView ); }
  764. };
  765. class CIntersectionView : public CBaseWorldView
  766. {
  767. DECLARE_CLASS( CIntersectionView, CBaseWorldView );
  768. public:
  769. explicit CIntersectionView(CViewRender *pMainView) : CBaseWorldView( pMainView ) {}
  770. void Setup();
  771. void Draw();
  772. private:
  773. CAboveWaterView *GetOuter() { return GET_OUTER( CAboveWaterView, m_IntersectionView ); }
  774. };
  775. friend class CRefractionView;
  776. friend class CReflectionView;
  777. friend class CIntersectionView;
  778. bool m_bViewIntersectsWater;
  779. CReflectionView m_ReflectionView;
  780. CRefractionView m_RefractionView;
  781. CIntersectionView m_IntersectionView;
  782. };
  783. //-----------------------------------------------------------------------------
  784. // Scenes below water
  785. //-----------------------------------------------------------------------------
  786. class CUnderWaterView : public CBaseWaterView
  787. {
  788. DECLARE_CLASS( CUnderWaterView, CBaseWaterView );
  789. public:
  790. explicit CUnderWaterView(CViewRender *pMainView) :
  791. CBaseWaterView( pMainView ),
  792. m_RefractionView( pMainView )
  793. {}
  794. void Setup( const CViewSetup &view, bool bDrawSkybox, const VisibleFogVolumeInfo_t &fogInfo, const WaterRenderInfo_t& info, ViewCustomVisibility_t *pCustomVisibility = NULL );
  795. void Draw();
  796. class CRefractionView : public CBaseWorldView
  797. {
  798. DECLARE_CLASS( CRefractionView, CBaseWorldView );
  799. public:
  800. explicit CRefractionView(CViewRender *pMainView) : CBaseWorldView( pMainView ) {}
  801. void Setup();
  802. void Draw();
  803. private:
  804. CUnderWaterView *GetOuter() { return GET_OUTER( CUnderWaterView, m_RefractionView ); }
  805. };
  806. friend class CRefractionView;
  807. bool m_bDrawSkybox; // @MULTICORE (toml 8/17/2006): remove after setup hoisted
  808. CRefractionView m_RefractionView;
  809. };
  810. //-----------------------------------------------------------------------------
  811. // Scenes containing reflective glass
  812. //-----------------------------------------------------------------------------
  813. class CReflectiveGlassView : public CSimpleWorldView
  814. {
  815. DECLARE_CLASS( CReflectiveGlassView, CSimpleWorldView );
  816. public:
  817. explicit CReflectiveGlassView( CViewRender *pMainView ) : BaseClass( pMainView )
  818. {
  819. }
  820. virtual bool AdjustView( float flWaterHeight );
  821. virtual void PushView( float waterHeight );
  822. virtual void PopView( );
  823. void Setup( const CViewSetup &view, int nClearFlags, bool bDrawSkybox, const VisibleFogVolumeInfo_t &fogInfo, const WaterRenderInfo_t &waterInfo, const cplane_t &reflectionPlane );
  824. void Draw();
  825. cplane_t m_ReflectionPlane;
  826. };
  827. class CRefractiveGlassView : public CSimpleWorldView
  828. {
  829. DECLARE_CLASS( CRefractiveGlassView, CSimpleWorldView );
  830. public:
  831. explicit CRefractiveGlassView( CViewRender *pMainView ) : BaseClass( pMainView )
  832. {
  833. }
  834. virtual bool AdjustView( float flWaterHeight );
  835. virtual void PushView( float waterHeight );
  836. virtual void PopView( );
  837. void Setup( const CViewSetup &view, int nClearFlags, bool bDrawSkybox, const VisibleFogVolumeInfo_t &fogInfo, const WaterRenderInfo_t &waterInfo, const cplane_t &reflectionPlane );
  838. void Draw();
  839. cplane_t m_ReflectionPlane;
  840. };
  841. //-----------------------------------------------------------------------------
  842. // view of a single entity by itself
  843. //-----------------------------------------------------------------------------
  844. #ifdef PORTAL2
  845. class CAperturePhotoView : public CSimpleWorldView
  846. {
  847. DECLARE_CLASS( CAperturePhotoView, CSimpleWorldView );
  848. public:
  849. CAperturePhotoView(CViewRender *pMainView) :
  850. CSimpleWorldView( pMainView ),
  851. m_pRenderTarget( NULL )
  852. {}
  853. bool Setup( C_BaseEntity *pTargetEntity, const CViewSetup &view, int *pClearFlags, SkyboxVisibility_t *pSkyboxVisible, ITexture *pRenderTarget = NULL );
  854. //Skybox drawing through portals with workarounds to fix area bits, position/scaling, view id's..........
  855. void Draw();
  856. #ifdef PORTAL
  857. virtual bool ShouldDrawPortals() { return false; }
  858. #endif
  859. private:
  860. ITexture *m_pRenderTarget;
  861. C_BaseEntity *m_pTargetEntity;
  862. };
  863. #endif
  864. //-----------------------------------------------------------------------------
  865. // Computes draw flags for the engine to build its world surface lists
  866. //-----------------------------------------------------------------------------
  867. static inline unsigned long BuildEngineDrawWorldListFlags( unsigned nDrawFlags )
  868. {
  869. unsigned long nEngineFlags = 0;
  870. if ( ( nDrawFlags & DF_SKIP_WORLD ) == 0 )
  871. {
  872. nEngineFlags |= DRAWWORLDLISTS_DRAW_WORLD_GEOMETRY;
  873. }
  874. if ( ( nDrawFlags & DF_SKIP_WORLD_DECALS_AND_OVERLAYS ) == 0 )
  875. {
  876. nEngineFlags |= DRAWWORLDLISTS_DRAW_DECALS_AND_OVERLAYS;
  877. }
  878. if ( nDrawFlags & DF_DRAWSKYBOX )
  879. {
  880. nEngineFlags |= DRAWWORLDLISTS_DRAW_SKYBOX;
  881. }
  882. if ( nDrawFlags & DF_RENDER_ABOVEWATER )
  883. {
  884. nEngineFlags |= DRAWWORLDLISTS_DRAW_STRICTLYABOVEWATER;
  885. nEngineFlags |= DRAWWORLDLISTS_DRAW_INTERSECTSWATER;
  886. }
  887. if ( nDrawFlags & DF_RENDER_UNDERWATER )
  888. {
  889. nEngineFlags |= DRAWWORLDLISTS_DRAW_STRICTLYUNDERWATER;
  890. nEngineFlags |= DRAWWORLDLISTS_DRAW_INTERSECTSWATER;
  891. }
  892. if ( nDrawFlags & DF_RENDER_WATER )
  893. {
  894. nEngineFlags |= DRAWWORLDLISTS_DRAW_WATERSURFACE;
  895. }
  896. if( nDrawFlags & DF_CLIP_SKYBOX )
  897. {
  898. nEngineFlags |= DRAWWORLDLISTS_DRAW_CLIPSKYBOX;
  899. }
  900. if( nDrawFlags & DF_SHADOW_DEPTH_MAP )
  901. {
  902. nEngineFlags |= DRAWWORLDLISTS_DRAW_SHADOWDEPTH;
  903. nEngineFlags &= ~DRAWWORLDLISTS_DRAW_DECALS_AND_OVERLAYS;
  904. }
  905. if( nDrawFlags & DF_RENDER_REFRACTION )
  906. {
  907. nEngineFlags |= DRAWWORLDLISTS_DRAW_REFRACTION;
  908. }
  909. if( nDrawFlags & DF_RENDER_REFLECTION )
  910. {
  911. nEngineFlags |= DRAWWORLDLISTS_DRAW_REFLECTION;
  912. }
  913. if ( nDrawFlags & ( DF_DRAW_SIMPLE_WORLD_MODEL | DF_DRAW_SIMPLE_WORLD_MODEL_WATER ) )
  914. {
  915. nEngineFlags &= ~DRAWWORLDLISTS_DRAW_WORLD_GEOMETRY;
  916. nEngineFlags &= ~DRAWWORLDLISTS_DRAW_DECALS_AND_OVERLAYS;
  917. if ( nDrawFlags & DF_DRAW_SIMPLE_WORLD_MODEL )
  918. {
  919. nEngineFlags |= DRAWWORLDLISTS_DRAW_SIMPLE_WORLD_MODEL;
  920. }
  921. if ( nDrawFlags & DF_DRAW_SIMPLE_WORLD_MODEL_WATER )
  922. {
  923. nEngineFlags |= DRAWWORLDLISTS_DRAW_SIMPLE_WORLD_MODEL_WATER;
  924. }
  925. }
  926. if ( nDrawFlags & DF_SSAO_DEPTH_PASS )
  927. {
  928. nEngineFlags |= DRAWWORLDLISTS_DRAW_SSAO | DRAWWORLDLISTS_DRAW_STRICTLYUNDERWATER | DRAWWORLDLISTS_DRAW_INTERSECTSWATER | DRAWWORLDLISTS_DRAW_STRICTLYABOVEWATER;
  929. nEngineFlags &= ~( DRAWWORLDLISTS_DRAW_WATERSURFACE | DRAWWORLDLISTS_DRAW_REFRACTION | DRAWWORLDLISTS_DRAW_REFLECTION | DRAWWORLDLISTS_DRAW_DECALS_AND_OVERLAYS );
  930. }
  931. return nEngineFlags;
  932. }
  933. //-----------------------------------------------------------------------------
  934. //
  935. //-----------------------------------------------------------------------------
  936. static void SetClearColorToFogColor()
  937. {
  938. unsigned char ucFogColor[3];
  939. CMatRenderContextPtr pRenderContext( materials );
  940. pRenderContext->GetFogColor( ucFogColor );
  941. if( g_pMaterialSystemHardwareConfig->GetHDRType() == HDR_TYPE_INTEGER )
  942. {
  943. // @MULTICORE (toml 8/16/2006): Find a way to not do this twice in eye above water case
  944. float scale = LinearToGammaFullRange( pRenderContext->GetToneMappingScaleLinear().x );
  945. ucFogColor[0] = clamp( (float)ucFogColor[0] * scale, 0, 255);
  946. ucFogColor[1] = clamp( (float)ucFogColor[1] * scale, 0, 255);
  947. ucFogColor[2] = clamp( (float)ucFogColor[2] * scale, 0, 255);
  948. }
  949. pRenderContext->ClearColor4ub( ucFogColor[0], ucFogColor[1], ucFogColor[2], 255 );
  950. }
  951. //-----------------------------------------------------------------------------
  952. // Precache of necessary materials
  953. //-----------------------------------------------------------------------------
  954. #ifdef HL2_CLIENT_DLL
  955. PRECACHE_REGISTER_BEGIN( GLOBAL, PrecacheViewRender )
  956. PRECACHE( MATERIAL, "scripted/intro_screenspaceeffect" )
  957. PRECACHE_REGISTER_END()
  958. #endif
  959. PRECACHE_REGISTER_BEGIN( GLOBAL, PrecachePostProcessingEffects )
  960. PRECACHE( MATERIAL, "dev/blurfiltery_and_add_nohdr" )
  961. PRECACHE( MATERIAL, "dev/blurfilterx" )
  962. PRECACHE( MATERIAL, "dev/blurfilterx_nohdr" )
  963. PRECACHE( MATERIAL, "dev/blurfiltery" )
  964. PRECACHE( MATERIAL, "dev/blurfiltery_nohdr" )
  965. PRECACHE( MATERIAL, "dev/blurfiltery_nohdr_clear" )
  966. PRECACHE( MATERIAL, "dev/bloomadd" )
  967. PRECACHE( MATERIAL, "dev/clearalpha" )
  968. PRECACHE( MATERIAL, "dev/downsample" )
  969. PRECACHE( MATERIAL, "dev/downsample_non_hdr" )
  970. PRECACHE( MATERIAL, "dev/no_pixel_write" )
  971. PRECACHE( MATERIAL, "dev/lumcompare" )
  972. PRECACHE( MATERIAL, "dev/floattoscreen_combine" )
  973. PRECACHE( MATERIAL, "dev/copyfullframefb_vanilla" )
  974. PRECACHE( MATERIAL, "dev/copyfullframefb" )
  975. PRECACHE( MATERIAL, "dev/engine_post" )
  976. PRECACHE( MATERIAL, "dev/engine_post_splitscreen" )
  977. PRECACHE( MATERIAL, "dev/motion_blur" )
  978. PRECACHE( MATERIAL, "dev/depth_of_field" )
  979. PRECACHE( MATERIAL, "dev/blurgaussian_3x3" )
  980. PRECACHE( MATERIAL, "dev/fade_blur" )
  981. PRECACHE( MATERIAL, "debug/debugscreenspacewireframe" )
  982. #if defined( INFESTED_DLL ) || defined( DOTA_DLL ) || defined( CSTRIKE_DLL )
  983. PRECACHE( MATERIAL, "dev/glow_color" )
  984. PRECACHE( MATERIAL, "dev/glow_health_color" )
  985. PRECACHE( MATERIAL, "dev/glow_downsample" )
  986. PRECACHE( MATERIAL, "dev/glow_blur_x" )
  987. PRECACHE( MATERIAL, "dev/glow_blur_y" )
  988. PRECACHE( MATERIAL, "dev/halo_add_to_screen" )
  989. PRECACHE( MATERIAL, "dev/glow_rim3d" )
  990. PRECACHE( MATERIAL, "dev/glow_edge_highlight" )
  991. #ifdef IRONSIGHT
  992. PRECACHE( MATERIAL, "dev/scope_blur_x" )
  993. PRECACHE( MATERIAL, "dev/scope_blur_y" )
  994. PRECACHE( MATERIAL, "dev/scope_bluroverlay" )
  995. PRECACHE( MATERIAL, "dev/scope_downsample" )
  996. PRECACHE( MATERIAL, "dev/scope_mask" )
  997. PRECACHE( MATERIAL, "models/weapons/shared/scope/scope_dot_green")
  998. PRECACHE( MATERIAL, "models/weapons/shared/scope/scope_dot_red")
  999. #endif
  1000. #endif // INFESTED_DLL || DOTA_DLL
  1001. #if defined( INFESTED_DLL )
  1002. PRECACHE( MATERIAL, "engine/writestencil" )
  1003. #endif // INFSETED_DLL
  1004. PRECACHE_REGISTER_END( )
  1005. //-----------------------------------------------------------------------------
  1006. // Accessors to return the current view being rendered
  1007. //-----------------------------------------------------------------------------
  1008. const Vector &CurrentViewOrigin()
  1009. {
  1010. Assert( s_bCanAccessCurrentView );
  1011. return g_vecCurrentRenderOrigin;
  1012. }
  1013. const QAngle &CurrentViewAngles()
  1014. {
  1015. Assert( s_bCanAccessCurrentView );
  1016. return g_vecCurrentRenderAngles;
  1017. }
  1018. const Vector &CurrentViewForward()
  1019. {
  1020. Assert( s_bCanAccessCurrentView );
  1021. return g_vecCurrentVForward;
  1022. }
  1023. const Vector &CurrentViewRight()
  1024. {
  1025. Assert( s_bCanAccessCurrentView );
  1026. return g_vecCurrentVRight;
  1027. }
  1028. const Vector &CurrentViewUp()
  1029. {
  1030. Assert( s_bCanAccessCurrentView );
  1031. return g_vecCurrentVUp;
  1032. }
  1033. const VMatrix &CurrentWorldToViewMatrix()
  1034. {
  1035. Assert( s_bCanAccessCurrentView );
  1036. return g_matCurrentCamInverse;
  1037. }
  1038. //-----------------------------------------------------------------------------
  1039. // Methods to set the current view/guard access to view parameters
  1040. //-----------------------------------------------------------------------------
  1041. void AllowCurrentViewAccess( bool allow )
  1042. {
  1043. s_bCanAccessCurrentView = allow;
  1044. }
  1045. bool IsCurrentViewAccessAllowed()
  1046. {
  1047. return s_bCanAccessCurrentView;
  1048. }
  1049. static ConVar mat_lpreview_mode( "mat_lpreview_mode", "-1", FCVAR_CHEAT );
  1050. void SetupCurrentView( const Vector &vecOrigin, const QAngle &angles, view_id_t viewID, bool bDrawWorldNormal = false, bool bCullFrontFaces = false )
  1051. {
  1052. // Store off view origin and angles
  1053. g_vecCurrentRenderOrigin = vecOrigin;
  1054. g_vecCurrentRenderAngles = angles;
  1055. // Compute the world->main camera transform
  1056. ComputeCameraVariables( vecOrigin, angles,
  1057. &g_vecCurrentVForward, &g_vecCurrentVRight, &g_vecCurrentVUp, &g_matCurrentCamInverse );
  1058. g_CurrentViewID = viewID;
  1059. AllowCurrentViewAccess( true );
  1060. // Cache off fade distances
  1061. float flScreenFadeMinSize, flScreenFadeMaxSize, flFadeDistScale;
  1062. view->GetScreenFadeDistances( &flScreenFadeMinSize, &flScreenFadeMaxSize, &flFadeDistScale );
  1063. modelinfo->SetViewScreenFadeRange( flScreenFadeMinSize, flScreenFadeMaxSize );
  1064. CMatRenderContextPtr pRenderContext( materials );
  1065. #ifdef PORTAL
  1066. if ( g_pPortalRender->GetViewRecursionLevel() == 0 )
  1067. {
  1068. pRenderContext->SetIntRenderingParameter( INT_RENDERPARM_WRITE_DEPTH_TO_DESTALPHA, ((viewID == VIEW_MAIN) || (viewID == VIEW_3DSKY)) ? 1 : 0 );
  1069. }
  1070. #else
  1071. pRenderContext->SetIntRenderingParameter( INT_RENDERPARM_WRITE_DEPTH_TO_DESTALPHA, ((viewID == VIEW_MAIN) || (viewID == VIEW_3DSKY)) ? 1 : 0 );
  1072. #endif
  1073. if ( bDrawWorldNormal )
  1074. pRenderContext->SetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING, ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH );
  1075. if ( mat_lpreview_mode.GetInt() != -1 )
  1076. pRenderContext->SetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING, mat_lpreview_mode.GetInt() );
  1077. if ( bCullFrontFaces )
  1078. {
  1079. pRenderContext->FlipCulling( true );
  1080. }
  1081. }
  1082. view_id_t CurrentViewID()
  1083. {
  1084. Assert( g_CurrentViewID != VIEW_ILLEGAL );
  1085. return ( view_id_t )g_CurrentViewID;
  1086. }
  1087. //-----------------------------------------------------------------------------
  1088. // Purpose: Portal views are considered 'Main' views. This function tests a view id
  1089. // against all view ids used by portal renderables, as well as the main view.
  1090. //-----------------------------------------------------------------------------
  1091. bool IsMainView ( view_id_t id )
  1092. {
  1093. #if defined(PORTAL)
  1094. return ( (id == VIEW_MAIN) || g_pPortalRender->IsPortalViewID( id ) );
  1095. #else
  1096. return (id == VIEW_MAIN);
  1097. #endif
  1098. }
  1099. void FinishCurrentView()
  1100. {
  1101. AllowCurrentViewAccess( false );
  1102. }
  1103. //-----------------------------------------------------------------------------
  1104. // Constructor
  1105. //-----------------------------------------------------------------------------
  1106. void CSimpleRenderExecutor::AddView( CRendering3dView *pView )
  1107. {
  1108. // slightly kludgy place to put the viewBuilder frame initialisation
  1109. g_viewBuilder.PushBuildView();
  1110. CBase3dView *pPrevRenderer = m_pMainView->SetActiveRenderer( pView );
  1111. pView->Draw();
  1112. m_pMainView->SetActiveRenderer( pPrevRenderer );
  1113. // slightly kludgy place to put the viewBuilder frame initialisation
  1114. g_viewBuilder.PopBuildView();
  1115. }
  1116. #if !defined( TF_CLIENT_DLL ) && !defined( INFESTED_DLL ) && !defined( DOTA_DLL ) && !defined(CSTRIKE_DLL)
  1117. static CViewRender g_ViewRender;
  1118. IViewRender *GetViewRenderInstance()
  1119. {
  1120. return &g_ViewRender;
  1121. }
  1122. #endif
  1123. //-----------------------------------------------------------------------------
  1124. // Constructor
  1125. //-----------------------------------------------------------------------------
  1126. CViewRender::CViewRender()
  1127. : m_SimpleExecutor( this )
  1128. {
  1129. m_flCheapWaterStartDistance = 0.0f;
  1130. m_flCheapWaterEndDistance = 0.1f;
  1131. m_BaseDrawFlags = 0;
  1132. m_pActiveRenderer = NULL;
  1133. m_pCurrentlyDrawingEntity = NULL;
  1134. m_bAllowViewAccess = false;
  1135. m_flOldChaseOverviewScale = 1.0f;
  1136. m_flIdealChaseOverviewScale = 1.0f;
  1137. m_flNextIdealOverviewScaleUpdate = 0;
  1138. m_flSmokeOverlayAmount = 0;
  1139. }
  1140. //-----------------------------------------------------------------------------
  1141. // Purpose:
  1142. // Output : Returns true on success, false on failure.
  1143. //-----------------------------------------------------------------------------
  1144. inline bool CViewRender::ShouldDrawEntities( void )
  1145. {
  1146. return ( !m_pDrawEntities || (m_pDrawEntities->GetInt() != 0) );
  1147. }
  1148. //-----------------------------------------------------------------------------
  1149. // Purpose: Check all conditions which would prevent drawing the view model
  1150. // Input : drawViewmodel -
  1151. // *viewmodel -
  1152. // Output : Returns true on success, false on failure.
  1153. //-----------------------------------------------------------------------------
  1154. bool CViewRender::ShouldDrawViewModel( bool bDrawViewmodel )
  1155. {
  1156. if ( !bDrawViewmodel )
  1157. return false;
  1158. if ( !r_drawviewmodel.GetBool() )
  1159. return false;
  1160. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  1161. if ( !C_BasePlayer::GetLocalPlayer() )
  1162. return false;
  1163. if ( C_BasePlayer::GetLocalPlayer()->ShouldDrawLocalPlayer() &&
  1164. ( C_BasePlayer::GetLocalPlayer()->GetObserverMode() != OBS_MODE_IN_EYE || C_BasePlayer::GetLocalPlayer()->GetObserverInterpState() == C_BasePlayer::OBSERVER_INTERP_TRAVELING ) )
  1165. return false;
  1166. if ( !ShouldDrawEntities() )
  1167. return false;
  1168. if ( render->GetViewEntity() > gpGlobals->maxClients )
  1169. return false;
  1170. return true;
  1171. }
  1172. //-----------------------------------------------------------------------------
  1173. // Purpose:
  1174. //-----------------------------------------------------------------------------
  1175. bool CViewRender::UpdateRefractIfNeededByList( CViewModelRenderablesList::RenderGroups_t &list )
  1176. {
  1177. int nCount = list.Count();
  1178. for( int i=0; i < nCount; ++i )
  1179. {
  1180. IClientRenderable *pRenderable = list[i].m_pRenderable;
  1181. Assert( pRenderable );
  1182. if ( pRenderable->GetRenderFlags() & ERENDERFLAGS_NEEDS_POWER_OF_TWO_FB )
  1183. {
  1184. UpdateRefractTexture();
  1185. return true;
  1186. }
  1187. }
  1188. return false;
  1189. }
  1190. //-----------------------------------------------------------------------------
  1191. // Purpose:
  1192. //-----------------------------------------------------------------------------
  1193. void CViewRender::DrawRenderablesInList( CViewModelRenderablesList::RenderGroups_t &renderGroups, int flags )
  1194. {
  1195. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  1196. #if defined( DBGFLAG_ASSERT )
  1197. int nSlot = GET_ACTIVE_SPLITSCREEN_SLOT();
  1198. #endif
  1199. Assert( m_pCurrentlyDrawingEntity == NULL );
  1200. int nCount = renderGroups.Count();
  1201. for( int i=0; i < nCount; ++i )
  1202. {
  1203. IClientRenderable *pRenderable = renderGroups[i].m_pRenderable;
  1204. Assert( pRenderable );
  1205. // Non-view models wanting to render in view model list...
  1206. Assert( pRenderable->ShouldDraw() );
  1207. #ifdef PORTAL
  1208. Assert( ( g_pPortalRender->GetViewRecursionLevel() > 0 ) || !IsSplitScreenSupported() || pRenderable->ShouldDrawForSplitScreenUser( nSlot ) );
  1209. #else
  1210. Assert( !IsSplitScreenSupported() || pRenderable->ShouldDrawForSplitScreenUser( nSlot ) );
  1211. #endif
  1212. m_pCurrentlyDrawingEntity = pRenderable->GetIClientUnknown()->GetBaseEntity();
  1213. int nDrawFlags = STUDIO_RENDER | flags;
  1214. nDrawFlags |= renderGroups[i].m_InstanceData.m_bTwoPass ? STUDIO_TWOPASS : 0;
  1215. pRenderable->DrawModel( nDrawFlags, renderGroups[i].m_InstanceData );
  1216. }
  1217. m_pCurrentlyDrawingEntity = NULL;
  1218. }
  1219. void CViewRender::DrawViewModelsShadowDepth( const CViewSetup &view )
  1220. {
  1221. bool bShouldDrawPlayerViewModel = ShouldDrawViewModel( true );
  1222. bool bShouldDrawToolViewModels = ToolsEnabled();
  1223. if ( !bShouldDrawPlayerViewModel && !bShouldDrawToolViewModels )
  1224. return;
  1225. CViewModelRenderablesList list;
  1226. ClientLeafSystem()->CollateViewModelRenderables( &list );
  1227. CViewModelRenderablesList::RenderGroups_t &opaqueList = list.m_RenderGroups[ CViewModelRenderablesList::VM_GROUP_OPAQUE ];
  1228. CViewModelRenderablesList listNormalFOV;
  1229. CViewModelRenderablesList::RenderGroups_t &opaqueNormalFOVList = listNormalFOV.m_RenderGroups[ CViewModelRenderablesList::VM_GROUP_OPAQUE ];
  1230. // Remove objects from the list that tools don't want
  1231. // Move objects that aren't actually of the view model class into a different list so we can render them with normal FOV
  1232. bool bRemove = ToolsEnabled() && ( !bShouldDrawPlayerViewModel || !bShouldDrawToolViewModels );
  1233. int nOpaque = opaqueList.Count();
  1234. for ( int i = nOpaque-1; i >= 0; --i )
  1235. {
  1236. IClientRenderable *pRenderable = opaqueList[ i ].m_pRenderable;
  1237. bool bEntity = pRenderable->GetIClientUnknown()->GetBaseEntity() ? true : false;
  1238. if ( bRemove )
  1239. {
  1240. if ( ( bEntity && !bShouldDrawPlayerViewModel ) || ( !bEntity && !bShouldDrawToolViewModels ) )
  1241. {
  1242. // Remove it
  1243. opaqueList.FastRemove( i );
  1244. continue;
  1245. }
  1246. }
  1247. if ( !dynamic_cast<C_BaseViewModel*>( pRenderable ) )
  1248. {
  1249. // Copy into the no VM FOV list
  1250. opaqueNormalFOVList.AddToTail( opaqueList[ i ] );
  1251. opaqueList.FastRemove( i );
  1252. }
  1253. }
  1254. // Update refract for opaque models & draw
  1255. DrawRenderablesInList( opaqueList );
  1256. // Render objects that use normal FOV
  1257. if ( opaqueNormalFOVList.Count() > 0 )
  1258. {
  1259. // Update refract for opaque models & draw
  1260. DrawRenderablesInList( opaqueNormalFOVList );
  1261. }
  1262. }
  1263. //-----------------------------------------------------------------------------
  1264. // Purpose: Actually draw the view model
  1265. // Input : drawViewModel -
  1266. //-----------------------------------------------------------------------------
  1267. #ifdef IRONSIGHT
  1268. void CViewRender::DrawViewModels( const CViewSetup &view, bool drawViewmodel, bool bDrawScopeLensMask )
  1269. #else
  1270. void CViewRender::DrawViewModels( const CViewSetup &view, bool drawViewmodel )
  1271. #endif
  1272. {
  1273. VPROF( "CViewRender::DrawViewModel" );
  1274. #ifdef PORTAL //in portal, we'd like a copy of the front buffer without the gun in it for use with the depth doubler
  1275. g_pPortalRender->UpdateDepthDoublerTexture( view );
  1276. #endif
  1277. bool bShouldDrawPlayerViewModel = ShouldDrawViewModel( drawViewmodel );
  1278. bool bShouldDrawToolViewModels = ToolsEnabled();
  1279. if ( !bShouldDrawPlayerViewModel && !bShouldDrawToolViewModels )
  1280. return;
  1281. CMatRenderContextPtr pRenderContext( materials );
  1282. MDLCACHE_CRITICAL_SECTION();
  1283. #if defined( _X360 )
  1284. pRenderContext->PushVertexShaderGPRAllocation( 32 );
  1285. #endif
  1286. PIXEVENT( pRenderContext, "DrawViewModels()" );
  1287. // Restore the matrices
  1288. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  1289. pRenderContext->PushMatrix();
  1290. CViewSetup viewModelSetup( view );
  1291. viewModelSetup.zNear = view.zNearViewmodel;
  1292. viewModelSetup.zFar = view.zFarViewmodel;
  1293. viewModelSetup.fov = view.fovViewmodel;
  1294. viewModelSetup.m_flAspectRatio = engine->GetScreenAspectRatio( view.width, view.height );
  1295. render->Push3DView( pRenderContext, viewModelSetup, 0, NULL, GetFrustum() );
  1296. #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)
  1297. //step up to a full depth clear if we're extremely close to a portal (in a portal environment)
  1298. 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
  1299. bool bUseDepthHack = !LocalPlayerIsCloseToPortal();
  1300. if( !bUseDepthHack )
  1301. pRenderContext->ClearBuffers( false, true, false );
  1302. #else
  1303. const bool bUseDepthHack = true;
  1304. #endif
  1305. // FIXME: Add code to read the current depth range
  1306. float depthmin = 0.0f;
  1307. float depthmax = 1.0f;
  1308. // HACK HACK: Munge the depth range to prevent view model from poking into walls, etc.
  1309. // Force clipped down range
  1310. if( bUseDepthHack )
  1311. pRenderContext->DepthRange( 0.0f, 0.1f );
  1312. CViewModelRenderablesList list;
  1313. ClientLeafSystem()->CollateViewModelRenderables( &list );
  1314. CViewModelRenderablesList::RenderGroups_t &opaqueList = list.m_RenderGroups[ CViewModelRenderablesList::VM_GROUP_OPAQUE ];
  1315. CViewModelRenderablesList::RenderGroups_t &translucentList = list.m_RenderGroups[ CViewModelRenderablesList::VM_GROUP_TRANSLUCENT ];
  1316. CViewModelRenderablesList listNormalFOV;
  1317. CViewModelRenderablesList::RenderGroups_t &opaqueNormalFOVList = listNormalFOV.m_RenderGroups[ CViewModelRenderablesList::VM_GROUP_OPAQUE ];
  1318. CViewModelRenderablesList::RenderGroups_t &translucentNormalFOVList = listNormalFOV.m_RenderGroups[ CViewModelRenderablesList::VM_GROUP_TRANSLUCENT ];
  1319. // Remove objects from the list that tools don't want
  1320. // Move objects that aren't actually of the view model class into a different list so we can render them with normal FOV
  1321. bool bRemove = ToolsEnabled() && ( !bShouldDrawPlayerViewModel || !bShouldDrawToolViewModels );
  1322. int nOpaque = opaqueList.Count();
  1323. for ( int i = nOpaque-1; i >= 0; --i )
  1324. {
  1325. IClientRenderable *pRenderable = opaqueList[ i ].m_pRenderable;
  1326. bool bEntity = pRenderable->GetIClientUnknown()->GetBaseEntity() ? true : false;
  1327. if ( bRemove )
  1328. {
  1329. if ( ( bEntity && !bShouldDrawPlayerViewModel ) || ( !bEntity && !bShouldDrawToolViewModels ) )
  1330. {
  1331. // Remove it
  1332. opaqueList.FastRemove( i );
  1333. continue;
  1334. }
  1335. }
  1336. if ( !dynamic_cast<C_BaseViewModel*>( pRenderable ) )
  1337. {
  1338. // Copy into the no VM FOV list
  1339. opaqueNormalFOVList.AddToTail( opaqueList[ i ] );
  1340. opaqueList.FastRemove( i );
  1341. }
  1342. #ifdef IRONSIGHT
  1343. else
  1344. {
  1345. //we want this renderable to render a special masking shape, so we need to turn on ScopeStencilMaskMode
  1346. C_BaseViewModel *pViewModel = dynamic_cast<C_BaseViewModel*>( pRenderable );
  1347. if ( pViewModel )
  1348. pViewModel->SetScopeStencilMaskMode( bDrawScopeLensMask );
  1349. }
  1350. #endif
  1351. }
  1352. int nTranslucent = translucentList.Count();
  1353. for ( int i = nTranslucent-1; i >= 0; --i )
  1354. {
  1355. IClientRenderable *pRenderable = translucentList[ i ].m_pRenderable;
  1356. bool bEntity = pRenderable->GetIClientUnknown()->GetBaseEntity() ? true : false;
  1357. if ( bRemove )
  1358. {
  1359. if ( ( bEntity && !bShouldDrawPlayerViewModel ) || ( !bEntity && !bShouldDrawToolViewModels ) )
  1360. {
  1361. // Remove it
  1362. translucentList.FastRemove( i );
  1363. continue;
  1364. }
  1365. }
  1366. if ( !dynamic_cast<C_BaseViewModel*>( pRenderable ) )
  1367. {
  1368. // Copy into the no VM FOV list
  1369. translucentNormalFOVList.AddToTail( translucentList[ i ] );
  1370. translucentList.FastRemove( i );
  1371. }
  1372. #ifdef IRONSIGHT
  1373. else
  1374. {
  1375. //we want this renderable to render a special masking shape, so we need to turn on ScopeStencilMaskMode
  1376. C_BaseViewModel *pViewModel = dynamic_cast<C_BaseViewModel*>( pRenderable );
  1377. if ( pViewModel )
  1378. pViewModel->SetScopeStencilMaskMode( bDrawScopeLensMask );
  1379. }
  1380. #endif
  1381. }
  1382. g_CascadeLightManager.BeginViewModelRendering();
  1383. // Update refract for opaque models & draw
  1384. bool bUpdatedRefractForOpaque = UpdateRefractIfNeededByList( opaqueList );
  1385. DrawRenderablesInList( opaqueList );
  1386. // Update refract for translucent models (if we didn't already update it above) & draw
  1387. if ( !bUpdatedRefractForOpaque ) // Only do this once for better perf
  1388. {
  1389. UpdateRefractIfNeededByList( translucentList );
  1390. }
  1391. DrawRenderablesInList( translucentList, STUDIO_TRANSPARENCY );
  1392. // Reset the depth range to the original values
  1393. if( bUseDepthHack )
  1394. pRenderContext->DepthRange( depthmin, depthmax );
  1395. render->PopView( pRenderContext, GetFrustum() );
  1396. // Render objects that use normal FOV
  1397. if ( !bDrawScopeLensMask && (opaqueNormalFOVList.Count() > 0 || translucentNormalFOVList.Count() > 0) )
  1398. {
  1399. viewModelSetup.fov = view.fov;
  1400. render->Push3DView( pRenderContext, viewModelSetup, 0, NULL, GetFrustum() );
  1401. // HACK HACK: Munge the depth range to prevent view model from poking into walls, etc.
  1402. // Force clipped down range
  1403. if( bUseDepthHack )
  1404. pRenderContext->DepthRange( 0.0f, 0.1f );
  1405. // Update refract for opaque models & draw
  1406. bool bUpdatedRefractForOpaque = UpdateRefractIfNeededByList( opaqueNormalFOVList );
  1407. DrawRenderablesInList( opaqueNormalFOVList );
  1408. // Update refract for translucent models (if we didn't already update it above) & draw
  1409. if ( !bUpdatedRefractForOpaque ) // Only do this once for better perf
  1410. {
  1411. UpdateRefractIfNeededByList( translucentNormalFOVList );
  1412. }
  1413. DrawRenderablesInList( translucentNormalFOVList, STUDIO_TRANSPARENCY );
  1414. // Reset the depth range to the original values
  1415. if( bUseDepthHack )
  1416. pRenderContext->DepthRange( depthmin, depthmax );
  1417. render->PopView( pRenderContext, GetFrustum() );
  1418. }
  1419. g_CascadeLightManager.EndViewModelRendering();
  1420. // Restore the matrices
  1421. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  1422. pRenderContext->PopMatrix();
  1423. #if defined( _X360 )
  1424. pRenderContext->PopVertexShaderGPRAllocation();
  1425. #endif
  1426. }
  1427. //-----------------------------------------------------------------------------
  1428. // Purpose:
  1429. // Output : Returns true on success, false on failure.
  1430. //-----------------------------------------------------------------------------
  1431. bool CViewRender::ShouldDrawBrushModels( void )
  1432. {
  1433. if ( m_pDrawBrushModels && !m_pDrawBrushModels->GetInt() )
  1434. return false;
  1435. return true;
  1436. }
  1437. //-----------------------------------------------------------------------------
  1438. // Purpose: Performs screen space effects, if any
  1439. //-----------------------------------------------------------------------------
  1440. void CViewRender::PerformScreenSpaceEffects( int x, int y, int w, int h )
  1441. {
  1442. VPROF("CViewRender::PerformScreenSpaceEffects()");
  1443. // FIXME: Screen-space effects are busted in the editor
  1444. if ( engine->IsHammerRunning() )
  1445. return;
  1446. g_pScreenSpaceEffects->RenderEffects( x, y, w, h );
  1447. }
  1448. //-----------------------------------------------------------------------------
  1449. // Purpose: Sets the screen space effect material (can't be done during rendering)
  1450. //-----------------------------------------------------------------------------
  1451. void CViewRender::SetScreenOverlayMaterial( IMaterial *pMaterial )
  1452. {
  1453. m_ScreenOverlayMaterial.Init( pMaterial );
  1454. }
  1455. //-----------------------------------------------------------------------------
  1456. //
  1457. //-----------------------------------------------------------------------------
  1458. IMaterial *CViewRender::GetScreenOverlayMaterial( )
  1459. {
  1460. return m_ScreenOverlayMaterial;
  1461. }
  1462. //-----------------------------------------------------------------------------
  1463. // Purpose: Performs screen space effects, if any
  1464. //-----------------------------------------------------------------------------
  1465. void CViewRender::PerformScreenOverlay( int x, int y, int w, int h )
  1466. {
  1467. VPROF("CViewRender::PerformScreenOverlay()");
  1468. if ( !r_drawscreenoverlay.GetBool() )
  1469. {
  1470. // As far as I can tell we don't ever draw the screen overlay on Portal2 - fading the screen in/out and blurring the screen is handled in engine_post.
  1471. // I'm disabling it because the framebuffer now lives in _rt_FullFrameFB here on PS3 (not the backbuffer), and this is not compatible with some of the code paths in PerformScreenOverlay().
  1472. if ( m_ScreenOverlayMaterial )
  1473. {
  1474. static bool s_bPrintedWarning;
  1475. if ( !s_bPrintedWarning )
  1476. {
  1477. s_bPrintedWarning = true;
  1478. Warning( "****** CViewRender::PerformScreenOverlay: Screen overlay wants to render, but it's been disabled!\n" );
  1479. Assert( false );
  1480. }
  1481. }
  1482. return;
  1483. }
  1484. if (m_ScreenOverlayMaterial)
  1485. {
  1486. if ( m_ScreenOverlayMaterial->NeedsFullFrameBufferTexture() )
  1487. {
  1488. DrawScreenEffectMaterial( m_ScreenOverlayMaterial, x, y, w, h );
  1489. }
  1490. else if ( m_ScreenOverlayMaterial->NeedsPowerOfTwoFrameBufferTexture() )
  1491. {
  1492. // First copy the FB off to the offscreen texture
  1493. UpdateRefractTexture( x, y, w, h, true );
  1494. // Now draw the entire screen using the material...
  1495. CMatRenderContextPtr pRenderContext( materials );
  1496. ITexture *pTexture = GetPowerOfTwoFrameBufferTexture( );
  1497. int sw = pTexture->GetActualWidth();
  1498. int sh = pTexture->GetActualHeight();
  1499. pRenderContext->DrawScreenSpaceRectangle( m_ScreenOverlayMaterial, x, y, w, h,
  1500. 0, 0, sw-1, sh-1, sw, sh );
  1501. }
  1502. else
  1503. {
  1504. byte color[4] = { 255, 255, 255, 255 };
  1505. render->ViewDrawFade( color, m_ScreenOverlayMaterial );
  1506. }
  1507. }
  1508. }
  1509. void CViewRender::DrawUnderwaterOverlay( void )
  1510. {
  1511. // Underwater overlay effect is disabled by default on Portal2 - as far as I can tell it's unused.
  1512. // It may need to be updated to work on PS3 (because _rt_FullFrameFB is used to hold the active framebuffer here on PS3 to avoid expensive resolves).
  1513. if ( !r_drawunderwateroverlay.GetBool() )
  1514. return;
  1515. IMaterial *pOverlayMat = m_UnderWaterOverlayMaterial;
  1516. if ( pOverlayMat )
  1517. {
  1518. CMatRenderContextPtr pRenderContext( materials );
  1519. int x, y, w, h;
  1520. pRenderContext->GetViewport( x, y, w, h );
  1521. if ( pOverlayMat->NeedsFullFrameBufferTexture() )
  1522. {
  1523. DrawScreenEffectMaterial( pOverlayMat, x, y, w, h );
  1524. }
  1525. else if ( pOverlayMat->NeedsPowerOfTwoFrameBufferTexture() )
  1526. {
  1527. // First copy the FB off to the offscreen texture
  1528. UpdateRefractTexture( x, y, w, h, true );
  1529. // Now draw the entire screen using the material...
  1530. CMatRenderContextPtr pRenderContext( materials );
  1531. ITexture *pTexture = GetPowerOfTwoFrameBufferTexture( );
  1532. int sw = pTexture->GetActualWidth();
  1533. int sh = pTexture->GetActualHeight();
  1534. pRenderContext->DrawScreenSpaceRectangle( pOverlayMat, x, y, w, h,
  1535. 0, 0, sw-1, sh-1, sw, sh );
  1536. }
  1537. else
  1538. {
  1539. pRenderContext->DrawScreenSpaceRectangle( pOverlayMat, x, y, w, h,
  1540. 0, 0, 1, 1, 1, 1 );
  1541. }
  1542. }
  1543. }
  1544. //-----------------------------------------------------------------------------
  1545. // Purpose: Returns the min/max fade distances, and distance scale
  1546. //-----------------------------------------------------------------------------
  1547. static ConVar r_fade360style( "r_fade360style", "1" );
  1548. void CViewRender::GetScreenFadeDistances( float *pMin, float *pMax, float *pScale )
  1549. {
  1550. *pMin = m_FadeData.m_flPixelMin;
  1551. *pMax = m_FadeData.m_flPixelMax;
  1552. *pScale = m_FadeData.m_flFadeDistScale;
  1553. // A complete, brutal hack, necessitated by our next-week ship date.
  1554. // On the 360, we use fade distances to deal with splitscreen.
  1555. // The tuning is such that the numbers used are correct for 720p.
  1556. // We are not doing this optimization to save on fillrate; instead we are doing it
  1557. // to save on CPU. Therefore, specifying the fades in terms of pixels is not correct.
  1558. // If we're not running @ 720p, then we will recompute a new number based on screen res ratio.
  1559. if ( IsGameConsole() || r_fade360style.GetInt() )
  1560. {
  1561. int screenWidth, screenHeight;
  1562. g_pMaterialSystem->GetBackBufferDimensions( screenWidth, screenHeight );
  1563. if ( screenHeight != 720 )
  1564. {
  1565. float flRatio = (float)screenHeight / 720.0f;
  1566. *pMin *= flRatio;
  1567. *pMax *= flRatio;
  1568. }
  1569. }
  1570. }
  1571. void CViewRender::OnScreenFadeMinSize( const CCommand &args )
  1572. {
  1573. if ( args.ArgC() < 2 )
  1574. return;
  1575. m_FadeData.m_flPixelMin = atof( args[1] ) * 1000.0f;
  1576. }
  1577. void CViewRender::OnScreenFadeMaxSize( const CCommand &args )
  1578. {
  1579. if ( args.ArgC() < 2 )
  1580. return;
  1581. m_FadeData.m_flPixelMax = atof( args[1] ) * 1000.0f;
  1582. }
  1583. //-----------------------------------------------------------------------------
  1584. // Purpose: Initialize the fade data.
  1585. //-----------------------------------------------------------------------------
  1586. void CViewRender::InitFadeData( void )
  1587. {
  1588. // What system are we running.
  1589. // L4D knocks down this convar in splitscreen mode to control the fade distances.
  1590. // We want to use the CPU level since it may be overriden for different systems NOT the "Acutal" level since that is just the convar.
  1591. int nSystemLevel = GetCPULevel();
  1592. // The +1 is because the system levels start at -1 for unknown and the fade levels start at 0 for unknown / none.
  1593. m_FadeData = g_aFadeData[nSystemLevel+1];
  1594. }
  1595. C_BaseEntity *CViewRender::GetCurrentlyDrawingEntity()
  1596. {
  1597. return m_pCurrentlyDrawingEntity;
  1598. }
  1599. void CViewRender::SetCurrentlyDrawingEntity( C_BaseEntity *pEnt )
  1600. {
  1601. m_pCurrentlyDrawingEntity = pEnt;
  1602. }
  1603. bool CViewRender::UpdateShadowDepthTexture( ITexture *pRenderTarget, ITexture *pDepthTexture, const CViewSetup &shadowViewIn, bool bRenderWorldAndObjects, bool bRenderViewModels )
  1604. {
  1605. VPROF_INCREMENT_COUNTER( "shadow depth textures rendered", 1 );
  1606. CMatRenderContextPtr pRenderContext( materials );
  1607. #if PIX_ENABLE
  1608. char szPIXEventName[128];
  1609. Q_snprintf( szPIXEventName, ARRAYSIZE( szPIXEventName ), "UpdateShadowDepthTexture (%s)", pDepthTexture ? pDepthTexture->GetName() : "null-depth-texture" );
  1610. PIXEVENT( pRenderContext, szPIXEventName );
  1611. #endif
  1612. CRefPtr<CShadowDepthView> pShadowDepthView = new CShadowDepthView( this );
  1613. pShadowDepthView->Setup( shadowViewIn, pRenderTarget, pDepthTexture, bRenderWorldAndObjects, bRenderViewModels );
  1614. AddViewToScene( pShadowDepthView );
  1615. return true;
  1616. }
  1617. #if defined(CSTRIKE15) && defined(_PS3)
  1618. //-----------------------------------------------------------------------------
  1619. // Purpose: Initialise mem area for SPU BuildWorldLists, BuildRenderables
  1620. //-----------------------------------------------------------------------------
  1621. void CViewRender::InitSPUBuildRenderingJobs( void )
  1622. {
  1623. // reset job view index
  1624. g_viewBuilder.ResetBuildViewID();
  1625. ClientLeafSystem()->PrepRenderablesListForSPU();
  1626. }
  1627. #endif
  1628. static bool IsThirdPersonOverview( void )
  1629. {
  1630. return input->CAM_IsThirdPersonOverview();
  1631. }
  1632. //-----------------------------------------------------------------------------
  1633. // Purpose: Renders world and all entities, etc.
  1634. //-----------------------------------------------------------------------------
  1635. void CViewRender::ViewDrawScene( bool bDrew3dSkybox, SkyboxVisibility_t nSkyboxVisible, const CViewSetup &view,
  1636. int nClearFlags, view_id_t viewID, bool bDrawViewModel, int baseDrawFlags, ViewCustomVisibility_t *pCustomVisibility )
  1637. {
  1638. VPROF( "CViewRender::ViewDrawScene" );
  1639. SNPROF( "CViewRender::ViewDrawScene" );
  1640. // this allows the refract texture to be updated once per *scene* on 360
  1641. // (e.g. once for a monitor scene and once for the main scene)
  1642. g_viewscene_refractUpdateFrame = gpGlobals->framecount - 1;
  1643. BEGIN_2PASS_BUILD_BLOCK
  1644. g_CascadeLightManager.PreRender();
  1645. g_pClientShadowMgr->PreRender();
  1646. END_2PASS_BLOCK
  1647. // Shadowed flashlights supported on ps_2_b and up...
  1648. if ( ( viewID == VIEW_MAIN ) && ( !view.m_bDrawWorldNormal ) )
  1649. {
  1650. g_CascadeLightManager.ComputeShadowDepthTextures( view );
  1651. // On the 360, we call this even when we don't have shadow depth textures enabled, so that
  1652. // the flashlight state gets set up properly
  1653. #if defined(_PS3)
  1654. g_pClientShadowMgr->ComputeShadowDepthTextures( view, g_viewBuilder.GetPassFlags() & PASS_BUILDLISTS_PS3 );
  1655. #else
  1656. g_pClientShadowMgr->ComputeShadowDepthTextures( view, ( g_viewBuilder.GetPassFlags() == PASS_BUILDLISTS ) );
  1657. #endif
  1658. }
  1659. m_BaseDrawFlags = baseDrawFlags;
  1660. // After cascading shadows are drawn, early out if vision is 100% obscured by smoke.
  1661. if ( m_flSmokeOverlayAmount >= 1 )
  1662. {
  1663. BEGIN_2PASS_DRAW_BLOCK
  1664. // Free shadow depth textures for use in future view
  1665. if ((viewID == VIEW_MAIN) && (!view.m_bDrawWorldNormal))
  1666. {
  1667. g_CascadeLightManager.UnlockAllShadowDepthTextures();
  1668. g_pClientShadowMgr->UnlockAllShadowDepthTextures();
  1669. }
  1670. END_2PASS_BLOCK
  1671. return;
  1672. }
  1673. SetupCurrentView( view.origin, view.angles, viewID, view.m_bDrawWorldNormal, view.m_bCullFrontFaces );
  1674. BEGIN_2PASS_BUILD_BLOCK
  1675. // Invoke pre-render methods
  1676. IGameSystem::PreRenderAllSystems();
  1677. END_2PASS_BLOCK
  1678. // Start view
  1679. unsigned int visFlags;
  1680. SetupVis( view, visFlags, pCustomVisibility );
  1681. if ( !bDrew3dSkybox )
  1682. {
  1683. if ( ( nSkyboxVisible == SKYBOX_NOT_VISIBLE ) && ( visFlags & IVRenderView::VIEW_SETUP_VIS_EX_RETURN_FLAGS_USES_RADIAL_VIS ) )
  1684. {
  1685. // This covers the case where we don't see a 3dskybox, yet radial vis is clipping
  1686. // the far plane. Need to clear to fog color in this case.
  1687. nClearFlags |= VIEW_CLEAR_COLOR;
  1688. SetClearColorToFogColor( );
  1689. }
  1690. else if ( IsX360() && ( !( nClearFlags & VIEW_CLEAR_COLOR ) ) )
  1691. {
  1692. // Make sure EDRAM color is always cleared to something on X360.
  1693. // From the XDK docs on IDirect3DDevice9::Present():
  1694. // Do not assume that the contents of extended dynamic random access memory (EDRAM) persist after calling the Present method. In
  1695. // debug builds, Direct3D clears the EDRAM to random values. After each call to Present, the color buffers and z-buffers are discarded.
  1696. nClearFlags |= VIEW_CLEAR_COLOR;
  1697. CMatRenderContextPtr pRenderContext( materials );
  1698. pRenderContext->ClearColor4ub( 0, 0, 0, 0 );
  1699. }
  1700. }
  1701. bool drawSkybox = r_skybox.GetBool();
  1702. if ( bDrew3dSkybox || ( nSkyboxVisible == SKYBOX_NOT_VISIBLE ) )
  1703. {
  1704. drawSkybox = false;
  1705. }
  1706. BEGIN_2PASS_BUILD_BLOCK
  1707. ParticleMgr()->IncrementFrameCode();
  1708. END_2PASS_BLOCK
  1709. DrawWorldAndEntities( drawSkybox, view, nClearFlags, pCustomVisibility );
  1710. // Disable fog for the rest of the stuff
  1711. DisableFog();
  1712. BEGIN_2PASS_DRAW_BLOCK
  1713. // UNDONE: Don't do this with masked brush models, they should probably be in a separate list
  1714. // render->DrawMaskEntities()
  1715. // Here are the overlays...
  1716. if ( !view.m_bDrawWorldNormal )
  1717. {
  1718. CGlowOverlay::DrawOverlays( view.m_bCacheFullSceneState );
  1719. }
  1720. // issue the pixel visibility tests
  1721. if ( IsMainView( CurrentViewID() ) && !view.m_bDrawWorldNormal )
  1722. {
  1723. PixelVisibility_EndCurrentView();
  1724. }
  1725. // Draw rain..
  1726. DrawPrecipitation();
  1727. // Draw volumetrics for shadowed flashlights
  1728. if ( r_flashlightvolumetrics.GetBool() && (viewID != VIEW_SHADOW_DEPTH_TEXTURE) && !view.m_bDrawWorldNormal )
  1729. {
  1730. g_pClientShadowMgr->DrawVolumetrics( view );
  1731. }
  1732. // Make sure sound doesn't stutter
  1733. engine->Sound_ExtraUpdate();
  1734. // Debugging info goes over the top
  1735. CDebugViewRender::Draw3DDebuggingInfo( view );
  1736. // Draw client side effects
  1737. // NOTE: These are not sorted against the rest of the frame
  1738. clienteffects->DrawEffects( gpGlobals->frametime );
  1739. END_2PASS_BLOCK
  1740. // Mark the frame as locked down for client fx additions
  1741. SetFXCreationAllowed( false );
  1742. BEGIN_2PASS_DRAW_BLOCK
  1743. // Invoke post-render methods
  1744. IGameSystem::PostRenderAllSystems();
  1745. END_2PASS_BLOCK
  1746. FinishCurrentView();
  1747. BEGIN_2PASS_DRAW_BLOCK
  1748. // Free shadow depth textures for use in future view
  1749. if ( ( viewID == VIEW_MAIN ) && ( !view.m_bDrawWorldNormal ) )
  1750. {
  1751. g_CascadeLightManager.UnlockAllShadowDepthTextures();
  1752. g_pClientShadowMgr->UnlockAllShadowDepthTextures();
  1753. }
  1754. // Set int rendering parameters back to defaults
  1755. CMatRenderContextPtr pRenderContext( materials );
  1756. pRenderContext->SetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING, 0 );
  1757. if ( view.m_bCullFrontFaces )
  1758. {
  1759. pRenderContext->FlipCulling( false );
  1760. }
  1761. END_2PASS_BLOCK
  1762. }
  1763. void CheckAndTransitionColor( float flPercent, float *pColor, float *pLerpToColor )
  1764. {
  1765. if ( pLerpToColor[0] != pColor[0] || pLerpToColor[1] != pColor[1] || pLerpToColor[2] != pColor[2] )
  1766. {
  1767. float flDestColor[3];
  1768. flDestColor[0] = pLerpToColor[0];
  1769. flDestColor[1] = pLerpToColor[1];
  1770. flDestColor[2] = pLerpToColor[2];
  1771. pColor[0] = FLerp( pColor[0], flDestColor[0], flPercent );
  1772. pColor[1] = FLerp( pColor[1], flDestColor[1], flPercent );
  1773. pColor[2] = FLerp( pColor[2], flDestColor[2], flPercent );
  1774. //Msg( "Actual(%f, %f, %f), Dest(%f, %f, %f), Percent(%f)\n", pColor[0], pColor[1], pColor[2], flDestColor[0], flDestColor[1], flDestColor[2], flPercent );
  1775. }
  1776. else
  1777. {
  1778. pColor[0] = pLerpToColor[0];
  1779. pColor[1] = pLerpToColor[1];
  1780. pColor[2] = pLerpToColor[2];
  1781. }
  1782. }
  1783. static void GetFogColorTransition( fogparams_t *pFogParams, float *pColorPrimary, float *pColorSecondary )
  1784. {
  1785. if ( !pFogParams )
  1786. return;
  1787. if ( pFogParams->lerptime >= gpGlobals->curtime )
  1788. {
  1789. float flPercent = MAX( 0, 1.0f - (( pFogParams->lerptime - gpGlobals->curtime ) / pFogParams->duration ) );
  1790. float flPrimaryColorLerp[3] = { pFogParams->colorPrimaryLerpTo.GetR(), pFogParams->colorPrimaryLerpTo.GetG(), pFogParams->colorPrimaryLerpTo.GetB() };
  1791. float flSecondaryColorLerp[3] = { pFogParams->colorSecondaryLerpTo.GetR(), pFogParams->colorSecondaryLerpTo.GetG(), pFogParams->colorSecondaryLerpTo.GetB() };
  1792. CheckAndTransitionColor( flPercent, pColorPrimary, flPrimaryColorLerp );
  1793. CheckAndTransitionColor( flPercent, pColorSecondary, flSecondaryColorLerp );
  1794. }
  1795. }
  1796. //-----------------------------------------------------------------------------
  1797. // Purpose: Returns the fog color to use in rendering the current frame.
  1798. //-----------------------------------------------------------------------------
  1799. static void GetFogColor( fogparams_t *pFogParams, float *pColor, bool ignoreOverride, bool ignoreHDRColorScale )
  1800. {
  1801. C_BasePlayer *pbp = C_BasePlayer::GetLocalPlayer();
  1802. if ( !pbp || !pFogParams )
  1803. return;
  1804. bool bFogOverride = fog_override.GetBool() && !ignoreOverride;
  1805. float HDRColorScale;
  1806. if( bFogOverride && (fog_hdrcolorscale.GetFloat() != -1.0f) )
  1807. {
  1808. HDRColorScale = fog_hdrcolorscale.GetFloat();
  1809. }
  1810. else
  1811. {
  1812. HDRColorScale = pFogParams->HDRColorScale;
  1813. }
  1814. pColor[0] = pColor[1] = pColor[2] = -1.0f;
  1815. const char *fogColorString = fog_color.GetString();
  1816. if( bFogOverride && fogColorString )
  1817. {
  1818. sscanf( fogColorString, "%f %f %f", pColor, pColor+1, pColor+2 );
  1819. }
  1820. if( (pColor[0] == -1.0f) && (pColor[1] == -1.0f) && (pColor[2] == -1.0f) ) //if not overriding fog, or if we get non-overridden fog color values
  1821. {
  1822. float flPrimaryColor[3] = { pFogParams->colorPrimary.GetR(), pFogParams->colorPrimary.GetG(), pFogParams->colorPrimary.GetB() };
  1823. float flSecondaryColor[3] = { pFogParams->colorSecondary.GetR(), pFogParams->colorSecondary.GetG(), pFogParams->colorSecondary.GetB() };
  1824. GetFogColorTransition( pFogParams, flPrimaryColor, flSecondaryColor );
  1825. if( pFogParams->blend )
  1826. {
  1827. //
  1828. // Blend between two fog colors based on viewing angle.
  1829. // The secondary fog color is at 180 degrees to the primary fog color.
  1830. //
  1831. Vector forward;
  1832. pbp->EyeVectors( &forward, NULL, NULL );
  1833. Vector vNormalized = pFogParams->dirPrimary;
  1834. VectorNormalize( vNormalized );
  1835. pFogParams->dirPrimary = vNormalized;
  1836. float flBlendFactor = 0.5 * forward.Dot( pFogParams->dirPrimary ) + 0.5;
  1837. // FIXME: convert to linear colorspace
  1838. pColor[0] = flPrimaryColor[0] * flBlendFactor + flSecondaryColor[0] * ( 1 - flBlendFactor );
  1839. pColor[1] = flPrimaryColor[1] * flBlendFactor + flSecondaryColor[1] * ( 1 - flBlendFactor );
  1840. pColor[2] = flPrimaryColor[2] * flBlendFactor + flSecondaryColor[2] * ( 1 - flBlendFactor );
  1841. }
  1842. else
  1843. {
  1844. pColor[0] = flPrimaryColor[0];
  1845. pColor[1] = flPrimaryColor[1];
  1846. pColor[2] = flPrimaryColor[2];
  1847. }
  1848. }
  1849. if ( !ignoreHDRColorScale && g_pMaterialSystemHardwareConfig->GetHDRType() != HDR_TYPE_NONE )
  1850. {
  1851. VectorScale( pColor, HDRColorScale, pColor );
  1852. }
  1853. VectorScale( pColor, 1.0f / 255.0f, pColor );
  1854. }
  1855. static float GetFogStart( fogparams_t *pFogParams, bool ignoreOverride )
  1856. {
  1857. if( !pFogParams )
  1858. return 0.0f;
  1859. if( fog_override.GetInt() && !ignoreOverride )
  1860. {
  1861. if( fog_start.GetFloat() == -1.0f )
  1862. {
  1863. return pFogParams->start;
  1864. }
  1865. else
  1866. {
  1867. return fog_start.GetFloat();
  1868. }
  1869. }
  1870. else
  1871. {
  1872. if ( pFogParams->lerptime > gpGlobals->curtime )
  1873. {
  1874. if ( pFogParams->start != pFogParams->startLerpTo )
  1875. {
  1876. if ( pFogParams->lerptime > gpGlobals->curtime )
  1877. {
  1878. float flPercent = MAX( 0, 1.0f - (( pFogParams->lerptime - gpGlobals->curtime ) / pFogParams->duration ) );
  1879. return FLerp( pFogParams->start, pFogParams->startLerpTo, flPercent );
  1880. }
  1881. else
  1882. {
  1883. if ( pFogParams->start != pFogParams->startLerpTo )
  1884. {
  1885. pFogParams->start = pFogParams->startLerpTo;
  1886. }
  1887. }
  1888. }
  1889. }
  1890. return pFogParams->start;
  1891. }
  1892. }
  1893. static float GetFogEnd( fogparams_t *pFogParams, bool ignoreOverride )
  1894. {
  1895. if( !pFogParams )
  1896. return 0.0f;
  1897. if( fog_override.GetInt() && !ignoreOverride )
  1898. {
  1899. if( fog_end.GetFloat() == -1.0f )
  1900. {
  1901. return pFogParams->end;
  1902. }
  1903. else
  1904. {
  1905. return fog_end.GetFloat();
  1906. }
  1907. }
  1908. else
  1909. {
  1910. if ( pFogParams->lerptime > gpGlobals->curtime )
  1911. {
  1912. if ( pFogParams->end != pFogParams->endLerpTo )
  1913. {
  1914. if ( pFogParams->lerptime > gpGlobals->curtime )
  1915. {
  1916. float flPercent = MAX( 0, 1.0f - (( pFogParams->lerptime - gpGlobals->curtime ) / pFogParams->duration ) );
  1917. float flEnd = pFogParams->end.Get();
  1918. float flLerpTo = pFogParams->endLerpTo.Get();
  1919. //Msg( "END = %f, LerpTo = %f, Percent = %f \n", flEnd, flLerpTo, flPercent );
  1920. return FLerp( flEnd, flLerpTo, flPercent );
  1921. }
  1922. else
  1923. {
  1924. if ( pFogParams->end != pFogParams->endLerpTo )
  1925. {
  1926. pFogParams->end = pFogParams->endLerpTo;
  1927. }
  1928. }
  1929. }
  1930. }
  1931. return pFogParams->end;
  1932. }
  1933. }
  1934. static bool GetFogEnable( fogparams_t *pFogParams, bool ignoreOverride )
  1935. {
  1936. if ( cl_leveloverview.GetInt() != 0 || input->CAM_IsThirdPersonOverview() )
  1937. return false;
  1938. // Ask the clientmode
  1939. if ( GetClientMode()->ShouldDrawFog() == false )
  1940. return false;
  1941. if( fog_override.GetInt() && !ignoreOverride )
  1942. {
  1943. if( fog_enable.GetInt() )
  1944. {
  1945. return true;
  1946. }
  1947. else
  1948. {
  1949. return false;
  1950. }
  1951. }
  1952. else
  1953. {
  1954. if( pFogParams )
  1955. return pFogParams->enable != false;
  1956. return false;
  1957. }
  1958. }
  1959. static float GetFogMaxDensity( fogparams_t *pFogParams, bool ignoreOverride )
  1960. {
  1961. if( !pFogParams )
  1962. return 1.0f;
  1963. if ( cl_leveloverview.GetInt() != 0 || input->CAM_IsThirdPersonOverview() )
  1964. return 1.0f;
  1965. // Ask the clientmode
  1966. if ( !GetClientMode()->ShouldDrawFog() )
  1967. return 1.0f;
  1968. if ( fog_override.GetInt() && !ignoreOverride )
  1969. {
  1970. if ( fog_maxdensity.GetFloat() == -1.0f )
  1971. return pFogParams->maxdensity;
  1972. else
  1973. return fog_maxdensity.GetFloat();
  1974. }
  1975. else
  1976. {
  1977. if ( pFogParams->lerptime > gpGlobals->curtime )
  1978. {
  1979. if ( pFogParams->maxdensity != pFogParams->maxdensityLerpTo )
  1980. {
  1981. if ( pFogParams->lerptime > gpGlobals->curtime )
  1982. {
  1983. float flPercent = MAX( 0, 1.0f - (( pFogParams->lerptime - gpGlobals->curtime ) / pFogParams->duration ) );
  1984. return FLerp( pFogParams->maxdensity, pFogParams->maxdensityLerpTo, flPercent );
  1985. }
  1986. else
  1987. {
  1988. if ( pFogParams->maxdensity != pFogParams->maxdensityLerpTo )
  1989. {
  1990. pFogParams->maxdensity = pFogParams->maxdensityLerpTo;
  1991. }
  1992. }
  1993. }
  1994. }
  1995. return pFogParams->maxdensity;
  1996. }
  1997. }
  1998. //-----------------------------------------------------------------------------
  1999. // Purpose: Returns the skybox fog color to use in rendering the current frame.
  2000. //-----------------------------------------------------------------------------
  2001. static void GetSkyboxFogColor( float *pColor, bool ignoreOverride, bool ignoreHDRColorScale )
  2002. {
  2003. C_BasePlayer *pbp = C_BasePlayer::GetLocalPlayer();
  2004. if( !pbp )
  2005. {
  2006. return;
  2007. }
  2008. CPlayerLocalData *local = &pbp->m_Local;
  2009. bool bFogOverride = fog_override.GetBool() && !ignoreOverride;
  2010. float HDRColorScale;
  2011. if( bFogOverride && (fog_hdrcolorscaleskybox.GetFloat() != -1.0f) )
  2012. {
  2013. HDRColorScale = fog_hdrcolorscaleskybox.GetFloat();
  2014. }
  2015. else
  2016. {
  2017. HDRColorScale = local->m_skybox3d.fog.HDRColorScale;
  2018. }
  2019. pColor[0] = pColor[1] = pColor[2] = -1.0f;
  2020. const char *fogColorString = fog_colorskybox.GetString();
  2021. if( bFogOverride && fogColorString )
  2022. {
  2023. sscanf( fogColorString, "%f %f %f", pColor, pColor+1, pColor+2 );
  2024. }
  2025. if( (pColor[0] == -1.0f) && (pColor[1] == -1.0f) && (pColor[2] == -1.0f) ) //if not overriding fog, or if we get non-overridden fog color values
  2026. {
  2027. if( local->m_skybox3d.fog.blend )
  2028. {
  2029. //
  2030. // Blend between two fog colors based on viewing angle.
  2031. // The secondary fog color is at 180 degrees to the primary fog color.
  2032. //
  2033. Vector forward;
  2034. pbp->EyeVectors( &forward, NULL, NULL );
  2035. Vector vNormalized = local->m_skybox3d.fog.dirPrimary;
  2036. VectorNormalize( vNormalized );
  2037. local->m_skybox3d.fog.dirPrimary = vNormalized;
  2038. float flBlendFactor = 0.5 * forward.Dot( local->m_skybox3d.fog.dirPrimary ) + 0.5;
  2039. // FIXME: convert to linear colorspace
  2040. pColor[0] = local->m_skybox3d.fog.colorPrimary.GetR() * flBlendFactor + local->m_skybox3d.fog.colorSecondary.GetR() * ( 1 - flBlendFactor );
  2041. pColor[1] = local->m_skybox3d.fog.colorPrimary.GetG() * flBlendFactor + local->m_skybox3d.fog.colorSecondary.GetG() * ( 1 - flBlendFactor );
  2042. pColor[2] = local->m_skybox3d.fog.colorPrimary.GetB() * flBlendFactor + local->m_skybox3d.fog.colorSecondary.GetB() * ( 1 - flBlendFactor );
  2043. }
  2044. else
  2045. {
  2046. pColor[0] = local->m_skybox3d.fog.colorPrimary.GetR();
  2047. pColor[1] = local->m_skybox3d.fog.colorPrimary.GetG();
  2048. pColor[2] = local->m_skybox3d.fog.colorPrimary.GetB();
  2049. }
  2050. }
  2051. if ( !ignoreHDRColorScale && g_pMaterialSystemHardwareConfig->GetHDRType() != HDR_TYPE_NONE )
  2052. {
  2053. VectorScale( pColor, HDRColorScale, pColor );
  2054. }
  2055. VectorScale( pColor, 1.0f / 255.0f, pColor );
  2056. }
  2057. static float GetSkyboxFogStart( bool ignoreOverride )
  2058. {
  2059. C_BasePlayer *pbp = C_BasePlayer::GetLocalPlayer();
  2060. if( !pbp )
  2061. {
  2062. return 0.0f;
  2063. }
  2064. CPlayerLocalData *local = &pbp->m_Local;
  2065. if( fog_override.GetInt() && !ignoreOverride )
  2066. {
  2067. if( fog_startskybox.GetFloat() == -1.0f )
  2068. {
  2069. return local->m_skybox3d.fog.start;
  2070. }
  2071. else
  2072. {
  2073. return fog_startskybox.GetFloat();
  2074. }
  2075. }
  2076. else
  2077. {
  2078. return local->m_skybox3d.fog.start;
  2079. }
  2080. }
  2081. static float GetSkyboxFogEnd( bool ignoreOverride )
  2082. {
  2083. C_BasePlayer *pbp = C_BasePlayer::GetLocalPlayer();
  2084. if( !pbp )
  2085. {
  2086. return 0.0f;
  2087. }
  2088. CPlayerLocalData *local = &pbp->m_Local;
  2089. if( fog_override.GetInt() && !ignoreOverride )
  2090. {
  2091. if( fog_endskybox.GetFloat() == -1.0f )
  2092. {
  2093. return local->m_skybox3d.fog.end;
  2094. }
  2095. else
  2096. {
  2097. return fog_endskybox.GetFloat();
  2098. }
  2099. }
  2100. else
  2101. {
  2102. return local->m_skybox3d.fog.end;
  2103. }
  2104. }
  2105. static float GetSkyboxFogMaxDensity( bool ignoreOverride )
  2106. {
  2107. C_BasePlayer *pbp = C_BasePlayer::GetLocalPlayer();
  2108. if ( !pbp )
  2109. return 1.0f;
  2110. CPlayerLocalData *local = &pbp->m_Local;
  2111. if ( cl_leveloverview.GetInt() != 0 || input->CAM_IsThirdPersonOverview() )
  2112. return 1.0f;
  2113. // Ask the clientmode
  2114. if ( !GetClientMode()->ShouldDrawFog() )
  2115. return 1.0f;
  2116. if ( fog_override.GetInt() && !ignoreOverride )
  2117. {
  2118. if ( fog_maxdensityskybox.GetFloat() == -1.0f )
  2119. return local->m_skybox3d.fog.maxdensity;
  2120. else
  2121. return fog_maxdensityskybox.GetFloat();
  2122. }
  2123. else
  2124. return local->m_skybox3d.fog.maxdensity;
  2125. }
  2126. void CViewRender::DisableFog( void )
  2127. {
  2128. VPROF("CViewRander::DisableFog()");
  2129. CMatRenderContextPtr pRenderContext( materials );
  2130. pRenderContext->FogMode( MATERIAL_FOG_NONE );
  2131. }
  2132. //-----------------------------------------------------------------------------
  2133. // Purpose:
  2134. //-----------------------------------------------------------------------------
  2135. void CViewRender::SetupVis( const CViewSetup& view, unsigned int &visFlags, ViewCustomVisibility_t *pCustomVisibility )
  2136. {
  2137. VPROF( "CViewRender::SetupVis" );
  2138. if ( pCustomVisibility && pCustomVisibility->m_nNumVisOrigins )
  2139. {
  2140. // Pass array or vis origins to merge
  2141. render->ViewSetupVisEx( ShouldForceNoVis(), pCustomVisibility->m_nNumVisOrigins, pCustomVisibility->m_rgVisOrigins, visFlags );
  2142. }
  2143. else
  2144. {
  2145. // Use render origin as vis origin by default
  2146. render->ViewSetupVisEx( ShouldForceNoVis(), 1, &view.origin, visFlags );
  2147. }
  2148. }
  2149. //-----------------------------------------------------------------------------
  2150. // Purpose: Renders voice feedback and other sprites attached to players
  2151. // Input : none
  2152. //-----------------------------------------------------------------------------
  2153. void CViewRender::RenderPlayerSprites()
  2154. {
  2155. GetClientVoiceMgr()->DrawHeadLabels();
  2156. }
  2157. void CViewRender::DrawLetterBoxRectangles( int nSlot, const CUtlVector< vrect_t >& vecLetterBoxRectangles )
  2158. {
  2159. CMatRenderContextPtr pRenderContext( materials );
  2160. pRenderContext->Bind( m_WhiteMaterial );
  2161. IMesh* pMesh = pRenderContext->GetDynamicMesh( true );
  2162. CMeshBuilder meshBuilder;
  2163. meshBuilder.Begin( pMesh, MATERIAL_QUADS, vecLetterBoxRectangles.Count() );
  2164. Color clr( 0, 0, 0, 255 );
  2165. float zpos = -99999;
  2166. for ( int i=0; i<vecLetterBoxRectangles.Count(); ++i )
  2167. {
  2168. const vrect_t &r = vecLetterBoxRectangles[ i ];
  2169. meshBuilder.Position3f( r.x, r.y, zpos );
  2170. meshBuilder.Color4ub( clr.r(), clr.g(), clr.b(), clr.a() );
  2171. meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
  2172. meshBuilder.AdvanceVertex();
  2173. meshBuilder.Position3f( r.x + r.width, r.y, zpos );
  2174. meshBuilder.Color4ub( clr.r(), clr.g(), clr.b(), clr.a() );
  2175. meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
  2176. meshBuilder.AdvanceVertex();
  2177. meshBuilder.Position3f( r.x + r.width, r.y + r.height, zpos );
  2178. meshBuilder.Color4ub( clr.r(), clr.g(), clr.b(), clr.a() );
  2179. meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
  2180. meshBuilder.AdvanceVertex();
  2181. meshBuilder.Position3f( r.x, r.y + r.height, zpos );
  2182. meshBuilder.Color4ub( clr.r(), clr.g(), clr.b(), clr.a() );
  2183. meshBuilder.TexCoord2f( 0, 0.0f, 0.0f );
  2184. meshBuilder.AdvanceVertex();
  2185. }
  2186. meshBuilder.End();
  2187. pMesh->Draw();
  2188. }
  2189. /*
  2190. 1, 2, 3 and 4 are the possible letter box rectangles, if any are needed
  2191. (x,y)------------------------------------
  2192. | | 2 | |
  2193. | |(view.x,view.y)----| |
  2194. | | | |
  2195. | 1 | | 4 |
  2196. | | | |
  2197. | |___________________|(vright,vbottom)
  2198. | | 3 | |
  2199. |---------------------------------------| (right, bottom)
  2200. | |
  2201. | |
  2202. | |
  2203. | |
  2204. -----------------------------------------
  2205. */
  2206. void CViewRender::GetLetterBoxRectangles( int nSlot, const CViewSetup &view, CUtlVector< vrect_t >& vecLetterBoxRectangles )
  2207. {
  2208. // This uses the full screen size, not the hud or 3d inset size
  2209. int x, y, w, h;
  2210. VGui_GetPanelBounds( nSlot, x, y, w, h );
  2211. int right = x + w;
  2212. int bottom = y + h;
  2213. vrect_t r;
  2214. int vbottom = view.y + view.height;
  2215. int vright = view.x + view.width;
  2216. // HACK: Adding in one extra pixel of slop at the border with the inset here...
  2217. // Need rect # 1?
  2218. if ( view.x != x )
  2219. {
  2220. r.x = x;
  2221. r.y = y;
  2222. r.width = view.x + 1;
  2223. r.height = h;
  2224. vecLetterBoxRectangles.AddToTail( r );
  2225. }
  2226. // Need rect # 2?
  2227. if ( view.y != y )
  2228. {
  2229. r.x = view.x;
  2230. r.y = y;
  2231. r.width = view.width;
  2232. r.height = view.y + 1;
  2233. vecLetterBoxRectangles.AddToTail( r );
  2234. }
  2235. // Need rect # 3?
  2236. if ( bottom != vbottom )
  2237. {
  2238. r.x = view.x;
  2239. r.y = vbottom - 1;
  2240. r.width = view.width;
  2241. r.height = bottom - vbottom + 1;
  2242. vecLetterBoxRectangles.AddToTail( r );
  2243. }
  2244. // Need rect # 4?
  2245. if ( right != vright )
  2246. {
  2247. r.x = vright - 1;
  2248. r.y = y;
  2249. r.width = right - vright + 1;
  2250. r.height = h;
  2251. vecLetterBoxRectangles.AddToTail( r );
  2252. }
  2253. }
  2254. //-----------------------------------------------------------------------------
  2255. // Sets up, cleans up the main 3D view
  2256. //-----------------------------------------------------------------------------
  2257. void CViewRender::SetupMain3DView( int nSlot, const CViewSetup &view, const CViewSetup &hudViewSetup, int &nClearFlags, ITexture *pRenderTarget )
  2258. {
  2259. // FIXME: I really want these fields removed from CViewSetup
  2260. // and passed in as independent flags
  2261. // Clear the color here if requested.
  2262. int nDepthStencilFlags = nClearFlags & ( VIEW_CLEAR_DEPTH | VIEW_CLEAR_STENCIL );
  2263. nClearFlags &= ~( nDepthStencilFlags ); // Clear these flags
  2264. if ( nClearFlags & VIEW_CLEAR_COLOR )
  2265. {
  2266. nClearFlags |= nDepthStencilFlags; // Add them back in if we're clearing color
  2267. }
  2268. CMatRenderContextPtr pRenderContext( materials );
  2269. // See if this view needs borders
  2270. CUtlVector< vrect_t > letterbox;
  2271. GetLetterBoxRectangles( nSlot, view, letterbox );
  2272. if ( letterbox.Count() )
  2273. {
  2274. CViewSetup letterBoxViewSetup;
  2275. letterBoxViewSetup.x = 0;
  2276. letterBoxViewSetup.y = 0;
  2277. VGui_GetTrueScreenSize( letterBoxViewSetup.width, letterBoxViewSetup.height );
  2278. render->Push2DView( pRenderContext, letterBoxViewSetup, 0, pRenderTarget, GetFrustum() );
  2279. DrawLetterBoxRectangles( nSlot, letterbox );
  2280. render->PopView( pRenderContext, GetFrustum() );
  2281. }
  2282. // If we are using HDR, we render to the HDR backbuffer
  2283. // instead of whatever was previously the render target
  2284. if( g_pMaterialSystemHardwareConfig->GetHDRType() == HDR_TYPE_FLOAT )
  2285. {
  2286. // Indicates that the render target is already HDR
  2287. if ( view.m_bHDRTarget )
  2288. {
  2289. render->Push3DView( pRenderContext, view, nClearFlags, pRenderTarget, GetFrustum() );
  2290. }
  2291. else
  2292. {
  2293. pRenderContext->SetIntRenderingParameter( INT_RENDERPARM_BACK_BUFFER_INDEX, BACK_BUFFER_INDEX_HDR );
  2294. render->Push3DView( pRenderContext, view, nClearFlags, NULL, GetFrustum() );
  2295. }
  2296. }
  2297. else
  2298. {
  2299. render->Push3DView( pRenderContext, view, nClearFlags, NULL, GetFrustum() );
  2300. }
  2301. pRenderContext.SafeRelease(); // don't want to hold for long periods in case in a locking active share thread mode
  2302. // If we didn't clear the depth here, we'll need to clear it later
  2303. nClearFlags ^= nDepthStencilFlags; // Toggle these bits
  2304. if ( nClearFlags & VIEW_CLEAR_COLOR )
  2305. {
  2306. // If we cleared the color here, we don't need to clear it later
  2307. nClearFlags &= ~( VIEW_CLEAR_COLOR | VIEW_CLEAR_FULL_TARGET );
  2308. }
  2309. }
  2310. void CViewRender::CleanupMain3DView( const CViewSetup &view )
  2311. {
  2312. // Make sure we reset from the HDR rendertarget back to the main backbuffer
  2313. CMatRenderContextPtr pRenderContext( materials );
  2314. if( g_pMaterialSystemHardwareConfig->GetHDRType() == HDR_TYPE_FLOAT )
  2315. {
  2316. pRenderContext->SetIntRenderingParameter( INT_RENDERPARM_BACK_BUFFER_INDEX, BACK_BUFFER_INDEX_DEFAULT );
  2317. }
  2318. render->PopView( pRenderContext, GetFrustum() );
  2319. pRenderContext.SafeRelease(); // don't want to hold for long periods in case in a locking active share thread mode
  2320. }
  2321. //-----------------------------------------------------------------------------
  2322. // Queues up an overlay rendering
  2323. //-----------------------------------------------------------------------------
  2324. void CViewRender::QueueOverlayRenderView( const CViewSetup &view, int nClearFlags, int whatToDraw )
  2325. {
  2326. // Can't have 2 in a single scene
  2327. Assert( !m_bDrawOverlay );
  2328. m_bDrawOverlay = true;
  2329. m_OverlayViewSetup = view;
  2330. m_OverlayClearFlags = nClearFlags;
  2331. m_OverlayDrawFlags = whatToDraw;
  2332. }
  2333. //-----------------------------------------------------------------------------
  2334. // Purpose: Force the view to freeze on the next frame for the specified time
  2335. //-----------------------------------------------------------------------------
  2336. void CViewRender::FreezeFrame( float flFreezeTime )
  2337. {
  2338. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  2339. int slot = GET_ACTIVE_SPLITSCREEN_SLOT();
  2340. if ( flFreezeTime == 0 )
  2341. {
  2342. m_FreezeParams[ slot ].m_flFreezeFrameUntil = 0;
  2343. m_FreezeParams[ slot ].m_bTakeFreezeFrame = false;
  2344. }
  2345. else
  2346. {
  2347. if ( m_FreezeParams[ slot ].m_flFreezeFrameUntil > gpGlobals->curtime )
  2348. {
  2349. m_FreezeParams[ slot ].m_flFreezeFrameUntil += flFreezeTime;
  2350. }
  2351. else
  2352. {
  2353. m_FreezeParams[ slot ].m_flFreezeFrameUntil = gpGlobals->curtime + flFreezeTime;
  2354. m_FreezeParams[ slot ].m_bTakeFreezeFrame = true;
  2355. }
  2356. }
  2357. }
  2358. void PositionHudPanels( CUtlVector< vgui::VPANEL > &list, const CViewSetup &view )
  2359. {
  2360. for ( int i = 0; i < list.Count(); ++i )
  2361. {
  2362. vgui::VPANEL root = list[ i ];
  2363. if ( root != 0 )
  2364. {
  2365. vgui::ipanel()->SetPos( root, view.x, view.y );
  2366. vgui::ipanel()->SetSize( root, view.width, view.height );
  2367. }
  2368. }
  2369. }
  2370. #ifdef PARTICLE_USAGE_DEMO
  2371. static ConVar r_particle_demo( "r_particle_demo", "0", FCVAR_CHEAT );
  2372. static CNonDrawingParticleSystem *s_pDemoSystem = NULL;
  2373. void ParticleUsageDemo( void )
  2374. {
  2375. if ( r_particle_demo.GetInt() )
  2376. {
  2377. if ( ! s_pDemoSystem )
  2378. {
  2379. s_pDemoSystem = ParticleMgr()->CreateNonDrawingEffect( "christest" );
  2380. }
  2381. // draw a bunch of bars
  2382. CParticleCollection *pSystem = s_pDemoSystem->Get();
  2383. for( int i = 0; i < pSystem->m_nActiveParticles; i++ )
  2384. {
  2385. Vector vecColor = pSystem->GetVectorAttributeValue( PARTICLE_ATTRIBUTE_TINT_RGB, i );
  2386. vecColor *= 255.0;
  2387. float flRadius = *( pSystem->GetFloatAttributePtr( PARTICLE_ATTRIBUTE_RADIUS, i ) );
  2388. CMatRenderContextPtr pRenderContext( materials );
  2389. pRenderContext->ClearColor4ub( vecColor.x, vecColor.y, vecColor.z, 255 );
  2390. pRenderContext->Viewport( 0, i * 20, flRadius, 17 );
  2391. pRenderContext->ClearBuffers( true, true );
  2392. }
  2393. }
  2394. else
  2395. {
  2396. // its off
  2397. if ( s_pDemoSystem )
  2398. {
  2399. delete s_pDemoSystem;
  2400. s_pDemoSystem = NULL;
  2401. }
  2402. }
  2403. }
  2404. #endif
  2405. //-----------------------------------------------------------------------------
  2406. // Purpose: This renders the entire 3D view and the in-game hud/viewmodel
  2407. // Input : &view -
  2408. // whatToDraw -
  2409. //-----------------------------------------------------------------------------
  2410. // This renders the entire 3D view.
  2411. extern ConVar r_drawothermodels;
  2412. void CViewRender::RenderView( const CViewSetup &view, const CViewSetup &hudViewSetup, int nClearFlags, int whatToDraw )
  2413. {
  2414. m_UnderWaterOverlayMaterial.Shutdown(); // underwater view will set
  2415. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  2416. int slot = GET_ACTIVE_SPLITSCREEN_SLOT();
  2417. m_CurrentView = view;
  2418. C_BaseAnimating::AutoAllowBoneAccess boneaccess( true, true );
  2419. VPROF( "CViewRender::RenderView" );
  2420. // Don't want CS:GO running less than SM3
  2421. // @wge: HACK FIXME - Not doing this on MacOSX for now...
  2422. if ( !IsGameConsole() && !IsOSX() && !IsOpenGL() && ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() < 95 ) )
  2423. {
  2424. // We know they were running at least 9.0 when the game started...we check the
  2425. // value in ClientDLL_Init()...so they must be messing with their DirectX settings.
  2426. static bool bFirstTime = true;
  2427. if ( bFirstTime )
  2428. {
  2429. bFirstTime = false;
  2430. Msg( "This game has a minimum requirement of Shader Model 3.0 and your video card must support cascaded shadow mapping to run properly.\n" );
  2431. }
  2432. return;
  2433. }
  2434. CMatRenderContextPtr pRenderContext( materials );
  2435. #if defined(_PS3)
  2436. pRenderContext->AntiAliasingHint( AA_HINT_MESHES );
  2437. // init SPU render job data for buildworldlists, buildrenderables
  2438. InitSPUBuildRenderingJobs();
  2439. g_viewBuilder.SetPassFlags( PASS_BUILDLISTS_PS3 | PASS_DRAWLISTS_PS3 );
  2440. #else
  2441. g_viewBuilder.Init();
  2442. g_viewBuilder.SetPassFlags( PASS_BUILDLISTS | PASS_DRAWLISTS );
  2443. // Update bounds of all renderables
  2444. ClientLeafSystem()->ComputeAllBounds();
  2445. #endif
  2446. ITexture *saveRenderTarget = pRenderContext->GetRenderTarget();
  2447. pRenderContext.SafeRelease(); // don't want to hold for long periods in case in a locking active share thread mode
  2448. if ( !m_FreezeParams[ slot ].m_bTakeFreezeFrame && m_FreezeParams[ slot ].m_flFreezeFrameUntil > gpGlobals->curtime )
  2449. {
  2450. CRefPtr<CFreezeFrameView> pFreezeFrameView = new CFreezeFrameView( this );
  2451. pFreezeFrameView->Setup( view );
  2452. AddViewToScene( pFreezeFrameView );
  2453. g_bRenderingView = true;
  2454. AllowCurrentViewAccess( true );
  2455. }
  2456. else
  2457. {
  2458. g_flFreezeFlash[ slot ] = 0.0f;
  2459. #ifdef USE_MONITORS
  2460. if ( cl_drawmonitors.GetBool() &&
  2461. ( ( whatToDraw & RENDERVIEW_SUPPRESSMONITORRENDERING ) == 0 ) )
  2462. {
  2463. DrawMonitors( view );
  2464. }
  2465. #endif
  2466. g_bRenderingView = true;
  2467. RenderPreScene( view );
  2468. // Must be first
  2469. render->SceneBegin();
  2470. g_pColorCorrectionMgr->UpdateColorCorrection();
  2471. // Send the current tonemap scalar to the material system
  2472. UpdateMaterialSystemTonemapScalar();
  2473. // clear happens here probably
  2474. SetupMain3DView( slot, view, hudViewSetup, nClearFlags, saveRenderTarget );
  2475. g_pClientShadowMgr->UpdateSplitscreenLocalPlayerShadowSkip();
  2476. bool bDrew3dSkybox = false;
  2477. SkyboxVisibility_t nSkyboxVisible = SKYBOX_NOT_VISIBLE;
  2478. // Don't bother with the skybox if we're drawing an ND buffer for the SFM
  2479. if ( !view.m_bDrawWorldNormal )
  2480. {
  2481. // if the 3d skybox world is drawn, then don't draw the normal skybox
  2482. if ( true ) // For pix event
  2483. {
  2484. #if PIX_ENABLE
  2485. {
  2486. CMatRenderContextPtr pRenderContext( materials );
  2487. PIXEVENT( pRenderContext, "Skybox Rendering" );
  2488. }
  2489. #endif
  2490. CSkyboxView *pSkyView = new CSkyboxView( this );
  2491. if ( ( bDrew3dSkybox = pSkyView->Setup( view, &nClearFlags, &nSkyboxVisible ) ) != false )
  2492. {
  2493. AddViewToScene( pSkyView );
  2494. }
  2495. SafeRelease( pSkyView );
  2496. }
  2497. }
  2498. // Force it to clear the framebuffer if they're in solid space.
  2499. if ( ( nClearFlags & VIEW_CLEAR_COLOR ) == 0 )
  2500. {
  2501. MDLCACHE_CRITICAL_SECTION();
  2502. if ( enginetrace->GetPointContents( view.origin ) == CONTENTS_SOLID )
  2503. {
  2504. nClearFlags |= VIEW_CLEAR_COLOR;
  2505. }
  2506. }
  2507. PreViewDrawScene( view );
  2508. // Render world and all entities, particles, etc.
  2509. if( !g_pIntroData )
  2510. {
  2511. MDLCACHE_CRITICAL_SECTION();
  2512. #if PIX_ENABLE
  2513. {
  2514. CMatRenderContextPtr pRenderContext( materials );
  2515. PIXEVENT( pRenderContext, "ViewDrawScene()" );
  2516. }
  2517. #endif
  2518. #if defined(_PS3)
  2519. // Entry point for 2 pass rendering on PS3, for CSTRIKE15
  2520. // pass 1 - build - kick off build world and renderable lists on SPU
  2521. // pass 2 - draw - sync build jobs and draw
  2522. // 2 passes allows the building jobs to be kicked off asap, and the rendering can then
  2523. // be performed in parallel
  2524. // This path is still undergoing testing, and does not support all rendering paths (refraction, proper reflection, etc)
  2525. // sync points and other 2 pass macros near the top of this file - wrap code to be performed in on or other pass with a begin/end macro (see examples)
  2526. if( r_PS3_2PassBuildDraw.GetInt() )
  2527. {
  2528. int numViews[2];
  2529. SNPROF("2PassBuildWRLists");
  2530. g_viewBuilder.Init();
  2531. // turn on SPU BuildWorld/Renderables jobs
  2532. g_viewBuilder.SPUBuildRWJobsOn( true );
  2533. // reset job view index
  2534. g_viewBuilder.ResetBuildViewID();
  2535. // Pass 1 - Build World and Renderables Lists
  2536. g_viewBuilder.SetPassFlags( PASS_BUILDLISTS_PS3 );
  2537. ViewDrawScene( bDrew3dSkybox, nSkyboxVisible, view, nClearFlags, VIEW_MAIN, whatToDraw & RENDERVIEW_DRAWVIEWMODEL );
  2538. numViews[0] = g_viewBuilder.GetBuildViewID();
  2539. // push all stored up buildrenderable jobs
  2540. g_viewBuilder.PushBuildRenderableJobs();
  2541. // kick off threaded audio here, this only does anything when running IsServer is true
  2542. // helps to hide any sync on buildworld/renderable jobs
  2543. engine->Sound_ServerUpdateSoundsPS3();
  2544. // reset job view index
  2545. g_viewBuilder.ResetBuildViewID();
  2546. // Pass 2 - Draw
  2547. g_viewBuilder.SetPassFlags( PASS_DRAWLISTS_PS3 );
  2548. ViewDrawScene( bDrew3dSkybox, nSkyboxVisible, view, nClearFlags, VIEW_MAIN, whatToDraw & RENDERVIEW_DRAWVIEWMODEL );
  2549. numViews[1] = g_viewBuilder.GetBuildViewID();
  2550. if( numViews[0] != numViews[1] )
  2551. {
  2552. Warning("PS3 2 pass draw error - numViews mismatch, p0:%d p1:%d\n", numViews[0], numViews[1]);
  2553. }
  2554. // turn off SPU BuildWorld/Renderables jobs
  2555. g_viewBuilder.SPUBuildRWJobsOn( false );
  2556. g_viewBuilder.Purge();
  2557. }
  2558. else
  2559. {
  2560. g_viewBuilder.Init();
  2561. g_viewBuilder.SPUBuildRWJobsOn( true );
  2562. g_viewBuilder.SetPassFlags( PASS_BUILDLISTS_PS3 | PASS_DRAWLISTS_PS3 );
  2563. ViewDrawScene( bDrew3dSkybox, nSkyboxVisible, view, nClearFlags, VIEW_MAIN, whatToDraw & RENDERVIEW_DRAWVIEWMODEL );
  2564. g_viewBuilder.SPUBuildRWJobsOn( false );
  2565. g_viewBuilder.Purge();
  2566. }
  2567. #else
  2568. g_viewBuilder.Init();
  2569. // Entry point for 2 pass rendering for CSTRIKE15
  2570. // pass 1 - build - kick off build world and renderable lists on different thread
  2571. // pass 2 - draw - sync build jobs and draw
  2572. // 2 passes allows the building jobs to be kicked off asap, and the rendering can then
  2573. // be performed in parallel
  2574. // This path is still undergoing testing, and does not support all rendering paths (refraction, proper reflection, etc)
  2575. // sync points and other 2 pass macros near the top of this file - wrap code to be performed in on or other pass with a begin/end macro (see examples)
  2576. if ( r_2PassBuildDraw.GetBool() )
  2577. {
  2578. g_viewBuilder.SetBuildWRThreaded( true );
  2579. //
  2580. // First pass - Generate build world and renderables lists
  2581. //
  2582. // reset job view index
  2583. g_viewBuilder.ResetBuildViewID();
  2584. {
  2585. g_viewBuilder.SetPassFlags( PASS_BUILDLISTS );
  2586. ViewDrawScene( bDrew3dSkybox, nSkyboxVisible, view, nClearFlags, VIEW_MAIN, whatToDraw & RENDERVIEW_DRAWVIEWMODEL );
  2587. }
  2588. g_viewBuilder.FlushBuildRenderablesListJob();
  2589. //
  2590. // Second pass - Draw
  2591. //
  2592. // reset job view index
  2593. g_viewBuilder.ResetBuildViewID();
  2594. {
  2595. g_viewBuilder.SetPassFlags( PASS_DRAWLISTS );
  2596. ViewDrawScene( bDrew3dSkybox, nSkyboxVisible, view, nClearFlags, VIEW_MAIN, whatToDraw & RENDERVIEW_DRAWVIEWMODEL );
  2597. }
  2598. g_viewBuilder.SetBuildWRThreaded( false );
  2599. }
  2600. else
  2601. {
  2602. // Single pass
  2603. g_viewBuilder.SetPassFlags( PASS_BUILDLISTS | PASS_DRAWLISTS );
  2604. g_viewBuilder.SetBuildWRThreaded( true );
  2605. ViewDrawScene( bDrew3dSkybox, nSkyboxVisible, view, nClearFlags, VIEW_MAIN, whatToDraw & RENDERVIEW_DRAWVIEWMODEL );
  2606. g_viewBuilder.SetBuildWRThreaded( false );
  2607. }
  2608. g_viewBuilder.Purge();
  2609. #endif
  2610. }
  2611. else
  2612. {
  2613. MDLCACHE_CRITICAL_SECTION();
  2614. #if PIX_ENABLE
  2615. {
  2616. CMatRenderContextPtr pRenderContext( materials );
  2617. PIXEVENT( pRenderContext, "ViewDrawScene_Intro()" );
  2618. }
  2619. #endif
  2620. ViewDrawScene_Intro( view, nClearFlags, *g_pIntroData );
  2621. }
  2622. // We can still use the 'current view' stuff set up in ViewDrawScene
  2623. AllowCurrentViewAccess( true );
  2624. PostViewDrawScene( view );
  2625. engine->DrawPortals();
  2626. DisableFog();
  2627. // Finish scene
  2628. render->SceneEnd();
  2629. // Draw lightsources if enabled
  2630. render->DrawLights();
  2631. RenderPlayerSprites();
  2632. // Image-space motion blur and depth of field
  2633. #if defined( _X360 )
  2634. {
  2635. CMatRenderContextPtr pRenderContext( materials );
  2636. pRenderContext->PushVertexShaderGPRAllocation( 16 ); //Max out pixel shader threads
  2637. pRenderContext.SafeRelease();
  2638. }
  2639. #endif
  2640. Rect_t curViewport;
  2641. if ( IsPS3() )
  2642. {
  2643. CMatRenderContextPtr pRenderContext( materials );
  2644. // On PS3, the motion blur pass reads from the backbuffer and outputs to _rt_FullFrameFB. Subsequent passes then read/write
  2645. // _rt_FullFrameFB, then engine_post reads from _rt_FullFrameFB and outputs to the backbuffer.
  2646. pRenderContext->GetViewport( curViewport.x, curViewport.y, curViewport.width, curViewport.height );
  2647. pRenderContext->SetRenderTarget( materials->FindTexture( "_rt_FullFrameFB", TEXTURE_GROUP_RENDER_TARGET ) );
  2648. pRenderContext->Viewport( curViewport.x, curViewport.y, curViewport.width, curViewport.height );
  2649. pRenderContext.SafeRelease();
  2650. }
  2651. bool bPerformedMotionBlur = false;
  2652. if ( !building_cubemaps.GetBool() )
  2653. {
  2654. if ( IsDepthOfFieldEnabled() )
  2655. {
  2656. pRenderContext.GetFrom( materials );
  2657. {
  2658. PIXEVENT( pRenderContext, "DoDepthOfField()" );
  2659. DoDepthOfField( view );
  2660. }
  2661. pRenderContext.SafeRelease();
  2662. }
  2663. // We don't want to motion blur the freeze frame. It isn't going to be moving much.
  2664. ConVarRef mat_motion_blur_enabled( "mat_motion_blur_enabled" );
  2665. if ( ( view.m_nMotionBlurMode != MOTION_BLUR_DISABLE ) && ( mat_motion_blur_enabled.GetInt() ) && !m_FreezeParams[ slot ].m_bTakeFreezeFrame )
  2666. {
  2667. pRenderContext.GetFrom( materials );
  2668. {
  2669. PIXEVENT( pRenderContext, "DoImageSpaceMotionBlur()" );
  2670. bPerformedMotionBlur = DoImageSpaceMotionBlur( view );
  2671. }
  2672. pRenderContext.SafeRelease();
  2673. }
  2674. }
  2675. if ( IsPS3() && !bPerformedMotionBlur )
  2676. {
  2677. // Ensure the final framebuffer is always copied into the backbuffer on PS3 (this is normally done by the postprocess pass, which for whatever reason didn't happen).
  2678. CMatRenderContextPtr pRenderContext( materials );
  2679. pRenderContext->PushRenderTargetAndViewport( NULL );
  2680. UpdateScreenEffectTexture( 0, view.x, view.y, view.width, view.height );
  2681. pRenderContext->PopRenderTargetAndViewport();
  2682. pRenderContext.SafeRelease();
  2683. }
  2684. #if defined( _X360 )
  2685. {
  2686. CMatRenderContextPtr pRenderContext( materials );
  2687. pRenderContext->PopVertexShaderGPRAllocation();
  2688. pRenderContext.SafeRelease();
  2689. }
  2690. #endif
  2691. RenderSmokeOverlay( true );
  2692. DrawViewModels( view, whatToDraw & RENDERVIEW_DRAWVIEWMODEL );
  2693. RenderSmokeOverlay( false );
  2694. DrawUnderwaterOverlay();
  2695. PixelVisibility_EndScene();
  2696. #if defined( _X360 )
  2697. {
  2698. CMatRenderContextPtr pRenderContext( materials );
  2699. pRenderContext->PushVertexShaderGPRAllocation( 16 ); //Max out pixel shader threads
  2700. pRenderContext.SafeRelease();
  2701. }
  2702. #endif
  2703. // Draw fade over entire screen if needed
  2704. byte color[4];
  2705. bool blend;
  2706. GetViewEffects()->GetFadeParams( &color[0], &color[1], &color[2], &color[3], &blend );
  2707. // Store off color fade params to be applied in fullscreen postprocess pass
  2708. SetViewFadeParams( color[0], color[1], color[2], color[3], blend );
  2709. // Draw an overlay to make it even harder to see inside smoke particle systems.
  2710. DrawSmokeFogOverlay();
  2711. // Overlay screen fade on entire screen
  2712. PerformScreenOverlay( view.x, view.y, view.width, view.height );
  2713. // Prevent sound stutter if going slow
  2714. engine->Sound_ExtraUpdate();
  2715. if ( g_pMaterialSystemHardwareConfig->GetHDRType() != HDR_TYPE_NONE )
  2716. {
  2717. pRenderContext.GetFrom( materials );
  2718. pRenderContext->SetToneMappingScaleLinear(Vector(1,1,1));
  2719. pRenderContext.SafeRelease();
  2720. }
  2721. if ( IsPS3() )
  2722. {
  2723. // On PS3, engine_post reads from _rt_FullFrameFB and outputs to the backbuffer.
  2724. CMatRenderContextPtr pRenderContext( materials );
  2725. pRenderContext->SetRenderTarget( NULL );
  2726. pRenderContext->Viewport( curViewport.x, curViewport.y, curViewport.width, curViewport.height );
  2727. pRenderContext.SafeRelease();
  2728. }
  2729. #ifdef IRONSIGHT
  2730. if ( r_drawothermodels.GetInt() == 1 && ApplyIronSightScopeEffect( view.x, view.y, view.width, view.height, &m_CurrentView, true ) )
  2731. {
  2732. //draw the viewmodel with a special flag that renders a special mask shape into the stencil buffer
  2733. DrawViewModels(view, whatToDraw & RENDERVIEW_DRAWVIEWMODEL, true);
  2734. //apply the finished blur effect over the screen, while masking out the scope lens
  2735. ApplyIronSightScopeEffect( view.x, view.y, view.width, view.height, &m_CurrentView, false );
  2736. }
  2737. #endif
  2738. bool bPerformedPostProcessing = false;
  2739. if ( !building_cubemaps.GetBool() && view.m_bDoBloomAndToneMapping )
  2740. {
  2741. pRenderContext.GetFrom( materials );
  2742. {
  2743. static bool bAlreadyShowedLoadTime = false;
  2744. if ( ! bAlreadyShowedLoadTime )
  2745. {
  2746. bAlreadyShowedLoadTime = true;
  2747. if ( CommandLine()->CheckParm( "-timeload" ) )
  2748. {
  2749. Warning( "time to initial render = %f\n", Plat_FloatTime() );
  2750. }
  2751. }
  2752. PIXEVENT( pRenderContext, "DoEnginePostProcessing()" );
  2753. bool bFlashlightIsOn = false;
  2754. C_BasePlayer *pLocal = C_BasePlayer::GetLocalPlayer();
  2755. if ( pLocal )
  2756. {
  2757. bFlashlightIsOn = pLocal->IsEffectActive( EF_DIMLIGHT );
  2758. }
  2759. bPerformedPostProcessing = DoEnginePostProcessing( view.x, view.y, view.width, view.height, bFlashlightIsOn );
  2760. }
  2761. pRenderContext.SafeRelease();
  2762. }
  2763. if ( IsPS3() && !bPerformedPostProcessing )
  2764. {
  2765. // Ensure the final framebuffer is always copied into the backbuffer on PS3 (this is normally done by the postprocess pass).
  2766. CMatRenderContextPtr pRenderContext( materials );
  2767. pRenderContext->PushRenderTargetAndViewport( materials->FindTexture( "_rt_FullFrameFB", TEXTURE_GROUP_RENDER_TARGET ) );
  2768. Rect_t rect;
  2769. rect.x = view.x; rect.y = view.y;
  2770. rect.width = view.width; rect.height = view.height;
  2771. pRenderContext->CopyRenderTargetToTextureEx( materials->FindTexture( "^PS3^BACKBUFFER", TEXTURE_GROUP_RENDER_TARGET ), 0, &rect, &rect );
  2772. pRenderContext->PopRenderTargetAndViewport();
  2773. pRenderContext.SafeRelease();
  2774. }
  2775. // And here are the screen-space effects
  2776. if ( IsPC() )
  2777. {
  2778. // Grab the pre-color corrected frame for editing purposes
  2779. engine->GrabPreColorCorrectedFrame( view.x, view.y, view.width, view.height );
  2780. }
  2781. PerformScreenSpaceEffects( view.x, view.y, view.width, view.height );
  2782. #if defined( _X360 )
  2783. {
  2784. CMatRenderContextPtr pRenderContext( materials );
  2785. pRenderContext->PopVertexShaderGPRAllocation();
  2786. pRenderContext.SafeRelease();
  2787. }
  2788. #endif
  2789. GetClientMode()->DoPostScreenSpaceEffects( &view );
  2790. CleanupMain3DView( view );
  2791. if ( m_FreezeParams[ slot ].m_bTakeFreezeFrame )
  2792. {
  2793. pRenderContext = materials->GetRenderContext();
  2794. if ( IsGameConsole() )
  2795. {
  2796. // 360 doesn't create the Fullscreen texture
  2797. pRenderContext->CopyRenderTargetToTextureEx( GetFullFrameFrameBufferTexture( 1 ), 0, NULL, NULL );
  2798. }
  2799. else
  2800. {
  2801. pRenderContext->CopyRenderTargetToTextureEx( GetFullscreenTexture(), 0, NULL, NULL );
  2802. }
  2803. pRenderContext.SafeRelease();
  2804. m_FreezeParams[ slot ].m_bTakeFreezeFrame = false;
  2805. }
  2806. pRenderContext = materials->GetRenderContext();
  2807. pRenderContext->SetRenderTarget( saveRenderTarget );
  2808. pRenderContext.SafeRelease();
  2809. // Draw the overlay
  2810. if ( m_bDrawOverlay )
  2811. {
  2812. // This allows us to be ok if there are nested overlay views
  2813. CViewSetup currentView = m_CurrentView;
  2814. CViewSetup tempView = m_OverlayViewSetup;
  2815. tempView.fov = ScaleFOVByWidthRatio( tempView.fov, tempView.m_flAspectRatio / ( 4.0f / 3.0f ) );
  2816. tempView.m_bDoBloomAndToneMapping = false; // FIXME: Hack to get Mark up and running
  2817. tempView.m_nMotionBlurMode = MOTION_BLUR_DISABLE; // FIXME: Hack to get Mark up and running
  2818. m_bDrawOverlay = false;
  2819. RenderView( tempView, hudViewSetup, m_OverlayClearFlags, m_OverlayDrawFlags );
  2820. m_CurrentView = currentView;
  2821. }
  2822. }
  2823. #if defined( USE_SDL )
  2824. if ( mat_viewportupscale.GetBool() && mat_viewportscale.GetFloat() < 1.0f )
  2825. {
  2826. CMatRenderContextPtr pRenderContext( materials );
  2827. ITexture *pFullFrameFB1 = materials->FindTexture( "_rt_FullFrameFB1", TEXTURE_GROUP_RENDER_TARGET );
  2828. Rect_t DownscaleRect, UpscaleRect;
  2829. DownscaleRect.x = view.x;
  2830. DownscaleRect.y = view.y;
  2831. DownscaleRect.width = view.width;
  2832. DownscaleRect.height = view.height;
  2833. UpscaleRect.x = view.m_nUnscaledX;
  2834. UpscaleRect.y = view.m_nUnscaledY;
  2835. UpscaleRect.width = view.m_nUnscaledWidth;
  2836. UpscaleRect.height = view.m_nUnscaledHeight;
  2837. pRenderContext->CopyRenderTargetToTextureEx( pFullFrameFB1, 0, &DownscaleRect, &DownscaleRect );
  2838. pRenderContext->CopyTextureToRenderTargetEx( 0, pFullFrameFB1, &DownscaleRect, &UpscaleRect );
  2839. }
  2840. #endif
  2841. // Clear a row of pixels at the edge of the viewport if it isn't at the edge of the screen
  2842. if ( VGui_IsSplitScreen() )
  2843. {
  2844. CMatRenderContextPtr pRenderContext( materials );
  2845. pRenderContext->PushRenderTargetAndViewport();
  2846. int nScreenWidth, nScreenHeight;
  2847. g_pMaterialSystem->GetBackBufferDimensions( nScreenWidth, nScreenHeight );
  2848. // NOTE: view.height is off by 1 on the PC in a release build, but debug is correct! I'm leaving this here to help track this down later.
  2849. // engine->Con_NPrintf( 25 + hh, "view( %d, %d, %d, %d ) GetBackBufferDimensions( %d, %d )\n", view.x, view.y, view.width, view.height, nScreenWidth, nScreenHeight );
  2850. if ( view.x != 0 ) // if left of viewport isn't at 0
  2851. {
  2852. pRenderContext->Viewport( view.x, view.y, 1, view.height );
  2853. pRenderContext->ClearColor3ub( 0, 0, 0 );
  2854. pRenderContext->ClearBuffers( true, false );
  2855. }
  2856. if ( ( view.x + view.width ) != nScreenWidth ) // if right of viewport isn't at edge of screen
  2857. {
  2858. pRenderContext->Viewport( view.x + view.width - 1, view.y, 1, view.height );
  2859. pRenderContext->ClearColor3ub( 0, 0, 0 );
  2860. pRenderContext->ClearBuffers( true, false );
  2861. }
  2862. if ( view.y != 0 ) // if top of viewport isn't at 0
  2863. {
  2864. pRenderContext->Viewport( view.x, view.y, view.width, 1 );
  2865. pRenderContext->ClearColor3ub( 0, 0, 0 );
  2866. pRenderContext->ClearBuffers( true, false );
  2867. }
  2868. if ( ( view.y + view.height ) != nScreenHeight ) // if bottom of viewport isn't at edge of screen
  2869. {
  2870. pRenderContext->Viewport( view.x, view.y + view.height - 1, view.width, 1 );
  2871. pRenderContext->ClearColor3ub( 0, 0, 0 );
  2872. pRenderContext->ClearBuffers( true, false );
  2873. }
  2874. pRenderContext->PopRenderTargetAndViewport();
  2875. pRenderContext->Release();
  2876. }
  2877. // Draw the 2D graphics
  2878. m_CurrentView = hudViewSetup;
  2879. pRenderContext = materials->GetRenderContext();
  2880. if( IsPS3() )
  2881. {
  2882. #if !defined( CSTRIKE15 )
  2883. extern bool ShouldDrawHudViewfinder();
  2884. // HUD viewfinder has complex material that isn't handled correctly by deferred queuing in material system, so we shouldn't attempt to
  2885. if( !ShouldDrawHudViewfinder() )
  2886. {
  2887. pRenderContext->AntiAliasingHint( AA_HINT_TEXT );
  2888. }
  2889. #else
  2890. // mdonofrio - Ensure we don't MLAA scaleform/hud rendering
  2891. pRenderContext->AntiAliasingHint( AA_HINT_TEXT );
  2892. #endif // CSTRIKE15
  2893. }
  2894. if ( true )
  2895. {
  2896. PIXEVENT( pRenderContext, "2D Client Rendering" );
  2897. render->Push2DView( pRenderContext, hudViewSetup, 0, saveRenderTarget, GetFrustum() );
  2898. Render2DEffectsPreHUD( hudViewSetup );
  2899. if ( whatToDraw & RENDERVIEW_DRAWHUD )
  2900. {
  2901. VPROF_BUDGET( "VGui_DrawHud", VPROF_BUDGETGROUP_OTHER_VGUI );
  2902. // paint the vgui screen
  2903. VGui_PreRender();
  2904. CUtlVector< vgui::VPANEL > vecHudPanels;
  2905. vecHudPanels.AddToTail( VGui_GetClientDLLRootPanel() );
  2906. // This block is suspect - why are we resizing fullscreen panels to be the size of the hudViewSetup
  2907. // which is potentially only half the screen
  2908. if ( GET_ACTIVE_SPLITSCREEN_SLOT() == 0 )
  2909. {
  2910. vecHudPanels.AddToTail( VGui_GetFullscreenRootVPANEL() );
  2911. #if defined( TOOLFRAMEWORK_VGUI_REFACTOR )
  2912. vecHudPanels.AddToTail( enginevgui->GetPanel( PANEL_GAMEUIDLL ) );
  2913. #endif
  2914. vecHudPanels.AddToTail( enginevgui->GetPanel( PANEL_CLIENTDLL_TOOLS ) );
  2915. }
  2916. PositionHudPanels( vecHudPanels, hudViewSetup );
  2917. // The crosshair, etc. needs to get at the current setup stuff
  2918. AllowCurrentViewAccess( true );
  2919. // Draw the in-game stuff based on the actual viewport being used
  2920. render->VGui_Paint( PAINT_INGAMEPANELS );
  2921. // Some hud elements want to position themselves based on the on-screen position
  2922. // of simulated actors (players, physics objects, etc). LateThink() gives them
  2923. // a chance to use the final rendering positions of those actors.
  2924. GetHud().LateThink();
  2925. AllowCurrentViewAccess( false );
  2926. VGui_PostRender();
  2927. GetClientMode()->PostRenderVGui();
  2928. #if defined( INCLUDE_SCALEFORM )
  2929. pRenderContext->SetScaleformSlotViewport( SF_SS_SLOT( slot ), hudViewSetup.x, hudViewSetup.y, hudViewSetup.width, hudViewSetup.height );
  2930. pRenderContext->AdvanceAndRenderScaleformSlot( SF_SS_SLOT( slot ) );
  2931. #endif
  2932. pRenderContext->Flush();
  2933. }
  2934. CDebugViewRender::Draw2DDebuggingInfo( hudViewSetup );
  2935. Render2DEffectsPostHUD( hudViewSetup );
  2936. g_bRenderingView = false;
  2937. // We can no longer use the 'current view' stuff set up in ViewDrawScene
  2938. AllowCurrentViewAccess( false );
  2939. if ( IsPC() )
  2940. {
  2941. CDebugViewRender::GenerateOverdrawForTesting();
  2942. }
  2943. render->PopView( pRenderContext, GetFrustum() );
  2944. }
  2945. //
  2946. // Render a fullscreen rect to wipe alpha.
  2947. // Software that is injecting into present chain
  2948. // is grabbing our buffer with alpha and is able to give
  2949. // away players positioning when players are in or behind
  2950. // smoke.
  2951. //
  2952. if ( IMaterial *pMaterialClearAlpha = materials->FindMaterial( "dev/clearalpha", TEXTURE_GROUP_OTHER, true ) )
  2953. {
  2954. pRenderContext->DrawScreenSpaceQuad( pMaterialClearAlpha );
  2955. }
  2956. pRenderContext.SafeRelease();
  2957. g_WorldListCache.Flush();
  2958. g_viewBuilder.Purge();
  2959. m_CurrentView = view;
  2960. #ifdef PARTICLE_USAGE_DEMO
  2961. ParticleUsageDemo();
  2962. #endif
  2963. }
  2964. //-----------------------------------------------------------------------------
  2965. // Purpose: Renders extra 2D effects in derived classes while the 2D view is on the stack
  2966. //-----------------------------------------------------------------------------
  2967. void CViewRender::Render2DEffectsPreHUD( const CViewSetup &view )
  2968. {
  2969. }
  2970. //-----------------------------------------------------------------------------
  2971. // Purpose: Renders extra 2D effects in derived classes while the 2D view is on the stack
  2972. //-----------------------------------------------------------------------------
  2973. void CViewRender::Render2DEffectsPostHUD( const CViewSetup &view )
  2974. {
  2975. }
  2976. //-----------------------------------------------------------------------------
  2977. //
  2978. // NOTE: Below here is all of the stuff that needs to be done for water rendering
  2979. //
  2980. //-----------------------------------------------------------------------------
  2981. //-----------------------------------------------------------------------------
  2982. // Determines what kind of water we're going to use
  2983. //-----------------------------------------------------------------------------
  2984. void CViewRender::DetermineWaterRenderInfo( const VisibleFogVolumeInfo_t &fogVolumeInfo, WaterRenderInfo_t &info )
  2985. {
  2986. // By default, assume cheap water (even if there's no water in the scene!)
  2987. info.m_bCheapWater = true;
  2988. info.m_bRefract = false;
  2989. info.m_bReflect = false;
  2990. info.m_bReflectEntities = false;
  2991. info.m_bReflectOnlyMarkedEntities = false;
  2992. info.m_bDrawWaterSurface = false;
  2993. info.m_bOpaqueWater = true;
  2994. info.m_bPseudoTranslucentWater = false;
  2995. info.m_bReflect2DSkybox = false;
  2996. IMaterial *pWaterMaterial = fogVolumeInfo.m_pFogVolumeMaterial;
  2997. if (( fogVolumeInfo.m_nVisibleFogVolume == -1 ) || !pWaterMaterial )
  2998. return;
  2999. // Use cheap water if mat_drawwater is set
  3000. info.m_bDrawWaterSurface = mat_drawwater.GetBool();
  3001. if ( !info.m_bDrawWaterSurface )
  3002. {
  3003. info.m_bOpaqueWater = false;
  3004. return;
  3005. }
  3006. #ifdef _GAMECONSOLE
  3007. bool bForceExpensive = false;
  3008. #else
  3009. bool bForceExpensive = r_waterforceexpensive.GetBool();
  3010. #endif
  3011. bool bForceReflectEntities = r_waterforcereflectentities.GetBool();
  3012. bool bForceCheap = false;
  3013. #ifdef PORTAL
  3014. switch( g_pPortalRender->ShouldForceCheaperWaterLevel() )
  3015. {
  3016. case 0: //force cheap water
  3017. info.m_bCheapWater = true;
  3018. bForceCheap = true;
  3019. return;
  3020. case 1: //downgrade level to "simple reflection"
  3021. bForceExpensive = false;
  3022. case 2: //downgrade level to "reflect world"
  3023. bForceReflectEntities = false;
  3024. default:
  3025. break;
  3026. };
  3027. #endif
  3028. // Determine if the water surface is opaque or not
  3029. info.m_bOpaqueWater = !pWaterMaterial->IsTranslucent();
  3030. // The material can override the default settings though
  3031. IMaterialVar *pForceCheapVar = pWaterMaterial->FindVar( "$forcecheap", NULL, false );
  3032. IMaterialVar *pForceExpensiveVar = pWaterMaterial->FindVar( "$forceexpensive", NULL, false );
  3033. if ( !bForceCheap && pForceCheapVar && pForceCheapVar->IsDefined() )
  3034. {
  3035. bForceCheap = ( pForceCheapVar->GetIntValueFast() != 0 );
  3036. }
  3037. if ( bForceCheap )
  3038. {
  3039. bForceExpensive = false;
  3040. }
  3041. if ( !bForceCheap && pForceExpensiveVar && pForceExpensiveVar->IsDefined() )
  3042. {
  3043. bForceExpensive = bForceExpensive || ( pForceExpensiveVar->GetIntValueFast() != 0 );
  3044. }
  3045. bool bDebugCheapWater = r_debugcheapwater.GetBool();
  3046. if( bDebugCheapWater )
  3047. {
  3048. Msg( "Water material: %s dist to water: %f\nforcecheap: %s forceexpensive: %s\n",
  3049. pWaterMaterial->GetName(), fogVolumeInfo.m_flDistanceToWater,
  3050. bForceCheap ? "true" : "false", bForceExpensive ? "true" : "false" );
  3051. }
  3052. // Unless expensive water is active, reflections are off.
  3053. bool bLocalReflection;
  3054. #ifdef _GAMECONSOLE
  3055. if( !r_WaterDrawReflection.GetBool() )
  3056. #else
  3057. if( !bForceExpensive || !r_WaterDrawReflection.GetBool() )
  3058. #endif
  3059. {
  3060. bLocalReflection = false;
  3061. }
  3062. else
  3063. {
  3064. IMaterialVar *pReflectTextureVar = pWaterMaterial->FindVar( "$reflecttexture", NULL, false );
  3065. bLocalReflection = pReflectTextureVar && (pReflectTextureVar->GetType() == MATERIAL_VAR_TYPE_TEXTURE);
  3066. }
  3067. // Brian says FIXME: I disabled cheap water LOD when local specular is specified.
  3068. // There are very few places that appear to actually
  3069. // take advantage of it (places where water is in the PVS, but outside of LOD range).
  3070. // It was 2 hours before code lock, and I had the choice of either doubling fill-rate everywhere
  3071. // by making cheap water lod actually work (the water LOD wasn't actually rendering!!!)
  3072. // or to just always render the reflection + refraction if there's a local specular specified.
  3073. // Note that water LOD *does* work with refract-only water
  3074. // Gary says: I'm reverting this change so that water LOD works on dx9 for ep2.
  3075. // Check if the water is out of the cheap water LOD range; if so, use cheap water
  3076. #ifdef _GAMECONSOLE
  3077. if ( !bForceExpensive && ( bForceCheap || ( fogVolumeInfo.m_flDistanceToWater >= m_flCheapWaterEndDistance ) ) )
  3078. {
  3079. return;
  3080. }
  3081. #else
  3082. if ( ( (fogVolumeInfo.m_flDistanceToWater >= m_flCheapWaterEndDistance) && !bLocalReflection ) || bForceCheap )
  3083. return;
  3084. #endif
  3085. // Get the material that is for the water surface that is visible and check to see
  3086. // what render targets need to be rendered, if any.
  3087. if ( !r_WaterDrawRefraction.GetBool() )
  3088. {
  3089. info.m_bRefract = false;
  3090. }
  3091. else
  3092. {
  3093. IMaterialVar *pRefractTextureVar = pWaterMaterial->FindVar( "$refracttexture", NULL, false );
  3094. info.m_bRefract = pRefractTextureVar && (pRefractTextureVar->GetType() == MATERIAL_VAR_TYPE_TEXTURE);
  3095. // Refractive water can be seen through
  3096. if ( info.m_bRefract )
  3097. {
  3098. info.m_bOpaqueWater = false;
  3099. }
  3100. }
  3101. if ( !info.m_bRefract )
  3102. {
  3103. info.m_bPseudoTranslucentWater = pWaterMaterial->GetMaterialVarFlag( MATERIAL_VAR_PSEUDO_TRANSLUCENT );
  3104. if ( info.m_bPseudoTranslucentWater )
  3105. {
  3106. info.m_bOpaqueWater = false;
  3107. }
  3108. }
  3109. info.m_bReflect = bLocalReflection;
  3110. if ( info.m_bReflect )
  3111. {
  3112. if( bForceReflectEntities )
  3113. {
  3114. info.m_bReflectEntities = true;
  3115. }
  3116. else
  3117. {
  3118. IMaterialVar *pReflectEntitiesVar = pWaterMaterial->FindVar( "$reflectentities", NULL, false );
  3119. info.m_bReflectEntities = pReflectEntitiesVar && (pReflectEntitiesVar->GetIntValueFast() != 0);
  3120. // -- PORTAL 2 console perf hack --
  3121. //
  3122. // Force this check on consoles even if the VMT says $reflectentities / $forceexpensive / etc.
  3123. // Unless you explicitly put "$reflectonlymarkedentities 0" in the VMT, you're going to get this feature...
  3124. // This may be somewhat confusing but it seems like the most straight-forward way to avoid perf regressions due to people
  3125. // making water VMTs naively without considering console performance.
  3126. if ( !info.m_bReflectEntities || IsGameConsole() )
  3127. {
  3128. bool bFound = false;
  3129. IMaterialVar *pReflectOnlyMarkedEntitiesVar = pWaterMaterial->FindVar( "$reflectonlymarkedentities", &bFound, false );
  3130. info.m_bReflectOnlyMarkedEntities = IsGameConsole(); // default to using fast reflections on consoles, not on PC
  3131. if ( pReflectOnlyMarkedEntitiesVar && bFound )
  3132. {
  3133. info.m_bReflectOnlyMarkedEntities = ( pReflectOnlyMarkedEntitiesVar->GetIntValueFast() != 0 );
  3134. }
  3135. if ( IsGameConsole() && info.m_bReflectOnlyMarkedEntities )
  3136. {
  3137. info.m_bReflectEntities = false;
  3138. }
  3139. }
  3140. }
  3141. IMaterialVar *pReflect2DSkybox = pWaterMaterial->FindVar( "$reflect2dskybox", NULL, false );
  3142. info.m_bReflect2DSkybox = pReflect2DSkybox && ( pReflect2DSkybox->GetIntValueFast() != 0 );
  3143. }
  3144. info.m_bCheapWater = !info.m_bReflect && !info.m_bRefract;
  3145. if( bDebugCheapWater )
  3146. {
  3147. Warning( "refract: %s reflect: %s\n", info.m_bRefract ? "true" : "false", info.m_bReflect ? "true" : "false" );
  3148. }
  3149. }
  3150. //-----------------------------------------------------------------------------
  3151. // Enables/disables water depth feathering, which requires the scene's depth.
  3152. //-----------------------------------------------------------------------------
  3153. void CViewRender::EnableWaterDepthFeathing( IMaterial *pWaterMaterial, bool bEnable )
  3154. {
  3155. if ( pWaterMaterial )
  3156. {
  3157. bool bFound = false;
  3158. IMaterialVar *pDepthFeather = pWaterMaterial->FindVar( "$depth_feather", &bFound, false );
  3159. if ( ( pDepthFeather ) && ( bFound ) )
  3160. {
  3161. pDepthFeather->SetIntValue( bEnable );
  3162. }
  3163. }
  3164. }
  3165. //-----------------------------------------------------------------------------
  3166. // Draws the world and all entities
  3167. //-----------------------------------------------------------------------------
  3168. void CViewRender::DrawWorldAndEntities( bool bDrawSkybox, const CViewSetup &viewIn, int nClearFlags, ViewCustomVisibility_t *pCustomVisibility )
  3169. {
  3170. MDLCACHE_CRITICAL_SECTION();
  3171. VisibleFogVolumeInfo_t fogVolumeInfo;
  3172. #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
  3173. if( g_pPortalRender->GetViewRecursionLevel() == 0 )
  3174. {
  3175. render->GetVisibleFogVolume( viewIn.origin, NULL, &fogVolumeInfo );
  3176. }
  3177. else
  3178. {
  3179. render->GetVisibleFogVolume( g_pPortalRender->GetExitPortalFogOrigin(), &pCustomVisibility->m_VisData, &fogVolumeInfo );
  3180. }
  3181. #else
  3182. render->GetVisibleFogVolume( viewIn.origin, NULL, &fogVolumeInfo );
  3183. #endif
  3184. WaterRenderInfo_t info;
  3185. DetermineWaterRenderInfo( fogVolumeInfo, info );
  3186. if ( info.m_bCheapWater )
  3187. {
  3188. // rg - This code path will probably going away soon, but for now I'm going to fix it so the water looks reasonable on PS3/X360.
  3189. EnableWaterDepthFeathing( fogVolumeInfo.m_pFogVolumeMaterial, true );
  3190. cplane_t glassReflectionPlane;
  3191. if ( IsReflectiveGlassInView( viewIn, glassReflectionPlane ) )
  3192. {
  3193. CRefPtr<CReflectiveGlassView> pGlassReflectionView = new CReflectiveGlassView( this );
  3194. pGlassReflectionView->Setup( viewIn, VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR, bDrawSkybox, fogVolumeInfo, info, glassReflectionPlane );
  3195. AddViewToScene( pGlassReflectionView );
  3196. CRefPtr<CRefractiveGlassView> pGlassRefractionView = new CRefractiveGlassView( this );
  3197. pGlassRefractionView->Setup( viewIn, VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR, bDrawSkybox, fogVolumeInfo, info, glassReflectionPlane );
  3198. AddViewToScene( pGlassRefractionView );
  3199. }
  3200. CRefPtr<CSimpleWorldView> pNoWaterView = new CSimpleWorldView( this );
  3201. pNoWaterView->Setup( viewIn, nClearFlags, bDrawSkybox, fogVolumeInfo, info, pCustomVisibility );
  3202. AddViewToScene( pNoWaterView );
  3203. EnableWaterDepthFeathing( fogVolumeInfo.m_pFogVolumeMaterial, false );
  3204. return;
  3205. }
  3206. Assert( !pCustomVisibility );
  3207. // Blat out the visible fog leaf if we're not going to use it
  3208. if ( !r_ForceWaterLeaf.GetBool() )
  3209. {
  3210. fogVolumeInfo.m_nVisibleFogVolumeLeaf = -1;
  3211. }
  3212. EnableWaterDepthFeathing( fogVolumeInfo.m_pFogVolumeMaterial, true );
  3213. // We can see water of some sort
  3214. if ( !fogVolumeInfo.m_bEyeInFogVolume )
  3215. {
  3216. CRefPtr<CAboveWaterView> pAboveWaterView = new CAboveWaterView( this );
  3217. pAboveWaterView->Setup( viewIn, bDrawSkybox, fogVolumeInfo, info );
  3218. AddViewToScene( pAboveWaterView );
  3219. }
  3220. else
  3221. {
  3222. CRefPtr<CUnderWaterView> pUnderWaterView = new CUnderWaterView( this );
  3223. pUnderWaterView->Setup( viewIn, bDrawSkybox, fogVolumeInfo, info );
  3224. AddViewToScene( pUnderWaterView );
  3225. }
  3226. EnableWaterDepthFeathing( fogVolumeInfo.m_pFogVolumeMaterial, false );
  3227. }
  3228. //-----------------------------------------------------------------------------
  3229. // Pushes a water render target
  3230. //-----------------------------------------------------------------------------
  3231. static Vector s_vSavedLinearLightMapScale(-1,-1,-1); // x<0 = no saved scale
  3232. static void SetLightmapScaleForWater(void)
  3233. {
  3234. if (g_pMaterialSystemHardwareConfig->GetHDRType()==HDR_TYPE_INTEGER)
  3235. {
  3236. CMatRenderContextPtr pRenderContext( materials );
  3237. s_vSavedLinearLightMapScale=pRenderContext->GetToneMappingScaleLinear();
  3238. Vector t25=s_vSavedLinearLightMapScale;
  3239. t25*=0.25;
  3240. pRenderContext->SetToneMappingScaleLinear(t25);
  3241. }
  3242. }
  3243. //-----------------------------------------------------------------------------
  3244. // Returns true if the view plane intersects the water
  3245. //-----------------------------------------------------------------------------
  3246. bool DoesViewPlaneIntersectWater( float waterZ, int leafWaterDataID )
  3247. {
  3248. if ( leafWaterDataID == -1 )
  3249. return false;
  3250. #ifdef PORTAL //when rendering portal views point/plane intersections just don't cut it.
  3251. if( g_pPortalRender->GetViewRecursionLevel() != 0 )
  3252. return g_pPortalRender->DoesExitPortalViewIntersectWaterPlane( waterZ, leafWaterDataID );
  3253. #endif
  3254. CMatRenderContextPtr pRenderContext( materials );
  3255. VMatrix viewMatrix, projectionMatrix, viewProjectionMatrix, inverseViewProjectionMatrix;
  3256. pRenderContext->GetMatrix( MATERIAL_VIEW, &viewMatrix );
  3257. pRenderContext->GetMatrix( MATERIAL_PROJECTION, &projectionMatrix );
  3258. MatrixMultiply( projectionMatrix, viewMatrix, viewProjectionMatrix );
  3259. MatrixInverseGeneral( viewProjectionMatrix, inverseViewProjectionMatrix );
  3260. Vector mins, maxs;
  3261. ClearBounds( mins, maxs );
  3262. Vector testPoint[4];
  3263. testPoint[0].Init( -1.0f, -1.0f, 0.0f );
  3264. testPoint[1].Init( -1.0f, 1.0f, 0.0f );
  3265. testPoint[2].Init( 1.0f, -1.0f, 0.0f );
  3266. testPoint[3].Init( 1.0f, 1.0f, 0.0f );
  3267. int i;
  3268. bool bAbove = false;
  3269. bool bBelow = false;
  3270. float fudge = 7.0f;
  3271. for( i = 0; i < 4; i++ )
  3272. {
  3273. Vector worldPos;
  3274. Vector3DMultiplyPositionProjective( inverseViewProjectionMatrix, testPoint[i], worldPos );
  3275. AddPointToBounds( worldPos, mins, maxs );
  3276. // Warning( "viewplanez: %f waterZ: %f\n", worldPos.z, waterZ );
  3277. if( worldPos.z + fudge > waterZ )
  3278. {
  3279. bAbove = true;
  3280. }
  3281. if( worldPos.z - fudge < waterZ )
  3282. {
  3283. bBelow = true;
  3284. }
  3285. }
  3286. // early out if the near plane doesn't cross the z plane of the water.
  3287. if( !( bAbove && bBelow ) )
  3288. return false;
  3289. Vector vecFudge( fudge, fudge, fudge );
  3290. mins -= vecFudge;
  3291. maxs += vecFudge;
  3292. // the near plane does cross the z value for the visible water volume. Call into
  3293. // the engine to find out if the near plane intersects the water volume.
  3294. return render->DoesBoxIntersectWaterVolume( mins, maxs, leafWaterDataID );
  3295. }
  3296. #ifdef PORTAL
  3297. //-----------------------------------------------------------------------------
  3298. // Purpose: Draw the scene during another draw scene call. We must draw our portals
  3299. // after opaques but before translucents, so this ViewDrawScene resets the view
  3300. // and doesn't flag the rendering as ended when it ends.
  3301. // Input : bDrawSkybox - do we draw the skybox
  3302. // &view - the camera view to render from
  3303. // nClearFlags - how to clear the buffer
  3304. //-----------------------------------------------------------------------------
  3305. void CViewRender::ViewDrawScene_PortalStencil( const CViewSetup &viewIn, ViewCustomVisibility_t *pCustomVisibility )
  3306. {
  3307. VPROF_BUDGET( "CViewRender::ViewDrawScene_PortalStencil", "ViewDrawScene_PortalStencil" );
  3308. CViewSetup view( viewIn );
  3309. // Record old view stats
  3310. Vector vecOldOrigin = CurrentViewOrigin();
  3311. QAngle vecOldAngles = CurrentViewAngles();
  3312. int iCurrentViewID = g_CurrentViewID;
  3313. #if defined( DBGFLAG_ASSERT )
  3314. int iRecursionLevel = g_pPortalRender->GetViewRecursionLevel();
  3315. Assert( iRecursionLevel > 0 );
  3316. #endif
  3317. bool bDrew3dSkybox = false;
  3318. SkyboxVisibility_t nSkyboxVisible = SKYBOX_NOT_VISIBLE;
  3319. int iClearFlags = 0;
  3320. Draw3dSkyboxworld_Portal( view, iClearFlags, bDrew3dSkybox, nSkyboxVisible );
  3321. bool drawSkybox = r_skybox.GetBool();
  3322. if ( bDrew3dSkybox || ( nSkyboxVisible == SKYBOX_NOT_VISIBLE ) )
  3323. {
  3324. drawSkybox = false;
  3325. }
  3326. //generate unique view ID's for each stencil view
  3327. view_id_t iNewViewID = (view_id_t)g_pPortalRender->GetCurrentViewId();
  3328. SetupCurrentView( view.origin, view.angles, (view_id_t)iNewViewID );
  3329. // update vis data
  3330. unsigned int visFlags;
  3331. SetupVis( view, visFlags, pCustomVisibility );
  3332. VisibleFogVolumeInfo_t fogInfo;
  3333. if( g_pPortalRender->GetViewRecursionLevel() == 0 )
  3334. {
  3335. render->GetVisibleFogVolume( view.origin, NULL, &fogInfo );
  3336. }
  3337. else
  3338. {
  3339. render->GetVisibleFogVolume( g_pPortalRender->GetExitPortalFogOrigin(), &pCustomVisibility->m_VisData, &fogInfo );
  3340. }
  3341. WaterRenderInfo_t waterInfo;
  3342. DetermineWaterRenderInfo( fogInfo, waterInfo );
  3343. if ( waterInfo.m_bCheapWater )
  3344. {
  3345. // Only bother to enable depth feathering with water seen through up to a single portal when cheap_water is active.
  3346. if ( g_pPortalRender->GetViewRecursionLevel() <= 1)
  3347. {
  3348. EnableWaterDepthFeathing( fogInfo.m_pFogVolumeMaterial, true );
  3349. }
  3350. cplane_t glassReflectionPlane;
  3351. if ( IsReflectiveGlassInView( viewIn, glassReflectionPlane ) )
  3352. {
  3353. CRefPtr<CReflectiveGlassView> pGlassReflectionView = new CReflectiveGlassView( this );
  3354. pGlassReflectionView->Setup( viewIn, VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR | VIEW_CLEAR_OBEY_STENCIL, drawSkybox, fogInfo, waterInfo, glassReflectionPlane );
  3355. AddViewToScene( pGlassReflectionView );
  3356. CRefPtr<CRefractiveGlassView> pGlassRefractionView = new CRefractiveGlassView( this );
  3357. pGlassRefractionView->Setup( viewIn, VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR | VIEW_CLEAR_OBEY_STENCIL, drawSkybox, fogInfo, waterInfo, glassReflectionPlane );
  3358. AddViewToScene( pGlassRefractionView );
  3359. }
  3360. CSimpleWorldView *pClientView = new CSimpleWorldView( this );
  3361. pClientView->Setup( view, VIEW_CLEAR_OBEY_STENCIL, drawSkybox, fogInfo, waterInfo, pCustomVisibility );
  3362. AddViewToScene( pClientView );
  3363. SafeRelease( pClientView );
  3364. EnableWaterDepthFeathing( fogInfo.m_pFogVolumeMaterial, false );
  3365. }
  3366. else
  3367. {
  3368. EnableWaterDepthFeathing( fogInfo.m_pFogVolumeMaterial, true );
  3369. // We can see water of some sort
  3370. if ( !fogInfo.m_bEyeInFogVolume )
  3371. {
  3372. CRefPtr<CAboveWaterView> pAboveWaterView = new CAboveWaterView( this );
  3373. pAboveWaterView->Setup( viewIn, drawSkybox, fogInfo, waterInfo, pCustomVisibility );
  3374. AddViewToScene( pAboveWaterView );
  3375. }
  3376. else
  3377. {
  3378. CRefPtr<CUnderWaterView> pUnderWaterView = new CUnderWaterView( this );
  3379. pUnderWaterView->Setup( viewIn, drawSkybox, fogInfo, waterInfo, pCustomVisibility );
  3380. AddViewToScene( pUnderWaterView );
  3381. }
  3382. EnableWaterDepthFeathing( fogInfo.m_pFogVolumeMaterial, false );
  3383. }
  3384. // Disable fog for the rest of the stuff
  3385. DisableFog();
  3386. CGlowOverlay::DrawOverlays( view.m_bCacheFullSceneState );
  3387. // Draw rain..
  3388. DrawPrecipitation();
  3389. //prerender version only
  3390. // issue the pixel visibility tests
  3391. PixelVisibility_EndCurrentView();
  3392. // Make sure sound doesn't stutter
  3393. engine->Sound_ExtraUpdate();
  3394. // Debugging info goes over the top
  3395. CDebugViewRender::Draw3DDebuggingInfo( view );
  3396. // Return to the previous view
  3397. SetupCurrentView( vecOldOrigin, vecOldAngles, (view_id_t)iCurrentViewID );
  3398. g_CurrentViewID = iCurrentViewID; //just in case the cast to view_id_t screwed up the id #
  3399. }
  3400. void CViewRender::Draw3dSkyboxworld_Portal( const CViewSetup &view, int &nClearFlags, bool &bDrew3dSkybox, SkyboxVisibility_t &nSkyboxVisible, ITexture *pRenderTarget )
  3401. {
  3402. CRefPtr<CPortalSkyboxView> pSkyView = new CPortalSkyboxView( this );
  3403. if ( ( bDrew3dSkybox = pSkyView->Setup( view, &nClearFlags, &nSkyboxVisible, pRenderTarget ) ) == true )
  3404. {
  3405. AddViewToScene( pSkyView );
  3406. }
  3407. }
  3408. #endif //PORTAL
  3409. #ifdef PORTAL2
  3410. void CViewRender::ViewDrawPhoto( ITexture *pRenderTarget, C_BaseEntity *pTargetEntity )
  3411. {
  3412. CRefPtr<CAperturePhotoView> pPhotoView = new CAperturePhotoView( this );
  3413. int nClearFlags = VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH | VIEW_CLEAR_STENCIL;
  3414. SkyboxVisibility_t nSkyboxVisible = SKYBOX_NOT_VISIBLE;
  3415. CMatRenderContextPtr pRenderContext( materials );
  3416. // pRenderContext->SetStencilEnable( false ); // FIXME: JDW
  3417. //bool bIsDormant = pTargetEntity->IsDormant();
  3418. //pTargetEntity->m_bDormant = false;
  3419. //IClientRenderable *pEntRenderable = pTargetEntity->GetClientRenderable();
  3420. bool bNoDraw = pTargetEntity->IsEffectActive( EF_NODRAW );
  3421. if( bNoDraw )
  3422. {
  3423. pTargetEntity->RemoveEffects( EF_NODRAW );
  3424. }
  3425. bool bHandle = pTargetEntity->GetRenderHandle() == INVALID_CLIENT_RENDER_HANDLE;
  3426. if( bHandle )
  3427. {
  3428. ClientLeafSystem()->AddRenderable( pTargetEntity, false, RENDERABLE_IS_OPAQUE, RENDERABLE_MODEL_UNKNOWN_TYPE );
  3429. ClientLeafSystem()->RenderableChanged( pTargetEntity->m_hRender );
  3430. ClientLeafSystem()->PreRender();
  3431. }
  3432. //bool bShouldDraw = pEntRenderable->ShouldDraw();
  3433. //bool bIsVisible = pTargetEntity->IsVisible();
  3434. Assert( pTargetEntity->ShouldDraw() );
  3435. CViewSetup photoview = m_CurrentView;
  3436. photoview.width = pRenderTarget->GetActualWidth();
  3437. photoview.height = pRenderTarget->GetActualHeight();
  3438. photoview.x = 0;
  3439. photoview.y = 0;
  3440. //photoview.origin = pCameraEnt->GetAbsOrigin();
  3441. //photoview.angles = pCameraEnt->GetAbsAngles();
  3442. //photoview.fov = pCameraEnt->GetFOV();
  3443. photoview.m_bOrtho = false;
  3444. //photoview.m_flAspectRatio = 0.0f;
  3445. //(*this) = photoview;
  3446. SetupCurrentView( photoview.origin, photoview.angles, VIEW_MONITOR );
  3447. Frustum frustum;
  3448. render->Push3DView( pRenderContext, photoview, VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR, pRenderTarget, (VPlane *)frustum );
  3449. //HACKHACK: need to setup a proper view
  3450. if( pPhotoView->Setup( pTargetEntity, photoview, &nClearFlags, &nSkyboxVisible, pRenderTarget ) == true )
  3451. {
  3452. AddViewToScene( pPhotoView );
  3453. }
  3454. render->PopView( pRenderContext, frustum );
  3455. //pTargetEntity->m_bDormant = bIsDormant;
  3456. if( bHandle )
  3457. {
  3458. ClientLeafSystem()->RemoveRenderable( pTargetEntity->GetRenderHandle() );
  3459. }
  3460. if( bNoDraw )
  3461. {
  3462. pTargetEntity->AddEffects( EF_NODRAW );
  3463. }
  3464. }
  3465. #endif
  3466. //-----------------------------------------------------------------------------
  3467. // Methods related to controlling the cheap water distance
  3468. //-----------------------------------------------------------------------------
  3469. void CViewRender::SetCheapWaterStartDistance( float flCheapWaterStartDistance )
  3470. {
  3471. m_flCheapWaterStartDistance = flCheapWaterStartDistance;
  3472. }
  3473. void CViewRender::SetCheapWaterEndDistance( float flCheapWaterEndDistance )
  3474. {
  3475. m_flCheapWaterEndDistance = flCheapWaterEndDistance;
  3476. }
  3477. void CViewRender::GetWaterLODParams( float &flCheapWaterStartDistance, float &flCheapWaterEndDistance )
  3478. {
  3479. flCheapWaterStartDistance = m_flCheapWaterStartDistance;
  3480. flCheapWaterEndDistance = m_flCheapWaterEndDistance;
  3481. }
  3482. //-----------------------------------------------------------------------------
  3483. // Purpose:
  3484. // Input : &view -
  3485. // &introData -
  3486. //-----------------------------------------------------------------------------
  3487. void CViewRender::ViewDrawScene_Intro( const CViewSetup &view, int nClearFlags, const IntroData_t &introData )
  3488. {
  3489. VPROF( "CViewRender::ViewDrawScene" );
  3490. PS3_SPUPATH_INVALID( "CViewRender::ViewDrawScene_Intro" );
  3491. CMatRenderContextPtr pRenderContext( materials );
  3492. // this allows the refract texture to be updated once per *scene* on 360
  3493. // (e.g. once for a monitor scene and once for the main scene)
  3494. g_viewscene_refractUpdateFrame = gpGlobals->framecount - 1;
  3495. // -----------------------------------------------------------------------
  3496. // Set the clear color to black since we are going to be adding up things
  3497. // in the frame buffer.
  3498. // -----------------------------------------------------------------------
  3499. // Clear alpha to 255 so that masking with the vortigaunts (0) works properly.
  3500. pRenderContext->ClearColor4ub( 0, 0, 0, 255 );
  3501. // -----------------------------------------------------------------------
  3502. // Draw the primary scene and copy it to the first framebuffer texture
  3503. // -----------------------------------------------------------------------
  3504. unsigned int visFlags;
  3505. // NOTE: We only increment this once since time doesn't move forward.
  3506. ParticleMgr()->IncrementFrameCode();
  3507. if( introData.m_bDrawPrimary )
  3508. {
  3509. CViewSetup playerView( view );
  3510. playerView.origin = introData.m_vecCameraView;
  3511. playerView.angles = introData.m_vecCameraViewAngles;
  3512. if ( introData.m_playerViewFOV )
  3513. {
  3514. playerView.fov = ScaleFOVByWidthRatio( introData.m_playerViewFOV, engine->GetScreenAspectRatio( view.width, view.height ) / ( 4.0f / 3.0f ) );
  3515. }
  3516. g_pClientShadowMgr->PreRender();
  3517. // Shadowed flashlights supported on ps_2_b and up...
  3518. if ( r_flashlightdepthtexture.GetBool() )
  3519. {
  3520. #if defined(_PS3)
  3521. g_pClientShadowMgr->ComputeShadowDepthTextures( playerView, g_viewBuilder.GetPassFlags() & PASS_BUILDLISTS_PS3 );
  3522. #else
  3523. g_pClientShadowMgr->ComputeShadowDepthTextures( playerView, ( g_viewBuilder.GetPassFlags() == PASS_BUILDLISTS ) );
  3524. #endif
  3525. }
  3526. SetupCurrentView( playerView.origin, playerView.angles, VIEW_INTRO_PLAYER );
  3527. // Invoke pre-render methods
  3528. IGameSystem::PreRenderAllSystems();
  3529. // Start view, clear frame/z buffer if necessary
  3530. SetupVis( playerView, visFlags );
  3531. render->Push3DView( pRenderContext, playerView, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH, NULL, GetFrustum() );
  3532. DrawWorldAndEntities( true /* drawSkybox */, playerView, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH );
  3533. render->PopView( pRenderContext, GetFrustum() );
  3534. // Free shadow depth textures for use in future view
  3535. if ( r_flashlightdepthtexture.GetBool() )
  3536. {
  3537. g_pClientShadowMgr->UnlockAllShadowDepthTextures();
  3538. }
  3539. }
  3540. else
  3541. {
  3542. pRenderContext->ClearBuffers( true, true );
  3543. }
  3544. Rect_t actualRect;
  3545. UpdateScreenEffectTexture( 0, view.x, view.y, view.width, view.height, false, &actualRect );
  3546. g_pClientShadowMgr->PreRender();
  3547. // Shadowed flashlights supported on ps_2_b and up...
  3548. if ( r_flashlightdepthtexture.GetBool() )
  3549. {
  3550. g_pClientShadowMgr->ComputeShadowDepthTextures( view );
  3551. }
  3552. // -----------------------------------------------------------------------
  3553. // Draw the secondary scene and copy it to the second framebuffer texture
  3554. // -----------------------------------------------------------------------
  3555. SetupCurrentView( view.origin, view.angles, VIEW_INTRO_CAMERA );
  3556. // Invoke pre-render methods
  3557. IGameSystem::PreRenderAllSystems();
  3558. // Start view, clear frame/z buffer if necessary
  3559. SetupVis( view, visFlags );
  3560. // Clear alpha to 255 so that masking with the vortigaunts (0) works properly.
  3561. pRenderContext->ClearColor4ub( 0, 0, 0, 255 );
  3562. DrawWorldAndEntities( true /* drawSkybox */, view, VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH );
  3563. UpdateScreenEffectTexture( 1, view.x, view.y, view.width, view.height );
  3564. // -----------------------------------------------------------------------
  3565. // Draw quads on the screen for each screenspace pass.
  3566. // -----------------------------------------------------------------------
  3567. // Find the material that we use to render the overlays
  3568. IMaterial *pOverlayMaterial = materials->FindMaterial( "scripted/intro_screenspaceeffect", TEXTURE_GROUP_OTHER );
  3569. IMaterialVar *pModeVar = pOverlayMaterial->FindVar( "$mode", NULL );
  3570. IMaterialVar *pAlphaVar = pOverlayMaterial->FindVar( "$alpha", NULL );
  3571. pRenderContext->ClearBuffers( true, true );
  3572. pRenderContext->MatrixMode( MATERIAL_VIEW );
  3573. pRenderContext->PushMatrix();
  3574. pRenderContext->LoadIdentity();
  3575. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  3576. pRenderContext->PushMatrix();
  3577. pRenderContext->LoadIdentity();
  3578. int passID;
  3579. for( passID = 0; passID < introData.m_Passes.Count(); passID++ )
  3580. {
  3581. const IntroDataBlendPass_t& pass = introData.m_Passes[passID];
  3582. if ( pass.m_Alpha == 0 )
  3583. continue;
  3584. // Pick one of the blend modes for the material.
  3585. if ( pass.m_BlendMode >= 0 && pass.m_BlendMode <= 9 )
  3586. {
  3587. pModeVar->SetIntValue( pass.m_BlendMode );
  3588. }
  3589. else
  3590. {
  3591. Assert(0);
  3592. }
  3593. // Set the alpha value for the material.
  3594. pAlphaVar->SetFloatValue( pass.m_Alpha );
  3595. // Draw a quad for this pass.
  3596. ITexture *pTexture = GetFullFrameFrameBufferTexture( 0 );
  3597. pRenderContext->DrawScreenSpaceRectangle( pOverlayMaterial, view.x, view.y, view.width, view.height,
  3598. actualRect.x, actualRect.y, actualRect.x+actualRect.width-1, actualRect.y+actualRect.height-1,
  3599. pTexture->GetActualWidth(), pTexture->GetActualHeight() );
  3600. }
  3601. pRenderContext->MatrixMode( MATERIAL_VIEW );
  3602. pRenderContext->PopMatrix();
  3603. pRenderContext->MatrixMode( MATERIAL_PROJECTION );
  3604. pRenderContext->PopMatrix();
  3605. // Draw the starfield
  3606. // FIXME
  3607. // blur?
  3608. // Disable fog for the rest of the stuff
  3609. DisableFog();
  3610. // Here are the overlays...
  3611. CGlowOverlay::DrawOverlays( view.m_bCacheFullSceneState );
  3612. BEGIN_2PASS_DRAW_BLOCK
  3613. // issue the pixel visibility tests
  3614. PixelVisibility_EndCurrentView();
  3615. END_2PASS_BLOCK
  3616. // And here are the screen-space effects
  3617. PerformScreenSpaceEffects( view.x, view.y, view.width, view.height );
  3618. // Make sure sound doesn't stutter
  3619. engine->Sound_ExtraUpdate();
  3620. // Debugging info goes over the top
  3621. CDebugViewRender::Draw3DDebuggingInfo( view );
  3622. // Let the particle manager simulate things that haven't been simulated.
  3623. ParticleMgr()->PostRender();
  3624. FinishCurrentView();
  3625. // Free shadow depth textures for use in future view
  3626. if ( r_flashlightdepthtexture.GetBool() )
  3627. {
  3628. g_pClientShadowMgr->UnlockAllShadowDepthTextures();
  3629. }
  3630. }
  3631. //-----------------------------------------------------------------------------
  3632. // Purpose: Sets up scene and renders camera view
  3633. // Input : cameraNum -
  3634. // &cameraView
  3635. // *localPlayer -
  3636. // x -
  3637. // y -
  3638. // width -
  3639. // height -
  3640. // highend -
  3641. // Output : Returns true on success, false on failure.
  3642. //-----------------------------------------------------------------------------
  3643. bool CViewRender::DrawOneMonitor( ITexture *pRenderTarget, int cameraNum, C_PointCamera *pCameraEnt,
  3644. const CViewSetup &cameraView, C_BasePlayer *localPlayer, int x, int y, int width, int height )
  3645. {
  3646. PS3_SPUPATH_INVALID( "CViewRender::DrawOneMonitor" );
  3647. #ifdef USE_MONITORS
  3648. VPROF_INCREMENT_COUNTER( "cameras rendered", 1 );
  3649. // Setup fog state for the camera.
  3650. fogparams_t oldFogParams;
  3651. float flOldZFar = 0.0f;
  3652. bool fogEnabled = pCameraEnt->IsFogEnabled();
  3653. CViewSetup monitorView = cameraView;
  3654. fogparams_t *pFogParams = NULL;
  3655. if ( fogEnabled )
  3656. {
  3657. if ( !localPlayer )
  3658. return false;
  3659. pFogParams = localPlayer->GetFogParams();
  3660. // Save old fog data.
  3661. oldFogParams = *pFogParams;
  3662. flOldZFar = cameraView.zFar;
  3663. pFogParams->enable = true;
  3664. pFogParams->start = pCameraEnt->GetFogStart();
  3665. pFogParams->end = pCameraEnt->GetFogEnd();
  3666. pFogParams->farz = pCameraEnt->GetFogEnd();
  3667. pFogParams->maxdensity = pCameraEnt->GetFogMaxDensity();
  3668. unsigned char r, g, b;
  3669. pCameraEnt->GetFogColor( r, g, b );
  3670. pFogParams->colorPrimary.SetR( r );
  3671. pFogParams->colorPrimary.SetG( g );
  3672. pFogParams->colorPrimary.SetB( b );
  3673. monitorView.zFar = pCameraEnt->GetFogEnd();
  3674. }
  3675. monitorView.width = width;
  3676. monitorView.height = height;
  3677. monitorView.x = x;
  3678. monitorView.y = y;
  3679. monitorView.origin = pCameraEnt->GetAbsOrigin();
  3680. monitorView.angles = pCameraEnt->GetAbsAngles();
  3681. monitorView.fov = pCameraEnt->GetFOV();
  3682. monitorView.m_bOrtho = false;
  3683. monitorView.m_flAspectRatio = pCameraEnt->UseScreenAspectRatio() ? 0.0f : 1.0f;
  3684. // @MULTICORE (toml 8/11/2006): this should be a renderer....
  3685. CMatRenderContextPtr pRenderContext( materials );
  3686. // Monitors do not support flashlight shadows because the depth texture isn't initialized until the main view (VIEW_MAIN) renders
  3687. FlashlightState_t nullFlashlight;
  3688. VMatrix matIdentity;
  3689. matIdentity.Identity();
  3690. pRenderContext->SetFlashlightState( nullFlashlight, matIdentity );
  3691. render->Push3DView( pRenderContext, monitorView, VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR, pRenderTarget, GetFrustum() );
  3692. ViewDrawScene( false, SKYBOX_2DSKYBOX_VISIBLE, monitorView, 0, VIEW_MONITOR );
  3693. render->PopView( pRenderContext, GetFrustum() );
  3694. // Reset the world fog parameters.
  3695. if ( fogEnabled )
  3696. {
  3697. if ( pFogParams )
  3698. {
  3699. *pFogParams = oldFogParams;
  3700. }
  3701. monitorView.zFar = flOldZFar;
  3702. }
  3703. #endif // USE_MONITORS
  3704. return true;
  3705. }
  3706. void CViewRender::DrawMonitors( const CViewSetup &cameraView )
  3707. {
  3708. #ifdef USE_MONITORS
  3709. // Early out if no cameras
  3710. C_PointCamera *pCameraEnt = GetPointCameraList();
  3711. if ( !pCameraEnt )
  3712. return;
  3713. #ifdef _DEBUG
  3714. g_bRenderingCameraView = true;
  3715. #endif
  3716. // FIXME: this should check for the ability to do a render target maybe instead.
  3717. // FIXME: shouldn't have to truck through all of the visible entities for this!!!!
  3718. ITexture *pCameraTarget = GetCameraTexture();
  3719. int width = pCameraTarget->GetActualWidth();
  3720. int height = pCameraTarget->GetActualHeight();
  3721. C_BasePlayer *player = C_BasePlayer::GetLocalPlayer();
  3722. int cameraNum;
  3723. for ( cameraNum = 0; pCameraEnt != NULL; pCameraEnt = pCameraEnt->m_pNext )
  3724. {
  3725. if ( !pCameraEnt->IsActive() || pCameraEnt->IsDormant() )
  3726. continue;
  3727. if ( !DrawOneMonitor( pCameraTarget, cameraNum, pCameraEnt, cameraView, player, 0, 0, width, height ) )
  3728. continue;
  3729. ++cameraNum;
  3730. }
  3731. if ( IsGameConsole() && cameraNum > 0 )
  3732. {
  3733. // resolve render target to system memory texture
  3734. // resolving *after* all monitors drawn to ensure a single blit using fastest resolve path
  3735. CMatRenderContextPtr pRenderContext( materials );
  3736. pRenderContext->PushRenderTargetAndViewport( pCameraTarget );
  3737. pRenderContext->CopyRenderTargetToTextureEx( pCameraTarget, 0, NULL, NULL );
  3738. pRenderContext->PopRenderTargetAndViewport();
  3739. }
  3740. #ifdef _DEBUG
  3741. g_bRenderingCameraView = false;
  3742. #endif
  3743. #endif // USE_MONITORS
  3744. }
  3745. //-----------------------------------------------------------------------------
  3746. //
  3747. //-----------------------------------------------------------------------------
  3748. ClientWorldListInfo_t *ClientWorldListInfo_t::AllocPooled( const ClientWorldListInfo_t &exemplar )
  3749. {
  3750. ClientWorldListInfo_t *pResult = gm_Pool.GetObject();
  3751. size_t nBytes = AlignValue( ( exemplar.m_LeafCount * (sizeof(WorldListLeafData_t) + sizeof(exemplar.m_pLeafDataList[0]))), 4096 );
  3752. byte *pMemory = (byte *)pResult->m_pLeafDataList;
  3753. if ( pMemory )
  3754. {
  3755. // Previously allocated, add a reference. Otherwise comes out of GetObject as a new object with a refcount of 1
  3756. pResult->AddRef();
  3757. }
  3758. if ( !pMemory || _msize( pMemory ) < nBytes )
  3759. {
  3760. pMemory = (byte *)realloc( pMemory, nBytes );
  3761. }
  3762. pResult->m_pLeafDataList = (WorldListLeafData_t*)pMemory;
  3763. pResult->m_pOriginalLeafIndex = (uint16*)( (byte *)( pResult->m_pLeafDataList ) + exemplar.m_LeafCount * sizeof(exemplar.m_pLeafDataList[0]) );
  3764. pResult->m_bPooledAlloc = true;
  3765. return pResult;
  3766. }
  3767. bool ClientWorldListInfo_t::OnFinalRelease()
  3768. {
  3769. if ( m_bPooledAlloc )
  3770. {
  3771. Assert( m_pLeafDataList );
  3772. gm_Pool.PutObject( this );
  3773. return false;
  3774. }
  3775. return true;
  3776. }
  3777. //-----------------------------------------------------------------------------
  3778. // Constructor
  3779. //-----------------------------------------------------------------------------
  3780. CBase3dView::CBase3dView( CViewRender *pMainView ) :
  3781. m_pMainView( pMainView ),
  3782. m_Frustum( pMainView->m_Frustum ),
  3783. m_nSlot( GET_ACTIVE_SPLITSCREEN_SLOT() )
  3784. {
  3785. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  3786. }
  3787. //-----------------------------------------------------------------------------
  3788. // Purpose:
  3789. // Input : *pEnt -
  3790. // Output : int
  3791. //-----------------------------------------------------------------------------
  3792. VPlane* CBase3dView::GetFrustum()
  3793. {
  3794. // The frustum is only valid while in a RenderView call.
  3795. // @MULTICORE (toml 8/11/2006): reimplement this when ready -- Assert(g_bRenderingView || g_bRenderingCameraView || g_bRenderingScreenshot);
  3796. return m_Frustum;
  3797. }
  3798. CObjectPool<ClientWorldListInfo_t> ClientWorldListInfo_t::gm_Pool;
  3799. #if defined(_PS3)
  3800. CClientRenderablesList g_RenderablesPool[ MAX_CONCURRENT_BUILDVIEWS ];
  3801. ClientWorldListInfo_t g_WorldListInfoPool[ MAX_CONCURRENT_BUILDVIEWS ];
  3802. #endif
  3803. //-----------------------------------------------------------------------------
  3804. // Base class for 3d views
  3805. //-----------------------------------------------------------------------------
  3806. CRendering3dView::CRendering3dView(CViewRender *pMainView) :
  3807. CBase3dView( pMainView ),
  3808. m_pWorldRenderList( NULL ),
  3809. #if !defined(_PS3)
  3810. m_pRenderables( NULL ),
  3811. m_pWorldListInfo( NULL ),
  3812. #endif
  3813. m_pCustomVisibility( NULL ),
  3814. m_DrawFlags( 0 ),
  3815. m_ClearFlags( 0 )
  3816. {
  3817. #if defined( CSTRIKE15 ) && defined(_PS3)
  3818. BEGIN_2PASS_BUILD_BLOCK
  3819. for( int i = 0; i < MAX_CONCURRENT_BUILDVIEWS; i++ )
  3820. {
  3821. m_pRenderablesList[ i ] = NULL;
  3822. m_pWorldListInfo[ i ] = NULL;
  3823. }
  3824. END_2PASS_BLOCK
  3825. #endif
  3826. }
  3827. //-----------------------------------------------------------------------------
  3828. // Sort entities in a back-to-front ordering
  3829. //-----------------------------------------------------------------------------
  3830. void CRendering3dView::Setup( const CViewSetup &setup )
  3831. {
  3832. // @MULTICORE (toml 8/15/2006): don't reset if parameters don't require it. For now, just reset
  3833. memcpy( static_cast<CViewSetup *>(this), &setup, sizeof( setup ) );
  3834. ReleaseLists();
  3835. #if defined( CSTRIKE15 ) && defined(_PS3)
  3836. // only want this statically allocated once ever really, or use a mempool
  3837. for( int i = 0; i < MAX_CONCURRENT_BUILDVIEWS; i++ )
  3838. {
  3839. m_pRenderablesList[ i ] = &g_RenderablesPool[ i ];
  3840. m_pWorldListInfo[ i ] = &g_WorldListInfoPool[ i ];
  3841. }
  3842. #else
  3843. //m_pRenderables = new CClientRenderablesList;
  3844. #endif
  3845. m_pCustomVisibility = NULL;
  3846. }
  3847. //-----------------------------------------------------------------------------
  3848. // Sort entities in a back-to-front ordering
  3849. //-----------------------------------------------------------------------------
  3850. void CRendering3dView::ReleaseLists()
  3851. {
  3852. #if defined( CSTRIKE15 ) && defined(_PS3)
  3853. for( int i = 0; i < MAX_CONCURRENT_BUILDVIEWS; i++ )
  3854. {
  3855. m_pRenderablesList[ i ] = NULL;
  3856. m_pWorldListInfo[ i ] = NULL;
  3857. }
  3858. #else
  3859. SafeRelease( m_pWorldRenderList );
  3860. SafeRelease( m_pRenderables );
  3861. SafeRelease( m_pWorldListInfo );
  3862. #endif
  3863. m_pCustomVisibility = NULL;
  3864. }
  3865. //-----------------------------------------------------------------------------
  3866. //
  3867. //-----------------------------------------------------------------------------
  3868. class SetupRenderablesListJob : public CJob
  3869. {
  3870. public:
  3871. explicit SetupRenderablesListJob( const SetupRenderInfo_t &info ) : m_SetupInfo( info ) {}
  3872. private:
  3873. virtual JobStatus_t DoExecute();
  3874. SetupRenderInfo_t m_SetupInfo;
  3875. };
  3876. JobStatus_t SetupRenderablesListJob::DoExecute()
  3877. {
  3878. ClientLeafSystem()->BuildRenderablesList( m_SetupInfo );
  3879. return JOB_OK;
  3880. }
  3881. void CRendering3dView::SetupRenderablesList( int viewID, bool bFastEntityRendering, bool bDrawDepthViewNonCachedObjectsOnly )
  3882. {
  3883. // VPROF( "CViewRender::SetupRenderablesList" );
  3884. VPROF_BUDGET( "SetupRenderablesList", "SetupRenderablesList" );
  3885. #if !defined( _PS3 )
  3886. // Create the list
  3887. m_pRenderables = new CClientRenderablesList;
  3888. g_viewBuilder.SetRenderablesListElement( m_pRenderables );
  3889. #endif
  3890. // Clear the list.
  3891. int i;
  3892. for( i=0; i < RENDER_GROUP_COUNT; i++ )
  3893. {
  3894. #if defined( CSTRIKE15 ) && defined(_PS3)
  3895. m_pRenderablesList[ g_viewBuilder.GetBuildViewID() ]->m_RenderGroupCounts[i] = 0;
  3896. #else
  3897. m_pRenderables->m_RenderGroupCounts[i] = 0;
  3898. #endif
  3899. }
  3900. // Now collate the entities in the leaves.
  3901. if( !m_pMainView->ShouldDrawEntities() )
  3902. return;
  3903. m_pMainView->IncRenderablesListsNumber();
  3904. // Precache information used commonly in CollateRenderables
  3905. SetupRenderInfo_t setupInfo;
  3906. setupInfo.m_nRenderFrame = m_pMainView->BuildRenderablesListsNumber(); // only one incremented?
  3907. setupInfo.m_nDetailBuildFrame = m_pMainView->BuildWorldListsNumber(); //
  3908. #if defined( CSTRIKE15 ) && defined(_PS3)
  3909. setupInfo.m_pWorldListInfo = m_pWorldListInfo[ g_viewBuilder.GetBuildViewID() ];
  3910. setupInfo.m_pRenderList = m_pRenderablesList[ g_viewBuilder.GetBuildViewID() ];
  3911. #endif
  3912. setupInfo.m_bDrawDetailObjects = GetClientMode()->ShouldDrawDetailObjects() && r_DrawDetailProps.GetInt();
  3913. if ( m_bCSMView )
  3914. {
  3915. setupInfo.m_bDrawTranslucentObjects = cl_csm_translucent_shadows.GetBool();
  3916. }
  3917. else
  3918. {
  3919. setupInfo.m_bDrawTranslucentObjects = ( r_flashlightdepth_drawtranslucents.GetBool() || (viewID != VIEW_SHADOW_DEPTH_TEXTURE) );
  3920. }
  3921. setupInfo.m_nViewID = viewID;
  3922. setupInfo.m_nBuildViewID = g_viewBuilder.GetBuildViewID();
  3923. setupInfo.m_nOcclustionViewID = engine->GetOcclusionViewId();
  3924. setupInfo.m_vecRenderOrigin = origin;
  3925. setupInfo.m_vecRenderForward = CurrentViewForward();
  3926. setupInfo.m_bFastEntityRendering = bFastEntityRendering;
  3927. setupInfo.m_bDrawDepthViewNonCachedObjectsOnly = bDrawDepthViewNonCachedObjectsOnly;
  3928. setupInfo.m_bCSMView = m_bCSMView;
  3929. ComputeScreenSizeInfo( &setupInfo.m_screenSizeInfo );
  3930. float fMaxDist = cl_maxrenderable_dist.GetFloat();
  3931. // Shadowing light typically has a smaller farz than cl_maxrenderable_dist
  3932. setupInfo.m_flRenderDistSq = (viewID == VIEW_SHADOW_DEPTH_TEXTURE) ? MIN(zFar, fMaxDist) : fMaxDist;
  3933. setupInfo.m_flRenderDistSq *= setupInfo.m_flRenderDistSq;
  3934. SetupRenderablesListJob *pJob = new SetupRenderablesListJob( setupInfo );
  3935. g_viewBuilder.QueueBuildRenderablesListJob( pJob );
  3936. pJob->Release();
  3937. }
  3938. #if defined(_PS3)
  3939. void CRendering3dView::SetupRenderablesList_PS3_Epilogue( void )
  3940. {
  3941. ConVarRef r_PS3_SPU_buildrenderables( "r_PS3_SPU_buildrenderables" );
  3942. if( r_PS3_SPU_buildrenderables.GetInt() )
  3943. {
  3944. ClientLeafSystem()->BuildRenderablesList_PS3_Epilogue();
  3945. }
  3946. }
  3947. #endif
  3948. //-----------------------------------------------------------------------------
  3949. //
  3950. //-----------------------------------------------------------------------------
  3951. // Kinda awkward...three optional parameters at the end...
  3952. void CRendering3dView::BuildWorldRenderLists( bool bDrawEntities, int iForceViewLeaf /* = -1 */,
  3953. bool bUseCacheIfEnabled /* = true */, bool bShadowDepth /* = false */, float *pReflectionWaterHeight /*= NULL*/ )
  3954. {
  3955. VPROF_BUDGET( "BuildWorldRenderLists", "World Render Setup" );
  3956. // @MULTICORE (toml 8/18/2006): to address....
  3957. extern void UpdateClientRenderableInPVSStatus();
  3958. UpdateClientRenderableInPVSStatus();
  3959. #if defined(_PS3)
  3960. int buildViewID = g_viewBuilder.GetBuildViewID();
  3961. Assert( !m_pWorldRenderList && !m_pWorldListInfo[ buildViewID ]);
  3962. g_viewBuilder.SetDrawFlags( m_DrawFlags );
  3963. #else
  3964. Assert( !m_pWorldRenderList && !m_pWorldListInfo);
  3965. #endif
  3966. m_pMainView->IncWorldListsNumber();
  3967. // Override vis data if specified this render, otherwise use default behavior with NULL
  3968. VisOverrideData_t* pVisData = ( m_pCustomVisibility && m_pCustomVisibility->m_VisData.m_fDistToAreaPortalTolerance != FLT_MAX ) ? &m_pCustomVisibility->m_VisData : NULL;
  3969. bool bUseCache = ( bUseCacheIfEnabled && r_worldlistcache.GetBool() );
  3970. if ( m_pCustomVisibility )
  3971. {
  3972. iForceViewLeaf = m_pCustomVisibility->m_iForceViewLeaf;
  3973. }
  3974. ClientWorldListInfo_t **ppWorldListInfo;
  3975. #if defined(_PS3)
  3976. ppWorldListInfo = &m_pWorldListInfo[ buildViewID ];
  3977. #else
  3978. ppWorldListInfo = &m_pWorldListInfo;
  3979. #endif
  3980. if ( !bUseCache || !g_WorldListCache.Find( *this, pVisData, iForceViewLeaf, &m_pWorldRenderList, ppWorldListInfo ) )
  3981. {
  3982. #if defined(_PS3)
  3983. m_pWorldRenderList = render->CreateWorldList_PS3( buildViewID );
  3984. m_pWorldListInfo[ buildViewID ] = &g_WorldListInfoPool[ buildViewID ];
  3985. m_pWorldListInfo[ buildViewID ]->Init();
  3986. //g_viewBuilder.m_pWorldRenderListCache[ buildViewID ] = m_pWorldRenderList;
  3987. g_viewBuilder.SetWorldRenderListElement( m_pWorldRenderList );
  3988. render->BuildWorldLists( m_pWorldRenderList, m_pWorldListInfo[ buildViewID ],
  3989. iForceViewLeaf, pVisData, bShadowDepth, pReflectionWaterHeight );
  3990. if ( bUseCache )
  3991. {
  3992. g_WorldListCache.Add( *this, pVisData, iForceViewLeaf, m_pWorldRenderList, m_pWorldListInfo[ buildViewID ] );
  3993. }
  3994. #else
  3995. // @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
  3996. m_pWorldRenderList = render->CreateWorldList();
  3997. m_pWorldListInfo = new ClientWorldListInfo_t;
  3998. g_viewBuilder.SetWorldRenderListElement( m_pWorldRenderList );
  3999. g_viewBuilder.SetWorldListInfoElement( m_pWorldListInfo );
  4000. render->BuildWorldLists( m_pWorldRenderList, m_pWorldListInfo,
  4001. iForceViewLeaf, pVisData, bShadowDepth, pReflectionWaterHeight );
  4002. if ( bUseCache )
  4003. {
  4004. g_WorldListCache.Add( *this, pVisData, iForceViewLeaf, m_pWorldRenderList, m_pWorldListInfo );
  4005. }
  4006. #endif
  4007. }
  4008. else
  4009. {
  4010. // Lists found in the cache, still need to set up the concurrent view builder
  4011. // (Investigate: Maybe we should cache CConcurrentViewData (as it contains all the info needed for the view) instead of
  4012. // caching the individual list)
  4013. g_viewBuilder.SetWorldRenderListElement( m_pWorldRenderList );
  4014. g_viewBuilder.SetWorldListInfoElement( m_pWorldListInfo );
  4015. g_viewBuilder.CacheFrustumData();
  4016. }
  4017. }
  4018. #if defined(_PS3)
  4019. void CRendering3dView::BuildWorldRenderLists_PS3_Epilogue( bool bShadowDepth )
  4020. {
  4021. if( !m_pWorldRenderList )
  4022. return;
  4023. ConVarRef r_PS3_SPU_buildworldlists( "r_PS3_SPU_buildworldlists" );
  4024. if( r_PS3_SPU_buildworldlists.GetInt() )
  4025. {
  4026. render->BuildWorldLists_PS3_Epilogue( m_pWorldRenderList, m_pWorldListInfo[ g_viewBuilder.GetBuildViewID() ], bShadowDepth );
  4027. }
  4028. }
  4029. #else
  4030. void CRendering3dView::BuildWorldRenderLists_Epilogue( bool bShadowDepth )
  4031. {
  4032. if( !m_pWorldRenderList )
  4033. return;
  4034. render->BuildWorldLists_Epilogue( m_pWorldRenderList, m_pWorldListInfo, bShadowDepth );
  4035. }
  4036. #endif
  4037. //-----------------------------------------------------------------------------
  4038. // Purpose: Computes the actual world list info based on the render flags
  4039. //-----------------------------------------------------------------------------
  4040. class PruneWorldListInfoJob : public CJob
  4041. {
  4042. public:
  4043. PruneWorldListInfoJob( int buildViewID, int drawFlags ) : m_nBuildViewID( buildViewID ), m_DrawFlags( drawFlags ) {}
  4044. private:
  4045. virtual JobStatus_t DoExecute();
  4046. int m_nBuildViewID;
  4047. int m_DrawFlags;
  4048. };
  4049. JobStatus_t PruneWorldListInfoJob::DoExecute()
  4050. {
  4051. ClientWorldListInfo_t *pWorldListInfo = g_viewBuilder.GetClientWorldListInfoElement( m_nBuildViewID );
  4052. int nWaterDrawFlags = m_DrawFlags & (DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER);
  4053. if ( nWaterDrawFlags == DF_RENDER_ABOVEWATER && !pWorldListInfo->m_bHasWater )
  4054. {
  4055. return JOB_OK;;
  4056. }
  4057. ClientWorldListInfo_t *pNewInfo = NULL;
  4058. if ( pWorldListInfo->m_LeafCount > 0 && nWaterDrawFlags )
  4059. {
  4060. pNewInfo = ClientWorldListInfo_t::AllocPooled( *pWorldListInfo );
  4061. pNewInfo->m_ViewFogVolume = pWorldListInfo->m_ViewFogVolume;
  4062. pNewInfo->m_bHasWater = pWorldListInfo->m_bHasWater;
  4063. pNewInfo->m_LeafCount = 0;
  4064. if ( nWaterDrawFlags != DF_RENDER_UNDERWATER || pWorldListInfo->m_bHasWater )
  4065. {
  4066. // Not drawing anything? Then don't bother with renderable lists
  4067. if ( nWaterDrawFlags != 0 )
  4068. {
  4069. // Create a sub-list based on the actual leaves being rendered
  4070. bool bRenderingUnderwater = (nWaterDrawFlags & DF_RENDER_UNDERWATER) != 0;
  4071. for ( int i = 0; i < pWorldListInfo->m_LeafCount; ++i )
  4072. {
  4073. bool bLeafIsUnderwater = ( pWorldListInfo->m_pLeafDataList[i].waterData != -1 );
  4074. if ( bRenderingUnderwater == bLeafIsUnderwater )
  4075. {
  4076. pNewInfo->m_pLeafDataList[ pNewInfo->m_LeafCount ] = pWorldListInfo->m_pLeafDataList[ i ];
  4077. pNewInfo->m_pOriginalLeafIndex[ pNewInfo->m_LeafCount ] = i;
  4078. ++pNewInfo->m_LeafCount;
  4079. }
  4080. }
  4081. }
  4082. }
  4083. g_viewBuilder.SetWorldListInfoElement( pNewInfo, m_nBuildViewID );
  4084. SafeRelease( pNewInfo );
  4085. }
  4086. else
  4087. {
  4088. //pNewInfo = new ClientWorldListInfo_t;
  4089. pWorldListInfo->m_LeafCount = 0;
  4090. }
  4091. return JOB_OK;
  4092. }
  4093. void CRendering3dView::PruneWorldListInfo()
  4094. {
  4095. #if !defined(_PS3)
  4096. // Drawing everything? Just return the world list info as-is
  4097. int nWaterDrawFlags = m_DrawFlags & (DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER);
  4098. if ( nWaterDrawFlags == (DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER) )
  4099. {
  4100. return;
  4101. }
  4102. PruneWorldListInfoJob *pJob = new PruneWorldListInfoJob( g_viewBuilder.GetBuildViewID(), m_DrawFlags );
  4103. g_viewBuilder.QueueBuildWorldListJob( pJob );
  4104. pJob->Release();
  4105. SafeRelease( m_pWorldListInfo );
  4106. #else
  4107. // TODO: Port To SPU or add to epilogue pass !!
  4108. ConVarRef r_PS3_SPU_buildworldlists("r_PS3_SPU_buildworldlists");
  4109. if( !( r_PS3_SPU_buildworldlists.GetInt() && g_viewBuilder.IsSPUBuildRWJobsOn() ) )
  4110. {
  4111. // Drawing everything? Just return the world list info as-is
  4112. int nWaterDrawFlags = m_DrawFlags & (DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER);
  4113. if ( nWaterDrawFlags == (DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER) )
  4114. {
  4115. return;
  4116. }
  4117. ClientWorldListInfo_t *pWorldListInfo = m_pWorldListInfo[ g_viewBuilder.GetBuildViewID() ];
  4118. if ( nWaterDrawFlags == DF_RENDER_ABOVEWATER && !pWorldListInfo->m_bHasWater )
  4119. return;
  4120. // in-place copy on PS3
  4121. ClientWorldListInfo_t *pNewInfo = pWorldListInfo;
  4122. int worldListInfo_LeafCount = pWorldListInfo->m_LeafCount;
  4123. //pNewInfo->m_LeafCount = 0;
  4124. int newLeafCount = 0;
  4125. if ( pWorldListInfo->m_LeafCount > 0 && nWaterDrawFlags )
  4126. {
  4127. // pNewInfo->m_pOriginalLeafIndex = (uint16*)( (byte *)( pNewInfo->m_pLeafDataList ) + pNewInfo->m_LeafCount * sizeof(pNewInfo->m_pLeafDataList[0]) );
  4128. }
  4129. else
  4130. {
  4131. // // reset
  4132. // pNewInfo->m_pLeafDataList = NULL;
  4133. }
  4134. if ( nWaterDrawFlags != DF_RENDER_UNDERWATER || pWorldListInfo->m_bHasWater )
  4135. {
  4136. // Not drawing anything? Then don't bother with renderable lists
  4137. if ( nWaterDrawFlags != 0 )
  4138. {
  4139. // Create a sub-list based on the actual leaves being rendered
  4140. bool bRenderingUnderwater = (nWaterDrawFlags & DF_RENDER_UNDERWATER) != 0;
  4141. for ( int i = 0; i < worldListInfo_LeafCount; ++i )
  4142. {
  4143. bool bLeafIsUnderwater = ( pWorldListInfo->m_pLeafDataList[i].waterData != -1 );
  4144. if ( bRenderingUnderwater == bLeafIsUnderwater )
  4145. {
  4146. pNewInfo->m_pLeafDataList[ newLeafCount ] = pWorldListInfo->m_pLeafDataList[ i ];
  4147. //pNewInfo->m_pOriginalLeafIndex[ newLeafCount ] = i;
  4148. ++newLeafCount;
  4149. }
  4150. }
  4151. }
  4152. }
  4153. pNewInfo->m_LeafCount = newLeafCount;
  4154. // m_pWorldListInfo->Release();
  4155. // m_pWorldListInfo = pNewInfo;
  4156. }
  4157. #endif
  4158. }
  4159. //-----------------------------------------------------------------------------
  4160. // Purpose:
  4161. //-----------------------------------------------------------------------------
  4162. static inline void UpdateBrushModelLightmap( IClientRenderable *pEnt )
  4163. {
  4164. model_t *pModel = ( model_t * )pEnt->GetModel();
  4165. render->UpdateBrushModelLightmap( pModel, pEnt );
  4166. }
  4167. void CRendering3dView::BuildRenderableRenderLists( int viewID, bool bFastEntityRendering, bool bDrawDepthViewNonCachedObjectsOnly )
  4168. {
  4169. MDLCACHE_CRITICAL_SECTION();
  4170. SetupRenderablesList( viewID, bFastEntityRendering, bDrawDepthViewNonCachedObjectsOnly );
  4171. }
  4172. #if defined(_PS3)
  4173. void CRendering3dView::BuildRenderableRenderLists_PS3_Epilogue( void )
  4174. {
  4175. SetupRenderablesList_PS3_Epilogue();
  4176. }
  4177. #else
  4178. void CRendering3dView::BuildRenderableRenderLists_Epilogue( int viewID )
  4179. {
  4180. if ( viewID != VIEW_SHADOW_DEPTH_TEXTURE )
  4181. {
  4182. MDLCACHE_CRITICAL_SECTION();
  4183. #if defined(_PS3)
  4184. CClientRenderablesList *pRenderablesList = m_pRenderablesList[ g_viewBuilder.GetBuildViewID() ];
  4185. #else
  4186. CClientRenderablesList *pRenderablesList = m_pRenderables;
  4187. #endif
  4188. render->BeginUpdateLightmaps();
  4189. // update lightmap on brush models if necessary
  4190. for ( int i = 0; i < RENDER_GROUP_COUNT; ++i )
  4191. {
  4192. CClientRenderablesList::CEntry *pEntities = pRenderablesList->m_RenderGroups[i];
  4193. int nCount = pRenderablesList->m_RenderGroupCounts[i];
  4194. for( int j=0; j < nCount; ++j )
  4195. {
  4196. if ( pEntities[j].m_nModelType != RENDERABLE_MODEL_BRUSH )
  4197. continue;
  4198. // For two-pass, do the work in the opaque pass.
  4199. if ( pEntities[j].m_TwoPass && ( i != RENDER_GROUP_OPAQUE) )
  4200. continue;
  4201. UpdateBrushModelLightmap( pEntities[j].m_pRenderable );
  4202. }
  4203. }
  4204. render->EndUpdateLightmaps();
  4205. }
  4206. for ( int i = 0; i < RENDER_GROUP_COUNT; ++i )
  4207. {
  4208. CClientRenderablesList *pRenderablesList = m_pRenderables;
  4209. int nCount = pRenderablesList->m_RenderGroupCounts[i];
  4210. VPROF_INCREMENT_COUNTER( "NumRenderables", nCount );
  4211. }
  4212. }
  4213. #endif
  4214. //-----------------------------------------------------------------------------
  4215. //
  4216. //-----------------------------------------------------------------------------
  4217. void CRendering3dView::DrawWorld( IMatRenderContext *pRenderContext, float waterZAdjust )
  4218. {
  4219. VPROF_INCREMENT_COUNTER( "RenderWorld", 1 );
  4220. VPROF_BUDGET( "DrawWorld", VPROF_BUDGETGROUP_WORLD_RENDERING );
  4221. if( !r_drawopaqueworld.GetBool() )
  4222. {
  4223. return;
  4224. }
  4225. unsigned long engineFlags = BuildEngineDrawWorldListFlags( m_DrawFlags );
  4226. if ( ( m_bCSMView ) && ( g_CascadeLightManager.GetCSMQualityMode() == CSMQUALITY_VERY_LOW ) )
  4227. {
  4228. engineFlags |= DRAWWORLDLISTS_DRAW_SKIP_DISPLACEMENTS;
  4229. }
  4230. render->DrawWorldLists( pRenderContext, m_pWorldRenderList, engineFlags, waterZAdjust );
  4231. }
  4232. //-----------------------------------------------------------------------------
  4233. // Sets up automatic z-prepass on the 360. No-op on PC.
  4234. //-----------------------------------------------------------------------------
  4235. void CRendering3dView::BeginConsoleZPass()
  4236. {
  4237. #if defined( _GAMECONSOLE )
  4238. {
  4239. #if defined( PORTAL )
  4240. if( g_pPortalRender->GetViewRecursionLevel() != 0 )
  4241. return;
  4242. #endif
  4243. // set up command buffer-based fast z rejection for 360
  4244. if ( r_fastzreject.GetBool() && !( m_DrawFlags & DF_SHADOW_DEPTH_MAP ) )
  4245. {
  4246. CMatRenderContextPtr pRenderContext( materials );
  4247. WorldListIndicesInfo_t indicesInfo;
  4248. render->GetWorldListIndicesInfo( &indicesInfo, m_pWorldRenderList, BuildEngineDrawWorldListFlags( m_DrawFlags ) );
  4249. pRenderContext->BeginConsoleZPass( indicesInfo );
  4250. }
  4251. }
  4252. #endif
  4253. }
  4254. //-----------------------------------------------------------------------------
  4255. // Finishes automatic z-prepass on the 360. Will kick of Z render and color
  4256. // render passes. No-op on PC.
  4257. //-----------------------------------------------------------------------------
  4258. void CRendering3dView::EndConsoleZPass()
  4259. {
  4260. #if defined( _GAMECONSOLE )
  4261. {
  4262. #if defined( PORTAL )
  4263. if( g_pPortalRender->GetViewRecursionLevel() != 0 )
  4264. return;
  4265. #endif
  4266. if ( r_fastzreject.GetBool() && !( m_DrawFlags & DF_SHADOW_DEPTH_MAP ) )
  4267. {
  4268. CMatRenderContextPtr pRenderContext( materials );
  4269. pRenderContext->EndConsoleZPass();
  4270. }
  4271. }
  4272. #endif
  4273. }
  4274. CMaterialReference g_material_WriteZ; //init'ed on by CViewRender::Init()
  4275. //-----------------------------------------------------------------------------
  4276. // Fakes per-entity clip planes on cards that don't support user clip planes.
  4277. // Achieves the effect by drawing an invisible box that writes to the depth buffer
  4278. // around the clipped area. It's not perfect, but better than nothing.
  4279. //-----------------------------------------------------------------------------
  4280. static void DrawClippedDepthBox( IClientRenderable *pEnt, float *pClipPlane )
  4281. {
  4282. //#define DEBUG_DRAWCLIPPEDDEPTHBOX //uncomment to draw the depth box as a colorful box
  4283. 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
  4284. { 3, 7, 5, 1, 3 },
  4285. { 1, 5, 4, 0, 1 },
  4286. { 2, 6, 7, 3, 2 },
  4287. { 0, 2, 3, 1, 0 },
  4288. { 5, 7, 6, 4, 5 } };
  4289. static const int iLines[12][2] = { { 0, 1 },
  4290. { 0, 2 },
  4291. { 0, 4 },
  4292. { 1, 3 },
  4293. { 1, 5 },
  4294. { 2, 3 },
  4295. { 2, 6 },
  4296. { 3, 7 },
  4297. { 4, 6 },
  4298. { 4, 5 },
  4299. { 5, 7 },
  4300. { 6, 7 } };
  4301. #ifdef DEBUG_DRAWCLIPPEDDEPTHBOX
  4302. static const float fColors[6][3] = { { 1.0f, 0.0f, 0.0f },
  4303. { 0.0f, 1.0f, 1.0f },
  4304. { 0.0f, 1.0f, 0.0f },
  4305. { 1.0f, 0.0f, 1.0f },
  4306. { 0.0f, 0.0f, 1.0f },
  4307. { 1.0f, 1.0f, 0.0f } };
  4308. #endif
  4309. Vector vNormal = *(Vector *)pClipPlane;
  4310. float fPlaneDist = pClipPlane[3];
  4311. Vector vMins, vMaxs;
  4312. pEnt->GetRenderBounds( vMins, vMaxs );
  4313. Vector vOrigin = pEnt->GetRenderOrigin();
  4314. QAngle qAngles = pEnt->GetRenderAngles();
  4315. Vector vForward, vUp, vRight;
  4316. AngleVectors( qAngles, &vForward, &vRight, &vUp );
  4317. Vector vPoints[8];
  4318. vPoints[0] = vOrigin + (vForward * vMins.x) + (vRight * vMins.y) + (vUp * vMins.z);
  4319. vPoints[1] = vOrigin + (vForward * vMaxs.x) + (vRight * vMins.y) + (vUp * vMins.z);
  4320. vPoints[2] = vOrigin + (vForward * vMins.x) + (vRight * vMaxs.y) + (vUp * vMins.z);
  4321. vPoints[3] = vOrigin + (vForward * vMaxs.x) + (vRight * vMaxs.y) + (vUp * vMins.z);
  4322. vPoints[4] = vOrigin + (vForward * vMins.x) + (vRight * vMins.y) + (vUp * vMaxs.z);
  4323. vPoints[5] = vOrigin + (vForward * vMaxs.x) + (vRight * vMins.y) + (vUp * vMaxs.z);
  4324. vPoints[6] = vOrigin + (vForward * vMins.x) + (vRight * vMaxs.y) + (vUp * vMaxs.z);
  4325. vPoints[7] = vOrigin + (vForward * vMaxs.x) + (vRight * vMaxs.y) + (vUp * vMaxs.z);
  4326. int iClipped[8];
  4327. float fDists[8];
  4328. for( int i = 0; i != 8; ++i )
  4329. {
  4330. fDists[i] = vPoints[i].Dot( vNormal ) - fPlaneDist;
  4331. iClipped[i] = (fDists[i] > 0.0f) ? 1 : 0;
  4332. }
  4333. 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
  4334. int iLineStates[8][8]; //0 = unclipped, 2 = wholly clipped, 3 = first point clipped, 4 = second point clipped
  4335. //categorize lines and generate split points where needed
  4336. for( int i = 0; i != 12; ++i )
  4337. {
  4338. const int *pPoints = iLines[i];
  4339. int iLineState = (iClipped[pPoints[0]] + iClipped[pPoints[1]]);
  4340. if( iLineState != 1 ) //either both points are clipped, or neither are clipped
  4341. {
  4342. iLineStates[pPoints[0]][pPoints[1]] =
  4343. iLineStates[pPoints[1]][pPoints[0]] =
  4344. iLineState;
  4345. }
  4346. else
  4347. {
  4348. //one point is clipped, the other is not
  4349. if( iClipped[pPoints[0]] == 1 )
  4350. {
  4351. //first point was clipped, index 1 has the negative distance
  4352. float fInvTotalDist = 1.0f / (fDists[pPoints[0]] - fDists[pPoints[1]]);
  4353. vSplitPoints[pPoints[0]][pPoints[1]] =
  4354. vSplitPoints[pPoints[1]][pPoints[0]] =
  4355. (vPoints[pPoints[1]] * (fDists[pPoints[0]] * fInvTotalDist)) - (vPoints[pPoints[0]] * (fDists[pPoints[1]] * fInvTotalDist));
  4356. Assert( fabs( vNormal.Dot( vSplitPoints[pPoints[0]][pPoints[1]] ) - fPlaneDist ) < 0.01f );
  4357. iLineStates[pPoints[0]][pPoints[1]] = 3;
  4358. iLineStates[pPoints[1]][pPoints[0]] = 4;
  4359. }
  4360. else
  4361. {
  4362. //second point was clipped, index 0 has the negative distance
  4363. float fInvTotalDist = 1.0f / (fDists[pPoints[1]] - fDists[pPoints[0]]);
  4364. vSplitPoints[pPoints[0]][pPoints[1]] =
  4365. vSplitPoints[pPoints[1]][pPoints[0]] =
  4366. (vPoints[pPoints[0]] * (fDists[pPoints[1]] * fInvTotalDist)) - (vPoints[pPoints[1]] * (fDists[pPoints[0]] * fInvTotalDist));
  4367. Assert( fabs( vNormal.Dot( vSplitPoints[pPoints[0]][pPoints[1]] ) - fPlaneDist ) < 0.01f );
  4368. iLineStates[pPoints[0]][pPoints[1]] = 4;
  4369. iLineStates[pPoints[1]][pPoints[0]] = 3;
  4370. }
  4371. }
  4372. }
  4373. CMatRenderContextPtr pRenderContext( materials );
  4374. #ifdef DEBUG_DRAWCLIPPEDDEPTHBOX
  4375. pRenderContext->Bind( materials->FindMaterial( "debug/debugvertexcolor", TEXTURE_GROUP_OTHER ), NULL );
  4376. #else
  4377. pRenderContext->Bind( g_material_WriteZ, NULL );
  4378. #endif
  4379. CMeshBuilder meshBuilder;
  4380. IMesh* pMesh = pRenderContext->GetDynamicMesh( false );
  4381. 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
  4382. //going to draw as a collection of triangles, arranged as a triangle fan on each side
  4383. for( int i = 0; i != 6; ++i )
  4384. {
  4385. const int *pPoints = iQuads[i];
  4386. //can't start the fan on a wholly clipped line, so seek to one that isn't
  4387. int j = 0;
  4388. do
  4389. {
  4390. if( iLineStates[pPoints[j]][pPoints[j+1]] != 2 ) //at least part of this line will be drawn
  4391. break;
  4392. ++j;
  4393. } while( j != 3 );
  4394. if( j == 3 ) //not enough lines to even form a triangle
  4395. continue;
  4396. float *pStartPoint = NULL;
  4397. float *pTriangleFanPoints[4]; //at most, one of our fans will have 5 points total, with the first point being stored separately as pStartPoint
  4398. int iTriangleFanPointCount = 1; //the switch below creates the first for sure
  4399. //figure out how to start the fan
  4400. switch( iLineStates[pPoints[j]][pPoints[j+1]] )
  4401. {
  4402. case 0: //uncut
  4403. pStartPoint = &vPoints[pPoints[j]].x;
  4404. pTriangleFanPoints[0] = &vPoints[pPoints[j+1]].x;
  4405. break;
  4406. case 4: //second index was clipped
  4407. pStartPoint = &vPoints[pPoints[j]].x;
  4408. pTriangleFanPoints[0] = &vSplitPoints[pPoints[j]][pPoints[j+1]].x;
  4409. break;
  4410. case 3: //first index was clipped
  4411. pStartPoint = &vSplitPoints[pPoints[j]][pPoints[j+1]].x;
  4412. pTriangleFanPoints[0] = &vPoints[pPoints[j + 1]].x;
  4413. break;
  4414. default:
  4415. Assert( false );
  4416. break;
  4417. };
  4418. for( ++j; j != 3; ++j ) //add end points for the rest of the indices, we're assembling a triangle fan
  4419. {
  4420. switch( iLineStates[pPoints[j]][pPoints[j+1]] )
  4421. {
  4422. case 0: //uncut line, normal endpoint
  4423. pTriangleFanPoints[iTriangleFanPointCount] = &vPoints[pPoints[j+1]].x;
  4424. ++iTriangleFanPointCount;
  4425. break;
  4426. case 2: //wholly cut line, no endpoint
  4427. break;
  4428. case 3: //first point is clipped, normal endpoint
  4429. //special case, adds start and end point
  4430. pTriangleFanPoints[iTriangleFanPointCount] = &vSplitPoints[pPoints[j]][pPoints[j+1]].x;
  4431. ++iTriangleFanPointCount;
  4432. pTriangleFanPoints[iTriangleFanPointCount] = &vPoints[pPoints[j+1]].x;
  4433. ++iTriangleFanPointCount;
  4434. break;
  4435. case 4: //second point is clipped
  4436. pTriangleFanPoints[iTriangleFanPointCount] = &vSplitPoints[pPoints[j]][pPoints[j+1]].x;
  4437. ++iTriangleFanPointCount;
  4438. break;
  4439. default:
  4440. Assert( false );
  4441. break;
  4442. };
  4443. }
  4444. //special case endpoints, half-clipped lines have a connecting line between them and the next line (first line in this case)
  4445. switch( iLineStates[pPoints[j]][pPoints[j+1]] )
  4446. {
  4447. case 3:
  4448. case 4:
  4449. pTriangleFanPoints[iTriangleFanPointCount] = &vSplitPoints[pPoints[j]][pPoints[j+1]].x;
  4450. ++iTriangleFanPointCount;
  4451. break;
  4452. };
  4453. Assert( iTriangleFanPointCount <= 4 );
  4454. //add the fan to the mesh
  4455. int iLoopStop = iTriangleFanPointCount - 1;
  4456. for( int k = 0; k != iLoopStop; ++k )
  4457. {
  4458. meshBuilder.Position3fv( pStartPoint );
  4459. #ifdef DEBUG_DRAWCLIPPEDDEPTHBOX
  4460. float fHalfColors[3] = { fColors[i][0] * 0.5f, fColors[i][1] * 0.5f, fColors[i][2] * 0.5f };
  4461. meshBuilder.Color3fv( fHalfColors );
  4462. #endif
  4463. meshBuilder.AdvanceVertex();
  4464. meshBuilder.Position3fv( pTriangleFanPoints[k] );
  4465. #ifdef DEBUG_DRAWCLIPPEDDEPTHBOX
  4466. meshBuilder.Color3fv( fColors[i] );
  4467. #endif
  4468. meshBuilder.AdvanceVertex();
  4469. meshBuilder.Position3fv( pTriangleFanPoints[k+1] );
  4470. #ifdef DEBUG_DRAWCLIPPEDDEPTHBOX
  4471. meshBuilder.Color3fv( fColors[i] );
  4472. #endif
  4473. meshBuilder.AdvanceVertex();
  4474. }
  4475. }
  4476. meshBuilder.End();
  4477. pMesh->Draw();
  4478. pRenderContext->Flush( false );
  4479. }
  4480. //-----------------------------------------------------------------------------
  4481. // Unified bit of draw code for opaque and translucent renderables
  4482. //-----------------------------------------------------------------------------
  4483. static inline void DrawRenderable( IClientRenderable *pEnt, int flags, const RenderableInstance_t &instance, bool bShadowDepth )
  4484. {
  4485. float *pRenderClipPlane = NULL;
  4486. if( r_entityclips.GetBool() )
  4487. pRenderClipPlane = pEnt->GetRenderClipPlane();
  4488. if( pRenderClipPlane )
  4489. {
  4490. CMatRenderContextPtr pRenderContext( materials );
  4491. if( !materials->UsingFastClipping() ) //do NOT change the fast clip plane mid-scene, depth problems result. Regular user clip planes are fine though
  4492. pRenderContext->PushCustomClipPlane( pRenderClipPlane );
  4493. else if ( !bShadowDepth ) // in shadow-depth pass, this step is unnecessary
  4494. DrawClippedDepthBox( pEnt, pRenderClipPlane );
  4495. Assert( view->GetCurrentlyDrawingEntity() == NULL );
  4496. view->SetCurrentlyDrawingEntity( pEnt->GetIClientUnknown()->GetBaseEntity() );
  4497. pEnt->DrawModel( flags, instance );
  4498. view->SetCurrentlyDrawingEntity( NULL );
  4499. if( !materials->UsingFastClipping() )
  4500. pRenderContext->PopCustomClipPlane();
  4501. }
  4502. else
  4503. {
  4504. Assert( view->GetCurrentlyDrawingEntity() == NULL );
  4505. view->SetCurrentlyDrawingEntity( pEnt->GetIClientUnknown()->GetBaseEntity() );
  4506. if( bShadowDepth )
  4507. flags |= DF_SHADOW_DEPTH_MAP;
  4508. pEnt->DrawModel( flags, instance );
  4509. view->SetCurrentlyDrawingEntity( NULL );
  4510. }
  4511. }
  4512. //-----------------------------------------------------------------------------
  4513. // Draws all opaque renderables in leaves that were rendered
  4514. //-----------------------------------------------------------------------------
  4515. static inline void DrawOpaqueRenderable( IClientRenderable *pEnt, bool bTwoPass, ERenderDepthMode_t DepthMode )
  4516. {
  4517. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  4518. #ifdef PORTAL
  4519. Assert( ( g_pPortalRender->GetViewRecursionLevel() > 0 ) || !IsSplitScreenSupported() || pEnt->ShouldDrawForSplitScreenUser( GET_ACTIVE_SPLITSCREEN_SLOT() ) );
  4520. #else
  4521. Assert( !IsSplitScreenSupported() || pEnt->ShouldDrawForSplitScreenUser( GET_ACTIVE_SPLITSCREEN_SLOT() ) );
  4522. #endif
  4523. Assert( (pEnt->GetIClientUnknown() == NULL) || (pEnt->GetIClientUnknown()->GetIClientEntity() == NULL) || (pEnt->GetIClientUnknown()->GetIClientEntity()->IsBlurred() == false) );
  4524. int flags = STUDIO_RENDER;
  4525. if ( bTwoPass )
  4526. {
  4527. flags |= STUDIO_TWOPASS;
  4528. }
  4529. if ( DepthMode == DEPTH_MODE_SHADOW )
  4530. {
  4531. flags |= STUDIO_SHADOWDEPTHTEXTURE;
  4532. }
  4533. else if ( DepthMode == DEPTH_MODE_SSA0 )
  4534. {
  4535. flags |= STUDIO_SSAODEPTHTEXTURE;
  4536. }
  4537. else
  4538. {
  4539. float color[3];
  4540. pEnt->GetColorModulation( color );
  4541. render->SetColorModulation( color );
  4542. }
  4543. RenderableInstance_t instance;
  4544. instance.m_nAlpha = 255;
  4545. DrawRenderable( pEnt, flags, instance, DepthMode == DEPTH_MODE_SHADOW );
  4546. }
  4547. //-------------------------------------
  4548. static void SetupBonesOnBaseAnimating( C_BaseAnimating *&pBaseAnimating )
  4549. {
  4550. pBaseAnimating->SetupBones( NULL, -1, -1, gpGlobals->curtime );
  4551. }
  4552. static ConVar cl_brushfastpath( "cl_brushfastpath", "1", FCVAR_CHEAT );
  4553. static ConVar r_drawbrushmodels( "r_drawbrushmodels", "1", FCVAR_CHEAT, "Render brush models. 0=Off, 1=Normal, 2=Wireframe" );
  4554. static void DrawOpaqueRenderables_DrawBrushModels( CClientRenderablesList::CEntry **pBrushEntities, int nBrushEntityCount, ERenderDepthMode_t DepthMode, CUtlVector< CClientRenderablesList::CEntry * > *pDeferClippedOpaqueRenderables_Out )
  4555. {
  4556. // Skip if we're not rendering brush model entities
  4557. if ( !r_drawbrushmodels.GetBool() )
  4558. return;
  4559. // See about rendering brushes in the "fast path"
  4560. int nRemainingBrushes = nBrushEntityCount;
  4561. if ( cl_brushfastpath.GetBool() )
  4562. {
  4563. nRemainingBrushes = 0;
  4564. CUtlVector< ModelRenderSystemData_t > arrBrushRenderables( (ModelRenderSystemData_t *)stackalloc( nBrushEntityCount * sizeof( ModelRenderSystemData_t ) ), nBrushEntityCount );
  4565. for ( int i = 0; i < nBrushEntityCount; ++i )
  4566. {
  4567. CClientRenderablesList::CEntry *itEntity = pBrushEntities[i];
  4568. Assert( itEntity->m_pRenderable );
  4569. if ( !itEntity->m_pRenderable )
  4570. continue;
  4571. IClientModelRenderable *pModelRenderable = itEntity->m_pRenderable->GetClientModelRenderable();
  4572. if ( !pModelRenderable )
  4573. {
  4574. pBrushEntities[nRemainingBrushes++] = itEntity;
  4575. continue;
  4576. }
  4577. ModelRenderSystemData_t data;
  4578. data.m_pRenderable = itEntity->m_pRenderable;
  4579. data.m_pModelRenderable = pModelRenderable;
  4580. data.m_InstanceData = itEntity->m_InstanceData;
  4581. arrBrushRenderables.AddToTail( data );
  4582. }
  4583. ModelRenderMode_t nRenderMode = MODEL_RENDER_MODE_NORMAL;
  4584. switch ( DepthMode )
  4585. {
  4586. case DEPTH_MODE_SHADOW:
  4587. nRenderMode = MODEL_RENDER_MODE_SHADOW_DEPTH;
  4588. break;
  4589. case DEPTH_MODE_SSA0:
  4590. nRenderMode = MODEL_RENDER_MODE_SSAO;
  4591. break;
  4592. default:
  4593. nRenderMode = MODEL_RENDER_MODE_NORMAL;
  4594. }
  4595. g_pModelRenderSystem->DrawBrushModels( arrBrushRenderables.Base(), arrBrushRenderables.Count(), nRenderMode );
  4596. }
  4597. if( pDeferClippedOpaqueRenderables_Out )
  4598. {
  4599. for( int i = 0; i < nRemainingBrushes; ++i )
  4600. {
  4601. CClientRenderablesList::CEntry* pEntity = pBrushEntities[i];
  4602. if( pEntity->m_pRenderable && (pEntity->m_pRenderable->GetRenderClipPlane() != NULL) )
  4603. {
  4604. pDeferClippedOpaqueRenderables_Out->AddToTail( pEntity );
  4605. }
  4606. else
  4607. {
  4608. DrawOpaqueRenderable( pEntity->m_pRenderable, pEntity->m_TwoPass, DepthMode );
  4609. }
  4610. }
  4611. }
  4612. else
  4613. {
  4614. for( int i = 0; i < nRemainingBrushes; ++i )
  4615. {
  4616. CClientRenderablesList::CEntry* pEntity = pBrushEntities[i];
  4617. DrawOpaqueRenderable( pEntity->m_pRenderable, pEntity->m_TwoPass, DepthMode );
  4618. }
  4619. }
  4620. }
  4621. static void DrawOpaqueRenderables_DrawStaticProps( int nCount, CClientRenderablesList::CEntry **ppEntities, ERenderDepthMode_t DepthMode )
  4622. {
  4623. if ( nCount == 0 )
  4624. return;
  4625. float one[4] = { 1.0f, 1.0f, 1.0f, 1.0f };
  4626. render->SetColorModulation( one );
  4627. render->SetBlend( 1.0f );
  4628. const int MAX_STATICS_PER_BATCH = 512;
  4629. IClientRenderable *pStatics[ MAX_STATICS_PER_BATCH ];
  4630. RenderableInstance_t pInstances[ MAX_STATICS_PER_BATCH ];
  4631. int numScheduled = 0, numAvailable = MAX_STATICS_PER_BATCH;
  4632. for( int i = 0; i < nCount; ++i )
  4633. {
  4634. CClientRenderablesList::CEntry *itEntity = ppEntities[i];
  4635. if ( !itEntity->m_pRenderable )
  4636. continue;
  4637. pInstances[ numScheduled ] = itEntity->m_InstanceData;
  4638. pStatics[ numScheduled ++ ] = itEntity->m_pRenderable;
  4639. if ( -- numAvailable > 0 )
  4640. continue; // place a hint for compiler to predict more common case in the loop
  4641. staticpropmgr->DrawStaticProps( pStatics, pInstances, numScheduled, DepthMode == DEPTH_MODE_SHADOW, vcollide_wireframe.GetBool() );
  4642. numScheduled = 0;
  4643. numAvailable = MAX_STATICS_PER_BATCH;
  4644. }
  4645. if ( numScheduled )
  4646. staticpropmgr->DrawStaticProps( pStatics, pInstances, numScheduled, DepthMode == DEPTH_MODE_SHADOW, vcollide_wireframe.GetBool() );
  4647. }
  4648. static void DrawOpaqueRenderables_Range( int nCount, CClientRenderablesList::CEntry **ppEntities, ERenderDepthMode_t DepthMode, CUtlVector< CClientRenderablesList::CEntry * > *pDeferClippedOpaqueRenderables_Out )
  4649. {
  4650. if( pDeferClippedOpaqueRenderables_Out )
  4651. {
  4652. for ( int i = 0; i < nCount; ++i )
  4653. {
  4654. CClientRenderablesList::CEntry *itEntity = ppEntities[i];
  4655. if( itEntity->m_pRenderable && (itEntity->m_pRenderable->GetRenderClipPlane() != NULL) )
  4656. {
  4657. pDeferClippedOpaqueRenderables_Out->AddToTail( itEntity );
  4658. }
  4659. else
  4660. {
  4661. DrawOpaqueRenderable( itEntity->m_pRenderable, ( itEntity->m_TwoPass != 0 ), DepthMode );
  4662. }
  4663. }
  4664. }
  4665. else
  4666. {
  4667. for ( int i = 0; i < nCount; ++i )
  4668. {
  4669. CClientRenderablesList::CEntry *itEntity = ppEntities[i];
  4670. if ( itEntity->m_pRenderable )
  4671. {
  4672. DrawOpaqueRenderable( itEntity->m_pRenderable, ( itEntity->m_TwoPass != 0 ), DepthMode );
  4673. }
  4674. }
  4675. }
  4676. }
  4677. //-----------------------------------------------------------------------------
  4678. // Renders all translucent world, entities, and detail objects in a particular set of leaves
  4679. //-----------------------------------------------------------------------------
  4680. //$TODO(msmith) This "fast path" (cl_modelfastpath) doesn't currently work on css15. Alpha does not render on enemies, only teammates.
  4681. // Investingation should be made as to why it's broken before turning it back on by default. And we should only look to turn
  4682. // it on if when we do turn it on there is a performance win (on PS3 and Xbox360).
  4683. ConVar cl_modelfastpath( "cl_modelfastpath", "1" );
  4684. ConVar cl_skipslowpath( "cl_skipslowpath", "0", FCVAR_CHEAT, "Set to 1 to skip any models that don't go through the model fast path" );
  4685. extern ConVar r_drawothermodels;
  4686. static void DrawOpaqueRenderables_ModelRenderables( int nCount, ModelRenderSystemData_t* pModelRenderables, ERenderDepthMode_t DepthMode, bool bShadowDepthIncludeTranslucentMaterials )
  4687. {
  4688. ModelRenderMode_t nRenderMode = MODEL_RENDER_MODE_NORMAL;
  4689. switch ( DepthMode )
  4690. {
  4691. case DEPTH_MODE_SHADOW:
  4692. nRenderMode = MODEL_RENDER_MODE_SHADOW_DEPTH;
  4693. break;
  4694. case DEPTH_MODE_SSA0:
  4695. nRenderMode = MODEL_RENDER_MODE_SSAO;
  4696. break;
  4697. default:
  4698. nRenderMode = MODEL_RENDER_MODE_NORMAL;
  4699. }
  4700. g_pModelRenderSystem->DrawModels( pModelRenderables, nCount, nRenderMode, bShadowDepthIncludeTranslucentMaterials );
  4701. }
  4702. static void DrawOpaqueRenderables_NPCs( int nCount, CClientRenderablesList::CEntry **ppEntities, ERenderDepthMode_t DepthMode, CUtlVector< CClientRenderablesList::CEntry * > *pDeferClippedOpaqueRenderables_Out )
  4703. {
  4704. DrawOpaqueRenderables_Range( nCount, ppEntities, DepthMode, pDeferClippedOpaqueRenderables_Out );
  4705. }
  4706. void CRendering3dView::DrawOpaqueRenderables( IMatRenderContext *pRenderContext, RenderablesRenderPath_t eRenderPath, ERenderDepthMode_t DepthMode, CUtlVector< CClientRenderablesList::CEntry * > *pDeferClippedOpaqueRenderables_Out, RenderGroup_t nGroup )
  4707. {
  4708. VPROF("CViewRender::DrawOpaqueRenderables" );
  4709. bool bShadowDepth = ( eRenderPath > 0 );
  4710. #if defined( _X360 )
  4711. // IESTYN -------- 11/5/2010 (June '09 XDK) -----------------------------------------
  4712. //
  4713. // There is currently a codegen bug in the X360 compiler, for which the below CFmtStr initialization is a workaround.
  4714. // The problem appears to be that the stackallocs below cause 'eRenderPath' (when pushed onto the stack) to be
  4715. // corrupted to some value which is less than zero. Replacing the stackallocs with regular mallocs, or adding any
  4716. // additional code (e.g. this CFmtStr) which references the 'bShadowDepth' variable will cause the bug to disappear.
  4717. // The original symptom was a GPU HANG on starting a Co-op game; bShadowDepth was erroneously determined to be
  4718. // FALSE during the shadow depth pass, so models were rendered using their regular (rather than NULL) pixel shaders,
  4719. // at a time when the pixel shader GPR allocation is set to its minimum value of 16.
  4720. //
  4721. if ( eRenderPath == 123454321 ) { CFmtStr buf( "Hocus Pocus Alakazam: %d %d", eRenderPath, bShadowDepth ); }
  4722. //
  4723. // IESTYN -------- 11/5/2010 (June '09 XDK) -----------------------------------------
  4724. #endif // _X360
  4725. if ( nGroup == RENDER_GROUP_TRANSLUCENT )
  4726. {
  4727. if( !r_drawtranslucentworld.GetBool() )
  4728. return;
  4729. }
  4730. else
  4731. {
  4732. if( !r_drawopaquerenderables.GetBool() )
  4733. return;
  4734. }
  4735. if( !m_pMainView->ShouldDrawEntities() )
  4736. return;
  4737. render->SetBlend( 1 );
  4738. //
  4739. // Prepare to iterate over all leaves that were visible, and draw opaque things in them.
  4740. //
  4741. RopeManager()->ResetRenderCache();
  4742. g_pParticleSystemMgr->ResetRenderCache();
  4743. // Categorize models by type
  4744. #if defined(_PS3)
  4745. int nOpaqueRenderableCount = m_pRenderablesList[ g_viewBuilder.GetBuildViewID() ]->m_RenderGroupCounts[nGroup];
  4746. #else
  4747. int nOpaqueRenderableCount = m_pRenderables->m_RenderGroupCounts[nGroup];
  4748. #endif
  4749. CClientRenderablesList::CEntry** pBrushModels = (CClientRenderablesList::CEntry **)stackalloc( nOpaqueRenderableCount * sizeof( CClientRenderablesList::CEntry* ) );
  4750. CClientRenderablesList::CEntry** pStaticProps = (CClientRenderablesList::CEntry **)stackalloc( nOpaqueRenderableCount * sizeof( CClientRenderablesList::CEntry* ) );
  4751. CClientRenderablesList::CEntry** pOtherRenderables = (CClientRenderablesList::CEntry **)stackalloc( nOpaqueRenderableCount * sizeof( CClientRenderablesList::CEntry* ) );
  4752. #if defined(_PS3)
  4753. CClientRenderablesList::CEntry *pOpaqueList = m_pRenderablesList[ g_viewBuilder.GetBuildViewID() ]->m_RenderGroups[nGroup];
  4754. #else
  4755. CClientRenderablesList::CEntry *pOpaqueList = m_pRenderables->m_RenderGroups[nGroup];
  4756. #endif
  4757. int nBrushCount = 0;
  4758. int nStaticCount = 0;
  4759. int nOtherCount = 0;
  4760. #ifdef _PS3
  4761. // extern uint32 g_ps3_ShadowDepth_TextureCache;
  4762. // 7LTODO
  4763. // for ( int iPs3depthGeoCacheLoopCounter = 0,
  4764. // iPs3depthGeoCacheLoopEnd = ( ( eRenderPath != RENDERABLES_RENDER_PATH_SHADOWDEPTH_BUILD_GEOCACHE ) ? 1 : 2 );
  4765. // iPs3depthGeoCacheLoopCounter < iPs3depthGeoCacheLoopEnd; ++ iPs3depthGeoCacheLoopCounter )
  4766. // {
  4767. // const bool bMultipassGeoCacheLoop = ( iPs3depthGeoCacheLoopEnd > 1 );
  4768. // if ( eRenderPath == RENDERABLES_RENDER_PATH_SHADOWDEPTH_USE_GEOCACHE )
  4769. // {
  4770. // pRenderContext->InvokeGpuDataTransferCache( g_ps3_ShadowDepth_TextureCache | PS3GPU_DATA_TRANSFER_CACHE2REAL ); // seed the rendertarget with the cached data
  4771. // }
  4772. // else if ( iPs3depthGeoCacheLoopCounter )
  4773. // {
  4774. // pRenderContext->InvokeGpuDataTransferCache( g_ps3_ShadowDepth_TextureCache | PS3GPU_DATA_TRANSFER_REAL2CACHE ); // copy off rendertarget data into cache
  4775. //
  4776. // nBrushCount = 0;
  4777. // nStaticCount = 0;
  4778. // nOtherCount = 0;
  4779. // }
  4780. #endif
  4781. for ( int i = 0; i < nOpaqueRenderableCount; ++i )
  4782. {
  4783. #ifdef _PS3
  4784. // Only render the correct cache part of opaques each loop iteration
  4785. // 7LTODO if ( bMultipassGeoCacheLoop && ( !iPs3depthGeoCacheLoopCounter == !!pOpaqueList[i].m_bShadowDepthNoCache) )
  4786. // continue;
  4787. #endif
  4788. switch( pOpaqueList[i].m_nModelType )
  4789. {
  4790. case RENDERABLE_MODEL_BRUSH: pBrushModels[nBrushCount++] = &pOpaqueList[i]; break;
  4791. case RENDERABLE_MODEL_STATIC_PROP: pStaticProps[nStaticCount++] = &pOpaqueList[i]; break;
  4792. default: pOtherRenderables[nOtherCount++] = &pOpaqueList[i]; break;
  4793. }
  4794. }
  4795. //
  4796. // First do the brush models
  4797. //
  4798. if ( nGroup != RENDER_GROUP_TRANSLUCENT )
  4799. {
  4800. DrawOpaqueRenderables_DrawBrushModels( pBrushModels, nBrushCount, DepthMode, pDeferClippedOpaqueRenderables_Out );
  4801. }
  4802. if( IsPS3() )
  4803. {
  4804. // PS3 vertex shader processors are underpowered relative to X360, so we only want to draw low-vertex high-fill pieces of the world, but not models that have
  4805. // a lot of vertices and not many pixels. This is why we end Z pass here on PS/3 but end it later on Xbox360
  4806. EndConsoleZPass();
  4807. }
  4808. // Move all static props to modelrendersystem
  4809. bool bUseFastPath = ( cl_modelfastpath.GetInt() != 0 );
  4810. //
  4811. // Sort everything that's not a static prop
  4812. //
  4813. CUtlVector< CClientRenderablesList::CEntry* > arrRenderEntsNpcsFirst( (CClientRenderablesList::CEntry **)stackalloc( nOtherCount * sizeof( CClientRenderablesList::CEntry ) ), nOtherCount );
  4814. CUtlVector< ModelRenderSystemData_t > arrModelRenderables( (ModelRenderSystemData_t *)stackalloc( ( nOtherCount + nStaticCount ) * sizeof( ModelRenderSystemData_t ) ), nOtherCount + nStaticCount );
  4815. // Queue up RENDER_GROUP_OPAQUE_ENTITY entities to be rendered later.
  4816. CClientRenderablesList::CEntry *itEntity;
  4817. int nRemainingOther = 0;
  4818. if( r_drawothermodels.GetBool() )
  4819. {
  4820. for ( int i = 0; i < nOtherCount; ++i )
  4821. {
  4822. itEntity = pOtherRenderables[i];
  4823. if ( !itEntity->m_pRenderable )
  4824. continue;
  4825. IClientModelRenderable *pModelRenderable = itEntity->m_pRenderable->GetClientModelRenderable();
  4826. // FIXME: Strangely, some static props are in the non-static prop bucket
  4827. // which is what the last case in this if statement is for
  4828. if ( bUseFastPath && pModelRenderable )
  4829. {
  4830. ModelRenderSystemData_t data;
  4831. data.m_pRenderable = itEntity->m_pRenderable;
  4832. data.m_pModelRenderable = pModelRenderable;
  4833. data.m_InstanceData = itEntity->m_InstanceData;
  4834. arrModelRenderables.AddToTail( data );
  4835. continue;
  4836. }
  4837. IClientUnknown *pUnknown = itEntity->m_pRenderable->GetIClientUnknown();
  4838. C_BaseEntity *pEntity = pUnknown->GetBaseEntity();
  4839. if ( pEntity && pEntity->IsNPC() )
  4840. {
  4841. arrRenderEntsNpcsFirst.AddToTail( itEntity );
  4842. continue;
  4843. }
  4844. pOtherRenderables[nRemainingOther++] = itEntity;
  4845. }
  4846. }
  4847. // Queue up the static props to be rendered later.
  4848. int nRemainingStatics = 0;
  4849. if ( bUseFastPath )
  4850. {
  4851. const int LOOKAHEAD_PREFETCH = 7;
  4852. int nPrefetchCount = MIN(nStaticCount, LOOKAHEAD_PREFETCH);
  4853. for ( int i = 0; i < nPrefetchCount; i++ )
  4854. {
  4855. PREFETCH_128( pStaticProps[i]->m_pRenderable, 0 );
  4856. }
  4857. int nLastPrefetch = nStaticCount - LOOKAHEAD_PREFETCH;
  4858. for ( int i = 0; i < nStaticCount; ++i )
  4859. {
  4860. if ( i < nLastPrefetch )
  4861. {
  4862. PREFETCH_128( pStaticProps[i+LOOKAHEAD_PREFETCH]->m_pRenderable, 0 );
  4863. }
  4864. itEntity = pStaticProps[i];
  4865. if ( !itEntity->m_pRenderable )
  4866. continue;
  4867. IClientModelRenderable *pModelRenderable = itEntity->m_pRenderable->GetClientModelRenderable();
  4868. if ( !pModelRenderable )
  4869. {
  4870. pStaticProps[nRemainingStatics++] = itEntity;
  4871. continue;
  4872. }
  4873. ModelRenderSystemData_t data;
  4874. data.m_pRenderable = itEntity->m_pRenderable;
  4875. data.m_pModelRenderable = pModelRenderable;
  4876. data.m_InstanceData = itEntity->m_InstanceData;
  4877. arrModelRenderables.AddToTail( data );
  4878. }
  4879. }
  4880. else
  4881. {
  4882. nRemainingStatics = nStaticCount;
  4883. }
  4884. //
  4885. // Draw model renderables now (ie. models that use the fast path)
  4886. //
  4887. DrawOpaqueRenderables_ModelRenderables( arrModelRenderables.Count(), arrModelRenderables.Base(), DepthMode, nGroup == RENDER_GROUP_TRANSLUCENT );
  4888. // Turn off z pass here. Don't want non-fastpath models with potentially large dynamic VB requirements overwrite
  4889. // stuff in the dynamic VB ringbuffer. We're calling EndConsoleZPass again in DrawExecute, but that's not a problem.
  4890. // BeginConsoleZPass/EndConsoleZPass don't have to be matched exactly. The first EndConsoleZPass ends Zpass, subsequent Ends don't have any effect
  4891. if( !IsPS3() )
  4892. {
  4893. // we end console ZPass earlier in this same function for PS/3, no need to call it twice
  4894. EndConsoleZPass();
  4895. }
  4896. //
  4897. // Draw static props + opaque entities that aren't using the fast path.
  4898. //
  4899. DrawOpaqueRenderables_Range( nRemainingOther, pOtherRenderables, DepthMode, pDeferClippedOpaqueRenderables_Out );
  4900. DrawOpaqueRenderables_DrawStaticProps( nRemainingStatics, pStaticProps, DepthMode );
  4901. //
  4902. // Draw NPCs now. 7LS - TODO - don't draw NPC's into viewmodel cascade on console
  4903. //
  4904. DrawOpaqueRenderables_NPCs( arrRenderEntsNpcsFirst.Count(), arrRenderEntsNpcsFirst.Base(), DepthMode, pDeferClippedOpaqueRenderables_Out );
  4905. #ifdef _PS3
  4906. // 7LTODO -- Took out for loop! }
  4907. #endif
  4908. //
  4909. // Ropes and particles
  4910. //
  4911. bool bDrawRopes = true;
  4912. if ( bShadowDepth )
  4913. {
  4914. if ( m_bCSMView && !( cl_csm_rope_shadows.GetBool() && cl_csm_shadows.GetBool() ) )
  4915. bDrawRopes = false;
  4916. if ( m_bCSMView && !IsGameConsole() && ( g_CascadeLightManager.GetCSMQualityMode() == CSMQUALITY_VERY_LOW ) )
  4917. bDrawRopes = false;
  4918. }
  4919. if ( DepthMode == DEPTH_MODE_SSA0 )
  4920. {
  4921. bDrawRopes = false;
  4922. }
  4923. if ( bDrawRopes )
  4924. {
  4925. RopeManager()->DrawRenderCache( pRenderContext, bShadowDepth );
  4926. }
  4927. g_pParticleSystemMgr->DrawRenderCache( pRenderContext, bShadowDepth );
  4928. }
  4929. void CRendering3dView::DrawDeferredClippedOpaqueRenderables( IMatRenderContext *pRenderContext, RenderablesRenderPath_t eRenderPath, ERenderDepthMode_t DepthMode, CUtlVector< CClientRenderablesList::CEntry * > *pDeferClippedOpaqueRenderables )
  4930. {
  4931. if( pDeferClippedOpaqueRenderables )
  4932. {
  4933. //bool bShadowDepth = ( eRenderPath > 0 );
  4934. int nCount = pDeferClippedOpaqueRenderables->Count();
  4935. CClientRenderablesList::CEntry **ppEntities = pDeferClippedOpaqueRenderables->Base();
  4936. for ( int i = 0; i < nCount; ++i )
  4937. {
  4938. CClientRenderablesList::CEntry *itEntity = ppEntities[i];
  4939. DrawOpaqueRenderable( itEntity->m_pRenderable, ( itEntity->m_TwoPass != 0 ), DepthMode );
  4940. }
  4941. }
  4942. }
  4943. //-----------------------------------------------------------------------------
  4944. // Renders all translucent world + detail objects in a particular set of leaves
  4945. //-----------------------------------------------------------------------------
  4946. void CRendering3dView::DrawTranslucentWorldInLeaves( IMatRenderContext *pRenderContext, bool bShadowDepth )
  4947. {
  4948. if ( bShadowDepth )
  4949. return;
  4950. VPROF_BUDGET( "CViewRender::DrawTranslucentWorldInLeaves", VPROF_BUDGETGROUP_WORLD_RENDERING );
  4951. #if defined(_PS3)
  4952. const ClientWorldListInfo_t& info = *m_pWorldListInfo[ g_viewBuilder.GetBuildViewID() ];
  4953. #else
  4954. const ClientWorldListInfo_t& info = *m_pWorldListInfo;
  4955. #endif
  4956. CUtlVectorFixedGrowable<int, 32> transSortIndexList;
  4957. for( int iCurLeafIndex = info.m_LeafCount - 1; iCurLeafIndex >= 0; iCurLeafIndex-- )
  4958. {
  4959. if ( info.m_pLeafDataList[iCurLeafIndex].translucentSurfaceCount )
  4960. {
  4961. int nActualLeafIndex = info.m_pOriginalLeafIndex ? info.m_pOriginalLeafIndex[ iCurLeafIndex ] : iCurLeafIndex;
  4962. Assert( nActualLeafIndex != INVALID_LEAF_INDEX );
  4963. transSortIndexList.AddToTail(nActualLeafIndex);
  4964. }
  4965. }
  4966. if ( transSortIndexList.Count() )
  4967. {
  4968. // Now draw the surfaces in this leaf
  4969. render->DrawTranslucentSurfaces( pRenderContext, m_pWorldRenderList, transSortIndexList.Base(), transSortIndexList.Count(), m_DrawFlags );
  4970. }
  4971. }
  4972. //-----------------------------------------------------------------------------
  4973. // Renders all translucent world + detail objects in a particular set of leaves
  4974. //-----------------------------------------------------------------------------
  4975. void CRendering3dView::DrawTranslucentWorldAndDetailPropsInLeaves( IMatRenderContext *pRenderContext, int iCurLeafIndex, int iFinalLeafIndex, int nEngineDrawFlags, int &nDetailLeafCount, LeafIndex_t* pDetailLeafList, bool bShadowDepth )
  4976. {
  4977. if ( bShadowDepth )
  4978. return;
  4979. CUtlVectorFixedGrowable<int, 32> transSortIndexList;
  4980. VPROF_BUDGET( "CViewRender::DrawTranslucentWorldAndDetailPropsInLeaves", VPROF_BUDGETGROUP_WORLD_RENDERING );
  4981. #if defined(_PS3)
  4982. const ClientWorldListInfo_t& info = *m_pWorldListInfo[ g_viewBuilder.GetBuildViewID() ];
  4983. CClientRenderablesList *pRenderablesList = m_pRenderablesList[ g_viewBuilder.GetBuildViewID() ];
  4984. #else
  4985. const ClientWorldListInfo_t& info = *m_pWorldListInfo;
  4986. CClientRenderablesList *pRenderablesList = m_pRenderables;
  4987. #endif
  4988. for( ; iCurLeafIndex >= iFinalLeafIndex; iCurLeafIndex-- )
  4989. {
  4990. if ( info.m_pLeafDataList[iCurLeafIndex].translucentSurfaceCount )
  4991. {
  4992. int nActualLeafIndex = info.m_pOriginalLeafIndex ? info.m_pOriginalLeafIndex[ iCurLeafIndex ] : iCurLeafIndex;
  4993. Assert( nActualLeafIndex != INVALID_LEAF_INDEX );
  4994. // First draw any queued-up detail props from previously visited leaves
  4995. if ( nDetailLeafCount )
  4996. {
  4997. DetailObjectSystem()->RenderTranslucentDetailObjects( pRenderablesList->m_DetailFade, CurrentViewOrigin(), CurrentViewForward(), CurrentViewRight(), CurrentViewUp(), nDetailLeafCount, pDetailLeafList );
  4998. nDetailLeafCount = 0;
  4999. }
  5000. transSortIndexList.AddToTail(nActualLeafIndex);
  5001. }
  5002. // Queue up detail props that existed in this leaf
  5003. if ( ClientLeafSystem()->ShouldDrawDetailObjectsInLeaf( info.m_pLeafDataList[iCurLeafIndex].leafIndex, m_pMainView->BuildWorldListsNumber() ) )
  5004. {
  5005. if ( transSortIndexList.Count() )
  5006. {
  5007. // Now draw the surfaces in this leaf
  5008. render->DrawTranslucentSurfaces( pRenderContext, m_pWorldRenderList, transSortIndexList.Base(), transSortIndexList.Count(), nEngineDrawFlags );
  5009. }
  5010. pDetailLeafList[nDetailLeafCount] = info.m_pLeafDataList[iCurLeafIndex].leafIndex;
  5011. ++nDetailLeafCount;
  5012. }
  5013. }
  5014. if ( transSortIndexList.Count() )
  5015. {
  5016. // Now draw the surfaces in this leaf
  5017. render->DrawTranslucentSurfaces( pRenderContext, m_pWorldRenderList, transSortIndexList.Base(), transSortIndexList.Count(), nEngineDrawFlags );
  5018. }
  5019. }
  5020. //-----------------------------------------------------------------------------
  5021. // Renders all translucent entities in the render list
  5022. //-----------------------------------------------------------------------------
  5023. static inline void DrawTranslucentRenderable( IClientRenderable *pEnt, const RenderableInstance_t &instance, bool twoPass, bool bShadowDepth )
  5024. {
  5025. ASSERT_LOCAL_PLAYER_RESOLVABLE();
  5026. #ifdef PORTAL
  5027. Assert( ( g_pPortalRender->GetViewRecursionLevel() > 0 ) || !IsSplitScreenSupported() || pEnt->ShouldDrawForSplitScreenUser( GET_ACTIVE_SPLITSCREEN_SLOT() ) );
  5028. #else
  5029. Assert( !IsSplitScreenSupported() || pEnt->ShouldDrawForSplitScreenUser( GET_ACTIVE_SPLITSCREEN_SLOT() ) );
  5030. #endif
  5031. // Renderable list building should already have caught this
  5032. Assert( instance.m_nAlpha > 0 );
  5033. // Determine blending amount and tell engine
  5034. float blend = (float)( instance.m_nAlpha / 255.0f );
  5035. // Tell engine
  5036. render->SetBlend( blend );
  5037. float color[3];
  5038. pEnt->GetColorModulation( color );
  5039. render->SetColorModulation( color );
  5040. int flags = STUDIO_RENDER | STUDIO_TRANSPARENCY;
  5041. if ( twoPass )
  5042. flags |= STUDIO_TWOPASS;
  5043. if ( bShadowDepth )
  5044. flags |= STUDIO_SHADOWDEPTHTEXTURE;
  5045. DrawRenderable( pEnt, flags, instance, bShadowDepth );
  5046. }
  5047. //-----------------------------------------------------------------------------
  5048. // Renders all translucent entities in the render list
  5049. //-----------------------------------------------------------------------------
  5050. void CRendering3dView::DrawTranslucentRenderablesNoWorld( bool bInSkybox )
  5051. {
  5052. VPROF( "CViewRender::DrawTranslucentRenderablesNoWorld" );
  5053. if ( !m_pMainView->ShouldDrawEntities() || !r_drawtranslucentrenderables.GetBool() )
  5054. return;
  5055. // Draw the particle singletons.
  5056. DrawParticleSingletons( bInSkybox );
  5057. bool bShadowDepth = (m_DrawFlags & DF_SHADOW_DEPTH_MAP ) != 0;
  5058. #if defined(_PS3)
  5059. CClientRenderablesList::CEntry *pEntities = m_pRenderablesList[ g_viewBuilder.GetBuildViewID() ]->m_RenderGroups[RENDER_GROUP_TRANSLUCENT];
  5060. int iCurTranslucentEntity = m_pRenderablesList[ g_viewBuilder.GetBuildViewID() ]->m_RenderGroupCounts[RENDER_GROUP_TRANSLUCENT] - 1;
  5061. #else
  5062. CClientRenderablesList::CEntry *pEntities = m_pRenderables->m_RenderGroups[RENDER_GROUP_TRANSLUCENT];
  5063. int iCurTranslucentEntity = m_pRenderables->m_RenderGroupCounts[RENDER_GROUP_TRANSLUCENT] - 1;
  5064. #endif
  5065. while( iCurTranslucentEntity >= 0 )
  5066. {
  5067. IClientRenderable *pRenderable = pEntities[iCurTranslucentEntity].m_pRenderable;
  5068. int nRenderFlags = pRenderable->GetRenderFlags();
  5069. if ( nRenderFlags & ERENDERFLAGS_NEEDS_POWER_OF_TWO_FB )
  5070. {
  5071. UpdateRefractTexture();
  5072. }
  5073. if ( nRenderFlags & ERENDERFLAGS_NEEDS_FULL_FB )
  5074. {
  5075. UpdateScreenEffectTexture();
  5076. }
  5077. DrawTranslucentRenderable( pRenderable, pEntities[iCurTranslucentEntity].m_InstanceData,
  5078. pEntities[iCurTranslucentEntity].m_TwoPass != 0, bShadowDepth );
  5079. --iCurTranslucentEntity;
  5080. }
  5081. // Reset the blend state.
  5082. render->SetBlend( 1 );
  5083. }
  5084. //-----------------------------------------------------------------------------
  5085. // Renders all translucent entities in the render list that ignore the Z buffer
  5086. //-----------------------------------------------------------------------------
  5087. void CRendering3dView::DrawNoZBufferTranslucentRenderables( void )
  5088. {
  5089. VPROF( "CViewRender::DrawNoZBufferTranslucentRenderables" );
  5090. if ( !m_pMainView->ShouldDrawEntities() || !r_drawtranslucentrenderables.GetBool() )
  5091. return;
  5092. bool bShadowDepth = (m_DrawFlags & DF_SHADOW_DEPTH_MAP ) != 0;
  5093. // FIXME: This ignores Z. We don't need to sort it at all? Not sure about refraction here...
  5094. // Could use fast path
  5095. #if defined(_PS3)
  5096. CClientRenderablesList::CEntry *pEntities = m_pRenderablesList[ g_viewBuilder.GetBuildViewID() ]->m_RenderGroups[RENDER_GROUP_TRANSLUCENT_IGNOREZ];
  5097. int iCurTranslucentEntity = m_pRenderablesList[ g_viewBuilder.GetBuildViewID() ]->m_RenderGroupCounts[RENDER_GROUP_TRANSLUCENT_IGNOREZ] - 1;
  5098. #else
  5099. CClientRenderablesList::CEntry *pEntities = m_pRenderables->m_RenderGroups[RENDER_GROUP_TRANSLUCENT_IGNOREZ];
  5100. int iCurTranslucentEntity = m_pRenderables->m_RenderGroupCounts[RENDER_GROUP_TRANSLUCENT_IGNOREZ] - 1;
  5101. #endif
  5102. while( iCurTranslucentEntity >= 0 )
  5103. {
  5104. IClientRenderable *pRenderable = pEntities[iCurTranslucentEntity].m_pRenderable;
  5105. int nRenderFlags = pRenderable->GetRenderFlags();
  5106. if ( nRenderFlags & ERENDERFLAGS_NEEDS_POWER_OF_TWO_FB )
  5107. {
  5108. UpdateRefractTexture();
  5109. }
  5110. if ( nRenderFlags & ERENDERFLAGS_NEEDS_FULL_FB )
  5111. {
  5112. UpdateScreenEffectTexture();
  5113. }
  5114. DrawTranslucentRenderable( pRenderable, pEntities[iCurTranslucentEntity].m_InstanceData,
  5115. pEntities[iCurTranslucentEntity].m_TwoPass != 0, bShadowDepth );
  5116. --iCurTranslucentEntity;
  5117. }
  5118. // Reset the blend state.
  5119. render->SetBlend( 1 );
  5120. }
  5121. static ConVar r_unlimitedrefract( "r_unlimitedrefract", "0" );
  5122. static void UpdateNecessaryRenderTargets( int nRenderFlags )
  5123. {
  5124. if ( nRenderFlags )
  5125. {
  5126. CMatRenderContextPtr pRenderContext( materials );
  5127. ITexture *rt = pRenderContext->GetRenderTarget();
  5128. // supress refract update
  5129. if (
  5130. ( nRenderFlags & ERENDERFLAGS_REFRACT_ONLY_ONCE_PER_FRAME ) &&
  5131. ( nRenderFlags & ERENDERFLAGS_NEEDS_POWER_OF_TWO_FB ) &&
  5132. ( gpGlobals->framecount == g_viewscene_refractUpdateFrame ) &&
  5133. ( r_unlimitedrefract.GetInt() == 0 ) )
  5134. {
  5135. nRenderFlags &= ~( ERENDERFLAGS_NEEDS_POWER_OF_TWO_FB );
  5136. }
  5137. if ( rt )
  5138. {
  5139. if ( nRenderFlags & ERENDERFLAGS_NEEDS_FULL_FB )
  5140. {
  5141. UpdateScreenEffectTexture( 0, 0, 0, rt->GetActualWidth(), rt->GetActualHeight(), true );
  5142. }
  5143. else if ( nRenderFlags & ERENDERFLAGS_NEEDS_POWER_OF_TWO_FB )
  5144. {
  5145. UpdateRefractTexture(0, 0, rt->GetActualWidth(), rt->GetActualHeight());
  5146. }
  5147. }
  5148. else
  5149. {
  5150. if ( nRenderFlags & ERENDERFLAGS_NEEDS_POWER_OF_TWO_FB )
  5151. {
  5152. UpdateRefractTexture();
  5153. }
  5154. }
  5155. pRenderContext.SafeRelease();
  5156. }
  5157. }
  5158. #ifdef PORTAL //if we're in the portal mod, we need to make a detour so we can render portal views using stencil areas
  5159. void CRendering3dView::DrawRecursivePortalViews( void )
  5160. {
  5161. if( ShouldDrawPortals() ) //no recursive stencil views during skybox rendering (although we might be drawing a skybox while already in a recursive stencil view)
  5162. {
  5163. int iDrawFlagsBackup = m_DrawFlags;
  5164. if( g_pPortalRender->DrawPortalsUsingStencils( (CViewRender *)m_pMainView ) )// @MULTICORE (toml 8/10/2006): remove this hack cast
  5165. {
  5166. m_DrawFlags = iDrawFlagsBackup;
  5167. //reset visibility
  5168. unsigned int iVisFlags = 0;
  5169. m_pMainView->SetupVis( *this, iVisFlags, m_pCustomVisibility );
  5170. //recreate drawlists (since I can't find an easy way to backup the originals)
  5171. {
  5172. SafeRelease( m_pWorldRenderList );
  5173. SafeRelease( m_pWorldListInfo );
  5174. BuildWorldRenderLists( ((m_DrawFlags & DF_DRAW_ENTITITES) != 0), m_pCustomVisibility ? m_pCustomVisibility->m_iForceViewLeaf : -1 );
  5175. AssertMsg( m_DrawFlags & DF_DRAW_ENTITITES, "It shouldn't be possible to get here if this wasn't set, needs special case investigation" );
  5176. }
  5177. if( r_depthoverlay.GetBool() )
  5178. {
  5179. CMatRenderContextPtr pRenderContext( materials );
  5180. ITexture *pDepthTex = GetFullFrameDepthTexture();
  5181. if ( pDepthTex )
  5182. {
  5183. IMaterial *pMaterial = materials->FindMaterial( "debug/showz", TEXTURE_GROUP_OTHER, true );
  5184. IMaterialVar *BaseTextureVar = pMaterial->FindVar( "$basetexture", NULL, false );
  5185. IMaterialVar *pDepthInAlpha = NULL;
  5186. if( IsPC() )
  5187. {
  5188. pDepthInAlpha = pMaterial->FindVar( "$ALPHADEPTH", NULL, false );
  5189. pDepthInAlpha->SetIntValue( 1 );
  5190. }
  5191. BaseTextureVar->SetTextureValue( pDepthTex );
  5192. pRenderContext->OverrideDepthEnable( true, false ); //don't write to depth, or else we'll never see translucents
  5193. pRenderContext->DrawScreenSpaceQuad( pMaterial );
  5194. pRenderContext->OverrideDepthEnable( false, true );
  5195. }
  5196. }
  5197. }
  5198. // PS3 reads directly from the depth buffer alias texture, so we don't need to update the full-screen depth texture.
  5199. else if ( !IsPS3() )
  5200. {
  5201. //done recursing in, time to go back out and do translucents
  5202. CMatRenderContextPtr pRenderContext( materials );
  5203. UpdateFullScreenDepthTexture();
  5204. }
  5205. }
  5206. }
  5207. #endif
  5208. //-----------------------------------------------------------------------------
  5209. // Renders all translucent world, entities, and detail objects in a particular set of leaves
  5210. //-----------------------------------------------------------------------------
  5211. //$TODO(msmith) This "fast path" (cl_tlucfastpath) doesn't currently work on css15. Alpha sorting is messed up.
  5212. // Investingation should be made as to why it's broken before turning it back on by default. And we should only look to turn
  5213. // it on if when we do turn it on there is a performance win (on PS3 and Xbox360).
  5214. ConVar cl_tlucfastpath( "cl_tlucfastpath", "1" );
  5215. extern ConVar cl_colorfastpath;
  5216. void CRendering3dView::DrawTranslucentRenderables( bool bInSkybox, bool bShadowDepth )
  5217. {
  5218. #if !defined( PORTAL )
  5219. {
  5220. //opaques generally write depth, and translucents generally don't.
  5221. //So immediately after opaques are done is the best time to snap off the depth buffer to a texture.
  5222. switch ( g_CurrentViewID )
  5223. {
  5224. case VIEW_MAIN:
  5225. #ifdef _GAMECONSOLE
  5226. case VIEW_INTRO_CAMERA:
  5227. case VIEW_INTRO_PLAYER:
  5228. #endif
  5229. UpdateFullScreenDepthTexture();
  5230. break;
  5231. default:
  5232. materials->GetRenderContext()->SetFullScreenDepthTextureValidityFlag( false );
  5233. break;
  5234. }
  5235. }
  5236. #endif
  5237. CMatRenderContextPtr pRenderContext( materials );
  5238. PIXEVENT( pRenderContext, "DrawTranslucent" );
  5239. #if defined(_PS3)
  5240. const ClientWorldListInfo_t& info = *m_pWorldListInfo[ g_viewBuilder.GetBuildViewID() ];
  5241. #else
  5242. const ClientWorldListInfo_t& info = *m_pWorldListInfo;
  5243. #endif
  5244. if ( !r_drawtranslucentworld.GetBool() || ( m_DrawFlags & ( DF_DRAW_SIMPLE_WORLD_MODEL | DF_DRAW_SIMPLE_WORLD_MODEL_WATER ) ) )
  5245. {
  5246. DrawTranslucentRenderablesNoWorld( bInSkybox );
  5247. return;
  5248. }
  5249. int iPrevLeaf = info.m_LeafCount - 1;
  5250. int nDetailLeafCount = 0;
  5251. LeafIndex_t *pDetailLeafList = (LeafIndex_t*)stackalloc( info.m_LeafCount * sizeof(LeafIndex_t) );
  5252. // bool bDrawUnderWater = (nFlags & DF_RENDER_UNDERWATER) != 0;
  5253. // bool bDrawAboveWater = (nFlags & DF_RENDER_ABOVEWATER) != 0;
  5254. // bool bDrawWater = (nFlags & DF_RENDER_WATER) != 0;
  5255. // bool bClipSkybox = (nFlags & DF_CLIP_SKYBOX ) != 0;
  5256. unsigned long nEngineDrawFlags = BuildEngineDrawWorldListFlags( m_DrawFlags & ~DF_DRAWSKYBOX );
  5257. DetailObjectSystem()->BeginTranslucentDetailRendering();
  5258. if ( m_pMainView->ShouldDrawEntities() && r_drawtranslucentrenderables.GetBool() )
  5259. {
  5260. VPROF_BUDGET( "DrawTranslucentEntities", "DrawTranslucentEntities" );
  5261. MDLCACHE_CRITICAL_SECTION();
  5262. // Draw the particle singletons.
  5263. DrawParticleSingletons( bInSkybox );
  5264. #if defined(_PS3)
  5265. int nTranslucentRenderableCount = m_pRenderablesList[ g_viewBuilder.GetBuildViewID() ]->m_RenderGroupCounts[RENDER_GROUP_TRANSLUCENT];
  5266. CClientRenderablesList::CEntry *pEntities = m_pRenderablesList[ g_viewBuilder.GetBuildViewID() ]->m_RenderGroups[RENDER_GROUP_TRANSLUCENT];
  5267. #else
  5268. int nTranslucentRenderableCount = m_pRenderables->m_RenderGroupCounts[RENDER_GROUP_TRANSLUCENT];
  5269. CClientRenderablesList::CEntry *pEntities = m_pRenderables->m_RenderGroups[RENDER_GROUP_TRANSLUCENT];
  5270. #endif
  5271. int iCurTranslucentEntity = nTranslucentRenderableCount - 1;
  5272. int *pFastPathIndex = (int*)stackalloc( nTranslucentRenderableCount * sizeof( int ) );
  5273. CUtlVector< ModelRenderSystemData_t > fastPathData( (ModelRenderSystemData_t *)stackalloc( nTranslucentRenderableCount * sizeof( ModelRenderSystemData_t ) ), nTranslucentRenderableCount );
  5274. TranslucentInstanceRenderData_t *pRenderData = (TranslucentInstanceRenderData_t*)stackalloc( nTranslucentRenderableCount * sizeof( TranslucentInstanceRenderData_t ) );
  5275. TranslucentTempData_t tempData;
  5276. tempData.m_pColorMeshHandles = ( DataCacheHandle_t * )stackalloc( nTranslucentRenderableCount * sizeof( DataCacheHandle_t ) );
  5277. bool bDoFastPath = cl_tlucfastpath.GetBool();
  5278. bool bColorizeFastPath = cl_colorfastpath.GetBool();
  5279. IMaterial *pFastPathColorMaterial = g_pModelRenderSystem->GetFastPathColorMaterial();
  5280. if ( bDoFastPath )
  5281. {
  5282. for ( int i = 0; i < nTranslucentRenderableCount; ++i )
  5283. {
  5284. Assert( pEntities[i].m_pRenderable );
  5285. IClientRenderable *pRenderable = pEntities[i].m_pRenderable;
  5286. IClientModelRenderable *pModelRenderable = pRenderable->GetClientModelRenderable();
  5287. // FIXME: Deal with brush models in the translucent path
  5288. if ( pModelRenderable && modelinfo->GetModelType( pRenderable->GetModel() ) == mod_studio )
  5289. {
  5290. int j = fastPathData.AddToTail( );
  5291. ModelRenderSystemData_t &data = fastPathData[j];
  5292. data.m_pRenderable = pRenderable;
  5293. data.m_pModelRenderable = pModelRenderable;
  5294. data.m_InstanceData = pEntities[i].m_InstanceData;
  5295. pFastPathIndex[i] = j;
  5296. }
  5297. else
  5298. {
  5299. pFastPathIndex[i] = -1;
  5300. }
  5301. }
  5302. g_pModelRenderSystem->ComputeTranslucentRenderData( fastPathData.Base(), fastPathData.Count(), pRenderData, &tempData );
  5303. }
  5304. bool bRenderingWaterRenderTargets = ( m_DrawFlags & ( DF_RENDER_REFRACTION | DF_RENDER_REFLECTION ) ) ? true : false;
  5305. #if defined(_PS3)
  5306. CClientRenderablesList *pRenderablesList = m_pRenderablesList[ g_viewBuilder.GetBuildViewID() ];
  5307. #else
  5308. CClientRenderablesList *pRenderablesList = m_pRenderables;
  5309. #endif
  5310. while( iCurTranslucentEntity >= 0 )
  5311. {
  5312. // Seek the current leaf up to our current translucent-entity leaf.
  5313. int iThisLeaf = pEntities[iCurTranslucentEntity].m_iWorldListInfoLeaf;
  5314. // First draw the translucent parts of the world up to and including those in this leaf
  5315. DrawTranslucentWorldAndDetailPropsInLeaves( pRenderContext, iPrevLeaf, iThisLeaf, nEngineDrawFlags, nDetailLeafCount, pDetailLeafList, bShadowDepth );
  5316. // We're traversing the leaf list backwards to get the appropriate sort ordering (back to front)
  5317. iPrevLeaf = iThisLeaf - 1;
  5318. // Draw all the translucent entities with this leaf.
  5319. int nLeaf = info.m_pLeafDataList[iThisLeaf].leafIndex;
  5320. bool bDrawDetailProps = ClientLeafSystem()->ShouldDrawDetailObjectsInLeaf( nLeaf, m_pMainView->BuildWorldListsNumber() );
  5321. if ( bDrawDetailProps )
  5322. {
  5323. // Draw detail props up to but not including this leaf
  5324. Assert( nDetailLeafCount > 0 );
  5325. --nDetailLeafCount;
  5326. Assert( pDetailLeafList[nDetailLeafCount] == nLeaf );
  5327. DetailObjectSystem()->RenderTranslucentDetailObjects( pRenderablesList->m_DetailFade, CurrentViewOrigin(), CurrentViewForward(), CurrentViewRight(), CurrentViewUp(), nDetailLeafCount, pDetailLeafList );
  5328. // HACK: for now just draw all the detail props in this leaf right away. They're alphatest and write z, so there's no need to manually sort them.
  5329. DetailObjectSystem()->RenderTranslucentDetailObjectsInLeaf( pRenderablesList->m_DetailFade, CurrentViewOrigin(), CurrentViewForward(), CurrentViewRight(), CurrentViewUp(), nLeaf, NULL );
  5330. // Draw translucent renderables in the leaf interspersed with detail props
  5331. for( ;pEntities[iCurTranslucentEntity].m_iWorldListInfoLeaf == iThisLeaf && iCurTranslucentEntity >= 0; --iCurTranslucentEntity )
  5332. {
  5333. IClientRenderable *pRenderable = pEntities[iCurTranslucentEntity].m_pRenderable;
  5334. // Draw any detail props in this leaf that's farther than the entity
  5335. // HACK: for now don't do this, we already rendered all the detail props, and they should sort ok. See above comment.
  5336. //const Vector &vecRenderOrigin = pRenderable->GetRenderOrigin();
  5337. //DetailObjectSystem()->RenderTranslucentDetailObjectsInLeaf( pRenderablesList->m_DetailFade, CurrentViewOrigin(), CurrentViewForward(), CurrentViewRight(), CurrentViewUp(), nLeaf, &vecRenderOrigin );
  5338. int nRenderFlags = pRenderable->GetRenderFlags();
  5339. if ( ( nRenderFlags & ( ERENDERFLAGS_NEEDS_FULL_FB | ERENDERFLAGS_NEEDS_POWER_OF_TWO_FB ) ) && !bShadowDepth )
  5340. {
  5341. if( bRenderingWaterRenderTargets )
  5342. {
  5343. continue;
  5344. }
  5345. UpdateNecessaryRenderTargets( nRenderFlags );
  5346. }
  5347. // Then draw the translucent renderable
  5348. if ( bDoFastPath && pFastPathIndex[iCurTranslucentEntity] >= 0 )
  5349. {
  5350. if ( bColorizeFastPath )
  5351. {
  5352. g_pStudioRender->ForcedMaterialOverride( pFastPathColorMaterial );
  5353. }
  5354. TranslucentInstanceRenderData_t &renderData = pRenderData[ pFastPathIndex[iCurTranslucentEntity] ];
  5355. int nDrawFlags = pEntities[iCurTranslucentEntity].m_TwoPass ? STUDIORENDER_DRAW_TRANSLUCENT_ONLY : STUDIORENDER_DRAW_ENTIRE_MODEL;
  5356. g_pStudioRender->DrawModelArray( *renderData.m_pModelInfo, 1, renderData.m_pInstanceData, sizeof(StudioArrayInstanceData_t), nDrawFlags );
  5357. g_pStudioRender->ForcedMaterialOverride( NULL );
  5358. }
  5359. else
  5360. {
  5361. DrawTranslucentRenderable( pRenderable, pEntities[iCurTranslucentEntity].m_InstanceData,
  5362. (pEntities[iCurTranslucentEntity].m_TwoPass != 0), bShadowDepth );
  5363. }
  5364. }
  5365. // Draw all remaining props in this leaf
  5366. // HACK: for now don't do this, we already rendered all the detail props, and they should sort ok. See above comment.
  5367. //DetailObjectSystem()->RenderTranslucentDetailObjectsInLeaf( pRenderablesList->m_DetailFade, CurrentViewOrigin(), CurrentViewForward(), CurrentViewRight(), CurrentViewUp(), nLeaf, NULL );
  5368. }
  5369. else
  5370. {
  5371. // Draw queued up detail props (we know that the list of detail leaves won't include this leaf, since ShouldDrawDetailObjectsInLeaf is false)
  5372. // Therefore no fixup on nDetailLeafCount is required as in the above section
  5373. DetailObjectSystem()->RenderTranslucentDetailObjects( pRenderablesList->m_DetailFade, CurrentViewOrigin(), CurrentViewForward(), CurrentViewRight(), CurrentViewUp(), nDetailLeafCount, pDetailLeafList );
  5374. for( ;pEntities[iCurTranslucentEntity].m_iWorldListInfoLeaf == iThisLeaf && iCurTranslucentEntity >= 0; --iCurTranslucentEntity )
  5375. {
  5376. IClientRenderable *pRenderable = pEntities[iCurTranslucentEntity].m_pRenderable;
  5377. int nRenderFlags = pRenderable->GetRenderFlags();
  5378. if ( ( nRenderFlags & ( ERENDERFLAGS_NEEDS_POWER_OF_TWO_FB | ERENDERFLAGS_NEEDS_FULL_FB ) ) && !bShadowDepth )
  5379. {
  5380. if( bRenderingWaterRenderTargets )
  5381. {
  5382. continue;
  5383. }
  5384. UpdateNecessaryRenderTargets( nRenderFlags );
  5385. }
  5386. if ( bDoFastPath && pFastPathIndex[iCurTranslucentEntity] >= 0 )
  5387. {
  5388. TranslucentInstanceRenderData_t &renderData = pRenderData[ pFastPathIndex[iCurTranslucentEntity] ];
  5389. if ( renderData.m_pInstanceData )
  5390. {
  5391. if (bColorizeFastPath)
  5392. {
  5393. g_pStudioRender->ForcedMaterialOverride( pFastPathColorMaterial );
  5394. }
  5395. int nDrawFlags = pEntities[iCurTranslucentEntity].m_TwoPass ? STUDIORENDER_DRAW_TRANSLUCENT_ONLY : STUDIORENDER_DRAW_ENTIRE_MODEL;
  5396. g_pStudioRender->DrawModelArray( *renderData.m_pModelInfo, 1, renderData.m_pInstanceData, sizeof(StudioArrayInstanceData_t), nDrawFlags );
  5397. g_pStudioRender->ForcedMaterialOverride( NULL );
  5398. }
  5399. }
  5400. else
  5401. {
  5402. DrawTranslucentRenderable( pRenderable, pEntities[iCurTranslucentEntity].m_InstanceData,
  5403. (pEntities[iCurTranslucentEntity].m_TwoPass != 0), bShadowDepth );
  5404. }
  5405. }
  5406. }
  5407. nDetailLeafCount = 0;
  5408. }
  5409. if ( bDoFastPath )
  5410. {
  5411. g_pModelRenderSystem->CleanupTranslucentTempData( &tempData );
  5412. }
  5413. }
  5414. // Draw the rest of the surfaces in world leaves
  5415. DrawTranslucentWorldAndDetailPropsInLeaves( pRenderContext, iPrevLeaf, 0, nEngineDrawFlags, nDetailLeafCount, pDetailLeafList, bShadowDepth );
  5416. // Draw any queued-up detail props from previously visited leaves
  5417. #if defined(_PS3)
  5418. DetailObjectSystem()->RenderTranslucentDetailObjects( m_pRenderablesList[ g_viewBuilder.GetBuildViewID() ]->m_DetailFade, CurrentViewOrigin(), CurrentViewForward(), CurrentViewRight(), CurrentViewUp(), nDetailLeafCount, pDetailLeafList );
  5419. #else
  5420. DetailObjectSystem()->RenderTranslucentDetailObjects( m_pRenderables->m_DetailFade, CurrentViewOrigin(), CurrentViewForward(), CurrentViewRight(), CurrentViewUp(), nDetailLeafCount, pDetailLeafList );
  5421. #endif
  5422. // Reset the blend state.
  5423. render->SetBlend( 1 );
  5424. }
  5425. //-----------------------------------------------------------------------------
  5426. //
  5427. //-----------------------------------------------------------------------------
  5428. void CRendering3dView::EnableWorldFog( void )
  5429. {
  5430. VPROF("CViewRender::EnableWorldFog");
  5431. CMatRenderContextPtr pRenderContext( materials );
  5432. fogparams_t *pFogParams = NULL;
  5433. C_BasePlayer *pbp = C_BasePlayer::GetLocalPlayer();
  5434. if ( pbp )
  5435. {
  5436. pFogParams = pbp->GetFogParams();
  5437. }
  5438. if( GetFogEnable( pFogParams ) )
  5439. {
  5440. float fogColor[3];
  5441. GetFogColor( pFogParams, fogColor );
  5442. pRenderContext->FogMode( MATERIAL_FOG_LINEAR );
  5443. pRenderContext->FogColor3fv( fogColor );
  5444. pRenderContext->FogStart( GetFogStart( pFogParams ) );
  5445. pRenderContext->FogEnd( GetFogEnd( pFogParams ) );
  5446. pRenderContext->FogMaxDensity( GetFogMaxDensity( pFogParams ) );
  5447. }
  5448. else
  5449. {
  5450. pRenderContext->FogMode( MATERIAL_FOG_NONE );
  5451. }
  5452. }
  5453. //-----------------------------------------------------------------------------
  5454. //
  5455. //-----------------------------------------------------------------------------
  5456. int CRendering3dView::GetDrawFlags()
  5457. {
  5458. return m_DrawFlags;
  5459. }
  5460. //-----------------------------------------------------------------------------
  5461. //
  5462. //-----------------------------------------------------------------------------
  5463. void CRendering3dView::SetFogVolumeState( const VisibleFogVolumeInfo_t &fogInfo, bool bUseHeightFog )
  5464. {
  5465. render->SetFogVolumeState( fogInfo.m_nVisibleFogVolume, bUseHeightFog );
  5466. #ifdef PORTAL
  5467. //the idea behind fog shifting is this...
  5468. //Normal fog simulates the effect of countless tiny particles between your viewpoint and whatever geometry is rendering.
  5469. //But, when rendering to a portal view, there's a large space between the virtual camera and the portal exit surface.
  5470. //This space isn't supposed to exist, and therefore has none of the tiny particles that make up fog.
  5471. //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
  5472. if( g_pPortalRender->GetViewRecursionLevel() == 0 )
  5473. return; //rendering one of the primary views, do nothing
  5474. g_pPortalRender->ShiftFogForExitPortalView();
  5475. #endif //#ifdef PORTAL
  5476. }
  5477. //-----------------------------------------------------------------------------
  5478. // Standard 3d skybox view
  5479. //-----------------------------------------------------------------------------
  5480. SkyboxVisibility_t CSkyboxView::ComputeSkyboxVisibility()
  5481. {
  5482. return engine->IsSkyboxVisibleFromPoint( origin );
  5483. }
  5484. //-----------------------------------------------------------------------------
  5485. //
  5486. //-----------------------------------------------------------------------------
  5487. bool CSkyboxView::GetSkyboxFogEnable()
  5488. {
  5489. C_BasePlayer *pbp = C_BasePlayer::GetLocalPlayer();
  5490. if( !pbp )
  5491. {
  5492. return false;
  5493. }
  5494. CPlayerLocalData *local = &pbp->m_Local;
  5495. if( fog_override.GetInt() )
  5496. {
  5497. if( fog_enableskybox.GetInt() )
  5498. {
  5499. return true;
  5500. }
  5501. else
  5502. {
  5503. return false;
  5504. }
  5505. }
  5506. else
  5507. {
  5508. return !!local->m_skybox3d.fog.enable;
  5509. }
  5510. }
  5511. //-----------------------------------------------------------------------------
  5512. //
  5513. //-----------------------------------------------------------------------------
  5514. void CSkyboxView::Enable3dSkyboxFog( void )
  5515. {
  5516. C_BasePlayer *pbp = C_BasePlayer::GetLocalPlayer();
  5517. if( !pbp )
  5518. {
  5519. return;
  5520. }
  5521. CPlayerLocalData *local = &pbp->m_Local;
  5522. CMatRenderContextPtr pRenderContext( materials );
  5523. if( GetSkyboxFogEnable() )
  5524. {
  5525. float fogColor[3];
  5526. GetSkyboxFogColor( fogColor );
  5527. float scale = 1.0f;
  5528. if ( local->m_skybox3d.scale > 0.0f )
  5529. {
  5530. scale = 1.0f / local->m_skybox3d.scale;
  5531. }
  5532. pRenderContext->FogMode( MATERIAL_FOG_LINEAR );
  5533. pRenderContext->FogColor3fv( fogColor );
  5534. pRenderContext->FogStart( GetSkyboxFogStart() * scale );
  5535. pRenderContext->FogEnd( GetSkyboxFogEnd() * scale );
  5536. pRenderContext->FogMaxDensity( GetSkyboxFogMaxDensity() );
  5537. }
  5538. else
  5539. {
  5540. pRenderContext->FogMode( MATERIAL_FOG_NONE );
  5541. }
  5542. }
  5543. //-----------------------------------------------------------------------------
  5544. //
  5545. //-----------------------------------------------------------------------------
  5546. sky3dparams_t *CSkyboxView::PreRender3dSkyboxWorld( SkyboxVisibility_t nSkyboxVisible )
  5547. {
  5548. if ( ( nSkyboxVisible != SKYBOX_3DSKYBOX_VISIBLE ) && r_3dsky.GetInt() != 2 )
  5549. return NULL;
  5550. // render the 3D skybox
  5551. if ( !r_3dsky.GetInt() )
  5552. return NULL;
  5553. C_BasePlayer *pbp = C_BasePlayer::GetLocalPlayer();
  5554. // No local player object yet...
  5555. if ( !pbp )
  5556. return NULL;
  5557. CPlayerLocalData* local = &pbp->m_Local;
  5558. if ( local->m_skybox3d.area == 255 )
  5559. return NULL;
  5560. return &local->m_skybox3d;
  5561. }
  5562. //-----------------------------------------------------------------------------
  5563. //
  5564. //-----------------------------------------------------------------------------
  5565. void CSkyboxView::DrawInternal( view_id_t iSkyBoxViewID, bool bInvokePreAndPostRender, ITexture *pRenderTarget )
  5566. {
  5567. PS3_SPUPATH_INVALID( "CSkyboxView::DrawInternal" );
  5568. unsigned char **areabits = render->GetAreaBits();
  5569. unsigned char *savebits;
  5570. unsigned char tmpbits[ 32 ];
  5571. savebits = *areabits;
  5572. memset( tmpbits, 0, sizeof(tmpbits) );
  5573. // set the sky area bit
  5574. tmpbits[m_pSky3dParams->area>>3] |= 1 << (m_pSky3dParams->area&7);
  5575. *areabits = tmpbits;
  5576. // if you can get really close to the skybox geometry it's possible that you'll be able to clip into it
  5577. // with this near plane. If so, move it in a bit. It's at 2.0 to give us more precision. That means you
  5578. // need to keep the eye position at least 2 * scale away from the geometry in the skybox
  5579. zNear = 2.0;
  5580. zFar = MAX_TRACE_LENGTH;
  5581. // scale origin by sky scale and translate to sky origin
  5582. {
  5583. float scale = (m_pSky3dParams->scale > 0) ? (1.0f / m_pSky3dParams->scale) : 1.0f;
  5584. Vector vSkyOrigin = m_pSky3dParams->origin;
  5585. VectorScale( origin, scale, origin );
  5586. VectorAdd( origin, vSkyOrigin, origin );
  5587. if( m_bCustomViewMatrix )
  5588. {
  5589. Vector vTransformedSkyOrigin;
  5590. VectorRotate( vSkyOrigin, m_matCustomViewMatrix, vTransformedSkyOrigin ); //Rotate instead of transform because we haven't scale the existing offset yet
  5591. //scale existing translation, and tack on the skybox offset (subtract because it's a view matrix)
  5592. m_matCustomViewMatrix.m_flMatVal[0][3] = (m_matCustomViewMatrix.m_flMatVal[0][3] * scale) - vTransformedSkyOrigin.x;
  5593. m_matCustomViewMatrix.m_flMatVal[1][3] = (m_matCustomViewMatrix.m_flMatVal[1][3] * scale) - vTransformedSkyOrigin.y;
  5594. m_matCustomViewMatrix.m_flMatVal[2][3] = (m_matCustomViewMatrix.m_flMatVal[2][3] * scale) - vTransformedSkyOrigin.z;
  5595. }
  5596. }
  5597. Enable3dSkyboxFog();
  5598. // BUGBUG: Fix this!!! We shouldn't need to call setup vis for the sky if we're connecting
  5599. // the areas. We'd have to mark all the clusters in the skybox area in the PVS of any
  5600. // cluster with sky. Then we could just connect the areas to do our vis.
  5601. //m_bOverrideVisOrigin could hose us here, so call direct
  5602. render->ViewSetupVis( false, 1, &m_pSky3dParams->origin.Get() );
  5603. CMatRenderContextPtr pRenderContext( materials );
  5604. render->Push3DView( pRenderContext, (*this), m_ClearFlags, pRenderTarget, GetFrustum() );
  5605. // For stereo rendering, we need to set the stereo depth by scaling the full matrix by the scale of the 3d skybox
  5606. if ( materials->IsStereoActiveThisFrame() )
  5607. {
  5608. pRenderContext->MatrixMode( MATERIAL_VIEW );
  5609. VMatrix matStereoScale;
  5610. matStereoScale.Identity();
  5611. float flScale = ( m_pSky3dParams->scale > 0 ) ? ( m_pSky3dParams->scale ) : 1.0f;
  5612. for ( int i = 0; i < 4; i++ ) // Yes, I am setting the entire diagonal on purpose to hint to nvidia's driver the intended stereo depth
  5613. {
  5614. matStereoScale.m[i][i] = flScale;
  5615. }
  5616. pRenderContext->MultMatrix( matStereoScale );
  5617. pRenderContext->MatrixMode( MATERIAL_MODEL );
  5618. }
  5619. // Store off view origin and angles
  5620. SetupCurrentView( origin, angles, iSkyBoxViewID );
  5621. #if defined( _X360 )
  5622. pRenderContext->PushVertexShaderGPRAllocation( 32 );
  5623. #endif
  5624. // Invoke pre-render methods
  5625. if ( bInvokePreAndPostRender )
  5626. {
  5627. IGameSystem::PreRenderAllSystems();
  5628. }
  5629. BEGIN_2PASS_BUILD_BLOCK
  5630. PROLOGUE_PASS_DRAWLISTS
  5631. render->BeginUpdateLightmaps();
  5632. BuildWorldRenderLists( true, -1, true );
  5633. g_viewBuilder.FlushBuildWorldListJob();
  5634. BuildRenderableRenderLists( iSkyBoxViewID );
  5635. render->EndUpdateLightmaps();
  5636. END_2PASS_BLOCK
  5637. BEGIN_2PASS_DRAW_BLOCK
  5638. EPILOGUE_PASS_DRAWLISTS
  5639. DrawWorld( pRenderContext, 0.0f );
  5640. // Iterate over all leaves and render objects in those leaves
  5641. DrawOpaqueRenderables( pRenderContext, RENDERABLES_RENDER_PATH_NORMAL, DEPTH_MODE_NORMAL, NULL );
  5642. #if defined( PORTAL )
  5643. DrawRecursivePortalViews(); //Dave K: probably does nothing in this view, calling it anyway because it's contents were directly inside DrawTranslucentRenderables() a moment ago and I don't want to risk breaking anything
  5644. #endif
  5645. // Iterate over all leaves and render objects in those leaves
  5646. DrawTranslucentRenderables( true, false );
  5647. DrawNoZBufferTranslucentRenderables();
  5648. m_pMainView->DisableFog();
  5649. CGlowOverlay::UpdateSkyOverlays( zFar, m_bCacheFullSceneState );
  5650. PixelVisibility_EndCurrentView();
  5651. // restore old area bits
  5652. *areabits = savebits;
  5653. pRenderContext.SafeRelease();
  5654. // Invoke post-render methods
  5655. if( bInvokePreAndPostRender )
  5656. {
  5657. IGameSystem::PostRenderAllSystems();
  5658. FinishCurrentView();
  5659. }
  5660. // FIXME: Workaround to 3d skybox not depth-of-fielding properly. The real fix is for the 3d skybox dest alpha depth values
  5661. // to be biased. Currently all I do is clear alpha to 1 after the 3D skybox path. This avoids the skybox being unblurred.
  5662. if( IsDepthOfFieldEnabled() )
  5663. {
  5664. // draw a fullscreen quad setting destalpha to 1
  5665. IMaterial *pMat = materials->FindMaterial( "dev/clearalpha", TEXTURE_GROUP_OTHER, true );
  5666. if ( pMat != NULL )
  5667. {
  5668. int nWidth = 0;
  5669. int nHeight = 0;
  5670. int nDummy = 0;
  5671. CMatRenderContextPtr pRenderContext( materials );
  5672. pRenderContext->GetViewport( nDummy, nDummy, nWidth, nHeight );
  5673. pRenderContext->DrawScreenSpaceRectangle(
  5674. pMat,
  5675. 0, 0, nWidth, nHeight,
  5676. 0, 0, nWidth-1, nHeight-1,
  5677. nWidth, nHeight, NULL /*GetClientWorldEntity()->GetClientRenderable()*/ );
  5678. }
  5679. }
  5680. END_2PASS_BLOCK
  5681. pRenderContext.GetFrom( materials );
  5682. render->PopView( pRenderContext, GetFrustum() );
  5683. #if defined( _X360 )
  5684. pRenderContext->PopVertexShaderGPRAllocation();
  5685. #endif
  5686. }
  5687. //-----------------------------------------------------------------------------
  5688. //
  5689. //-----------------------------------------------------------------------------
  5690. bool CSkyboxView::Setup( const CViewSetup &view, int *pClearFlags, SkyboxVisibility_t *pSkyboxVisible )
  5691. {
  5692. BaseClass::Setup( view );
  5693. // The skybox might not be visible from here
  5694. *pSkyboxVisible = ComputeSkyboxVisibility();
  5695. m_pSky3dParams = PreRender3dSkyboxWorld( *pSkyboxVisible );
  5696. if ( !m_pSky3dParams )
  5697. {
  5698. return false;
  5699. }
  5700. // At this point, we've cleared everything we need to clear
  5701. // The next path will need to clear depth, though.
  5702. m_ClearFlags = *pClearFlags;
  5703. *pClearFlags &= ~( VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH | VIEW_CLEAR_STENCIL | VIEW_CLEAR_FULL_TARGET );
  5704. *pClearFlags |= VIEW_CLEAR_DEPTH; // Need to clear depth after rednering the skybox
  5705. m_DrawFlags = DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER | DF_RENDER_WATER;
  5706. if( r_skybox.GetBool() )
  5707. {
  5708. m_DrawFlags |= DF_DRAWSKYBOX;
  5709. }
  5710. return true;
  5711. }
  5712. //-----------------------------------------------------------------------------
  5713. //
  5714. //-----------------------------------------------------------------------------
  5715. void CSkyboxView::Draw()
  5716. {
  5717. VPROF_BUDGET( "CViewRender::Draw3dSkyboxworld", "3D Skybox" );
  5718. DrawInternal();
  5719. }
  5720. #ifdef PORTAL
  5721. //-----------------------------------------------------------------------------
  5722. //
  5723. //-----------------------------------------------------------------------------
  5724. bool CPortalSkyboxView::Setup( const CViewSetup &view, int *pClearFlags, SkyboxVisibility_t *pSkyboxVisible, ITexture *pRenderTarget )
  5725. {
  5726. if ( !BaseClass::Setup( view, pClearFlags, pSkyboxVisible ) )
  5727. return false;
  5728. m_pRenderTarget = pRenderTarget;
  5729. return true;
  5730. }
  5731. //-----------------------------------------------------------------------------
  5732. //
  5733. //-----------------------------------------------------------------------------
  5734. SkyboxVisibility_t CPortalSkyboxView::ComputeSkyboxVisibility()
  5735. {
  5736. return g_pPortalRender->IsSkyboxVisibleFromExitPortal();
  5737. }
  5738. //-----------------------------------------------------------------------------
  5739. //
  5740. //-----------------------------------------------------------------------------
  5741. void CPortalSkyboxView::Draw()
  5742. {
  5743. AssertMsg( (g_pPortalRender->GetViewRecursionLevel() != 0) && g_pPortalRender->IsRenderingPortal(), "This is designed for through-portal views. Use the regular skybox drawing code for primary views" );
  5744. VPROF( "CViewRender::Draw3dSkyboxworld_Portal" );
  5745. int iCurrentViewID = g_CurrentViewID;
  5746. Frustum FrustumBackup;
  5747. memcpy( FrustumBackup, GetFrustum(), sizeof( Frustum ) );
  5748. CMatRenderContextPtr pRenderContext( materials );
  5749. bool bClippingEnabled = pRenderContext->EnableClipping( false );
  5750. //NOTE: doesn't magically map to VIEW_3DSKY at (0,0) like PORTAL_VIEWID maps to VIEW_MAIN
  5751. view_id_t iSkyBoxViewID = (view_id_t)g_pPortalRender->GetCurrentSkyboxViewId();
  5752. bool bInvokePreAndPostRender = false;
  5753. DrawInternal( iSkyBoxViewID, bInvokePreAndPostRender, m_pRenderTarget );
  5754. pRenderContext->ClearBuffersObeyStencil( false, true );
  5755. #ifdef _PS3
  5756. // Reload z-cull after 3D skybox render if in a portal view since we just re-cleared depth values
  5757. if ( g_pPortalRender->GetViewRecursionLevel() > 0 )
  5758. {
  5759. g_pPortalRender->ReloadZcullMemory();
  5760. }
  5761. #endif // _PS3
  5762. pRenderContext->EnableClipping( bClippingEnabled );
  5763. memcpy( GetFrustum(), FrustumBackup, sizeof( Frustum ) );
  5764. render->OverrideViewFrustum( FrustumBackup );
  5765. g_CurrentViewID = iCurrentViewID;
  5766. }
  5767. #endif // PORTAL
  5768. #ifdef PORTAL2
  5769. //-----------------------------------------------------------------------------
  5770. //
  5771. //-----------------------------------------------------------------------------
  5772. bool CAperturePhotoView::Setup( C_BaseEntity *pTargetEntity, const CViewSetup &view, int *pClearFlags, SkyboxVisibility_t *pSkyboxVisible, ITexture *pRenderTarget )
  5773. {
  5774. if( pTargetEntity == NULL )
  5775. return false;
  5776. IClientRenderable *pEntRenderable = pTargetEntity->GetClientRenderable();
  5777. if( pEntRenderable == NULL )
  5778. return false;
  5779. m_pTargetEntity = pTargetEntity;
  5780. VisibleFogVolumeInfo_t fogInfo;
  5781. WaterRenderInfo_t waterInfo;
  5782. memset( &fogInfo, 0, sizeof( VisibleFogVolumeInfo_t ) );
  5783. memset( &waterInfo, 0, sizeof( WaterRenderInfo_t ) );
  5784. waterInfo.m_bCheapWater = true;
  5785. BaseClass::Setup( view, *pClearFlags, false, fogInfo, waterInfo, NULL );
  5786. m_pRenderTarget = pRenderTarget;
  5787. return true;
  5788. }
  5789. ConVar cl_camera_minimal_photos( "cl_camera_minimal_photos", "1", 0, "Draw just the targetted entity when taking a camera photo" );
  5790. void AddIClientRenderableToRenderList( IClientRenderable *pRenderable, CClientRenderablesList *pRenderablesList )
  5791. {
  5792. CClientRenderablesList::CEntry renderableEntry;
  5793. RenderGroup_t group = ClientLeafSystem()->GenerateRenderListEntry( pRenderable, renderableEntry );
  5794. if( group == RENDER_GROUP_COUNT )
  5795. return;
  5796. for( int i = 0; i != pRenderablesList->m_RenderGroupCounts[group]; ++i )
  5797. {
  5798. if( pRenderablesList->m_RenderGroups[group][i].m_pRenderable == pRenderable )
  5799. return; //already in the list
  5800. }
  5801. int iAddIndex = pRenderablesList->m_RenderGroupCounts[group];
  5802. ++pRenderablesList->m_RenderGroupCounts[group];
  5803. pRenderablesList->m_RenderGroups[group][iAddIndex] = renderableEntry;
  5804. }
  5805. void GetAllChildRenderables( C_BaseEntity *pEntity, IClientRenderable **pKeepers, int &iKeepCount, int iKeepArraySize )
  5806. {
  5807. IClientRenderable *pThisRenderable = pEntity->GetClientRenderable();
  5808. //avoid duplicates and infinite recursion
  5809. for( int i = 0; i != iKeepCount; ++i )
  5810. {
  5811. if( pThisRenderable == pKeepers[i] )
  5812. return;
  5813. }
  5814. pKeepers[iKeepCount++] = pThisRenderable;
  5815. if( pEntity->ParticleProp() )
  5816. {
  5817. iKeepCount += pEntity->ParticleProp()->GetAllParticleEffectRenderables( &pKeepers[iKeepCount], iKeepArraySize - iKeepCount );
  5818. }
  5819. if( pEntity->GetEffectEntity() != NULL )
  5820. {
  5821. GetAllChildRenderables( pEntity->GetEffectEntity(), pKeepers, iKeepCount, iKeepArraySize );
  5822. }
  5823. for( C_BaseEntity *pMoveChild = pEntity->FirstMoveChild(); pMoveChild != NULL; pMoveChild = pMoveChild->NextMovePeer() )
  5824. {
  5825. GetAllChildRenderables( pMoveChild, pKeepers, iKeepCount, iKeepArraySize );
  5826. }
  5827. }
  5828. ConVar cl_blur_test( "cl_blur_test", "0", 0, "Blurs entities that have had their photo taken" );
  5829. ConVar cl_photo_disable_model_alpha_writes( "cl_photo_disable_model_alpha_writes", "1", FCVAR_ARCHIVE, "Disallows the target entity in photos from writing to the photo's alpha channel" );
  5830. //-----------------------------------------------------------------------------
  5831. //
  5832. //-----------------------------------------------------------------------------
  5833. void CAperturePhotoView::Draw()
  5834. {
  5835. CMatRenderContextPtr pRenderContext( materials );
  5836. Vector vDiff = m_pTargetEntity->GetRenderOrigin() - origin;
  5837. Vector vMins, vMaxs;
  5838. m_pTargetEntity->GetRenderBounds( vMins, vMaxs );
  5839. float fGoodDist = MAX((vMaxs - vMins).Length() * (1.5f/2.0f), 20.0f );
  5840. float fLength = vDiff.Length();
  5841. if( fLength > fGoodDist )
  5842. {
  5843. //move the camera closer for a better view
  5844. #if 1 //use camera forward as offset direction
  5845. Vector vCameraForward;
  5846. AngleVectors( angles, &vCameraForward );
  5847. origin = m_pTargetEntity->WorldSpaceCenter() - (vCameraForward * fGoodDist);
  5848. #else //use existing offset direction, but shorter
  5849. origin = m_pTargetEntity->WorldSpaceCenter() - (vDiff * (fGoodDist / fLength));
  5850. #endif
  5851. //Vector vCameraForward;
  5852. //AngleVectors( angles, &vCameraForward );
  5853. //origin += vCameraForward * ((fLength - fGoodDist) * vCameraForward.Dot( vDiff / fLength ));
  5854. }
  5855. render->Push3DView( pRenderContext, *this, VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR | VIEW_CLEAR_STENCIL, m_pRenderTarget, GetFrustum() );
  5856. SetupCurrentView( origin, angles, VIEW_MONITOR );
  5857. MDLCACHE_CRITICAL_SECTION();
  5858. bool bDrawEverything = !cl_camera_minimal_photos.GetBool();
  5859. //Build the world list for now because I don't want to track down crash bugs and this doesn't happen often.
  5860. BuildWorldRenderLists( true, -1, true, false ); // @MULTICORE (toml 8/9/2006): Portal problem, not sending custom vis down
  5861. if( !bDrawEverything )
  5862. {
  5863. memset( m_pRenderablesList->m_RenderGroupCounts, 0, sizeof( m_pRenderablesList->m_RenderGroupCounts ) );
  5864. }
  5865. BuildRenderableRenderLists( CurrentViewID() );
  5866. IClientRenderable *keepHandles[MAX_EDICTS];
  5867. int iKeepChildren = 0;
  5868. GetAllChildRenderables( m_pTargetEntity, keepHandles, iKeepChildren, MAX_EDICTS );
  5869. //set the target entity as the only entity in the renderables list
  5870. {
  5871. if( !bDrawEverything )
  5872. memset( m_pRenderablesList->m_RenderGroupCounts, 0, sizeof( m_pRenderablesList->m_RenderGroupCounts ) );
  5873. for( int i = 0; i != iKeepChildren; ++i )
  5874. {
  5875. AddIClientRenderableToRenderList( keepHandles[i], m_pRenderablesList );
  5876. }
  5877. }
  5878. engine->Sound_ExtraUpdate(); // Make sure sound doesn't stutter
  5879. m_DrawFlags = m_pMainView->GetBaseDrawFlags() | DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER; // Don't draw water surface...
  5880. IMaterial *pPhotoBackground = materials->FindMaterial( "photos/photo_background", TEXTURE_GROUP_CLIENT_EFFECTS, false );
  5881. pRenderContext->DrawScreenSpaceQuad( pPhotoBackground );
  5882. if( cl_photo_disable_model_alpha_writes.GetBool() )
  5883. pRenderContext->OverrideAlphaWriteEnable( true, false );
  5884. if( bDrawEverything )
  5885. DrawWorld( pRenderContext, 0.0f );
  5886. DrawOpaqueRenderables( pRenderContext, RENDERABLES_RENDER_PATH_NORMAL, NULL );
  5887. if( bDrawEverything )
  5888. {
  5889. #if defined( PORTAL )
  5890. DrawRecursivePortalViews();
  5891. #endif
  5892. DrawTranslucentRenderables( false, false );
  5893. }
  5894. else
  5895. {
  5896. DrawTranslucentRenderablesNoWorld( false );
  5897. }
  5898. if( cl_photo_disable_model_alpha_writes.GetBool() )
  5899. pRenderContext->OverrideAlphaWriteEnable( false, false );
  5900. IMaterial *pPhotoForeground = materials->FindMaterial( "photos/photo_foreground", TEXTURE_GROUP_CLIENT_EFFECTS, false );
  5901. pRenderContext->DrawScreenSpaceQuad( pPhotoForeground );
  5902. m_DrawFlags = 0;
  5903. render->PopView( pRenderContext, GetFrustum() );
  5904. if( cl_blur_test.GetBool() )
  5905. m_pTargetEntity->SetBlurState( true );
  5906. }
  5907. #endif
  5908. //-----------------------------------------------------------------------------
  5909. //
  5910. //-----------------------------------------------------------------------------
  5911. void CShadowDepthView::Setup( const CViewSetup &shadowViewIn, ITexture *pRenderTarget, ITexture *pDepthTexture, bool bRenderWorldAndObjects, bool bRenderViewModels )
  5912. {
  5913. BaseClass::Setup( shadowViewIn );
  5914. m_pRenderTarget = pRenderTarget;
  5915. m_pDepthTexture = pDepthTexture;
  5916. m_bRenderWorldAndObjects = bRenderWorldAndObjects;
  5917. m_bRenderViewModels = bRenderViewModels;
  5918. }
  5919. bool DrawingShadowDepthView( void ) //for easy externing
  5920. {
  5921. return (CurrentViewID() == VIEW_SHADOW_DEPTH_TEXTURE);
  5922. }
  5923. #ifdef _PS3
  5924. struct ShadowDepthStaticGeoCacheEntry_t
  5925. {
  5926. ShadowDepthStaticGeoCacheEntry_t() { V_memset( this, 0, sizeof( *this ) ); }
  5927. explicit ShadowDepthStaticGeoCacheEntry_t( const CViewSetup &viewSetup )
  5928. {
  5929. memset( this, 0, sizeof( *this ) );
  5930. fov = viewSetup.fov;
  5931. origin = viewSetup.origin;
  5932. angles = viewSetup.angles;
  5933. zNear = viewSetup.zNear;
  5934. zFar = viewSetup.zFar;
  5935. }
  5936. // The fields from CViewSetup and ViewCustomVisibility_t that would actually affect the list
  5937. float fov;
  5938. Vector origin;
  5939. QAngle angles;
  5940. float zNear;
  5941. float zFar;
  5942. };
  5943. ConVar r_flashlight_staticgeocache( "r_flashlight_staticgeocache", "0", FCVAR_DEVELOPMENTONLY );
  5944. static ShadowDepthStaticGeoCacheEntry_t g_flashlight_staticgeo_cache;
  5945. static uint32 g_flashlight_staticgeo_cache_id;
  5946. static bool g_flashlight_staticgeo_cache_valid;
  5947. #endif
  5948. //-----------------------------------------------------------------------------
  5949. //
  5950. //-----------------------------------------------------------------------------
  5951. void CShadowDepthView::Draw()
  5952. {
  5953. VPROF_BUDGET( "CShadowDepthView::Draw", VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING );
  5954. bool bRenderWorldAndObjects = true;
  5955. #if 0
  5956. if ( ( m_bRenderViewModels ) && ( g_CascadeLightManager.GetCSMQualityMode() < CSMQUALITY_LOW ) )
  5957. {
  5958. bRenderWorldAndObjects = false;
  5959. }
  5960. #endif
  5961. // Start view
  5962. unsigned int visFlags;
  5963. BEGIN_2PASS_BUILD_BLOCK
  5964. m_pMainView->SetupVis( (*this), visFlags ); // @MULTICORE (toml 8/9/2006): Portal problem, not sending custom vis down
  5965. #if defined(_PS3)
  5966. g_viewBuilder.SetVisFlags( visFlags );
  5967. #endif
  5968. END_2PASS_BLOCK
  5969. CMatRenderContextPtr pRenderContext( materials );
  5970. BEGIN_2PASS_DRAW_BLOCK
  5971. pRenderContext->ClearColor3ub(0xFF, 0xFF, 0xFF);
  5972. END_2PASS_BLOCK
  5973. #if defined( _X360 )
  5974. pRenderContext->PushVertexShaderGPRAllocation( 112 ); //almost all work is done in vertex shaders for depth rendering, max out their threads
  5975. #endif
  5976. if( IsPC() || IsPS3() )
  5977. {
  5978. int nClearFlags = ( g_viewBuilder.GetPassFlags() & PASS_DRAWLISTS ) ? VIEW_CLEAR_DEPTH : 0;
  5979. render->Push3DView( pRenderContext, (*this), nClearFlags, m_pRenderTarget, GetFrustum(), m_pDepthTexture );
  5980. }
  5981. else if( IsX360() )
  5982. {
  5983. //for the 360, the dummy render target has a separate depth buffer which we Resolve() from afterward
  5984. render->Push3DView( pRenderContext, (*this), VIEW_CLEAR_DEPTH, m_pRenderTarget, GetFrustum() );
  5985. }
  5986. SetupCurrentView( origin, angles, VIEW_SHADOW_DEPTH_TEXTURE );
  5987. MDLCACHE_CRITICAL_SECTION();
  5988. bool bFlashlightStaticGeoCacheValid = false;
  5989. bool bFlashlightStaticGeoCacheEnabled = 0; bFlashlightStaticGeoCacheEnabled;
  5990. #if 0
  5991. bool bFlashlightStaticGeoCacheEnabled = r_flashlight_staticgeocache.GetBool();
  5992. if ( bFlashlightStaticGeoCacheEnabled )
  5993. {
  5994. if ( g_flashlight_staticgeo_cache_valid )
  5995. {
  5996. ShadowDepthStaticGeoCacheEntry_t entry( *this );
  5997. bFlashlightStaticGeoCacheValid = !V_memcmp( &entry, &g_flashlight_staticgeo_cache, sizeof( entry ) );
  5998. if ( !bFlashlightStaticGeoCacheValid )
  5999. {
  6000. if ( r_flashlight_staticgeocache.GetInt() > 1 )
  6001. {
  6002. DevMsg( "Shadow Depth View: depth cache is stale [id=%d]\n", g_flashlight_staticgeo_cache_id );
  6003. DevMsg( " pos = %.3f:%.3f:%.3f -> %.3f:%.3f:%.3f\n",
  6004. g_flashlight_staticgeo_cache.origin.x, g_flashlight_staticgeo_cache.origin.y, g_flashlight_staticgeo_cache.origin.z,
  6005. entry.origin.x, entry.origin.y, entry.origin.z );
  6006. DevMsg( " ang = %.3f:%.3f:%.3f -> %.3f:%.3f:%.3f\n",
  6007. g_flashlight_staticgeo_cache.angles.x, g_flashlight_staticgeo_cache.angles.y, g_flashlight_staticgeo_cache.angles.z,
  6008. entry.angles.x, entry.angles.y, entry.angles.z );
  6009. DevMsg( " fov = %.3f -> %.3f\n", g_flashlight_staticgeo_cache.fov, entry.fov );
  6010. DevMsg( " zNear = %.3f -> %.3f\n", g_flashlight_staticgeo_cache.zNear, entry.zNear );
  6011. DevMsg( " zFar = %.3f -> %.3f\n", g_flashlight_staticgeo_cache.zFar, entry.zFar );
  6012. }
  6013. V_memcpy( &g_flashlight_staticgeo_cache, &entry, sizeof( entry ) );
  6014. }
  6015. }
  6016. if ( !bFlashlightStaticGeoCacheValid )
  6017. {
  6018. ++ g_flashlight_staticgeo_cache_id;
  6019. g_flashlight_staticgeo_cache_valid = true;
  6020. if ( r_flashlight_staticgeocache.GetInt() > 1 )
  6021. {
  6022. DevMsg( "Shadow Depth View: fully refreshing depth cache [id=%d]\n", g_flashlight_staticgeo_cache_id );
  6023. }
  6024. }
  6025. }
  6026. else
  6027. {
  6028. g_flashlight_staticgeo_cache_valid = false;
  6029. }
  6030. #endif
  6031. bool bRenderWorld;
  6032. // 7LS - turn off all world rendering in view model cascade, viewmodel and renderables only
  6033. // ambient cube lighting should take care of gross shadow areas.
  6034. // TODO - find a way to turn off rendering of characters into viewmodel cascade too
  6035. if( m_bRenderViewModels && !cl_csm_world_shadows_in_viewmodelcascade.GetBool() )
  6036. {
  6037. bRenderWorld = false;
  6038. }
  6039. else
  6040. {
  6041. bRenderWorld = m_bRenderWorldAndObjects && !m_bCSMView || ( cl_csm_world_shadows.GetBool() && cl_csm_shadows.GetBool() ) && bRenderWorldAndObjects;
  6042. }
  6043. #if defined(_PS3)
  6044. // turn off world rendering into all cascades for listen server
  6045. if( m_bCSMView && engine->IsClientLocalToActiveServer() && r_ps3_csm_disableWorldInListenServer.GetInt() )
  6046. {
  6047. bRenderWorld = false;
  6048. }
  6049. #endif
  6050. BEGIN_2PASS_BUILD_BLOCK
  6051. PROLOGUE_PASS_DRAWLISTS
  6052. // cache volume culler
  6053. g_viewBuilder.CacheBuildViewVolumeCuller( m_pCSMVolumeCuller );
  6054. if ( ( m_bCSMView ) && ( bRenderWorld ) )
  6055. {
  6056. render->DrawTopView( true );
  6057. render->TopViewNoBackfaceCulling( true );
  6058. render->TopViewNoVisCheck( true ); //render->TopViewNoVisCheck( false ); <- consider as an optimisation for PS3/listenserver mode
  6059. render->TopViewBounds( Vector2D( -30000.0f, -30000.0f ), Vector2D( 30000.0f, 30000.0f ) );
  6060. if ( !cl_csm_disable_culling.GetBool() )
  6061. {
  6062. render->SetTopViewVolumeCuller( g_viewBuilder.GetBuildViewVolumeCuller() );
  6063. }
  6064. }
  6065. {
  6066. BuildWorldRenderLists( true, -1, true, true ); // @MULTICORE (toml 8/9/2006): Portal problem, not sending custom vis down
  6067. g_viewBuilder.FlushBuildWorldListJob();
  6068. if ( !m_bCSMView )
  6069. {
  6070. g_viewBuilder.AddDependencyToWorldList();
  6071. }
  6072. BuildRenderableRenderLists( CurrentViewID(), false, bFlashlightStaticGeoCacheValid );
  6073. }
  6074. if ( ( m_bCSMView ) && ( bRenderWorld ) )
  6075. {
  6076. render->TopViewNoBackfaceCulling( false );
  6077. render->TopViewNoVisCheck( false );
  6078. render->DrawTopView( false );
  6079. render->SetTopViewVolumeCuller( NULL );
  6080. }
  6081. END_2PASS_BLOCK
  6082. BEGIN_2PASS_DRAW_BLOCK
  6083. EPILOGUE_PASS_DRAWLISTS
  6084. engine->Sound_ExtraUpdate(); // Make sure sound doesn't stutter
  6085. m_DrawFlags = m_pMainView->GetBaseDrawFlags() | DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER | DF_SHADOW_DEPTH_MAP; // Don't draw water surface...
  6086. if ( ( m_bCSMView ) && ( bRenderWorld ) )
  6087. {
  6088. render->DrawTopView( true );
  6089. }
  6090. SYNC_BUILDWORLD_JOB( true )
  6091. if ( ( m_bCSMView ) && ( bRenderWorld ) )
  6092. {
  6093. render->DrawTopView( false );
  6094. }
  6095. if ( ( !bFlashlightStaticGeoCacheValid ) && ( bRenderWorld ) )
  6096. {
  6097. DrawWorld( pRenderContext, 0.0f );
  6098. }
  6099. // Draw opaque and translucent renderables with appropriate override materials
  6100. // OVERRIDE_DEPTH_WRITE is OK with a NULL material pointer
  6101. modelrender->ForcedMaterialOverride( NULL, OVERRIDE_DEPTH_WRITE );
  6102. SYNC_BUILDRENDERABLES_JOB( CurrentViewID() )
  6103. if ( m_bRenderWorldAndObjects && bRenderWorldAndObjects )
  6104. {
  6105. DrawOpaqueRenderables( pRenderContext,
  6106. #ifdef _PS3
  6107. bFlashlightStaticGeoCacheEnabled
  6108. ? ( bFlashlightStaticGeoCacheValid
  6109. ? RENDERABLES_RENDER_PATH_SHADOWDEPTH_USE_GEOCACHE
  6110. : RENDERABLES_RENDER_PATH_SHADOWDEPTH_BUILD_GEOCACHE
  6111. ) :
  6112. #endif
  6113. RENDERABLES_RENDER_PATH_SHADOWDEPTH_DEFAULT,
  6114. DEPTH_MODE_SHADOW,
  6115. NULL
  6116. );
  6117. }
  6118. if ( m_bRenderViewModels )
  6119. {
  6120. m_pMainView->DrawViewModelsShadowDepth( *this );
  6121. }
  6122. if ( m_bCSMView )
  6123. {
  6124. if ( cl_csm_translucent_shadows.GetBool() && ( g_CascadeLightManager.GetCSMQualityMode() >= CSMQUALITY_MEDIUM ) )
  6125. {
  6126. if ( cl_csm_translucent_shadows_using_opaque_path.GetBool() )
  6127. {
  6128. // cstrike15 supports efficiently rendering translucent materials into CSM shadow buffers
  6129. DrawOpaqueRenderables( pRenderContext,
  6130. RENDERABLES_RENDER_PATH_SHADOWDEPTH_DEFAULT, DEPTH_MODE_SHADOW,
  6131. NULL, RENDER_GROUP_TRANSLUCENT );
  6132. }
  6133. else
  6134. {
  6135. DrawTranslucentRenderables( false, true );
  6136. }
  6137. }
  6138. }
  6139. else
  6140. {
  6141. #ifndef _PS3
  6142. // Attention PaulB/Mario: We need to remove this PS3 specific thing for CS:GO CSM, so translucent renderables can cast shadows.
  6143. // PS3 is not supporting translucent renderables for now, will need support in static geo cache
  6144. if ( r_flashlightdepth_drawtranslucents.GetBool() )
  6145. {
  6146. #if defined( PORTAL )
  6147. DrawRecursivePortalViews(); //Dave K: probably does nothing in this view, calling it anyway because it's contents were directly inside DrawTranslucentRenderables() a moment ago and I don't want to risk breaking anything
  6148. #endif
  6149. DrawTranslucentRenderables( false, true );
  6150. }
  6151. #endif
  6152. }
  6153. modelrender->ForcedMaterialOverride( 0 );
  6154. m_DrawFlags = 0;
  6155. #if defined(_X360)
  6156. {
  6157. //Resolve() the depth texture here. Before the pop so the copy will recognize that the resolutions are the same
  6158. if( m_bCSMView )
  6159. {
  6160. // send appropriate src/dst rects for csm rendering
  6161. Rect_t src, dst;
  6162. src.x = 0;
  6163. src.y = 0;
  6164. src.width = width;
  6165. src.height = height;
  6166. dst.x = xCsmDstOffset;
  6167. dst.y = yCsmDstOffset;
  6168. dst.width = width;
  6169. dst.height = height;
  6170. pRenderContext->CopyRenderTargetToTextureEx( m_pDepthTexture, -1, &src, &dst );
  6171. }
  6172. else
  6173. {
  6174. pRenderContext->CopyRenderTargetToTextureEx( m_pDepthTexture, -1, NULL, NULL );
  6175. }
  6176. }
  6177. #endif
  6178. END_2PASS_BLOCK
  6179. render->PopView( pRenderContext, GetFrustum() );
  6180. #if defined( _X360 )
  6181. pRenderContext->PopVertexShaderGPRAllocation();
  6182. #endif
  6183. pRenderContext->ClearColor3ub( 0, 0, 0 );
  6184. }
  6185. //-----------------------------------------------------------------------------
  6186. //
  6187. //-----------------------------------------------------------------------------
  6188. void CFreezeFrameView::Setup( const CViewSetup &shadowViewIn )
  6189. {
  6190. BaseClass::Setup( shadowViewIn );
  6191. VGui_GetTrueScreenSize( m_nScreenSize[ 0 ], m_nScreenSize[ 1 ] );
  6192. VGui_GetPanelBounds( GET_ACTIVE_SPLITSCREEN_SLOT(), m_nSubRect[ 0 ], m_nSubRect[ 1 ], m_nSubRect[ 2 ], m_nSubRect[ 3 ] );
  6193. KeyValues *pVMTKeyValues = new KeyValues( "UnlitGeneric" );
  6194. pVMTKeyValues->SetString( "$basetexture", IsGameConsole() ? "_rt_FullFrameFB1" : "_rt_FullScreen" );
  6195. pVMTKeyValues->SetInt( "$nocull", 1 );
  6196. pVMTKeyValues->SetInt( "$nofog", 1 );
  6197. pVMTKeyValues->SetInt( "$ignorez", 1 );
  6198. m_pFreezeFrame.Init( "FreezeFrame_FullScreen", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  6199. m_pFreezeFrame->Refresh();
  6200. m_TranslucentSingleColor.Init( "debug/debugtranslucentsinglecolor", TEXTURE_GROUP_OTHER );
  6201. }
  6202. //-----------------------------------------------------------------------------
  6203. // Purpose:
  6204. //-----------------------------------------------------------------------------
  6205. void CFreezeFrameView::Draw( void )
  6206. {
  6207. CMatRenderContextPtr pRenderContext( materials );
  6208. #if defined( _X360 )
  6209. pRenderContext->PushVertexShaderGPRAllocation( 16 ); //max out pixel shader threads
  6210. #endif
  6211. pRenderContext->DrawScreenSpaceRectangle( m_pFreezeFrame, x, y, width, height,
  6212. m_nSubRect[ 0 ], m_nSubRect[ 1 ], m_nSubRect[ 0 ] + m_nSubRect[ 2 ] - 1, m_nSubRect[ 1 ] + m_nSubRect[ 3 ] - 1, m_nScreenSize[ 0 ], m_nScreenSize[ 1 ] );
  6213. //Fake a fade during freezeframe view.
  6214. if ( g_flFreezeFlash[ m_nSlot ] >= gpGlobals->curtime &&
  6215. engine->IsTakingScreenshot() == false )
  6216. {
  6217. // Overlay screen fade on entire screen
  6218. IMaterial* pMaterial = m_TranslucentSingleColor;
  6219. int iFadeAlpha = FREEZECAM_SNAPSHOT_FADE_SPEED * ( g_flFreezeFlash[ m_nSlot ] - gpGlobals->curtime );
  6220. iFadeAlpha = MIN( iFadeAlpha, 255 );
  6221. iFadeAlpha = MAX( 0, iFadeAlpha );
  6222. pMaterial->AlphaModulate( iFadeAlpha * ( 1.0f / 255.0f ) );
  6223. pMaterial->ColorModulate( 1.0f, 1.0f, 1.0f );
  6224. pMaterial->SetMaterialVarFlag( MATERIAL_VAR_IGNOREZ, true );
  6225. pRenderContext->DrawScreenSpaceRectangle( pMaterial, x, y, width, height, m_nSubRect[ 0 ], m_nSubRect[ 1 ], m_nSubRect[ 0 ] + m_nSubRect[ 2 ] - 1, m_nSubRect[ 1 ] + m_nSubRect[ 3 ] - 1, m_nScreenSize[ 0 ], m_nScreenSize[ 1 ] );
  6226. }
  6227. #if defined( _X360 )
  6228. pRenderContext->PopVertexShaderGPRAllocation();
  6229. #endif
  6230. }
  6231. //-----------------------------------------------------------------------------
  6232. // Pops a water render target
  6233. //-----------------------------------------------------------------------------
  6234. bool CBaseWorldView::AdjustView( float waterHeight )
  6235. {
  6236. if( m_DrawFlags & DF_RENDER_REFRACTION )
  6237. {
  6238. ITexture *pTexture = GetWaterRefractionTexture();
  6239. // Use the aspect ratio of the main view! So, don't recompute it here
  6240. x = y = 0;
  6241. width = pTexture->GetActualWidth();
  6242. height = pTexture->GetActualHeight();
  6243. return true;
  6244. }
  6245. if( m_DrawFlags & DF_RENDER_REFLECTION )
  6246. {
  6247. ITexture *pTexture = GetWaterReflectionTexture();
  6248. // Use the aspect ratio of the main view! So, don't recompute it here
  6249. x = y = 0;
  6250. width = pTexture->GetActualWidth();
  6251. height = pTexture->GetActualHeight();
  6252. float fHeightDiff = (origin[2] - waterHeight) * 2.0f;
  6253. angles[0] = -angles[0];
  6254. angles[2] = -angles[2];
  6255. origin[2] -= fHeightDiff;
  6256. // PORTAL2-specific code
  6257. if( m_bCustomViewMatrix )
  6258. {
  6259. QAngle newAngles;
  6260. Vector vNewOrigin;
  6261. VMatrix customMatrix;
  6262. // Recompute angles from custom view matrix (which is concatenation of view matrix and portal matrix)
  6263. customMatrix.CopyFrom3x4( m_matCustomViewMatrix );
  6264. customMatrix = customMatrix.Transpose();
  6265. MatrixToAngles( customMatrix, newAngles );
  6266. // Apply reflection transformation
  6267. newAngles[0] = -newAngles[0];
  6268. newAngles[2] = -newAngles[2];
  6269. // Extract origin from matrix (coordinates in matrix are in view space; convert back to world space)
  6270. vNewOrigin = -(
  6271. m_matCustomViewMatrix.m_flMatVal[0][3] * Vector( *( Vector * )m_matCustomViewMatrix.m_flMatVal[0] ) +
  6272. m_matCustomViewMatrix.m_flMatVal[1][3] * Vector( *( Vector * )m_matCustomViewMatrix.m_flMatVal[1] ) +
  6273. m_matCustomViewMatrix.m_flMatVal[2][3] * Vector( *( Vector * )m_matCustomViewMatrix.m_flMatVal[2] )
  6274. );
  6275. // Reflect position beneath water plane
  6276. vNewOrigin[2] -= (vNewOrigin[2] - waterHeight) * 2.0f;
  6277. VMatrix newCustomMatrix;
  6278. newCustomMatrix.Identity();
  6279. // Re-generate the custom view matrix from angles & origin
  6280. MatrixRotate( newCustomMatrix, Vector( 1, 0, 0 ), -newAngles[2] );
  6281. MatrixRotate( newCustomMatrix, Vector( 0, 1, 0 ), -newAngles[0] );
  6282. MatrixRotate( newCustomMatrix, Vector( 0, 0, 1 ), -newAngles[1] );
  6283. MatrixTranslate( newCustomMatrix, -vNewOrigin );
  6284. m_matCustomViewMatrix = newCustomMatrix.As3x4();
  6285. }
  6286. return true;
  6287. }
  6288. return false;
  6289. }
  6290. //-----------------------------------------------------------------------------
  6291. // Pops a water render target
  6292. //-----------------------------------------------------------------------------
  6293. void CBaseWorldView::PushView( float waterHeight )
  6294. {
  6295. float spread = 2.0f;
  6296. if( m_DrawFlags & DF_FUDGE_UP )
  6297. {
  6298. waterHeight += spread;
  6299. }
  6300. else
  6301. {
  6302. waterHeight -= spread;
  6303. }
  6304. MaterialHeightClipMode_t clipMode = MATERIAL_HEIGHTCLIPMODE_DISABLE;
  6305. if ( ( m_DrawFlags & DF_CLIP_Z ) && mat_clipz.GetBool() )
  6306. {
  6307. if( m_DrawFlags & DF_CLIP_BELOW )
  6308. {
  6309. clipMode = MATERIAL_HEIGHTCLIPMODE_RENDER_ABOVE_HEIGHT;
  6310. }
  6311. else
  6312. {
  6313. clipMode = MATERIAL_HEIGHTCLIPMODE_RENDER_BELOW_HEIGHT;
  6314. }
  6315. }
  6316. CMatRenderContextPtr pRenderContext( materials );
  6317. if( m_DrawFlags & DF_RENDER_REFRACTION )
  6318. {
  6319. pRenderContext->SetFogZ( waterHeight );
  6320. pRenderContext->SetHeightClipZ( waterHeight );
  6321. pRenderContext->SetHeightClipMode( clipMode );
  6322. // Have to re-set up the view since we reset the size
  6323. render->Push3DView( pRenderContext, *this, m_ClearFlags, GetWaterRefractionTexture(), GetFrustum() );
  6324. return;
  6325. }
  6326. if( m_DrawFlags & DF_RENDER_REFLECTION )
  6327. {
  6328. ITexture *pTexture = GetWaterReflectionTexture();
  6329. pRenderContext->SetFogZ( waterHeight );
  6330. bool bSoftwareUserClipPlane = g_pMaterialSystemHardwareConfig->UseFastClipping();
  6331. if( bSoftwareUserClipPlane && ( origin[2] > waterHeight - r_eyewaterepsilon.GetFloat() ) )
  6332. {
  6333. waterHeight = origin[2] + r_eyewaterepsilon.GetFloat();
  6334. }
  6335. pRenderContext->SetHeightClipZ( waterHeight );
  6336. pRenderContext->SetHeightClipMode( clipMode );
  6337. render->Push3DView( pRenderContext, *this, m_ClearFlags, pTexture, GetFrustum() );
  6338. SetLightmapScaleForWater();
  6339. return;
  6340. }
  6341. if ( m_ClearFlags & ( VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR | VIEW_CLEAR_STENCIL ) )
  6342. {
  6343. if ( m_ClearFlags & VIEW_CLEAR_OBEY_STENCIL )
  6344. {
  6345. pRenderContext->ClearBuffersObeyStencil( ( m_ClearFlags & VIEW_CLEAR_COLOR ) ? true : false, ( m_ClearFlags & VIEW_CLEAR_DEPTH ) ? true : false );
  6346. }
  6347. else
  6348. {
  6349. if ( r_shadow_deferred.GetBool() )
  6350. {
  6351. // FIXME: Is there a better place to force a stencil clear for deferred shadows?
  6352. if ( m_ClearFlags & VIEW_CLEAR_DEPTH )
  6353. m_ClearFlags |= VIEW_CLEAR_STENCIL;
  6354. }
  6355. pRenderContext->ClearBuffers( ( m_ClearFlags & VIEW_CLEAR_COLOR ) ? true : false, ( m_ClearFlags & VIEW_CLEAR_DEPTH ) ? true : false, ( m_ClearFlags & VIEW_CLEAR_STENCIL ) ? true : false );
  6356. }
  6357. }
  6358. pRenderContext->SetHeightClipMode( clipMode );
  6359. if ( clipMode != MATERIAL_HEIGHTCLIPMODE_DISABLE )
  6360. {
  6361. pRenderContext->SetHeightClipZ( waterHeight );
  6362. }
  6363. }
  6364. //-----------------------------------------------------------------------------
  6365. // Pops a water render target
  6366. //-----------------------------------------------------------------------------
  6367. void CBaseWorldView::PopView()
  6368. {
  6369. CMatRenderContextPtr pRenderContext( materials );
  6370. pRenderContext->SetHeightClipMode( MATERIAL_HEIGHTCLIPMODE_DISABLE );
  6371. if( m_DrawFlags & (DF_RENDER_REFRACTION | DF_RENDER_REFLECTION) )
  6372. {
  6373. if ( IsGameConsole() )
  6374. {
  6375. // these renders paths used their surfaces, so blit their results
  6376. if ( m_DrawFlags & DF_RENDER_REFRACTION )
  6377. {
  6378. pRenderContext->CopyRenderTargetToTextureEx( GetWaterRefractionTexture(), NULL, NULL );
  6379. }
  6380. if ( m_DrawFlags & DF_RENDER_REFLECTION )
  6381. {
  6382. pRenderContext->CopyRenderTargetToTextureEx( GetWaterReflectionTexture(), NULL, NULL );
  6383. }
  6384. }
  6385. render->PopView( pRenderContext, GetFrustum() );
  6386. if (s_vSavedLinearLightMapScale.x>=0)
  6387. {
  6388. pRenderContext->SetToneMappingScaleLinear(s_vSavedLinearLightMapScale);
  6389. s_vSavedLinearLightMapScale.x=-1;
  6390. }
  6391. }
  6392. }
  6393. //-----------------------------------------------------------------------------
  6394. // Draws the world + entities
  6395. //-----------------------------------------------------------------------------
  6396. void CBaseWorldView::DrawSetup( IMatRenderContext *pRenderContext, float waterHeight, int nSetupFlags, float waterZAdjust, int iForceViewLeaf )
  6397. {
  6398. VPROF( "CBaseWorldView::DrawSetup" );
  6399. int savedViewID = g_CurrentViewID;
  6400. g_CurrentViewID = VIEW_ILLEGAL;
  6401. bool bViewChanged = AdjustView( waterHeight );
  6402. if ( bViewChanged )
  6403. {
  6404. render->Push3DView( pRenderContext, *this, 0, NULL, GetFrustum() );
  6405. }
  6406. BEGIN_2PASS_BUILD_BLOCK
  6407. if ( ( nSetupFlags & ( DF_DRAW_SIMPLE_WORLD_MODEL | DF_DRAW_SIMPLE_WORLD_MODEL_WATER ) ) == 0 )
  6408. {
  6409. render->BeginUpdateLightmaps();
  6410. bool bDrawEntities = ( nSetupFlags & DF_DRAW_ENTITITES ) != 0;
  6411. bool bDrawReflection = ( nSetupFlags & DF_RENDER_REFLECTION ) != 0;
  6412. bool bFastEntityRendering = ( nSetupFlags & DF_FAST_ENTITY_RENDERING ) != 0;
  6413. BuildWorldRenderLists( bDrawEntities, iForceViewLeaf, true, false, bDrawReflection ? &waterHeight : NULL );
  6414. PruneWorldListInfo();
  6415. g_viewBuilder.FlushBuildWorldListJob(); // PruneWorldListInfo part of the BuildWorldList job
  6416. g_viewBuilder.AddDependencyToWorldList();
  6417. if ( bDrawEntities )
  6418. {
  6419. BuildRenderableRenderLists( savedViewID, bFastEntityRendering );
  6420. }
  6421. else
  6422. {
  6423. // DrawExecute still expect a valid m_pRenderables (empty)
  6424. m_pRenderables = new CClientRenderablesList;
  6425. g_viewBuilder.SetRenderablesListElement( m_pRenderables );
  6426. }
  6427. render->EndUpdateLightmaps();
  6428. }
  6429. else
  6430. {
  6431. bool bDrawEntities = ( nSetupFlags & DF_DRAW_ENTITITES ) != 0;
  6432. bool bFastEntityRendering = ( nSetupFlags & DF_FAST_ENTITY_RENDERING ) != 0;
  6433. // We require fast water reflections here since the other code path assumes that world lists are built, etc.
  6434. if ( bDrawEntities && bFastEntityRendering )
  6435. {
  6436. // Make sure to cache frustum list as BuildRenderableRenderLists will used the cached frustum
  6437. // (Frustum normally cached in BuildWorldRenderLists!)
  6438. g_viewBuilder.CacheFrustumData();
  6439. BuildRenderableRenderLists( savedViewID, bFastEntityRendering );
  6440. }
  6441. else
  6442. {
  6443. Error( "Bad stuff will happen (crashes, stack corruption, etc) because opaque renderables will attempt to render with junk data" );
  6444. }
  6445. }
  6446. END_2PASS_BLOCK
  6447. if ( bViewChanged )
  6448. {
  6449. render->PopView( pRenderContext, GetFrustum() );
  6450. }
  6451. g_CurrentViewID = savedViewID;
  6452. }
  6453. void CBaseWorldView::DrawExecute( float waterHeight, view_id_t viewID, float waterZAdjust )
  6454. {
  6455. BEGIN_2PASS_DRAW_BLOCK
  6456. EPILOGUE_PASS_DRAWLISTS
  6457. // Make sure sound doesn't stutter
  6458. engine->Sound_ExtraUpdate();
  6459. static ConVarRef mat_resolveFullFrameDepth( "mat_resolveFullFrameDepth" );
  6460. // perform full cpu depth only pass into rt_fullframedepth - only do this if forced on via mat_resolveFullFrameDepth = 2, useful for compatability or debugging vs depth resolve
  6461. if ( ( viewID == VIEW_MAIN ) && g_pMaterialSystemHardwareConfig->HasFullResolutionDepthTexture() && ( mat_resolveFullFrameDepth.GetInt() == 2 ) )
  6462. {
  6463. SSAO_DepthPass();
  6464. }
  6465. SYNC_BUILDWORLD_JOB(false)
  6466. // @MULTICORE (toml 8/16/2006): rethink how, where, and when this is done...
  6467. if ( !( m_DrawFlags & ( DF_DRAW_SIMPLE_WORLD_MODEL | DF_DRAW_SIMPLE_WORLD_MODEL_WATER ) ) )
  6468. {
  6469. #if defined(_PS3)
  6470. g_pClientShadowMgr->ComputeShadowTextures( *this, m_pWorldListInfo[ g_viewBuilder.GetBuildViewID() ]->m_LeafCount, m_pWorldListInfo[ g_viewBuilder.GetBuildViewID() ]->m_pLeafDataList );
  6471. #else
  6472. g_pClientShadowMgr->ComputeShadowTextures( *this, m_pWorldListInfo->m_LeafCount, m_pWorldListInfo->m_pLeafDataList );
  6473. #endif
  6474. }
  6475. int savedViewID = g_CurrentViewID;
  6476. g_CurrentViewID = viewID;
  6477. // Update our render view flags.
  6478. int iDrawFlagsBackup = m_DrawFlags;
  6479. m_DrawFlags |= m_pMainView->GetBaseDrawFlags();
  6480. PushView( waterHeight );
  6481. CMatRenderContextPtr pRenderContext( materials );
  6482. #if defined( _X360 )
  6483. pRenderContext->PushVertexShaderGPRAllocation( 32 );
  6484. #endif
  6485. ITexture *pSaveFrameBufferCopyTexture = pRenderContext->GetFrameBufferCopyTexture( 0 );
  6486. pRenderContext->SetFrameBufferCopyTexture( GetPowerOfTwoFrameBufferTexture() );
  6487. if ( !( m_DrawFlags & ( DF_DRAW_SIMPLE_WORLD_MODEL | DF_DRAW_SIMPLE_WORLD_MODEL_WATER ) ) )
  6488. {
  6489. BeginConsoleZPass();
  6490. }
  6491. #ifdef PORTAL
  6492. if ( IsMainView( viewID ) )
  6493. {
  6494. g_pPortalRender->DrawEarlyZPortals( (CViewRender*)view );
  6495. }
  6496. #endif // PORTAL
  6497. //#if !defined(_PS3) - trying to re-order drawing of world and renderables on PS3 (small gpu perf win, but now confuses/delays the syncing of SPU buildworld/renderable jobs)
  6498. m_DrawFlags |= DF_SKIP_WORLD_DECALS_AND_OVERLAYS;
  6499. DrawWorld( pRenderContext, waterZAdjust );
  6500. //#endif
  6501. SYNC_BUILDRENDERABLES_JOB( savedViewID )
  6502. #if defined(_PS3)
  6503. CUtlVector< CClientRenderablesList::CEntry * > arrFastClippedOpaqueRenderables( (CClientRenderablesList::CEntry **)stackalloc( m_pRenderablesList[ g_viewBuilder.GetBuildViewID() ]->m_RenderGroupCounts[RENDER_GROUP_OPAQUE] * sizeof( CClientRenderablesList::CEntry * ) ), m_pRenderablesList[ g_viewBuilder.GetBuildViewID() ]->m_RenderGroupCounts[RENDER_GROUP_OPAQUE] );
  6504. #else
  6505. CUtlVector< CClientRenderablesList::CEntry * > arrFastClippedOpaqueRenderables( (CClientRenderablesList::CEntry **)stackalloc( m_pRenderables->m_RenderGroupCounts[RENDER_GROUP_OPAQUE] * sizeof( CClientRenderablesList::CEntry * ) ), m_pRenderables->m_RenderGroupCounts[RENDER_GROUP_OPAQUE] );
  6506. #endif
  6507. CUtlVector< CClientRenderablesList::CEntry * > *pArrFastClippedOpaqueRenderables = (r_deferopaquefastclipped.GetBool() && !m_bDrawWorldNormal && r_entityclips.GetBool() && materials->UsingFastClipping()) ? &arrFastClippedOpaqueRenderables : NULL;
  6508. m_DrawFlags &= ~DF_SKIP_WORLD_DECALS_AND_OVERLAYS;
  6509. if ( m_DrawFlags & DF_DRAW_ENTITITES )
  6510. {
  6511. DrawOpaqueRenderables( pRenderContext, RENDERABLES_RENDER_PATH_NORMAL, DEPTH_MODE_NORMAL, pArrFastClippedOpaqueRenderables );
  6512. }
  6513. // #if defined(_PS3) - trying to re-order drawing of world and renderables on PS3 (small gpu perf win, but now confuses/delays the syncing of SPU buildworld/renderable jobs)
  6514. // m_DrawFlags |= DF_SKIP_WORLD_DECALS_AND_OVERLAYS;
  6515. // DrawWorld( pRenderContext, waterZAdjust );
  6516. // m_DrawFlags &= ~DF_SKIP_WORLD_DECALS_AND_OVERLAYS;
  6517. // #endif
  6518. if ( !( m_DrawFlags & ( DF_DRAW_SIMPLE_WORLD_MODEL | DF_DRAW_SIMPLE_WORLD_MODEL_WATER ) ) )
  6519. {
  6520. EndConsoleZPass(); // DrawOpaqueRenderables currently already calls EndConsoleZPass. No harm in calling it again to make sure we're always ending it
  6521. }
  6522. if ( m_DrawFlags & DF_RENDER_PSEUDO_TRANSLUCENT_WATER )
  6523. {
  6524. if ( IsX360() )
  6525. {
  6526. // Update depth texture for depth-based water edge feathering.
  6527. UpdateFullScreenDepthTexture();
  6528. }
  6529. int nOldFlags = m_DrawFlags;
  6530. // In addition to decals, draw only water but not above/below water (we need to un-skip the world for this to have any effect)
  6531. m_DrawFlags &= ~DF_RENDER_ABOVEWATER;
  6532. m_DrawFlags &= ~DF_RENDER_UNDERWATER;
  6533. m_DrawFlags &= ~DF_DRAWSKYBOX;
  6534. m_DrawFlags |= DF_RENDER_WATER;
  6535. m_DrawFlags |= DF_SKIP_WORLD_DECALS_AND_OVERLAYS;
  6536. DrawWorld( pRenderContext, waterZAdjust );
  6537. m_DrawFlags = nOldFlags;
  6538. }
  6539. // Only draw decals on opaque surfaces after now. Benefit is two-fold: Early Z benefits on PC, and
  6540. // we're pulling out stuff that uses the dynamic VB from the 360 Z pass
  6541. // (which can lead to rendering corruption if we overflow the dyn. VB ring buffer).
  6542. m_DrawFlags |= DF_SKIP_WORLD;
  6543. if ( !( m_DrawFlags & ( DF_DRAW_SIMPLE_WORLD_MODEL | DF_DRAW_SIMPLE_WORLD_MODEL_WATER ) ) )
  6544. {
  6545. DrawWorld( pRenderContext, waterZAdjust );
  6546. }
  6547. m_DrawFlags &= ~DF_SKIP_WORLD;
  6548. if ( !m_bDrawWorldNormal )
  6549. {
  6550. if ( m_DrawFlags & DF_DRAW_ENTITITES )
  6551. {
  6552. #if defined( PORTAL )
  6553. DrawRecursivePortalViews();
  6554. #endif
  6555. DrawDeferredClippedOpaqueRenderables( pRenderContext, RENDERABLES_RENDER_PATH_NORMAL, DEPTH_MODE_NORMAL, pArrFastClippedOpaqueRenderables );
  6556. DrawTranslucentRenderables( false, false );
  6557. DrawNoZBufferTranslucentRenderables();
  6558. }
  6559. else
  6560. {
  6561. // Draw translucent world brushes only, no entities
  6562. DrawTranslucentWorldInLeaves( pRenderContext, false );
  6563. }
  6564. }
  6565. // issue the pixel visibility tests for sub-views
  6566. if ( !IsMainView( CurrentViewID() ) && CurrentViewID() != VIEW_INTRO_CAMERA )
  6567. {
  6568. PixelVisibility_EndCurrentView();
  6569. }
  6570. pRenderContext.GetFrom( materials );
  6571. pRenderContext->SetFrameBufferCopyTexture( pSaveFrameBufferCopyTexture );
  6572. PopView();
  6573. m_DrawFlags = iDrawFlagsBackup;
  6574. g_CurrentViewID = savedViewID;
  6575. #if defined( _X360 )
  6576. pRenderContext->PopVertexShaderGPRAllocation();
  6577. #endif
  6578. END_2PASS_BLOCK
  6579. }
  6580. void CBaseWorldView::SSAO_DepthPass()
  6581. {
  6582. VPROF_BUDGET( "CSimpleWorldView::SSAO_DepthPass", VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING );
  6583. int savedViewID = g_CurrentViewID;
  6584. g_CurrentViewID = VIEW_SSAO;
  6585. SYNC_BUILDWORLD_JOB( false );
  6586. SYNC_BUILDRENDERABLES_JOB( VIEW_MAIN );
  6587. ITexture *pSSAO = materials->FindTexture( "_rt_FullFrameDepth", TEXTURE_GROUP_RENDER_TARGET );
  6588. CMatRenderContextPtr pRenderContext( materials );
  6589. PIXEVENT( pRenderContext, "Depth SSAO" );
  6590. pRenderContext->ClearColor4ub( 255, 255, 255, 255 );
  6591. // pRenderContext.SafeRelease();
  6592. if ( IsPC() )
  6593. {
  6594. render->Push3DView( pRenderContext, ( *this ), VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR, pSSAO, GetFrustum() );
  6595. }
  6596. else if ( IsX360() )
  6597. {
  6598. render->Push3DView( pRenderContext, ( *this ), VIEW_CLEAR_DEPTH | VIEW_CLEAR_COLOR, pSSAO, GetFrustum() );
  6599. }
  6600. MDLCACHE_CRITICAL_SECTION();
  6601. engine->Sound_ExtraUpdate(); // Make sure sound doesn't stutter
  6602. m_DrawFlags |= DF_SSAO_DEPTH_PASS;
  6603. {
  6604. VPROF_BUDGET( "DrawWorld", VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING );
  6605. DrawWorld( pRenderContext, 0.0f );
  6606. }
  6607. // Draw opaque and translucent renderables with appropriate override materials
  6608. // OVERRIDE_SSAO_DEPTH_WRITE is OK with a NULL material pointer
  6609. modelrender->ForcedMaterialOverride( NULL, OVERRIDE_SSAO_DEPTH_WRITE );
  6610. {
  6611. VPROF_BUDGET( "DrawOpaqueRenderables", VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING );
  6612. //DrawOpaqueRenderables( pRenderContext, DEPTH_MODE_SSA0 );
  6613. DrawOpaqueRenderables( pRenderContext, RENDERABLES_RENDER_PATH_NORMAL, DEPTH_MODE_SSA0, NULL );
  6614. }
  6615. #if 0
  6616. if ( m_bRenderFlashlightDepthTranslucents || r_flashlightdepth_drawtranslucents.GetBool() )
  6617. {
  6618. VPROF_BUDGET( "DrawTranslucentRenderables", VPROF_BUDGETGROUP_SHADOW_DEPTH_TEXTURING );
  6619. DrawTranslucentRenderables( false, true );
  6620. }
  6621. #endif
  6622. modelrender->ForcedMaterialOverride( 0 );
  6623. m_DrawFlags &= ~DF_SSAO_DEPTH_PASS;
  6624. // pRenderContext.GetFrom( materials );
  6625. if ( IsX360() )
  6626. {
  6627. //Resolve() the depth texture here. Before the pop so the copy will recognize that the resolutions are the same
  6628. pRenderContext->CopyRenderTargetToTextureEx( NULL, -1, NULL, NULL );
  6629. }
  6630. render->PopView( pRenderContext, GetFrustum() );
  6631. pRenderContext.SafeRelease();
  6632. g_CurrentViewID = savedViewID;
  6633. }
  6634. //-----------------------------------------------------------------------------
  6635. // Draws the scene when there's no water or only cheap water
  6636. //-----------------------------------------------------------------------------
  6637. void CSimpleWorldView::Setup( const CViewSetup &view, int nClearFlags, bool bDrawSkybox, const VisibleFogVolumeInfo_t &fogInfo, const WaterRenderInfo_t &waterInfo, ViewCustomVisibility_t *pCustomVisibility )
  6638. {
  6639. BaseClass::Setup( view );
  6640. m_ClearFlags = nClearFlags;
  6641. m_DrawFlags = DF_DRAW_ENTITITES;
  6642. if ( !waterInfo.m_bOpaqueWater )
  6643. {
  6644. m_DrawFlags |= DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER;
  6645. }
  6646. else
  6647. {
  6648. bool bViewIntersectsWater = DoesViewPlaneIntersectWater( fogInfo.m_flWaterHeight, fogInfo.m_nVisibleFogVolume );
  6649. if( bViewIntersectsWater )
  6650. {
  6651. // have to draw both sides if we can see both.
  6652. m_DrawFlags |= DF_RENDER_UNDERWATER | DF_RENDER_ABOVEWATER;
  6653. }
  6654. else if ( fogInfo.m_bEyeInFogVolume )
  6655. {
  6656. m_DrawFlags |= DF_RENDER_UNDERWATER;
  6657. }
  6658. else
  6659. {
  6660. m_DrawFlags |= DF_RENDER_ABOVEWATER;
  6661. }
  6662. }
  6663. if ( waterInfo.m_bDrawWaterSurface )
  6664. {
  6665. if ( waterInfo.m_bPseudoTranslucentWater )
  6666. {
  6667. m_DrawFlags |= DF_RENDER_PSEUDO_TRANSLUCENT_WATER;
  6668. }
  6669. else
  6670. {
  6671. m_DrawFlags |= DF_RENDER_WATER;
  6672. }
  6673. }
  6674. if ( !fogInfo.m_bEyeInFogVolume && bDrawSkybox )
  6675. {
  6676. m_DrawFlags |= DF_DRAWSKYBOX;
  6677. }
  6678. #if defined( PORTAL2 )
  6679. m_DrawFlags |= ComputeSimpleWorldModelDrawFlags();
  6680. #endif // PORTAL2
  6681. m_pCustomVisibility = pCustomVisibility;
  6682. m_fogInfo = fogInfo;
  6683. }
  6684. //-----------------------------------------------------------------------------
  6685. // Draws the scene when there's no water or only cheap water
  6686. //-----------------------------------------------------------------------------
  6687. void CSimpleWorldView::Draw()
  6688. {
  6689. VPROF( "CViewRender::ViewDrawScene_NoWater" );
  6690. CMatRenderContextPtr pRenderContext( materials );
  6691. PIXEVENT( pRenderContext, "CSimpleWorldView::Draw" );
  6692. #if defined( _X360 )
  6693. pRenderContext->PushVertexShaderGPRAllocation( 32 ); //lean toward pixel shader threads
  6694. #endif
  6695. PROLOGUE_PASS_DRAWLISTS
  6696. DrawSetup( pRenderContext, 0, m_DrawFlags, 0 );
  6697. pRenderContext.SafeRelease();
  6698. if ( !m_fogInfo.m_bEyeInFogVolume )
  6699. {
  6700. EnableWorldFog();
  6701. }
  6702. else
  6703. {
  6704. m_ClearFlags |= VIEW_CLEAR_COLOR;
  6705. SetFogVolumeState( m_fogInfo, false );
  6706. pRenderContext.GetFrom( materials );
  6707. unsigned char ucFogColor[3];
  6708. pRenderContext->GetFogColor( ucFogColor );
  6709. pRenderContext->ClearColor4ub( ucFogColor[0], ucFogColor[1], ucFogColor[2], 255 );
  6710. }
  6711. pRenderContext.SafeRelease();
  6712. DrawExecute( 0, CurrentViewID(), 0 );
  6713. pRenderContext.GetFrom( materials );
  6714. pRenderContext->ClearColor4ub( 0, 0, 0, 255 );
  6715. #if defined( _X360 )
  6716. pRenderContext->PopVertexShaderGPRAllocation();
  6717. #endif
  6718. }
  6719. //-----------------------------------------------------------------------------
  6720. //
  6721. //-----------------------------------------------------------------------------
  6722. void CBaseWaterView::CalcWaterEyeAdjustments( const VisibleFogVolumeInfo_t &fogInfo,
  6723. float &newWaterHeight, float &waterZAdjust, bool bSoftwareUserClipPlane )
  6724. {
  6725. if( !bSoftwareUserClipPlane )
  6726. {
  6727. newWaterHeight = fogInfo.m_flWaterHeight;
  6728. waterZAdjust = 0.0f;
  6729. return;
  6730. }
  6731. newWaterHeight = fogInfo.m_flWaterHeight;
  6732. float eyeToWaterZDelta = origin[2] - fogInfo.m_flWaterHeight;
  6733. float epsilon = r_eyewaterepsilon.GetFloat();
  6734. waterZAdjust = 0.0f;
  6735. if( fabs( eyeToWaterZDelta ) < epsilon )
  6736. {
  6737. if( eyeToWaterZDelta > 0 )
  6738. {
  6739. newWaterHeight = origin[2] - epsilon;
  6740. }
  6741. else
  6742. {
  6743. newWaterHeight = origin[2] + epsilon;
  6744. }
  6745. waterZAdjust = newWaterHeight - fogInfo.m_flWaterHeight;
  6746. }
  6747. // Warning( "view.origin[2]: %f newWaterHeight: %f fogInfo.m_flWaterHeight: %f waterZAdjust: %f\n",
  6748. // ( float )view.origin[2], newWaterHeight, fogInfo.m_flWaterHeight, waterZAdjust );
  6749. }
  6750. //-----------------------------------------------------------------------------
  6751. //
  6752. //-----------------------------------------------------------------------------
  6753. void CBaseWaterView::CSoftwareIntersectionView::Setup( bool bAboveWater )
  6754. {
  6755. BaseClass::Setup( *GetOuter() );
  6756. m_DrawFlags = 0;
  6757. m_DrawFlags = ( bAboveWater ) ? DF_RENDER_UNDERWATER : DF_RENDER_ABOVEWATER;
  6758. }
  6759. //-----------------------------------------------------------------------------
  6760. //
  6761. //-----------------------------------------------------------------------------
  6762. void CBaseWaterView::CSoftwareIntersectionView::Draw()
  6763. {
  6764. CMatRenderContextPtr pRenderContext( materials );
  6765. PROLOGUE_PASS_DRAWLISTS
  6766. DrawSetup( pRenderContext, GetOuter()->m_waterHeight, m_DrawFlags, GetOuter()->m_waterZAdjust );
  6767. DrawExecute( GetOuter()->m_waterHeight, CurrentViewID(), GetOuter()->m_waterZAdjust );
  6768. }
  6769. //-----------------------------------------------------------------------------
  6770. // Draws the scene when the view point is above the level of the water
  6771. //-----------------------------------------------------------------------------
  6772. void CAboveWaterView::Setup( const CViewSetup &view, bool bDrawSkybox, const VisibleFogVolumeInfo_t &fogInfo, const WaterRenderInfo_t& waterInfo, ViewCustomVisibility_t *pCustomVisibility )
  6773. {
  6774. BaseClass::Setup( view );
  6775. m_bSoftwareUserClipPlane = g_pMaterialSystemHardwareConfig->UseFastClipping();
  6776. CalcWaterEyeAdjustments( fogInfo, m_waterHeight, m_waterZAdjust, m_bSoftwareUserClipPlane );
  6777. // BROKEN STUFF!
  6778. if ( m_waterZAdjust == 0.0f )
  6779. {
  6780. m_bSoftwareUserClipPlane = false;
  6781. }
  6782. m_DrawFlags = DF_RENDER_ABOVEWATER | DF_DRAW_ENTITITES;
  6783. #ifdef PORTAL
  6784. if ( g_pPortalRender->GetViewRecursionLevel() == 0 )
  6785. #endif
  6786. {
  6787. m_ClearFlags = VIEW_CLEAR_DEPTH;
  6788. }
  6789. #ifdef PORTAL
  6790. if( g_pPortalRender->ShouldObeyStencilForClears() )
  6791. m_ClearFlags |= VIEW_CLEAR_OBEY_STENCIL;
  6792. #endif
  6793. if ( bDrawSkybox )
  6794. {
  6795. m_DrawFlags |= DF_DRAWSKYBOX;
  6796. }
  6797. if ( waterInfo.m_bDrawWaterSurface )
  6798. {
  6799. if ( waterInfo.m_bPseudoTranslucentWater )
  6800. {
  6801. m_DrawFlags |= DF_RENDER_PSEUDO_TRANSLUCENT_WATER;
  6802. }
  6803. else
  6804. {
  6805. m_DrawFlags |= DF_RENDER_WATER;
  6806. }
  6807. }
  6808. if ( !waterInfo.m_bRefract && !waterInfo.m_bOpaqueWater )
  6809. {
  6810. m_DrawFlags |= DF_RENDER_UNDERWATER;
  6811. }
  6812. #if defined( PORTAL2 )
  6813. m_DrawFlags |= ComputeSimpleWorldModelDrawFlags();
  6814. #endif // PORTAL2
  6815. m_fogInfo = fogInfo;
  6816. m_waterInfo = waterInfo;
  6817. m_pCustomVisibility = pCustomVisibility;
  6818. }
  6819. //-----------------------------------------------------------------------------
  6820. //
  6821. //-----------------------------------------------------------------------------
  6822. void CAboveWaterView::Draw()
  6823. {
  6824. VPROF( "CViewRender::ViewDrawScene_EyeAboveWater" );
  6825. // eye is outside of water
  6826. CMatRenderContextPtr pRenderContext( materials );
  6827. PIXEVENT( pRenderContext, "CAboveWaterView::Draw" );
  6828. // render the reflection
  6829. if( m_waterInfo.m_bReflect )
  6830. {
  6831. m_ReflectionView.Setup( m_waterInfo.m_bReflectEntities, m_waterInfo.m_bReflectOnlyMarkedEntities, m_waterInfo.m_bReflect2DSkybox );
  6832. m_pMainView->AddViewToScene( &m_ReflectionView );
  6833. }
  6834. bool bViewIntersectsWater = false;
  6835. // render refraction
  6836. if ( m_waterInfo.m_bRefract )
  6837. {
  6838. m_RefractionView.Setup();
  6839. m_pMainView->AddViewToScene( &m_RefractionView );
  6840. if( !m_bSoftwareUserClipPlane )
  6841. {
  6842. bViewIntersectsWater = DoesViewPlaneIntersectWater( m_fogInfo.m_flWaterHeight, m_fogInfo.m_nVisibleFogVolume );
  6843. }
  6844. }
  6845. #ifdef PORTAL
  6846. if( g_pPortalRender->ShouldObeyStencilForClears() )
  6847. m_ClearFlags |= VIEW_CLEAR_OBEY_STENCIL;
  6848. #endif
  6849. // NOTE!!!!! YOU CAN ONLY DO THIS IF YOU HAVE HARDWARE USER CLIP PLANES!!!!!!
  6850. bool bHardwareUserClipPlanes = !g_pMaterialSystemHardwareConfig->UseFastClipping();
  6851. if( bViewIntersectsWater && bHardwareUserClipPlanes )
  6852. {
  6853. // This is necessary to keep the non-water fogged world from drawing underwater in
  6854. // the case where we want to partially see into the water.
  6855. m_DrawFlags |= DF_CLIP_Z | DF_CLIP_BELOW;
  6856. }
  6857. PROLOGUE_PASS_DRAWLISTS
  6858. // render the world
  6859. DrawSetup( pRenderContext, m_waterHeight, m_DrawFlags, m_waterZAdjust );
  6860. EnableWorldFog();
  6861. DrawExecute( m_waterHeight, CurrentViewID(), m_waterZAdjust );
  6862. if ( m_waterInfo.m_bRefract )
  6863. {
  6864. if ( m_bSoftwareUserClipPlane )
  6865. {
  6866. m_SoftwareIntersectionView.Setup( true );
  6867. m_pMainView->AddViewToScene( &m_SoftwareIntersectionView );
  6868. }
  6869. else if ( bViewIntersectsWater )
  6870. {
  6871. m_IntersectionView.Setup();
  6872. m_pMainView->AddViewToScene( &m_IntersectionView );
  6873. }
  6874. }
  6875. }
  6876. //-----------------------------------------------------------------------------
  6877. //
  6878. //-----------------------------------------------------------------------------
  6879. void CAboveWaterView::CReflectionView::Setup( bool bReflectEntities, bool bReflectOnlyMarkedEntities, bool bReflect2DSkybox )
  6880. {
  6881. BaseClass::Setup( *GetOuter() );
  6882. m_ClearFlags = VIEW_CLEAR_DEPTH;
  6883. m_DrawFlags = DF_RENDER_REFLECTION | DF_CLIP_Z | DF_CLIP_BELOW |
  6884. DF_RENDER_ABOVEWATER;
  6885. if ( bReflect2DSkybox )
  6886. {
  6887. m_DrawFlags |= DF_DRAWSKYBOX;
  6888. }
  6889. else
  6890. {
  6891. m_ClearFlags |= VIEW_CLEAR_COLOR;
  6892. }
  6893. bool bSimpleWorldModeWaterReflection;
  6894. int nSimpleWorldModelRecursionLevel;
  6895. float flSimpleWorldModelDrawBeyondDistance;
  6896. GetSimpleWorldModelConfiguration( bSimpleWorldModeWaterReflection, nSimpleWorldModelRecursionLevel, flSimpleWorldModelDrawBeyondDistance );
  6897. if ( bSimpleWorldModeWaterReflection )
  6898. {
  6899. m_DrawFlags |= DF_DRAW_SIMPLE_WORLD_MODEL | DF_FAST_ENTITY_RENDERING | DF_DRAW_ENTITITES;
  6900. }
  6901. else
  6902. {
  6903. if( bReflectEntities )
  6904. {
  6905. Assert( !bReflectOnlyMarkedEntities );
  6906. m_DrawFlags |= DF_DRAW_ENTITITES;
  6907. }
  6908. else if ( bReflectOnlyMarkedEntities )
  6909. {
  6910. m_DrawFlags |= DF_FAST_ENTITY_RENDERING | DF_DRAW_ENTITITES;
  6911. }
  6912. }
  6913. }
  6914. //-----------------------------------------------------------------------------
  6915. //
  6916. //-----------------------------------------------------------------------------
  6917. void CAboveWaterView::CReflectionView::Draw()
  6918. {
  6919. #ifdef PORTAL
  6920. g_pPortalRender->WaterRenderingHandler_PreReflection();
  6921. #endif
  6922. CMatRenderContextPtr pRenderContext( materials );
  6923. PIXEVENT( pRenderContext, "CAboveWaterView::CReflectionView" );
  6924. g_CascadeLightManager.BeginReflectionView();
  6925. // Store off view origin and angles and set the new view
  6926. int nSaveViewID = CurrentViewID();
  6927. Vector vecOldOrigin = CurrentViewOrigin();
  6928. QAngle vecOldAngles = CurrentViewAngles();
  6929. SetupCurrentView( origin, angles, VIEW_REFLECTION );
  6930. // Disable occlusion visualization in reflection
  6931. bool bVisOcclusion = r_visocclusion.GetBool();
  6932. r_visocclusion.SetValue( 0 );
  6933. PROLOGUE_PASS_DRAWLISTS
  6934. DrawSetup( pRenderContext, GetOuter()->m_fogInfo.m_flWaterHeight, m_DrawFlags, 0.0f, GetOuter()->m_fogInfo.m_nVisibleFogVolumeLeaf );
  6935. BEGIN_2PASS_DRAW_BLOCK
  6936. EnableWorldFog();
  6937. pRenderContext->ClearColor4ub( 0, 0, 0, 255 );
  6938. END_2PASS_BLOCK
  6939. DrawExecute( GetOuter()->m_fogInfo.m_flWaterHeight, VIEW_REFLECTION, 0.0f );
  6940. r_visocclusion.SetValue( bVisOcclusion );
  6941. #ifdef PORTAL
  6942. // deal with stencil
  6943. g_pPortalRender->WaterRenderingHandler_PostReflection();
  6944. #endif
  6945. // finish off the view and restore the previous view.
  6946. SetupCurrentView( vecOldOrigin, vecOldAngles, ( view_id_t )nSaveViewID );
  6947. g_CascadeLightManager.EndReflectionView();
  6948. // This is here for multithreading
  6949. pRenderContext->Flush();
  6950. }
  6951. //-----------------------------------------------------------------------------
  6952. //
  6953. //-----------------------------------------------------------------------------
  6954. void CAboveWaterView::CRefractionView::Setup()
  6955. {
  6956. BaseClass::Setup( *GetOuter() );
  6957. m_ClearFlags = VIEW_CLEAR_COLOR | VIEW_CLEAR_DEPTH;
  6958. m_DrawFlags = DF_RENDER_REFRACTION | DF_CLIP_Z |
  6959. DF_RENDER_UNDERWATER | DF_FUDGE_UP |
  6960. DF_DRAW_ENTITITES ;
  6961. }
  6962. // PS3 - warning - Refraction not yet fully supported on SPU BuildWorld/Renderables parallel job path
  6963. // so we disable that path for now when drawing refraction views and turn it back on at the end
  6964. //-----------------------------------------------------------------------------
  6965. //
  6966. //-----------------------------------------------------------------------------
  6967. void CAboveWaterView::CRefractionView::Draw()
  6968. {
  6969. #if defined(_PS3)
  6970. BEGIN_2PASS_DRAW_BLOCK
  6971. // don't support PruneWorldLists on SPU yet, so can't support refraction
  6972. bool bBuildViewSPU = g_viewBuilder.IsSPUBuildRWJobsOn();
  6973. g_viewBuilder.SPUBuildRWJobsOn( false );
  6974. #endif
  6975. PS3_SPUPATH_INVALID( "CAboveWaterView::CRefractionView::Draw" );
  6976. #ifdef PORTAL
  6977. g_pPortalRender->WaterRenderingHandler_PreRefraction();
  6978. #endif
  6979. CMatRenderContextPtr pRenderContext( materials );
  6980. PIXEVENT( pRenderContext, "CAboveWaterView::CRefractionView" );
  6981. // Store off view origin and angles and set the new view
  6982. int nSaveViewID = CurrentViewID();
  6983. Vector vecOldOrigin = CurrentViewOrigin();
  6984. QAngle vecOldAngles = CurrentViewAngles();
  6985. SetupCurrentView( origin, angles, VIEW_REFRACTION );
  6986. PROLOGUE_PASS_DRAWLISTS
  6987. DrawSetup( pRenderContext, GetOuter()->m_waterHeight, m_DrawFlags, GetOuter()->m_waterZAdjust );
  6988. BEGIN_2PASS_DRAW_BLOCK
  6989. SetFogVolumeState( GetOuter()->m_fogInfo, true );
  6990. SetClearColorToFogColor();
  6991. END_2PASS_BLOCK
  6992. DrawExecute( GetOuter()->m_waterHeight, VIEW_REFRACTION, GetOuter()->m_waterZAdjust );
  6993. #ifdef PORTAL
  6994. // deal with stencil
  6995. g_pPortalRender->WaterRenderingHandler_PostRefraction();
  6996. #endif
  6997. // finish off the view. restore the previous view.
  6998. SetupCurrentView( vecOldOrigin, vecOldAngles, ( view_id_t )nSaveViewID );
  6999. BEGIN_2PASS_DRAW_BLOCK
  7000. // This is here for multithreading
  7001. pRenderContext->ClearColor4ub( 0, 0, 0, 255 );
  7002. pRenderContext->Flush();
  7003. END_2PASS_BLOCK
  7004. #if defined(_PS3)
  7005. g_viewBuilder.SPUBuildRWJobsOn( bBuildViewSPU );
  7006. END_2PASS_BLOCK
  7007. #endif
  7008. }
  7009. //-----------------------------------------------------------------------------
  7010. //
  7011. //-----------------------------------------------------------------------------
  7012. void CAboveWaterView::CIntersectionView::Setup()
  7013. {
  7014. BaseClass::Setup( *GetOuter() );
  7015. m_DrawFlags = DF_RENDER_UNDERWATER | DF_CLIP_Z | DF_DRAW_ENTITITES;
  7016. }
  7017. //-----------------------------------------------------------------------------
  7018. //
  7019. //-----------------------------------------------------------------------------
  7020. void CAboveWaterView::CIntersectionView::Draw()
  7021. {
  7022. PS3_SPUPATH_INVALID( "CAboveWaterView::CIntersectionView::Draw" );
  7023. CMatRenderContextPtr pRenderContext( materials );
  7024. PROLOGUE_PASS_DRAWLISTS
  7025. DrawSetup( pRenderContext, GetOuter()->m_fogInfo.m_flWaterHeight, m_DrawFlags, 0 );
  7026. SetFogVolumeState( GetOuter()->m_fogInfo, true );
  7027. SetClearColorToFogColor( );
  7028. DrawExecute( GetOuter()->m_fogInfo.m_flWaterHeight, VIEW_NONE, 0 );
  7029. pRenderContext->ClearColor4ub( 0, 0, 0, 255 );
  7030. }
  7031. //-----------------------------------------------------------------------------
  7032. // Draws the scene when the view point is under the level of the water
  7033. //-----------------------------------------------------------------------------
  7034. void CUnderWaterView::Setup( const CViewSetup &view, bool bDrawSkybox, const VisibleFogVolumeInfo_t &fogInfo, const WaterRenderInfo_t& waterInfo, ViewCustomVisibility_t *pCustomVisibility )
  7035. {
  7036. BaseClass::Setup( view );
  7037. m_bSoftwareUserClipPlane = g_pMaterialSystemHardwareConfig->UseFastClipping();
  7038. CalcWaterEyeAdjustments( fogInfo, m_waterHeight, m_waterZAdjust, m_bSoftwareUserClipPlane );
  7039. IMaterial *pWaterMaterial = fogInfo.m_pFogVolumeMaterial;
  7040. IMaterialVar *pScreenOverlayVar = pWaterMaterial->FindVar( "$underwateroverlay", NULL, false );
  7041. if ( pScreenOverlayVar && ( pScreenOverlayVar->IsDefined() ) )
  7042. {
  7043. char const *pOverlayName = pScreenOverlayVar->GetStringValue();
  7044. if ( pOverlayName[0] != '0' ) // fixme!!!
  7045. {
  7046. IMaterial *pOverlayMaterial = materials->FindMaterial( pOverlayName, TEXTURE_GROUP_OTHER );
  7047. m_pMainView->SetWaterOverlayMaterial( pOverlayMaterial );
  7048. }
  7049. }
  7050. // NOTE: We're not drawing the 2d skybox under water since it's assumed to not be visible.
  7051. // render the world underwater
  7052. // Clear the color to get the appropriate underwater fog color
  7053. m_DrawFlags = DF_FUDGE_UP | DF_RENDER_UNDERWATER | DF_DRAW_ENTITITES;
  7054. #ifdef PORTAL
  7055. if ( g_pPortalRender->GetViewRecursionLevel() == 0 )
  7056. #endif
  7057. {
  7058. m_ClearFlags = VIEW_CLEAR_DEPTH;
  7059. }
  7060. if( !m_bSoftwareUserClipPlane )
  7061. {
  7062. m_DrawFlags |= DF_CLIP_Z;
  7063. }
  7064. if ( waterInfo.m_bDrawWaterSurface )
  7065. {
  7066. if ( waterInfo.m_bPseudoTranslucentWater )
  7067. {
  7068. m_DrawFlags |= DF_RENDER_PSEUDO_TRANSLUCENT_WATER;
  7069. }
  7070. else
  7071. {
  7072. m_DrawFlags |= DF_RENDER_WATER;
  7073. }
  7074. }
  7075. if ( !waterInfo.m_bRefract && !waterInfo.m_bOpaqueWater )
  7076. {
  7077. m_DrawFlags |= DF_RENDER_ABOVEWATER;
  7078. }
  7079. m_fogInfo = fogInfo;
  7080. m_waterInfo = waterInfo;
  7081. m_bDrawSkybox = bDrawSkybox;
  7082. m_pCustomVisibility = pCustomVisibility;
  7083. }
  7084. //-----------------------------------------------------------------------------
  7085. //
  7086. //-----------------------------------------------------------------------------
  7087. void CUnderWaterView::Draw()
  7088. {
  7089. // FIXME: The 3d skybox shouldn't be drawn when the eye is under water
  7090. VPROF( "CViewRender::ViewDrawScene_EyeUnderWater" );
  7091. CMatRenderContextPtr pRenderContext( materials );
  7092. PIXEVENT( pRenderContext, "CUnderWaterView::Draw" );
  7093. // render refraction (out of water)
  7094. if ( m_waterInfo.m_bRefract )
  7095. {
  7096. m_RefractionView.Setup( );
  7097. m_pMainView->AddViewToScene( &m_RefractionView );
  7098. }
  7099. if ( !m_waterInfo.m_bRefract )
  7100. {
  7101. SetFogVolumeState( m_fogInfo, true );
  7102. unsigned char ucFogColor[3];
  7103. pRenderContext->GetFogColor( ucFogColor );
  7104. pRenderContext->ClearColor4ub( ucFogColor[0], ucFogColor[1], ucFogColor[2], 255 );
  7105. }
  7106. PROLOGUE_PASS_DRAWLISTS
  7107. DrawSetup( pRenderContext, m_waterHeight, m_DrawFlags, m_waterZAdjust );
  7108. SetFogVolumeState( m_fogInfo, false );
  7109. DrawExecute( m_waterHeight, CurrentViewID(), m_waterZAdjust );
  7110. m_ClearFlags = 0;
  7111. if( m_waterZAdjust != 0.0f && m_bSoftwareUserClipPlane && m_waterInfo.m_bRefract )
  7112. {
  7113. m_SoftwareIntersectionView.Setup( false );
  7114. m_pMainView->AddViewToScene( &m_SoftwareIntersectionView );
  7115. }
  7116. pRenderContext->ClearColor4ub( 0, 0, 0, 255 );
  7117. }
  7118. //-----------------------------------------------------------------------------
  7119. //
  7120. //-----------------------------------------------------------------------------
  7121. void CUnderWaterView::CRefractionView::Setup()
  7122. {
  7123. BaseClass::Setup( *GetOuter() );
  7124. // NOTE: Refraction renders into the back buffer, over the top of the 3D skybox
  7125. // It is then blitted out into the refraction target. This is so that
  7126. // we only have to set up 3d sky vis once, and only render it once also!
  7127. m_DrawFlags = DF_CLIP_Z |
  7128. DF_CLIP_BELOW | DF_RENDER_ABOVEWATER |
  7129. DF_DRAW_ENTITITES;
  7130. m_ClearFlags = VIEW_CLEAR_DEPTH;
  7131. if ( GetOuter()->m_bDrawSkybox )
  7132. {
  7133. m_ClearFlags |= VIEW_CLEAR_COLOR;
  7134. m_DrawFlags |= DF_DRAWSKYBOX | DF_CLIP_SKYBOX;
  7135. }
  7136. }
  7137. //-----------------------------------------------------------------------------
  7138. //
  7139. //-----------------------------------------------------------------------------
  7140. void CUnderWaterView::CRefractionView::Draw()
  7141. {
  7142. PS3_SPUPATH_INVALID( "CUnderWaterView::CRefractionView::Draw" );
  7143. CMatRenderContextPtr pRenderContext( materials );
  7144. SetFogVolumeState( GetOuter()->m_fogInfo, true );
  7145. unsigned char ucFogColor[3];
  7146. pRenderContext->GetFogColor( ucFogColor );
  7147. pRenderContext->ClearColor4ub( ucFogColor[0], ucFogColor[1], ucFogColor[2], 255 );
  7148. PROLOGUE_PASS_DRAWLISTS
  7149. DrawSetup( pRenderContext, GetOuter()->m_waterHeight, m_DrawFlags, GetOuter()->m_waterZAdjust );
  7150. EnableWorldFog();
  7151. DrawExecute( GetOuter()->m_waterHeight, VIEW_REFRACTION, GetOuter()->m_waterZAdjust );
  7152. BEGIN_2PASS_DRAW_BLOCK
  7153. Rect_t srcRect;
  7154. srcRect.x = x;
  7155. srcRect.y = y;
  7156. srcRect.width = width;
  7157. srcRect.height = height;
  7158. ITexture *pTexture = GetWaterRefractionTexture();
  7159. pRenderContext->CopyRenderTargetToTextureEx( pTexture, 0, &srcRect, NULL );
  7160. END_2PASS_BLOCK
  7161. }
  7162. //-----------------------------------------------------------------------------
  7163. //
  7164. // Reflective glass view starts here
  7165. //
  7166. //-----------------------------------------------------------------------------
  7167. //-----------------------------------------------------------------------------
  7168. // Draws the scene when the view contains reflective glass
  7169. //-----------------------------------------------------------------------------
  7170. void CReflectiveGlassView::Setup( const CViewSetup &view, int nClearFlags, bool bDrawSkybox,
  7171. const VisibleFogVolumeInfo_t &fogInfo, const WaterRenderInfo_t &waterInfo, const cplane_t &reflectionPlane )
  7172. {
  7173. BaseClass::Setup( view, nClearFlags, bDrawSkybox, fogInfo, waterInfo, NULL );
  7174. m_ReflectionPlane = reflectionPlane;
  7175. }
  7176. bool CReflectiveGlassView::AdjustView( float flWaterHeight )
  7177. {
  7178. ITexture *pTexture = GetWaterReflectionTexture();
  7179. // Use the aspect ratio of the main view! So, don't recompute it here
  7180. x = y = 0;
  7181. width = pTexture->GetActualWidth();
  7182. height = pTexture->GetActualHeight();
  7183. // Reflect the camera origin + vectors around the reflection plane
  7184. float flDist = DotProduct( origin, m_ReflectionPlane.normal ) - m_ReflectionPlane.dist;
  7185. VectorMA( origin, - 2.0f * flDist, m_ReflectionPlane.normal, origin );
  7186. Vector vecForward, vecUp;
  7187. AngleVectors( angles, &vecForward, NULL, &vecUp );
  7188. float flDot = DotProduct( vecForward, m_ReflectionPlane.normal );
  7189. VectorMA( vecForward, - 2.0f * flDot, m_ReflectionPlane.normal, vecForward );
  7190. flDot = DotProduct( vecUp, m_ReflectionPlane.normal );
  7191. VectorMA( vecUp, - 2.0f * flDot, m_ReflectionPlane.normal, vecUp );
  7192. VectorAngles( vecForward, vecUp, angles );
  7193. return true;
  7194. }
  7195. void CReflectiveGlassView::PushView( float waterHeight )
  7196. {
  7197. CMatRenderContextPtr pRenderContext( materials );
  7198. render->Push3DView( pRenderContext, *this, m_ClearFlags, GetWaterReflectionTexture(), GetFrustum() );
  7199. Vector4D plane;
  7200. VectorCopy( m_ReflectionPlane.normal, plane.AsVector3D() );
  7201. plane.w = m_ReflectionPlane.dist + 0.1f;
  7202. pRenderContext->PushCustomClipPlane( plane.Base() );
  7203. }
  7204. void CReflectiveGlassView::PopView( )
  7205. {
  7206. CMatRenderContextPtr pRenderContext( materials );
  7207. pRenderContext->PopCustomClipPlane( );
  7208. render->PopView( pRenderContext, GetFrustum() );
  7209. }
  7210. //-----------------------------------------------------------------------------
  7211. // Renders reflective or refractive parts of glass
  7212. //-----------------------------------------------------------------------------
  7213. void CReflectiveGlassView::Draw()
  7214. {
  7215. VPROF( "CReflectiveGlassView::Draw" );
  7216. CMatRenderContextPtr pRenderContext( materials );
  7217. PIXEVENT( pRenderContext, "CReflectiveGlassView::Draw" );
  7218. // Disable occlusion visualization in reflection
  7219. bool bVisOcclusion = r_visocclusion.GetBool();
  7220. r_visocclusion.SetValue( 0 );
  7221. BaseClass::Draw();
  7222. r_visocclusion.SetValue( bVisOcclusion );
  7223. pRenderContext->ClearColor4ub( 0, 0, 0, 255 );
  7224. pRenderContext->Flush();
  7225. }
  7226. //-----------------------------------------------------------------------------
  7227. // Draws the scene when the view contains reflective glass
  7228. //-----------------------------------------------------------------------------
  7229. void CRefractiveGlassView::Setup( const CViewSetup &view, int nClearFlags, bool bDrawSkybox,
  7230. const VisibleFogVolumeInfo_t &fogInfo, const WaterRenderInfo_t &waterInfo, const cplane_t &reflectionPlane )
  7231. {
  7232. BaseClass::Setup( view, nClearFlags, bDrawSkybox, fogInfo, waterInfo, NULL );
  7233. m_ReflectionPlane = reflectionPlane;
  7234. }
  7235. bool CRefractiveGlassView::AdjustView( float flWaterHeight )
  7236. {
  7237. ITexture *pTexture = GetWaterRefractionTexture();
  7238. // Use the aspect ratio of the main view! So, don't recompute it here
  7239. x = y = 0;
  7240. width = pTexture->GetActualWidth();
  7241. height = pTexture->GetActualHeight();
  7242. return true;
  7243. }
  7244. void CRefractiveGlassView::PushView( float waterHeight )
  7245. {
  7246. CMatRenderContextPtr pRenderContext( materials );
  7247. render->Push3DView( pRenderContext, *this, m_ClearFlags, GetWaterRefractionTexture(), GetFrustum() );
  7248. Vector4D plane;
  7249. VectorMultiply( m_ReflectionPlane.normal, -1, plane.AsVector3D() );
  7250. plane.w = -m_ReflectionPlane.dist + 0.1f;
  7251. pRenderContext->PushCustomClipPlane( plane.Base() );
  7252. }
  7253. void CRefractiveGlassView::PopView( )
  7254. {
  7255. CMatRenderContextPtr pRenderContext( materials );
  7256. pRenderContext->PopCustomClipPlane( );
  7257. render->PopView( pRenderContext, GetFrustum() );
  7258. }
  7259. //-----------------------------------------------------------------------------
  7260. // Renders reflective or refractive parts of glass
  7261. //-----------------------------------------------------------------------------
  7262. void CRefractiveGlassView::Draw()
  7263. {
  7264. VPROF( "CRefractiveGlassView::Draw" );
  7265. CMatRenderContextPtr pRenderContext( materials );
  7266. PIXEVENT( pRenderContext, "CRefractiveGlassView::Draw" );
  7267. BaseClass::Draw();
  7268. pRenderContext->ClearColor4ub( 0, 0, 0, 255 );
  7269. pRenderContext->Flush();
  7270. }
  7271. //-----------------------------------------------------------------------------
  7272. // Purpose:
  7273. //-----------------------------------------------------------------------------
  7274. void FrustumCache_t::Add( const CViewSetup *pView, int iSlot )
  7275. {
  7276. // Check for a valid view setup.
  7277. if ( !pView )
  7278. return;
  7279. // Create the perspective frustum.
  7280. GeneratePerspectiveFrustum( pView->origin, pView->angles, pView->zNear, pView->zFar, pView->fov, pView->m_flAspectRatio, m_Frustums[iSlot] );
  7281. }
  7282. #if defined(_PS3)
  7283. //-----------------------------------------------------------------------------
  7284. // PS3 - CConcurrentViewBuilderPS3 methods
  7285. //-----------------------------------------------------------------------------
  7286. CConcurrentViewBuilderPS3::CConcurrentViewBuilderPS3()
  7287. {
  7288. m_buildViewID = -1;
  7289. m_bSPUBuildRWJobsOn = false;
  7290. m_passFlags = 0;
  7291. for( int lp = 0; lp < MAX_CONCURRENT_BUILDVIEWS; lp++ )
  7292. {
  7293. m_gAreaFrustum[lp].EnsureCapacity(16);
  7294. m_gAreaFrustum[lp].SetCount(0);
  7295. }
  7296. }
  7297. void CConcurrentViewBuilderPS3::Init( void )
  7298. {
  7299. m_buildViewID = -1;
  7300. m_bSPUBuildRWJobsOn = false;
  7301. m_passFlags = 0;
  7302. for( int lp = 0; lp < MAX_CONCURRENT_BUILDVIEWS; lp++ )
  7303. {
  7304. m_gAreaFrustum[lp].EnsureCapacity(16);
  7305. m_gAreaFrustum[lp].SetCount(0);
  7306. }
  7307. }
  7308. void CConcurrentViewBuilderPS3::Purge( void )
  7309. {
  7310. for( int lp = 0; lp < MAX_CONCURRENT_BUILDVIEWS; lp++ )
  7311. {
  7312. m_gAreaFrustum[lp].Purge();
  7313. }
  7314. };
  7315. void CConcurrentViewBuilderPS3::ResetBuildViewID( void )
  7316. {
  7317. m_buildViewID = -1;
  7318. m_nextFreeBuildViewID = 0;
  7319. m_pBuildViewStack = m_buildViewStack - 1;
  7320. m_buildViewStack[ 0 ] = -1;
  7321. };
  7322. // get current view index
  7323. int CConcurrentViewBuilderPS3::GetBuildViewID( void )
  7324. {
  7325. if( m_buildViewID == -1 )
  7326. {
  7327. // bad view initialisation
  7328. Warning("*** BAD BUILD VIEW INITIALIZATION ***\n");
  7329. return 0;
  7330. }
  7331. return m_buildViewID;
  7332. };
  7333. // call at the start of each view
  7334. void CConcurrentViewBuilderPS3::PushBuildView( void )
  7335. {
  7336. m_pBuildViewStack++;
  7337. if( m_pBuildViewStack >= &m_buildViewStack[MAX_CONCURRENT_BUILDVIEWS] )
  7338. {
  7339. Error("*** exceeded concurrent buildview push ***\n");
  7340. }
  7341. if( m_nextFreeBuildViewID >= MAX_CONCURRENT_BUILDVIEWS )
  7342. {
  7343. Error("*** exceeded max concurrent buildviews ***\n");
  7344. }
  7345. *m_pBuildViewStack = m_nextFreeBuildViewID;
  7346. m_buildViewID = *m_pBuildViewStack;
  7347. m_nextFreeBuildViewID++;
  7348. }
  7349. void CConcurrentViewBuilderPS3::PopBuildView( void )
  7350. {
  7351. if( m_pBuildViewStack == m_buildViewStack )
  7352. {
  7353. m_buildViewID = *m_pBuildViewStack;
  7354. m_pBuildViewStack--;
  7355. }
  7356. else
  7357. {
  7358. m_pBuildViewStack--;
  7359. m_buildViewID = *m_pBuildViewStack;
  7360. }
  7361. }
  7362. void CConcurrentViewBuilderPS3::SyncViewBuilderJobs( void )
  7363. {
  7364. // sync all ports, only used for debugging multipass views
  7365. }
  7366. IWorldRenderList *CConcurrentViewBuilderPS3::GetWorldRenderListElement( void )
  7367. {
  7368. if( m_buildViewID == -1 )
  7369. {
  7370. Warning( "PS3 ViewBuilder Begin/End Error - Accessing WorldRenderListElement(-1)\n" );
  7371. return NULL;
  7372. }
  7373. else
  7374. {
  7375. return m_pWorldRenderListCache[ m_buildViewID ];
  7376. }
  7377. }
  7378. void CConcurrentViewBuilderPS3::SetWorldRenderListElement( IWorldRenderList *pRenderList )
  7379. {
  7380. if( m_buildViewID == -1 )
  7381. {
  7382. Warning( "PS3 ViewBuilder Begin/End Error - Setting WorldRenderListElement(-1)\n" );
  7383. return;
  7384. }
  7385. else
  7386. {
  7387. m_pWorldRenderListCache[ m_buildViewID ] = pRenderList;
  7388. }
  7389. }
  7390. unsigned int CConcurrentViewBuilderPS3::GetVisFlags( void )
  7391. {
  7392. if( m_buildViewID == -1 )
  7393. {
  7394. Warning( "PS3 ViewBuilder Begin/End Error - GetVisFlags(-1)\n" );
  7395. return 0;
  7396. }
  7397. else
  7398. {
  7399. return m_visFlags[ m_buildViewID ];
  7400. }
  7401. }
  7402. void CConcurrentViewBuilderPS3::SetVisFlags( unsigned int visFlags )
  7403. {
  7404. if( m_buildViewID == -1 )
  7405. {
  7406. Warning( "PS3 ViewBuilder Begin/End Error - SetVisFlags(-1)\n" );
  7407. return;
  7408. }
  7409. else
  7410. {
  7411. m_visFlags[ m_buildViewID ] = visFlags;
  7412. }
  7413. }
  7414. void* CConcurrentViewBuilderPS3::GetBuildViewVolumeCuller( void )
  7415. {
  7416. if( m_buildViewID == -1 )
  7417. {
  7418. Warning( "PS3 ViewBuilder Begin/End Error - GetBuildViewVolumeCuller(-1)\n" );
  7419. return NULL;
  7420. }
  7421. else
  7422. {
  7423. return &m_volumeCullerCache[ m_buildViewID ];
  7424. }
  7425. }
  7426. Frustum_t *CConcurrentViewBuilderPS3::GetBuildViewFrustum( void )
  7427. {
  7428. if( m_buildViewID == -1 )
  7429. {
  7430. Warning( "PS3 ViewBuilder Begin/End Error - GetBuildViewFrustum(-1)\n" );
  7431. return NULL;
  7432. }
  7433. else
  7434. {
  7435. return &m_gFrustum[ m_buildViewID ];
  7436. }
  7437. }
  7438. Frustum_t *CConcurrentViewBuilderPS3::GetBuildViewAreaFrustum( void )
  7439. {
  7440. if( m_buildViewID == -1 )
  7441. {
  7442. Warning( "PS3 ViewBuilder Begin/End Error - GetBuildViewAreaFrustum(-1)\n" );
  7443. return NULL;
  7444. }
  7445. else
  7446. {
  7447. return m_gAreaFrustum[ m_buildViewID ].Base();
  7448. }
  7449. }
  7450. unsigned char *CConcurrentViewBuilderPS3::GetBuildViewRenderAreaBits( void )
  7451. {
  7452. if( m_buildViewID == -1 )
  7453. {
  7454. Warning( "PS3 ViewBuilder Begin/End Error - GetBuildViewRenderAreaBits(-1)\n" );
  7455. return NULL;
  7456. }
  7457. else
  7458. {
  7459. return m_gRenderAreaBits[ m_buildViewID ];
  7460. }
  7461. };
  7462. int CConcurrentViewBuilderPS3::GetNumAreaFrustum( void )
  7463. {
  7464. if( m_buildViewID == -1 )
  7465. {
  7466. Warning( "PS3 ViewBuilder Begin/End Error - GetNumAreaFrustum(-1)\n" );
  7467. return 0;
  7468. }
  7469. else
  7470. {
  7471. return m_gAreaFrustum[ m_buildViewID ].Count();
  7472. }
  7473. };
  7474. Frustum_t *CConcurrentViewBuilderPS3::GetBuildViewAreaFrustumID( int frustumID )
  7475. {
  7476. if( m_buildViewID == -1 )
  7477. {
  7478. Warning( "PS3 ViewBuilder Begin/End Error - GetNumAreaFrustum(-1)\n" );
  7479. return NULL;
  7480. }
  7481. else
  7482. {
  7483. return &m_gAreaFrustum[ m_buildViewID ][ frustumID ];
  7484. }
  7485. };
  7486. void CConcurrentViewBuilderPS3::CacheFrustumData( Frustum_t *pFrustum, Frustum_t *pAreaFrustum, void *pRenderAreaBits, int numArea, bool bViewerInSolidSpace )
  7487. {
  7488. if( m_buildViewID == -1 )
  7489. return;
  7490. // cache g_Frustum
  7491. memcpy( &m_gFrustum[ m_buildViewID ], pFrustum, sizeof(Frustum_t) );
  7492. // cache g_RenderAreaBits
  7493. memcpy( &m_gRenderAreaBits[ m_buildViewID ], pRenderAreaBits, sizeof(m_gRenderAreaBits[ m_buildViewID ]) );
  7494. // cache viewerinSolidSpace
  7495. m_bViewerInSolidSpace[ m_buildViewID ] = bViewerInSolidSpace;
  7496. // cache g_AreaFrustum
  7497. m_gAreaFrustum[ m_buildViewID ].CopyArray( pAreaFrustum, numArea );
  7498. }
  7499. void CConcurrentViewBuilderPS3::CacheBuildViewVolumeCuller( void *pVC )
  7500. {
  7501. if( (m_buildViewID == -1) || (pVC == NULL) )
  7502. return;
  7503. memcpy( &m_volumeCullerCache[ m_buildViewID ], pVC, sizeof(CVolumeCuller) );
  7504. }
  7505. // push all buildrenderable jobs - we have descriptors and cached data ready
  7506. // renderable jobs can't run concurrently and must sync to the matching buildworldjob
  7507. void CConcurrentViewBuilderPS3::PushBuildRenderableJobs( void )
  7508. {
  7509. SNPROF("CConcurrentViewBuilder::PushBuildRenderableJobs");
  7510. int numViews = m_buildViewID + 1;
  7511. unsigned int syncTagR, syncTagW, syncMask;
  7512. syncMask = 0;
  7513. unsigned int lastSyncTagR = 0;
  7514. //Msg("PushBuildRenderables\n");
  7515. for( int lp = 0; lp < numViews; lp++ )
  7516. {
  7517. PS3BuildRenderablesJobData *pJobData = g_pBuildRenderablesJob->GetJobData( lp );
  7518. job_buildrenderables::JobDescriptor_t *pJobDescriptor = &pJobData->jobDescriptor;
  7519. syncTagW = (lp+1);
  7520. // alternative - none of the buildrenderable jobs will run in parallel
  7521. if( lp > 0 )
  7522. syncTagR = numViews+2; // magic no.
  7523. else
  7524. syncTagR = 0;
  7525. // alternative
  7526. //if( lp > 1 )
  7527. //{
  7528. // syncTagR = numViews+2;
  7529. //}
  7530. //else
  7531. //{
  7532. // syncTagR = 0;
  7533. //}
  7534. syncMask = (0x01 << syncTagW) | (0x01 << lastSyncTagR);
  7535. // pushsync
  7536. CELL_VERIFY( g_pBuildRenderablesJob->m_pRoot->m_queuePortBuildRenderables[ lp ].pushSync( syncMask, 0 ) );
  7537. //Msg("PushSync %d, syncTagW %d, syncTagR %d\n", syncMask, syncTagW, syncTagR );
  7538. // testing syncTagR = numViews+2;
  7539. // pushjob
  7540. CELL_VERIFY( g_pBuildRenderablesJob->m_pRoot->m_queuePortBuildRenderables[ lp ].pushJob( &pJobDescriptor->header, sizeof(*pJobDescriptor), syncTagR, CELL_SPURS_JOBQUEUE_FLAG_SYNC_JOB ) );
  7541. lastSyncTagR = syncTagR;
  7542. }
  7543. }
  7544. #else // _PS3 CConcurrentViewBuilderPS3 methods
  7545. //-----------------------------------------------------------------------------
  7546. // CConcurrentViewData Methods
  7547. //-----------------------------------------------------------------------------
  7548. void CConcurrentViewData::Init()
  7549. {
  7550. m_pWorldRenderList = NULL;
  7551. m_pWorldListInfo = NULL;
  7552. m_pRenderablesList = NULL;
  7553. m_pBuildWorldListJob = NULL;
  7554. m_pBuildRenderablesListJob = NULL;
  7555. m_bWaitForWorldList = false;
  7556. m_volumeCuller.Clear();
  7557. for ( int lp = 0; lp < MAX_MAP_AREAS; ++lp )
  7558. {
  7559. m_frustumList[lp] = NULL;
  7560. }
  7561. }
  7562. void CConcurrentViewData::Purge()
  7563. {
  7564. SafeRelease( m_pWorldRenderList );
  7565. SafeRelease( m_pWorldListInfo );
  7566. SafeRelease( m_pRenderablesList );
  7567. SafeRelease( m_pBuildWorldListJob );
  7568. SafeRelease( m_pBuildRenderablesListJob );
  7569. m_AreaFrustums.RemoveAll();
  7570. }
  7571. //-----------------------------------------------------------------------------
  7572. // CConcurrentViewBuilder Methods (Non PS3)
  7573. //-----------------------------------------------------------------------------
  7574. CConcurrentViewBuilder::CConcurrentViewBuilder()
  7575. {
  7576. Init();
  7577. }
  7578. CConcurrentViewBuilder::~CConcurrentViewBuilder()
  7579. {
  7580. Purge();
  7581. }
  7582. void CConcurrentViewBuilder::Init()
  7583. {
  7584. // Release lists (in case a list has been added between 2 Init calls)
  7585. Purge();
  7586. SetBuildWRThreaded( false );
  7587. ResetBuildViewID();
  7588. for( int lp = 0; lp < MAX_CONCURRENT_BUILDVIEWS; lp++ )
  7589. {
  7590. m_viewData[lp].Init();
  7591. }
  7592. m_pCurrentSeqJobs = NULL;
  7593. m_pPendingSeqJobs = NULL;
  7594. }
  7595. void CConcurrentViewBuilder::Purge()
  7596. {
  7597. // Make sure all jobs added to the global thread pool have finished
  7598. // in case we have a mismatched between the build and draw pass
  7599. // ie a job has been added in the build pass but we are not waiting for
  7600. // in the draw pass (ie it did not get drawn)
  7601. for (int i = 0; i < mJobsAddedToThreadPool.Count(); i++)
  7602. {
  7603. mJobsAddedToThreadPool[i]->WaitForFinishAndRelease();
  7604. }
  7605. mJobsAddedToThreadPool.RemoveAll();
  7606. for( int lp = 0; lp < MAX_CONCURRENT_BUILDVIEWS; lp++ )
  7607. {
  7608. m_viewData[lp].Purge();
  7609. }
  7610. SafeRelease( m_pCurrentSeqJobs );
  7611. SafeRelease( m_pPendingSeqJobs );
  7612. }
  7613. void CConcurrentViewBuilder::ResetBuildViewID( void )
  7614. {
  7615. m_buildViewID = -1;
  7616. m_nextFreeBuildViewID = 0;
  7617. m_pBuildViewStack = m_buildViewStack - 1;
  7618. m_buildViewStack[ 0 ] = -1;
  7619. };
  7620. // get current view index
  7621. int CConcurrentViewBuilder::GetBuildViewID( void )
  7622. {
  7623. if( m_buildViewID == -1 )
  7624. {
  7625. // bad view initialisation
  7626. Warning("*** BAD BUILD VIEW INITIALIZATION ***\n");
  7627. return 0;
  7628. }
  7629. return m_buildViewID;
  7630. };
  7631. // call at the start of each view
  7632. void CConcurrentViewBuilder::PushBuildView( void )
  7633. {
  7634. m_pBuildViewStack++;
  7635. if( m_pBuildViewStack >= &m_buildViewStack[MAX_CONCURRENT_BUILDVIEWS] )
  7636. {
  7637. Error("*** exceeded concurrent buildview push ***\n");
  7638. }
  7639. if( m_nextFreeBuildViewID >= MAX_CONCURRENT_BUILDVIEWS )
  7640. {
  7641. Error("*** exceeded max concurrent buildviews ***\n");
  7642. }
  7643. *m_pBuildViewStack = m_nextFreeBuildViewID;
  7644. m_buildViewID = *m_pBuildViewStack;
  7645. m_nextFreeBuildViewID++;
  7646. }
  7647. void CConcurrentViewBuilder::PopBuildView( void )
  7648. {
  7649. if( m_pBuildViewStack == m_buildViewStack )
  7650. {
  7651. m_buildViewID = *m_pBuildViewStack;
  7652. m_pBuildViewStack--;
  7653. }
  7654. else
  7655. {
  7656. m_pBuildViewStack--;
  7657. m_buildViewID = *m_pBuildViewStack;
  7658. }
  7659. }
  7660. void CConcurrentViewBuilder::CacheBuildViewVolumeCuller( const CVolumeCuller *pVC )
  7661. {
  7662. if( m_buildViewID == -1 )
  7663. {
  7664. Warning( "ViewBuilder Begin/End Error - Setting volume culler(-1)\n" );
  7665. return;
  7666. }
  7667. else if ( pVC )
  7668. {
  7669. m_viewData[ m_buildViewID ].m_volumeCuller = *pVC;
  7670. }
  7671. }
  7672. const CVolumeCuller* CConcurrentViewBuilder::GetBuildViewVolumeCuller( int buildViewID /*= -1*/ ) const
  7673. {
  7674. int viewID = ( buildViewID >= 0 ) ? buildViewID : m_buildViewID;
  7675. if( viewID == -1 )
  7676. {
  7677. Warning( "ViewBuilder Begin/End Error - Accessing volume culler(-1)\n" );
  7678. return NULL;
  7679. }
  7680. else
  7681. {
  7682. const CVolumeCuller* pVolumeCuller = &m_viewData[viewID].m_volumeCuller;
  7683. return ( pVolumeCuller->IsValid() ? pVolumeCuller : NULL );
  7684. }
  7685. }
  7686. void CConcurrentViewBuilder::CacheFrustumData( const Frustum_t& frustum, const CUtlVector< Frustum_t, CUtlMemoryAligned< Frustum_t,16 > >& aeraFrustums )
  7687. {
  7688. if( m_buildViewID == -1 )
  7689. {
  7690. Warning( "ViewBuilder Begin/End Error - Setting frustum data(-1)\n" );
  7691. }
  7692. else
  7693. {
  7694. CConcurrentViewData* pViewData = &m_viewData[m_buildViewID];
  7695. // Copy frustum and area frustums
  7696. pViewData->m_Frustum = frustum;
  7697. pViewData->m_AreaFrustums = aeraFrustums;
  7698. // Setup frustum list used by the ClientLeafSystem
  7699. pViewData->m_frustumList[0] = &pViewData->m_Frustum;
  7700. int count = MIN( MAX_MAP_AREAS-1, pViewData->m_AreaFrustums.Count() );
  7701. for ( int i = 0; i < count; i++ )
  7702. {
  7703. if ( engine->ShouldUseAreaFrustum( i ) )
  7704. {
  7705. pViewData->m_frustumList[i+1] = &pViewData->m_AreaFrustums[i];
  7706. }
  7707. else
  7708. {
  7709. pViewData->m_frustumList[i+1] = &pViewData->m_Frustum;
  7710. }
  7711. }
  7712. }
  7713. }
  7714. void CConcurrentViewBuilder::CacheFrustumData( void )
  7715. {
  7716. if( m_buildViewID == -1 )
  7717. {
  7718. Warning( "ViewBuilder Begin/End Error - Setting frustum data(-1)\n" );
  7719. }
  7720. else
  7721. {
  7722. CConcurrentViewData* pViewData = &m_viewData[m_buildViewID];
  7723. int numFrustums = engine->GetFrustumList( pViewData->m_frustumList, MAX_MAP_AREAS );
  7724. // Copy frustum and frustum areas
  7725. pViewData->m_Frustum = *pViewData->m_frustumList[0];
  7726. if ( numFrustums > 1 )
  7727. {
  7728. for ( int i = 1; i < numFrustums; ++i )
  7729. {
  7730. pViewData->m_AreaFrustums.AddToTail( *pViewData->m_frustumList[i] );
  7731. }
  7732. }
  7733. // Regenerate frustum list
  7734. pViewData->m_frustumList[0] = &pViewData->m_Frustum;
  7735. int count = MIN( MAX_MAP_AREAS-1, pViewData->m_AreaFrustums.Count() );
  7736. for ( int i = 0; i < count; i++ )
  7737. {
  7738. pViewData->m_frustumList[i+1] = &pViewData->m_AreaFrustums[i];
  7739. }
  7740. }
  7741. }
  7742. const Frustum_t* CConcurrentViewBuilder::GetBuildViewFrustum( int buildViewID /*= -1*/ ) const
  7743. {
  7744. int viewID = ( buildViewID >= 0 ) ? buildViewID : m_buildViewID;
  7745. if( viewID == -1 )
  7746. {
  7747. Warning( "ViewBuilder Begin/End Error - Accessing frustum(-1)\n" );
  7748. return NULL;
  7749. }
  7750. else
  7751. {
  7752. return &m_viewData[viewID].m_Frustum;
  7753. }
  7754. }
  7755. const CUtlVector< Frustum_t, CUtlMemoryAligned< Frustum_t,16 > >* CConcurrentViewBuilder::GetBuildViewAeraFrustums( int buildViewID /*= -1*/ ) const
  7756. {
  7757. int viewID = ( buildViewID >= 0 ) ? buildViewID : m_buildViewID;
  7758. if( viewID == -1 )
  7759. {
  7760. Warning( "ViewBuilder Begin/End Error - Accessing aera frustums(-1)\n" );
  7761. return NULL;
  7762. }
  7763. else
  7764. {
  7765. return &m_viewData[viewID].m_AreaFrustums;
  7766. }
  7767. }
  7768. Frustum_t** CConcurrentViewBuilder::GetBuildViewFrustumList( int buildViewID /*= -1*/ )
  7769. {
  7770. int viewID = ( buildViewID >= 0 ) ? buildViewID : m_buildViewID;
  7771. if( viewID == -1 )
  7772. {
  7773. Warning( "ViewBuilder Begin/End Error - Accessing frustum list(-1)\n" );
  7774. return NULL;
  7775. }
  7776. else
  7777. {
  7778. return m_viewData[viewID].m_frustumList;
  7779. }
  7780. }
  7781. IWorldRenderList *CConcurrentViewBuilder::GetWorldRenderListElement( void )
  7782. {
  7783. if( m_buildViewID == -1 )
  7784. {
  7785. Warning( "ViewBuilder Begin/End Error - Accessing WorldRenderListElement(-1)\n" );
  7786. return NULL;
  7787. }
  7788. else
  7789. {
  7790. return m_viewData[m_buildViewID].m_pWorldRenderList;
  7791. }
  7792. }
  7793. void CConcurrentViewBuilder::SetWorldRenderListElement( IWorldRenderList *pRenderList )
  7794. {
  7795. if( m_buildViewID == -1 )
  7796. {
  7797. Warning( "ViewBuilder Begin/End Error - Setting WorldRenderListElement(-1)\n" );
  7798. return;
  7799. }
  7800. else
  7801. {
  7802. m_viewData[m_buildViewID].m_pWorldRenderList = pRenderList;
  7803. // Increment ref count
  7804. InlineAddRef( pRenderList );
  7805. }
  7806. }
  7807. ClientWorldListInfo_t *CConcurrentViewBuilder::GetClientWorldListInfoElement( int buildViewID /*= -1*/ )
  7808. {
  7809. int viewID = ( buildViewID >= 0 ) ? buildViewID : m_buildViewID;
  7810. if( viewID == -1 )
  7811. {
  7812. Warning( "ViewBuilder Begin/End Error - Accessing ClientWorlListInfoElement(-1)\n" );
  7813. return NULL;
  7814. }
  7815. else
  7816. {
  7817. return m_viewData[viewID].m_pWorldListInfo;
  7818. }
  7819. }
  7820. WorldListInfo_t *CConcurrentViewBuilder::GetWorldListInfoElement( int buildViewID )
  7821. {
  7822. if( buildViewID == -1 )
  7823. {
  7824. Warning( "ViewBuilder Begin/End Error - Accessing WorlListInfoElement(-1)\n" );
  7825. return NULL;
  7826. }
  7827. else
  7828. {
  7829. return m_viewData[buildViewID].m_pWorldListInfo;
  7830. }
  7831. }
  7832. void CConcurrentViewBuilder::SetWorldListInfoElement( ClientWorldListInfo_t *pWorldListInfo, int buildViewID /*= -1*/ )
  7833. {
  7834. int viewID = ( buildViewID >= 0 ) ? buildViewID : m_buildViewID;
  7835. if( viewID == -1 )
  7836. {
  7837. Warning( "ViewBuilder Begin/End Error - Setting WorldListInfoElement(-1)\n" );
  7838. return;
  7839. }
  7840. else
  7841. {
  7842. CConcurrentViewData* pViewData = &m_viewData[viewID];
  7843. // Release old list if necessary
  7844. SafeRelease( pViewData->m_pWorldListInfo );
  7845. pViewData->m_pWorldListInfo = pWorldListInfo;
  7846. // Increment ref count
  7847. InlineAddRef( pWorldListInfo );
  7848. }
  7849. }
  7850. CClientRenderablesList *CConcurrentViewBuilder::GetRenderablesListElement( int buildViewID /*= -1*/ )
  7851. {
  7852. int viewID = ( buildViewID >= 0 ) ? buildViewID : m_buildViewID;
  7853. if( viewID == -1 )
  7854. {
  7855. Warning( "ViewBuilder Begin/End Error - Accessing RenderablesListElement(-1)\n" );
  7856. return NULL;
  7857. }
  7858. else
  7859. {
  7860. return m_viewData[viewID].m_pRenderablesList;
  7861. }
  7862. }
  7863. void CConcurrentViewBuilder::SetRenderablesListElement( CClientRenderablesList *pRenderables )
  7864. {
  7865. if( m_buildViewID == -1 )
  7866. {
  7867. Warning( "ViewBuilder Begin/End Error - Setting RenderablesListElement(-1)\n" );
  7868. return;
  7869. }
  7870. else
  7871. {
  7872. m_viewData[m_buildViewID].m_pRenderablesList = pRenderables;
  7873. // Increment ref count
  7874. InlineAddRef( pRenderables );
  7875. }
  7876. }
  7877. void CConcurrentViewBuilder::QueueBuildWorldListJob( CJob* pJob )
  7878. {
  7879. if( m_buildViewID == -1 )
  7880. {
  7881. Warning( "ViewBuilder Begin/End Error - Queueing Build World list job(-1)\n" );
  7882. return;
  7883. }
  7884. else
  7885. {
  7886. if ( r_threaded_buildWRlist.GetBool() && GetBuildWRThreaded() )
  7887. {
  7888. TryRunSequentialJobs();
  7889. CConcurrentViewData* pViewData = &m_viewData[m_buildViewID];
  7890. if ( !pViewData->m_pBuildWorldListJob )
  7891. {
  7892. pViewData->m_pBuildWorldListJob = new SequentialJobs( pJob );
  7893. }
  7894. else
  7895. {
  7896. SequentialJobs* pSeqJob = (SequentialJobs *)pViewData->m_pBuildWorldListJob;
  7897. pSeqJob->AddJob( pJob );
  7898. }
  7899. }
  7900. else
  7901. {
  7902. pJob->Execute();
  7903. }
  7904. }
  7905. }
  7906. void CConcurrentViewBuilder::FlushBuildWorldListJob( void )
  7907. {
  7908. if( m_buildViewID == -1 )
  7909. {
  7910. Warning( "ViewBuilder Begin/End Error - Flushing Build World list job(-1)\n" );
  7911. return;
  7912. }
  7913. else
  7914. {
  7915. CConcurrentViewData* pViewData = &m_viewData[m_buildViewID];
  7916. if ( pViewData->m_pBuildWorldListJob )
  7917. {
  7918. //DevMsg("***** FlushBuildWorldListJob %d\n", m_buildViewID);
  7919. AddJobToThreadPool( pViewData->m_pBuildWorldListJob );
  7920. }
  7921. }
  7922. }
  7923. void CConcurrentViewBuilder::WaitForBuildWorldListJob( void )
  7924. {
  7925. if( m_buildViewID == -1 )
  7926. {
  7927. Warning( "ViewBuilder Begin/End Error - Wait for Build World list job to finish (-1)\n" );
  7928. return;
  7929. }
  7930. else
  7931. {
  7932. CJob* pJob = m_viewData[m_buildViewID].m_pBuildWorldListJob;
  7933. if ( pJob )
  7934. {
  7935. pJob->WaitForFinish();
  7936. }
  7937. }
  7938. }
  7939. void CConcurrentViewBuilder::InternalWaitForBuildWorldListJob( int buildViewID )
  7940. {
  7941. if( buildViewID == -1 )
  7942. {
  7943. Warning( "ViewBuilder Begin/End Error - Wait for Build World list job to finish (-1)\n" );
  7944. return;
  7945. }
  7946. else
  7947. {
  7948. CJob* pJob = m_viewData[buildViewID].m_pBuildWorldListJob;
  7949. if ( pJob && !pJob->IsFinished() )
  7950. {
  7951. // Called on a worker thread so do not call pJob->WaitForFinish() as it could try to
  7952. // execute new job while waiting (=> deadlock). Instead wait on CJob::m_CompletedEvent.
  7953. pJob->AccessEvent()->Wait();
  7954. }
  7955. }
  7956. }
  7957. void CConcurrentViewBuilder::QueueBuildRenderablesListJob( CJob* pJob )
  7958. {
  7959. if( m_buildViewID == -1 )
  7960. {
  7961. Warning( "ViewBuilder Begin/End Error - Queueing Build renderables list job(-1)\n" );
  7962. return;
  7963. }
  7964. else
  7965. {
  7966. CConcurrentViewData* pViewData = &m_viewData[m_buildViewID];
  7967. pViewData->m_pBuildRenderablesListJob = pJob;
  7968. // Increment ref count
  7969. InlineAddRef( pJob ); // Released in Purge()
  7970. if ( r_threaded_buildWRlist.GetBool() && GetBuildWRThreaded() )
  7971. {
  7972. if ( pViewData->m_bWaitForWorldList )
  7973. {
  7974. CFunctorJob *pWaitJob = new CFunctorJob( CreateFunctor( this, &CConcurrentViewBuilder::InternalWaitForBuildWorldListJob, m_buildViewID ) );
  7975. AddToSequentialJobs( pWaitJob );
  7976. pWaitJob->Release();
  7977. }
  7978. AddToSequentialJobs( pJob );
  7979. TryRunSequentialJobs();
  7980. }
  7981. else
  7982. {
  7983. pJob->Execute();
  7984. }
  7985. }
  7986. }
  7987. void CConcurrentViewBuilder::WaitForBuildRenderablesListJob( void )
  7988. {
  7989. if( m_buildViewID == -1 )
  7990. {
  7991. Warning( "ViewBuilder Begin/End Error - Wait for Build renderables list job to finish (-1)\n" );
  7992. return;
  7993. }
  7994. else
  7995. {
  7996. CJob* pJob = m_viewData[m_buildViewID].m_pBuildRenderablesListJob;
  7997. if ( pJob )
  7998. {
  7999. pJob->WaitForFinish();
  8000. }
  8001. }
  8002. }
  8003. void CConcurrentViewBuilder::FlushBuildRenderablesListJob( void )
  8004. {
  8005. if ( m_pPendingSeqJobs )
  8006. {
  8007. if ( m_pCurrentSeqJobs )
  8008. {
  8009. // Wait for the current job to finish before executing pending jobs
  8010. // Use a job to wait so that the main thread can keep running
  8011. CFunctorJob *pJob = new CFunctorJob( CreateFunctor(this, &CConcurrentViewBuilder::WaitForCurrentSequentialJobAndRunPending ) );
  8012. AddJobToThreadPool( pJob );
  8013. pJob->Release();
  8014. }
  8015. else
  8016. {
  8017. TryRunSequentialJobs();
  8018. }
  8019. }
  8020. }
  8021. void CConcurrentViewBuilder::AddDependencyToWorldList( void )
  8022. {
  8023. if( m_buildViewID == -1 )
  8024. {
  8025. Warning( "ViewBuilder Begin/End Error - Add dependency to world list (-1)\n" );
  8026. return;
  8027. }
  8028. else
  8029. {
  8030. m_viewData[m_buildViewID].m_bWaitForWorldList = true;
  8031. }
  8032. }
  8033. void CConcurrentViewBuilder::AddToSequentialJobs( CJob* pJob )
  8034. {
  8035. if ( !m_pPendingSeqJobs )
  8036. {
  8037. m_pPendingSeqJobs = new SequentialJobs();
  8038. }
  8039. m_pPendingSeqJobs->AddJob( pJob );
  8040. }
  8041. void CConcurrentViewBuilder::TryRunSequentialJobs( void )
  8042. {
  8043. if ( m_pCurrentSeqJobs && m_pCurrentSeqJobs->IsFinished() )
  8044. {
  8045. SafeRelease( m_pCurrentSeqJobs );
  8046. m_pCurrentSeqJobs = NULL;
  8047. }
  8048. if ( !m_pCurrentSeqJobs && m_pPendingSeqJobs )
  8049. {
  8050. m_pCurrentSeqJobs = m_pPendingSeqJobs;
  8051. AddJobToThreadPool( m_pCurrentSeqJobs );
  8052. m_pPendingSeqJobs = NULL;
  8053. }
  8054. }
  8055. void CConcurrentViewBuilder::WaitForCurrentSequentialJobAndRunPending()
  8056. {
  8057. if ( m_pCurrentSeqJobs && !m_pCurrentSeqJobs->IsFinished() )
  8058. {
  8059. m_pCurrentSeqJobs->AccessEvent()->Wait();
  8060. }
  8061. // Run pending jobs
  8062. // m_pCurrentSeqJobs & m_pPendingSeqJobs will get released in Purge()
  8063. if ( m_pPendingSeqJobs )
  8064. {
  8065. m_pPendingSeqJobs->Execute();
  8066. }
  8067. }
  8068. void CConcurrentViewBuilder::AddJobToThreadPool( CJob* pJob )
  8069. {
  8070. // Keeps track of all jobs added to the thread pool
  8071. mJobsAddedToThreadPool.AddToTail( pJob );
  8072. InlineAddRef( pJob ); // Get released in purge
  8073. // Set JF_QUEUE flag to make sure that the job is not executed in CThreadPool::AddJob
  8074. // We want the job to be executed on a worker thread unless we are waiting for job to
  8075. // complete on the main thread
  8076. pJob->SetFlags( pJob->GetFlags() | JF_QUEUE );
  8077. g_pThreadPool->AddJob( pJob );
  8078. }
  8079. CConcurrentViewBuilder::SequentialJobs::SequentialJobs( CJob* pJob /* = NULL */ )
  8080. {
  8081. if ( pJob )
  8082. {
  8083. AddJob( pJob );
  8084. }
  8085. }
  8086. CConcurrentViewBuilder::SequentialJobs::~SequentialJobs()
  8087. {
  8088. for ( int i = 0; i < m_jobs.Count(); i++ )
  8089. {
  8090. SafeRelease( m_jobs[i] );
  8091. }
  8092. }
  8093. void CConcurrentViewBuilder::SequentialJobs::AddJob( CJob* pJob )
  8094. {
  8095. m_jobs.AddToTail( pJob );
  8096. InlineAddRef( pJob );
  8097. }
  8098. JobStatus_t CConcurrentViewBuilder::SequentialJobs::DoExecute()
  8099. {
  8100. for ( int i = 0; i < m_jobs.Count(); i++ )
  8101. {
  8102. m_jobs[i]->Execute();
  8103. }
  8104. return JOB_OK;
  8105. }
  8106. #endif