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.

2025 lines
69 KiB

  1. //===== Copyright 1996-2005, 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 "modelloader.h"
  17. #include "staticpropmgr.h"
  18. #include "gl_model_private.h"
  19. #include "view.h"
  20. #include "gl_matsysiface.h"
  21. #include "gl_cvars.h"
  22. #include "gl_lightmap.h"
  23. #include "lightcache.h"
  24. #include "vstdlib/random.h"
  25. #include "tier0/icommandline.h"
  26. #include "draw.h"
  27. #include "decal_private.h"
  28. #include "l_studio.h"
  29. #include "keyvalues.h"
  30. #include "materialsystem/imaterial.h"
  31. #include "gl_shader.h"
  32. #include "ivideomode.h"
  33. #include "cdll_engine_int.h"
  34. #include "utldict.h"
  35. #include "filesystem.h"
  36. #include "host_saverestore.h"
  37. #include "server.h"
  38. #include "game/client/iclientrendertargets.h"
  39. #include "tier2/tier2.h"
  40. #include "videocfg/videocfg.h"
  41. #include "LoadScreenUpdate.h"
  42. #include "cl_main.h"
  43. #include <vgui/IScheme.h>
  44. #include <vgui_controls/Controls.h>
  45. #include "GameEventManager.h"
  46. #if defined( _X360 )
  47. #include "xbox/xbox_launch.h"
  48. #endif
  49. extern IFileSystem *g_pFileSystem;
  50. #ifndef DEDICATED
  51. #include "iregistry.h"
  52. #endif
  53. #include "igame.h"
  54. #include "toolframework/itoolframework.h"
  55. // memdbgon must be the last include file in a .cpp file!!!
  56. #include "tier0/memdbgon.h"
  57. // Start the frame count at one so stuff gets updated the first frame
  58. int r_framecount = 1; // used for dlight + lightstyle push checking
  59. int d_lightstylevalue[256];
  60. int d_lightstylenumframes[256];
  61. const MaterialSystem_Config_t *g_pMaterialSystemConfig;
  62. static CSysModule *g_MaterialsDLL = NULL;
  63. bool g_LostVideoMemory = false;
  64. IMaterial* g_materialEmpty; // purple checkerboard for missing textures
  65. void ReleaseMaterialSystemObjects( int nChangeFlags );
  66. void RestoreMaterialSystemObjects( int nChangeFlags );
  67. static ConVar mat_shadowstate( "mat_shadowstate", "1" );
  68. static ConVar mat_maxframelatency( "mat_maxframelatency", "1" );
  69. ConVar mat_debugalttab( "mat_debugalttab", "0", FCVAR_CHEAT );
  70. // Static pointers to renderable textures
  71. static CTextureReference g_PowerOfTwoFBTexture;
  72. static CTextureReference g_WaterReflectionTexture;
  73. static CTextureReference g_WaterRefractionTexture;
  74. static CTextureReference g_CameraTexture;
  75. static CTextureReference g_BuildCubemaps16BitTexture;
  76. static CTextureReference g_QuarterSizedFBTexture0;
  77. static CTextureReference g_QuarterSizedFBTexture1;
  78. static CTextureReference g_QuarterSizedFBTexture2;
  79. static CTextureReference g_QuarterSizedFBTexture3;
  80. static CTextureReference g_TeenyFBTexture0;
  81. static CTextureReference g_TeenyFBTexture1;
  82. static CTextureReference g_TeenyFBTexture2;
  83. #ifdef _PS3
  84. static CTextureReference g_FullFrameRawBufferAliasPS3_BackBuffer;
  85. static CTextureReference g_FullFrameRawBufferAliasPS3_DepthBuffer;
  86. #endif
  87. static CTextureReference g_FullFrameFBTexture0;
  88. static CTextureReference g_FullFrameFBTexture1;
  89. static CTextureReference g_FullFrameFBTexture2;
  90. static CTextureReference g_FullFrameDepth;
  91. #if defined( _X360 )
  92. static CTextureReference g_RtGlowTexture360;
  93. #endif
  94. // each sort ID's mesh for the depth fill render
  95. CUtlVector<IMesh *> g_DepthMeshForSortID;
  96. // Each surface's first vertex index in the depth fill VB
  97. CUtlVector<uint16> g_DepthFillVBFirstVertexForSurface;
  98. void WorldStaticMeshCreate( void );
  99. void WorldStaticMeshDestroy( void );
  100. int GetScreenAspectMode( int width, int height );
  101. ConVar r_norefresh( "r_norefresh","0");
  102. ConVar r_decals( "r_decals", "2048" );
  103. ConVar r_lightmap( "r_lightmap", "-1", FCVAR_CHEAT | FCVAR_MATERIAL_SYSTEM_THREAD );
  104. ConVar r_lightstyle( "r_lightstyle","-1", FCVAR_CHEAT | FCVAR_MATERIAL_SYSTEM_THREAD );
  105. ConVar r_dynamic( "r_dynamic","1", FCVAR_RELEASE );
  106. ConVar mat_norendering( "mat_norendering", "0", FCVAR_CHEAT );
  107. ConVar mat_wireframe( "mat_wireframe", "0", FCVAR_CHEAT );
  108. ConVar mat_luxels( "mat_luxels", "0", FCVAR_CHEAT );
  109. ConVar mat_normals( "mat_normals", "0", FCVAR_CHEAT );
  110. ConVar mat_bumpbasis( "mat_bumpbasis", "0", FCVAR_CHEAT );
  111. ConVar mat_envmapsize( "mat_envmapsize", "128" );
  112. ConVar mat_envmaptgasize( "mat_envmaptgasize", "32.0" );
  113. ConVar mat_levelflush( "mat_levelflush", "1" );
  114. ConVar mat_fastspecular( "mat_fastspecular", "1", 0, "Enable/Disable specularity for visual testing. Will not reload materials and will not affect perf." );
  115. ConVar mat_fullbright( "mat_fullbright","0", FCVAR_CHEAT );
  116. static ConVar mat_monitorgamma( "mat_monitorgamma", "2.2", FCVAR_ARCHIVE | FCVAR_ARCHIVE_GAMECONSOLE, "monitor gamma (typically 2.2 for CRT and 1.7 for LCD)", true, 1.6f, true, 2.6f );
  117. static ConVar mat_monitorgamma_tv_range_min( "mat_monitorgamma_tv_range_min", "16" );
  118. static ConVar mat_monitorgamma_tv_range_max( "mat_monitorgamma_tv_range_max", "235" );
  119. // 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
  120. static ConVar mat_monitorgamma_tv_exp( "mat_monitorgamma_tv_exp", "2.5", 0, "", true, 1.0f, true, 4.0f );
  121. static ConVar mat_monitorgamma_tv_enabled( "mat_monitorgamma_tv_enabled", IsGameConsole() ? "1" : "0", FCVAR_ARCHIVE | FCVAR_ARCHIVE_GAMECONSOLE, "" );
  122. ConVar r_drawbrushmodels( "r_drawbrushmodels", "1", FCVAR_CHEAT, "Render brush models. 0=Off, 1=Normal, 2=Wireframe" );
  123. ConVar r_shadowrendertotexture( "r_shadowrendertotexture", "0" );
  124. #if ( defined( CSTRIKE15 ) && defined( _PS3 ) )
  125. ConVar r_flashlightdepthtexture( "r_flashlightdepthtexture", "1" );
  126. #else
  127. ConVar r_flashlightdepthtexture( "r_flashlightdepthtexture", "1" );
  128. #endif
  129. // On non-gameconsoles mat_motion_blur_enabled now comes from video.txt/videodefaults.txt
  130. ConVar mat_motion_blur_enabled( "mat_motion_blur_enabled", IsGameConsole() ? "1" : "0" );
  131. // Note: this is only here so we can ship an update without changing materialsystem.dll.
  132. // Once we ship materialsystem.dll again, we can get rid of this and make the only one exist in materialsystem.dll.
  133. ConVar mat_depthbias_normal( "mat_depthbias_normal", "0.0f", FCVAR_CHEAT );
  134. static ITexture *CreateFullFrameDepthTexture( void );
  135. static void mat_resolveFullFrameDepth_changed( IConVar *var, const char *pOldValue, float flOldValue )
  136. {
  137. ConVar *cVar = (ConVar*)(var);
  138. int newVal = cVar->GetInt();
  139. int oldVal = atoi( pOldValue );
  140. static int oldNonZeroVal = -1;
  141. if ( newVal == oldVal )
  142. return;
  143. g_pMaterialSystem->ReloadMaterials( "particle" );
  144. }
  145. static ConVar mat_resolveFullFrameDepth( "mat_resolveFullFrameDepth", "0", FCVAR_CHEAT, "Enable depth resolve to a texture. 0=disable, 1=enable via resolve tricks if supported in hw, otherwise disable, 2=force extra depth only pass", mat_resolveFullFrameDepth_changed );
  146. static void NukeModeSwitchSaveGames( void )
  147. {
  148. if( g_pFileSystem->FileExists( "SAVE\\modeswitchsave.sav" ) )
  149. {
  150. g_pFileSystem->RemoveFile( "SAVE\\modeswitchsave.sav" );
  151. }
  152. if( g_pFileSystem->FileExists( "SAVE\\modeswitchsave.tga" ) )
  153. {
  154. g_pFileSystem->RemoveFile( "SAVE\\modeswitchsave.tga" );
  155. }
  156. }
  157. void mat_hdr_level_Callback( IConVar *var, const char *pOldString, float flOldValue )
  158. {
  159. if ( IsX360() )
  160. {
  161. // can't support, expected to be static
  162. return;
  163. }
  164. // CSGO doesn't support any values other than 2.
  165. mat_hdr_level.SetValue( clamp( mat_hdr_level.GetInt(), 2, 2 ) );
  166. // Can do any reloading that is necessary here upon change.
  167. // FIXME: should check if there is actually going to be a change here (ie. are we able to run in HDR
  168. // given the current map and hardware.
  169. #ifndef DEDICATED
  170. if ( g_pMaterialSystemHardwareConfig->GetHardwareHDRType() != HDR_TYPE_NONE &&
  171. saverestore->IsValidSave() &&
  172. modelloader->LastLoadedMapHasHDRLighting() &&
  173. sv.GetMaxClients() == 1 &&
  174. !sv.IsLevelMainMenuBackground()
  175. )
  176. {
  177. NukeModeSwitchSaveGames();
  178. Cbuf_AddText( Cbuf_GetCurrentPlayer(), "save modeswitchsave;wait;load modeswitchsave\n" );
  179. }
  180. #endif
  181. }
  182. // Convar range change to [2,2] since CS:GO does not support any other setting.
  183. ConVar mat_hdr_level( "mat_hdr_level", "2", FCVAR_DEVELOPMENTONLY,
  184. "Set to 0 for no HDR, 1 for LDR+bloom on HDR maps, and 2 for full HDR on HDR maps.",
  185. mat_hdr_level_Callback );
  186. MaterialSystem_SortInfo_t *materialSortInfoArray = 0;
  187. static bool s_bConfigLightingChanged = false;
  188. extern unsigned long GetRam();
  189. //-----------------------------------------------------------------------------
  190. // return true if lightmaps need to be redownloaded
  191. //-----------------------------------------------------------------------------
  192. bool MaterialConfigLightingChanged()
  193. {
  194. return s_bConfigLightingChanged;
  195. }
  196. void ClearMaterialConfigLightingChanged()
  197. {
  198. s_bConfigLightingChanged = false;
  199. }
  200. //-----------------------------------------------------------------------------
  201. // Reads convars from the registry
  202. //-----------------------------------------------------------------------------
  203. static void ReadMaterialSystemConfigFromRegistry( MaterialSystem_Config_t &config )
  204. {
  205. #if defined(DEDICATED) || defined(_GAMECONSOLE)
  206. return;
  207. #else
  208. // Create and Init the video config block.
  209. KeyValues *pConfigKeys = new KeyValues( "VideoConfig" );
  210. if ( !pConfigKeys )
  211. return;
  212. if ( !ReadCurrentVideoConfig( pConfigKeys ) )
  213. {
  214. pConfigKeys->deleteThis();
  215. return;
  216. }
  217. // Does gamma need to have config set here too!
  218. // Get the window sizes and (whether or not we are windowed).
  219. KeyValues *pFindKey = pConfigKeys->FindKey( "setting.defaultres" );
  220. if ( pFindKey )
  221. {
  222. config.m_VideoMode.m_Width = pFindKey->GetInt();
  223. }
  224. pFindKey = pConfigKeys->FindKey( "setting.defaultresheight" );
  225. if ( pFindKey )
  226. {
  227. config.m_VideoMode.m_Height = pFindKey->GetInt();
  228. }
  229. pFindKey = pConfigKeys->FindKey( "setting.fullscreen" );
  230. if ( pFindKey )
  231. {
  232. bool bFullscreen = pFindKey->GetBool();
  233. config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, !bFullscreen );
  234. }
  235. pFindKey = pConfigKeys->FindKey( "setting.nowindowborder" );
  236. if ( pFindKey )
  237. {
  238. bool bNoWindowBorder = pFindKey->GetBool();
  239. config.SetFlag( MATSYS_VIDCFG_FLAGS_NO_WINDOW_BORDER, bNoWindowBorder );
  240. }
  241. UpdateVideoConfigConVars( pConfigKeys );
  242. // Destroy the keys.
  243. pConfigKeys->deleteThis();
  244. #endif
  245. }
  246. //=============================================================================
  247. // FIXME! This was copied from VUI\perfwizardpanel.cpp
  248. struct RatioToAspectMode_t
  249. {
  250. int anamorphic;
  251. float aspectRatio;
  252. };
  253. RatioToAspectMode_t g_RatioToAspectModes[] =
  254. {
  255. { 0, 4.0f / 3.0f },
  256. { 1, 16.0f / 9.0f },
  257. { 2, 16.0f / 10.0f },
  258. { 2, 1.0f },
  259. };
  260. //--------------------------------------------------------------------------------------------------------------
  261. int GetScreenAspectMode( int width, int height )
  262. {
  263. float aspectRatio = (float)width / (float)height;
  264. // just find the closest ratio
  265. float closestAspectRatioDist = 99999.0f;
  266. int closestAnamorphic = 0;
  267. for (int i = 0; i < ARRAYSIZE(g_RatioToAspectModes); i++)
  268. {
  269. float dist = fabs( g_RatioToAspectModes[i].aspectRatio - aspectRatio );
  270. if (dist < closestAspectRatioDist)
  271. {
  272. closestAspectRatioDist = dist;
  273. closestAnamorphic = g_RatioToAspectModes[i].anamorphic;
  274. }
  275. }
  276. return closestAnamorphic;
  277. }
  278. //-----------------------------------------------------------------------------
  279. // Writes convars into the registry
  280. //-----------------------------------------------------------------------------
  281. static void WriteMaterialSystemConfigToRegistry( const MaterialSystem_Config_t &config )
  282. {
  283. #if defined(DEDICATED) || defined(_GAMECONSOLE)
  284. return;
  285. #else
  286. ConVarRef defaultres_restart( "defaultres_restart" );
  287. ConVarRef defaultresheight_restart( "defaultresheight_restart" );
  288. int nWidth = defaultres_restart.GetInt() != -1 ? defaultres_restart.GetInt() : config.m_VideoMode.m_Width;
  289. int nHeight = defaultresheight_restart.GetInt() != -1 ? defaultresheight_restart.GetInt() : config.m_VideoMode.m_Height;
  290. int nAspectRatioMode = GetScreenAspectMode( nWidth, nHeight );
  291. UpdateCurrentVideoConfig( config.m_VideoMode.m_Width, config.m_VideoMode.m_Height, nAspectRatioMode, !config.Windowed(), config.NoWindowBorder(), true );
  292. #endif
  293. }
  294. //-----------------------------------------------------------------------------
  295. // Override config with command line params
  296. //-----------------------------------------------------------------------------
  297. static void OverrideMaterialSystemConfigFromCommandLine( MaterialSystem_Config_t &config )
  298. {
  299. if ( IsX360() )
  300. {
  301. // these overrides cannot be supported
  302. // the console configuration is explicit
  303. return;
  304. }
  305. // Check for windowed mode command line override
  306. if ( CommandLine()->FindParm( "-sw" ) ||
  307. CommandLine()->FindParm( "-startwindowed" ) ||
  308. CommandLine()->FindParm( "-windowed" ) ||
  309. CommandLine()->FindParm( "-window" ) )
  310. {
  311. config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, true );
  312. }
  313. // Check for fullscreen override
  314. else if ( CommandLine()->FindParm( "-full" ) || CommandLine()->FindParm( "-fullscreen" ) )
  315. {
  316. config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, false );
  317. }
  318. // Get width and height
  319. if ( CommandLine()->FindParm( "-width" ) || CommandLine()->FindParm( "-w" ) )
  320. {
  321. config.m_VideoMode.m_Width = CommandLine()->ParmValue( "-width", config.m_VideoMode.m_Width );
  322. config.m_VideoMode.m_Width = CommandLine()->ParmValue( "-w", config.m_VideoMode.m_Width );
  323. if( !( CommandLine()->FindParm( "-height" ) || CommandLine()->FindParm( "-h" ) ) )
  324. {
  325. config.m_VideoMode.m_Height = ( config.m_VideoMode.m_Width * 3 ) / 4;
  326. }
  327. }
  328. if ( CommandLine()->FindParm( "-height" ) || CommandLine()->FindParm( "-h" ) )
  329. {
  330. config.m_VideoMode.m_Height = CommandLine()->ParmValue( "-height", config.m_VideoMode.m_Height );
  331. config.m_VideoMode.m_Height = CommandLine()->ParmValue( "-h", config.m_VideoMode.m_Height );
  332. }
  333. if ( CommandLine()->FindParm( "-resizing" ) )
  334. {
  335. config.SetFlag( MATSYS_VIDCFG_FLAGS_RESIZING, CommandLine()->CheckParm( "-resizing" ) ? true : false );
  336. }
  337. if ( CommandLine()->FindParm( "-mat_vsync" ) )
  338. {
  339. int vsync = CommandLine()->ParmValue( "-mat_vsync", 0 );
  340. config.SetFlag( MATSYS_VIDCFG_FLAGS_NO_WAIT_FOR_VSYNC, vsync == 0 );
  341. }
  342. if ( CommandLine()->FindParm( "-mat_antialias" ) )
  343. {
  344. config.m_nAASamples = CommandLine()->ParmValue( "-mat_antialias", config.m_nAASamples );
  345. ConVarRef mat_antialias( "mat_antialias" );
  346. mat_antialias.SetValue( config.m_nAASamples );
  347. }
  348. if ( CommandLine()->FindParm( "-mat_aaquality" ) )
  349. {
  350. config.m_nAAQuality = CommandLine()->ParmValue( "-mat_aaquality", config.m_nAAQuality );
  351. ConVarRef mat_aaquality( "mat_aaquality" );
  352. mat_aaquality.SetValue( config.m_nAAQuality );
  353. }
  354. if ( CommandLine()->FindParm( "-csm_quality_level" ) )
  355. {
  356. int nCSMQuality = CommandLine()->ParmValue( "-csm_quality_level", CSMQUALITY_VERY_LOW );
  357. config.m_nCSMQuality = (CSMQualityMode_t)clamp( nCSMQuality, CSMQUALITY_VERY_LOW, CSMQUALITY_TOTAL_MODES - 1 );
  358. // Just slam the convar because CMaterialSystem::ReadConfigFromConVars() just overrides the config anyway. ARGH.
  359. ConVarRef csm_quality_level( "csm_quality_level" );
  360. csm_quality_level.SetValue( config.m_nCSMQuality );
  361. }
  362. if ( CommandLine()->FindParm( "-mat_resolveFullFrameDepth" ) )
  363. {
  364. int resolveFullFrameDepth = CommandLine()->ParmValue( "-mat_resolveFullFrameDepth", 1 );
  365. mat_resolveFullFrameDepth.SetValue( resolveFullFrameDepth );
  366. }
  367. // safe mode
  368. if ( CommandLine()->FindParm( "-safe" ) )
  369. {
  370. config.SetFlag( MATSYS_VIDCFG_FLAGS_WINDOWED, true );
  371. config.m_VideoMode.m_Width = 640;
  372. config.m_VideoMode.m_Height = 480;
  373. config.m_VideoMode.m_RefreshRate = 0;
  374. config.m_nAASamples = 0;
  375. config.m_nAAQuality = 0;
  376. config.m_bWantTripleBuffered = false;
  377. config.m_nCSMQuality = CSMQUALITY_VERY_LOW;
  378. }
  379. }
  380. //-----------------------------------------------------------------------------
  381. // Updates the material system config
  382. //-----------------------------------------------------------------------------
  383. void OverrideMaterialSystemConfig( MaterialSystem_Config_t &config )
  384. {
  385. // enable/disable flashlight support based on mod (user can also set this explicitly)
  386. // FIXME: this is only here because dxsupport_override.cfg is currently broken
  387. ConVarRef mat_supportflashlight( "mat_supportflashlight" );
  388. if ( mat_supportflashlight.GetInt() == -1 )
  389. {
  390. const char * gameName = COM_GetModDirectory();
  391. if ( !V_stricmp( gameName, "portal" ) ||
  392. !V_stricmp( gameName, "tf" ) )
  393. {
  394. mat_supportflashlight.SetValue( false );
  395. }
  396. else
  397. {
  398. mat_supportflashlight.SetValue( true );
  399. }
  400. }
  401. config.m_bSupportFlashlight = mat_supportflashlight.GetBool();
  402. // apply the settings in the material system
  403. bool bLightmapsNeedReloading = materials->OverrideConfig( config, false );
  404. if ( bLightmapsNeedReloading )
  405. {
  406. s_bConfigLightingChanged = true;
  407. }
  408. }
  409. // auto config version to store in the registry so we can force reconfigs if needed
  410. #define AUTOCONFIG_VERSION 1
  411. //-----------------------------------------------------------------------------
  412. // Purpose: Initializes configuration
  413. //-----------------------------------------------------------------------------
  414. void InitMaterialSystemConfig( bool bInEditMode )
  415. {
  416. // get the default config for the current card as a starting point.
  417. g_pMaterialSystemConfig = &materials->GetCurrentConfigForVideoCard();
  418. if ( !g_pMaterialSystemConfig )
  419. {
  420. Sys_Error( "Could not get the material system config record!" );
  421. }
  422. if ( bInEditMode )
  423. return;
  424. MaterialSystem_Config_t config = *g_pMaterialSystemConfig;
  425. #if !defined(DEDICATED)
  426. // Capture autoconfig.
  427. if ( CommandLine()->FindParm( "-autoconfig" ) )
  428. {
  429. #ifdef _GAMECONSOLE
  430. AssertMsg( false, "VideoCFG not supported on Xbox 360." );
  431. #else
  432. ResetVideoConfigToDefaults();
  433. #endif
  434. }
  435. ReadMaterialSystemConfigFromRegistry( config );
  436. #endif
  437. OverrideMaterialSystemConfigFromCommandLine( config );
  438. OverrideMaterialSystemConfig( config );
  439. // now, set default hdr state
  440. bool bEnableHDR = ( mat_hdr_level.GetInt() >= 2 );
  441. g_pMaterialSystemHardwareConfig->SetHDREnabled( bEnableHDR );
  442. UpdateMaterialSystemConfig();
  443. }
  444. //-----------------------------------------------------------------------------
  445. // Updates the material system config
  446. //-----------------------------------------------------------------------------
  447. void UpdateMaterialSystemConfig( void )
  448. {
  449. // INFESTED_DLL - Alien Swarm doesn't want fullbright turned on when there are no lights (since it uses dynamic lights and skips vrad)
  450. static char gamedir[MAX_OSPATH];
  451. Q_FileBase( com_gamedir, gamedir, sizeof( gamedir ) );
  452. if ( host_state.worldbrush && !host_state.worldbrush->lightdata && Q_stricmp( gamedir, "infested" ) )
  453. {
  454. mat_fullbright.SetValue( 1 );
  455. }
  456. // apply the settings in the material system
  457. bool bLightmapsNeedReloading = materials->UpdateConfig( false );
  458. if ( bLightmapsNeedReloading )
  459. {
  460. s_bConfigLightingChanged = true;
  461. }
  462. }
  463. //-----------------------------------------------------------------------------
  464. // Purpose: Sets all the relevant keyvalue data to be uploaded as part of the benchmark data
  465. // Input : *dataToUpload - keyvalue set that will be uploaded
  466. //-----------------------------------------------------------------------------
  467. void GetMaterialSystemConfigForBenchmarkUpload(KeyValues *dataToUpload)
  468. {
  469. #if !defined(DEDICATED)
  470. // hardware info
  471. MaterialAdapterInfo_t driverInfo;
  472. materials->GetDisplayAdapterInfo( materials->GetCurrentAdapter(), driverInfo );
  473. dataToUpload->SetInt( "vendorID", driverInfo.m_VendorID );
  474. dataToUpload->SetInt( "deviceID", driverInfo.m_DeviceID );
  475. dataToUpload->SetInt( "ram", GetRam() );
  476. const CPUInformation& pi = GetCPUInformation();
  477. double fFrequency = pi.m_Speed / 1000000.0;
  478. dataToUpload->SetInt( "cpu_speed", (int)fFrequency );
  479. dataToUpload->SetString( "cpu", pi.m_szProcessorID );
  480. // material system settings
  481. dataToUpload->SetInt( "width", g_pMaterialSystemConfig->m_VideoMode.m_Width );
  482. dataToUpload->SetInt( "height", g_pMaterialSystemConfig->m_VideoMode.m_Height );
  483. dataToUpload->SetInt( "AASamples", g_pMaterialSystemConfig->m_nAASamples );
  484. dataToUpload->SetInt( "AAQuality", g_pMaterialSystemConfig->m_nAAQuality );
  485. dataToUpload->SetBool( "TripleBuffered", g_pMaterialSystemConfig->m_bWantTripleBuffered );
  486. dataToUpload->SetInt( "AnisoLevel", g_pMaterialSystemConfig->m_nForceAnisotropicLevel );
  487. dataToUpload->SetInt( "SkipMipLevels", g_pMaterialSystemConfig->skipMipLevels );
  488. dataToUpload->SetInt( "DXLevel", g_pMaterialSystemConfig->dxSupportLevel );
  489. dataToUpload->SetBool( "ShadowDepthTexture", g_pMaterialSystemConfig->ShadowDepthTexture() );
  490. dataToUpload->SetBool( "MotionBlur", g_pMaterialSystemConfig->MotionBlur() );
  491. dataToUpload->SetBool( "Windowed", (g_pMaterialSystemConfig->m_Flags & MATSYS_VIDCFG_FLAGS_WINDOWED) ? true : false );
  492. dataToUpload->SetBool( "NoWaitForVSync", (g_pMaterialSystemConfig->m_Flags & MATSYS_VIDCFG_FLAGS_NO_WAIT_FOR_VSYNC) ? true : false );
  493. dataToUpload->SetBool( "DisableSpecular", (g_pMaterialSystemConfig->m_Flags & MATSYS_VIDCFG_FLAGS_DISABLE_SPECULAR) ? true : false );
  494. dataToUpload->SetBool( "DisableBumpmapping", (g_pMaterialSystemConfig->m_Flags & MATSYS_VIDCFG_FLAGS_DISABLE_BUMPMAP) ? true : false );
  495. dataToUpload->SetBool( "EnableParallaxMapping", (g_pMaterialSystemConfig->m_Flags & MATSYS_VIDCFG_FLAGS_ENABLE_PARALLAX_MAPPING) ? true : false );
  496. dataToUpload->SetBool( "ZPrefill", (g_pMaterialSystemConfig->m_Flags & MATSYS_VIDCFG_FLAGS_USE_Z_PREFILL) ? 1 : 0 );
  497. dataToUpload->SetBool( "RenderToTextureShadows", r_shadowrendertotexture.GetBool() );
  498. dataToUpload->SetBool( "FlashlightDepthTexture", r_flashlightdepthtexture.GetBool() );
  499. #endif
  500. }
  501. //-----------------------------------------------------------------------------
  502. // Purpose: Dumps the specified config info to the console
  503. //-----------------------------------------------------------------------------
  504. void PrintMaterialSystemConfig( const MaterialSystem_Config_t &config )
  505. {
  506. Warning( "width: %d\n", config.m_VideoMode.m_Width );
  507. Warning( "height: %d\n", config.m_VideoMode.m_Height );
  508. Warning( "m_nForceAnisotropicLevel: %d\n", config.m_nForceAnisotropicLevel );
  509. Warning( "aasamples: %d\n", config.m_nAASamples );
  510. Warning( "aaquality: %d\n", config.m_nAAQuality );
  511. Warning( "tripleBuffered: %s\n", config.m_bWantTripleBuffered ? "true" : "false" );
  512. Warning( "skipMipLevels: %d\n", config.skipMipLevels );
  513. Warning( "dxSupportLevel: %d\n", config.dxSupportLevel );
  514. Warning( "monitorGamma: %f\n", config.m_fMonitorGamma );
  515. Warning( "MATSYS_VIDCFG_FLAGS_UNSUPPORTED: %s\n", ( config.m_Flags & MATSYS_VIDCFG_FLAGS_UNSUPPORTED ) ? "true" : "false" );
  516. Warning( "MATSYS_VIDCFG_FLAGS_WINDOWED: %s\n", ( config.m_Flags & MATSYS_VIDCFG_FLAGS_WINDOWED ) ? "true" : "false" );
  517. Warning( "MATSYS_VIDCFG_FLAGS_DISABLE_SPECULAR: %s\n", ( config.m_Flags & MATSYS_VIDCFG_FLAGS_DISABLE_SPECULAR ) ? "true" : "false" );
  518. Warning( "MATSYS_VIDCFG_FLAGS_ENABLE_PARALLAX_MAPPING: %s\n", ( config.m_Flags & MATSYS_VIDCFG_FLAGS_ENABLE_PARALLAX_MAPPING ) ? "true" : "false" );
  519. Warning( "MATSYS_VIDCFG_FLAGS_USE_Z_PREFILL: %s\n", ( config.m_Flags & MATSYS_VIDCFG_FLAGS_USE_Z_PREFILL ) ? "true" : "false" );
  520. Warning( "r_shadowrendertotexture: %s\n", r_shadowrendertotexture.GetBool() ? "true" : "false" );
  521. Warning( "motionblur: %s\n", config.m_bMotionBlur ? "true" : "false" );
  522. Warning( "shadowdepthtexture: %s\n", config.m_bShadowDepthTexture ? "true" : "false" );
  523. Warning( "CSM Quality Level: %u\n", config.m_nCSMQuality );
  524. }
  525. CON_COMMAND( mat_configcurrent, "show the current video control panel config for the material system" )
  526. {
  527. const MaterialSystem_Config_t &config = materials->GetCurrentConfigForVideoCard();
  528. PrintMaterialSystemConfig( config );
  529. }
  530. #if !defined(DEDICATED) && !defined( _X360 )
  531. CON_COMMAND( mat_setvideomode, "sets the width, height, windowed state of the material system" )
  532. {
  533. if ( args.ArgC() < 4 )
  534. return;
  535. int nWidth = Q_atoi( args[1] );
  536. int nHeight = Q_atoi( args[2] );
  537. bool bWindowed = Q_atoi( args[3] ) > 0 ? true : false;
  538. bool bNoBorder = videomode->NoWindowBorder();
  539. if ( args.ArgC() >= 5 )
  540. {
  541. bNoBorder = Q_atoi( args[4] ) > 0 ? true : false;
  542. }
  543. videomode->SetMode( nWidth, nHeight, bWindowed, bNoBorder );
  544. }
  545. #endif
  546. CON_COMMAND( mat_savechanges, "saves current video configuration to the registry" )
  547. {
  548. // if the user has got to the point where they can adjust and apply video changes, then we can clear safe mode
  549. CommandLine()->RemoveParm( "-safe" );
  550. // write out config
  551. UpdateMaterialSystemConfig();
  552. WriteMaterialSystemConfigToRegistry( *g_pMaterialSystemConfig );
  553. }
  554. #if !defined( _GAMECONSOLE ) && !defined( DEDICATED )
  555. CON_COMMAND( mat_updateconvars, "updates the video config convars" )
  556. {
  557. UpdateVideoConfigConVars();
  558. }
  559. #endif
  560. // Players have been using mat_debug to cheat in CS.
  561. bool g_bHasIssuedMatSuppressOrDebug;
  562. //-----------------------------------------------------------------------------
  563. // A console command to debug materials
  564. //-----------------------------------------------------------------------------
  565. CON_COMMAND_F( mat_debug, "Activates debugging spew for a specific material.", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY )
  566. {
  567. if ( args.ArgC() != 2 )
  568. {
  569. ConMsg ("usage: mat_debug [ <material name> ]\n");
  570. return;
  571. }
  572. materials->ToggleDebugMaterial( args[1] );
  573. g_bHasIssuedMatSuppressOrDebug = true;
  574. }
  575. // Players have been using mat_suppress to cheat
  576. //-----------------------------------------------------------------------------
  577. // A console command to suppress materials
  578. //-----------------------------------------------------------------------------
  579. CON_COMMAND_F( mat_suppress, "Suppress a material from drawing", FCVAR_CHEAT | FCVAR_DEVELOPMENTONLY )
  580. {
  581. if ( args.ArgC() != 2 )
  582. {
  583. ConMsg ("usage: mat_suppress [ <material name> ]\n");
  584. return;
  585. }
  586. materials->ToggleSuppressMaterial( args[1] );
  587. g_bHasIssuedMatSuppressOrDebug = true;
  588. }
  589. static ITexture *CreatePowerOfTwoFBTexture( void )
  590. {
  591. if ( IsX360() )
  592. return NULL;
  593. return materials->CreateNamedRenderTargetTextureEx2(
  594. "_rt_PowerOfTwoFB",
  595. 1024, 1024, RT_SIZE_DEFAULT,
  596. // Has dest alpha for vort warp effect
  597. IMAGE_FORMAT_RGBA8888,
  598. MATERIAL_RT_DEPTH_SHARED,
  599. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
  600. CREATERENDERTARGETFLAGS_HDR );
  601. }
  602. static ITexture *CreateWaterReflectionTexture( void )
  603. {
  604. int iSize = CommandLine()->ParmValue( "-reflectionTextureSize", 1024 );
  605. return materials->CreateNamedRenderTargetTextureEx2(
  606. "_rt_WaterReflection",
  607. iSize, iSize, RT_SIZE_PICMIP,
  608. materials->GetBackBufferFormat(),
  609. MATERIAL_RT_DEPTH_SHARED,
  610. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
  611. CREATERENDERTARGETFLAGS_HDR );
  612. }
  613. static ITexture *CreateWaterRefractionTexture( void )
  614. {
  615. int iSize = CommandLine()->ParmValue( "-reflectionTextureSize", 1024 );
  616. return materials->CreateNamedRenderTargetTextureEx2(
  617. "_rt_WaterRefraction",
  618. iSize, iSize, RT_SIZE_PICMIP,
  619. // This is different than reflection because it has to have alpha for fog factor.
  620. IMAGE_FORMAT_RGBA8888,
  621. MATERIAL_RT_DEPTH_SHARED,
  622. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
  623. CREATERENDERTARGETFLAGS_HDR );
  624. }
  625. static ITexture *CreateCameraTexture( void )
  626. {
  627. int iSize = CommandLine()->ParmValue( "-monitorTextureSize", 256 );
  628. return materials->CreateNamedRenderTargetTextureEx2(
  629. "_rt_Camera",
  630. iSize, iSize, RT_SIZE_DEFAULT,
  631. materials->GetBackBufferFormat(),
  632. MATERIAL_RT_DEPTH_SHARED,
  633. 0,
  634. CREATERENDERTARGETFLAGS_HDR );
  635. }
  636. static ITexture *CreateBuildCubemaps16BitTexture( void )
  637. {
  638. return materials->CreateNamedRenderTargetTextureEx2(
  639. "_rt_BuildCubemaps16bit",
  640. 0, 0,
  641. RT_SIZE_FULL_FRAME_BUFFER,
  642. IMAGE_FORMAT_RGBA16161616,
  643. MATERIAL_RT_DEPTH_SHARED );
  644. }
  645. static ITexture *CreateQuarterSizedFBTexture( int n, unsigned int iRenderTargetFlags )
  646. {
  647. char nbuf[20];
  648. sprintf(nbuf,"_rt_SmallFB%d",n);
  649. ImageFormat fmt=materials->GetBackBufferFormat();
  650. if ( g_pMaterialSystemHardwareConfig->GetHDRType() == HDR_TYPE_FLOAT )
  651. fmt = IMAGE_FORMAT_RGBA16161616F;
  652. return materials->CreateNamedRenderTargetTextureEx2(
  653. nbuf, 0, 0, RT_SIZE_HDR,
  654. fmt, MATERIAL_RT_DEPTH_SHARED,
  655. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
  656. iRenderTargetFlags );
  657. }
  658. static ITexture *CreateTeenyFBTexture( int n )
  659. {
  660. char nbuf[20];
  661. sprintf(nbuf,"_rt_TeenyFB%d",n);
  662. ImageFormat fmt = materials->GetBackBufferFormat();
  663. if ( g_pMaterialSystemHardwareConfig->GetHDRType() == HDR_TYPE_FLOAT )
  664. fmt = IMAGE_FORMAT_RGBA16161616F;
  665. return materials->CreateNamedRenderTargetTextureEx2(
  666. nbuf, 32, 32, RT_SIZE_DEFAULT,
  667. fmt, MATERIAL_RT_DEPTH_SHARED );
  668. }
  669. static ITexture *CreateFullFrameFBTexture( int textureIndex, int iExtraFlags = 0 )
  670. {
  671. char textureName[256];
  672. if ( textureIndex > 0 )
  673. {
  674. sprintf( textureName, "_rt_FullFrameFB%d", textureIndex );
  675. }
  676. else
  677. {
  678. Q_strcpy( textureName, "_rt_FullFrameFB" );
  679. }
  680. int rtFlags = iExtraFlags | CREATERENDERTARGETFLAGS_HDR;
  681. if ( IsX360() )
  682. {
  683. // just make the system memory texture only
  684. rtFlags |= CREATERENDERTARGETFLAGS_NOEDRAM;
  685. }
  686. return materials->CreateNamedRenderTargetTextureEx2(
  687. textureName,
  688. 1, 1, RT_SIZE_FULL_FRAME_BUFFER, materials->GetBackBufferFormat(),
  689. MATERIAL_RT_DEPTH_SHARED,
  690. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
  691. rtFlags );
  692. }
  693. static ITexture *CreateFullFrameDepthTexture( void )
  694. {
  695. if ( IsGameConsole() )
  696. {
  697. return materials->CreateNamedRenderTargetTextureEx2( "_rt_FullFrameDepth", 1, 1,
  698. RT_SIZE_FULL_FRAME_BUFFER, g_pMaterialSystemHardwareConfig->GetShadowDepthTextureFormat(), MATERIAL_RT_DEPTH_NONE,
  699. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_POINTSAMPLE,
  700. CREATERENDERTARGETFLAGS_NOEDRAM );
  701. }
  702. else
  703. {
  704. if ( g_pMaterialSystemHardwareConfig->SupportsResolveDepth() )
  705. {
  706. if ( IsPlatformOpenGL() )
  707. {
  708. return materials->CreateNamedRenderTargetTextureEx2( "_rt_FullFrameDepth", 1, 1,
  709. RT_SIZE_FULL_FRAME_BUFFER, IMAGE_FORMAT_D24S8, MATERIAL_RT_DEPTH_ONLY,
  710. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_POINTSAMPLE,
  711. CREATERENDERTARGETFLAGS_NOEDRAM );
  712. }
  713. else
  714. {
  715. return materials->CreateNamedRenderTargetTextureEx2( "_rt_FullFrameDepth", 1, 1,
  716. RT_SIZE_FULL_FRAME_BUFFER, IMAGE_FORMAT_INTZ, MATERIAL_RT_DEPTH_NONE,
  717. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_POINTSAMPLE,
  718. CREATERENDERTARGETFLAGS_NOEDRAM );
  719. }
  720. }
  721. else
  722. {
  723. return materials->CreateNamedRenderTargetTextureEx2( "_rt_FullFrameDepth", 1, 1,
  724. RT_SIZE_FULL_FRAME_BUFFER, IMAGE_FORMAT_R32F, MATERIAL_RT_DEPTH_SHARED,
  725. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_POINTSAMPLE,
  726. CREATERENDERTARGETFLAGS_NOEDRAM );
  727. }
  728. }
  729. return NULL;
  730. }
  731. //-----------------------------------------------------------------------------
  732. // Purpose: Create render targets which mods rely upon to render correctly
  733. //-----------------------------------------------------------------------------
  734. void InitWellKnownRenderTargets( void )
  735. {
  736. #if !defined( DEDICATED )
  737. if ( mat_debugalttab.GetBool() )
  738. {
  739. Warning( "mat_debugalttab: InitWellKnownRenderTargets\n" );
  740. }
  741. // Begin block in which all render targets should be allocated
  742. materials->BeginRenderTargetAllocation();
  743. // Create the render targets upon which mods may rely
  744. if ( IsPC() )
  745. {
  746. // Create for all mods as vgui2 uses it for 3D painting
  747. g_PowerOfTwoFBTexture.Init( CreatePowerOfTwoFBTexture() );
  748. }
  749. // Create these for all mods because the engine references them
  750. if ( IsPC() && g_pMaterialSystemHardwareConfig->GetHDRType() == HDR_TYPE_FLOAT )
  751. {
  752. // Used for building HDR Cubemaps
  753. g_BuildCubemaps16BitTexture.Init( CreateBuildCubemaps16BitTexture() );
  754. }
  755. // Used in Bloom effects
  756. g_QuarterSizedFBTexture0.Init( CreateQuarterSizedFBTexture( 0, 0 ) );
  757. /*
  758. // Commenting out this texture aliasing because it breaks the paint screenspace effect in Portal 2.
  759. if( IsX360() )
  760. 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
  761. else
  762. g_QuarterSizedFBTexture1.Init( CreateQuarterSizedFBTexture( 1, 0 ) );
  763. */
  764. g_QuarterSizedFBTexture1.Init( CreateQuarterSizedFBTexture( 1, 0 ) );
  765. #if ! ( defined( LEFT4DEAD ) || defined( CSTRIKE15 ) )
  766. g_QuarterSizedFBTexture2.Init( CreateQuarterSizedFBTexture( 2, 0 ) );
  767. g_QuarterSizedFBTexture3.Init( CreateQuarterSizedFBTexture( 3, 0 ) );
  768. #endif
  769. #if defined( _X360 )
  770. g_RtGlowTexture360.InitRenderTargetTexture( 8, 8, RT_SIZE_NO_CHANGE, IMAGE_FORMAT_ARGB8888, MATERIAL_RT_DEPTH_NONE, false, "_rt_Glows360" );
  771. // NOTE: The 360 requires render targets generated with 1xMSAA to be 80x16 aligned in EDRAM
  772. // Using 1120x624 since this seems to be the largest surface we can fit in EDRAM next to the back buffer
  773. g_RtGlowTexture360.InitRenderTargetSurface( 1120, 624, IMAGE_FORMAT_ARGB8888, false );
  774. #endif
  775. if ( IsPC() )
  776. {
  777. g_TeenyFBTexture0.Init( CreateTeenyFBTexture( 0 ) );
  778. g_TeenyFBTexture1.Init( CreateTeenyFBTexture( 1 ) );
  779. g_TeenyFBTexture2.Init( CreateTeenyFBTexture( 2 ) );
  780. }
  781. #ifdef _PS3
  782. g_FullFrameRawBufferAliasPS3_BackBuffer.Init(
  783. materials->CreateNamedRenderTargetTextureEx2(
  784. "^PS3^BACKBUFFER",
  785. 1, 1, RT_SIZE_FULL_FRAME_BUFFER,
  786. materials->GetBackBufferFormat(),
  787. MATERIAL_RT_DEPTH_SHARED,
  788. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT,
  789. CREATERENDERTARGETFLAGS_HDR ) );
  790. g_FullFrameRawBufferAliasPS3_DepthBuffer.Init(
  791. materials->CreateNamedRenderTargetTextureEx2(
  792. "^PS3^DEPTHBUFFER",
  793. 1, 1, RT_SIZE_FULL_FRAME_BUFFER,
  794. g_pMaterialSystemHardwareConfig->GetShadowDepthTextureFormat(),
  795. MATERIAL_RT_DEPTH_NONE,
  796. TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_POINTSAMPLE,
  797. CREATERENDERTARGETFLAGS_NOEDRAM ) );
  798. #endif
  799. g_FullFrameFBTexture0.Init( CreateFullFrameFBTexture( 0 ) );
  800. // Since the tools may not draw the world, we don't want depth buffer effects
  801. if ( toolframework->InToolMode() )
  802. {
  803. mat_resolveFullFrameDepth.SetValue( 0 );
  804. }
  805. #if defined( LEFT4DEAD )
  806. if ( IsPC() )
  807. {
  808. g_FullFrameFBTexture1.Init( CreateFullFrameFBTexture( 1 ) ); // save some memory on the 360
  809. }
  810. #else
  811. g_FullFrameFBTexture1.Init( CreateFullFrameFBTexture( 1, CREATERENDERTARGETFLAGS_TEMP ) );
  812. #endif
  813. #ifndef _PS3
  814. g_FullFrameDepth.Init( CreateFullFrameDepthTexture() );
  815. #endif
  816. // Allow the client to init their own mod-specific render targets
  817. if ( g_pClientRenderTargets )
  818. {
  819. g_pClientRenderTargets->InitClientRenderTargets( materials, g_pMaterialSystemHardwareConfig );
  820. }
  821. else
  822. {
  823. // If this mod doesn't define the interface, fallback to initializing the standard render textures
  824. // NOTE: these should match up with the 'Get' functions in cl_dll/rendertexture.h/cpp
  825. g_WaterReflectionTexture.Init( CreateWaterReflectionTexture() );
  826. g_WaterRefractionTexture.Init( CreateWaterRefractionTexture() );
  827. g_CameraTexture.Init( CreateCameraTexture() );
  828. }
  829. // End block in which all render targets should be allocated (kicking off an Alt-Tab type behavior)
  830. materials->EndRenderTargetAllocation();
  831. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  832. pRenderContext->SetNonInteractiveTempFullscreenBuffer( g_FullFrameFBTexture0, MATERIAL_NON_INTERACTIVE_MODE_LEVEL_LOAD );
  833. #endif
  834. }
  835. //-----------------------------------------------------------------------------
  836. // Purpose: Shut down the render targets which mods rely upon to render correctly
  837. //-----------------------------------------------------------------------------
  838. void ShutdownWellKnownRenderTargets( void )
  839. {
  840. #if !defined( DEDICATED )
  841. if ( IsX360() )
  842. {
  843. // cannot allowing RT's to reconstruct, causes other fatal problems
  844. // many other 360 systems have been coded with this expected constraint
  845. Assert( 0 );
  846. return;
  847. }
  848. if ( IsPC() && mat_debugalttab.GetBool() )
  849. {
  850. Warning( "mat_debugalttab: ShutdownWellKnownRenderTargets\n" );
  851. }
  852. g_PowerOfTwoFBTexture.Shutdown();
  853. g_BuildCubemaps16BitTexture.Shutdown();
  854. g_QuarterSizedFBTexture0.Shutdown();
  855. if( IsX360() )
  856. materials->RemoveTextureAlias( "_rt_SmallFB1" );
  857. else
  858. g_QuarterSizedFBTexture1.Shutdown();
  859. g_QuarterSizedFBTexture2.Shutdown();
  860. g_QuarterSizedFBTexture3.Shutdown();
  861. #if defined( _X360 )
  862. g_RtGlowTexture360.Shutdown();
  863. #endif
  864. g_TeenyFBTexture0.Shutdown();
  865. g_TeenyFBTexture1.Shutdown();
  866. g_TeenyFBTexture2.Shutdown();
  867. g_FullFrameFBTexture0.Shutdown();
  868. g_FullFrameFBTexture1.Shutdown();
  869. if ( IsX360() )
  870. {
  871. g_FullFrameFBTexture2.Shutdown();
  872. }
  873. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  874. pRenderContext->SetNonInteractiveTempFullscreenBuffer( NULL, MATERIAL_NON_INTERACTIVE_MODE_LEVEL_LOAD );
  875. g_FullFrameDepth.Shutdown();
  876. // Shutdown client render targets
  877. if ( g_pClientRenderTargets )
  878. {
  879. g_pClientRenderTargets->ShutdownClientRenderTargets();
  880. }
  881. else
  882. {
  883. g_WaterReflectionTexture.Shutdown();
  884. g_WaterRefractionTexture.Shutdown();
  885. g_CameraTexture.Shutdown();
  886. }
  887. #endif
  888. }
  889. //-----------------------------------------------------------------------------
  890. // Purpose: Make the debug system materials
  891. //-----------------------------------------------------------------------------
  892. static void InitDebugMaterials( void )
  893. {
  894. if ( IsPC() && mat_debugalttab.GetBool() )
  895. {
  896. Warning( "mat_debugalttab: InitDebugMaterials\n" );
  897. }
  898. g_materialEmpty = GL_LoadMaterial( "debug/debugempty", TEXTURE_GROUP_OTHER );
  899. #ifndef DEDICATED
  900. g_materialWireframe = GL_LoadMaterial( "debug/debugwireframe", TEXTURE_GROUP_OTHER );
  901. g_materialTranslucentSingleColor = GL_LoadMaterial( "debug/debugtranslucentsinglecolor", TEXTURE_GROUP_OTHER );
  902. g_materialTranslucentVertexColor = GL_LoadMaterial( "debug/debugtranslucentvertexcolor", TEXTURE_GROUP_OTHER );
  903. g_materialWorldWireframe = GL_LoadMaterial( "debug/debugworldwireframe", TEXTURE_GROUP_OTHER );
  904. g_materialWorldWireframeZBuffer = GL_LoadMaterial( "debug/debugworldwireframezbuffer", TEXTURE_GROUP_OTHER );
  905. g_materialWorldWireframeGreen = GL_LoadMaterial( "debug/debugworldwireframegreen", TEXTURE_GROUP_OTHER );
  906. g_materialBrushWireframe = GL_LoadMaterial( "debug/debugbrushwireframe", TEXTURE_GROUP_OTHER );
  907. g_materialDecalWireframe = GL_LoadMaterial( "debug/debugdecalwireframe", TEXTURE_GROUP_OTHER );
  908. g_materialDebugLightmap = GL_LoadMaterial( "debug/debuglightmap", TEXTURE_GROUP_OTHER );
  909. g_materialDebugLightmapZBuffer = GL_LoadMaterial( "debug/debuglightmapzbuffer", TEXTURE_GROUP_OTHER );
  910. g_materialDebugLuxels = GL_LoadMaterial( "debug/debugluxels", TEXTURE_GROUP_OTHER );
  911. g_materialLeafVisWireframe = GL_LoadMaterial( "debug/debugleafviswireframe", TEXTURE_GROUP_OTHER );
  912. g_pMaterialWireframeVertexColor = GL_LoadMaterial( "debug/debugwireframevertexcolor", TEXTURE_GROUP_OTHER );
  913. g_pMaterialWireframeVertexColorIgnoreZ = GL_LoadMaterial( "debug/debugwireframevertexcolorignorez", TEXTURE_GROUP_OTHER );
  914. g_pMaterialLightSprite = GL_LoadMaterial( "engine/lightsprite", TEXTURE_GROUP_OTHER );
  915. g_pMaterialShadowBuild = GL_LoadMaterial( "engine/shadowbuild", TEXTURE_GROUP_OTHER);
  916. g_pMaterialMRMWireframe = GL_LoadMaterial( "debug/debugmrmwireframe", TEXTURE_GROUP_OTHER );
  917. g_pMaterialDebugFlat = GL_LoadMaterial( "debug/debugdrawflattriangles", TEXTURE_GROUP_OTHER );
  918. g_pMaterialAmbientCube = GL_LoadMaterial( "debug/debugambientcube", TEXTURE_GROUP_OTHER );
  919. g_pMaterialWriteZ = GL_LoadMaterial( "engine/writez", TEXTURE_GROUP_OTHER );
  920. // Materials for writing to shadow depth buffer
  921. KeyValues *pVMTKeyValues = new KeyValues( "DepthWrite" );
  922. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  923. pVMTKeyValues->SetInt( "$alphatest", 0 );
  924. pVMTKeyValues->SetInt( "$nocull", 0 );
  925. pVMTKeyValues->SetInt( "$color_depth", 0 );
  926. g_pMaterialDepthWrite[0][0] = g_pMaterialSystem->FindProceduralMaterial("__DepthWrite00", TEXTURE_GROUP_OTHER, pVMTKeyValues);
  927. g_pMaterialDepthWrite[0][0]->IncrementReferenceCount();
  928. pVMTKeyValues = new KeyValues( "DepthWrite" );
  929. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  930. pVMTKeyValues->SetInt( "$alphatest", 0 );
  931. pVMTKeyValues->SetInt( "$nocull", 1 );
  932. pVMTKeyValues->SetInt("$color_depth", 0);
  933. g_pMaterialDepthWrite[0][1] = g_pMaterialSystem->FindProceduralMaterial("__DepthWrite01", TEXTURE_GROUP_OTHER, pVMTKeyValues);
  934. g_pMaterialDepthWrite[0][1]->IncrementReferenceCount();
  935. pVMTKeyValues = new KeyValues( "DepthWrite" );
  936. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  937. pVMTKeyValues->SetInt( "$alphatest", 1 );
  938. pVMTKeyValues->SetInt( "$nocull", 0 );
  939. pVMTKeyValues->SetInt("$color_depth", 0);
  940. g_pMaterialDepthWrite[1][0] = g_pMaterialSystem->FindProceduralMaterial("__DepthWrite10", TEXTURE_GROUP_OTHER, pVMTKeyValues);
  941. g_pMaterialDepthWrite[1][0]->IncrementReferenceCount();
  942. pVMTKeyValues = new KeyValues( "DepthWrite" );
  943. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  944. pVMTKeyValues->SetInt( "$alphatest", 1 );
  945. pVMTKeyValues->SetInt( "$nocull", 1 );
  946. pVMTKeyValues->SetInt("$color_depth", 0);
  947. g_pMaterialDepthWrite[1][1] = g_pMaterialSystem->FindProceduralMaterial("__DepthWrite11", TEXTURE_GROUP_OTHER, pVMTKeyValues);
  948. g_pMaterialDepthWrite[1][1]->IncrementReferenceCount();
  949. pVMTKeyValues = new KeyValues( "DepthWrite" );
  950. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  951. pVMTKeyValues->SetInt( "$alphatest", 0 );
  952. pVMTKeyValues->SetInt( "$nocull", 0 );
  953. pVMTKeyValues->SetInt( "$color_depth", 1 );
  954. g_pMaterialSSAODepthWrite[ 0 ][ 0 ] = g_pMaterialSystem->FindProceduralMaterial( "__ColorDepthWrite00", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  955. g_pMaterialSSAODepthWrite[ 0 ][ 0 ]->IncrementReferenceCount();
  956. pVMTKeyValues = new KeyValues( "DepthWrite" );
  957. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  958. pVMTKeyValues->SetInt( "$alphatest", 0 );
  959. pVMTKeyValues->SetInt( "$nocull", 1 );
  960. pVMTKeyValues->SetInt( "$color_depth", 1 );
  961. g_pMaterialSSAODepthWrite[ 0 ][ 1 ] = g_pMaterialSystem->FindProceduralMaterial( "__ColorDepthWrite01", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  962. g_pMaterialSSAODepthWrite[ 0 ][ 1 ]->IncrementReferenceCount();
  963. pVMTKeyValues = new KeyValues( "DepthWrite" );
  964. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  965. pVMTKeyValues->SetInt( "$alphatest", 1 );
  966. pVMTKeyValues->SetInt( "$nocull", 0 );
  967. pVMTKeyValues->SetInt( "$color_depth", 1 );
  968. g_pMaterialSSAODepthWrite[ 1 ][ 0 ] = g_pMaterialSystem->FindProceduralMaterial( "__ColorDepthWrite10", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  969. g_pMaterialSSAODepthWrite[ 1 ][ 0 ]->IncrementReferenceCount();
  970. pVMTKeyValues = new KeyValues( "DepthWrite" );
  971. pVMTKeyValues->SetInt( "$no_fullbright", 1 );
  972. pVMTKeyValues->SetInt( "$alphatest", 1 );
  973. pVMTKeyValues->SetInt( "$nocull", 1 );
  974. pVMTKeyValues->SetInt( "$color_depth", 1 );
  975. g_pMaterialSSAODepthWrite[ 1 ][ 1 ] = g_pMaterialSystem->FindProceduralMaterial( "__ColorDepthWrite11", TEXTURE_GROUP_OTHER, pVMTKeyValues );
  976. g_pMaterialSSAODepthWrite[ 1 ][ 1 ]->IncrementReferenceCount();
  977. #endif
  978. }
  979. //-----------------------------------------------------------------------------
  980. // Purpose:
  981. //-----------------------------------------------------------------------------
  982. static void ShutdownDebugMaterials( void )
  983. {
  984. if ( IsPC() && mat_debugalttab.GetBool() )
  985. {
  986. Warning( "mat_debugalttab: ShutdownDebugMaterials\n" );
  987. }
  988. GL_UnloadMaterial( g_materialEmpty );
  989. #ifndef DEDICATED
  990. GL_UnloadMaterial( g_pMaterialLightSprite );
  991. GL_UnloadMaterial( g_pMaterialWireframeVertexColor );
  992. GL_UnloadMaterial( g_pMaterialWireframeVertexColorIgnoreZ );
  993. GL_UnloadMaterial( g_materialLeafVisWireframe );
  994. GL_UnloadMaterial( g_materialDebugLuxels );
  995. GL_UnloadMaterial( g_materialDebugLightmapZBuffer );
  996. GL_UnloadMaterial( g_materialDebugLightmap );
  997. GL_UnloadMaterial( g_materialDecalWireframe );
  998. GL_UnloadMaterial( g_materialBrushWireframe );
  999. GL_UnloadMaterial( g_materialWorldWireframeGreen );
  1000. GL_UnloadMaterial( g_materialWorldWireframeZBuffer );
  1001. GL_UnloadMaterial( g_materialWorldWireframe );
  1002. GL_UnloadMaterial( g_materialTranslucentSingleColor );
  1003. GL_UnloadMaterial( g_materialTranslucentVertexColor );
  1004. GL_UnloadMaterial( g_materialWireframe );
  1005. GL_UnloadMaterial( g_pMaterialShadowBuild );
  1006. GL_UnloadMaterial( g_pMaterialMRMWireframe );
  1007. GL_UnloadMaterial( g_pMaterialWriteZ );
  1008. GL_UnloadMaterial( g_pMaterialAmbientCube );
  1009. GL_UnloadMaterial( g_pMaterialDebugFlat );
  1010. // Materials for writing to shadow depth buffer
  1011. for (int i = 0; i<2; i++)
  1012. {
  1013. for (int j = 0; j<2; j++)
  1014. {
  1015. if( g_pMaterialDepthWrite[i][j] )
  1016. {
  1017. g_pMaterialDepthWrite[i][j]->DecrementReferenceCount();
  1018. }
  1019. g_pMaterialDepthWrite[i][j] = NULL;
  1020. if ( g_pMaterialSSAODepthWrite[ i ][ j ] )
  1021. {
  1022. g_pMaterialSSAODepthWrite[ i ][ j ]->DecrementReferenceCount();
  1023. }
  1024. g_pMaterialSSAODepthWrite[ i ][ j ] = NULL;
  1025. }
  1026. }
  1027. #endif
  1028. }
  1029. //-----------------------------------------------------------------------------
  1030. // Used to deal with making sure Present is called often enough
  1031. //-----------------------------------------------------------------------------
  1032. void InitStartupScreen()
  1033. {
  1034. if ( !IsGameConsole() )
  1035. return;
  1036. int screenWidth, screenHeight;
  1037. materials->GetBackBufferDimensions( screenWidth, screenHeight );
  1038. // NOTE: Brutal hackery, this code is duplicated in gameui.dll, and a bunch of other places
  1039. // but I have to do this prior to gameui being loaded.
  1040. char filename[MAX_PATH];
  1041. CL_GetStartupImage( filename, sizeof( filename ) );
  1042. ITexture *pTexture = materials->FindTexture( filename, TEXTURE_GROUP_OTHER );
  1043. CMatRenderContextPtr pRenderContext( g_pMaterialSystem );
  1044. pRenderContext->SetNonInteractiveTempFullscreenBuffer( pTexture, MATERIAL_NON_INTERACTIVE_MODE_STARTUP );
  1045. #if defined( CSTRIKE15 )
  1046. pTexture = materials->FindTexture( "console/spinner", TEXTURE_GROUP_OTHER );
  1047. pRenderContext->SetNonInteractivePacifierTexture( pTexture, 0.5f, 0.5f, 0.2f );
  1048. const int logoWidth = 896;
  1049. const int logoHeight = 64;
  1050. float x, y, w, h;
  1051. w = vgui::scheme()->GetProportionalScaledValue( logoWidth ) / 2;
  1052. h = vgui::scheme()->GetProportionalScaledValue( logoHeight ) / 2;
  1053. x = (screenWidth / 2 - w / 2 ) / (float)screenWidth;
  1054. y = (screenHeight / 2 - h / 2) / (float)screenHeight;
  1055. w = (w / (float)screenWidth);
  1056. h = (h / (float)screenHeight);
  1057. pTexture = materials->FindTexture( "console/logo", TEXTURE_GROUP_OTHER );
  1058. pRenderContext->SetNonInteractiveLogoTexture( pTexture, x, y, w, h );
  1059. #else
  1060. // this is what the loading progress calcs
  1061. float x, y, w, h, size;
  1062. size = vgui::scheme()->GetProportionalScaledValue( 85 );
  1063. x = screenWidth - vgui::scheme()->GetProportionalScaledValue( 85 );
  1064. y = vgui::scheme()->GetProportionalScaledValue( 70 );
  1065. // back solve to send in to achieve the above placement
  1066. x = x /(float)screenWidth;
  1067. y = y /(float)screenHeight;
  1068. size = size/(float)screenHeight;
  1069. pTexture = materials->FindTexture( "vgui/spinner", TEXTURE_GROUP_OTHER );
  1070. pRenderContext->SetNonInteractivePacifierTexture( pTexture, x, y, size );
  1071. y = vgui::scheme()->GetProportionalScaledValue( 390 );
  1072. w = vgui::scheme()->GetProportionalScaledValue( 240 );
  1073. h = vgui::scheme()->GetProportionalScaledValue( 60 );
  1074. // center align at bottom
  1075. x = (screenWidth/2 - w/2)/(float)screenWidth;
  1076. y = y/(float)screenHeight;
  1077. w = w/(float)screenWidth;
  1078. h = h/(float)screenHeight;
  1079. pTexture = materials->FindTexture( "vgui/portal2logo", TEXTURE_GROUP_OTHER );
  1080. pRenderContext->SetNonInteractiveLogoTexture( pTexture, x, y, w, h );
  1081. #endif // CSTRIKE15
  1082. }
  1083. //-----------------------------------------------------------------------------
  1084. // A console command to spew out driver information
  1085. //-----------------------------------------------------------------------------
  1086. CON_COMMAND( mat_info, "Shows material system info" )
  1087. {
  1088. materials->SpewDriverInfo();
  1089. }
  1090. extern ConVar r_fastzreject;
  1091. void InitMaterialSystem( void )
  1092. {
  1093. materials->AddReleaseFunc( ReleaseMaterialSystemObjects );
  1094. materials->AddRestoreFunc( RestoreMaterialSystemObjects );
  1095. r_fastzreject.SetValue( g_pMaterialSystemHardwareConfig->PreferZPrepass() );
  1096. UpdateMaterialSystemConfig();
  1097. InitWellKnownRenderTargets();
  1098. InitDebugMaterials();
  1099. }
  1100. void ShutdownMaterialSystem( void )
  1101. {
  1102. ShutdownDebugMaterials();
  1103. ShutdownWellKnownRenderTargets();
  1104. }
  1105. //-----------------------------------------------------------------------------
  1106. // Methods to restore, release material system objects
  1107. //-----------------------------------------------------------------------------
  1108. void ReleaseMaterialSystemObjects( int nChangeFlags )
  1109. {
  1110. if ( IsGameConsole() )
  1111. {
  1112. // 360 has not implemented release/restore
  1113. Warning( "ReleaseMaterialSystemObjects(): not implemented for 360\n" );
  1114. Assert( 0 );
  1115. return;
  1116. }
  1117. #ifndef DEDICATED
  1118. DispInfo_ReleaseMaterialSystemObjects( host_state.worldmodel );
  1119. modelrender->ReleaseAllStaticPropColorData();
  1120. #endif
  1121. #ifndef DEDICATED
  1122. WorldStaticMeshDestroy();
  1123. #endif
  1124. g_LostVideoMemory = true;
  1125. }
  1126. void RestoreMaterialSystemObjects( int nChangeFlags )
  1127. {
  1128. if ( IsGameConsole() )
  1129. {
  1130. // 360 has not implemented release/restore
  1131. Warning( "RestoreMaterialSystemObjects(): not implemented for 360\n" );
  1132. Assert( 0 );
  1133. return;
  1134. }
  1135. bool bThreadingAllowed = Host_AllowQueuedMaterialSystem( false );
  1136. g_LostVideoMemory = false;
  1137. if ( nChangeFlags & MATERIAL_RESTORE_VERTEX_FORMAT_CHANGED )
  1138. {
  1139. // ensure decals have no stale references to invalid lods
  1140. modelrender->RemoveAllDecalsFromAllModels( false );
  1141. }
  1142. if (host_state.worldmodel && materialSortInfoArray)
  1143. {
  1144. if ( (nChangeFlags & MATERIAL_RESTORE_VERTEX_FORMAT_CHANGED) || materials->GetNumSortIDs() == 0 )
  1145. {
  1146. #ifndef DEDICATED
  1147. // Reload lightmaps, world meshes, etc. because we may have switched from bumped to unbumped
  1148. R_LoadWorldGeometry( true );
  1149. #endif
  1150. }
  1151. else
  1152. {
  1153. modelloader->Map_LoadDisplacements( host_state.worldmodel, true );
  1154. #ifndef DEDICATED
  1155. WorldStaticMeshCreate();
  1156. // Gotta recreate the lightmaps
  1157. R_RedownloadAllLightmaps();
  1158. #endif
  1159. }
  1160. #ifndef DEDICATED
  1161. // Need to re-figure out the env_cubemaps, so blow away the lightcache.
  1162. R_StudioInitLightingCache();
  1163. modelrender->RestoreAllStaticPropColorData();
  1164. // Make sure we update visibility flags for props (especially coming back from an Alt-Tab)
  1165. StaticPropMgr()->RestoreStaticProps();
  1166. #endif
  1167. }
  1168. #ifndef DEDICATED
  1169. // Rebuild the overlay vertex buffer.
  1170. OverlayMgr()->ReSortMaterials();
  1171. #endif
  1172. Host_AllowQueuedMaterialSystem( bThreadingAllowed );
  1173. }
  1174. bool TangentSpaceSurfaceSetup( SurfaceHandle_t surfID, Vector &tVect )
  1175. {
  1176. Vector sVect;
  1177. VectorCopy( MSurf_TexInfo( surfID )->textureVecsTexelsPerWorldUnits[0].AsVector3D(), sVect );
  1178. VectorCopy( MSurf_TexInfo( surfID )->textureVecsTexelsPerWorldUnits[1].AsVector3D(), tVect );
  1179. VectorNormalize( sVect );
  1180. VectorNormalize( tVect );
  1181. Vector tmpVect;
  1182. CrossProduct( sVect, tVect, tmpVect );
  1183. // Make sure that the tangent space works if textures are mapped "backwards".
  1184. if( DotProduct( MSurf_Plane( surfID ).normal, tmpVect ) > 0.0f )
  1185. {
  1186. return true;
  1187. }
  1188. return false;
  1189. }
  1190. void TangentSpaceComputeBasis( Vector& tangentS, Vector& tangentT, const Vector& normal, const Vector& tVect, bool negateTangent )
  1191. {
  1192. // tangent x binormal = normal
  1193. // tangent = sVect
  1194. // binormal = tVect
  1195. CrossProduct( normal, tVect, tangentS );
  1196. VectorNormalize( tangentS );
  1197. CrossProduct( tangentS, normal, tangentT );
  1198. VectorNormalize( tangentT );
  1199. if ( negateTangent )
  1200. {
  1201. VectorScale( tangentS, -1.0f, tangentS );
  1202. }
  1203. }
  1204. //-----------------------------------------------------------------------------
  1205. // Purpose:
  1206. //-----------------------------------------------------------------------------
  1207. void MaterialSystem_DestroySortinfo( void )
  1208. {
  1209. if ( materialSortInfoArray )
  1210. {
  1211. #ifndef DEDICATED
  1212. WorldStaticMeshDestroy();
  1213. #endif
  1214. delete[] materialSortInfoArray;
  1215. materialSortInfoArray = NULL;
  1216. }
  1217. }
  1218. #ifndef DEDICATED
  1219. //-----------------------------------------------------------------------------
  1220. // Purpose: Build a vertex buffer for this face
  1221. // Input : *pWorld - world model base
  1222. // *surf - surf to add to the mesh
  1223. // overbright - overbright factor (for colors)
  1224. // &builder - mesh that holds the vertex buffer
  1225. //-----------------------------------------------------------------------------
  1226. #ifdef NEWMESH
  1227. void BuildMSurfaceVertexArrays( worldbrushdata_t *pBrushData, SurfaceHandle_t surfID, CVertexBufferBuilder &builder )
  1228. {
  1229. SurfaceCtx_t ctx;
  1230. SurfSetupSurfaceContext( ctx, surfID );
  1231. byte flatColor[4] = { 255, 255, 255, 255 };
  1232. Vector tVect;
  1233. bool negate = false;
  1234. if ( MSurf_Flags( surfID ) & SURFDRAW_TANGENTSPACE )
  1235. {
  1236. negate = TangentSpaceSurfaceSetup( surfID, tVect );
  1237. }
  1238. for ( int i = 0; i < MSurf_VertCount( surfID ); i++ )
  1239. {
  1240. int vertIndex = pBrushData->vertindices[MSurf_FirstVertIndex( surfID ) + i];
  1241. // world-space vertex
  1242. Vector& vec = pBrushData->vertexes[vertIndex].position;
  1243. // output to mesh
  1244. builder.Position3fv( vec.Base() );
  1245. Vector2D uv;
  1246. SurfComputeTextureCoordinate( surfID, vec, uv.Base() );
  1247. builder.TexCoord2fv( 0, uv.Base() );
  1248. // garymct: normalized (within space of surface) lightmap texture coordinates
  1249. SurfComputeLightmapCoordinate( ctx, surfID, vec, uv );
  1250. builder.TexCoord2fv( 1, uv.Base() );
  1251. if ( MSurf_Flags( surfID ) & SURFDRAW_BUMPLIGHT )
  1252. {
  1253. // bump maps appear left to right in lightmap page memory, calculate
  1254. // the offset for the width of a single map. The pixel shader will use
  1255. // this to compute the actual texture coordinates
  1256. builder.TexCoord2f( 2, ctx.m_BumpSTexCoordOffset, 0.0f );
  1257. }
  1258. else
  1259. {
  1260. // PORTAL 2 FIX - paint shader assumes it can use 3 lightmapped coordinates in all cases, so set the offset to something reasonable
  1261. builder.TexCoord2f( 2, 0.0f, 0.0f );
  1262. }
  1263. Vector& normal = pBrushData->vertnormals[ pBrushData->vertnormalindices[MSurf_FirstVertNormal( surfID ) + i] ];
  1264. builder.Normal3fv( normal.Base() );
  1265. if ( MSurf_Flags( surfID ) & SURFDRAW_TANGENTSPACE )
  1266. {
  1267. Vector tangentS, tangentT;
  1268. TangentSpaceComputeBasis( tangentS, tangentT, normal, tVect, negate );
  1269. builder.TangentS3fv( tangentS.Base() );
  1270. builder.TangentT3fv( tangentT.Base() );
  1271. }
  1272. // The amount to blend between basetexture and basetexture2 used to sit in lightmap
  1273. // alpha, so we didn't care about the vertex color or vertex alpha. But now if they're
  1274. // using it, we have to make sure the vertex has the color and alpha specified correctly
  1275. // or it will look weird.
  1276. if ( !SurfaceHasDispInfo( surfID ) &&
  1277. (MSurf_TexInfo( surfID )->texinfoFlags & TEXINFO_USING_BASETEXTURE2) )
  1278. {
  1279. static bool bWarned = false;
  1280. if ( !bWarned )
  1281. {
  1282. const char *pMaterialName = MSurf_TexInfo( surfID )->material->GetName();
  1283. bWarned = true;
  1284. Warning( "Warning: WorldTwoTextureBlend found on a non-displacement surface (material: %s). This wastes perf for no benefit.\n", pMaterialName );
  1285. }
  1286. builder.Color4ub( 255, 255, 255, 0 );
  1287. }
  1288. else
  1289. {
  1290. builder.Color3ubv( flatColor );
  1291. }
  1292. builder.AdvanceVertex();
  1293. }
  1294. }
  1295. #else
  1296. //-----------------------------------------------------------------------------
  1297. // Purpose: Build a vertex buffer for this face
  1298. // Input : *pWorld - world model base
  1299. // *surf - surf to add to the mesh
  1300. // &builder - mesh that holds the vertex buffer
  1301. //-----------------------------------------------------------------------------
  1302. static byte flatColor[4] = { 255, 255, 255, 255 };
  1303. static byte flatColorNoAlpha[4] = { 255, 255, 255, 0 };
  1304. void BuildMSurfaceVertexArrays( worldbrushdata_t *pBrushData, SurfaceHandle_t surfID, CMeshBuilder &builder )
  1305. {
  1306. SurfaceCtx_t ctx;
  1307. SurfSetupSurfaceContext( ctx, surfID );
  1308. Vector tVect;
  1309. bool negate = false;
  1310. if ( MSurf_Flags( surfID ) & SURFDRAW_TANGENTSPACE )
  1311. {
  1312. negate = TangentSpaceSurfaceSetup( surfID, tVect );
  1313. }
  1314. int vertCount = MSurf_VertCount(surfID);
  1315. for ( int i = 0; i < vertCount; i++ )
  1316. {
  1317. int vertIndex = pBrushData->vertindices[MSurf_FirstVertIndex( surfID ) + i];
  1318. // world-space vertex
  1319. Vector& vec = pBrushData->vertexes[vertIndex].position;
  1320. // output to mesh
  1321. builder.Position3fv( vec.Base() );
  1322. Vector2D uv;
  1323. SurfComputeTextureCoordinate( surfID, vec, uv.Base() );
  1324. builder.TexCoord2fv( 0, uv.Base() );
  1325. // garymct: normalized (within space of surface) lightmap texture coordinates
  1326. SurfComputeLightmapCoordinate( ctx, surfID, vec, uv );
  1327. builder.TexCoord2fv( 1, uv.Base() );
  1328. if ( MSurf_Flags( surfID ) & SURFDRAW_BUMPLIGHT )
  1329. {
  1330. // bump maps appear left to right in lightmap page memory, calculate
  1331. // the offset for the width of a single map. The pixel shader will use
  1332. // this to compute the actual texture coordinates
  1333. if ( uv.x + ctx.m_BumpSTexCoordOffset*3 > 1.00001f )
  1334. {
  1335. Assert(0);
  1336. SurfComputeLightmapCoordinate( ctx, surfID, vec, uv );
  1337. }
  1338. builder.TexCoord2f( 2, ctx.m_BumpSTexCoordOffset, 0.0f );
  1339. }
  1340. else
  1341. {
  1342. // PORTAL 2 FIX - paint shader assumes it can use 3 lightmapped coordinates in all cases, so set the offset to something reasonable
  1343. builder.TexCoord2f( 2, 0.0f, 0.0f );
  1344. }
  1345. Vector& normal = pBrushData->vertnormals[ pBrushData->vertnormalindices[MSurf_FirstVertNormal( surfID ) + i] ];
  1346. builder.Normal3fv( normal.Base() );
  1347. if ( MSurf_Flags( surfID ) & SURFDRAW_TANGENTSPACE )
  1348. {
  1349. Vector tangentS, tangentT;
  1350. TangentSpaceComputeBasis( tangentS, tangentT, normal, tVect, negate );
  1351. builder.TangentS3fv( tangentS.Base() );
  1352. builder.TangentT3fv( tangentT.Base() );
  1353. }
  1354. // The amount to blend between basetexture and basetexture2 used to sit in lightmap
  1355. // alpha, so we didn't care about the vertex color or vertex alpha. But now if they're
  1356. // using it, we have to make sure the vertex has the color and alpha specified correctly
  1357. // or it will look weird.
  1358. if ( !SurfaceHasDispInfo( surfID ) && (MSurf_TexInfo( surfID )->texinfoFlags & TEXINFO_USING_BASETEXTURE2) )
  1359. {
  1360. builder.Color4ubv( flatColorNoAlpha );
  1361. }
  1362. else
  1363. {
  1364. builder.Color4ubv( flatColor );
  1365. }
  1366. builder.AdvanceVertex();
  1367. }
  1368. }
  1369. #endif // NEWMESH
  1370. static int VertexCountForSurfaceList( const CMSurfaceSortList &list, const surfacesortgroup_t &group )
  1371. {
  1372. int vertexCount = 0;
  1373. MSL_FOREACH_SURFACE_IN_GROUP_BEGIN(list, group, surfID)
  1374. vertexCount += MSurf_VertCount(surfID);
  1375. MSL_FOREACH_SURFACE_IN_GROUP_END();
  1376. return vertexCount;
  1377. }
  1378. //-----------------------------------------------------------------------------
  1379. // Builds a static mesh from a list of all surfaces with the same material
  1380. //-----------------------------------------------------------------------------
  1381. struct meshlist_t
  1382. {
  1383. #ifdef NEWMESH
  1384. IVertexBuffer *pVertexBuffer;
  1385. #else
  1386. IMesh *pMesh;
  1387. #endif
  1388. IMaterial *pMaterial;
  1389. int vertCount;
  1390. VertexFormat_t vertexFormat;
  1391. };
  1392. static CUtlVector<meshlist_t> g_Meshes;
  1393. ConVar mat_max_worldmesh_vertices("mat_max_worldmesh_vertices", "65536");
  1394. static VertexFormat_t GetUncompressedFormat( const IMaterial * pMaterial )
  1395. {
  1396. // FIXME: IMaterial::GetVertexFormat() should do this stripping (add a separate 'SupportsCompression' accessor)
  1397. return ( pMaterial->GetVertexFormat() & ~VERTEX_FORMAT_COMPRESSED );
  1398. }
  1399. int FindOrAddMesh( IMaterial *pMaterial, int vertexCount )
  1400. {
  1401. VertexFormat_t format = GetUncompressedFormat( pMaterial );
  1402. CMatRenderContextPtr pRenderContext( materials );
  1403. int nMaxVertices = pRenderContext->GetMaxVerticesToRender( pMaterial );
  1404. int worldLimit = mat_max_worldmesh_vertices.GetInt();
  1405. worldLimit = MAX(worldLimit,1024);
  1406. if ( nMaxVertices > worldLimit )
  1407. {
  1408. nMaxVertices = mat_max_worldmesh_vertices.GetInt();
  1409. }
  1410. for ( int i = 0; i < g_Meshes.Count(); i++ )
  1411. {
  1412. if ( g_Meshes[i].vertexFormat != format )
  1413. continue;
  1414. if ( g_Meshes[i].vertCount + vertexCount > nMaxVertices )
  1415. continue;
  1416. g_Meshes[i].vertCount += vertexCount;
  1417. return i;
  1418. }
  1419. int index = g_Meshes.AddToTail();
  1420. g_Meshes[index].vertCount = vertexCount;
  1421. g_Meshes[index].vertexFormat = format;
  1422. g_Meshes[index].pMaterial = pMaterial;
  1423. return index;
  1424. }
  1425. void SetTexInfoBaseTexture2Flags()
  1426. {
  1427. for ( int i=0; i < host_state.worldbrush->numtexinfo; i++ )
  1428. {
  1429. host_state.worldbrush->texinfo[i].texinfoFlags &= ~TEXINFO_USING_BASETEXTURE2;
  1430. }
  1431. for ( int i=0; i < host_state.worldbrush->numtexinfo; i++ )
  1432. {
  1433. mtexinfo_t *pTexInfo = &host_state.worldbrush->texinfo[i];
  1434. IMaterial *pMaterial = pTexInfo->material;
  1435. if ( !pMaterial )
  1436. continue;
  1437. IMaterialVar **pParms = pMaterial->GetShaderParams();
  1438. int nParms = pMaterial->ShaderParamCount();
  1439. for ( int i=0; i < nParms; i++ )
  1440. {
  1441. if ( !pParms[i]->IsDefined() )
  1442. continue;
  1443. if ( Q_stricmp( pParms[i]->GetName(), "$basetexture2" ) == 0 )
  1444. {
  1445. pTexInfo->texinfoFlags |= TEXINFO_USING_BASETEXTURE2;
  1446. break;
  1447. }
  1448. }
  1449. }
  1450. }
  1451. //-----------------------------------------------------------------------------
  1452. // Determines vertex formats for all the world geometry
  1453. //-----------------------------------------------------------------------------
  1454. VertexFormat_t ComputeWorldStaticMeshVertexFormat( const IMaterial * pMaterial )
  1455. {
  1456. VertexFormat_t vertexFormat = GetUncompressedFormat( pMaterial );
  1457. // FIXME: set VERTEX_FORMAT_COMPRESSED if there are no artifacts and if it saves enough memory (use 'mem_dumpvballocs')
  1458. // vertexFormat |= VERTEX_FORMAT_COMPRESSED;
  1459. // FIXME: check for and strip unused vertex elements (TANGENT_S/T?)
  1460. return vertexFormat;
  1461. }
  1462. //-----------------------------------------------------------------------------
  1463. // Builds static meshes for all the world geometry
  1464. //-----------------------------------------------------------------------------
  1465. void WorldStaticMeshCreate( void )
  1466. {
  1467. r_framecount = 1;
  1468. WorldStaticMeshDestroy();
  1469. g_Meshes.RemoveAll();
  1470. SetTexInfoBaseTexture2Flags();
  1471. int nSortIDs = materials->GetNumSortIDs();
  1472. if ( nSortIDs == 0 )
  1473. {
  1474. // this is probably a bug in alt-tab. It's calling this as a restore function
  1475. // but the lightmaps haven't been allocated yet
  1476. Assert(0);
  1477. return;
  1478. }
  1479. // Setup sortbins for flashlight rendering
  1480. // FIXME!!!! Could have less bins since we don't care about the lightmap
  1481. // for projective light rendering purposes.
  1482. // Not entirely true since we need the correct lightmap page for WorldVertexTransition materials.
  1483. g_pShadowMgr->SetNumWorldMaterialBuckets( nSortIDs );
  1484. Assert( !g_WorldStaticMeshes.Count() );
  1485. g_WorldStaticMeshes.SetCount( nSortIDs );
  1486. memset( g_WorldStaticMeshes.Base(), 0, sizeof(g_WorldStaticMeshes[0]) * g_WorldStaticMeshes.Count() );
  1487. CMSurfaceSortList matSortArray;
  1488. matSortArray.Init( nSortIDs, 512 );
  1489. CUtlVector<int> sortIndex;
  1490. sortIndex.SetCount( g_WorldStaticMeshes.Count() );
  1491. CUtlVector<int> depthMeshIndexList;
  1492. depthMeshIndexList.SetCount( g_WorldStaticMeshes.Count() );
  1493. g_DepthMeshForSortID.SetCount( g_WorldStaticMeshes.Count() );
  1494. extern bool g_bReplayLoadedTools;
  1495. bool bTools = CommandLine()->CheckParm( "-tools" ) != NULL || g_bReplayLoadedTools;
  1496. int i;
  1497. // sort the surfaces into the sort arrays
  1498. for( int surfaceIndex = 0; surfaceIndex < host_state.worldbrush->numsurfaces; surfaceIndex++ )
  1499. {
  1500. SurfaceHandle_t surfID = SurfaceHandleFromIndex( surfaceIndex );
  1501. // set these flags here as they are determined by material data
  1502. MSurf_Flags( surfID ) &= ~(SURFDRAW_TANGENTSPACE);
  1503. // do we need to compute tangent space here?
  1504. if ( bTools || ( MSurf_TexInfo( surfID )->material->GetVertexFormat() & VERTEX_TANGENT_SPACE ) )
  1505. {
  1506. MSurf_Flags( surfID ) |= SURFDRAW_TANGENTSPACE;
  1507. }
  1508. // don't create vertex buffers for nodraw faces, water faces, or faces with dynamic data
  1509. // if ( (MSurf_Flags( surfID ) & (SURFDRAW_NODRAW|SURFDRAW_WATERSURFACE|SURFDRAW_DYNAMIC))
  1510. // || SurfaceHasDispInfo( surfID ) )
  1511. if( SurfaceHasDispInfo( surfID ) )
  1512. {
  1513. MSurf_VertBufferIndex( surfID ) = 0xFFFF;
  1514. continue;
  1515. }
  1516. // attach to head of list
  1517. matSortArray.AddSurfaceToTail( surfID, 0, MSurf_MaterialSortID( surfID ) );
  1518. }
  1519. // iterate the arrays and create buffers
  1520. for ( i = 0; i < g_WorldStaticMeshes.Count(); i++ )
  1521. {
  1522. const surfacesortgroup_t &group = matSortArray.GetGroupForSortID(0,i);
  1523. int vertexCount = VertexCountForSurfaceList( matSortArray, group );
  1524. SurfaceHandle_t surfID = matSortArray.GetSurfaceAtHead( group );
  1525. g_WorldStaticMeshes[i] = NULL;
  1526. sortIndex[i] = surfID ? FindOrAddMesh( MSurf_TexInfo( surfID )->material, vertexCount ) : -1;
  1527. depthMeshIndexList[i] = surfID ? FindOrAddMesh( g_pMaterialDepthWrite[0][1], vertexCount ) : -1;
  1528. }
  1529. CMatRenderContextPtr pRenderContext( materials );
  1530. PIXEVENT( pRenderContext, "WorldStaticMeshCreate()" );
  1531. #ifdef NEWMESH
  1532. for ( i = 0; i < g_Meshes.Count(); i++ )
  1533. {
  1534. Assert( g_Meshes[i].vertCount > 0 );
  1535. Assert( g_Meshes[i].pMaterial );
  1536. g_Meshes[i].pVertexBuffer = pRenderContext->CreateStaticVertexBuffer( GetUncompressedFormat( g_Meshes[i].pMaterial ), g_Meshes[i].vertCount, TEXTURE_GROUP_STATIC_VERTEX_BUFFER_WORLD );
  1537. int vertBufferIndex = 0;
  1538. // NOTE: Index count is zero because this will be a static vertex buffer!!!
  1539. CVertexBufferBuilder vertexBufferBuilder;
  1540. vertexBufferBuilder.Begin( g_Meshes[i].pVertexBuffer, g_Meshes[i].vertCount );
  1541. for ( int j = 0; j < g_WorldStaticMeshes.Count(); j++ )
  1542. {
  1543. int meshId = sortIndex[j];
  1544. if ( meshId == i )
  1545. {
  1546. g_WorldStaticMeshes[j] = g_Meshes[i].pVertexBuffer;
  1547. const surfacesortgroup_t &group = matSortArray.GetGroupForSortID(0,j);
  1548. MSL_FOREACH_SURFACE_IN_GROUP_BEGIN(matSortArray, group, surfID);
  1549. MSurf_VertBufferIndex( surfID ) = vertBufferIndex;
  1550. BuildMSurfaceVertexArrays( host_state.worldbrush, surfID, vertexBufferBuilder );
  1551. vertBufferIndex += MSurf_VertCount( surfID );
  1552. MSL_FOREACH_SURFACE_IN_GROUP_END();
  1553. }
  1554. }
  1555. vertexBufferBuilder.End();
  1556. Assert(vertBufferIndex == g_Meshes[i].vertCount);
  1557. }
  1558. #else
  1559. g_DepthFillVBFirstVertexForSurface.SetCount( host_state.worldbrush->numsurfaces );
  1560. for ( i = 0; i < g_Meshes.Count(); i++ )
  1561. {
  1562. Assert( g_Meshes[i].vertCount > 0 );
  1563. if ( g_VBAllocTracker )
  1564. g_VBAllocTracker->TrackMeshAllocations( "WorldStaticMeshCreate" );
  1565. VertexFormat_t vertexFormat = ComputeWorldStaticMeshVertexFormat( g_Meshes[i].pMaterial );
  1566. g_Meshes[i].pMesh = pRenderContext->CreateStaticMesh( vertexFormat, TEXTURE_GROUP_STATIC_VERTEX_BUFFER_WORLD, g_Meshes[i].pMaterial );
  1567. int vertBufferIndex = 0;
  1568. // NOTE: Index count is zero because this will be a static vertex buffer!!!
  1569. CMeshBuilder meshBuilder;
  1570. meshBuilder.Begin( g_Meshes[i].pMesh, MATERIAL_TRIANGLES, g_Meshes[i].vertCount, 0 );
  1571. for ( int j = 0; j < g_WorldStaticMeshes.Count(); j++ )
  1572. {
  1573. int meshId = sortIndex[j];
  1574. if ( meshId == i )
  1575. {
  1576. g_WorldStaticMeshes[j] = g_Meshes[i].pMesh;
  1577. const surfacesortgroup_t &group = matSortArray.GetGroupForSortID(0,j);
  1578. MSL_FOREACH_SURFACE_IN_GROUP_BEGIN(matSortArray, group, surfID);
  1579. MSurf_VertBufferIndex( surfID ) = vertBufferIndex;
  1580. BuildMSurfaceVertexArrays( host_state.worldbrush, surfID, meshBuilder );
  1581. vertBufferIndex += MSurf_VertCount( surfID );
  1582. MSL_FOREACH_SURFACE_IN_GROUP_END();
  1583. }
  1584. if ( depthMeshIndexList[j] == i )
  1585. {
  1586. g_DepthMeshForSortID[j] = g_Meshes[i].pMesh;
  1587. const surfacesortgroup_t &group = matSortArray.GetGroupForSortID(0,j);
  1588. MSL_FOREACH_SURFACE_IN_GROUP_BEGIN(matSortArray, group, surfID);
  1589. g_DepthFillVBFirstVertexForSurface[ MSurf_Index(surfID) ] = vertBufferIndex;
  1590. BuildMSurfaceVertexArrays( host_state.worldbrush, surfID, meshBuilder );
  1591. vertBufferIndex += MSurf_VertCount( surfID );
  1592. MSL_FOREACH_SURFACE_IN_GROUP_END();
  1593. }
  1594. }
  1595. meshBuilder.End();
  1596. Assert(vertBufferIndex == g_Meshes[i].vertCount);
  1597. if ( g_VBAllocTracker )
  1598. g_VBAllocTracker->TrackMeshAllocations( NULL );
  1599. }
  1600. #endif
  1601. //Msg("Total %d meshes, %d before\n", g_Meshes.Count(), g_WorldStaticMeshes.Count() );
  1602. }
  1603. void WorldStaticMeshDestroy( void )
  1604. {
  1605. CMatRenderContextPtr pRenderContext( materials );
  1606. // Blat out the static meshes associated with each material
  1607. for ( int i = 0; i < g_Meshes.Count(); i++ )
  1608. {
  1609. #ifdef NEWMESH
  1610. pRenderContext->DestroyVertexBuffer( g_Meshes[i].pVertexBuffer );
  1611. #else
  1612. pRenderContext->DestroyStaticMesh( g_Meshes[i].pMesh );
  1613. #endif
  1614. }
  1615. g_WorldStaticMeshes.Purge();
  1616. g_Meshes.RemoveAll();
  1617. g_DepthMeshForSortID.RemoveAll();
  1618. }
  1619. //-----------------------------------------------------------------------------
  1620. // Compute texture and lightmap coordinates
  1621. //-----------------------------------------------------------------------------
  1622. void SurfComputeTextureCoordinate( SurfaceHandle_t surfID, Vector const& vec, float * RESTRICT pUV )
  1623. {
  1624. mtexinfo_t* pTexInfo = MSurf_TexInfo( surfID );
  1625. // base texture coordinate
  1626. float u = DotProduct (vec, pTexInfo->textureVecsTexelsPerWorldUnits[0].AsVector3D()) +
  1627. pTexInfo->textureVecsTexelsPerWorldUnits[0][3];
  1628. u /= pTexInfo->material->GetMappingWidth();
  1629. float v = DotProduct (vec, pTexInfo->textureVecsTexelsPerWorldUnits[1].AsVector3D()) +
  1630. pTexInfo->textureVecsTexelsPerWorldUnits[1][3];
  1631. v /= pTexInfo->material->GetMappingHeight();
  1632. pUV[0] = u;
  1633. pUV[1] = v;
  1634. }
  1635. #if _DEBUG
  1636. void CheckTexCoord( float coord )
  1637. {
  1638. Assert(coord <= 1.0f );
  1639. }
  1640. #endif
  1641. void SurfComputeLightmapCoordinate( SurfaceCtx_t const& ctx, SurfaceHandle_t surfID,
  1642. Vector const& vec, Vector2D& uv )
  1643. {
  1644. if ( (MSurf_Flags( surfID ) & SURFDRAW_NOLIGHT) )
  1645. {
  1646. uv.x = uv.y = 0.5f;
  1647. }
  1648. else if ( MSurf_LightmapExtents( surfID )[0] == 0 )
  1649. {
  1650. uv = (0.5f * ctx.m_Scale + ctx.m_Offset);
  1651. }
  1652. else
  1653. {
  1654. mtexinfo_t* pTexInfo = MSurf_TexInfo( surfID );
  1655. uv.x = DotProduct (vec, pTexInfo->lightmapVecsLuxelsPerWorldUnits[0].AsVector3D()) +
  1656. pTexInfo->lightmapVecsLuxelsPerWorldUnits[0][3];
  1657. uv.x -= MSurf_LightmapMins( surfID )[0];
  1658. uv.x += 0.5f;
  1659. uv.y = DotProduct (vec, pTexInfo->lightmapVecsLuxelsPerWorldUnits[1].AsVector3D()) +
  1660. pTexInfo->lightmapVecsLuxelsPerWorldUnits[1][3];
  1661. uv.y -= MSurf_LightmapMins( surfID )[1];
  1662. uv.y += 0.5f;
  1663. uv *= ctx.m_Scale;
  1664. uv += ctx.m_Offset;
  1665. assert( uv.IsValid() );
  1666. }
  1667. #if _DEBUG
  1668. // This was here for check against displacements and they actually get calculated later correctly.
  1669. // CheckTexCoord( uv.x );
  1670. // CheckTexCoord( uv.y );
  1671. #endif
  1672. uv.x = clamp(uv.x, 0.0f, 1.0f);
  1673. uv.y = clamp(uv.y, 0.0f, 1.0f);
  1674. }
  1675. //-----------------------------------------------------------------------------
  1676. // Compute a context necessary for creating vertex data
  1677. //-----------------------------------------------------------------------------
  1678. void SurfSetupSurfaceContext( SurfaceCtx_t& ctx, SurfaceHandle_t surfID )
  1679. {
  1680. materials->GetLightmapPageSize(
  1681. SortInfoToLightmapPage( MSurf_MaterialSortID( surfID ) ),
  1682. &ctx.m_LightmapPageSize[0], &ctx.m_LightmapPageSize[1] );
  1683. ctx.m_LightmapSize[0] = ( MSurf_LightmapExtents( surfID )[0] ) + 1;
  1684. ctx.m_LightmapSize[1] = ( MSurf_LightmapExtents( surfID )[1] ) + 1;
  1685. ctx.m_Scale.x = 1.0f / ( float )ctx.m_LightmapPageSize[0];
  1686. ctx.m_Scale.y = 1.0f / ( float )ctx.m_LightmapPageSize[1];
  1687. ctx.m_Offset.x = ( float )MSurf_OffsetIntoLightmapPage( surfID )[0] * ctx.m_Scale.x;
  1688. ctx.m_Offset.y = ( float )MSurf_OffsetIntoLightmapPage( surfID )[1] * ctx.m_Scale.y;
  1689. if ( ctx.m_LightmapPageSize[0] != 0.0f )
  1690. {
  1691. ctx.m_BumpSTexCoordOffset = ( float )ctx.m_LightmapSize[0] / ( float )ctx.m_LightmapPageSize[0];
  1692. }
  1693. else
  1694. {
  1695. ctx.m_BumpSTexCoordOffset = 0.0f;
  1696. }
  1697. }
  1698. #endif // DEDICATED