//========= Copyright Valve Corporation, All rights reserved. ============//
//
// Purpose: loads and unloads main matsystem dll and interface
//
//===========================================================================//
# include "render_pch.h"
# include "materialsystem/imaterialsystemhardwareconfig.h"
# include "materialsystem/materialsystem_config.h"
# include "materialsystem/MaterialSystemUtil.h"
# include "materialsystem/ivballoctracker.h"
# include "materialsystem/imesh.h"
# include "tier0/dbg.h"
# include "sys_dll.h"
# include "host.h"
# include "cmodel_engine.h"
# include "gl_model_private.h"
# include "view.h"
# include "gl_matsysiface.h"
# include "gl_cvars.h"
# include "gl_lightmap.h"
# include "lightcache.h"
# include "vstdlib/random.h"
# include "tier0/icommandline.h"
# include "draw.h"
# include "decal_private.h"
# include "l_studio.h"
# include "KeyValues.h"
# include "materialsystem/imaterial.h"
# include "gl_shader.h"
# include "ivideomode.h"
# include "cdll_engine_int.h"
# include "utldict.h"
# include "filesystem.h"
# include "host_saverestore.h"
# include "server.h"
# include "game/client/iclientrendertargets.h"
# include "tier2/tier2.h"
# include "LoadScreenUpdate.h"
# include "client.h"
# include "sourcevr/isourcevirtualreality.h"
# if defined( _X360 )
# include "xbox/xbox_launch.h"
# endif
# if defined( USE_SDL )
# include "SDL.h"
# endif
//X360TEMP
# include "materialsystem/itexture.h"
extern IFileSystem * g_pFileSystem ;
# ifndef SWDS
# include "iregistry.h"
# endif
# include "igame.h"
// memdbgon must be the last include file in a .cpp file!!!
# include "tier0/memdbgon.h"
// Start the frame count at one so stuff gets updated the first frame
int r_framecount = 1 ; // used for dlight + lightstyle push checking
int d_lightstylevalue [ 256 ] ;
int d_lightstylenumframes [ 256 ] ;
const MaterialSystem_Config_t * g_pMaterialSystemConfig ;
static CSysModule * g_MaterialsDLL = NULL ;
bool g_LostVideoMemory = false ;
IMaterial * g_materialEmpty ; // purple checkerboard for missing textures
void ReleaseMaterialSystemObjects ( ) ;
void RestoreMaterialSystemObjects ( int nChangeFlags ) ;
extern ConVar mat_colorcorrection ;
extern ConVar sv_allow_color_correction ;
ConVar mat_debugalttab ( " mat_debugalttab " , " 0 " , FCVAR_CHEAT ) ;
// Static pointers to renderable textures
static CTextureReference g_PowerOfTwoFBTexture ;
static CTextureReference g_WaterReflectionTexture ;
static CTextureReference g_WaterRefractionTexture ;
static CTextureReference g_CameraTexture ;
static CTextureReference g_BuildCubemaps16BitTexture ;
static CTextureReference g_QuarterSizedFBTexture0 ;
static CTextureReference g_QuarterSizedFBTexture1 ;
static CTextureReference g_TeenyFBTexture0 ;
static CTextureReference g_TeenyFBTexture1 ;
static CTextureReference g_TeenyFBTexture2 ;
static CTextureReference g_FullFrameFBTexture0 ;
static CTextureReference g_FullFrameFBTexture1 ;
static CTextureReference g_FullFrameFBTexture2 ;
static CTextureReference g_FullFrameDepth ;
static CTextureReference g_ResolvedFullFrameDepth ;
void WorldStaticMeshCreate ( void ) ;
void WorldStaticMeshDestroy ( void ) ;
ConVar r_norefresh ( " r_norefresh " , " 0 " ) ;
ConVar r_decals ( " r_decals " , " 2048 " ) ;
ConVar mp_decals ( " mp_decals " , " 200 " , FCVAR_ARCHIVE ) ;
ConVar r_lightmap ( " r_lightmap " , " -1 " , FCVAR_CHEAT | FCVAR_MATERIAL_SYSTEM_THREAD ) ;
ConVar r_lightstyle ( " r_lightstyle " , " -1 " , FCVAR_CHEAT | FCVAR_MATERIAL_SYSTEM_THREAD ) ;
ConVar r_dynamic ( " r_dynamic " , " 1 " ) ;
ConVar mat_norendering ( " mat_norendering " , " 0 " , FCVAR_CHEAT ) ;
ConVar mat_wireframe ( " mat_wireframe " , " 0 " , FCVAR_CHEAT ) ;
ConVar mat_luxels ( " mat_luxels " , " 0 " , FCVAR_CHEAT ) ;
ConVar mat_normals ( " mat_normals " , " 0 " , FCVAR_CHEAT ) ;
ConVar mat_bumpbasis ( " mat_bumpbasis " , " 0 " , FCVAR_CHEAT ) ;
ConVar mat_envmapsize ( " mat_envmapsize " , " 128 " ) ;
ConVar mat_envmaptgasize ( " mat_envmaptgasize " , " 32.0 " ) ;
ConVar mat_levelflush ( " mat_levelflush " , " 1 " ) ;
ConVar mat_fastspecular ( " mat_fastspecular " , " 1 " , 0 , " Enable/Disable specularity for visual testing. Will not reload materials and will not affect perf. " ) ;
ConVar mat_fullbright ( " mat_fullbright " , " 0 " , FCVAR_CHEAT ) ;
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 ) ;
static ConVar mat_monitorgamma_tv_range_min ( " mat_monitorgamma_tv_range_min " , " 16 " ) ;
static ConVar mat_monitorgamma_tv_range_max ( " mat_monitorgamma_tv_range_max " , " 255 " ) ;
// 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
static ConVar mat_monitorgamma_tv_exp ( " mat_monitorgamma_tv_exp " , " 2.5 " , 0 , " " , true , 1.0f , true , 4.0f ) ;
# ifdef _X360
static ConVar mat_monitorgamma_tv_enabled ( " mat_monitorgamma_tv_enabled " , " 1 " , FCVAR_ARCHIVE , " " ) ;
# else
static ConVar mat_monitorgamma_tv_enabled ( " mat_monitorgamma_tv_enabled " , " 0 " , FCVAR_ARCHIVE , " " ) ;
# endif
ConVar r_drawbrushmodels ( " r_drawbrushmodels " , " 1 " , FCVAR_CHEAT , " Render brush models. 0=Off, 1=Normal, 2=Wireframe " ) ;
ConVar r_shadowrendertotexture ( " r_shadowrendertotexture " , " 0 " ) ;
ConVar r_flashlightdepthtexture ( " r_flashlightdepthtexture " , " 1 " ) ;
# ifndef _X360
ConVar r_waterforceexpensive ( " r_waterforceexpensive " , " 0 " , FCVAR_ARCHIVE ) ;
# endif
ConVar r_waterforcereflectentities ( " r_waterforcereflectentities " , " 0 " ) ;
// Note: this is only here so we can ship an update without changing materialsystem.dll.
// Once we ship materialsystem.dll again, we can get rid of this and make the only one exist in materialsystem.dll.
ConVar mat_depthbias_normal ( " mat_depthbias_normal " , " 0.0f " , FCVAR_CHEAT ) ;
// This is here so that the client and the materialsystem can both see this.
ConVar mat_show_ab_hdr ( " mat_show_ab_hdr " , " 0 " ) ;
static void NukeModeSwitchSaveGames ( void )
{
if ( g_pFileSystem - > FileExists ( " save \\ modeswitchsave.sav " ) )
{
g_pFileSystem - > RemoveFile ( " save \\ modeswitchsave.sav " ) ;
}
if ( g_pFileSystem - > FileExists ( " save \\ modeswitchsave.tga " ) )
{
g_pFileSystem - > RemoveFile ( " save \\ modeswitchsave.tga " ) ;
}
}
void mat_hdr_level_Callback ( IConVar * var , const char * pOldString , float flOldValue )
{
if ( IsX360 ( ) )
{
// can't support, expected to be static
return ;
}
# ifdef CSS_PERF_TEST
ConVarRef hdr ( var ) ;
if ( hdr . GetInt ( ) > 0 )
hdr . SetValue ( 0 ) ;
return ;
# endif
// Can do any reloading that is necessary here upon change.
// FIXME: should check if there is actually going to be a change here (ie. are we able to run in HDR
// given the current map and hardware.
# ifndef SWDS
if ( g_pMaterialSystemHardwareConfig - > GetHardwareHDRType ( ) ! = HDR_TYPE_NONE & &
saverestore - > IsValidSave ( ) & &
modelloader - > LastLoadedMapHasHDRLighting ( ) & &
sv . GetMaxClients ( ) = = 1 & &
! sv . IsLevelMainMenuBackground ( )
)
{
NukeModeSwitchSaveGames ( ) ;
Cbuf_AddText ( " save modeswitchsave;wait;load modeswitchsave \n " ) ;
}
# endif
}
# ifdef CSS_PERF_TEST
ConVar mat_hdr_level ( " mat_hdr_level " , " 0 " , 0 ,
" Set to 0 for no HDR, 1 for LDR+bloom on HDR maps, and 2 for full HDR on HDR maps. " ,
mat_hdr_level_Callback ) ;
# else
ConVar mat_hdr_level ( " mat_hdr_level " , " 2 " , FCVAR_ARCHIVE ,
" Set to 0 for no HDR, 1 for LDR+bloom on HDR maps, and 2 for full HDR on HDR maps. " ,
mat_hdr_level_Callback ) ;
# endif
MaterialSystem_SortInfo_t * materialSortInfoArray = 0 ;
static bool s_bConfigLightingChanged = false ;
extern unsigned long GetRam ( ) ;
//-----------------------------------------------------------------------------
// return true if lightmaps need to be redownloaded
//-----------------------------------------------------------------------------
bool MaterialConfigLightingChanged ( )
{
return s_bConfigLightingChanged ;
}
void ClearMaterialConfigLightingChanged ( )
{
s_bConfigLightingChanged = false ;
}
//-----------------------------------------------------------------------------
// List of all convars to store into the registry
//-----------------------------------------------------------------------------
static const char * s_pRegistryConVars [ ] =
{
" mat_forceaniso " ,
" mat_picmip " ,
// "mat_dxlevel",
" mat_trilinear " ,
" mat_vsync " ,
" mat_forcehardwaresync " ,
" mat_parallaxmap " ,
" mat_reducefillrate " ,
" r_shadowrendertotexture " ,
" r_rootlod " ,
# ifndef _X360
" r_waterforceexpensive " ,
# endif
" r_waterforcereflectentities " ,
" mat_antialias " ,
" mat_aaquality " ,
" mat_specular " ,
" mat_bumpmap " ,
" mat_hdr_level " ,
" mat_colorcorrection " ,
// NOTE: Empty string must always be last!
" "
} ;
# if defined( OSX )
# define MOD_VIDEO_CONFIG_SETTINGS "videoconfig_mac.cfg"
# define USE_VIDEOCONFIG_FILE 1
# elif defined( ANDROID )
# define MOD_VIDEO_CONFIG_SETTINGS "videoconfig_android.cfg"
# define USE_VIDEOCONFIG_FILE 1
# elif defined( POSIX )
# define MOD_VIDEO_CONFIG_SETTINGS "videoconfig_linux.cfg"
# define USE_VIDEOCONFIG_FILE 1
# elif defined( DX_TO_GL_ABSTRACTION )
# define MOD_VIDEO_CONFIG_SETTINGS "videoconfig_gl.cfg"
# define USE_VIDEOCONFIG_FILE 1
# else
# define MOD_VIDEO_CONFIG_SETTINGS "videoconfig.cfg"
# define USE_VIDEOCONFIG_FILE 0
# endif
# if USE_VIDEOCONFIG_FILE
static CThreadMutex g_VideoConfigMutex ;
# endif
static int ReadVideoConfigInt ( const char * pName , int nDefault )
{
# if USE_VIDEOCONFIG_FILE
AUTO_LOCK ( g_VideoConfigMutex ) ;
// Try to make a keyvalues from the cfg file
KeyValues * pVideoConfig = new KeyValues ( " videoconfig " ) ;
bool bFileExists = pVideoConfig - > LoadFromFile ( g_pFullFileSystem , MOD_VIDEO_CONFIG_SETTINGS , " MOD " ) ;
// We probably didn't have one on disk yet, just bail. It'll get created soon.
if ( ! bFileExists )
return nDefault ;
int nInt = pVideoConfig - > GetInt ( pName , nDefault ) ;
pVideoConfig - > deleteThis ( ) ;
return nInt ;
# else
return registry - > ReadInt ( pName , nDefault ) ;
# endif
}
static void ReadVideoConfigInt ( const char * pName , int * pEntry )
{
# if USE_VIDEOCONFIG_FILE
AUTO_LOCK ( g_VideoConfigMutex ) ;
// Try to make a keyvalues from the cfg file
KeyValues * pVideoConfig = new KeyValues ( " videoconfig " ) ;
bool bFileExists = pVideoConfig - > LoadFromFile ( g_pFullFileSystem , MOD_VIDEO_CONFIG_SETTINGS , " MOD " ) ;
// We probably didn't have one on disk yet, just bail. It'll get created soon.
if ( ! bFileExists )
return ;
if ( pVideoConfig - > GetInt ( pName , - 1 ) ! = - 1 )
{
* pEntry = pVideoConfig - > GetInt ( pName , 0 ) ;
}
pVideoConfig - > deleteThis ( ) ;
# else
if ( registry - > ReadInt ( pName , - 1 ) ! = - 1 )
{
* pEntry = registry - > ReadInt ( pName , 0 ) ;
}
# endif
}
static const char * ReadVideoConfigString ( const char * pName , const char * pDefault )
{
# if USE_VIDEOCONFIG_FILE
AUTO_LOCK ( g_VideoConfigMutex ) ;
static char szRetString [ 255 ] ;
// Try to make a keyvalues from the cfg file
KeyValues * pVideoConfig = new KeyValues ( " videoconfig " ) ;
bool bFileExists = pVideoConfig - > LoadFromFile ( g_pFullFileSystem , MOD_VIDEO_CONFIG_SETTINGS , " MOD " ) ;
// We probably didn't have one on disk yet, just bail. It'll get created soon.
if ( ! bFileExists )
return pDefault ;
const char * pString = pVideoConfig - > GetString ( pName , pDefault ) ;
Q_strncpy ( szRetString , pString , sizeof ( szRetString ) ) ;
pVideoConfig - > deleteThis ( ) ;
return szRetString ;
# else
return registry - > ReadString ( pName , pDefault ) ;
# endif
}
static void WriteVideoConfigInt ( const char * pName , int nEntry )
{
# if USE_VIDEOCONFIG_FILE
AUTO_LOCK ( g_VideoConfigMutex ) ;
// Try to make a keyvalues from the cfg file
KeyValues * pVideoConfig = new KeyValues ( " videoconfig " ) ;
pVideoConfig - > LoadFromFile ( g_pFullFileSystem , MOD_VIDEO_CONFIG_SETTINGS , " MOD " ) ;
pVideoConfig - > SetInt ( pName , nEntry ) ;
pVideoConfig - > SaveToFile ( g_pFullFileSystem , MOD_VIDEO_CONFIG_SETTINGS , " MOD " , false , false , true ) ;
pVideoConfig - > deleteThis ( ) ;
# else
registry - > WriteInt ( pName , nEntry ) ;
# endif
}
static void WriteVideoConfigString ( const char * pName , const char * pString )
{
# if USE_VIDEOCONFIG_FILE
AUTO_LOCK ( g_VideoConfigMutex ) ;
// Try to make a keyvalues from the cfg file
KeyValues * pVideoConfig = new KeyValues ( " videoconfig " ) ;
pVideoConfig - > LoadFromFile ( g_pFullFileSystem , MOD_VIDEO_CONFIG_SETTINGS , " MOD " ) ;
pVideoConfig - > SetString ( pName , pString ) ;
pVideoConfig - > SaveToFile ( g_pFullFileSystem , MOD_VIDEO_CONFIG_SETTINGS , " MOD " , false , false , true ) ;
pVideoConfig - > deleteThis ( ) ;
# else
registry - > WriteString ( pName , pString ) ;
# endif
}
//-----------------------------------------------------------------------------
// Scan for video config convars which are overridden on the cmd line, used
// for development and automated timedemo regression testing.
// (Unfortunately, convars aren't set early enough during init from the cmd line
// for the usual machinery to work here.)
//-----------------------------------------------------------------------------
static bool s_bVideoConfigOverriddenFromCmdLine ;
template < typename T >
static T OverrideVideoConfigFromCommandLine ( const char * pCVarName , T curVal )
{
char szOption [ 256 ] ;
V_snprintf ( szOption , sizeof ( szOption ) , " +%s " , pCVarName ) ;
if ( CommandLine ( ) - > CheckParm ( szOption ) )
{
T newVal = CommandLine ( ) - > ParmValue ( szOption , curVal ) ;
Warning ( " Video configuration ignoring %s due to command line override \n " , pCVarName ) ;
s_bVideoConfigOverriddenFromCmdLine = true ;
return newVal ;
}
return curVal ;
}
//-----------------------------------------------------------------------------
// Reads convars from the registry
//-----------------------------------------------------------------------------
static void ReadMaterialSystemConfigFromRegistry ( MaterialSystem_Config_t & config )
{
# ifndef SWDS
if ( IsX360 ( ) )
return ;
ReadVideoConfigInt ( " ScreenWidth " , & config . m_VideoMode . m_Width ) ;
ReadVideoConfigInt ( " ScreenHeight " , & config . m_VideoMode . m_Height ) ;
config . SetFlag ( MATSYS_VIDCFG_FLAGS_WINDOWED , ReadVideoConfigInt ( " ScreenWindowed " , 0 ) ! = 0 ) ;
# if defined( USE_SDL ) && !defined( SWDS )
// Read the ScreenDisplayIndex and set sdl_displayindex if it's there.
ConVarRef conVar ( " sdl_displayindex " ) ;
if ( conVar . IsValid ( ) )
{
int displayIndex = 0 ;
ReadVideoConfigInt ( " ScreenDisplayIndex " , & displayIndex ) ;
conVar . SetValue ( displayIndex ) ;
displayIndex = conVar . GetInt ( ) ;
// Make sure the width / height isn't too large for this display.
SDL_Rect rect ;
if ( ! SDL_GetDisplayBounds ( displayIndex , & rect ) )
{
if ( ( config . m_VideoMode . m_Width > rect . w ) | | ( config . m_VideoMode . m_Height > rect . h ) )
{
config . m_VideoMode . m_Width = rect . w ;
config . m_VideoMode . m_Height = rect . h ;
}
}
}
# endif // USE_SDL && !SWDS
// Special case...
const char * szMonitorGamma = ReadVideoConfigString ( " ScreenMonitorGamma " , " 2.2 " ) ;
if ( szMonitorGamma & & strlen ( szMonitorGamma ) > 0 )
{
float flMonitorGamma = atof ( szMonitorGamma ) ;
// temp, to make sure people with gamma values saved in the old format don't max out
if ( flMonitorGamma > 3.0f )
{
flMonitorGamma = 2.2f ;
}
flMonitorGamma = OverrideVideoConfigFromCommandLine ( " mat_monitorgamma " , flMonitorGamma ) ;
mat_monitorgamma . SetValue ( flMonitorGamma ) ;
config . m_fMonitorGamma = mat_monitorgamma . GetFloat ( ) ;
}
for ( int i = 0 ; s_pRegistryConVars [ i ] [ 0 ] ; + + i )
{
int nValue = ReadVideoConfigInt ( s_pRegistryConVars [ i ] , 0x80000000 ) ;
if ( nValue = = 0x80000000 )
continue ;
nValue = OverrideVideoConfigFromCommandLine ( s_pRegistryConVars [ i ] , nValue ) ;
ConVarRef conVar ( s_pRegistryConVars [ i ] ) ;
if ( conVar . IsValid ( ) )
{
conVar . SetValue ( nValue ) ;
}
}
int nValue = ReadVideoConfigInt ( " DXLevel_V1 " , - 1 ) ;
if ( nValue ! = - 1 )
{
nValue = OverrideVideoConfigFromCommandLine ( " mat_dxlevel " , nValue ) ;
ConVarRef conVar ( " mat_dxlevel " ) ;
if ( conVar . IsValid ( ) )
{
conVar . SetValue ( nValue ) ;
}
}
nValue = ReadVideoConfigInt ( " MotionBlur " , - 1 ) ;
if ( nValue ! = - 1 )
{
nValue = OverrideVideoConfigFromCommandLine ( " mat_motion_blur_enabled " , nValue ) ;
ConVarRef conVar ( " mat_motion_blur_enabled " ) ;
if ( conVar . IsValid ( ) )
{
conVar . SetValue ( nValue ) ;
config . m_bMotionBlur = ReadVideoConfigInt ( " MotionBlur " , 0 ) ! = 0 ;
}
}
nValue = ReadVideoConfigInt ( " ShadowDepthTexture " , - 1 ) ;
if ( nValue ! = - 1 )
{
nValue = OverrideVideoConfigFromCommandLine ( " r_flashlightdepthtexture " , nValue ) ;
ConVarRef conVar ( " r_flashlightdepthtexture " ) ;
if ( conVar . IsValid ( ) )
{
conVar . SetValue ( nValue ) ;
config . m_bShadowDepthTexture = ReadVideoConfigInt ( " ShadowDepthTexture " , 0 ) ! = 0 ;
}
}
nValue = ReadVideoConfigInt ( " VRModeAdapter " , - 1 ) ;
if ( nValue ! = - 1 )
{
nValue = OverrideVideoConfigFromCommandLine ( " mat_vrmode_adapter " , nValue ) ;
ConVarRef conVar ( " mat_vrmode_adapter " ) ;
if ( conVar . IsValid ( ) )
{
conVar . SetValue ( nValue ) ;
config . m_nVRModeAdapter = ReadVideoConfigInt ( " VRModeAdapter " , - 1 ) ;
}
}
# endif
}
//-----------------------------------------------------------------------------
// Writes convars into the registry
//-----------------------------------------------------------------------------
static void WriteMaterialSystemConfigToRegistry ( const MaterialSystem_Config_t & config )
{
# ifndef SWDS
if ( IsX360 ( ) )
return ;
# if defined( USE_SDL ) && !defined( SWDS )
// Save sdl_displayindex out to ScreenDisplayIndex.
ConVarRef conVar ( " sdl_displayindex " ) ;
if ( conVar . IsValid ( ) & & ! UseVR ( ) )
{
WriteVideoConfigInt ( " ScreenDisplayIndex " , conVar . GetInt ( ) ) ;
}
# endif // USE_SDL && !SWDS
WriteVideoConfigInt ( " ScreenWidth " , config . m_VideoMode . m_Width ) ;
WriteVideoConfigInt ( " ScreenHeight " , config . m_VideoMode . m_Height ) ;
WriteVideoConfigInt ( " ScreenWindowed " , config . Windowed ( ) ) ;
WriteVideoConfigInt ( " ScreenMSAA " , config . m_nAASamples ) ;
WriteVideoConfigInt ( " ScreenMSAAQuality " , config . m_nAAQuality ) ;
WriteVideoConfigInt ( " MotionBlur " , config . m_bMotionBlur ? 1 : 0 ) ;
WriteVideoConfigInt ( " ShadowDepthTexture " , config . m_bShadowDepthTexture ? 1 : 0 ) ;
WriteVideoConfigInt ( " VRModeAdapter " , config . m_nVRModeAdapter ) ;
// Registry only stores ints, so divide/multiply by 100 when reading/writing.
WriteVideoConfigString ( " ScreenMonitorGamma " , mat_monitorgamma . GetString ( ) ) ;
for ( int i = 0 ; s_pRegistryConVars [ i ] [ 0 ] ; + + i )
{
ConVarRef conVar ( s_pRegistryConVars [ i ] ) ;
if ( ! conVar . IsValid ( ) )
continue ;
WriteVideoConfigInt ( s_pRegistryConVars [ i ] , conVar . GetInt ( ) ) ;
}
# endif
}
//-----------------------------------------------------------------------------
// Override config with command line params
//-----------------------------------------------------------------------------
static void OverrideMaterialSystemConfigFromCommandLine ( MaterialSystem_Config_t & config )
{
if ( IsX360 ( ) )
{
// these overrides cannot be supported
// the console configuration is explicit
return ;
}
if ( CommandLine ( ) - > FindParm ( " -dxlevel " ) )
{
config . dxSupportLevel = CommandLine ( ) - > ParmValue ( " -dxlevel " , config . dxSupportLevel ) ;
// hack, mat_dxlevel is a special case, since it's saved in the registry
// but has a special different command-line override
// we need to re-apply the cvar
ConVarRef conVar ( " mat_dxlevel " ) ;
if ( conVar . IsValid ( ) )
{
conVar . SetValue ( config . dxSupportLevel ) ;
}
}
// Check for windowed mode command line override
if ( CommandLine ( ) - > FindParm ( " -sw " ) | |
CommandLine ( ) - > FindParm ( " -startwindowed " ) | |
CommandLine ( ) - > FindParm ( " -windowed " ) | |
CommandLine ( ) - > FindParm ( " -window " ) )
{
config . SetFlag ( MATSYS_VIDCFG_FLAGS_WINDOWED , true ) ;
}
// Check for fullscreen override
else if ( CommandLine ( ) - > FindParm ( " -full " ) | | CommandLine ( ) - > FindParm ( " -fullscreen " ) )
{
config . SetFlag ( MATSYS_VIDCFG_FLAGS_WINDOWED , false ) ;
}
// Get width and height
if ( CommandLine ( ) - > FindParm ( " -width " ) | | CommandLine ( ) - > FindParm ( " -w " ) )
{
config . m_VideoMode . m_Width = CommandLine ( ) - > ParmValue ( " -width " , config . m_VideoMode . m_Width ) ;
config . m_VideoMode . m_Width = CommandLine ( ) - > ParmValue ( " -w " , config . m_VideoMode . m_Width ) ;
if ( ! ( CommandLine ( ) - > FindParm ( " -height " ) | | CommandLine ( ) - > FindParm ( " -h " ) ) )
{
config . m_VideoMode . m_Height = ( config . m_VideoMode . m_Width * 3 ) / 4 ;
}
}
if ( CommandLine ( ) - > FindParm ( " -height " ) | | CommandLine ( ) - > FindParm ( " -h " ) )
{
config . m_VideoMode . m_Height = CommandLine ( ) - > ParmValue ( " -height " , config . m_VideoMode . m_Height ) ;
config . m_VideoMode . m_Height = CommandLine ( ) - > ParmValue ( " -h " , config . m_VideoMode . m_Height ) ;
}
# if defined( USE_SDL ) && !defined( SWDS )
// If -displayindex was specified on the command line, then set sdl_displayindex.
if ( CommandLine ( ) - > FindParm ( " -displayindex " ) )
{
ConVarRef conVar ( " sdl_displayindex " ) ;
if ( conVar . IsValid ( ) )
{
int displayIndex = CommandLine ( ) - > ParmValue ( " -displayindex " , conVar . GetInt ( ) ) ;
conVar . SetValue ( displayIndex ) ;
displayIndex = conVar . GetInt ( ) ;
// Make sure the width / height isn't too large for this display.
SDL_Rect rect ;
if ( ! SDL_GetDisplayBounds ( displayIndex , & rect ) )
{
if ( ( config . m_VideoMode . m_Width > rect . w ) | | ( config . m_VideoMode . m_Height > rect . h ) )
{
config . m_VideoMode . m_Width = rect . w ;
config . m_VideoMode . m_Height = rect . h ;
}
}
}
}
# endif // USE_SDL && !SWDS
if ( CommandLine ( ) - > FindParm ( " -resizing " ) )
{
config . SetFlag ( MATSYS_VIDCFG_FLAGS_RESIZING , CommandLine ( ) - > CheckParm ( " -resizing " ) ? true : false ) ;
}
# ifndef CSS_PERF_TEST
if ( CommandLine ( ) - > FindParm ( " -mat_vsync " ) )
{
int vsync = CommandLine ( ) - > ParmValue ( " -mat_vsync " , 1 ) ;
config . SetFlag ( MATSYS_VIDCFG_FLAGS_NO_WAIT_FOR_VSYNC , vsync = = 0 ) ;
}
# endif
config . m_nAASamples = CommandLine ( ) - > ParmValue ( " -mat_antialias " , config . m_nAASamples ) ;
config . m_nAAQuality = CommandLine ( ) - > ParmValue ( " -mat_aaquality " , config . m_nAAQuality ) ;
// Clamp the requested dimensions to the display resolution
MaterialVideoMode_t videoMode ;
materials - > GetDisplayMode ( videoMode ) ;
config . m_VideoMode . m_Width = MIN ( videoMode . m_Width , config . m_VideoMode . m_Width ) ;
config . m_VideoMode . m_Height = MIN ( videoMode . m_Height , config . m_VideoMode . m_Height ) ;
// safe mode
if ( CommandLine ( ) - > FindParm ( " -safe " ) )
{
config . SetFlag ( MATSYS_VIDCFG_FLAGS_WINDOWED , true ) ;
config . m_VideoMode . m_Width = 640 ;
config . m_VideoMode . m_Height = 480 ;
config . m_VideoMode . m_RefreshRate = 0 ;
config . m_nAASamples = 0 ;
config . m_nAAQuality = 0 ;
}
}
//-----------------------------------------------------------------------------
// Updates the material system config
//-----------------------------------------------------------------------------
void OverrideMaterialSystemConfig ( MaterialSystem_Config_t & config )
{
// enable/disable flashlight support based on mod (user can also set this explicitly)
// FIXME: this is only here because dxsupport_override.cfg is currently broken
ConVarRef mat_supportflashlight ( " mat_supportflashlight " ) ;
if ( mat_supportflashlight . GetInt ( ) = = - 1 )
{
const char * gameName = COM_GetModDirectory ( ) ;
if ( ! V_stricmp ( gameName , " portal " ) | |
! V_stricmp ( gameName , " tf " ) | |
! V_stricmp ( gameName , " tf_beta " ) )
{
mat_supportflashlight . SetValue ( false ) ;
}
else
{
mat_supportflashlight . SetValue ( true ) ;
}
}
config . m_bSupportFlashlight = mat_supportflashlight . GetBool ( ) ;
// apply the settings in the material system
bool bLightmapsNeedReloading = materials - > OverrideConfig ( config , false ) ;
if ( bLightmapsNeedReloading )
{
s_bConfigLightingChanged = true ;
}
// if VRModeAdapter is set, don't let things come up full screen
// They will be on the HMD display and that's BAD.
if ( config . m_nVRModeAdapter ! = - 1 )
{
WriteVideoConfigInt ( " ScreenWindowed " , 1 ) ;
config . SetFlag ( MATSYS_VIDCFG_FLAGS_WINDOWED , true ) ;
}
}
void HandleServerAllowColorCorrection ( )
{
# ifndef SWDS
if ( ! sv_allow_color_correction . GetBool ( ) & & mat_colorcorrection . GetInt ( ) )
{
Warning ( " mat_colorcorrection being forced to 0 due to sv_allow_color_correction=0. \n " ) ;
mat_colorcorrection . SetValue ( 0 ) ;
}
# endif
}
// auto config version to store in the registry so we can force reconfigs if needed
# define AUTOCONFIG_VERSION 1
//-----------------------------------------------------------------------------
// Purpose: Initializes configuration
//-----------------------------------------------------------------------------
void InitMaterialSystemConfig ( bool bInEditMode )
{
// get the default config for the current card as a starting point.
g_pMaterialSystemConfig = & materials - > GetCurrentConfigForVideoCard ( ) ;
if ( ! g_pMaterialSystemConfig )
{
Sys_Error ( " Could not get the material system config record! " ) ;
}
if ( bInEditMode )
return ;
MaterialSystem_Config_t config = * g_pMaterialSystemConfig ;
# if !defined(SWDS)
// see if they've changed video card, or have no settings present
MaterialAdapterInfo_t driverInfo ;
materials - > GetDisplayAdapterInfo ( materials - > GetCurrentAdapter ( ) , driverInfo ) ;
// see if the user has changed video cards or dx levels
uint currentVendorID = ReadVideoConfigInt ( " VendorID " , - 1 ) ;
uint currentDeviceID = ReadVideoConfigInt ( " DeviceID " , - 1 ) ;
uint autoConfigVersion = ReadVideoConfigInt ( " AutoConfigVersion " , - 1 ) ;
if ( autoConfigVersion ! = AUTOCONFIG_VERSION )
{
uint max_dxlevel , recommended_dxlevel ;
materials - > GetDXLevelDefaults ( max_dxlevel , recommended_dxlevel ) ;
uint currentDXLevel = ReadVideoConfigInt ( " DXLevel_V1 " , - 1 ) ;
if ( ( max_dxlevel ! = recommended_dxlevel ) & & ( currentDXLevel ! = recommended_dxlevel ) )
{
ConVarRef conVar ( " mat_dxlevel " ) ;
if ( conVar . IsValid ( ) )
{
conVar . SetValue ( ( int ) recommended_dxlevel ) ;
}
}
// Update the autoconfig version.
WriteVideoConfigInt ( " AutoConfigVersion " , AUTOCONFIG_VERSION ) ;
}
if ( driverInfo . m_VendorID = = currentVendorID & &
driverInfo . m_DeviceID = = currentDeviceID & &
! CommandLine ( ) - > FindParm ( " -autoconfig " ) & &
! CommandLine ( ) - > FindParm ( " -dxlevel " ) )
{
// the stored configuration looks like it will be valid, load it in
ReadMaterialSystemConfigFromRegistry ( config ) ;
}
# endif
OverrideMaterialSystemConfigFromCommandLine ( config ) ;
OverrideMaterialSystemConfig ( config ) ;
// Force the convars to update -- need this due to threading
g_pCVar - > ProcessQueuedMaterialThreadConVarSets ( ) ;
// Don't smack registry if dxlevel is overridden, or if the video config was overridden from the command line.
if ( ! CommandLine ( ) - > FindParm ( " -dxlevel " ) & & ! s_bVideoConfigOverriddenFromCmdLine )
{
WriteMaterialSystemConfigToRegistry ( * g_pMaterialSystemConfig ) ;
}
UpdateMaterialSystemConfig ( ) ;
# if !defined(SWDS)
// write out the current vendor has been seen & registered
WriteVideoConfigInt ( " VendorID " , driverInfo . m_VendorID ) ;
WriteVideoConfigInt ( " DeviceID " , driverInfo . m_DeviceID ) ;
WriteVideoConfigInt ( " DXLevel_V1 " , g_pMaterialSystemConfig - > dxSupportLevel ) ;
# endif
}
//-----------------------------------------------------------------------------
// Updates the material system config
//-----------------------------------------------------------------------------
void UpdateMaterialSystemConfig ( void )
{
if ( host_state . worldbrush & & ! host_state . worldbrush - > lightdata )
{
mat_fullbright . SetValue ( 1 ) ;
}
// apply the settings in the material system
bool bLightmapsNeedReloading = materials - > UpdateConfig ( false ) ;
if ( bLightmapsNeedReloading )
{
s_bConfigLightingChanged = true ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Sets all the relevant keyvalue data to be uploaded as part of the benchmark data
// Input : *dataToUpload - keyvalue set that will be uploaded
//-----------------------------------------------------------------------------
void GetMaterialSystemConfigForBenchmarkUpload ( KeyValues * dataToUpload )
{
# if !defined(SWDS)
// hardware info
MaterialAdapterInfo_t driverInfo ;
materials - > GetDisplayAdapterInfo ( materials - > GetCurrentAdapter ( ) , driverInfo ) ;
dataToUpload - > SetInt ( " vendorID " , driverInfo . m_VendorID ) ;
dataToUpload - > SetInt ( " deviceID " , driverInfo . m_DeviceID ) ;
dataToUpload - > SetInt ( " ram " , GetRam ( ) ) ;
const CPUInformation & pi = * GetCPUInformation ( ) ;
double fFrequency = pi . m_Speed / 1000000.0 ;
dataToUpload - > SetInt ( " cpu_speed " , ( int ) fFrequency ) ;
dataToUpload - > SetString ( " cpu " , pi . m_szProcessorID ) ;
// material system settings
dataToUpload - > SetInt ( " width " , g_pMaterialSystemConfig - > m_VideoMode . m_Width ) ;
dataToUpload - > SetInt ( " height " , g_pMaterialSystemConfig - > m_VideoMode . m_Height ) ;
dataToUpload - > SetInt ( " AASamples " , g_pMaterialSystemConfig - > m_nAASamples ) ;
dataToUpload - > SetInt ( " AAQuality " , g_pMaterialSystemConfig - > m_nAAQuality ) ;
dataToUpload - > SetInt ( " AnisoLevel " , g_pMaterialSystemConfig - > m_nForceAnisotropicLevel ) ;
dataToUpload - > SetInt ( " SkipMipLevels " , g_pMaterialSystemConfig - > skipMipLevels ) ;
dataToUpload - > SetInt ( " DXLevel " , g_pMaterialSystemConfig - > dxSupportLevel ) ;
dataToUpload - > SetInt ( " ShadowDepthTexture " , g_pMaterialSystemConfig - > ShadowDepthTexture ( ) ) ;
dataToUpload - > SetInt ( " MotionBlur " , g_pMaterialSystemConfig - > MotionBlur ( ) ) ;
dataToUpload - > SetInt ( " Windowed " , ( g_pMaterialSystemConfig - > m_Flags & MATSYS_VIDCFG_FLAGS_WINDOWED ) ? 1 : 0 ) ;
dataToUpload - > SetInt ( " Trilinear " , ( g_pMaterialSystemConfig - > m_Flags & MATSYS_VIDCFG_FLAGS_FORCE_TRILINEAR ) ? 1 : 0 ) ;
dataToUpload - > SetInt ( " ForceHWSync " , ( g_pMaterialSystemConfig - > m_Flags & MATSYS_VIDCFG_FLAGS_FORCE_HWSYNC ) ? 1 : 0 ) ;
dataToUpload - > SetInt ( " NoWaitForVSync " , ( g_pMaterialSystemConfig - > m_Flags & MATSYS_VIDCFG_FLAGS_NO_WAIT_FOR_VSYNC ) ? 1 : 0 ) ;
dataToUpload - > SetInt ( " DisableSpecular " , ( g_pMaterialSystemConfig - > m_Flags & MATSYS_VIDCFG_FLAGS_DISABLE_SPECULAR ) ? 1 : 0 ) ;
dataToUpload - > SetInt ( " DisableBumpmapping " , ( g_pMaterialSystemConfig - > m_Flags & MATSYS_VIDCFG_FLAGS_DISABLE_BUMPMAP ) ? 1 : 0 ) ;
dataToUpload - > SetInt ( " EnableParallaxMapping " , ( g_pMaterialSystemConfig - > m_Flags & MATSYS_VIDCFG_FLAGS_ENABLE_PARALLAX_MAPPING ) ? 1 : 0 ) ;
dataToUpload - > SetInt ( " ZPrefill " , ( g_pMaterialSystemConfig - > m_Flags & MATSYS_VIDCFG_FLAGS_USE_Z_PREFILL ) ? 1 : 0 ) ;
dataToUpload - > SetInt ( " ReduceFillRate " , ( g_pMaterialSystemConfig - > m_Flags & MATSYS_VIDCFG_FLAGS_REDUCE_FILLRATE ) ? 1 : 0 ) ;
dataToUpload - > SetInt ( " RenderToTextureShadows " , r_shadowrendertotexture . GetInt ( ) ? 1 : 0 ) ;
dataToUpload - > SetInt ( " FlashlightDepthTexture " , r_flashlightdepthtexture . GetInt ( ) ? 1 : 0 ) ;
# ifndef _X360
dataToUpload - > SetInt ( " RealtimeWaterReflection " , r_waterforceexpensive . GetInt ( ) ? 1 : 0 ) ;
# endif
dataToUpload - > SetInt ( " WaterReflectEntities " , r_waterforcereflectentities . GetInt ( ) ? 1 : 0 ) ;
# endif
}
//-----------------------------------------------------------------------------
// Purpose: Dumps the specified config info to the console
//-----------------------------------------------------------------------------
void PrintMaterialSystemConfig ( const MaterialSystem_Config_t & config )
{
Warning ( " width: %d \n " , config . m_VideoMode . m_Width ) ;
Warning ( " height: %d \n " , config . m_VideoMode . m_Height ) ;
Warning ( " m_nForceAnisotropicLevel: %d \n " , config . m_nForceAnisotropicLevel ) ;
Warning ( " aasamples: %d \n " , config . m_nAASamples ) ;
Warning ( " aaquality: %d \n " , config . m_nAAQuality ) ;
Warning ( " skipMipLevels: %d \n " , config . skipMipLevels ) ;
Warning ( " dxSupportLevel: %d \n " , config . dxSupportLevel ) ;
Warning ( " monitorGamma: %f \n " , config . m_fMonitorGamma ) ;
Warning ( " MATSYS_VIDCFG_FLAGS_WINDOWED: %s \n " , ( config . m_Flags & MATSYS_VIDCFG_FLAGS_WINDOWED ) ? " true " : " false " ) ;
Warning ( " MATSYS_VIDCFG_FLAGS_FORCE_TRILINEAR: %s \n " , ( config . m_Flags & MATSYS_VIDCFG_FLAGS_FORCE_TRILINEAR ) ? " true " : " false " ) ;
Warning ( " MATSYS_VIDCFG_FLAGS_FORCE_HWSYNC: %s \n " , ( config . m_Flags & MATSYS_VIDCFG_FLAGS_FORCE_HWSYNC ) ? " true " : " false " ) ;
Warning ( " MATSYS_VIDCFG_FLAGS_DISABLE_SPECULAR: %s \n " , ( config . m_Flags & MATSYS_VIDCFG_FLAGS_DISABLE_SPECULAR ) ? " true " : " false " ) ;
Warning ( " MATSYS_VIDCFG_FLAGS_ENABLE_PARALLAX_MAPPING: %s \n " , ( config . m_Flags & MATSYS_VIDCFG_FLAGS_ENABLE_PARALLAX_MAPPING ) ? " true " : " false " ) ;
Warning ( " MATSYS_VIDCFG_FLAGS_USE_Z_PREFILL: %s \n " , ( config . m_Flags & MATSYS_VIDCFG_FLAGS_USE_Z_PREFILL ) ? " true " : " false " ) ;
Warning ( " MATSYS_VIDCFG_FLAGS_REDUCE_FILLRATE: %s \n " , ( config . m_Flags & MATSYS_VIDCFG_FLAGS_REDUCE_FILLRATE ) ? " true " : " false " ) ;
Warning ( " r_shadowrendertotexture: %s \n " , r_shadowrendertotexture . GetInt ( ) ? " true " : " false " ) ;
Warning ( " motionblur: %s \n " , config . m_bMotionBlur ? " true " : " false " ) ;
Warning ( " shadowdepthtexture: %s \n " , config . m_bShadowDepthTexture ? " true " : " false " ) ;
# ifndef _X360
Warning ( " r_waterforceexpensive: %s \n " , r_waterforceexpensive . GetInt ( ) ? " true " : " false " ) ;
# endif
Warning ( " r_waterforcereflectentities: %s \n " , r_waterforcereflectentities . GetInt ( ) ? " true " : " false " ) ;
}
CON_COMMAND ( mat_configcurrent , " show the current video control panel config for the material system " )
{
const MaterialSystem_Config_t & config = materials - > GetCurrentConfigForVideoCard ( ) ;
PrintMaterialSystemConfig ( config ) ;
}
# if !defined(SWDS) && !defined( _X360 )
CON_COMMAND ( mat_setvideomode , " sets the width, height, windowed state of the material system " )
{
if ( args . ArgC ( ) ! = 4 )
return ;
int nWidth = Q_atoi ( args [ 1 ] ) ;
int nHeight = Q_atoi ( args [ 2 ] ) ;
bool bWindowed = Q_atoi ( args [ 3 ] ) > 0 ? true : false ;
videomode - > SetMode ( nWidth , nHeight , bWindowed ) ;
}
# endif
CON_COMMAND ( mat_enable_vrmode , " Switches the material system to VR mode (after restart) " )
{
if ( args . ArgC ( ) ! = 2 )
return ;
if ( ! g_pSourceVR )
return ;
ConVarRef mat_vrmode_adapter ( " mat_vrmode_adapter " ) ;
bool bVRMode = Q_atoi ( args [ 1 ] ) ! = 0 ;
if ( bVRMode )
{
# if defined( _WIN32 )
int32 nVRModeAdapter = g_pSourceVR - > GetVRModeAdapter ( ) ;
if ( nVRModeAdapter = = - 1 )
{
Warning ( " Unable to get VRModeAdapter from OpenVR. VR mode will not be enabled. Try restarting and then enabling VR again. \n " ) ;
}
mat_vrmode_adapter . SetValue ( nVRModeAdapter ) ;
# else
mat_vrmode_adapter . SetValue ( 0 ) ; // This convar isn't actually used on other platforms so just use 0 to indicate that it's set
# endif
}
else
{
mat_vrmode_adapter . SetValue ( - 1 ) ;
}
}
CON_COMMAND ( mat_savechanges , " saves current video configuration to the registry " )
{
// if the user has got to the point where they can adjust and apply video changes, then we can clear safe mode
CommandLine ( ) - > RemoveParm ( " -safe " ) ;
// write out config
UpdateMaterialSystemConfig ( ) ;
if ( ! CommandLine ( ) - > FindParm ( " -dxlevel " ) )
{
WriteMaterialSystemConfigToRegistry ( * g_pMaterialSystemConfig ) ;
}
}
# ifdef _DEBUG
//-----------------------------------------------------------------------------
// A console command to debug materials
//-----------------------------------------------------------------------------
CON_COMMAND_F ( mat_debug , " Activates debugging spew for a specific material. " , FCVAR_CHEAT )
{
if ( args . ArgC ( ) ! = 2 )
{
ConMsg ( " usage: mat_debug [ <material name> ] \n " ) ;
return ;
}
materials - > ToggleDebugMaterial ( args [ 1 ] ) ;
}
//-----------------------------------------------------------------------------
// A console command to suppress materials
//-----------------------------------------------------------------------------
CON_COMMAND_F ( mat_suppress , " Supress a material from drawing " , FCVAR_CHEAT )
{
if ( args . ArgC ( ) ! = 2 )
{
ConMsg ( " usage: mat_suppress [ <material name> ] \n " ) ;
return ;
}
materials - > ToggleSuppressMaterial ( args [ 1 ] ) ;
}
# endif // _DEBUG
static ITexture * CreatePowerOfTwoFBTexture ( void )
{
if ( IsX360 ( ) )
return NULL ;
return materials - > CreateNamedRenderTargetTextureEx2 (
" _rt_PowerOfTwoFB " ,
1024 , 1024 , RT_SIZE_DEFAULT ,
// Has dest alpha for vort warp effect
IMAGE_FORMAT_RGBA8888 ,
MATERIAL_RT_DEPTH_SHARED ,
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT ,
CREATERENDERTARGETFLAGS_HDR ) ;
}
static ITexture * CreateWaterReflectionTexture ( void )
{
return materials - > CreateNamedRenderTargetTextureEx2 (
" _rt_WaterReflection " ,
1024 , 1024 , RT_SIZE_PICMIP ,
materials - > GetBackBufferFormat ( ) ,
MATERIAL_RT_DEPTH_SHARED ,
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT ,
CREATERENDERTARGETFLAGS_HDR ) ;
}
static ITexture * CreateWaterRefractionTexture ( void )
{
return materials - > CreateNamedRenderTargetTextureEx2 (
" _rt_WaterRefraction " ,
1024 , 1024 , RT_SIZE_PICMIP ,
// This is different than reflection because it has to have alpha for fog factor.
IMAGE_FORMAT_RGBA8888 ,
MATERIAL_RT_DEPTH_SHARED ,
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT ,
CREATERENDERTARGETFLAGS_HDR ) ;
}
static ITexture * CreateCameraTexture ( void )
{
return materials - > CreateNamedRenderTargetTextureEx2 (
" _rt_Camera " ,
256 , 256 , RT_SIZE_DEFAULT ,
materials - > GetBackBufferFormat ( ) ,
MATERIAL_RT_DEPTH_SHARED ,
0 ,
CREATERENDERTARGETFLAGS_HDR ) ;
}
static ITexture * CreateBuildCubemaps16BitTexture ( void )
{
return materials - > CreateNamedRenderTargetTextureEx2 (
" _rt_BuildCubemaps16bit " ,
0 , 0 ,
RT_SIZE_FULL_FRAME_BUFFER ,
IMAGE_FORMAT_RGBA16161616 ,
MATERIAL_RT_DEPTH_SHARED ) ;
}
static ITexture * CreateQuarterSizedFBTexture ( int n , unsigned int iRenderTargetFlags )
{
char nbuf [ 20 ] ;
sprintf ( nbuf , " _rt_SmallFB%d " , n ) ;
ImageFormat fmt = materials - > GetBackBufferFormat ( ) ;
if ( g_pMaterialSystemHardwareConfig - > GetHDRType ( ) = = HDR_TYPE_FLOAT )
fmt = IMAGE_FORMAT_RGBA16161616F ;
return materials - > CreateNamedRenderTargetTextureEx2 (
nbuf , 0 , 0 , RT_SIZE_HDR ,
fmt , MATERIAL_RT_DEPTH_SHARED ,
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT ,
iRenderTargetFlags ) ;
}
static ITexture * CreateTeenyFBTexture ( int n )
{
char nbuf [ 20 ] ;
sprintf ( nbuf , " _rt_TeenyFB%d " , n ) ;
ImageFormat fmt = materials - > GetBackBufferFormat ( ) ;
if ( g_pMaterialSystemHardwareConfig - > GetHDRType ( ) = = HDR_TYPE_FLOAT )
fmt = IMAGE_FORMAT_RGBA16161616F ;
return materials - > CreateNamedRenderTargetTextureEx2 (
nbuf , 32 , 32 , RT_SIZE_DEFAULT ,
fmt , MATERIAL_RT_DEPTH_SHARED ) ;
}
static ITexture * CreateFullFrameFBTexture ( int textureIndex , int iExtraFlags = 0 )
{
char textureName [ 256 ] ;
if ( textureIndex > 0 )
{
sprintf ( textureName , " _rt_FullFrameFB%d " , textureIndex ) ;
}
else
{
V_strcpy_safe ( textureName , " _rt_FullFrameFB " ) ;
}
int rtFlags = iExtraFlags | CREATERENDERTARGETFLAGS_HDR ;
if ( IsX360 ( ) )
{
// just make the system memory texture only
rtFlags | = CREATERENDERTARGETFLAGS_NOEDRAM ;
}
return materials - > CreateNamedRenderTargetTextureEx2 (
textureName ,
1 , 1 , RT_SIZE_FULL_FRAME_BUFFER , materials - > GetBackBufferFormat ( ) ,
MATERIAL_RT_DEPTH_SHARED ,
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT ,
rtFlags ) ;
}
static ITexture * CreateFullFrameDepthTexture ( void )
{
if ( IsX360 ( ) )
{
return materials - > CreateNamedRenderTargetTextureEx2 ( " _rt_FullFrameDepth " , 1 , 1 ,
RT_SIZE_FULL_FRAME_BUFFER , materials - > GetShadowDepthTextureFormat ( ) , MATERIAL_RT_DEPTH_NONE ,
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_POINTSAMPLE ,
CREATERENDERTARGETFLAGS_NOEDRAM ) ;
}
else
{
materials - > AddTextureAlias ( " _rt_FullFrameDepth " , " _rt_PowerOfTwoFB " ) ;
}
return NULL ;
}
static ITexture * CreateResolvedFullFrameDepthTexture ( void )
{
if ( IsPC ( ) )
{
return materials - > CreateNamedRenderTargetTextureEx2 ( " _rt_ResolvedFullFrameDepth " , 1 , 1 ,
RT_SIZE_FULL_FRAME_BUFFER , IMAGE_FORMAT_RGBA8888 , MATERIAL_RT_DEPTH_SEPARATE ,
TEXTUREFLAGS_CLAMPS | TEXTUREFLAGS_CLAMPT | TEXTUREFLAGS_POINTSAMPLE ,
CREATERENDERTARGETFLAGS_NOEDRAM ) ;
}
return NULL ;
}
//-----------------------------------------------------------------------------
// Purpose: Create render targets which mods rely upon to render correctly
//-----------------------------------------------------------------------------
void InitWellKnownRenderTargets ( void )
{
# if !defined( SWDS )
if ( mat_debugalttab . GetBool ( ) )
{
Warning ( " mat_debugalttab: InitWellKnownRenderTargets \n " ) ;
}
// Begin block in which all render targets should be allocated
materials - > BeginRenderTargetAllocation ( ) ;
// JasonM -
// Do we put logic in here to determine which of these to create, based upon DX level, HDR enable etc?
// YES! DX Level should gate these
// before we create anything, see if VR mode wants to override the "framebuffer" size
if ( UseVR ( ) )
{
int nWidth , nHeight ;
g_pSourceVR - > GetRenderTargetFrameBufferDimensions ( nWidth , nHeight ) ;
g_pMaterialSystem - > SetRenderTargetFrameBufferSizeOverrides ( nWidth , nHeight ) ;
}
else
{
g_pMaterialSystem - > SetRenderTargetFrameBufferSizeOverrides ( 0 , 0 ) ;
}
// Create the render targets upon which mods may rely
if ( IsPC ( ) )
{
// Create for all mods as vgui2 uses it for 3D painting
g_PowerOfTwoFBTexture . Init ( CreatePowerOfTwoFBTexture ( ) ) ;
}
// Create these for all mods because the engine references them
if ( g_pMaterialSystemHardwareConfig - > GetDXSupportLevel ( ) > = 80 )
{
if ( IsPC ( ) & & g_pMaterialSystemHardwareConfig - > GetDXSupportLevel ( ) > = 90 & &
g_pMaterialSystemHardwareConfig - > GetHDRType ( ) = = HDR_TYPE_FLOAT )
{
// Used for building HDR Cubemaps
g_BuildCubemaps16BitTexture . Init ( CreateBuildCubemaps16BitTexture ( ) ) ;
}
// Used in Bloom effects
g_QuarterSizedFBTexture0 . Init ( CreateQuarterSizedFBTexture ( 0 , 0 ) ) ;
if ( IsX360 ( ) )
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
else
g_QuarterSizedFBTexture1 . Init ( CreateQuarterSizedFBTexture ( 1 , 0 ) ) ;
}
if ( IsPC ( ) )
{
g_TeenyFBTexture0 . Init ( CreateTeenyFBTexture ( 0 ) ) ;
g_TeenyFBTexture1 . Init ( CreateTeenyFBTexture ( 1 ) ) ;
g_TeenyFBTexture2 . Init ( CreateTeenyFBTexture ( 2 ) ) ;
}
g_FullFrameFBTexture0 . Init ( CreateFullFrameFBTexture ( 0 ) ) ;
g_FullFrameFBTexture1 . Init ( CreateFullFrameFBTexture ( 1 ) ) ;
if ( IsX360 ( ) )
{
g_FullFrameFBTexture2 . Init ( CreateFullFrameFBTexture ( 2 , CREATERENDERTARGETFLAGS_TEMP ) ) ;
}
g_FullFrameDepth . Init ( CreateFullFrameDepthTexture ( ) ) ;
g_ResolvedFullFrameDepth . Init ( CreateResolvedFullFrameDepthTexture ( ) ) ;
// if we're in stereo mode init a render target for VGUI
if ( UseVR ( ) )
{
g_pSourceVR - > CreateRenderTargets ( materials ) ;
}
// Allow the client to init their own mod-specific render targets
if ( g_pClientRenderTargets )
{
g_pClientRenderTargets - > InitClientRenderTargets ( materials , g_pMaterialSystemHardwareConfig ) ;
}
else
{
// If this mod doesn't define the interface, fallback to initializing the standard render textures
// NOTE: these should match up with the 'Get' functions in cl_dll/rendertexture.h/cpp
g_WaterReflectionTexture . Init ( CreateWaterReflectionTexture ( ) ) ;
g_WaterRefractionTexture . Init ( CreateWaterRefractionTexture ( ) ) ;
g_CameraTexture . Init ( CreateCameraTexture ( ) ) ;
}
// End block in which all render targets should be allocated (kicking off an Alt-Tab type behavior)
materials - > EndRenderTargetAllocation ( ) ;
CMatRenderContextPtr pRenderContext ( g_pMaterialSystem ) ;
pRenderContext - > SetNonInteractiveTempFullscreenBuffer ( g_FullFrameFBTexture0 , MATERIAL_NON_INTERACTIVE_MODE_LEVEL_LOAD ) ;
# endif
}
//-----------------------------------------------------------------------------
// Purpose: Shut down the render targets which mods rely upon to render correctly
//-----------------------------------------------------------------------------
void ShutdownWellKnownRenderTargets ( void )
{
# if !defined( SWDS )
if ( IsX360 ( ) )
{
// cannot allowing RT's to reconstruct, causes other fatal problems
// many other 360 systems have been coded with this expected constraint
Assert ( 0 ) ;
return ;
}
if ( IsPC ( ) & & mat_debugalttab . GetBool ( ) )
{
Warning ( " mat_debugalttab: ShutdownWellKnownRenderTargets \n " ) ;
}
g_PowerOfTwoFBTexture . Shutdown ( ) ;
g_BuildCubemaps16BitTexture . Shutdown ( ) ;
g_QuarterSizedFBTexture0 . Shutdown ( ) ;
if ( IsX360 ( ) )
materials - > RemoveTextureAlias ( " _rt_SmallFB1 " ) ;
else
g_QuarterSizedFBTexture1 . Shutdown ( ) ;
g_TeenyFBTexture0 . Shutdown ( ) ;
g_TeenyFBTexture1 . Shutdown ( ) ;
g_TeenyFBTexture2 . Shutdown ( ) ;
g_FullFrameFBTexture0 . Shutdown ( ) ;
g_FullFrameFBTexture1 . Shutdown ( ) ;
if ( IsX360 ( ) )
{
g_FullFrameFBTexture2 . Shutdown ( ) ;
}
CMatRenderContextPtr pRenderContext ( g_pMaterialSystem ) ;
pRenderContext - > SetNonInteractiveTempFullscreenBuffer ( NULL , MATERIAL_NON_INTERACTIVE_MODE_LEVEL_LOAD ) ;
g_FullFrameDepth . Shutdown ( ) ;
if ( IsPC ( ) )
{
materials - > RemoveTextureAlias ( " _rt_FullFrameDepth " ) ;
}
if ( g_pSourceVR )
g_pSourceVR - > ShutdownRenderTargets ( ) ;
// Shutdown client render targets
if ( g_pClientRenderTargets )
{
g_pClientRenderTargets - > ShutdownClientRenderTargets ( ) ;
}
else
{
g_WaterReflectionTexture . Shutdown ( ) ;
g_WaterRefractionTexture . Shutdown ( ) ;
g_CameraTexture . Shutdown ( ) ;
}
# endif
}
//-----------------------------------------------------------------------------
// A console command to spew out driver information
//-----------------------------------------------------------------------------
CON_COMMAND ( mat_reset_rendertargets , " Resets all the render targets " )
{
ShutdownWellKnownRenderTargets ( ) ;
InitWellKnownRenderTargets ( ) ;
}
//-----------------------------------------------------------------------------
// Purpose: Make the debug system materials
//-----------------------------------------------------------------------------
static void InitDebugMaterials ( void )
{
if ( IsPC ( ) & & mat_debugalttab . GetBool ( ) )
{
Warning ( " mat_debugalttab: InitDebugMaterials \n " ) ;
}
g_materialEmpty = GL_LoadMaterial ( " debug/debugempty " , TEXTURE_GROUP_OTHER ) ;
# ifndef SWDS
g_materialWireframe = GL_LoadMaterial ( " debug/debugwireframe " , TEXTURE_GROUP_OTHER ) ;
g_materialTranslucentSingleColor = GL_LoadMaterial ( " debug/debugtranslucentsinglecolor " , TEXTURE_GROUP_OTHER ) ;
g_materialTranslucentVertexColor = GL_LoadMaterial ( " debug/debugtranslucentvertexcolor " , TEXTURE_GROUP_OTHER ) ;
g_materialWorldWireframe = GL_LoadMaterial ( " debug/debugworldwireframe " , TEXTURE_GROUP_OTHER ) ;
g_materialWorldWireframeZBuffer = GL_LoadMaterial ( " debug/debugworldwireframezbuffer " , TEXTURE_GROUP_OTHER ) ;
g_materialBrushWireframe = GL_LoadMaterial ( " debug/debugbrushwireframe " , TEXTURE_GROUP_OTHER ) ;
g_materialDecalWireframe = GL_LoadMaterial ( " debug/debugdecalwireframe " , TEXTURE_GROUP_OTHER ) ;
g_materialDebugLightmap = GL_LoadMaterial ( " debug/debuglightmap " , TEXTURE_GROUP_OTHER ) ;
g_materialDebugLightmapZBuffer = GL_LoadMaterial ( " debug/debuglightmapzbuffer " , TEXTURE_GROUP_OTHER ) ;
g_materialDebugLuxels = GL_LoadMaterial ( " debug/debugluxels " , TEXTURE_GROUP_OTHER ) ;
g_materialLeafVisWireframe = GL_LoadMaterial ( " debug/debugleafviswireframe " , TEXTURE_GROUP_OTHER ) ;
g_pMaterialWireframeVertexColor = GL_LoadMaterial ( " debug/debugwireframevertexcolor " , TEXTURE_GROUP_OTHER ) ;
g_pMaterialWireframeVertexColorIgnoreZ = GL_LoadMaterial ( " debug/debugwireframevertexcolorignorez " , TEXTURE_GROUP_OTHER ) ;
g_pMaterialLightSprite = GL_LoadMaterial ( " engine/lightsprite " , TEXTURE_GROUP_OTHER ) ;
g_pMaterialShadowBuild = GL_LoadMaterial ( " engine/shadowbuild " , TEXTURE_GROUP_OTHER ) ;
g_pMaterialMRMWireframe = GL_LoadMaterial ( " debug/debugmrmwireframe " , TEXTURE_GROUP_OTHER ) ;
g_pMaterialDebugFlat = GL_LoadMaterial ( " debug/debugdrawflattriangles " , TEXTURE_GROUP_OTHER ) ;
g_pMaterialAmbientCube = GL_LoadMaterial ( " debug/debugambientcube " , TEXTURE_GROUP_OTHER ) ;
g_pMaterialWriteZ = GL_LoadMaterial ( " engine/writez " , TEXTURE_GROUP_OTHER ) ;
if ( g_pMaterialSystemHardwareConfig - > GetDXSupportLevel ( ) > = 90 )
{
// Materials for writing to shadow depth buffer
KeyValues * pVMTKeyValues = new KeyValues ( " DepthWrite " ) ;
pVMTKeyValues - > SetInt ( " $no_fullbright " , 1 ) ;
pVMTKeyValues - > SetInt ( " $alphatest " , 0 ) ;
pVMTKeyValues - > SetInt ( " $nocull " , 0 ) ;
g_pMaterialDepthWrite [ 0 ] [ 0 ] = g_pMaterialSystem - > FindProceduralMaterial ( " __DepthWrite00 " , TEXTURE_GROUP_OTHER , pVMTKeyValues ) ;
g_pMaterialDepthWrite [ 0 ] [ 0 ] - > IncrementReferenceCount ( ) ;
pVMTKeyValues = new KeyValues ( " DepthWrite " ) ;
pVMTKeyValues - > SetInt ( " $no_fullbright " , 1 ) ;
pVMTKeyValues - > SetInt ( " $alphatest " , 0 ) ;
pVMTKeyValues - > SetInt ( " $nocull " , 1 ) ;
g_pMaterialDepthWrite [ 0 ] [ 1 ] = g_pMaterialSystem - > FindProceduralMaterial ( " __DepthWrite01 " , TEXTURE_GROUP_OTHER , pVMTKeyValues ) ;
g_pMaterialDepthWrite [ 0 ] [ 1 ] - > IncrementReferenceCount ( ) ;
pVMTKeyValues = new KeyValues ( " DepthWrite " ) ;
pVMTKeyValues - > SetInt ( " $no_fullbright " , 1 ) ;
pVMTKeyValues - > SetInt ( " $alphatest " , 1 ) ;
pVMTKeyValues - > SetInt ( " $nocull " , 0 ) ;
g_pMaterialDepthWrite [ 1 ] [ 0 ] = g_pMaterialSystem - > FindProceduralMaterial ( " __DepthWrite10 " , TEXTURE_GROUP_OTHER , pVMTKeyValues ) ;
g_pMaterialDepthWrite [ 1 ] [ 0 ] - > IncrementReferenceCount ( ) ;
pVMTKeyValues = new KeyValues ( " DepthWrite " ) ;
pVMTKeyValues - > SetInt ( " $no_fullbright " , 1 ) ;
pVMTKeyValues - > SetInt ( " $alphatest " , 1 ) ;
pVMTKeyValues - > SetInt ( " $nocull " , 1 ) ;
g_pMaterialDepthWrite [ 1 ] [ 1 ] = g_pMaterialSystem - > FindProceduralMaterial ( " __DepthWrite11 " , TEXTURE_GROUP_OTHER , pVMTKeyValues ) ;
g_pMaterialDepthWrite [ 1 ] [ 1 ] - > IncrementReferenceCount ( ) ;
pVMTKeyValues = new KeyValues ( " DepthWrite " ) ;
pVMTKeyValues - > SetInt ( " $no_fullbright " , 1 ) ;
pVMTKeyValues - > SetInt ( " $alphatest " , 0 ) ;
pVMTKeyValues - > SetInt ( " $nocull " , 0 ) ;
pVMTKeyValues - > SetInt ( " $color_depth " , 1 ) ;
g_pMaterialSSAODepthWrite [ 0 ] [ 0 ] = g_pMaterialSystem - > FindProceduralMaterial ( " __ColorDepthWrite00 " , TEXTURE_GROUP_OTHER , pVMTKeyValues ) ;
g_pMaterialSSAODepthWrite [ 0 ] [ 0 ] - > IncrementReferenceCount ( ) ;
pVMTKeyValues = new KeyValues ( " DepthWrite " ) ;
pVMTKeyValues - > SetInt ( " $no_fullbright " , 1 ) ;
pVMTKeyValues - > SetInt ( " $alphatest " , 0 ) ;
pVMTKeyValues - > SetInt ( " $nocull " , 1 ) ;
pVMTKeyValues - > SetInt ( " $color_depth " , 1 ) ;
g_pMaterialSSAODepthWrite [ 0 ] [ 1 ] = g_pMaterialSystem - > FindProceduralMaterial ( " __ColorDepthWrite01 " , TEXTURE_GROUP_OTHER , pVMTKeyValues ) ;
g_pMaterialSSAODepthWrite [ 0 ] [ 1 ] - > IncrementReferenceCount ( ) ;
pVMTKeyValues = new KeyValues ( " DepthWrite " ) ;
pVMTKeyValues - > SetInt ( " $no_fullbright " , 1 ) ;
pVMTKeyValues - > SetInt ( " $alphatest " , 1 ) ;
pVMTKeyValues - > SetInt ( " $nocull " , 0 ) ;
pVMTKeyValues - > SetInt ( " $color_depth " , 1 ) ;
g_pMaterialSSAODepthWrite [ 1 ] [ 0 ] = g_pMaterialSystem - > FindProceduralMaterial ( " __ColorDepthWrite10 " , TEXTURE_GROUP_OTHER , pVMTKeyValues ) ;
g_pMaterialSSAODepthWrite [ 1 ] [ 0 ] - > IncrementReferenceCount ( ) ;
pVMTKeyValues = new KeyValues ( " DepthWrite " ) ;
pVMTKeyValues - > SetInt ( " $no_fullbright " , 1 ) ;
pVMTKeyValues - > SetInt ( " $alphatest " , 1 ) ;
pVMTKeyValues - > SetInt ( " $nocull " , 1 ) ;
pVMTKeyValues - > SetInt ( " $color_depth " , 1 ) ;
g_pMaterialSSAODepthWrite [ 1 ] [ 1 ] = g_pMaterialSystem - > FindProceduralMaterial ( " __ColorDepthWrite11 " , TEXTURE_GROUP_OTHER , pVMTKeyValues ) ;
g_pMaterialSSAODepthWrite [ 1 ] [ 1 ] - > IncrementReferenceCount ( ) ;
}
else
{
g_pMaterialDepthWrite [ 0 ] [ 0 ] = g_pMaterialDepthWrite [ 0 ] [ 1 ] = g_pMaterialDepthWrite [ 1 ] [ 0 ] = g_pMaterialDepthWrite [ 1 ] [ 1 ] = NULL ;
g_pMaterialSSAODepthWrite [ 0 ] [ 0 ] = g_pMaterialSSAODepthWrite [ 0 ] [ 1 ] = g_pMaterialSSAODepthWrite [ 1 ] [ 0 ] = g_pMaterialSSAODepthWrite [ 1 ] [ 1 ] = NULL ;
}
# endif
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
static void ShutdownDebugMaterials ( void )
{
if ( IsPC ( ) & & mat_debugalttab . GetBool ( ) )
{
Warning ( " mat_debugalttab: ShutdownDebugMaterials \n " ) ;
}
GL_UnloadMaterial ( g_materialEmpty ) ;
# ifndef SWDS
GL_UnloadMaterial ( g_pMaterialLightSprite ) ;
GL_UnloadMaterial ( g_pMaterialWireframeVertexColor ) ;
GL_UnloadMaterial ( g_pMaterialWireframeVertexColorIgnoreZ ) ;
GL_UnloadMaterial ( g_materialLeafVisWireframe ) ;
GL_UnloadMaterial ( g_materialDebugLuxels ) ;
GL_UnloadMaterial ( g_materialDebugLightmapZBuffer ) ;
GL_UnloadMaterial ( g_materialDebugLightmap ) ;
GL_UnloadMaterial ( g_materialDecalWireframe ) ;
GL_UnloadMaterial ( g_materialBrushWireframe ) ;
GL_UnloadMaterial ( g_materialWorldWireframeZBuffer ) ;
GL_UnloadMaterial ( g_materialWorldWireframe ) ;
GL_UnloadMaterial ( g_materialTranslucentSingleColor ) ;
GL_UnloadMaterial ( g_materialTranslucentVertexColor ) ;
GL_UnloadMaterial ( g_materialWireframe ) ;
GL_UnloadMaterial ( g_pMaterialShadowBuild ) ;
GL_UnloadMaterial ( g_pMaterialMRMWireframe ) ;
GL_UnloadMaterial ( g_pMaterialWriteZ ) ;
GL_UnloadMaterial ( g_pMaterialAmbientCube ) ;
GL_UnloadMaterial ( g_pMaterialDebugFlat ) ;
// Materials for writing to shadow depth buffer
if ( g_pMaterialSystemHardwareConfig - > GetDXSupportLevel ( ) > = 90 )
{
for ( int i = 0 ; i < 2 ; i + + )
{
for ( int j = 0 ; j < 2 ; j + + )
{
if ( g_pMaterialDepthWrite [ i ] [ j ] )
{
g_pMaterialDepthWrite [ i ] [ j ] - > DecrementReferenceCount ( ) ;
}
g_pMaterialDepthWrite [ i ] [ j ] = NULL ;
if ( g_pMaterialSSAODepthWrite [ i ] [ j ] )
{
g_pMaterialSSAODepthWrite [ i ] [ j ] - > DecrementReferenceCount ( ) ;
}
g_pMaterialSSAODepthWrite [ i ] [ j ] = NULL ;
}
}
}
# endif
}
//-----------------------------------------------------------------------------
// Used to deal with making sure Present is called often enough
//-----------------------------------------------------------------------------
void InitStartupScreen ( )
{
if ( ! IsX360 ( ) )
return ;
# ifdef _X360
XVIDEO_MODE videoMode ;
XGetVideoMode ( & videoMode ) ;
bool bIsWidescreen = videoMode . fIsWideScreen ! = FALSE ;
# else
int width , height ;
materials - > GetBackBufferDimensions ( width , height ) ;
float aspectRatio = ( float ) width / ( float ) height ;
bool bIsWidescreen = aspectRatio > = 1.5999f ;
# endif
// NOTE: Brutal hackery, this code is duplicated in gameui.dll
// but I have to do this prior to gameui being loaded.
// 360 uses hi-res game specific backgrounds
char gameName [ MAX_PATH ] ;
char filename [ MAX_PATH ] ;
V_FileBase ( com_gamedir , gameName , sizeof ( gameName ) ) ;
V_snprintf ( filename , sizeof ( filename ) , " vgui/appchooser/background_%s%s " , gameName , ( bIsWidescreen ? " _widescreen " : " " ) ) ;
ITexture * pTexture = materials - > FindTexture ( filename , TEXTURE_GROUP_OTHER ) ;
CMatRenderContextPtr pRenderContext ( g_pMaterialSystem ) ;
pRenderContext - > SetNonInteractiveTempFullscreenBuffer ( pTexture , MATERIAL_NON_INTERACTIVE_MODE_STARTUP ) ;
pTexture = materials - > FindTexture ( " //platform/materials/engine/box " , TEXTURE_GROUP_OTHER ) ;
KeyValues * modinfo = new KeyValues ( " ModInfo " ) ;
if ( modinfo - > LoadFromFile ( g_pFileSystem , " gameinfo.txt " ) )
{
if ( V_stricmp ( modinfo - > GetString ( " type " , " singleplayer_only " ) , " multiplayer_only " ) = = 0 )
{
pRenderContext - > SetNonInteractivePacifierTexture ( pTexture , 0.5f , 0.9f , 0.1f ) ;
}
else
{
pRenderContext - > SetNonInteractivePacifierTexture ( pTexture , 0.5f , 0.86f , 0.1f ) ;
}
}
modinfo - > deleteThis ( ) ;
BeginLoadingUpdates ( MATERIAL_NON_INTERACTIVE_MODE_STARTUP ) ;
}
//-----------------------------------------------------------------------------
// A console command to spew out driver information
//-----------------------------------------------------------------------------
CON_COMMAND ( mat_info , " Shows material system info " )
{
materials - > SpewDriverInfo ( ) ;
}
void InitMaterialSystem ( void )
{
materials - > AddReleaseFunc ( ReleaseMaterialSystemObjects ) ;
materials - > AddRestoreFunc ( RestoreMaterialSystemObjects ) ;
UpdateMaterialSystemConfig ( ) ;
InitWellKnownRenderTargets ( ) ;
InitDebugMaterials ( ) ;
# ifndef SWDS
DispInfo_InitMaterialSystem ( ) ;
# endif
# ifdef BENCHMARK
if ( g_pMaterialSystemHardwareConfig - > GetDXSupportLevel ( ) < 80 )
{
Error ( " dx6 and dx7 hardware not supported by this benchmark! " ) ;
}
# endif
}
void ShutdownMaterialSystem ( void )
{
ShutdownDebugMaterials ( ) ;
ShutdownWellKnownRenderTargets ( ) ;
# ifndef SWDS
DispInfo_ShutdownMaterialSystem ( ) ;
# endif
}
//-----------------------------------------------------------------------------
// Methods to restore, release material system objects
//-----------------------------------------------------------------------------
void ReleaseMaterialSystemObjects ( )
{
# ifndef SWDS
DispInfo_ReleaseMaterialSystemObjects ( host_state . worldmodel ) ;
modelrender - > ReleaseAllStaticPropColorData ( ) ;
# endif
# ifndef SWDS
WorldStaticMeshDestroy ( ) ;
# endif
g_LostVideoMemory = true ;
}
void RestoreMaterialSystemObjects ( int nChangeFlags )
{
if ( IsX360 ( ) )
return ;
bool bThreadingAllowed = Host_AllowQueuedMaterialSystem ( false ) ;
g_LostVideoMemory = false ;
if ( nChangeFlags & MATERIAL_RESTORE_VERTEX_FORMAT_CHANGED )
{
// ensure decals have no stale references to invalid lods
modelrender - > RemoveAllDecalsFromAllModels ( ) ;
}
if ( host_state . worldmodel )
{
if ( ( nChangeFlags & MATERIAL_RESTORE_VERTEX_FORMAT_CHANGED ) | | materials - > GetNumSortIDs ( ) = = 0 )
{
# ifndef SWDS
// Reload lightmaps, world meshes, etc. because we may have switched from bumped to unbumped
R_LoadWorldGeometry ( true ) ;
# endif
}
else
{
modelloader - > Map_LoadDisplacements ( host_state . worldmodel , true ) ;
# ifndef SWDS
WorldStaticMeshCreate ( ) ;
// Gotta recreate the lightmaps
R_RedownloadAllLightmaps ( ) ;
# endif
}
# ifndef SWDS
// Need to re-figure out the env_cubemaps, so blow away the lightcache.
R_StudioInitLightingCache ( ) ;
modelrender - > RestoreAllStaticPropColorData ( ) ;
# endif
}
# ifndef DEDICATED
cl . ForceFullUpdate ( ) ;
# endif
Host_AllowQueuedMaterialSystem ( bThreadingAllowed ) ;
}
bool TangentSpaceSurfaceSetup ( SurfaceHandle_t surfID , Vector & tVect )
{
Vector sVect ;
VectorCopy ( MSurf_TexInfo ( surfID ) - > textureVecsTexelsPerWorldUnits [ 0 ] . AsVector3D ( ) , sVect ) ;
VectorCopy ( MSurf_TexInfo ( surfID ) - > textureVecsTexelsPerWorldUnits [ 1 ] . AsVector3D ( ) , tVect ) ;
VectorNormalize ( sVect ) ;
VectorNormalize ( tVect ) ;
Vector tmpVect ;
CrossProduct ( sVect , tVect , tmpVect ) ;
// Make sure that the tangent space works if textures are mapped "backwards".
if ( DotProduct ( MSurf_Plane ( surfID ) . normal , tmpVect ) > 0.0f )
{
return true ;
}
return false ;
}
void TangentSpaceComputeBasis ( Vector & tangentS , Vector & tangentT , const Vector & normal , const Vector & tVect , bool negateTangent )
{
// tangent x binormal = normal
// tangent = sVect
// binormal = tVect
CrossProduct ( normal , tVect , tangentS ) ;
VectorNormalize ( tangentS ) ;
CrossProduct ( tangentS , normal , tangentT ) ;
VectorNormalize ( tangentT ) ;
if ( negateTangent )
{
VectorScale ( tangentS , - 1.0f , tangentS ) ;
}
}
//-----------------------------------------------------------------------------
// Purpose:
//-----------------------------------------------------------------------------
void MaterialSystem_DestroySortinfo ( void )
{
if ( materialSortInfoArray )
{
# ifndef SWDS
WorldStaticMeshDestroy ( ) ;
# endif
delete [ ] materialSortInfoArray ;
materialSortInfoArray = NULL ;
}
}
# ifndef SWDS
// The amount to blend between basetexture and basetexture2 used to sit in lightmap
// alpha, so we didn't care about the vertex color or vertex alpha. But now if they're
// using it, we have to make sure the vertex has the color and alpha specified correctly
// or it will look weird.
static inline bool CheckMSurfaceBaseTexture2 ( worldbrushdata_t * pBrushData , SurfaceHandle_t surfID )
{
if ( ! SurfaceHasDispInfo ( surfID ) & &
( MSurf_TexInfo ( surfID ) - > texinfoFlags & TEXINFO_USING_BASETEXTURE2 ) )
{
const char * pMaterialName = MSurf_TexInfo ( surfID ) - > material - > GetName ( ) ;
if ( pMaterialName )
{
bool bShowIt = false ;
if ( developer . GetInt ( ) < = 1 )
{
static CUtlDict < int , int > nameDict ;
if ( nameDict . Find ( pMaterialName ) = = - 1 )
{
nameDict . Insert ( pMaterialName , 0 ) ;
bShowIt = true ;
}
}
else
{
bShowIt = true ;
}
if ( bShowIt )
{
// Calculate the surface's centerpoint.
Vector vCenter ( 0 , 0 , 0 ) ;
for ( int i = 0 ; i < MSurf_VertCount ( surfID ) ; i + + )
{
int vertIndex = pBrushData - > vertindices [ MSurf_FirstVertIndex ( surfID ) + i ] ;
vCenter + = pBrushData - > vertexes [ vertIndex ] . position ;
}
vCenter / = ( float ) MSurf_VertCount ( surfID ) ;
// Spit out the warning.
Warning ( " Warning: using WorldTwoTextureBlend on a non-displacement surface. \n "
" Support for this will go away soon. \n "
" - Material : %s \n "
" - Surface center : %d %d %d \n "
, pMaterialName , ( int ) vCenter . x , ( int ) vCenter . y , ( int ) vCenter . z ) ;
}
}
return true ;
}
else
{
return false ;
}
}
//-----------------------------------------------------------------------------
// Purpose: Build a vertex buffer for this face
// Input : *pWorld - world model base
// *surf - surf to add to the mesh
// overbright - overbright factor (for colors)
// &builder - mesh that holds the vertex buffer
//-----------------------------------------------------------------------------
# ifdef NEWMESH
void BuildMSurfaceVertexArrays ( worldbrushdata_t * pBrushData , SurfaceHandle_t surfID , float overbright ,
CVertexBufferBuilder & builder )
{
SurfaceCtx_t ctx ;
SurfSetupSurfaceContext ( ctx , surfID ) ;
byte flatColor [ 4 ] = { 255 , 255 , 255 , 255 } ;
Vector tVect ;
bool negate = false ;
if ( MSurf_Flags ( surfID ) & SURFDRAW_TANGENTSPACE )
{
negate = TangentSpaceSurfaceSetup ( surfID , tVect ) ;
}
CheckMSurfaceBaseTexture2 ( pBrushData , surfID ) ;
for ( int i = 0 ; i < MSurf_VertCount ( surfID ) ; i + + )
{
int vertIndex = pBrushData - > vertindices [ MSurf_FirstVertIndex ( surfID ) + i ] ;
// world-space vertex
Vector & vec = pBrushData - > vertexes [ vertIndex ] . position ;
// output to mesh
builder . Position3fv ( vec . Base ( ) ) ;
Vector2D uv ;
SurfComputeTextureCoordinate ( ctx , surfID , vec , uv ) ;
builder . TexCoord2fv ( 0 , uv . Base ( ) ) ;
// garymct: normalized (within space of surface) lightmap texture coordinates
SurfComputeLightmapCoordinate ( ctx , surfID , vec , uv ) ;
builder . TexCoord2fv ( 1 , uv . Base ( ) ) ;
if ( MSurf_Flags ( surfID ) & SURFDRAW_BUMPLIGHT )
{
// bump maps appear left to right in lightmap page memory, calculate
// the offset for the width of a single map. The pixel shader will use
// this to compute the actual texture coordinates
builder . TexCoord2f ( 2 , ctx . m_BumpSTexCoordOffset , 0.0f ) ;
}
Vector & normal = pBrushData - > vertnormals [ pBrushData - > vertnormalindices [ MSurf_FirstVertNormal ( surfID ) + i ] ] ;
builder . Normal3fv ( normal . Base ( ) ) ;
if ( MSurf_Flags ( surfID ) & SURFDRAW_TANGENTSPACE )
{
Vector tangentS , tangentT ;
TangentSpaceComputeBasis ( tangentS , tangentT , normal , tVect , negate ) ;
builder . TangentS3fv ( tangentS . Base ( ) ) ;
builder . TangentT3fv ( tangentT . Base ( ) ) ;
}
// The amount to blend between basetexture and basetexture2 used to sit in lightmap
// alpha, so we didn't care about the vertex color or vertex alpha. But now if they're
// using it, we have to make sure the vertex has the color and alpha specified correctly
// or it will look weird.
if ( ! SurfaceHasDispInfo ( surfID ) & &
( MSurf_TexInfo ( surfID ) - > texinfoFlags & TEXINFO_USING_BASETEXTURE2 ) )
{
static bool bWarned = false ;
if ( ! bWarned )
{
const char * pMaterialName = MSurf_TexInfo ( surfID ) - > material - > GetName ( ) ;
bWarned = true ;
Warning ( " Warning: WorldTwoTextureBlend found on a non-displacement surface (material: %s). This wastes perf for no benefit. \n " , pMaterialName ) ;
}
builder . Color4ub ( 255 , 255 , 255 , 0 ) ;
}
else
{
builder . Color3ubv ( flatColor ) ;
}
builder . AdvanceVertex ( ) ;
}
}
# else
//-----------------------------------------------------------------------------
// Purpose: Build a vertex buffer for this face
// Input : *pWorld - world model base
// *surf - surf to add to the mesh
// overbright - overbright factor (for colors)
// &builder - mesh that holds the vertex buffer
//-----------------------------------------------------------------------------
void BuildMSurfaceVertexArrays ( worldbrushdata_t * pBrushData , SurfaceHandle_t surfID , float overbright ,
CMeshBuilder & builder )
{
SurfaceCtx_t ctx ;
SurfSetupSurfaceContext ( ctx , surfID ) ;
byte flatColor [ 4 ] = { 255 , 255 , 255 , 255 } ;
Vector tVect ;
bool negate = false ;
if ( MSurf_Flags ( surfID ) & SURFDRAW_TANGENTSPACE )
{
negate = TangentSpaceSurfaceSetup ( surfID , tVect ) ;
}
CheckMSurfaceBaseTexture2 ( pBrushData , surfID ) ;
for ( int i = 0 ; i < MSurf_VertCount ( surfID ) ; i + + )
{
int vertIndex = pBrushData - > vertindices [ MSurf_FirstVertIndex ( surfID ) + i ] ;
// world-space vertex
Vector & vec = pBrushData - > vertexes [ vertIndex ] . position ;
// output to mesh
builder . Position3fv ( vec . Base ( ) ) ;
Vector2D uv ;
SurfComputeTextureCoordinate ( ctx , surfID , vec , uv ) ;
builder . TexCoord2fv ( 0 , uv . Base ( ) ) ;
// garymct: normalized (within space of surface) lightmap texture coordinates
SurfComputeLightmapCoordinate ( ctx , surfID , vec , uv ) ;
builder . TexCoord2fv ( 1 , uv . Base ( ) ) ;
if ( MSurf_Flags ( surfID ) & SURFDRAW_BUMPLIGHT )
{
// bump maps appear left to right in lightmap page memory, calculate
// the offset for the width of a single map. The pixel shader will use
// this to compute the actual texture coordinates
if ( uv . x + ctx . m_BumpSTexCoordOffset * 3 > 1.00001f )
{
Assert ( 0 ) ;
SurfComputeLightmapCoordinate ( ctx , surfID , vec , uv ) ;
}
builder . TexCoord2f ( 2 , ctx . m_BumpSTexCoordOffset , 0.0f ) ;
}
Vector & normal = pBrushData - > vertnormals [ pBrushData - > vertnormalindices [ MSurf_FirstVertNormal ( surfID ) + i ] ] ;
builder . Normal3fv ( normal . Base ( ) ) ;
if ( MSurf_Flags ( surfID ) & SURFDRAW_TANGENTSPACE )
{
Vector tangentS , tangentT ;
TangentSpaceComputeBasis ( tangentS , tangentT , normal , tVect , negate ) ;
builder . TangentS3fv ( tangentS . Base ( ) ) ;
builder . TangentT3fv ( tangentT . Base ( ) ) ;
}
// The amount to blend between basetexture and basetexture2 used to sit in lightmap
// alpha, so we didn't care about the vertex color or vertex alpha. But now if they're
// using it, we have to make sure the vertex has the color and alpha specified correctly
// or it will look weird.
if ( ! SurfaceHasDispInfo ( surfID ) & &
( MSurf_TexInfo ( surfID ) - > texinfoFlags & TEXINFO_USING_BASETEXTURE2 ) )
{
static bool bWarned = false ;
if ( ! bWarned )
{
const char * pMaterialName = MSurf_TexInfo ( surfID ) - > material - > GetName ( ) ;
bWarned = true ;
Warning ( " Warning: WorldTwoTextureBlend found on a non-displacement surface (material: %s). This wastes perf for no benefit. \n " , pMaterialName ) ;
}
builder . Color4ub ( 255 , 255 , 255 , 0 ) ;
}
else
{
builder . Color3ubv ( flatColor ) ;
}
builder . AdvanceVertex ( ) ;
}
}
# endif // NEWMESH
static int VertexCountForSurfaceList ( const CMSurfaceSortList & list , const surfacesortgroup_t & group )
{
int vertexCount = 0 ;
MSL_FOREACH_SURFACE_IN_GROUP_BEGIN ( list , group , surfID )
vertexCount + = MSurf_VertCount ( surfID ) ;
MSL_FOREACH_SURFACE_IN_GROUP_END ( ) ;
return vertexCount ;
}
//-----------------------------------------------------------------------------
// Builds a static mesh from a list of all surfaces with the same material
//-----------------------------------------------------------------------------
struct meshlist_t
{
# ifdef NEWMESH
IVertexBuffer * pVertexBuffer ;
# else
IMesh * pMesh ;
# endif
IMaterial * pMaterial ;
int vertCount ;
VertexFormat_t vertexFormat ;
} ;
static CUtlVector < meshlist_t > g_Meshes ;
ConVar mat_max_worldmesh_vertices ( " mat_max_worldmesh_vertices " , " 65536 " ) ;
static VertexFormat_t GetUncompressedFormat ( const IMaterial * pMaterial )
{
// FIXME: IMaterial::GetVertexFormat() should do this stripping (add a separate 'SupportsCompression' accessor)
return ( pMaterial - > GetVertexFormat ( ) & ~ VERTEX_FORMAT_COMPRESSED ) ;
}
int FindOrAddMesh ( IMaterial * pMaterial , int vertexCount )
{
VertexFormat_t format = GetUncompressedFormat ( pMaterial ) ;
CMatRenderContextPtr pRenderContext ( materials ) ;
int nMaxVertices = pRenderContext - > GetMaxVerticesToRender ( pMaterial ) ;
int worldLimit = mat_max_worldmesh_vertices . GetInt ( ) ;
worldLimit = max ( worldLimit , 1024 ) ;
if ( nMaxVertices > worldLimit )
{
nMaxVertices = mat_max_worldmesh_vertices . GetInt ( ) ;
}
for ( int i = 0 ; i < g_Meshes . Count ( ) ; i + + )
{
if ( g_Meshes [ i ] . vertexFormat ! = format )
continue ;
if ( g_Meshes [ i ] . vertCount + vertexCount > nMaxVertices )
continue ;
g_Meshes [ i ] . vertCount + = vertexCount ;
return i ;
}
int index = g_Meshes . AddToTail ( ) ;
g_Meshes [ index ] . vertCount = vertexCount ;
g_Meshes [ index ] . vertexFormat = format ;
g_Meshes [ index ] . pMaterial = pMaterial ;
return index ;
}
void SetTexInfoBaseTexture2Flags ( )
{
for ( int i = 0 ; i < host_state . worldbrush - > numtexinfo ; i + + )
{
host_state . worldbrush - > texinfo [ i ] . texinfoFlags & = ~ TEXINFO_USING_BASETEXTURE2 ;
}
for ( int i = 0 ; i < host_state . worldbrush - > numtexinfo ; i + + )
{
mtexinfo_t * pTexInfo = & host_state . worldbrush - > texinfo [ i ] ;
IMaterial * pMaterial = pTexInfo - > material ;
if ( ! pMaterial )
continue ;
IMaterialVar * * pParms = pMaterial - > GetShaderParams ( ) ;
int nParms = pMaterial - > ShaderParamCount ( ) ;
for ( int j = 0 ; j < nParms ; j + + )
{
if ( ! pParms [ j ] - > IsDefined ( ) )
continue ;
if ( Q_stricmp ( pParms [ j ] - > GetName ( ) , " $basetexture2 " ) = = 0 )
{
pTexInfo - > texinfoFlags | = TEXINFO_USING_BASETEXTURE2 ;
break ;
}
}
}
}
//-----------------------------------------------------------------------------
// Determines vertex formats for all the world geometry
//-----------------------------------------------------------------------------
VertexFormat_t ComputeWorldStaticMeshVertexFormat ( const IMaterial * pMaterial )
{
VertexFormat_t vertexFormat = GetUncompressedFormat ( pMaterial ) ;
// FIXME: set VERTEX_FORMAT_COMPRESSED if there are no artifacts and if it saves enough memory (use 'mem_dumpvballocs')
// vertexFormat |= VERTEX_FORMAT_COMPRESSED;
// FIXME: check for and strip unused vertex elements (TANGENT_S/T?)
return vertexFormat ;
}
//-----------------------------------------------------------------------------
// Builds static meshes for all the world geometry
//-----------------------------------------------------------------------------
void WorldStaticMeshCreate ( void )
{
r_framecount = 1 ;
WorldStaticMeshDestroy ( ) ;
g_Meshes . RemoveAll ( ) ;
SetTexInfoBaseTexture2Flags ( ) ;
int nSortIDs = materials - > GetNumSortIDs ( ) ;
if ( nSortIDs = = 0 )
{
// this is probably a bug in alt-tab. It's calling this as a restore function
// but the lightmaps haven't been allocated yet
Assert ( 0 ) ;
return ;
}
// Setup sortbins for flashlight rendering
// FIXME!!!! Could have less bins since we don't care about the lightmap
// for projective light rendering purposes.
// Not entirely true since we need the correct lightmap page for WorldVertexTransition materials.
g_pShadowMgr - > SetNumWorldMaterialBuckets ( nSortIDs ) ;
Assert ( ! g_WorldStaticMeshes . Count ( ) ) ;
g_WorldStaticMeshes . SetCount ( nSortIDs ) ;
memset ( g_WorldStaticMeshes . Base ( ) , 0 , sizeof ( g_WorldStaticMeshes [ 0 ] ) * g_WorldStaticMeshes . Count ( ) ) ;
CMSurfaceSortList matSortArray ;
matSortArray . Init ( nSortIDs , 512 ) ;
int * sortIndex = ( int * ) _alloca ( sizeof ( int ) * g_WorldStaticMeshes . Count ( ) ) ;
bool bTools = CommandLine ( ) - > CheckParm ( " -tools " ) ! = NULL ;
int i ;
// sort the surfaces into the sort arrays
for ( int surfaceIndex = 0 ; surfaceIndex < host_state . worldbrush - > numsurfaces ; surfaceIndex + + )
{
SurfaceHandle_t surfID = SurfaceHandleFromIndex ( surfaceIndex ) ;
// set these flags here as they are determined by material data
MSurf_Flags ( surfID ) & = ~ ( SURFDRAW_TANGENTSPACE ) ;
// do we need to compute tangent space here?
if ( bTools | | ( MSurf_TexInfo ( surfID ) - > material - > GetVertexFormat ( ) & VERTEX_TANGENT_SPACE ) )
{
MSurf_Flags ( surfID ) | = SURFDRAW_TANGENTSPACE ;
}
// don't create vertex buffers for nodraw faces, water faces, or faces with dynamic data
// if ( (MSurf_Flags( surfID ) & (SURFDRAW_NODRAW|SURFDRAW_WATERSURFACE|SURFDRAW_DYNAMIC))
// || SurfaceHasDispInfo( surfID ) )
if ( SurfaceHasDispInfo ( surfID ) )
{
MSurf_VertBufferIndex ( surfID ) = 0xFFFF ;
continue ;
}
// attach to head of list
matSortArray . AddSurfaceToTail ( surfID , 0 , MSurf_MaterialSortID ( surfID ) ) ;
}
// iterate the arrays and create buffers
for ( i = 0 ; i < g_WorldStaticMeshes . Count ( ) ; i + + )
{
const surfacesortgroup_t & group = matSortArray . GetGroupForSortID ( 0 , i ) ;
int vertexCount = VertexCountForSurfaceList ( matSortArray , group ) ;
SurfaceHandle_t surfID = matSortArray . GetSurfaceAtHead ( group ) ;
g_WorldStaticMeshes [ i ] = NULL ;
sortIndex [ i ] = surfID ? FindOrAddMesh ( MSurf_TexInfo ( surfID ) - > material , vertexCount ) : - 1 ;
}
CMatRenderContextPtr pRenderContext ( materials ) ;
PIXEVENT ( pRenderContext , " WorldStaticMeshCreate " ) ;
# ifdef NEWMESH
for ( i = 0 ; i < g_Meshes . Count ( ) ; i + + )
{
Assert ( g_Meshes [ i ] . vertCount > 0 ) ;
Assert ( g_Meshes [ i ] . pMaterial ) ;
g_Meshes [ i ] . pVertexBuffer = pRenderContext - > CreateStaticVertexBuffer ( GetUncompressedFormat ( g_Meshes [ i ] . pMaterial ) , g_Meshes [ i ] . vertCount , TEXTURE_GROUP_STATIC_VERTEX_BUFFER_WORLD ) ;
int vertBufferIndex = 0 ;
// NOTE: Index count is zero because this will be a static vertex buffer!!!
CVertexBufferBuilder vertexBufferBuilder ;
vertexBufferBuilder . Begin ( g_Meshes [ i ] . pVertexBuffer , g_Meshes [ i ] . vertCount ) ;
for ( int j = 0 ; j < g_WorldStaticMeshes . Count ( ) ; j + + )
{
int meshId = sortIndex [ j ] ;
if ( meshId = = i )
{
g_WorldStaticMeshes [ j ] = g_Meshes [ i ] . pVertexBuffer ;
const surfacesortgroup_t & group = matSortArray . GetGroupForSortID ( 0 , j ) ;
MSL_FOREACH_SURFACE_IN_GROUP_BEGIN ( matSortArray , group , surfID ) ;
MSurf_VertBufferIndex ( surfID ) = vertBufferIndex ;
BuildMSurfaceVertexArrays ( host_state . worldbrush , surfID , OVERBRIGHT , vertexBufferBuilder ) ;
vertBufferIndex + = MSurf_VertCount ( surfID ) ;
MSL_FOREACH_SURFACE_IN_GROUP_END ( ) ;
}
}
vertexBufferBuilder . End ( ) ;
Assert ( vertBufferIndex = = g_Meshes [ i ] . vertCount ) ;
}
# else
for ( i = 0 ; i < g_Meshes . Count ( ) ; i + + )
{
Assert ( g_Meshes [ i ] . vertCount > 0 ) ;
if ( g_VBAllocTracker )
g_VBAllocTracker - > TrackMeshAllocations ( " WorldStaticMeshCreate " ) ;
VertexFormat_t vertexFormat = ComputeWorldStaticMeshVertexFormat ( g_Meshes [ i ] . pMaterial ) ;
g_Meshes [ i ] . pMesh = pRenderContext - > CreateStaticMesh ( vertexFormat , TEXTURE_GROUP_STATIC_VERTEX_BUFFER_WORLD , g_Meshes [ i ] . pMaterial ) ;
int vertBufferIndex = 0 ;
// NOTE: Index count is zero because this will be a static vertex buffer!!!
CMeshBuilder meshBuilder ;
meshBuilder . Begin ( g_Meshes [ i ] . pMesh , MATERIAL_TRIANGLES , g_Meshes [ i ] . vertCount , 0 ) ;
for ( int j = 0 ; j < g_WorldStaticMeshes . Count ( ) ; j + + )
{
int meshId = sortIndex [ j ] ;
if ( meshId = = i )
{
g_WorldStaticMeshes [ j ] = g_Meshes [ i ] . pMesh ;
const surfacesortgroup_t & group = matSortArray . GetGroupForSortID ( 0 , j ) ;
MSL_FOREACH_SURFACE_IN_GROUP_BEGIN ( matSortArray , group , surfID ) ;
MSurf_VertBufferIndex ( surfID ) = vertBufferIndex ;
BuildMSurfaceVertexArrays ( host_state . worldbrush , surfID , OVERBRIGHT , meshBuilder ) ;
vertBufferIndex + = MSurf_VertCount ( surfID ) ;
MSL_FOREACH_SURFACE_IN_GROUP_END ( ) ;
}
}
meshBuilder . End ( ) ;
Assert ( vertBufferIndex = = g_Meshes [ i ] . vertCount ) ;
if ( g_VBAllocTracker )
g_VBAllocTracker - > TrackMeshAllocations ( NULL ) ;
}
# endif
//Msg("Total %d meshes, %d before\n", g_Meshes.Count(), g_WorldStaticMeshes.Count() );
}
void WorldStaticMeshDestroy ( void )
{
CMatRenderContextPtr pRenderContext ( materials ) ;
// Blat out the static meshes associated with each material
for ( int i = 0 ; i < g_Meshes . Count ( ) ; i + + )
{
# ifdef NEWMESH
pRenderContext - > DestroyVertexBuffer ( g_Meshes [ i ] . pVertexBuffer ) ;
# else
pRenderContext - > DestroyStaticMesh ( g_Meshes [ i ] . pMesh ) ;
# endif
}
g_WorldStaticMeshes . Purge ( ) ;
g_Meshes . RemoveAll ( ) ;
}
//-----------------------------------------------------------------------------
// Compute texture and lightmap coordinates
//-----------------------------------------------------------------------------
void SurfComputeTextureCoordinate ( SurfaceCtx_t const & ctx , SurfaceHandle_t surfID ,
Vector const & vec , Vector2D & uv )
{
mtexinfo_t * pTexInfo = MSurf_TexInfo ( surfID ) ;
// base texture coordinate
uv . x = DotProduct ( vec , pTexInfo - > textureVecsTexelsPerWorldUnits [ 0 ] . AsVector3D ( ) ) +
pTexInfo - > textureVecsTexelsPerWorldUnits [ 0 ] [ 3 ] ;
uv . x / = pTexInfo - > material - > GetMappingWidth ( ) ;
uv . y = DotProduct ( vec , pTexInfo - > textureVecsTexelsPerWorldUnits [ 1 ] . AsVector3D ( ) ) +
pTexInfo - > textureVecsTexelsPerWorldUnits [ 1 ] [ 3 ] ;
uv . y / = pTexInfo - > material - > GetMappingHeight ( ) ;
}
# if _DEBUG
void CheckTexCoord ( float coord )
{
Assert ( coord < = 1.0f ) ;
}
# endif
void SurfComputeLightmapCoordinate ( SurfaceCtx_t const & ctx , SurfaceHandle_t surfID ,
Vector const & vec , Vector2D & uv )
{
if ( ( MSurf_Flags ( surfID ) & SURFDRAW_NOLIGHT ) )
{
uv . x = uv . y = 0.5f ;
}
else if ( MSurf_LightmapExtents ( surfID ) [ 0 ] = = 0 )
{
uv = ( 0.5f * ctx . m_Scale + ctx . m_Offset ) ;
}
else
{
mtexinfo_t * pTexInfo = MSurf_TexInfo ( surfID ) ;
uv . x = DotProduct ( vec , pTexInfo - > lightmapVecsLuxelsPerWorldUnits [ 0 ] . AsVector3D ( ) ) +
pTexInfo - > lightmapVecsLuxelsPerWorldUnits [ 0 ] [ 3 ] ;
uv . x - = MSurf_LightmapMins ( surfID ) [ 0 ] ;
uv . x + = 0.5f ;
uv . y = DotProduct ( vec , pTexInfo - > lightmapVecsLuxelsPerWorldUnits [ 1 ] . AsVector3D ( ) ) +
pTexInfo - > lightmapVecsLuxelsPerWorldUnits [ 1 ] [ 3 ] ;
uv . y - = MSurf_LightmapMins ( surfID ) [ 1 ] ;
uv . y + = 0.5f ;
uv * = ctx . m_Scale ;
uv + = ctx . m_Offset ;
assert ( uv . IsValid ( ) ) ;
}
# if _DEBUG
// This was here for check against displacements and they actually get calculated later correctly.
// CheckTexCoord( uv.x );
// CheckTexCoord( uv.y );
# endif
uv . x = clamp ( uv . x , 0.0f , 1.0f ) ;
uv . y = clamp ( uv . y , 0.0f , 1.0f ) ;
}
//-----------------------------------------------------------------------------
// Compute a context necessary for creating vertex data
//-----------------------------------------------------------------------------
void SurfSetupSurfaceContext ( SurfaceCtx_t & ctx , SurfaceHandle_t surfID )
{
materials - > GetLightmapPageSize (
SortInfoToLightmapPage ( MSurf_MaterialSortID ( surfID ) ) ,
& ctx . m_LightmapPageSize [ 0 ] , & ctx . m_LightmapPageSize [ 1 ] ) ;
ctx . m_LightmapSize [ 0 ] = ( MSurf_LightmapExtents ( surfID ) [ 0 ] ) + 1 ;
ctx . m_LightmapSize [ 1 ] = ( MSurf_LightmapExtents ( surfID ) [ 1 ] ) + 1 ;
ctx . m_Scale . x = 1.0f / ( float ) ctx . m_LightmapPageSize [ 0 ] ;
ctx . m_Scale . y = 1.0f / ( float ) ctx . m_LightmapPageSize [ 1 ] ;
ctx . m_Offset . x = ( float ) MSurf_OffsetIntoLightmapPage ( surfID ) [ 0 ] * ctx . m_Scale . x ;
ctx . m_Offset . y = ( float ) MSurf_OffsetIntoLightmapPage ( surfID ) [ 1 ] * ctx . m_Scale . y ;
if ( ctx . m_LightmapPageSize [ 0 ] ! = 0.0f )
{
ctx . m_BumpSTexCoordOffset = ( float ) ctx . m_LightmapSize [ 0 ] / ( float ) ctx . m_LightmapPageSize [ 0 ] ;
}
else
{
ctx . m_BumpSTexCoordOffset = 0.0f ;
}
}
# endif // SWDS