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.

1026 lines
31 KiB

  1. //========= Copyright (c) 1996-2005, Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. //===========================================================================//
  6. #include "shaderlib/BaseShader.h"
  7. #include "shaderlib/ShaderDLL.h"
  8. #include "tier0/dbg.h"
  9. #include "shaderDLL_Global.h"
  10. #include "materialsystem/ishadersystem.h"
  11. #include "materialsystem/imaterial.h"
  12. #include "materialsystem/itexture.h"
  13. #include "materialsystem/ishaderapi.h"
  14. #include "materialsystem/materialsystem_config.h"
  15. #include "shaderlib/cshader.h"
  16. #include "shaderlib/commandbuilder.h"
  17. #include "renderparm.h"
  18. #include "mathlib/vmatrix.h"
  19. #include "tier1/strtools.h"
  20. #include "convar.h"
  21. #include "tier0/vprof.h"
  22. #include "shaderapifast.h"
  23. // NOTE: This must be the last include file in a .cpp file!
  24. #include "tier0/memdbgon.h"
  25. //-----------------------------------------------------------------------------
  26. // Storage buffer used for instance command buffers
  27. //-----------------------------------------------------------------------------
  28. class CPerInstanceContextData : public CBasePerInstanceContextData
  29. {
  30. public:
  31. CPerInstanceContextData() : m_pCommandBuffer( NULL ), m_nSize( 0 ) {}
  32. virtual ~CPerInstanceContextData()
  33. {
  34. if ( m_pCommandBuffer )
  35. {
  36. delete m_pCommandBuffer;
  37. }
  38. }
  39. virtual unsigned char* GetInstanceCommandBuffer()
  40. {
  41. return m_pCommandBuffer;
  42. }
  43. unsigned char *m_pCommandBuffer;
  44. int m_nSize;
  45. };
  46. //-----------------------------------------------------------------------------
  47. // Globals
  48. //-----------------------------------------------------------------------------
  49. const char *CBaseShader::s_pTextureGroupName = NULL;
  50. IMaterialVar **CBaseShader::s_ppParams = NULL;
  51. IShaderShadow *CBaseShader::s_pShaderShadow;
  52. IShaderDynamicAPI *CBaseShader::s_pShaderAPI;
  53. IShaderInit *CBaseShader::s_pShaderInit;
  54. int CBaseShader::s_nModulationFlags;
  55. int CBaseShader::s_nPassCount = 0;
  56. CPerInstanceContextData** CBaseShader::s_pInstanceDataPtr = NULL;
  57. static bool s_bBuildingInstanceCommandBuffer = false;
  58. static CInstanceCommandBufferBuilder< CFixedCommandStorageBuffer< 512 > > s_InstanceCommandBuffer;
  59. bool g_shaderConfigDumpEnable = false; //true; //DO NOT CHECK IN ENABLED FIXME
  60. //-----------------------------------------------------------------------------
  61. // constructor
  62. //-----------------------------------------------------------------------------
  63. CBaseShader::CBaseShader()
  64. {
  65. GetShaderDLL()->InsertShader( this );
  66. }
  67. //-----------------------------------------------------------------------------
  68. // Shader parameter info
  69. //-----------------------------------------------------------------------------
  70. // Look in BaseShader.h for the enumeration for these.
  71. // Update there if you update here.
  72. static ShaderParamInfo_t s_StandardParams[NUM_SHADER_MATERIAL_VARS] =
  73. {
  74. { "$flags", "flags", SHADER_PARAM_TYPE_INTEGER, "0", SHADER_PARAM_NOT_EDITABLE },
  75. { "$flags_defined", "flags_defined", SHADER_PARAM_TYPE_INTEGER, "0", SHADER_PARAM_NOT_EDITABLE },
  76. { "$flags2", "flags2", SHADER_PARAM_TYPE_INTEGER, "0", SHADER_PARAM_NOT_EDITABLE },
  77. { "$flags_defined2", "flags2_defined", SHADER_PARAM_TYPE_INTEGER, "0", SHADER_PARAM_NOT_EDITABLE },
  78. { "$color", "color", SHADER_PARAM_TYPE_COLOR, "[1 1 1]", 0 },
  79. { "$alpha", "alpha", SHADER_PARAM_TYPE_FLOAT, "1.0", 0 },
  80. { "$basetexture", "Base Texture with lighting built in", SHADER_PARAM_TYPE_TEXTURE, "shadertest/BaseTexture", 0 },
  81. { "$frame", "Animation Frame", SHADER_PARAM_TYPE_INTEGER, "0", 0 },
  82. { "$basetexturetransform", "Base Texture Texcoord Transform",SHADER_PARAM_TYPE_MATRIX, "center .5 .5 scale 1 1 rotate 0 translate 0 0", 0 },
  83. { "$flashlighttexture", "flashlight spotlight shape texture", SHADER_PARAM_TYPE_TEXTURE, "effects/flashlight001", SHADER_PARAM_NOT_EDITABLE },
  84. { "$flashlighttextureframe", "Animation Frame for $flashlight", SHADER_PARAM_TYPE_INTEGER, "0", SHADER_PARAM_NOT_EDITABLE },
  85. { "$color2", "color2", SHADER_PARAM_TYPE_COLOR, "[1 1 1]", 0 },
  86. { "$srgbtint", "tint value to be applied when running on new-style srgb parts", SHADER_PARAM_TYPE_COLOR, "[1 1 1]", 0 },
  87. };
  88. //-----------------------------------------------------------------------------
  89. // Gets the standard shader parameter names
  90. // FIXME: Turn this into one function?
  91. //-----------------------------------------------------------------------------
  92. int CBaseShader::GetParamCount( ) const
  93. {
  94. return NUM_SHADER_MATERIAL_VARS;
  95. }
  96. const ShaderParamInfo_t &CBaseShader::GetParamInfo( int nParamIndex ) const
  97. {
  98. Assert( nParamIndex < NUM_SHADER_MATERIAL_VARS );
  99. return s_StandardParams[nParamIndex];
  100. }
  101. //-----------------------------------------------------------------------------
  102. // Necessary to snag ahold of some important data for the helper methods
  103. //-----------------------------------------------------------------------------
  104. void CBaseShader::InitShaderParams( IMaterialVar** ppParams, const char *pMaterialName )
  105. {
  106. // Re-entrancy check
  107. Assert( !s_ppParams );
  108. s_ppParams = ppParams;
  109. OnInitShaderParams( ppParams, pMaterialName );
  110. s_ppParams = NULL;
  111. }
  112. void CBaseShader::InitShaderInstance( IMaterialVar** ppParams, IShaderInit *pShaderInit, const char *pMaterialName, const char *pTextureGroupName )
  113. {
  114. // Re-entrancy check
  115. Assert( !s_ppParams );
  116. s_ppParams = ppParams;
  117. s_pShaderInit = pShaderInit;
  118. s_pTextureGroupName = pTextureGroupName;
  119. OnInitShaderInstance( ppParams, pShaderInit, pMaterialName );
  120. s_pTextureGroupName = NULL;
  121. s_ppParams = NULL;
  122. s_pShaderInit = NULL;
  123. }
  124. void CBaseShader::DrawElements( IMaterialVar **ppParams, int nModulationFlags,
  125. IShaderShadow* pShaderShadow, IShaderDynamicAPI* pShaderAPI, VertexCompressionType_t vertexCompression, CBasePerMaterialContextData **pContextDataPtr, CBasePerInstanceContextData** pInstanceDataPtr )
  126. {
  127. VPROF("CBaseShader::DrawElements");
  128. // Re-entrancy check
  129. Assert( !s_ppParams );
  130. s_ppParams = ppParams;
  131. s_pShaderAPI = pShaderAPI;
  132. s_pShaderShadow = pShaderShadow;
  133. s_nModulationFlags = nModulationFlags;
  134. s_pInstanceDataPtr = (CPerInstanceContextData**)( pInstanceDataPtr );
  135. s_nPassCount = 0;
  136. if ( IsSnapshotting() )
  137. {
  138. // Set up the shadow state
  139. SetInitialShadowState( );
  140. }
  141. OnDrawElements( ppParams, pShaderShadow, pShaderAPI, vertexCompression, pContextDataPtr );
  142. s_pInstanceDataPtr = NULL;
  143. s_nPassCount = 0;
  144. s_nModulationFlags = 0;
  145. s_ppParams = NULL;
  146. s_pShaderAPI = NULL;
  147. s_pShaderShadow = NULL;
  148. }
  149. //-----------------------------------------------------------------------------
  150. // Sets the default shadow state
  151. //-----------------------------------------------------------------------------
  152. void CBaseShader::SetInitialShadowState( )
  153. {
  154. // Set the default state
  155. s_pShaderShadow->SetDefaultState();
  156. // Init the standard states...
  157. int flags = s_ppParams[FLAGS]->GetIntValue();
  158. if (flags & MATERIAL_VAR_IGNOREZ)
  159. {
  160. s_pShaderShadow->EnableDepthTest( false );
  161. s_pShaderShadow->EnableDepthWrites( false );
  162. }
  163. if (flags & MATERIAL_VAR_DECAL)
  164. {
  165. s_pShaderShadow->EnablePolyOffset( SHADER_POLYOFFSET_DECAL );
  166. s_pShaderShadow->EnableDepthWrites( false );
  167. }
  168. if (flags & MATERIAL_VAR_NOCULL)
  169. {
  170. s_pShaderShadow->EnableCulling( false );
  171. }
  172. if (flags & MATERIAL_VAR_ZNEARER)
  173. {
  174. s_pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_NEARER );
  175. }
  176. if (flags & MATERIAL_VAR_WIREFRAME)
  177. {
  178. s_pShaderShadow->PolyMode( SHADER_POLYMODEFACE_FRONT_AND_BACK, SHADER_POLYMODE_LINE );
  179. }
  180. // Set alpha to coverage
  181. if (flags & MATERIAL_VAR_ALLOWALPHATOCOVERAGE)
  182. {
  183. // Force the bit on and then check against alpha blend and test states in CShaderShadowDX8::ComputeAggregateShadowState()
  184. s_pShaderShadow->EnableAlphaToCoverage( true );
  185. }
  186. }
  187. //-----------------------------------------------------------------------------
  188. // Draws a snapshot
  189. //-----------------------------------------------------------------------------
  190. void CBaseShader::Draw( bool bMakeActualDrawCall )
  191. {
  192. // You forgot to call PI_EndCommandBuffer
  193. Assert( !s_bBuildingInstanceCommandBuffer );
  194. if ( IsSnapshotting() )
  195. {
  196. // Turn off transparency if we're asked to....
  197. if (g_pConfig->bNoTransparency &&
  198. ((s_ppParams[FLAGS]->GetIntValue() & MATERIAL_VAR_NO_DEBUG_OVERRIDE) == 0))
  199. {
  200. s_pShaderShadow->EnableDepthWrites( true );
  201. s_pShaderShadow->EnableBlending( false );
  202. }
  203. GetShaderSystem()->TakeSnapshot();
  204. // Automagically add skinning + vertex lighting
  205. if ( !s_pInstanceDataPtr[s_nPassCount] )
  206. {
  207. bool bIsSkinning = CShader_IsFlag2Set( s_ppParams, MATERIAL_VAR2_SUPPORTS_HW_SKINNING );
  208. bool bIsVertexLit = CShader_IsFlag2Set( s_ppParams, MATERIAL_VAR2_LIGHTING_VERTEX_LIT );
  209. if ( bIsSkinning || bIsVertexLit )
  210. {
  211. PI_BeginCommandBuffer();
  212. // NOTE: EndCommandBuffer will insert the appropriate commands
  213. PI_EndCommandBuffer();
  214. }
  215. }
  216. }
  217. else
  218. {
  219. //SNPROF("CBaseShader::Draw");
  220. GetShaderSystem()->DrawSnapshot( s_pInstanceDataPtr[s_nPassCount] ?
  221. s_pInstanceDataPtr[s_nPassCount]->m_pCommandBuffer : NULL, bMakeActualDrawCall );
  222. }
  223. ++s_nPassCount;
  224. }
  225. //-----------------------------------------------------------------------------
  226. // Methods related to building per-instance command buffers
  227. //-----------------------------------------------------------------------------
  228. void CBaseShader::PI_BeginCommandBuffer()
  229. {
  230. // NOTE: This assertion is here because the memory allocation strategy
  231. // is perhaps not the best if this is used in dynamic states; we should
  232. // rethink in that case.
  233. Assert( IsSnapshotting() );
  234. Assert( !s_bBuildingInstanceCommandBuffer );
  235. s_bBuildingInstanceCommandBuffer = true;
  236. s_InstanceCommandBuffer.Reset();
  237. }
  238. void CBaseShader::PI_EndCommandBuffer()
  239. {
  240. Assert( s_bBuildingInstanceCommandBuffer );
  241. // Automagically add skinning
  242. if ( CShader_IsFlag2Set( s_ppParams, MATERIAL_VAR2_SUPPORTS_HW_SKINNING ) )
  243. {
  244. PI_SetSkinningMatrices();
  245. }
  246. if ( CShader_IsFlag2Set( s_ppParams, MATERIAL_VAR2_LIGHTING_VERTEX_LIT ) )
  247. {
  248. PI_SetVertexShaderLocalLighting();
  249. }
  250. s_bBuildingInstanceCommandBuffer = false;
  251. s_InstanceCommandBuffer.End();
  252. int nSize = s_InstanceCommandBuffer.Size();
  253. if ( nSize > 0 )
  254. {
  255. CPerInstanceContextData *pContextData = s_pInstanceDataPtr[ s_nPassCount ];
  256. if ( !pContextData )
  257. {
  258. pContextData = new CPerInstanceContextData;
  259. s_pInstanceDataPtr[ s_nPassCount ] = pContextData;
  260. }
  261. unsigned char *pBuf = pContextData->m_pCommandBuffer;
  262. if ( pContextData->m_nSize < nSize )
  263. {
  264. if ( pContextData->m_pCommandBuffer )
  265. {
  266. delete pContextData->m_pCommandBuffer;
  267. }
  268. pBuf = new unsigned char[nSize];
  269. pContextData->m_pCommandBuffer = pBuf;
  270. pContextData->m_nSize = nSize;
  271. }
  272. memcpy( pBuf, s_InstanceCommandBuffer.Base(), nSize );
  273. }
  274. }
  275. //-----------------------------------------------------------------------------
  276. // Queues commands onto the instance command buffer
  277. //-----------------------------------------------------------------------------
  278. void CBaseShader::PI_SetPixelShaderAmbientLightCube( int nFirstRegister )
  279. {
  280. Assert( s_bBuildingInstanceCommandBuffer );
  281. s_InstanceCommandBuffer.SetPixelShaderAmbientLightCube( nFirstRegister );
  282. }
  283. void CBaseShader::PI_SetPixelShaderLocalLighting( int nFirstRegister )
  284. {
  285. Assert( s_bBuildingInstanceCommandBuffer );
  286. s_InstanceCommandBuffer.SetPixelShaderLocalLighting( nFirstRegister );
  287. }
  288. void CBaseShader::PI_SetVertexShaderAmbientLightCube( /*int nFirstRegister*/ )
  289. {
  290. Assert( s_bBuildingInstanceCommandBuffer );
  291. s_InstanceCommandBuffer.SetVertexShaderAmbientLightCube( /*nFirstRegister*/ );
  292. }
  293. void CBaseShader::PI_SetVertexShaderLocalLighting()
  294. {
  295. Assert( s_bBuildingInstanceCommandBuffer );
  296. s_InstanceCommandBuffer.SetVertexShaderLocalLighting( );
  297. }
  298. void CBaseShader::PI_SetSkinningMatrices()
  299. {
  300. Assert( s_bBuildingInstanceCommandBuffer );
  301. s_InstanceCommandBuffer.SetSkinningMatrices();
  302. }
  303. void CBaseShader::PI_SetPixelShaderAmbientLightCubeLuminance( int nFirstRegister )
  304. {
  305. Assert( s_bBuildingInstanceCommandBuffer );
  306. s_InstanceCommandBuffer.SetPixelShaderAmbientLightCubeLuminance( nFirstRegister );
  307. }
  308. void CBaseShader::PI_SetPixelShaderGlintDamping( int nFirstRegister )
  309. {
  310. Assert( s_bBuildingInstanceCommandBuffer );
  311. s_InstanceCommandBuffer.SetPixelShaderGlintDamping( nFirstRegister );
  312. }
  313. void CBaseShader::PI_SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( int nRegister, float scale )
  314. {
  315. Assert( s_bBuildingInstanceCommandBuffer );
  316. Vector color2( 1.0f, 1.0f, 1.0f );
  317. ApplyColor2Factor( color2.Base(), true );
  318. s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState_LinearColorSpace_LinearScale( nRegister, color2, scale );
  319. }
  320. void CBaseShader::PI_SetModulationPixelShaderDynamicState_LinearScale( int nRegister, float scale )
  321. {
  322. Assert( s_bBuildingInstanceCommandBuffer );
  323. Vector color2( 1.0f, 1.0f, 1.0f );
  324. ApplyColor2Factor( color2.Base() );
  325. s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState_LinearScale( nRegister, color2, scale );
  326. }
  327. void CBaseShader::PI_SetModulationPixelShaderDynamicState_LinearScale_ScaleInW( int nRegister, float scale )
  328. {
  329. Assert( s_bBuildingInstanceCommandBuffer );
  330. Vector color2( 1.0f, 1.0f, 1.0f );
  331. ApplyColor2Factor( color2.Base() );
  332. s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState_LinearScale_ScaleInW( nRegister, color2, scale );
  333. }
  334. void CBaseShader::PI_SetModulationPixelShaderDynamicState_LinearColorSpace( int nRegister )
  335. {
  336. Assert( s_bBuildingInstanceCommandBuffer );
  337. Vector color2( 1.0f, 1.0f, 1.0f );
  338. ApplyColor2Factor( color2.Base(), true );
  339. s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState_LinearColorSpace( nRegister, color2 );
  340. }
  341. void CBaseShader::PI_SetModulationPixelShaderDynamicState( int nRegister )
  342. {
  343. Assert( s_bBuildingInstanceCommandBuffer );
  344. Vector color2( 1.0f, 1.0f, 1.0f );
  345. ApplyColor2Factor( color2.Base() );
  346. s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState( nRegister, color2 );
  347. }
  348. void CBaseShader::PI_SetModulationVertexShaderDynamicState()
  349. {
  350. Assert( s_bBuildingInstanceCommandBuffer );
  351. Vector color2( 1.0f, 1.0f, 1.0f );
  352. ApplyColor2Factor( color2.Base() );
  353. s_InstanceCommandBuffer.SetModulationVertexShaderDynamicState( VERTEX_SHADER_MODULATION_COLOR, color2 );
  354. }
  355. void CBaseShader::PI_SetModulationVertexShaderDynamicState_LinearScale( float flScale )
  356. {
  357. Assert( s_bBuildingInstanceCommandBuffer );
  358. Vector color2( 1.0f, 1.0f, 1.0f );
  359. ApplyColor2Factor( color2.Base() );
  360. s_InstanceCommandBuffer.SetModulationVertexShaderDynamicState_LinearScale( VERTEX_SHADER_MODULATION_COLOR, color2, flScale );
  361. }
  362. void CBaseShader::PI_SetModulationPixelShaderDynamicState_Identity( int nRegister )
  363. {
  364. Assert( s_bBuildingInstanceCommandBuffer );
  365. s_InstanceCommandBuffer.SetModulationPixelShaderDynamicState_Identity( nRegister );
  366. }
  367. //-----------------------------------------------------------------------------
  368. // Finds a particular parameter (works because the lowest parameters match the shader)
  369. //-----------------------------------------------------------------------------
  370. int CBaseShader::FindParamIndex( const char *pName ) const
  371. {
  372. int numParams = GetParamCount();
  373. for( int i = 0; i < numParams; i++ )
  374. {
  375. if( Q_strnicmp( GetParamInfo( i ).m_pName, pName, 64 ) == 0 )
  376. {
  377. return i;
  378. }
  379. }
  380. return -1;
  381. }
  382. //-----------------------------------------------------------------------------
  383. // Are we using graphics?
  384. //-----------------------------------------------------------------------------
  385. bool CBaseShader::IsUsingGraphics()
  386. {
  387. return GetShaderSystem()->IsUsingGraphics();
  388. }
  389. //-----------------------------------------------------------------------------
  390. // Are we using graphics?
  391. //-----------------------------------------------------------------------------
  392. bool CBaseShader::CanUseEditorMaterials() const
  393. {
  394. return GetShaderSystem()->CanUseEditorMaterials();
  395. }
  396. //-----------------------------------------------------------------------------
  397. // Loads a texture
  398. //-----------------------------------------------------------------------------
  399. void CBaseShader::LoadTexture( int nTextureVar, int nAdditionalCreationFlags /* = 0 */ )
  400. {
  401. if ((!s_ppParams) || (nTextureVar == -1))
  402. return;
  403. IMaterialVar* pNameVar = s_ppParams[nTextureVar];
  404. if( pNameVar && pNameVar->IsDefined() )
  405. {
  406. s_pShaderInit->LoadTexture( pNameVar, s_pTextureGroupName, nAdditionalCreationFlags );
  407. }
  408. }
  409. //-----------------------------------------------------------------------------
  410. // Loads a bumpmap
  411. //-----------------------------------------------------------------------------
  412. void CBaseShader::LoadBumpMap( int nTextureVar, int nAdditionalCreationFlags )
  413. {
  414. if ((!s_ppParams) || (nTextureVar == -1))
  415. return;
  416. IMaterialVar* pNameVar = s_ppParams[nTextureVar];
  417. if( pNameVar && pNameVar->IsDefined() )
  418. {
  419. s_pShaderInit->LoadBumpMap( pNameVar, s_pTextureGroupName, nAdditionalCreationFlags );
  420. }
  421. }
  422. //-----------------------------------------------------------------------------
  423. // Loads a cubemap
  424. //-----------------------------------------------------------------------------
  425. void CBaseShader::LoadCubeMap( int nTextureVar, int nAdditionalCreationFlags /* = 0 */ )
  426. {
  427. if ((!s_ppParams) || (nTextureVar == -1))
  428. return;
  429. IMaterialVar* pNameVar = s_ppParams[nTextureVar];
  430. if( pNameVar && pNameVar->IsDefined() )
  431. {
  432. s_pShaderInit->LoadCubeMap( s_ppParams, pNameVar, nAdditionalCreationFlags );
  433. }
  434. }
  435. ShaderAPITextureHandle_t CBaseShader::GetShaderAPITextureBindHandle( int nTextureVar, int nFrameVar, int nTextureChannel )
  436. {
  437. Assert( !IsSnapshotting() );
  438. Assert( nTextureVar != -1 );
  439. Assert ( s_ppParams );
  440. IMaterialVar* pTextureVar = s_ppParams[nTextureVar];
  441. IMaterialVar* pFrameVar = (nFrameVar != -1) ? s_ppParams[nFrameVar] : NULL;
  442. int nFrame = pFrameVar ? pFrameVar->GetIntValue() : 0;
  443. return GetShaderSystem()->GetShaderAPITextureBindHandle( pTextureVar->GetTextureValue(), nFrame, nTextureChannel );
  444. }
  445. void CBaseShader::BindVertexTexture( VertexTextureSampler_t vtSampler, int nTextureVar, int nFrame /* = 0 */)
  446. {
  447. Assert( !IsSnapshotting() );
  448. IMaterialVar* pTextureVar = s_ppParams[nTextureVar];
  449. if ( !pTextureVar )
  450. return;
  451. GetShaderSystem()->BindVertexTexture( vtSampler, pTextureVar->GetTextureValue() );
  452. }
  453. ShaderAPITextureHandle_t CBaseShader::GetShaderAPITextureBindHandle( ITexture *pTexture, int nFrame, int nTextureChannel )
  454. {
  455. return GetShaderSystem()->GetShaderAPITextureBindHandle( pTexture, nFrame, nTextureChannel );
  456. }
  457. //-----------------------------------------------------------------------------
  458. // Four different flavors of BindTexture(), handling the two-sampler
  459. // case as well as ITexture* versus textureVar forms
  460. //-----------------------------------------------------------------------------
  461. void CBaseShader::BindTexture( Sampler_t sampler1, TextureBindFlags_t nBindFlags, int nTextureVar, int nFrameVar /* = -1 */ )
  462. {
  463. BindTexture( sampler1, SHADER_SAMPLER_INVALID, nBindFlags, nTextureVar, nFrameVar );
  464. }
  465. void CBaseShader::BindTexture( Sampler_t sampler1, Sampler_t sampler2, TextureBindFlags_t nBindFlags, int nTextureVar, int nFrameVar /* = -1 */ )
  466. {
  467. Assert( !IsSnapshotting() );
  468. Assert( nTextureVar != -1 );
  469. Assert ( s_ppParams );
  470. IMaterialVar* pTextureVar = s_ppParams[nTextureVar];
  471. IMaterialVar* pFrameVar = (nFrameVar != -1) ? s_ppParams[nFrameVar] : NULL;
  472. if (pTextureVar)
  473. {
  474. int nFrame = pFrameVar ? pFrameVar->GetIntValue() : 0;
  475. if ( sampler2 == -1 )
  476. {
  477. GetShaderSystem()->BindTexture( sampler1, nBindFlags, pTextureVar->GetTextureValue(), nFrame );
  478. }
  479. else
  480. {
  481. GetShaderSystem()->BindTexture( sampler1, sampler2, nBindFlags, pTextureVar->GetTextureValue(), nFrame );
  482. }
  483. }
  484. }
  485. void CBaseShader::BindTexture( Sampler_t sampler1, TextureBindFlags_t nBindFlags, ITexture *pTexture, int nFrame /* = 0 */ )
  486. {
  487. BindTexture( sampler1, SHADER_SAMPLER_INVALID, nBindFlags, pTexture, nFrame );
  488. }
  489. void CBaseShader::BindTexture( Sampler_t sampler1, Sampler_t sampler2, TextureBindFlags_t nBindFlags, ITexture *pTexture, int nFrame /* = 0 */ )
  490. {
  491. Assert( !IsSnapshotting() );
  492. if ( sampler2 == -1 )
  493. {
  494. GetShaderSystem()->BindTexture( sampler1, nBindFlags, pTexture, nFrame );
  495. }
  496. else
  497. {
  498. GetShaderSystem()->BindTexture( sampler1, sampler2, nBindFlags, pTexture, nFrame );
  499. }
  500. }
  501. //-----------------------------------------------------------------------------
  502. // Does the texture store translucency in its alpha channel?
  503. //-----------------------------------------------------------------------------
  504. bool CBaseShader::TextureIsTranslucent( int textureVar, bool isBaseTexture )
  505. {
  506. if (textureVar < 0)
  507. return false;
  508. IMaterialVar** params = s_ppParams;
  509. if (params[textureVar]->GetType() == MATERIAL_VAR_TYPE_TEXTURE)
  510. {
  511. if (!isBaseTexture)
  512. {
  513. return params[textureVar]->GetTextureValue()->IsTranslucent();
  514. }
  515. else
  516. {
  517. // Override translucency settings if this flag is set.
  518. if (IS_FLAG_SET(MATERIAL_VAR_OPAQUETEXTURE))
  519. return false;
  520. bool bHasSelfIllum = ( ( CurrentMaterialVarFlags() & MATERIAL_VAR_SELFILLUM ) != 0 );
  521. bool bHasSelfIllumMask = ( ( CurrentMaterialVarFlags2() & MATERIAL_VAR2_SELFILLUMMASK ) != 0 );
  522. bool bHasBaseAlphaEnvmapMask = ( ( CurrentMaterialVarFlags() & MATERIAL_VAR_BASEALPHAENVMAPMASK ) != 0 );
  523. bool bUsingBaseTextureAlphaForSelfIllum = bHasSelfIllum && !bHasSelfIllumMask;
  524. // Check if we are using base texture alpha for something other than translucency.
  525. if ( !bUsingBaseTextureAlphaForSelfIllum && !bHasBaseAlphaEnvmapMask )
  526. {
  527. // We aren't using base alpha for anything other than trancluceny.
  528. // check if the material is marked as translucent or alpha test.
  529. if ((CurrentMaterialVarFlags() & MATERIAL_VAR_TRANSLUCENT) ||
  530. (CurrentMaterialVarFlags() & MATERIAL_VAR_ALPHATEST))
  531. {
  532. // Make sure the texture has an alpha channel.
  533. return params[textureVar]->GetTextureValue()->IsTranslucent();
  534. }
  535. }
  536. }
  537. }
  538. return false;
  539. }
  540. //-----------------------------------------------------------------------------
  541. //
  542. // Helper methods for color modulation
  543. //
  544. //-----------------------------------------------------------------------------
  545. //-----------------------------------------------------------------------------
  546. // Are we alpha or color modulating?
  547. //-----------------------------------------------------------------------------
  548. bool CBaseShader::IsAlphaModulating()
  549. {
  550. return (s_nModulationFlags & SHADER_USING_ALPHA_MODULATION) != 0;
  551. }
  552. //-----------------------------------------------------------------------------
  553. // FIXME: Figure out a better way to do this?
  554. //-----------------------------------------------------------------------------
  555. int CBaseShader::ComputeModulationFlags( IMaterialVar** params, IShaderDynamicAPI* pShaderAPI )
  556. {
  557. s_pShaderAPI = pShaderAPI;
  558. int mod = 0;
  559. if ( UsingFlashlight(params) )
  560. {
  561. mod |= SHADER_USING_FLASHLIGHT;
  562. }
  563. if ( UsingEditor(params) )
  564. {
  565. mod |= SHADER_USING_EDITOR;
  566. }
  567. if ( IsRenderingPaint(params) )
  568. {
  569. mod |= SHADER_USING_PAINT;
  570. }
  571. if ( IsSnapshotting() )
  572. {
  573. if ( IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) )
  574. mod |= SHADER_USING_GBUFFER0;
  575. if ( IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 ) )
  576. mod |= SHADER_USING_GBUFFER1;
  577. }
  578. else
  579. {
  580. int nFixedLightingMode = ShaderApiFast( pShaderAPI )->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING );
  581. if ( nFixedLightingMode & 1 )
  582. mod |= SHADER_USING_GBUFFER0;
  583. if ( nFixedLightingMode & 2 )
  584. mod |= SHADER_USING_GBUFFER1;
  585. }
  586. s_pShaderAPI = NULL;
  587. return mod;
  588. }
  589. //-----------------------------------------------------------------------------
  590. //
  591. //-----------------------------------------------------------------------------
  592. bool CBaseShader::NeedsPowerOfTwoFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const
  593. {
  594. return CShader_IsFlag2Set( params, MATERIAL_VAR2_NEEDS_POWER_OF_TWO_FRAME_BUFFER_TEXTURE );
  595. }
  596. //-----------------------------------------------------------------------------
  597. //
  598. //-----------------------------------------------------------------------------
  599. bool CBaseShader::NeedsFullFrameBufferTexture( IMaterialVar **params, bool bCheckSpecificToThisFrame ) const
  600. {
  601. return CShader_IsFlag2Set( params, MATERIAL_VAR2_NEEDS_FULL_FRAME_BUFFER_TEXTURE );
  602. }
  603. //-----------------------------------------------------------------------------
  604. //
  605. //-----------------------------------------------------------------------------
  606. bool CBaseShader::IsTranslucent( IMaterialVar **params ) const
  607. {
  608. return IS_FLAG_SET( MATERIAL_VAR_TRANSLUCENT );
  609. }
  610. //-----------------------------------------------------------------------------
  611. // Returns the translucency...
  612. //-----------------------------------------------------------------------------
  613. void CBaseShader::ApplyColor2Factor( float *pColorOut, bool isLinearSpace ) const // (*pColorOut) *= COLOR2
  614. {
  615. if ( !g_pConfig->bShowDiffuse )
  616. {
  617. pColorOut[0] = pColorOut[1] = pColorOut[2] = 0.0f;
  618. return;
  619. }
  620. IMaterialVar* pColor2Var = s_ppParams[COLOR2];
  621. if ( pColor2Var->GetType() == MATERIAL_VAR_TYPE_VECTOR )
  622. {
  623. float flColor2[3];
  624. pColor2Var->GetVecValue( flColor2, 3 );
  625. pColorOut[0] *= flColor2[0];
  626. pColorOut[1] *= flColor2[1];
  627. pColorOut[2] *= flColor2[2];
  628. }
  629. #ifndef _PS3
  630. if ( g_pHardwareConfig->UsesSRGBCorrectBlending() )
  631. {
  632. IMaterialVar* pSRGBVar = s_ppParams[SRGBTINT];
  633. if (pSRGBVar->GetType() == MATERIAL_VAR_TYPE_VECTOR)
  634. {
  635. float flSRGB[3];
  636. pSRGBVar->GetVecValue( flSRGB, 3 );
  637. if ( isLinearSpace )
  638. {
  639. pColorOut[0] *= flSRGB[0];
  640. pColorOut[1] *= flSRGB[1];
  641. pColorOut[2] *= flSRGB[2];
  642. }
  643. else
  644. {
  645. pColorOut[0] *= GammaToLinearFullRange( flSRGB[0] );
  646. pColorOut[1] *= GammaToLinearFullRange( flSRGB[1] );
  647. pColorOut[2] *= GammaToLinearFullRange( flSRGB[2] );
  648. }
  649. }
  650. }
  651. #endif
  652. }
  653. //-----------------------------------------------------------------------------
  654. //
  655. // Helper methods for alpha blending....
  656. //
  657. //-----------------------------------------------------------------------------
  658. void CBaseShader::EnableAlphaBlending( ShaderBlendFactor_t src, ShaderBlendFactor_t dst )
  659. {
  660. Assert( IsSnapshotting() );
  661. s_pShaderShadow->EnableBlending( true );
  662. s_pShaderShadow->BlendFunc( src, dst );
  663. s_pShaderShadow->EnableDepthWrites(false);
  664. }
  665. void CBaseShader::DisableAlphaBlending()
  666. {
  667. Assert( IsSnapshotting() );
  668. s_pShaderShadow->EnableBlending( false );
  669. }
  670. void CBaseShader::SetNormalBlendingShadowState( int textureVar, bool isBaseTexture )
  671. {
  672. Assert( IsSnapshotting() );
  673. // Either we've got a constant modulation
  674. bool isTranslucent = IsAlphaModulating();
  675. // Or we've got a vertex alpha
  676. isTranslucent = isTranslucent || (CurrentMaterialVarFlags() & MATERIAL_VAR_VERTEXALPHA);
  677. // Or we've got a texture alpha
  678. isTranslucent = isTranslucent || ( TextureIsTranslucent( textureVar, isBaseTexture ) &&
  679. !(CurrentMaterialVarFlags() & MATERIAL_VAR_ALPHATEST ) );
  680. if (isTranslucent)
  681. {
  682. EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA );
  683. }
  684. else
  685. {
  686. DisableAlphaBlending();
  687. }
  688. }
  689. //ConVar mat_debug_flashlight_only( "mat_debug_flashlight_only", "0" );
  690. void CBaseShader::SetAdditiveBlendingShadowState( int textureVar, bool isBaseTexture )
  691. {
  692. Assert( IsSnapshotting() );
  693. // Either we've got a constant modulation
  694. bool isTranslucent = IsAlphaModulating();
  695. // Or we've got a vertex alpha
  696. isTranslucent = isTranslucent || (CurrentMaterialVarFlags() & MATERIAL_VAR_VERTEXALPHA);
  697. // Or we've got a texture alpha
  698. isTranslucent = isTranslucent || ( TextureIsTranslucent( textureVar, isBaseTexture ) &&
  699. !(CurrentMaterialVarFlags() & MATERIAL_VAR_ALPHATEST ) );
  700. /*
  701. if ( mat_debug_flashlight_only.GetBool() )
  702. {
  703. if (isTranslucent)
  704. {
  705. EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA);
  706. //s_pShaderShadow->EnableAlphaTest( true );
  707. //s_pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GREATER, 0.99f );
  708. }
  709. else
  710. {
  711. EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ZERO);
  712. }
  713. }
  714. else
  715. */
  716. {
  717. if (isTranslucent)
  718. {
  719. EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE );
  720. }
  721. else
  722. {
  723. EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE );
  724. }
  725. }
  726. }
  727. void CBaseShader::SetDefaultBlendingShadowState( int textureVar, bool isBaseTexture )
  728. {
  729. if ( CurrentMaterialVarFlags() & MATERIAL_VAR_ADDITIVE )
  730. {
  731. SetAdditiveBlendingShadowState( textureVar, isBaseTexture );
  732. }
  733. else
  734. {
  735. SetNormalBlendingShadowState( textureVar, isBaseTexture );
  736. }
  737. }
  738. void CBaseShader::SetBlendingShadowState( BlendType_t nMode )
  739. {
  740. switch ( nMode )
  741. {
  742. case BT_NONE:
  743. DisableAlphaBlending();
  744. break;
  745. case BT_BLEND:
  746. EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE_MINUS_SRC_ALPHA );
  747. break;
  748. case BT_ADD:
  749. EnableAlphaBlending( SHADER_BLEND_ONE, SHADER_BLEND_ONE );
  750. break;
  751. case BT_BLENDADD:
  752. EnableAlphaBlending( SHADER_BLEND_SRC_ALPHA, SHADER_BLEND_ONE );
  753. break;
  754. }
  755. }
  756. //-----------------------------------------------------------------------------
  757. // Sets lightmap blending mode for single texturing
  758. //-----------------------------------------------------------------------------
  759. void CBaseShader::SingleTextureLightmapBlendMode( )
  760. {
  761. Assert( IsSnapshotting() );
  762. s_pShaderShadow->EnableBlending( true );
  763. s_pShaderShadow->BlendFunc( SHADER_BLEND_DST_COLOR, SHADER_BLEND_SRC_COLOR );
  764. }
  765. FORCEINLINE void CBaseShader::SetFogMode( ShaderFogMode_t fogMode )
  766. {
  767. bool bVertexFog = ((CurrentMaterialVarFlags() & MATERIAL_VAR_VERTEXFOG) != 0);
  768. if (( CurrentMaterialVarFlags() & MATERIAL_VAR_NOFOG ) == 0)
  769. {
  770. s_pShaderShadow->FogMode( fogMode, bVertexFog );
  771. }
  772. else
  773. {
  774. s_pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED, bVertexFog );
  775. }
  776. }
  777. //-----------------------------------------------------------------------------
  778. //
  779. // Helper methods for fog
  780. //
  781. //-----------------------------------------------------------------------------
  782. void CBaseShader::FogToOOOverbright( void )
  783. {
  784. Assert( IsSnapshotting() );
  785. SetFogMode( SHADER_FOGMODE_OO_OVERBRIGHT );
  786. }
  787. void CBaseShader::FogToWhite( void )
  788. {
  789. Assert( IsSnapshotting() );
  790. SetFogMode( SHADER_FOGMODE_WHITE );
  791. }
  792. void CBaseShader::FogToBlack( void )
  793. {
  794. Assert( IsSnapshotting() );
  795. SetFogMode( SHADER_FOGMODE_BLACK );
  796. }
  797. void CBaseShader::FogToGrey( void )
  798. {
  799. Assert( IsSnapshotting() );
  800. SetFogMode( SHADER_FOGMODE_GREY );
  801. }
  802. void CBaseShader::FogToFogColor( void )
  803. {
  804. Assert( IsSnapshotting() );
  805. SetFogMode( SHADER_FOGMODE_FOGCOLOR );
  806. }
  807. void CBaseShader::DisableFog( void )
  808. {
  809. Assert( IsSnapshotting() );
  810. s_pShaderShadow->FogMode( SHADER_FOGMODE_DISABLED, false );
  811. }
  812. void CBaseShader::DefaultFog( void )
  813. {
  814. if ( CurrentMaterialVarFlags() & MATERIAL_VAR_ADDITIVE )
  815. {
  816. FogToBlack();
  817. }
  818. else
  819. {
  820. FogToFogColor();
  821. }
  822. }
  823. bool CBaseShader::UsingFlashlight( IMaterialVar **params ) const
  824. {
  825. if( IsSnapshotting() )
  826. {
  827. return CShader_IsFlag2Set( params, MATERIAL_VAR2_USE_FLASHLIGHT );
  828. }
  829. else
  830. {
  831. return s_pShaderAPI->InFlashlightMode();
  832. }
  833. }
  834. bool CBaseShader::UsingEditor( IMaterialVar **params ) const
  835. {
  836. if( IsSnapshotting() )
  837. {
  838. return CShader_IsFlag2Set( params, MATERIAL_VAR2_USE_EDITOR );
  839. }
  840. else
  841. {
  842. return s_pShaderAPI->InEditorMode();
  843. }
  844. }
  845. bool CBaseShader::IsRenderingPaint( IMaterialVar **params ) const
  846. {
  847. if( IsSnapshotting() )
  848. {
  849. // NOTE: This only works because IsRenderingPaint
  850. // really only affects lightmappedgeneric in a specific way.
  851. // If we make it used more generally, then we'll need a pattern
  852. // more similar to UsingEditor or UsingFlashlight
  853. return CShader_IsFlag2Set( params, MATERIAL_VAR2_USE_PAINT );
  854. }
  855. else
  856. {
  857. if ( !g_pConfig->m_bPaintInGame || !g_pConfig->m_bPaintInMap )
  858. return false;
  859. return s_pShaderAPI->IsRenderingPaint();
  860. }
  861. }
  862. bool CBaseShader::IsHDREnabled( void )
  863. {
  864. #ifdef _PS3
  865. return true;
  866. #else
  867. // HDRFIXME! Need to fix this for vgui materials
  868. HDRType_t hdr_mode = g_pHardwareConfig->GetHDRType();
  869. return ( hdr_mode == HDR_TYPE_INTEGER ) || ( hdr_mode == HDR_TYPE_FLOAT );
  870. #endif
  871. }