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

2313 lines
76 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: loads and unloads main matsystem dll and interface
  4. //
  5. //===========================================================================//
  6. #include "render_pch.h"
  7. #include "materialsystem/imaterialsystemhardwareconfig.h"
  8. #include "materialsystem/materialsystem_config.h"
  9. #include "materialsystem/MaterialSystemUtil.h"
  10. #include "materialsystem/ivballoctracker.h"
  11. #include "materialsystem/imesh.h"
  12. #include "tier0/dbg.h"
  13. #include "sys_dll.h"
  14. #include "host.h"
  15. #include "cmodel_engine.h"
  16. #include "gl_model_private.h"
  17. #include "view.h"
  18. #include "gl_matsysiface.h"
  19. #include "gl_cvars.h"
  20. #include "gl_lightmap.h"
  21. #include "lightcache.h"
  22. #include "vstdlib/random.h"
  23. #include "tier0/icommandline.h"
  24. #include "draw.h"
  25. #include "decal_private.h"
  26. #include "l_studio.h"
  27. #include "KeyValues.h"
  28. #include "materialsystem/imaterial.h"
  29. #include "gl_shader.h"
  30. #include "ivideomode.h"
  31. #include "cdll_engine_int.h"
  32. #include "utldict.h"
  33. #include "filesystem.h"
  34. #include "host_saverestore.h"
  35. #include "server.h"
  36. #include "game/client/iclientrendertargets.h"
  37. #include "tier2/tier2.h"
  38. #include "LoadScreenUpdate.h"
  39. #include "client.h"
  40. #include "sourcevr/isourcevirtualreality.h"
  41. #if defined( _X360 )
  42. #include "xbox/xbox_launch.h"
  43. #endif
  44. #if defined( USE_SDL )
  45. #include "SDL.h"
  46. #endif
  47. //X360TEMP
  48. #include "materialsystem/itexture.h"
  49. extern IFileSystem *g_pFileSystem;
  50. #ifndef SWDS
  51. #include "iregistry.h"
  52. #endif
  53. #include "igame.h"
  54. // memdbgon must be the last include file in a .cpp file!!!
  55. #include "tier0/memdbgon.h"
  56. // Start the frame count at one so stuff gets updated the first frame
  57. int r_framecount = 1; // used for dlight + lightstyle push checking
  58. int d_lightstylevalue[256];
  59. int d_lightstylenumframes[256];
  60. const MaterialSystem_Config_t *g_pMaterialSystemConfig;
  61. static CSysModule *g_MaterialsDLL = NULL;
  62. bool g_LostVideoMemory = false;
  63. IMaterial* g_materialEmpty; // purple checkerboard for missing textures
  64. void ReleaseMaterialSystemObjects();
  65. void RestoreMaterialSystemObjects( int nChangeFlags );
  66. extern ConVar mat_colorcorrection;
  67. extern ConVar sv_allow_color_correction;
  68. ConVar mat_debugalttab( "mat_debugalttab", "0", FCVAR_CHEAT );
  69. // Static pointers to renderable textures
  70. static CTextureReference g_PowerOfTwoFBTexture;
  71. static CTextureReference g_WaterReflectionTexture;
  72. static CTextureReference g_WaterRefractionTexture;
  73. static CTextureReference g_CameraTexture;
  74. static CTextureReference g_BuildCubemaps16BitTexture;
  75. static CTextureReference g_QuarterSizedFBTexture0;
  76. static CTextureReference g_QuarterSizedFBTexture1;
  77. static CTextureReference g_TeenyFBTexture0;
  78. static CTextureReference g_TeenyFBTexture1;
  79. static CTextureReference g_TeenyFBTexture2;
  80. static CTextureReference g_FullFrameFBTexture0;
  81. static CTextureReference g_FullFrameFBTexture1;
  82. static CTextureReference g_FullFrameFBTexture2;
  83. static CTextureReference g_FullFrameDepth;
  84. static CTextureReference g_ResolvedFullFrameDepth;
  85. void WorldStaticMeshCreate( void );
  86. void WorldStaticMeshDestroy( void );
  87. ConVar r_norefresh( "r_norefresh","0");
  88. ConVar r_decals( "r_decals", "2048" );
  89. ConVar mp_decals( "mp_decals","200", FCVAR_ARCHIVE);
  90. ConVar r_lightmap( "r_lightmap", "-1", FCVAR_CHEAT | FCVAR_MATERIAL_SYSTEM_THREAD );
  91. ConVar r_lightstyle( "r_lightstyle","-1", FCVAR_CHEAT | FCVAR_MATERIAL_SYSTEM_THREAD );
  92. ConVar r_dynamic( "r_dynamic","1");
  93. ConVar mat_norendering( "mat_norendering", "0", FCVAR_CHEAT );
  94. ConVar mat_wireframe( "mat_wireframe", "0", FCVAR_CHEAT );
  95. ConVar mat_luxels( "mat_luxels", "0", FCVAR_CHEAT );
  96. ConVar mat_normals( "mat_normals", "0", FCVAR_CHEAT );
  97. ConVar mat_bumpbasis( "mat_bumpbasis", "0", FCVAR_CHEAT );
  98. ConVar mat_envmapsize( "mat_envmapsize", "128" );
  99. ConVar mat_envmaptgasize( "mat_envmaptgasize", "32.0" );
  100. ConVar mat_levelflush( "mat_levelflush", "1" );
  101. ConVar mat_fastspecular( "mat_fastspecular", "1", 0, "Enable/Disable specularity for visual testing. Will not reload materials and will not affect perf." );
  102. ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT );
  103. static ConVar mat_monitorgamma( "mat_monitorgamma", "2.2", FCVAR_ARCHIVE, "monitor gamma (typically 2.2 for CRT and 1.7 for LCD)", true, 1.6f, true, 2.6f );
  104. static ConVar mat_monitorgamma_tv_range_min( "mat_monitorgamma_tv_range_min", "16" );
  105. static ConVar mat_monitorgamma_tv_range_max( "mat_monitorgamma_tv_range_max", "255" );
  106. // TV's generally have a 2.5 gamma, so we need to convert our 2.2 frame buffer into a 2.5 frame buffer for display on a TV
  107. static ConVar mat_monitorgamma_tv_exp( "mat_monitorgamma_tv_exp", "2.5", 0, "", true, 1.0f, true, 4.0f );
  108. #ifdef _X360
  109. static ConVar mat_monitorgamma_tv_enabled( "mat_monitorgamma_tv_enabled", "1", FCVAR_ARCHIVE, "" );
  110. #else
  111. static ConVar mat_monitorgamma_tv_enabled( "mat_monitorgamma_tv_enabled", "0", FCVAR_ARCHIVE, "" );
  112. #endif
  113. ConVar r_drawbrushmodels( "r_drawbrushmodels", "1", FCVAR_CHEAT, "Render brush models. 0=Off, 1=Normal, 2=Wireframe" );
  114. ConVar r_shadowrendertotexture( "r_shadowrendertotexture", "0" );
  115. ConVar r_flashlightdepthtexture( "r_flashlightdepthtexture", "1" );
  116. #ifndef _X360
  117. ConVar r_waterforceexpensive( "r_waterforceexpensive", "0", FCVAR_ARCHIVE );
  118. #endif
  119. ConVar r_waterforcereflectentities( "r_waterforcereflectentities", "0" );
  120. // Note: this is only here so we can ship an update without changing materialsystem.dll.
  121. // Once we ship materialsystem.dll again, we can get rid of this and make the only one exist in materialsystem.dll.
  122. ConVar mat_depthbias_normal( "mat_depthbias_normal", "0.0f", FCVAR_CHEAT );
  123. // This is here so that the client and the materialsystem can both see this.
  124. ConVar mat_show_ab_hdr( "mat_show_ab_hdr", "0" );
  125. static void NukeModeSwitchSaveGames( void )
  126. {
  127. if( g_pFileSystem->FileExists( "save\\modeswitchsave.sav" ) )
  128. {
  129. g_pFileSystem->RemoveFile( "save\\modeswitchsave.sav" );
  130. }
  131. if( g_pFileSystem->FileExists( "save\\modeswitchsave.tga" ) )
  132. {
  133. g_pFileSystem->RemoveFile( "save\\modeswitchsave.tga" );
  134. }
  135. }
  136. void mat_hdr_level_Callback( IConVar *var, const char *pOldString, float flOldValue )
  137. {
  138. if ( IsX360() )
  139. {
  140. // can't support, expected to be static
  141. return;
  142. }
  143. #ifdef CSS_PERF_TEST
  144. ConVarRef hdr( var );
  145. if ( hdr.GetInt() > 0 )
  146. hdr.SetValue( 0 );
  147. return;
  148. #endif
  149. // Can do any reloading that is necessary here upon change.
  150. // FIXME: should check if there is actually going to be a change here (ie. are we able to run in HDR
  151. // given the current map and hardware.
  152. #ifndef SWDS
  153. if ( g_pMaterialSystemHardwareConfig->GetHardwareHDRType() != HDR_TYPE_NONE &&
  154. saverestore->IsValidSave() &&
  155. modelloader->LastLoadedMapHasHDRLighting() &&
  156. sv.GetMaxClients() == 1 &&
  157. !sv.IsLevelMainMenuBackground()
  158. )
  159. {
  160. NukeModeSwitchSaveGames();
  161. Cbuf_AddText( "save modeswitchsave;wait;load modeswitchsave\n" );
  162. }
  163. #endif
  164. }
  165. #ifdef CSS_PERF_TEST
  166. ConVar mat_hdr_level( "mat_hdr_level", "0", 0,
  167. "Set to 0 for no HDR, 1 for LDR+bloom on HDR maps, and 2 for full HDR on HDR maps.",
  168. mat_hdr_level_Callback );
  169. #else
  170. ConVar mat_hdr_level( "mat_hdr_level", "2", FCVAR_ARCHIVE,
  171. "Set to 0 for no HDR, 1 for LDR+bloom on HDR maps, and 2 for full HDR on HDR maps.",
  172. mat_hdr_level_Callback );
  173. #endif
  174. MaterialSystem_SortInfo_t *materialSortInfoArray = 0;
  175. static bool s_bConfigLightingChanged = false;
  176. extern unsigned long GetRam();
  177. //-----------------------------------------------------------------------------
  178. // return true if lightmaps need to be redownloaded
  179. //-----------------------------------------------------------------------------
  180. bool MaterialConfigLightingChanged()
  181. {
  182. return s_bConfigLightingChanged;
  183. }
  184. void ClearMaterialConfigLightingChanged()
  185. {
  186. s_bConfigLightingChanged = false;
  187. }
  188. //-----------------------------------------------------------------------------
  189. // List of all convars to store into the registry
  190. //-----------------------------------------------------------------------------
  191. static const char *s_pRegistryConVars[] =
  192. {
  193. "mat_forceaniso",
  194. "mat_picmip",
  195. // "mat_dxlevel",
  196. "mat_trilinear",
  197. "mat_vsync",
  198. "mat_forcehardwaresync",
  199. "mat_parallaxmap",
  200. "mat_reducefillrate",
  201. "r_shadowrendertotexture",
  202. "r_rootlod",
  203. #ifndef _X360
  204. "r_waterforceexpensive",
  205. #endif
  206. "r_waterforcereflectentities",
  207. "mat_antialias",
  208. "mat_aaquality",
  209. "mat_specular",
  210. "mat_bumpmap",
  211. "mat_hdr_level",
  212. "mat_colorcorrection",
  213. // NOTE: Empty string must always be last!
  214. ""
  215. };
  216. #if defined( OSX )
  217. #define MOD_VIDEO_CONFIG_SETTINGS "videoconfig_mac.cfg"
  218. #define USE_VIDEOCONFIG_FILE 1
  219. #elif defined( POSIX )
  220. #define MOD_VIDEO_CONFIG_SETTINGS "videoconfig_linux.cfg"
  221. #define USE_VIDEOCONFIG_FILE 1
  222. #elif defined( DX_TO_GL_ABSTRACTION )
  223. #define MOD_VIDEO_CONFIG_SETTINGS "videoconfig_gl.cfg"
  224. #define USE_VIDEOCONFIG_FILE 1
  225. #else
  226. #define MOD_VIDEO_CONFIG_SETTINGS "videoconfig.cfg"
  227. #define USE_VIDEOCONFIG_FILE 0
  228. #endif
  229. #if USE_VIDEOCONFIG_FILE
  230. static CThreadMutex g_VideoConfigMutex;
  231. #endif
  232. static int ReadVideoConfigInt( const char *pName, int nDefault )
  233. {
  234. #if USE_VIDEOCONFIG_FILE
  235. AUTO_LOCK( g_VideoConfigMutex );
  236. // Try to make a keyvalues from the cfg file
  237. KeyValues *pVideoConfig = new KeyValues( "videoconfig" );
  238. bool bFileExists = pVideoConfig->LoadFromFile( g_pFullFileSystem, MOD_VIDEO_CONFIG_SETTINGS, "MOD" );
  239. // We probably didn't have one on disk yet, just bail. It'll get created soon.
  240. if ( !bFileExists )
  241. return nDefault;
  242. int nInt = pVideoConfig->GetInt( pName, nDefault );
  243. pVideoConfig->deleteThis();
  244. return nInt;
  245. #else
  246. return registry->ReadInt( pName, nDefault );
  247. #endif
  248. }
  249. static void ReadVideoConfigInt( const char *pName, int *pEntry )
  250. {
  251. #if USE_VIDEOCONFIG_FILE
  252. AUTO_LOCK( g_VideoConfigMutex );
  253. // Try to make a keyvalues from the cfg file
  254. KeyValues *pVideoConfig = new KeyValues( "videoconfig" );
  255. bool bFileExists = pVideoConfig->LoadFromFile( g_pFullFileSystem, MOD_VIDEO_CONFIG_SETTINGS, "MOD" );
  256. // We probably didn't have one on disk yet, just bail. It'll get created soon.
  257. if ( !bFileExists )
  258. return;
  259. if ( pVideoConfig->GetInt( pName, -1 ) != -1 )
  260. {
  261. *pEntry = pVideoConfig->GetInt( pName, 0 );
  262. }
  263. pVideoConfig->deleteThis();
  264. #else
  265. if ( registry->ReadInt( pName, -1 ) != -1 )
  266. {
  267. *pEntry = registry->ReadInt( pName, 0 );
  268. }
  269. #endif
  270. }
  271. static const char *ReadVideoConfigString( const char *pName, const char *pDefault )
  272. {
  273. #if USE_VIDEOCONFIG_FILE
  274. AUTO_LOCK( g_VideoConfigMutex );
  275. static char szRetString[ 255 ];
  276. // Try to make a keyvalues from the cfg file
  277. KeyValues *pVideoConfig = new KeyValues( "videoconfig" );
  278. bool bFileExists = pVideoConfig->LoadFromFile( g_pFullFileSystem, MOD_VIDEO_CONFIG_SETTINGS, "MOD" );
  279. // We probably didn't have one on disk yet, just bail. It'll get created soon.
  280. if ( !bFileExists )
  281. return pDefault;
  282. const char *pString = pVideoConfig->GetString( pName, pDefault );
  283. Q_strncpy( szRetString, pString, sizeof(szRetString) );
  284. pVideoConfig->deleteThis();
  285. return szRetString;
  286. #else
  287. return registry->ReadString( pName, pDefault );
  288. #endif
  289. }
  290. static void WriteVideoConfigInt( const char *pName, int nEntry )
  291. {
  292. #if USE_VIDEOCONFIG_FILE
  293. AUTO_LOCK( g_VideoConfigMutex );
  294. // Try to make a keyvalues from the cfg file
  295. KeyValues *pVideoConfig = new KeyValues( "videoconfig" );
  296. pVideoConfig->LoadFromFile( g_pFullFileSystem, MOD_VIDEO_CONFIG_SETTINGS, "MOD" );
  297. pVideoConfig->SetInt( pName, nEntry );
  298. pVideoConfig->SaveToFile( g_pFullFileSystem, MOD_VIDEO_CONFIG_SETTINGS, "MOD", false, false, true );
  299. pVideoConfig->deleteThis();
  300. #else
  301. registry->WriteInt( pName, nEntry );
  302. #endif
  303. }
  304. static void WriteVideoConfigString( const char *pName, const char *pString )
  305. {
  306. #if USE_VIDEOCONFIG_FILE
  307. AUTO_LOCK( g_VideoConfigMutex );
  308. // Try to make a keyvalues from the cfg file
  309. KeyValues *pVideoConfig = new KeyValues( "videoconfig" );
  310. pVideoConfig->LoadFromFile( g_pFullFileSystem, MOD_VIDEO_CONFIG_SETTINGS, "MOD" );
  311. pVideoConfig->SetString( pName, pString );
  312. pVideoConfig->SaveToFile( g_pFullFileSystem, MOD_VIDEO_CONFIG_SETTINGS, "MOD", false, false, true );
  313. pVideoConfig->deleteThis();
  314. #else
  315. registry->WriteString( pName, pString );
  316. #endif
  317. }
  318. //-----------------------------------------------------------------------------
  319. // Scan for video config convars which are overridden on the cmd line, used
  320. // for development and automated timedemo regression testing.
  321. // (Unfortunately, convars aren't set early enough during init from the cmd line
  322. // for the usual machinery to work here.)
  323. //-----------------------------------------------------------------------------
  324. static bool s_bVideoConfigOverriddenFromCmdLine;
  325. template<typename T>
  326. static T OverrideVideoConfigFromCommandLine( const char *pCVarName, T curVal )
  327. {
  328. char szOption[256];
  329. V_snprintf( szOption, sizeof( szOption ), "+%s", pCVarName );
  330. if ( CommandLine()->CheckParm( szOption ) )
  331. {
  332. T newVal = CommandLine()->ParmValue( szOption, curVal );
  333. Warning( "Video configuration ignoring %s due to command line override\n", pCVarName );
  334. s_bVideoConfigOverriddenFromCmdLine = true;
  335. return newVal;
  336. }
  337. return curVal;
  338. }
  339. //-----------------------------------------------------------------------------
  340. // Reads convars from the registry
  341. //-----------------------------------------------------------------------------
  342. static void ReadMaterialSystemConfigFromRegistry( MaterialSystem_Config_t &config )
  343. {
  344. #ifndef SWDS
  345. if ( IsX360() )
  346. return;
  347. ReadVideoConfigInt( "ScreenWidth", &config.m_VideoMode.m_Width );
  348. ReadVideoConfigInt( "ScreenHeight", &config.m_VideoMode.m_Height );
  349. config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, ReadVideoConfigInt( "ScreenWindowed", 0 ) != 0 );
  350. #if defined( USE_SDL ) && !defined( SWDS )
  351. // Read the ScreenDisplayIndex and set sdl_displayindex if it's there.
  352. ConVarRef conVar( "sdl_displayindex" );
  353. if ( conVar.IsValid() )
  354. {
  355. int displayIndex = 0;
  356. ReadVideoConfigInt( "ScreenDisplayIndex", &displayIndex );
  357. conVar.SetValue( displayIndex );
  358. displayIndex = conVar.GetInt();
  359. // Make sure the width / height isn't too large for this display.
  360. SDL_Rect rect;
  361. if ( !SDL_GetDisplayBounds( displayIndex, &rect ) )
  362. {
  363. if ( ( config.m_VideoMode.m_Width > rect.w ) || ( config.m_VideoMode.m_Height > rect.h ) )
  364. {
  365. config.m_VideoMode.m_Width = rect.w;
  366. config.m_VideoMode.m_Height = rect.h;
  367. }
  368. }
  369. }
  370. #endif // USE_SDL && !SWDS
  371. // Special case...
  372. const char *szMonitorGamma = ReadVideoConfigString( "ScreenMonitorGamma", "2.2" );
  373. if ( szMonitorGamma && strlen(szMonitorGamma) > 0 )
  374. {
  375. float flMonitorGamma = atof( szMonitorGamma );
  376. // temp, to make sure people with gamma values saved in the old format don't max out
  377. if (flMonitorGamma > 3.0f)
  378. {
  379. flMonitorGamma = 2.2f;
  380. }
  381. flMonitorGamma = OverrideVideoConfigFromCommandLine( "mat_monitorgamma", flMonitorGamma );
  382. mat_monitorgamma.SetValue( flMonitorGamma );
  383. config.m_fMonitorGamma = mat_monitorgamma.GetFloat();
  384. }
  385. for ( int i = 0; s_pRegistryConVars[i][0]; ++i )
  386. {
  387. int nValue = ReadVideoConfigInt( s_pRegistryConVars[i], 0x80000000 );
  388. if ( nValue == 0x80000000 )
  389. continue;
  390. nValue = OverrideVideoConfigFromCommandLine( s_pRegistryConVars[i], nValue );
  391. ConVarRef conVar( s_pRegistryConVars[i] );
  392. if ( conVar.IsValid() )
  393. {
  394. conVar.SetValue( nValue );
  395. }
  396. }
  397. int nValue = ReadVideoConfigInt( "DXLevel_V1", -1 );
  398. if ( nValue != -1 )
  399. {
  400. nValue = OverrideVideoConfigFromCommandLine( "mat_dxlevel", nValue );
  401. ConVarRef conVar( "mat_dxlevel" );
  402. if ( conVar.IsValid() )
  403. {
  404. conVar.SetValue( nValue );
  405. }
  406. }
  407. nValue = ReadVideoConfigInt( "MotionBlur", -1 );
  408. if ( nValue != -1 )
  409. {
  410. nValue = OverrideVideoConfigFromCommandLine( "mat_motion_blur_enabled", nValue );
  411. ConVarRef conVar( "mat_motion_blur_enabled" );
  412. if ( conVar.IsValid() )
  413. {
  414. conVar.SetValue( nValue );
  415. config.m_bMotionBlur = ReadVideoConfigInt( "MotionBlur", 0 ) != 0;
  416. }
  417. }
  418. nValue = ReadVideoConfigInt( "ShadowDepthTexture", -1 );
  419. if ( nValue != -1 )
  420. {
  421. nValue = OverrideVideoConfigFromCommandLine( "r_flashlightdepthtexture", nValue );
  422. ConVarRef conVar( "r_flashlightdepthtexture" );
  423. if ( conVar.IsValid() )
  424. {
  425. conVar.SetValue( nValue );
  426. config.m_bShadowDepthTexture = ReadVideoConfigInt( "ShadowDepthTexture", 0 ) != 0;
  427. }
  428. }
  429. nValue = ReadVideoConfigInt( "VRModeAdapter", -1 );
  430. if ( nValue != -1 )
  431. {
  432. nValue = OverrideVideoConfigFromCommandLine( "mat_vrmode_adapter", nValue );
  433. ConVarRef conVar( "mat_vrmode_adapter" );
  434. if ( conVar.IsValid() )
  435. {
  436. conVar.SetValue( nValue );
  437. config.m_nVRModeAdapter = ReadVideoConfigInt( "VRModeAdapter", -1 );
  438. }
  439. }
  440. #endif
  441. }
  442. //-----------------------------------------------------------------------------
  443. // Writes convars into the registry
  444. //-----------------------------------------------------------------------------
  445. static void WriteMaterialSystemConfigToRegistry( const MaterialSystem_Config_t &config )
  446. {
  447. #ifndef SWDS
  448. if ( IsX360() )
  449. return;
  450. #if defined( USE_SDL ) && !defined( SWDS )
  451. // Save sdl_displayindex out to ScreenDisplayIndex.
  452. ConVarRef conVar( "sdl_displayindex" );
  453. if ( conVar.IsValid() && !UseVR() )
  454. {
  455. WriteVideoConfigInt( "ScreenDisplayIndex", conVar.GetInt() );
  456. }
  457. #endif // USE_SDL && !SWDS
  458. WriteVideoConfigInt( "ScreenWidth", config.m_VideoMode.m_Width );
  459. WriteVideoConfigInt( "ScreenHeight", config.m_VideoMode.m_Height );
  460. WriteVideoConfigInt( "ScreenWindowed", config.Windowed() );
  461. WriteVideoConfigInt( "ScreenMSAA", config.m_nAASamples );
  462. WriteVideoConfigInt( "ScreenMSAAQuality", config.m_nAAQuality );
  463. WriteVideoConfigInt( "MotionBlur", config.m_bMotionBlur ? 1 : 0 );
  464. WriteVideoConfigInt( "ShadowDepthTexture", config.m_bShadowDepthTexture ? 1 : 0 );
  465. WriteVideoConfigInt( "VRModeAdapter", config.m_nVRModeAdapter );
  466. // Registry only stores ints, so divide/multiply by 100 when reading/writing.
  467. WriteVideoConfigString( "ScreenMonitorGamma", mat_monitorgamma.GetString() );
  468. for ( int i = 0; s_pRegistryConVars[i][0]; ++i )
  469. {
  470. ConVarRef conVar( s_pRegistryConVars[i] );
  471. if ( !conVar.IsValid() )
  472. continue;
  473. WriteVideoConfigInt( s_pRegistryConVars[i], conVar.GetInt() );
  474. }
  475. #endif
  476. }
  477. //-----------------------------------------------------------------------------
  478. // Override config with command line params
  479. //-----------------------------------------------------------------------------
  480. static void OverrideMaterialSystemConfigFromCommandLine( MaterialSystem_Config_t &config )
  481. {
  482. if ( IsX360() )
  483. {
  484. // these overrides cannot be supported
  485. // the console configuration is explicit
  486. return;
  487. }
  488. if ( CommandLine()->FindParm( "-dxlevel" ) )
  489. {
  490. config.dxSupportLevel = CommandLine()->ParmValue( "-dxlevel", config.dxSupportLevel );
  491. // hack, mat_dxlevel is a special case, since it's saved in the registry
  492. // but has a special different command-line override
  493. // we need to re-apply the cvar
  494. ConVarRef conVar( "mat_dxlevel" );
  495. if ( conVar.IsValid() )
  496. {
  497. conVar.SetValue( config.dxSupportLevel );
  498. }
  499. }
  500. // Check for windowed mode command line override
  501. if ( CommandLine()->FindParm( "-sw" ) ||
  502. CommandLine()->FindParm( "-startwindowed" ) ||
  503. CommandLine()->FindParm( "-windowed" ) ||
  504. CommandLine()->FindParm( "-window" ) )
  505. {
  506. config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, true );
  507. }
  508. // Check for fullscreen override
  509. else if ( CommandLine()->FindParm( "-full" ) || CommandLine()->FindParm( "-fullscreen" ) )
  510. {
  511. config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, false );
  512. }
  513. // Get width and height
  514. if ( CommandLine()->FindParm( "-width" ) || CommandLine()->FindParm( "-w" ) )
  515. {
  516. config.m_VideoMode.m_Width = CommandLine()->ParmValue( "-width", config.m_VideoMode.m_Width );
  517. config.m_VideoMode.m_Width = CommandLine()->ParmValue( "-w", config.m_VideoMode.m_Width );
  518. if( !( CommandLine()->FindParm( "-height" ) || CommandLine()->FindParm( "-h" ) ) )
  519. {
  520. config.m_VideoMode.m_Height = ( config.m_VideoMode.m_Width * 3 ) / 4;
  521. }
  522. }
  523. if ( CommandLine()->FindParm( "-height" ) || CommandLine()->FindParm( "-h" ) )
  524. {
  525. config.m_VideoMode.m_Height = CommandLine()->ParmValue( "-height", config.m_VideoMode.m_Height );
  526. config.m_VideoMode.m_Height = CommandLine()->ParmValue( "-h", config.m_VideoMode.m_Height );
  527. }
  528. #if defined( USE_SDL ) && !defined( SWDS )
  529. // If -displayindex was specified on the command line, then set sdl_displayindex.
  530. if ( CommandLine()->FindParm( "-displayindex" ) )
  531. {
  532. ConVarRef conVar( "sdl_displayindex" );
  533. if ( conVar.IsValid() )
  534. {
  535. int displayIndex = CommandLine()->ParmValue( "-displayindex", conVar.GetInt() );
  536. conVar.SetValue( displayIndex );
  537. displayIndex = conVar.GetInt();
  538. // Make sure the width / height isn't too large for this display.
  539. SDL_Rect rect;
  540. if ( !SDL_GetDisplayBounds( displayIndex, &rect ) )
  541. {
  542. if ( ( config.m_VideoMode.m_Width > rect.w ) || ( config.m_VideoMode.m_Height > rect.h ) )
  543. {
  544. config.m_VideoMode.m_Width = rect.w;
  545. config.m_VideoMode.m_Height = rect.h;
  546. }
  547. }
  548. }
  549. }
  550. #endif // USE_SDL && !SWDS
  551. if ( CommandLine()->FindParm( "-resizing" ) )
  552. {
  553. config.SetFlag( MATSYS_VIDCFG_FLAGS_RESIZING, CommandLine()->CheckParm( "-resizing" ) ? true : false );
  554. }
  555. #ifndef CSS_PERF_TEST
  556. if ( CommandLine()->FindParm( "-mat_vsync" ) )
  557. {
  558. int vsync = CommandLine()->ParmValue( "-mat_vsync", 1 );
  559. config.SetFlag( MATSYS_VIDCFG_FLAGS_NO_WAIT_FOR_VSYNC, vsync == 0 );
  560. }
  561. #endif
  562. config.m_nAASamples = CommandLine()->ParmValue( "-mat_antialias", config.m_nAASamples );
  563. config.m_nAAQuality = CommandLine()->ParmValue( "-mat_aaquality", config.m_nAAQuality );
  564. // Clamp the requested dimensions to the display resolution
  565. MaterialVideoMode_t videoMode;
  566. materials->GetDisplayMode( videoMode );
  567. config.m_VideoMode.m_Width = MIN( videoMode.m_Width, config.m_VideoMode.m_Width );
  568. config.m_VideoMode.m_Height = MIN( videoMode.m_Height, config.m_VideoMode.m_Height );
  569. // safe mode
  570. if ( CommandLine()->FindParm( "-safe" ) )
  571. {
  572. config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, true );
  573. config.m_VideoMode.m_Width = 640;
  574. config.m_VideoMode.m_Height = 480;
  575. config.m_VideoMode.m_RefreshRate = 0;
  576. config.m_nAASamples = 0;
  577. config.m_nAAQuality = 0;
  578. }
  579. }
  580. //-----------------------------------------------------------------------------
  581. // Updates the material system config
  582. //-----------------------------------------------------------------------------
  583. void OverrideMaterialSystemConfig( MaterialSystem_Config_t &config )
  584. {
  585. // enable/disable flashlight support based on mod (user can also set this explicitly)
  586. // FIXME: this is only here because dxsupport_override.cfg is currently broken
  587. ConVarRef mat_supportflashlight( "mat_supportflashlight" );
  588. if ( mat_supportflashlight.GetInt() == -1 )
  589. {
  590. const char * gameName = COM_GetModDirectory();
  591. if ( !V_stricmp( gameName, "portal" ) ||
  592. !V_stricmp( gameName, "tf" ) ||
  593. !V_stricmp( gameName, "tf_beta" ) )
  594. {
  595. mat_supportflashlight.SetValue( false );
  596. }
  597. else
  598. {
  599. mat_supportflashlight.SetValue( true );
  600. }
  601. }
  602. config.m_bSupportFlashlight = mat_supportflashlight.GetBool();
  603. // apply the settings in the material system
  604. bool bLightmapsNeedReloading = materials->OverrideConfig( config, false );
  605. if ( bLightmapsNeedReloading )
  606. {
  607. s_bConfigLightingChanged = true;
  608. }
  609. // if VRModeAdapter is set, don't let things come up full screen
  610. // They will be on the HMD display and that's BAD.
  611. if( config.m_nVRModeAdapter != -1 )
  612. {
  613. WriteVideoConfigInt( "ScreenWindowed", 1 );
  614. config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, true );
  615. }
  616. }
  617. void HandleServerAllowColorCorrection()
  618. {
  619. #ifndef SWDS
  620. if ( !sv_allow_color_correction.GetBool() && mat_colorcorrection.GetInt() )
  621. {
  622. Warning( "mat_colorcorrection being forced to 0 due to sv_allow_color_correction=0.\n" );
  623. mat_colorcorrection.SetValue( 0 );
  624. }
  625. #endif
  626. }
  627. // auto config version to store in the registry so we can force reconfigs if needed
  628. #define AUTOCONFIG_VERSION 1
  629. //-----------------------------------------------------------------------------
  630. // Purpose: Initializes configuration
  631. //-----------------------------------------------------------------------------
  632. void InitMaterialSystemConfig( bool bInEditMode )
  633. {
  634. // get the default config for the current card as a starting point.
  635. g_pMaterialSystemConfig = &materials->GetCurrentConfigForVideoCard();
  636. if ( !g_pMaterialSystemConfig )
  637. {
  638. Sys_Error( "Could not get the material system config record!" );
  639. }
  640. if ( bInEditMode )
  641. return;
  642. MaterialSystem_Config_t config = *g_pMaterialSystemConfig;
  643. #if !defined(SWDS)
  644. // see if they've changed video card, or have no settings present
  645. MaterialAdapterInfo_t driverInfo;
  646. materials->GetDisplayAdapterInfo( materials->GetCurrentAdapter(), driverInfo );
  647. // see if the user has changed video cards or dx levels
  648. uint currentVendorID = ReadVideoConfigInt( "VendorID", -1 );
  649. uint currentDeviceID = ReadVideoConfigInt( "DeviceID", -1 );
  650. uint autoConfigVersion = ReadVideoConfigInt( "AutoConfigVersion", -1 );
  651. if ( autoConfigVersion != AUTOCONFIG_VERSION )
  652. {
  653. uint max_dxlevel, recommended_dxlevel;
  654. materials->GetDXLevelDefaults( max_dxlevel, recommended_dxlevel );
  655. uint currentDXLevel = ReadVideoConfigInt( "DXLevel_V1", -1 );
  656. if ((max_dxlevel != recommended_dxlevel) && (currentDXLevel != recommended_dxlevel))
  657. {
  658. ConVarRef conVar( "mat_dxlevel" );
  659. if ( conVar.IsValid() )
  660. {
  661. conVar.SetValue( (int)recommended_dxlevel );
  662. }
  663. }
  664. // Update the autoconfig version.
  665. WriteVideoConfigInt( "AutoConfigVersion", AUTOCONFIG_VERSION );
  666. }
  667. if ( driverInfo.m_VendorID == currentVendorID &&
  668. driverInfo.m_DeviceID == currentDeviceID &&
  669. !CommandLine()->FindParm( "-autoconfig" ) &&
  670. !CommandLine()->FindParm( "-dxlevel" ))
  671. {
  672. // the stored configuration looks like it will be valid, load it in
  673. ReadMaterialSystemConfigFromRegistry( config );
  674. }
  675. #endif
  676. OverrideMaterialSystemConfigFromCommandLine( config );
  677. OverrideMaterialSystemConfig( config );
  678. // Force the convars to update -- need this due to threading
  679. g_pCVar->ProcessQueuedMaterialThreadConVarSets();
  680. // Don't smack registry if dxlevel is overridden, or if the video config was overridden from the command line.
  681. if ( !CommandLine()->FindParm( "-dxlevel" ) && !s_bVideoConfigOverriddenFromCmdLine )
  682. {
  683. WriteMaterialSystemConfigToRegistry( *g_pMaterialSystemConfig );
  684. }
  685. UpdateMaterialSystemConfig();
  686. #if !defined(SWDS)
  687. // write out the current vendor has been seen & registered
  688. WriteVideoConfigInt( "VendorID", driverInfo.m_VendorID );
  689. WriteVideoConfigInt( "DeviceID", driverInfo.m_DeviceID );
  690. WriteVideoConfigInt( "DXLevel_V1", g_pMaterialSystemConfig->dxSupportLevel );
  691. #endif
  692. }
  693. //-----------------------------------------------------------------------------
  694. // Updates the material system config
  695. //-----------------------------------------------------------------------------
  696. void UpdateMaterialSystemConfig( void )
  697. {
  698. if ( host_state.worldbrush && !host_state.worldbrush->lightdata )
  699. {
  700. mat_fullbright.SetValue( 1 );
  701. }
  702. // apply the settings in the material system
  703. bool bLightmapsNeedReloading = materials->UpdateConfig( false );
  704. if ( bLightmapsNeedReloading )
  705. {
  706. s_bConfigLightingChanged = true;
  707. }
  708. }
  709. //-----------------------------------------------------------------------------
  710. // Purpose: Sets all the relevant keyvalue data to be uploaded as part of the benchmark data
  711. // Input : *dataToUpload - keyvalue set that will be uploaded
  712. //-----------------------------------------------------------------------------
  713. void GetMaterialSystemConfigForBenchmarkUpload(KeyValues *dataToUpload)
  714. {
  715. #if !defined(SWDS)
  716. // hardware info
  717. MaterialAdapterInfo_t driverInfo;
  718. materials->GetDisplayAdapterInfo( materials->GetCurrentAdapter(), driverInfo );
  719. dataToUpload->SetInt( "vendorID", driverInfo.m_VendorID );
  720. dataToUpload->SetInt( "deviceID", driverInfo.m_DeviceID );
  721. dataToUpload->SetInt( "ram", GetRam() );
  722. const CPUInformation& pi = *GetCPUInformation();
  723. double fFrequency = pi.m_Speed / 1000000.0;
  724. dataToUpload->SetInt( "cpu_speed", (int)fFrequency );
  725. dataToUpload->SetString( "cpu", pi.m_szProcessorID );
  726. // material system settings
  727. dataToUpload->SetInt( "width", g_pMaterialSystemConfig->m_VideoMode.m_Width );
  728. dataToUpload->SetInt( "height", g_pMaterialSystemConfig->m_VideoMode.m_Height );
  729. dataToUpload->SetInt( "AASamples", g_pMaterialSystemConfig->m_nAASamples );
  730. dataToUpload->SetInt( "AAQuality", g_pMaterialSystemConfig->m_nAAQuality );
  731. dataToUpload->SetInt( "AnisoLevel", g_pMaterialSystemConfig->m_nForceAnisotropicLevel );
  732. dataToUpload->SetInt( "SkipMipLevels", g_pMaterialSystemConfig->skipMipLevels );
  733. dataToUpload->SetInt( "DXLevel", g_pMaterialSystemConfig->dxSupportLevel );
  734. dataToUpload->SetInt( "ShadowDepthTexture", g_pMaterialSystemConfig->ShadowDepthTexture() );
  735. dataToUpload->SetInt( "MotionBlur", g_pMaterialSystemConfig->MotionBlur() );
  736. dataToUpload->SetInt( "Windowed", (g_pMaterialSystemConfig->m_Flags & MATSYS_VIDCFG_FLAGS_WINDOWED) ? 1 : 0 );
  737. dataToUpload->SetInt( "Trilinear", (g_pMaterialSystemConfig->m_Flags & MATSYS_VIDCFG_FLAGS_FORCE_TRILINEAR) ? 1 : 0 );
  738. dataToUpload->SetInt( "ForceHWSync", (g_pMaterialSystemConfig->m_Flags & MATSYS_VIDCFG_FLAGS_FORCE_HWSYNC) ? 1 : 0 );
  739. dataToUpload->SetInt( "NoWaitForVSync", (g_pMaterialSystemConfig->m_Flags & MATSYS_VIDCFG_FLAGS_NO_WAIT_FOR_VSYNC) ? 1 : 0 );
  740. dataToUpload->SetInt( "DisableSpecular", (g_pMaterialSystemConfig->m_Flags & MATSYS_VIDCFG_FLAGS_DISABLE_SPECULAR) ? 1 : 0 );
  741. dataToUpload->SetInt( "DisableBumpmapping", (g_pMaterialSystemConfig->m_Flags & MATSYS_VIDCFG_FLAGS_DISABLE_BUMPMAP) ? 1 : 0 );
  742. dataToUpload->SetInt( "EnableParallaxMapping", (g_pMaterialSystemConfig->m_Flags & MATSYS_VIDCFG_FLAGS_ENABLE_PARALLAX_MAPPING) ? 1 : 0 );
  743. dataToUpload->SetInt( "ZPrefill", (g_pMaterialSystemConfig->m_Flags & MATSYS_VIDCFG_FLAGS_USE_Z_PREFILL) ? 1 : 0 );
  744. dataToUpload->SetInt( "ReduceFillRate", (g_pMaterialSystemConfig->m_Flags & MATSYS_VIDCFG_FLAGS_REDUCE_FILLRATE) ? 1 : 0 );
  745. dataToUpload->SetInt( "RenderToTextureShadows", r_shadowrendertotexture.GetInt() ? 1 : 0 );
  746. dataToUpload->SetInt( "FlashlightDepthTexture", r_flashlightdepthtexture.GetInt() ? 1 : 0 );
  747. #ifndef _X360
  748. dataToUpload->SetInt( "RealtimeWaterReflection", r_waterforceexpensive.GetInt() ? 1 : 0 );
  749. #endif
  750. dataToUpload->SetInt( "WaterReflectEntities", r_waterforcereflectentities.GetInt() ? 1 : 0 );
  751. #endif
  752. }
  753. //-----------------------------------------------------------------------------
  754. // Purpose: Dumps the specified config info to the console
  755. //-----------------------------------------------------------------------------
  756. void PrintMaterialSystemConfig( const MaterialSystem_Config_t &config )
  757. {
  758. Warning( "width: %d\n", config.m_VideoMode.m_Width );
  759. Warning( "height: %d\n", config.m_VideoMode.m_Height );
  760. Warning( "m_nForceAnisotropicLevel: %d\n", config.m_nForceAnisotropicLevel );
  761. Warning( "aasamples: %d\n", config.m_nAASamples );
  762. Warning( "aaquality: %d\n", config.m_nAAQuality );
  763. Warning( "skipMipLevels: %d\n", config.skipMipLevels );
  764. Warning( "dxSupportLevel: %d\n", config.dxSupportLevel );
  765. Warning( "monitorGamma: %f\n", config.m_fMonitorGamma );
  766. Warning( "MATSYS_VIDCFG_FLAGS_WINDOWED: %s\n", ( config.m_Flags & MATSYS_VIDCFG_FLAGS_WINDOWED ) ? "true" : "false" );
  767. Warning( "MATSYS_VIDCFG_FLAGS_FORCE_TRILINEAR: %s\n", ( config.m_Flags & MATSYS_VIDCFG_FLAGS_FORCE_TRILINEAR ) ? "true" : "false" );
  768. Warning( "MATSYS_VIDCFG_FLAGS_FORCE_HWSYNC: %s\n", ( config.m_Flags & MATSYS_VIDCFG_FLAGS_FORCE_HWSYNC ) ? "true" : "false" );
  769. Warning( "MATSYS_VIDCFG_FLAGS_DISABLE_SPECULAR: %s\n", ( config.m_Flags & MATSYS_VIDCFG_FLAGS_DISABLE_SPECULAR ) ? "true" : "false" );
  770. Warning( "MATSYS_VIDCFG_FLAGS_ENABLE_PARALLAX_MAPPING: %s\n", ( config.m_Flags & MATSYS_VIDCFG_FLAGS_ENABLE_PARALLAX_MAPPING ) ? "true" : "false" );
  771. Warning( "MATSYS_VIDCFG_FLAGS_USE_Z_PREFILL: %s\n", ( config.m_Flags & MATSYS_VIDCFG_FLAGS_USE_Z_PREFILL ) ? "true" : "false" );
  772. Warning( "MATSYS_VIDCFG_FLAGS_REDUCE_FILLRATE: %s\n", ( config.m_Flags & MATSYS_VIDCFG_FLAGS_REDUCE_FILLRATE ) ? "true" : "false" );
  773. Warning( "r_shadowrendertotexture: %s\n", r_shadowrendertotexture.GetInt() ? "true" : "false" );
  774. Warning( "motionblur: %s\n", config.m_bMotionBlur ? "true" : "false" );
  775. Warning( "shadowdepthtexture: %s\n", config.m_bShadowDepthTexture ? "true" : "false" );
  776. #ifndef _X360
  777. Warning( "r_waterforceexpensive: %s\n", r_waterforceexpensive.GetInt() ? "true" : "false" );
  778. #endif
  779. Warning( "r_waterforcereflectentities: %s\n", r_waterforcereflectentities.GetInt() ? "true" : "false" );
  780. }
  781. CON_COMMAND( mat_configcurrent, "show the current video control panel config for the material system" )
  782. {
  783. const MaterialSystem_Config_t &config = materials->GetCurrentConfigForVideoCard();
  784. PrintMaterialSystemConfig( config );
  785. }
  786. #if !defined(SWDS) && !defined( _X360 )
  787. CON_COMMAND( mat_setvideomode, "sets the width, height, windowed state of the material system" )
  788. {
  789. if ( args.ArgC() != 4 )
  790. return;
  791. int nWidth = Q_atoi( args[1] );
  792. int nHeight = Q_atoi( args[2] );
  793. bool bWindowed = Q_atoi( args[3] ) > 0 ? true : false;
  794. videomode->SetMode( nWidth, nHeight, bWindowed );
  795. }
  796. #endif
  797. CON_COMMAND( mat_enable_vrmode, "Switches the material system to VR mode (after restart)" )
  798. {
  799. if( args.ArgC() != 2 )
  800. return;
  801. if( !g_pSourceVR )
  802. return;
  803. ConVarRef mat_vrmode_adapter( "mat_vrmode_adapter" );
  804. bool bVRMode = Q_atoi( args[1] ) != 0;
  805. if( bVRMode )
  806. {
  807. #if defined( _WIN32 )
  808. int32 nVRModeAdapter = g_pSourceVR->GetVRModeAdapter();
  809. if( nVRModeAdapter == -1 )
  810. {
  811. Warning( "Unable to get VRModeAdapter from OpenVR. VR mode will not be enabled. Try restarting and then enabling VR again.\n" );
  812. }
  813. mat_vrmode_adapter.SetValue( nVRModeAdapter );
  814. #else
  815. mat_vrmode_adapter.SetValue( 0 ); // This convar isn't actually used on other platforms so just use 0 to indicate that it's set
  816. #endif
  817. }
  818. else
  819. {
  820. mat_vrmode_adapter.SetValue( -1 );
  821. }
  822. }
  823. CON_COMMAND( mat_savechanges, "saves current video configuration to the registry" )
  824. {
  825. // if the user has got to the point where they can adjust and apply video changes, then we can clear safe mode
  826. CommandLine()->RemoveParm( "-safe" );
  827. // write out config
  828. UpdateMaterialSystemConfig();
  829. if ( !CommandLine()->FindParm( "-dxlevel" ) )
  830. {
  831. WriteMaterialSystemConfigToRegistry( *g_pMaterialSystemConfig );
  832. }
  833. }
  834. #ifdef _DEBUG
  835. //-----------------------------------------------------------------------------
  836. // A console command to debug materials
  837. //-----------------------------------------------------------------------------
  838. CON_COMMAND_F( mat_debug, "Activates debugging spew for a specific material.", FCVAR_CHEAT )
  839. {
  840. if ( args.ArgC() != 2 )
  841. {
  842. ConMsg ("usage: mat_debug [ <material name> ]\n");
  843. return;
  844. }
  845. materials->ToggleDebugMaterial( args[1] );
  846. }
  847. //-----------------------------------------------------------------------------
  848. // A console command to suppress materials
  849. //-----------------------------------------------------------------------------
  850. CON_COMMAND_F( mat_suppress, "Supress a material from drawing", FCVAR_CHEAT )
  851. {
  852. if ( args.ArgC() != 2 )
  853. {
  854. ConMsg ("usage: mat_suppress [ <material name> ]\n");
  855. return;
  856. }
  857. materials->ToggleSuppressMaterial( args[1] );
  858. }
  859. #endif // _DEBUG
  860. static ITexture *CreatePowerOfTwoFBTexture( void )
  861. {
  862. if ( IsX360() )
  863. return NULL;
  864. return materials->CreateNamedRenderTargetTextureEx2(
  865. "_rt_PowerOfTwoFB",
  866. 1024, 1024, RT_SIZE_DEFAULT,
  867. // Has dest alpha for vort warp effect
  868. IMAGE_FORMAT_RGBA8888,
  869. MATERIAL_RT_DEPTH_SHARED,
  870. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
  871. CREATERENDERTARGETFLAGS_HDR );
  872. }
  873. static ITexture *CreateWaterReflectionTexture( void )
  874. {
  875. return materials->CreateNamedRenderTargetTextureEx2(
  876. "_rt_WaterReflection",
  877. 1024, 1024, RT_SIZE_PICMIP,
  878. materials->GetBackBufferFormat(),
  879. MATERIAL_RT_DEPTH_SHARED,
  880. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
  881. CREATERENDERTARGETFLAGS_HDR );
  882. }
  883. static ITexture *CreateWaterRefractionTexture( void )
  884. {
  885. return materials->CreateNamedRenderTargetTextureEx2(
  886. "_rt_WaterRefraction",
  887. 1024, 1024, RT_SIZE_PICMIP,
  888. // This is different than reflection because it has to have alpha for fog factor.
  889. IMAGE_FORMAT_RGBA8888,
  890. MATERIAL_RT_DEPTH_SHARED,
  891. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
  892. CREATERENDERTARGETFLAGS_HDR );
  893. }
  894. static ITexture *CreateCameraTexture( void )
  895. {
  896. return materials->CreateNamedRenderTargetTextureEx2(
  897. "_rt_Camera",
  898. 256, 256, RT_SIZE_DEFAULT,
  899. materials->GetBackBufferFormat(),
  900. MATERIAL_RT_DEPTH_SHARED,
  901. 0,
  902. CREATERENDERTARGETFLAGS_HDR );
  903. }
  904. static ITexture *CreateBuildCubemaps16BitTexture( void )
  905. {
  906. return materials->CreateNamedRenderTargetTextureEx2(
  907. "_rt_BuildCubemaps16bit",
  908. 0, 0,
  909. RT_SIZE_FULL_FRAME_BUFFER,
  910. IMAGE_FORMAT_RGBA16161616,
  911. MATERIAL_RT_DEPTH_SHARED );
  912. }
  913. static ITexture *CreateQuarterSizedFBTexture( int n, unsigned int iRenderTargetFlags )
  914. {
  915. char nbuf[20];
  916. sprintf(nbuf,"_rt_SmallFB%d",n);
  917. ImageFormat fmt=materials->GetBackBufferFormat();
  918. if ( g_pMaterialSystemHardwareConfig->GetHDRType() == HDR_TYPE_FLOAT )
  919. fmt = IMAGE_FORMAT_RGBA16161616F;
  920. return materials->CreateNamedRenderTargetTextureEx2(
  921. nbuf, 0, 0, RT_SIZE_HDR,
  922. fmt, MATERIAL_RT_DEPTH_SHARED,
  923. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
  924. iRenderTargetFlags );
  925. }
  926. static ITexture *CreateTeenyFBTexture( int n )
  927. {
  928. char nbuf[20];
  929. sprintf(nbuf,"_rt_TeenyFB%d",n);
  930. ImageFormat fmt = materials->GetBackBufferFormat();
  931. if ( g_pMaterialSystemHardwareConfig->GetHDRType() == HDR_TYPE_FLOAT )
  932. fmt = IMAGE_FORMAT_RGBA16161616F;
  933. return materials->CreateNamedRenderTargetTextureEx2(
  934. nbuf, 32, 32, RT_SIZE_DEFAULT,
  935. fmt, MATERIAL_RT_DEPTH_SHARED );
  936. }
  937. static ITexture *CreateFullFrameFBTexture( int textureIndex, int iExtraFlags = 0 )
  938. {
  939. char textureName[256];
  940. if ( textureIndex > 0 )
  941. {
  942. sprintf( textureName, "_rt_FullFrameFB%d", textureIndex );
  943. }
  944. else
  945. {
  946. V_strcpy_safe( textureName, "_rt_FullFrameFB" );
  947. }
  948. int rtFlags = iExtraFlags | CREATERENDERTARGETFLAGS_HDR;
  949. if ( IsX360() )
  950. {
  951. // just make the system memory texture only
  952. rtFlags |= CREATERENDERTARGETFLAGS_NOEDRAM;
  953. }
  954. return materials->CreateNamedRenderTargetTextureEx2(
  955. textureName,
  956. 1, 1, RT_SIZE_FULL_FRAME_BUFFER, materials->GetBackBufferFormat(),
  957. MATERIAL_RT_DEPTH_SHARED,
  958. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
  959. rtFlags );
  960. }
  961. static ITexture *CreateFullFrameDepthTexture( void )
  962. {
  963. if ( IsX360() )
  964. {
  965. return materials->CreateNamedRenderTargetTextureEx2( "_rt_FullFrameDepth", 1, 1,
  966. RT_SIZE_FULL_FRAME_BUFFER, materials->GetShadowDepthTextureFormat(), MATERIAL_RT_DEPTH_NONE,
  967. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_POINTSAMPLE,
  968. CREATERENDERTARGETFLAGS_NOEDRAM );
  969. }
  970. else
  971. {
  972. materials->AddTextureAlias( "_rt_FullFrameDepth", "_rt_PowerOfTwoFB" );
  973. }
  974. return NULL;
  975. }
  976. static ITexture *CreateResolvedFullFrameDepthTexture( void )
  977. {
  978. if ( IsPC() )
  979. {
  980. return materials->CreateNamedRenderTargetTextureEx2( "_rt_ResolvedFullFrameDepth", 1, 1,
  981. RT_SIZE_FULL_FRAME_BUFFER, IMAGE_FORMAT_RGBA8888, MATERIAL_RT_DEPTH_SEPARATE,
  982. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_POINTSAMPLE,
  983. CREATERENDERTARGETFLAGS_NOEDRAM );
  984. }
  985. return NULL;
  986. }
  987. //-----------------------------------------------------------------------------
  988. // Purpose: Create render targets which mods rely upon to render correctly
  989. //-----------------------------------------------------------------------------
  990. void InitWellKnownRenderTargets( void )
  991. {
  992. #if !defined( SWDS )
  993. if ( mat_debugalttab.GetBool() )
  994. {
  995. Warning( "mat_debugalttab: InitWellKnownRenderTargets\n" );
  996. }
  997. // Begin block in which all render targets should be allocated
  998. materials->BeginRenderTargetAllocation();
  999. // JasonM -
  1000. // Do we put logic in here to determine which of these to create, based upon DX level, HDR enable etc?
  1001. // YES! DX Level should gate these
  1002. // before we create anything, see if VR mode wants to override the "framebuffer" size
  1003. if( UseVR() )
  1004. {
  1005. int nWidth, nHeight;
  1006. g_pSourceVR->GetRenderTargetFrameBufferDimensions( nWidth, nHeight );
  1007. g_pMaterialSystem->SetRenderTargetFrameBufferSizeOverrides( nWidth, nHeight );
  1008. }
  1009. else
  1010. {
  1011. g_pMaterialSystem->SetRenderTargetFrameBufferSizeOverrides( 0, 0 );
  1012. }
  1013. // Create the render targets upon which mods may rely
  1014. if ( IsPC() )
  1015. {
  1016. // Create for all mods as vgui2 uses it for 3D painting
  1017. g_PowerOfTwoFBTexture.Init( CreatePowerOfTwoFBTexture() );
  1018. }
  1019. // Create these for all mods because the engine references them
  1020. if ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() >= 80 )
  1021. {
  1022. if ( IsPC() && g_pMaterialSystemHardwareConfig->GetDXSupportLevel() >= 90 &&
  1023. g_pMaterialSystemHardwareConfig->GetHDRType() == HDR_TYPE_FLOAT )
  1024. {
  1025. // Used for building HDR Cubemaps
  1026. g_BuildCubemaps16BitTexture.Init( CreateBuildCubemaps16BitTexture() );
  1027. }
  1028. // Used in Bloom effects
  1029. g_QuarterSizedFBTexture0.Init( CreateQuarterSizedFBTexture( 0, 0 ) );
  1030. if( IsX360() )
  1031. materials->AddTextureAlias( "_rt_SmallFB1", "_rt_SmallFB0" ); //an alias is good enough on the 360 since we don't have a texture lock problem during post processing
  1032. else
  1033. g_QuarterSizedFBTexture1.Init( CreateQuarterSizedFBTexture( 1, 0 ) );
  1034. }
  1035. if ( IsPC() )
  1036. {
  1037. g_TeenyFBTexture0.Init( CreateTeenyFBTexture( 0 ) );
  1038. g_TeenyFBTexture1.Init( CreateTeenyFBTexture( 1 ) );
  1039. g_TeenyFBTexture2.Init( CreateTeenyFBTexture( 2 ) );
  1040. }
  1041. g_FullFrameFBTexture0.Init( CreateFullFrameFBTexture( 0 ) );
  1042. g_FullFrameFBTexture1.Init( CreateFullFrameFBTexture( 1 ) );
  1043. if ( IsX360() )
  1044. {
  1045. g_FullFrameFBTexture2.Init( CreateFullFrameFBTexture( 2, CREATERENDERTARGETFLAGS_TEMP ) );
  1046. }
  1047. g_FullFrameDepth.Init( CreateFullFrameDepthTexture() );
  1048. g_ResolvedFullFrameDepth.Init( CreateResolvedFullFrameDepthTexture() );
  1049. // if we're in stereo mode init a render target for VGUI
  1050. if( UseVR() )
  1051. {
  1052. g_pSourceVR->CreateRenderTargets( materials );
  1053. }
  1054. // Allow the client to init their own mod-specific render targets
  1055. if ( g_pClientRenderTargets )
  1056. {
  1057. g_pClientRenderTargets->InitClientRenderTargets( materials, g_pMaterialSystemHardwareConfig );
  1058. }
  1059. else
  1060. {
  1061. // If this mod doesn't define the interface, fallback to initializing the standard render textures
  1062. // NOTE: these should match up with the 'Get' functions in cl_dll/rendertexture.h/cpp
  1063. g_WaterReflectionTexture.Init( CreateWaterReflectionTexture() );
  1064. g_WaterRefractionTexture.Init( CreateWaterRefractionTexture() );
  1065. g_CameraTexture.Init( CreateCameraTexture() );
  1066. }
  1067. // End block in which all render targets should be allocated (kicking off an Alt-Tab type behavior)
  1068. materials->EndRenderTargetAllocation();
  1069. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1070. pRenderContext->SetNonInteractiveTempFullscreenBuffer( g_FullFrameFBTexture0, MATERIAL_NON_INTERACTIVE_MODE_LEVEL_LOAD );
  1071. #endif
  1072. }
  1073. //-----------------------------------------------------------------------------
  1074. // Purpose: Shut down the render targets which mods rely upon to render correctly
  1075. //-----------------------------------------------------------------------------
  1076. void ShutdownWellKnownRenderTargets( void )
  1077. {
  1078. #if !defined( SWDS )
  1079. if ( IsX360() )
  1080. {
  1081. // cannot allowing RT's to reconstruct, causes other fatal problems
  1082. // many other 360 systems have been coded with this expected constraint
  1083. Assert( 0 );
  1084. return;
  1085. }
  1086. if ( IsPC() && mat_debugalttab.GetBool() )
  1087. {
  1088. Warning( "mat_debugalttab: ShutdownWellKnownRenderTargets\n" );
  1089. }
  1090. g_PowerOfTwoFBTexture.Shutdown();
  1091. g_BuildCubemaps16BitTexture.Shutdown();
  1092. g_QuarterSizedFBTexture0.Shutdown();
  1093. if( IsX360() )
  1094. materials->RemoveTextureAlias( "_rt_SmallFB1" );
  1095. else
  1096. g_QuarterSizedFBTexture1.Shutdown();
  1097. g_TeenyFBTexture0.Shutdown();
  1098. g_TeenyFBTexture1.Shutdown();
  1099. g_TeenyFBTexture2.Shutdown();
  1100. g_FullFrameFBTexture0.Shutdown();
  1101. g_FullFrameFBTexture1.Shutdown();
  1102. if ( IsX360() )
  1103. {
  1104. g_FullFrameFBTexture2.Shutdown();
  1105. }
  1106. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1107. pRenderContext->SetNonInteractiveTempFullscreenBuffer( NULL, MATERIAL_NON_INTERACTIVE_MODE_LEVEL_LOAD );
  1108. g_FullFrameDepth.Shutdown();
  1109. if( IsPC() )
  1110. {
  1111. materials->RemoveTextureAlias( "_rt_FullFrameDepth" );
  1112. }
  1113. if( g_pSourceVR )
  1114. g_pSourceVR->ShutdownRenderTargets();
  1115. // Shutdown client render targets
  1116. if ( g_pClientRenderTargets )
  1117. {
  1118. g_pClientRenderTargets->ShutdownClientRenderTargets();
  1119. }
  1120. else
  1121. {
  1122. g_WaterReflectionTexture.Shutdown();
  1123. g_WaterRefractionTexture.Shutdown();
  1124. g_CameraTexture.Shutdown();
  1125. }
  1126. #endif
  1127. }
  1128. //-----------------------------------------------------------------------------
  1129. // A console command to spew out driver information
  1130. //-----------------------------------------------------------------------------
  1131. CON_COMMAND( mat_reset_rendertargets, "Resets all the render targets" )
  1132. {
  1133. ShutdownWellKnownRenderTargets();
  1134. InitWellKnownRenderTargets();
  1135. }
  1136. //-----------------------------------------------------------------------------
  1137. // Purpose: Make the debug system materials
  1138. //-----------------------------------------------------------------------------
  1139. static void InitDebugMaterials( void )
  1140. {
  1141. if ( IsPC() && mat_debugalttab.GetBool() )
  1142. {
  1143. Warning( "mat_debugalttab: InitDebugMaterials\n" );
  1144. }
  1145. g_materialEmpty = GL_LoadMaterial( "debug/debugempty", TEXTURE_GROUP_OTHER );
  1146. #ifndef SWDS
  1147. g_materialWireframe = GL_LoadMaterial( "debug/debugwireframe", TEXTURE_GROUP_OTHER );
  1148. g_materialTranslucentSingleColor = GL_LoadMaterial( "debug/debugtranslucentsinglecolor", TEXTURE_GROUP_OTHER );
  1149. g_materialTranslucentVertexColor = GL_LoadMaterial( "debug/debugtranslucentvertexcolor", TEXTURE_GROUP_OTHER );
  1150. g_materialWorldWireframe = GL_LoadMaterial( "debug/debugworldwireframe", TEXTURE_GROUP_OTHER );
  1151. g_materialWorldWireframeZBuffer = GL_LoadMaterial( "debug/debugworldwireframezbuffer", TEXTURE_GROUP_OTHER );
  1152. g_materialBrushWireframe = GL_LoadMaterial( "debug/debugbrushwireframe", TEXTURE_GROUP_OTHER );
  1153. g_materialDecalWireframe = GL_LoadMaterial( "debug/debugdecalwireframe", TEXTURE_GROUP_OTHER );
  1154. g_materialDebugLightmap = GL_LoadMaterial( "debug/debuglightmap", TEXTURE_GROUP_OTHER );
  1155. g_materialDebugLightmapZBuffer = GL_LoadMaterial( "debug/debuglightmapzbuffer", TEXTURE_GROUP_OTHER );
  1156. g_materialDebugLuxels = GL_LoadMaterial( "debug/debugluxels", TEXTURE_GROUP_OTHER );
  1157. g_materialLeafVisWireframe = GL_LoadMaterial( "debug/debugleafviswireframe", TEXTURE_GROUP_OTHER );
  1158. g_pMaterialWireframeVertexColor = GL_LoadMaterial( "debug/debugwireframevertexcolor", TEXTURE_GROUP_OTHER );
  1159. g_pMaterialWireframeVertexColorIgnoreZ = GL_LoadMaterial( "debug/debugwireframevertexcolorignorez", TEXTURE_GROUP_OTHER );
  1160. g_pMaterialLightSprite = GL_LoadMaterial( "engine/lightsprite", TEXTURE_GROUP_OTHER );
  1161. g_pMaterialShadowBuild = GL_LoadMaterial( "engine/shadowbuild", TEXTURE_GROUP_OTHER);
  1162. g_pMaterialMRMWireframe = GL_LoadMaterial( "debug/debugmrmwireframe", TEXTURE_GROUP_OTHER );
  1163. g_pMaterialDebugFlat = GL_LoadMaterial( "debug/debugdrawflattriangles", TEXTURE_GROUP_OTHER );
  1164. g_pMaterialAmbientCube = GL_LoadMaterial( "debug/debugambientcube", TEXTURE_GROUP_OTHER );
  1165. g_pMaterialWriteZ = GL_LoadMaterial( "engine/writez", TEXTURE_GROUP_OTHER );
  1166. if( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() >= 90 )
  1167. {
  1168. // Materials for writing to shadow depth buffer
  1169. KeyValues *pVMTKeyValues = new KeyValues( "DepthWrite" );
  1170. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  1171. pVMTKeyValues->SetInt( "$alphatest", 0 );
  1172. pVMTKeyValues->SetInt( "$nocull", 0 );
  1173. g_pMaterialDepthWrite[0][0] = g_pMaterialSystem->FindProceduralMaterial( "__DepthWrite00", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  1174. g_pMaterialDepthWrite[0][0]->IncrementReferenceCount();
  1175. pVMTKeyValues = new KeyValues( "DepthWrite" );
  1176. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  1177. pVMTKeyValues->SetInt( "$alphatest", 0 );
  1178. pVMTKeyValues->SetInt( "$nocull", 1 );
  1179. g_pMaterialDepthWrite[0][1] = g_pMaterialSystem->FindProceduralMaterial( "__DepthWrite01", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  1180. g_pMaterialDepthWrite[0][1]->IncrementReferenceCount();
  1181. pVMTKeyValues = new KeyValues( "DepthWrite" );
  1182. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  1183. pVMTKeyValues->SetInt( "$alphatest", 1 );
  1184. pVMTKeyValues->SetInt( "$nocull", 0 );
  1185. g_pMaterialDepthWrite[1][0] = g_pMaterialSystem->FindProceduralMaterial( "__DepthWrite10", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  1186. g_pMaterialDepthWrite[1][0]->IncrementReferenceCount();
  1187. pVMTKeyValues = new KeyValues( "DepthWrite" );
  1188. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  1189. pVMTKeyValues->SetInt( "$alphatest", 1 );
  1190. pVMTKeyValues->SetInt( "$nocull", 1 );
  1191. g_pMaterialDepthWrite[1][1] = g_pMaterialSystem->FindProceduralMaterial( "__DepthWrite11", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  1192. g_pMaterialDepthWrite[1][1]->IncrementReferenceCount();
  1193. pVMTKeyValues = new KeyValues( "DepthWrite" );
  1194. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  1195. pVMTKeyValues->SetInt( "$alphatest", 0 );
  1196. pVMTKeyValues->SetInt( "$nocull", 0 );
  1197. pVMTKeyValues->SetInt( "$color_depth", 1 );
  1198. g_pMaterialSSAODepthWrite[0][0] = g_pMaterialSystem->FindProceduralMaterial( "__ColorDepthWrite00", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  1199. g_pMaterialSSAODepthWrite[0][0]->IncrementReferenceCount();
  1200. pVMTKeyValues = new KeyValues( "DepthWrite" );
  1201. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  1202. pVMTKeyValues->SetInt( "$alphatest", 0 );
  1203. pVMTKeyValues->SetInt( "$nocull", 1 );
  1204. pVMTKeyValues->SetInt( "$color_depth", 1 );
  1205. g_pMaterialSSAODepthWrite[0][1] = g_pMaterialSystem->FindProceduralMaterial( "__ColorDepthWrite01", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  1206. g_pMaterialSSAODepthWrite[0][1]->IncrementReferenceCount();
  1207. pVMTKeyValues = new KeyValues( "DepthWrite" );
  1208. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  1209. pVMTKeyValues->SetInt( "$alphatest", 1 );
  1210. pVMTKeyValues->SetInt( "$nocull", 0 );
  1211. pVMTKeyValues->SetInt( "$color_depth", 1 );
  1212. g_pMaterialSSAODepthWrite[1][0] = g_pMaterialSystem->FindProceduralMaterial( "__ColorDepthWrite10", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  1213. g_pMaterialSSAODepthWrite[1][0]->IncrementReferenceCount();
  1214. pVMTKeyValues = new KeyValues( "DepthWrite" );
  1215. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  1216. pVMTKeyValues->SetInt( "$alphatest", 1 );
  1217. pVMTKeyValues->SetInt( "$nocull", 1 );
  1218. pVMTKeyValues->SetInt( "$color_depth", 1 );
  1219. g_pMaterialSSAODepthWrite[1][1] = g_pMaterialSystem->FindProceduralMaterial( "__ColorDepthWrite11", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  1220. g_pMaterialSSAODepthWrite[1][1]->IncrementReferenceCount();
  1221. }
  1222. else
  1223. {
  1224. g_pMaterialDepthWrite[0][0] = g_pMaterialDepthWrite[0][1] = g_pMaterialDepthWrite[1][0] = g_pMaterialDepthWrite[1][1] = NULL;
  1225. g_pMaterialSSAODepthWrite[0][0] = g_pMaterialSSAODepthWrite[0][1] = g_pMaterialSSAODepthWrite[1][0] = g_pMaterialSSAODepthWrite[1][1] = NULL;
  1226. }
  1227. #endif
  1228. }
  1229. //-----------------------------------------------------------------------------
  1230. // Purpose:
  1231. //-----------------------------------------------------------------------------
  1232. static void ShutdownDebugMaterials( void )
  1233. {
  1234. if ( IsPC() && mat_debugalttab.GetBool() )
  1235. {
  1236. Warning( "mat_debugalttab: ShutdownDebugMaterials\n" );
  1237. }
  1238. GL_UnloadMaterial( g_materialEmpty );
  1239. #ifndef SWDS
  1240. GL_UnloadMaterial( g_pMaterialLightSprite );
  1241. GL_UnloadMaterial( g_pMaterialWireframeVertexColor );
  1242. GL_UnloadMaterial( g_pMaterialWireframeVertexColorIgnoreZ );
  1243. GL_UnloadMaterial( g_materialLeafVisWireframe );
  1244. GL_UnloadMaterial( g_materialDebugLuxels );
  1245. GL_UnloadMaterial( g_materialDebugLightmapZBuffer );
  1246. GL_UnloadMaterial( g_materialDebugLightmap );
  1247. GL_UnloadMaterial( g_materialDecalWireframe );
  1248. GL_UnloadMaterial( g_materialBrushWireframe );
  1249. GL_UnloadMaterial( g_materialWorldWireframeZBuffer );
  1250. GL_UnloadMaterial( g_materialWorldWireframe );
  1251. GL_UnloadMaterial( g_materialTranslucentSingleColor );
  1252. GL_UnloadMaterial( g_materialTranslucentVertexColor );
  1253. GL_UnloadMaterial( g_materialWireframe );
  1254. GL_UnloadMaterial( g_pMaterialShadowBuild );
  1255. GL_UnloadMaterial( g_pMaterialMRMWireframe );
  1256. GL_UnloadMaterial( g_pMaterialWriteZ );
  1257. GL_UnloadMaterial( g_pMaterialAmbientCube );
  1258. GL_UnloadMaterial( g_pMaterialDebugFlat );
  1259. // Materials for writing to shadow depth buffer
  1260. if ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() >= 90 )
  1261. {
  1262. for (int i = 0; i<2; i++)
  1263. {
  1264. for (int j = 0; j<2; j++)
  1265. {
  1266. if( g_pMaterialDepthWrite[i][j] )
  1267. {
  1268. g_pMaterialDepthWrite[i][j]->DecrementReferenceCount();
  1269. }
  1270. g_pMaterialDepthWrite[i][j] = NULL;
  1271. if( g_pMaterialSSAODepthWrite[i][j] )
  1272. {
  1273. g_pMaterialSSAODepthWrite[i][j]->DecrementReferenceCount();
  1274. }
  1275. g_pMaterialSSAODepthWrite[i][j] = NULL;
  1276. }
  1277. }
  1278. }
  1279. #endif
  1280. }
  1281. //-----------------------------------------------------------------------------
  1282. // Used to deal with making sure Present is called often enough
  1283. //-----------------------------------------------------------------------------
  1284. void InitStartupScreen()
  1285. {
  1286. if ( !IsX360() )
  1287. return;
  1288. #ifdef _X360
  1289. XVIDEO_MODE videoMode;
  1290. XGetVideoMode( &videoMode );
  1291. bool bIsWidescreen = videoMode.fIsWideScreen != FALSE;
  1292. #else
  1293. int width, height;
  1294. materials->GetBackBufferDimensions( width, height );
  1295. float aspectRatio = (float)width/(float)height;
  1296. bool bIsWidescreen = aspectRatio >= 1.5999f;
  1297. #endif
  1298. // NOTE: Brutal hackery, this code is duplicated in gameui.dll
  1299. // but I have to do this prior to gameui being loaded.
  1300. // 360 uses hi-res game specific backgrounds
  1301. char gameName[MAX_PATH];
  1302. char filename[MAX_PATH];
  1303. V_FileBase( com_gamedir, gameName, sizeof( gameName ) );
  1304. V_snprintf( filename, sizeof( filename ), "vgui/appchooser/background_%s%s", gameName, ( bIsWidescreen ? "_widescreen" : "" ) );
  1305. ITexture *pTexture = materials->FindTexture( filename, TEXTURE_GROUP_OTHER );
  1306. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1307. pRenderContext->SetNonInteractiveTempFullscreenBuffer( pTexture, MATERIAL_NON_INTERACTIVE_MODE_STARTUP );
  1308. pTexture = materials->FindTexture( "//platform/materials/engine/box", TEXTURE_GROUP_OTHER );
  1309. KeyValues *modinfo = new KeyValues("ModInfo");
  1310. if ( modinfo->LoadFromFile( g_pFileSystem, "gameinfo.txt" ) )
  1311. {
  1312. if ( V_stricmp( modinfo->GetString("type", "singleplayer_only" ), "multiplayer_only" ) == 0 )
  1313. {
  1314. pRenderContext->SetNonInteractivePacifierTexture( pTexture, 0.5f, 0.9f, 0.1f );
  1315. }
  1316. else
  1317. {
  1318. pRenderContext->SetNonInteractivePacifierTexture( pTexture, 0.5f, 0.86f, 0.1f );
  1319. }
  1320. }
  1321. modinfo->deleteThis();
  1322. BeginLoadingUpdates( MATERIAL_NON_INTERACTIVE_MODE_STARTUP );
  1323. }
  1324. //-----------------------------------------------------------------------------
  1325. // A console command to spew out driver information
  1326. //-----------------------------------------------------------------------------
  1327. CON_COMMAND( mat_info, "Shows material system info" )
  1328. {
  1329. materials->SpewDriverInfo();
  1330. }
  1331. void InitMaterialSystem( void )
  1332. {
  1333. materials->AddReleaseFunc( ReleaseMaterialSystemObjects );
  1334. materials->AddRestoreFunc( RestoreMaterialSystemObjects );
  1335. UpdateMaterialSystemConfig();
  1336. InitWellKnownRenderTargets();
  1337. InitDebugMaterials();
  1338. #ifndef SWDS
  1339. DispInfo_InitMaterialSystem();
  1340. #endif
  1341. #ifdef BENCHMARK
  1342. if ( g_pMaterialSystemHardwareConfig->GetDXSupportLevel() < 80 )
  1343. {
  1344. Error( "dx6 and dx7 hardware not supported by this benchmark!" );
  1345. }
  1346. #endif
  1347. }
  1348. void ShutdownMaterialSystem( void )
  1349. {
  1350. ShutdownDebugMaterials();
  1351. ShutdownWellKnownRenderTargets();
  1352. #ifndef SWDS
  1353. DispInfo_ShutdownMaterialSystem();
  1354. #endif
  1355. }
  1356. //-----------------------------------------------------------------------------
  1357. // Methods to restore, release material system objects
  1358. //-----------------------------------------------------------------------------
  1359. void ReleaseMaterialSystemObjects()
  1360. {
  1361. #ifndef SWDS
  1362. DispInfo_ReleaseMaterialSystemObjects( host_state.worldmodel );
  1363. modelrender->ReleaseAllStaticPropColorData();
  1364. #endif
  1365. #ifndef SWDS
  1366. WorldStaticMeshDestroy();
  1367. #endif
  1368. g_LostVideoMemory = true;
  1369. }
  1370. void RestoreMaterialSystemObjects( int nChangeFlags )
  1371. {
  1372. if ( IsX360() )
  1373. return;
  1374. bool bThreadingAllowed = Host_AllowQueuedMaterialSystem( false );
  1375. g_LostVideoMemory = false;
  1376. if ( nChangeFlags & MATERIAL_RESTORE_VERTEX_FORMAT_CHANGED )
  1377. {
  1378. // ensure decals have no stale references to invalid lods
  1379. modelrender->RemoveAllDecalsFromAllModels();
  1380. }
  1381. if (host_state.worldmodel)
  1382. {
  1383. if ( (nChangeFlags & MATERIAL_RESTORE_VERTEX_FORMAT_CHANGED) || materials->GetNumSortIDs() == 0 )
  1384. {
  1385. #ifndef SWDS
  1386. // Reload lightmaps, world meshes, etc. because we may have switched from bumped to unbumped
  1387. R_LoadWorldGeometry( true );
  1388. #endif
  1389. }
  1390. else
  1391. {
  1392. modelloader->Map_LoadDisplacements( host_state.worldmodel, true );
  1393. #ifndef SWDS
  1394. WorldStaticMeshCreate();
  1395. // Gotta recreate the lightmaps
  1396. R_RedownloadAllLightmaps();
  1397. #endif
  1398. }
  1399. #ifndef SWDS
  1400. // Need to re-figure out the env_cubemaps, so blow away the lightcache.
  1401. R_StudioInitLightingCache();
  1402. modelrender->RestoreAllStaticPropColorData();
  1403. #endif
  1404. }
  1405. #ifndef DEDICATED
  1406. cl.ForceFullUpdate();
  1407. #endif
  1408. Host_AllowQueuedMaterialSystem( bThreadingAllowed );
  1409. }
  1410. bool TangentSpaceSurfaceSetup( SurfaceHandle_t surfID, Vector &tVect )
  1411. {
  1412. Vector sVect;
  1413. VectorCopy( MSurf_TexInfo( surfID )->textureVecsTexelsPerWorldUnits[0].AsVector3D(), sVect );
  1414. VectorCopy( MSurf_TexInfo( surfID )->textureVecsTexelsPerWorldUnits[1].AsVector3D(), tVect );
  1415. VectorNormalize( sVect );
  1416. VectorNormalize( tVect );
  1417. Vector tmpVect;
  1418. CrossProduct( sVect, tVect, tmpVect );
  1419. // Make sure that the tangent space works if textures are mapped "backwards".
  1420. if( DotProduct( MSurf_Plane( surfID ).normal, tmpVect ) > 0.0f )
  1421. {
  1422. return true;
  1423. }
  1424. return false;
  1425. }
  1426. void TangentSpaceComputeBasis( Vector& tangentS, Vector& tangentT, const Vector& normal, const Vector& tVect, bool negateTangent )
  1427. {
  1428. // tangent x binormal = normal
  1429. // tangent = sVect
  1430. // binormal = tVect
  1431. CrossProduct( normal, tVect, tangentS );
  1432. VectorNormalize( tangentS );
  1433. CrossProduct( tangentS, normal, tangentT );
  1434. VectorNormalize( tangentT );
  1435. if ( negateTangent )
  1436. {
  1437. VectorScale( tangentS, -1.0f, tangentS );
  1438. }
  1439. }
  1440. //-----------------------------------------------------------------------------
  1441. // Purpose:
  1442. //-----------------------------------------------------------------------------
  1443. void MaterialSystem_DestroySortinfo( void )
  1444. {
  1445. if ( materialSortInfoArray )
  1446. {
  1447. #ifndef SWDS
  1448. WorldStaticMeshDestroy();
  1449. #endif
  1450. delete[] materialSortInfoArray;
  1451. materialSortInfoArray = NULL;
  1452. }
  1453. }
  1454. #ifndef SWDS
  1455. // The amount to blend between basetexture and basetexture2 used to sit in lightmap
  1456. // alpha, so we didn't care about the vertex color or vertex alpha. But now if they're
  1457. // using it, we have to make sure the vertex has the color and alpha specified correctly
  1458. // or it will look weird.
  1459. static inline bool CheckMSurfaceBaseTexture2( worldbrushdata_t *pBrushData, SurfaceHandle_t surfID )
  1460. {
  1461. if ( !SurfaceHasDispInfo( surfID ) &&
  1462. (MSurf_TexInfo( surfID )->texinfoFlags & TEXINFO_USING_BASETEXTURE2) )
  1463. {
  1464. const char *pMaterialName = MSurf_TexInfo( surfID )->material->GetName();
  1465. if ( pMaterialName )
  1466. {
  1467. bool bShowIt = false;
  1468. if ( developer.GetInt() <= 1 )
  1469. {
  1470. static CUtlDict<int,int> nameDict;
  1471. if ( nameDict.Find( pMaterialName ) == -1 )
  1472. {
  1473. nameDict.Insert( pMaterialName, 0 );
  1474. bShowIt = true;
  1475. }
  1476. }
  1477. else
  1478. {
  1479. bShowIt = true;
  1480. }
  1481. if ( bShowIt )
  1482. {
  1483. // Calculate the surface's centerpoint.
  1484. Vector vCenter( 0, 0, 0 );
  1485. for ( int i = 0; i < MSurf_VertCount( surfID ); i++ )
  1486. {
  1487. int vertIndex = pBrushData->vertindices[MSurf_FirstVertIndex( surfID ) + i];
  1488. vCenter += pBrushData->vertexes[vertIndex].position;
  1489. }
  1490. vCenter /= (float)MSurf_VertCount( surfID );
  1491. // Spit out the warning.
  1492. Warning( "Warning: using WorldTwoTextureBlend on a non-displacement surface.\n"
  1493. "Support for this will go away soon.\n"
  1494. " - Material : %s\n"
  1495. " - Surface center : %d %d %d\n"
  1496. , pMaterialName, (int)vCenter.x, (int)vCenter.y, (int)vCenter.z );
  1497. }
  1498. }
  1499. return true;
  1500. }
  1501. else
  1502. {
  1503. return false;
  1504. }
  1505. }
  1506. //-----------------------------------------------------------------------------
  1507. // Purpose: Build a vertex buffer for this face
  1508. // Input : *pWorld - world model base
  1509. // *surf - surf to add to the mesh
  1510. // overbright - overbright factor (for colors)
  1511. // &builder - mesh that holds the vertex buffer
  1512. //-----------------------------------------------------------------------------
  1513. #ifdef NEWMESH
  1514. void BuildMSurfaceVertexArrays( worldbrushdata_t *pBrushData, SurfaceHandle_t surfID, float overbright,
  1515. CVertexBufferBuilder &builder )
  1516. {
  1517. SurfaceCtx_t ctx;
  1518. SurfSetupSurfaceContext( ctx, surfID );
  1519. byte flatColor[4] = { 255, 255, 255, 255 };
  1520. Vector tVect;
  1521. bool negate = false;
  1522. if ( MSurf_Flags( surfID ) & SURFDRAW_TANGENTSPACE )
  1523. {
  1524. negate = TangentSpaceSurfaceSetup( surfID, tVect );
  1525. }
  1526. CheckMSurfaceBaseTexture2( pBrushData, surfID );
  1527. for ( int i = 0; i < MSurf_VertCount( surfID ); i++ )
  1528. {
  1529. int vertIndex = pBrushData->vertindices[MSurf_FirstVertIndex( surfID ) + i];
  1530. // world-space vertex
  1531. Vector& vec = pBrushData->vertexes[vertIndex].position;
  1532. // output to mesh
  1533. builder.Position3fv( vec.Base() );
  1534. Vector2D uv;
  1535. SurfComputeTextureCoordinate( ctx, surfID, vec, uv );
  1536. builder.TexCoord2fv( 0, uv.Base() );
  1537. // garymct: normalized (within space of surface) lightmap texture coordinates
  1538. SurfComputeLightmapCoordinate( ctx, surfID, vec, uv );
  1539. builder.TexCoord2fv( 1, uv.Base() );
  1540. if ( MSurf_Flags( surfID ) & SURFDRAW_BUMPLIGHT )
  1541. {
  1542. // bump maps appear left to right in lightmap page memory, calculate
  1543. // the offset for the width of a single map. The pixel shader will use
  1544. // this to compute the actual texture coordinates
  1545. builder.TexCoord2f( 2, ctx.m_BumpSTexCoordOffset, 0.0f );
  1546. }
  1547. Vector& normal = pBrushData->vertnormals[ pBrushData->vertnormalindices[MSurf_FirstVertNormal( surfID ) + i] ];
  1548. builder.Normal3fv( normal.Base() );
  1549. if ( MSurf_Flags( surfID ) & SURFDRAW_TANGENTSPACE )
  1550. {
  1551. Vector tangentS, tangentT;
  1552. TangentSpaceComputeBasis( tangentS, tangentT, normal, tVect, negate );
  1553. builder.TangentS3fv( tangentS.Base() );
  1554. builder.TangentT3fv( tangentT.Base() );
  1555. }
  1556. // The amount to blend between basetexture and basetexture2 used to sit in lightmap
  1557. // alpha, so we didn't care about the vertex color or vertex alpha. But now if they're
  1558. // using it, we have to make sure the vertex has the color and alpha specified correctly
  1559. // or it will look weird.
  1560. if ( !SurfaceHasDispInfo( surfID ) &&
  1561. (MSurf_TexInfo( surfID )->texinfoFlags & TEXINFO_USING_BASETEXTURE2) )
  1562. {
  1563. static bool bWarned = false;
  1564. if ( !bWarned )
  1565. {
  1566. const char *pMaterialName = MSurf_TexInfo( surfID )->material->GetName();
  1567. bWarned = true;
  1568. Warning( "Warning: WorldTwoTextureBlend found on a non-displacement surface (material: %s). This wastes perf for no benefit.\n", pMaterialName );
  1569. }
  1570. builder.Color4ub( 255, 255, 255, 0 );
  1571. }
  1572. else
  1573. {
  1574. builder.Color3ubv( flatColor );
  1575. }
  1576. builder.AdvanceVertex();
  1577. }
  1578. }
  1579. #else
  1580. //-----------------------------------------------------------------------------
  1581. // Purpose: Build a vertex buffer for this face
  1582. // Input : *pWorld - world model base
  1583. // *surf - surf to add to the mesh
  1584. // overbright - overbright factor (for colors)
  1585. // &builder - mesh that holds the vertex buffer
  1586. //-----------------------------------------------------------------------------
  1587. void BuildMSurfaceVertexArrays( worldbrushdata_t *pBrushData, SurfaceHandle_t surfID, float overbright,
  1588. CMeshBuilder &builder )
  1589. {
  1590. SurfaceCtx_t ctx;
  1591. SurfSetupSurfaceContext( ctx, surfID );
  1592. byte flatColor[4] = { 255, 255, 255, 255 };
  1593. Vector tVect;
  1594. bool negate = false;
  1595. if ( MSurf_Flags( surfID ) & SURFDRAW_TANGENTSPACE )
  1596. {
  1597. negate = TangentSpaceSurfaceSetup( surfID, tVect );
  1598. }
  1599. CheckMSurfaceBaseTexture2( pBrushData, surfID );
  1600. for ( int i = 0; i < MSurf_VertCount( surfID ); i++ )
  1601. {
  1602. int vertIndex = pBrushData->vertindices[MSurf_FirstVertIndex( surfID ) + i];
  1603. // world-space vertex
  1604. Vector& vec = pBrushData->vertexes[vertIndex].position;
  1605. // output to mesh
  1606. builder.Position3fv( vec.Base() );
  1607. Vector2D uv;
  1608. SurfComputeTextureCoordinate( ctx, surfID, vec, uv );
  1609. builder.TexCoord2fv( 0, uv.Base() );
  1610. // garymct: normalized (within space of surface) lightmap texture coordinates
  1611. SurfComputeLightmapCoordinate( ctx, surfID, vec, uv );
  1612. builder.TexCoord2fv( 1, uv.Base() );
  1613. if ( MSurf_Flags( surfID ) & SURFDRAW_BUMPLIGHT )
  1614. {
  1615. // bump maps appear left to right in lightmap page memory, calculate
  1616. // the offset for the width of a single map. The pixel shader will use
  1617. // this to compute the actual texture coordinates
  1618. if ( uv.x + ctx.m_BumpSTexCoordOffset*3 > 1.00001f )
  1619. {
  1620. Assert(0);
  1621. SurfComputeLightmapCoordinate( ctx, surfID, vec, uv );
  1622. }
  1623. builder.TexCoord2f( 2, ctx.m_BumpSTexCoordOffset, 0.0f );
  1624. }
  1625. Vector& normal = pBrushData->vertnormals[ pBrushData->vertnormalindices[MSurf_FirstVertNormal( surfID ) + i] ];
  1626. builder.Normal3fv( normal.Base() );
  1627. if ( MSurf_Flags( surfID ) & SURFDRAW_TANGENTSPACE )
  1628. {
  1629. Vector tangentS, tangentT;
  1630. TangentSpaceComputeBasis( tangentS, tangentT, normal, tVect, negate );
  1631. builder.TangentS3fv( tangentS.Base() );
  1632. builder.TangentT3fv( tangentT.Base() );
  1633. }
  1634. // The amount to blend between basetexture and basetexture2 used to sit in lightmap
  1635. // alpha, so we didn't care about the vertex color or vertex alpha. But now if they're
  1636. // using it, we have to make sure the vertex has the color and alpha specified correctly
  1637. // or it will look weird.
  1638. if ( !SurfaceHasDispInfo( surfID ) &&
  1639. (MSurf_TexInfo( surfID )->texinfoFlags & TEXINFO_USING_BASETEXTURE2) )
  1640. {
  1641. static bool bWarned = false;
  1642. if ( !bWarned )
  1643. {
  1644. const char *pMaterialName = MSurf_TexInfo( surfID )->material->GetName();
  1645. bWarned = true;
  1646. Warning( "Warning: WorldTwoTextureBlend found on a non-displacement surface (material: %s). This wastes perf for no benefit.\n", pMaterialName );
  1647. }
  1648. builder.Color4ub( 255, 255, 255, 0 );
  1649. }
  1650. else
  1651. {
  1652. builder.Color3ubv( flatColor );
  1653. }
  1654. builder.AdvanceVertex();
  1655. }
  1656. }
  1657. #endif // NEWMESH
  1658. static int VertexCountForSurfaceList( const CMSurfaceSortList &list, const surfacesortgroup_t &group )
  1659. {
  1660. int vertexCount = 0;
  1661. MSL_FOREACH_SURFACE_IN_GROUP_BEGIN(list, group, surfID)
  1662. vertexCount += MSurf_VertCount(surfID);
  1663. MSL_FOREACH_SURFACE_IN_GROUP_END();
  1664. return vertexCount;
  1665. }
  1666. //-----------------------------------------------------------------------------
  1667. // Builds a static mesh from a list of all surfaces with the same material
  1668. //-----------------------------------------------------------------------------
  1669. struct meshlist_t
  1670. {
  1671. #ifdef NEWMESH
  1672. IVertexBuffer *pVertexBuffer;
  1673. #else
  1674. IMesh *pMesh;
  1675. #endif
  1676. IMaterial *pMaterial;
  1677. int vertCount;
  1678. VertexFormat_t vertexFormat;
  1679. };
  1680. static CUtlVector<meshlist_t> g_Meshes;
  1681. ConVar mat_max_worldmesh_vertices("mat_max_worldmesh_vertices", "65536");
  1682. static VertexFormat_t GetUncompressedFormat( const IMaterial * pMaterial )
  1683. {
  1684. // FIXME: IMaterial::GetVertexFormat() should do this stripping (add a separate 'SupportsCompression' accessor)
  1685. return ( pMaterial->GetVertexFormat() & ~VERTEX_FORMAT_COMPRESSED );
  1686. }
  1687. int FindOrAddMesh( IMaterial *pMaterial, int vertexCount )
  1688. {
  1689. VertexFormat_t format = GetUncompressedFormat( pMaterial );
  1690. CMatRenderContextPtr pRenderContext( materials );
  1691. int nMaxVertices = pRenderContext->GetMaxVerticesToRender( pMaterial );
  1692. int worldLimit = mat_max_worldmesh_vertices.GetInt();
  1693. worldLimit = max(worldLimit,1024);
  1694. if ( nMaxVertices > worldLimit )
  1695. {
  1696. nMaxVertices = mat_max_worldmesh_vertices.GetInt();
  1697. }
  1698. for ( int i = 0; i < g_Meshes.Count(); i++ )
  1699. {
  1700. if ( g_Meshes[i].vertexFormat != format )
  1701. continue;
  1702. if ( g_Meshes[i].vertCount + vertexCount > nMaxVertices )
  1703. continue;
  1704. g_Meshes[i].vertCount += vertexCount;
  1705. return i;
  1706. }
  1707. int index = g_Meshes.AddToTail();
  1708. g_Meshes[index].vertCount = vertexCount;
  1709. g_Meshes[index].vertexFormat = format;
  1710. g_Meshes[index].pMaterial = pMaterial;
  1711. return index;
  1712. }
  1713. void SetTexInfoBaseTexture2Flags()
  1714. {
  1715. for ( int i=0; i < host_state.worldbrush->numtexinfo; i++ )
  1716. {
  1717. host_state.worldbrush->texinfo[i].texinfoFlags &= ~TEXINFO_USING_BASETEXTURE2;
  1718. }
  1719. for ( int i=0; i < host_state.worldbrush->numtexinfo; i++ )
  1720. {
  1721. mtexinfo_t *pTexInfo = &host_state.worldbrush->texinfo[i];
  1722. IMaterial *pMaterial = pTexInfo->material;
  1723. if ( !pMaterial )
  1724. continue;
  1725. IMaterialVar **pParms = pMaterial->GetShaderParams();
  1726. int nParms = pMaterial->ShaderParamCount();
  1727. for ( int j=0; j < nParms; j++ )
  1728. {
  1729. if ( !pParms[j]->IsDefined() )
  1730. continue;
  1731. if ( Q_stricmp( pParms[j]->GetName(), "$basetexture2" ) == 0 )
  1732. {
  1733. pTexInfo->texinfoFlags |= TEXINFO_USING_BASETEXTURE2;
  1734. break;
  1735. }
  1736. }
  1737. }
  1738. }
  1739. //-----------------------------------------------------------------------------
  1740. // Determines vertex formats for all the world geometry
  1741. //-----------------------------------------------------------------------------
  1742. VertexFormat_t ComputeWorldStaticMeshVertexFormat( const IMaterial * pMaterial )
  1743. {
  1744. VertexFormat_t vertexFormat = GetUncompressedFormat( pMaterial );
  1745. // FIXME: set VERTEX_FORMAT_COMPRESSED if there are no artifacts and if it saves enough memory (use 'mem_dumpvballocs')
  1746. // vertexFormat |= VERTEX_FORMAT_COMPRESSED;
  1747. // FIXME: check for and strip unused vertex elements (TANGENT_S/T?)
  1748. return vertexFormat;
  1749. }
  1750. //-----------------------------------------------------------------------------
  1751. // Builds static meshes for all the world geometry
  1752. //-----------------------------------------------------------------------------
  1753. void WorldStaticMeshCreate( void )
  1754. {
  1755. r_framecount = 1;
  1756. WorldStaticMeshDestroy();
  1757. g_Meshes.RemoveAll();
  1758. SetTexInfoBaseTexture2Flags();
  1759. int nSortIDs = materials->GetNumSortIDs();
  1760. if ( nSortIDs == 0 )
  1761. {
  1762. // this is probably a bug in alt-tab. It's calling this as a restore function
  1763. // but the lightmaps haven't been allocated yet
  1764. Assert(0);
  1765. return;
  1766. }
  1767. // Setup sortbins for flashlight rendering
  1768. // FIXME!!!! Could have less bins since we don't care about the lightmap
  1769. // for projective light rendering purposes.
  1770. // Not entirely true since we need the correct lightmap page for WorldVertexTransition materials.
  1771. g_pShadowMgr->SetNumWorldMaterialBuckets( nSortIDs );
  1772. Assert( !g_WorldStaticMeshes.Count() );
  1773. g_WorldStaticMeshes.SetCount( nSortIDs );
  1774. memset( g_WorldStaticMeshes.Base(), 0, sizeof(g_WorldStaticMeshes[0]) * g_WorldStaticMeshes.Count() );
  1775. CMSurfaceSortList matSortArray;
  1776. matSortArray.Init( nSortIDs, 512 );
  1777. int *sortIndex = (int *)_alloca( sizeof(int) * g_WorldStaticMeshes.Count() );
  1778. bool bTools = CommandLine()->CheckParm( "-tools" ) != NULL;
  1779. int i;
  1780. // sort the surfaces into the sort arrays
  1781. for( int surfaceIndex = 0; surfaceIndex < host_state.worldbrush->numsurfaces; surfaceIndex++ )
  1782. {
  1783. SurfaceHandle_t surfID = SurfaceHandleFromIndex( surfaceIndex );
  1784. // set these flags here as they are determined by material data
  1785. MSurf_Flags( surfID ) &= ~(SURFDRAW_TANGENTSPACE);
  1786. // do we need to compute tangent space here?
  1787. if ( bTools || ( MSurf_TexInfo( surfID )->material->GetVertexFormat() & VERTEX_TANGENT_SPACE ) )
  1788. {
  1789. MSurf_Flags( surfID ) |= SURFDRAW_TANGENTSPACE;
  1790. }
  1791. // don't create vertex buffers for nodraw faces, water faces, or faces with dynamic data
  1792. // if ( (MSurf_Flags( surfID ) & (SURFDRAW_NODRAW|SURFDRAW_WATERSURFACE|SURFDRAW_DYNAMIC))
  1793. // || SurfaceHasDispInfo( surfID ) )
  1794. if( SurfaceHasDispInfo( surfID ) )
  1795. {
  1796. MSurf_VertBufferIndex( surfID ) = 0xFFFF;
  1797. continue;
  1798. }
  1799. // attach to head of list
  1800. matSortArray.AddSurfaceToTail( surfID, 0, MSurf_MaterialSortID( surfID ) );
  1801. }
  1802. // iterate the arrays and create buffers
  1803. for ( i = 0; i < g_WorldStaticMeshes.Count(); i++ )
  1804. {
  1805. const surfacesortgroup_t &group = matSortArray.GetGroupForSortID(0,i);
  1806. int vertexCount = VertexCountForSurfaceList( matSortArray, group );
  1807. SurfaceHandle_t surfID = matSortArray.GetSurfaceAtHead( group );
  1808. g_WorldStaticMeshes[i] = NULL;
  1809. sortIndex[i] = surfID ? FindOrAddMesh( MSurf_TexInfo( surfID )->material, vertexCount ) : -1;
  1810. }
  1811. CMatRenderContextPtr pRenderContext( materials );
  1812. PIXEVENT( pRenderContext, "WorldStaticMeshCreate" );
  1813. #ifdef NEWMESH
  1814. for ( i = 0; i < g_Meshes.Count(); i++ )
  1815. {
  1816. Assert( g_Meshes[i].vertCount > 0 );
  1817. Assert( g_Meshes[i].pMaterial );
  1818. g_Meshes[i].pVertexBuffer = pRenderContext->CreateStaticVertexBuffer( GetUncompressedFormat( g_Meshes[i].pMaterial ), g_Meshes[i].vertCount, TEXTURE_GROUP_STATIC_VERTEX_BUFFER_WORLD );
  1819. int vertBufferIndex = 0;
  1820. // NOTE: Index count is zero because this will be a static vertex buffer!!!
  1821. CVertexBufferBuilder vertexBufferBuilder;
  1822. vertexBufferBuilder.Begin( g_Meshes[i].pVertexBuffer, g_Meshes[i].vertCount );
  1823. for ( int j = 0; j < g_WorldStaticMeshes.Count(); j++ )
  1824. {
  1825. int meshId = sortIndex[j];
  1826. if ( meshId == i )
  1827. {
  1828. g_WorldStaticMeshes[j] = g_Meshes[i].pVertexBuffer;
  1829. const surfacesortgroup_t &group = matSortArray.GetGroupForSortID(0,j);
  1830. MSL_FOREACH_SURFACE_IN_GROUP_BEGIN(matSortArray, group, surfID);
  1831. MSurf_VertBufferIndex( surfID ) = vertBufferIndex;
  1832. BuildMSurfaceVertexArrays( host_state.worldbrush, surfID, OVERBRIGHT, vertexBufferBuilder );
  1833. vertBufferIndex += MSurf_VertCount( surfID );
  1834. MSL_FOREACH_SURFACE_IN_GROUP_END();
  1835. }
  1836. }
  1837. vertexBufferBuilder.End();
  1838. Assert(vertBufferIndex == g_Meshes[i].vertCount);
  1839. }
  1840. #else
  1841. for ( i = 0; i < g_Meshes.Count(); i++ )
  1842. {
  1843. Assert( g_Meshes[i].vertCount > 0 );
  1844. if ( g_VBAllocTracker )
  1845. g_VBAllocTracker->TrackMeshAllocations( "WorldStaticMeshCreate" );
  1846. VertexFormat_t vertexFormat = ComputeWorldStaticMeshVertexFormat( g_Meshes[i].pMaterial );
  1847. g_Meshes[i].pMesh = pRenderContext->CreateStaticMesh( vertexFormat, TEXTURE_GROUP_STATIC_VERTEX_BUFFER_WORLD, g_Meshes[i].pMaterial );
  1848. int vertBufferIndex = 0;
  1849. // NOTE: Index count is zero because this will be a static vertex buffer!!!
  1850. CMeshBuilder meshBuilder;
  1851. meshBuilder.Begin( g_Meshes[i].pMesh, MATERIAL_TRIANGLES, g_Meshes[i].vertCount, 0 );
  1852. for ( int j = 0; j < g_WorldStaticMeshes.Count(); j++ )
  1853. {
  1854. int meshId = sortIndex[j];
  1855. if ( meshId == i )
  1856. {
  1857. g_WorldStaticMeshes[j] = g_Meshes[i].pMesh;
  1858. const surfacesortgroup_t &group = matSortArray.GetGroupForSortID(0,j);
  1859. MSL_FOREACH_SURFACE_IN_GROUP_BEGIN(matSortArray, group, surfID);
  1860. MSurf_VertBufferIndex( surfID ) = vertBufferIndex;
  1861. BuildMSurfaceVertexArrays( host_state.worldbrush, surfID, OVERBRIGHT, meshBuilder );
  1862. vertBufferIndex += MSurf_VertCount( surfID );
  1863. MSL_FOREACH_SURFACE_IN_GROUP_END();
  1864. }
  1865. }
  1866. meshBuilder.End();
  1867. Assert(vertBufferIndex == g_Meshes[i].vertCount);
  1868. if ( g_VBAllocTracker )
  1869. g_VBAllocTracker->TrackMeshAllocations( NULL );
  1870. }
  1871. #endif
  1872. //Msg("Total %d meshes, %d before\n", g_Meshes.Count(), g_WorldStaticMeshes.Count() );
  1873. }
  1874. void WorldStaticMeshDestroy( void )
  1875. {
  1876. CMatRenderContextPtr pRenderContext( materials );
  1877. // Blat out the static meshes associated with each material
  1878. for ( int i = 0; i < g_Meshes.Count(); i++ )
  1879. {
  1880. #ifdef NEWMESH
  1881. pRenderContext->DestroyVertexBuffer( g_Meshes[i].pVertexBuffer );
  1882. #else
  1883. pRenderContext->DestroyStaticMesh( g_Meshes[i].pMesh );
  1884. #endif
  1885. }
  1886. g_WorldStaticMeshes.Purge();
  1887. g_Meshes.RemoveAll();
  1888. }
  1889. //-----------------------------------------------------------------------------
  1890. // Compute texture and lightmap coordinates
  1891. //-----------------------------------------------------------------------------
  1892. void SurfComputeTextureCoordinate( SurfaceCtx_t const& ctx, SurfaceHandle_t surfID,
  1893. Vector const& vec, Vector2D& uv )
  1894. {
  1895. mtexinfo_t* pTexInfo = MSurf_TexInfo( surfID );
  1896. // base texture coordinate
  1897. uv.x = DotProduct (vec, pTexInfo->textureVecsTexelsPerWorldUnits[0].AsVector3D()) +
  1898. pTexInfo->textureVecsTexelsPerWorldUnits[0][3];
  1899. uv.x /= pTexInfo->material->GetMappingWidth();
  1900. uv.y = DotProduct (vec, pTexInfo->textureVecsTexelsPerWorldUnits[1].AsVector3D()) +
  1901. pTexInfo->textureVecsTexelsPerWorldUnits[1][3];
  1902. uv.y /= pTexInfo->material->GetMappingHeight();
  1903. }
  1904. #if _DEBUG
  1905. void CheckTexCoord( float coord )
  1906. {
  1907. Assert(coord <= 1.0f );
  1908. }
  1909. #endif
  1910. void SurfComputeLightmapCoordinate( SurfaceCtx_t const& ctx, SurfaceHandle_t surfID,
  1911. Vector const& vec, Vector2D& uv )
  1912. {
  1913. if ( (MSurf_Flags( surfID ) & SURFDRAW_NOLIGHT) )
  1914. {
  1915. uv.x = uv.y = 0.5f;
  1916. }
  1917. else if ( MSurf_LightmapExtents( surfID )[0] == 0 )
  1918. {
  1919. uv = (0.5f * ctx.m_Scale + ctx.m_Offset);
  1920. }
  1921. else
  1922. {
  1923. mtexinfo_t* pTexInfo = MSurf_TexInfo( surfID );
  1924. uv.x = DotProduct (vec, pTexInfo->lightmapVecsLuxelsPerWorldUnits[0].AsVector3D()) +
  1925. pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][3];
  1926. uv.x -= MSurf_LightmapMins( surfID )[0];
  1927. uv.x += 0.5f;
  1928. uv.y = DotProduct (vec, pTexInfo->lightmapVecsLuxelsPerWorldUnits[1].AsVector3D()) +
  1929. pTexInfo->lightmapVecsLuxelsPerWorldUnits[1][3];
  1930. uv.y -= MSurf_LightmapMins( surfID )[1];
  1931. uv.y += 0.5f;
  1932. uv *= ctx.m_Scale;
  1933. uv += ctx.m_Offset;
  1934. assert( uv.IsValid() );
  1935. }
  1936. #if _DEBUG
  1937. // This was here for check against displacements and they actually get calculated later correctly.
  1938. // CheckTexCoord( uv.x );
  1939. // CheckTexCoord( uv.y );
  1940. #endif
  1941. uv.x = clamp(uv.x, 0.0f, 1.0f);
  1942. uv.y = clamp(uv.y, 0.0f, 1.0f);
  1943. }
  1944. //-----------------------------------------------------------------------------
  1945. // Compute a context necessary for creating vertex data
  1946. //-----------------------------------------------------------------------------
  1947. void SurfSetupSurfaceContext( SurfaceCtx_t& ctx, SurfaceHandle_t surfID )
  1948. {
  1949. materials->GetLightmapPageSize(
  1950. SortInfoToLightmapPage( MSurf_MaterialSortID( surfID ) ),
  1951. &ctx.m_LightmapPageSize[0], &ctx.m_LightmapPageSize[1] );
  1952. ctx.m_LightmapSize[0] = ( MSurf_LightmapExtents( surfID )[0] ) + 1;
  1953. ctx.m_LightmapSize[1] = ( MSurf_LightmapExtents( surfID )[1] ) + 1;
  1954. ctx.m_Scale.x = 1.0f / ( float )ctx.m_LightmapPageSize[0];
  1955. ctx.m_Scale.y = 1.0f / ( float )ctx.m_LightmapPageSize[1];
  1956. ctx.m_Offset.x = ( float )MSurf_OffsetIntoLightmapPage( surfID )[0] * ctx.m_Scale.x;
  1957. ctx.m_Offset.y = ( float )MSurf_OffsetIntoLightmapPage( surfID )[1] * ctx.m_Scale.y;
  1958. if ( ctx.m_LightmapPageSize[0] != 0.0f )
  1959. {
  1960. ctx.m_BumpSTexCoordOffset = ( float )ctx.m_LightmapSize[0] / ( float )ctx.m_LightmapPageSize[0];
  1961. }
  1962. else
  1963. {
  1964. ctx.m_BumpSTexCoordOffset = 0.0f;
  1965. }
  1966. }
  1967. #endif // SWDS