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.

1313 lines
58 KiB

  1. //===== Copyright � 1996-2008, Valve Corporation, All rights reserved. ======//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #include "BaseVSShader.h"
  9. #include "phong_dx9_helper.h"
  10. #include "convar.h"
  11. #include "cpp_shader_constant_register_map.h"
  12. #include "phong_vs20.inc"
  13. #include "phong_ps20b.inc"
  14. #include "shaderlib/commandbuilder.h"
  15. #include "tier0/vprof.h"
  16. #if !defined( _X360 ) && !defined( _PS3 )
  17. #include "phong_vs30.inc"
  18. #include "phong_ps30.inc"
  19. #endif
  20. #include "shaderapifast.h"
  21. // memdbgon must be the last include file in a .cpp file!!!
  22. #include "tier0/memdbgon.h"
  23. static ConVar mat_displacementmap( "mat_displacementmap", "1", FCVAR_CHEAT );
  24. static ConVar r_lightwarpidentity( "r_lightwarpidentity", "0", FCVAR_CHEAT );
  25. static ConVar r_rimlight( "r_rimlight", "1", FCVAR_CHEAT );
  26. static ConVar cl_teamid_min( "cl_teamid_min", "200" );
  27. static ConVar cl_teamid_max( "cl_teamid_max", "1000" );
  28. #if defined( CSTRIKE15 ) && defined( _X360 )
  29. static ConVar r_shader_srgbread( "r_shader_srgbread", "1", 0, "1 = use shader srgb texture reads, 0 = use HW" );
  30. #else
  31. static ConVar r_shader_srgbread( "r_shader_srgbread", "0", 0, "1 = use shader srgb texture reads, 0 = use HW" );
  32. #endif
  33. static ConVar r_csm_viewmodelquality( "r_csm_viewmodelquality", "1" );
  34. // Textures may be bound to the following samplers:
  35. // SHADER_SAMPLER0 Base (Albedo) / Gloss in alpha
  36. // SHADER_SAMPLER1 Specular warp (including iridescence)
  37. // SHADER_SAMPLER2 Diffuse Lighting warp texture
  38. // SHADER_SAMPLER3 Normal Map
  39. // SHADER_SAMPLER4 Flashlight Shadow Depth Map
  40. // SHADER_SAMPLER5 Normalization cube map
  41. // SHADER_SAMPLER6 Flashlight Cookie
  42. // SHADER_SAMPLER7 Specular exponent
  43. // SHADER_SAMPLER8 Cubic environment map
  44. // SHADER_SAMPLER9 Compressed wrinklemap
  45. // SHADER_SAMPLER10 Stretched wrinklemap
  46. // SHADER_SAMPLER11 Compressed wrinkle normal map
  47. // SHADER_SAMPLER12 Stretched wrinkle normal map
  48. // SHADER_SAMPLER13 Detail texture
  49. // SHADER_SAMPLER14 Separate self illumination mask
  50. // SHADER_SAMPLER15 Screen space ambient occlusion texture (on PC only)
  51. //-----------------------------------------------------------------------------
  52. // Initialize shader parameters
  53. //-----------------------------------------------------------------------------
  54. void InitParamsPhong_DX9( CBaseVSShader *pShader, IMaterialVar** params, const char *pMaterialName, VertexLitGeneric_DX9_Vars_t &info )
  55. {
  56. // FLASHLIGHTFIXME: Do ShaderAPI::BindFlashlightTexture
  57. Assert( info.m_nFlashlightTexture >= 0 );
  58. params[FLASHLIGHTTEXTURE]->SetStringValue( GetFlashlightTextureFilename() );
  59. // Write over $basetexture with $info.m_nBumpmap if we are going to be using diffuse normal mapping.
  60. if( info.m_nAlbedo != -1 && g_pConfig->UseBumpmapping() && info.m_nBumpmap != -1 && params[info.m_nBumpmap]->IsDefined() && params[info.m_nAlbedo]->IsDefined() &&
  61. params[info.m_nBaseTexture]->IsDefined() )
  62. {
  63. params[info.m_nBaseTexture]->SetStringValue( params[info.m_nAlbedo]->GetStringValue() );
  64. }
  65. // This shader can be used with hw skinning
  66. SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_HW_SKINNING );
  67. SET_FLAGS2( MATERIAL_VAR2_LIGHTING_VERTEX_LIT );
  68. // No texture means no env mask in base alpha
  69. if ( !params[info.m_nBaseTexture]->IsDefined() )
  70. {
  71. CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK );
  72. }
  73. // If in decal mode, no debug override...
  74. if (IS_FLAG_SET(MATERIAL_VAR_DECAL))
  75. {
  76. SET_FLAGS( MATERIAL_VAR_NO_DEBUG_OVERRIDE );
  77. }
  78. // We always specify we're using user data, therefore we always need tangent spaces
  79. SET_FLAGS2( MATERIAL_VAR2_NEEDS_TANGENT_SPACES );
  80. bool bBump = (info.m_nBumpmap != -1) && g_pConfig->UseBumpmapping() && params[info.m_nBumpmap]->IsDefined();
  81. bool bEnvMap = (info.m_nEnvmap != -1) && params[info.m_nEnvmap]->IsDefined();
  82. bool bDiffuseWarp = (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined();
  83. bool bPhong = (info.m_nPhong != -1) && params[info.m_nPhong]->IsDefined();
  84. if( !bBump && !bEnvMap && !bDiffuseWarp && !bPhong )
  85. {
  86. CLEAR_FLAGS( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK );
  87. }
  88. if ( ( info.m_nSelfIllumFresnelMinMaxExp != -1 ) && ( !params[info.m_nSelfIllumFresnelMinMaxExp]->IsDefined() ) )
  89. {
  90. params[info.m_nSelfIllumFresnelMinMaxExp]->SetVecValue( 0.0f, 1.0f, 1.0f );
  91. }
  92. InitFloatParam( info.m_nEnvmapFresnel, params, 0.0f );
  93. InitFloatParam( info.m_nAmbientOcclusion, params, 0.0f );
  94. InitFloatParam( info.m_nDisplacementWrinkleMap, params, 0.0f );
  95. InitIntParam( info.m_nSelfIllumFresnel, params, 0 );
  96. InitIntParam( info.m_nBaseMapAlphaPhongMask, params, 0 );
  97. InitIntParam( info.m_nBaseMapLuminancePhongMask, params, 0 );
  98. #if defined ( CSTRIKE15 )
  99. InitIntParam( info.m_nShaderSrgbRead360, params, 1 );
  100. #else
  101. InitIntParam( info.m_nShaderSrgbRead360, params, 0 );
  102. #endif
  103. InitIntParam( info.m_nAllowDiffuseModulation, params, 1 );
  104. InitIntParam( info.m_nPhongDisableHalfLambert, params, 0 );
  105. InitIntParam( info.m_nSelfIllumFresnelEnabledThisFrame, params, 0 );
  106. }
  107. //-----------------------------------------------------------------------------
  108. // Initialize shader
  109. //-----------------------------------------------------------------------------
  110. void InitPhong_DX9( CBaseVSShader *pShader, IMaterialVar** params, VertexLitGeneric_DX9_Vars_t &info )
  111. {
  112. Assert( info.m_nFlashlightTexture >= 0 );
  113. pShader->LoadTexture( info.m_nFlashlightTexture, TEXTUREFLAGS_SRGB );
  114. static ConVarRef r_staticlight_mode( "r_staticlight_mode" );
  115. bool bIsBaseTextureTranslucent = false;
  116. if ( params[info.m_nBaseTexture]->IsDefined() )
  117. {
  118. pShader->LoadTexture( info.m_nBaseTexture, TEXTUREFLAGS_SRGB | ANISOTROPIC_OVERRIDE );
  119. if ( params[info.m_nBaseTexture]->GetTextureValue()->IsTranslucent() )
  120. {
  121. bIsBaseTextureTranslucent = true;
  122. }
  123. if ( ( info.m_nWrinkle != -1 ) && ( info.m_nStretch != -1 ) &&
  124. params[info.m_nWrinkle]->IsDefined() && params[info.m_nStretch]->IsDefined() )
  125. {
  126. pShader->LoadTexture( info.m_nWrinkle, TEXTUREFLAGS_SRGB | ANISOTROPIC_OVERRIDE );
  127. pShader->LoadTexture( info.m_nStretch, TEXTUREFLAGS_SRGB | ANISOTROPIC_OVERRIDE );
  128. }
  129. }
  130. bool bHasSelfIllumMask = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) && IS_FLAG2_SET( MATERIAL_VAR2_SELFILLUMMASK );
  131. // No alpha channel in any of the textures? No self illum or envmapmask
  132. if ( !bIsBaseTextureTranslucent )
  133. {
  134. bool bHasSelfIllumFresnel = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) && ( info.m_nSelfIllumFresnel != -1 ) && ( params[info.m_nSelfIllumFresnel]->GetIntValue() != 0 );
  135. // Can still be self illum with no base alpha if using one of these alternate modes
  136. if ( !bHasSelfIllumFresnel && !bHasSelfIllumMask )
  137. {
  138. CLEAR_FLAGS( MATERIAL_VAR_SELFILLUM );
  139. }
  140. CLEAR_FLAGS( MATERIAL_VAR_BASEALPHAENVMAPMASK );
  141. }
  142. if ( (info.m_nPhongExponentTexture != -1) && params[info.m_nPhongExponentTexture]->IsDefined() &&
  143. (info.m_nPhong != -1) && params[info.m_nPhong]->IsDefined() )
  144. {
  145. pShader->LoadTexture( info.m_nPhongExponentTexture );
  146. }
  147. if ( (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsDefined() &&
  148. (info.m_nPhong != -1) && params[info.m_nPhong]->IsDefined() )
  149. {
  150. pShader->LoadTexture( info.m_nDiffuseWarpTexture );
  151. }
  152. if ( (info.m_nPhongWarpTexture != -1) && params[info.m_nPhongWarpTexture]->IsDefined() &&
  153. (info.m_nPhong != -1) && params[info.m_nPhong]->IsDefined() )
  154. {
  155. pShader->LoadTexture( info.m_nPhongWarpTexture );
  156. }
  157. if ( info.m_nDetail != -1 && params[info.m_nDetail]->IsDefined() )
  158. {
  159. int nDetailBlendMode = ( info.m_nDetailTextureCombineMode == -1 ) ? 0 : params[info.m_nDetailTextureCombineMode]->GetIntValue();
  160. pShader->LoadTexture( info.m_nDetail, IsSRGBDetailTexture( nDetailBlendMode ) ? TEXTUREFLAGS_SRGB : 0 ); // SRGB if non-Mod2X
  161. }
  162. if ( g_pConfig->UseBumpmapping() )
  163. {
  164. if ( (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsDefined() )
  165. {
  166. pShader->LoadBumpMap( info.m_nBumpmap, ANISOTROPIC_OVERRIDE );
  167. SET_FLAGS2( MATERIAL_VAR2_DIFFUSE_BUMPMAPPED_MODEL );
  168. if ( ( info.m_nNormalWrinkle != -1 ) && ( info.m_nNormalStretch != -1 ) &&
  169. params[info.m_nNormalWrinkle]->IsDefined() && params[info.m_nNormalStretch]->IsDefined() )
  170. {
  171. pShader->LoadTexture( info.m_nNormalWrinkle, ANISOTROPIC_OVERRIDE );
  172. pShader->LoadTexture( info.m_nNormalStretch, ANISOTROPIC_OVERRIDE );
  173. }
  174. }
  175. }
  176. if ( params[info.m_nEnvmap]->IsDefined() )
  177. {
  178. pShader->LoadCubeMap( info.m_nEnvmap, ( g_pHardwareConfig->GetHDRType() == HDR_TYPE_NONE ? TEXTUREFLAGS_SRGB : 0 ) | ANISOTROPIC_OVERRIDE );
  179. }
  180. if ( bHasSelfIllumMask )
  181. {
  182. pShader->LoadTexture( info.m_nSelfIllumMask );
  183. }
  184. if ( params[info.m_nDisplacementMap]->IsDefined() )
  185. {
  186. pShader->LoadTexture( info.m_nDisplacementMap );
  187. }
  188. if ( (info.m_nDecalTexture != -1) && params[info.m_nDecalTexture]->IsDefined() )
  189. {
  190. int nDecalBlendMode = (info.m_nDecalTextureCombineMode == -1) ? 0 : params[info.m_nDecalTextureCombineMode]->GetIntValue();
  191. pShader->LoadTexture( info.m_nDecalTexture, IsSRGBDecalTexture( nDecalBlendMode ) ? TEXTUREFLAGS_SRGB : 0 ); // SRGB if non-Mod2X
  192. }
  193. if ( (info.m_nTintMaskTexture != -1) && params[info.m_nTintMaskTexture]->IsDefined() )
  194. {
  195. pShader->LoadTexture( info.m_nTintMaskTexture, TEXTUREFLAGS_SRGB );
  196. }
  197. }
  198. //-----------------------------------------------------------------------------
  199. // Draws the shader
  200. //-----------------------------------------------------------------------------
  201. class CPhong_DX9_Context : public CBasePerMaterialContextData
  202. {
  203. public:
  204. CCommandBufferBuilder< CFixedCommandStorageBuffer< 800 > > m_SemiStaticCmdsOut;
  205. #ifdef _PS3
  206. CCommandBufferBuilder< CFixedCommandStorageBuffer< 256 > > m_flashlightECB;
  207. #endif
  208. };
  209. struct PhongShaderInfo_t
  210. {
  211. bool m_bHasBaseTexture;
  212. bool m_bHasBaseTextureWrinkle;
  213. bool m_bHasBumpWrinkle;
  214. bool m_bHasDiffuseWarp;
  215. bool m_bHasPhong;
  216. bool m_bHasPhongWarp;
  217. bool m_bHasDetailTexture;
  218. bool m_bHasSelfIllum;
  219. bool m_bHasSelfIllumFresnel;
  220. bool m_bHasEnvmap;
  221. bool m_bHasRimLight;
  222. bool m_bHasDecalTexture;
  223. bool m_bHasTintMaskTexture;
  224. };
  225. static void ComputePhongShaderInfo( CBaseVSShader *pShader, IMaterialVar** params,
  226. VertexLitGeneric_DX9_Vars_t &info, bool bHasFlashlightOnly, PhongShaderInfo_t *pInfo )
  227. {
  228. static ConVarRef r_staticlight_mode( "r_staticlight_mode" );
  229. pInfo->m_bHasBaseTexture = (info.m_nBaseTexture != -1) && params[info.m_nBaseTexture]->IsTexture();
  230. pInfo->m_bHasBaseTextureWrinkle = pInfo->m_bHasBaseTexture &&
  231. (info.m_nWrinkle != -1) && params[info.m_nWrinkle]->IsTexture() &&
  232. (info.m_nStretch != -1) && params[info.m_nStretch]->IsTexture();
  233. pInfo->m_bHasBumpWrinkle = (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsTexture() &&
  234. (info.m_nNormalWrinkle != -1) && params[info.m_nNormalWrinkle]->IsTexture() &&
  235. (info.m_nNormalStretch != -1) && params[info.m_nNormalStretch]->IsTexture();
  236. pInfo->m_bHasDecalTexture = (!pInfo->m_bHasBumpWrinkle) &&
  237. ((info.m_nDecalTexture != -1) && params[info.m_nDecalTexture]->IsTexture());
  238. pInfo->m_bHasTintMaskTexture = (!pInfo->m_bHasBumpWrinkle) &&
  239. ((info.m_nTintMaskTexture != -1) && params[info.m_nTintMaskTexture]->IsTexture());
  240. pInfo->m_bHasEnvmap = !bHasFlashlightOnly && params[info.m_nEnvmap]->IsTexture();
  241. pInfo->m_bHasSelfIllum = IS_FLAG_SET( MATERIAL_VAR_SELFILLUM ) != 0;
  242. pInfo->m_bHasSelfIllumFresnel = ( pInfo->m_bHasSelfIllum ) && ( info.m_nSelfIllumFresnel != -1 ) && ( params[info.m_nSelfIllumFresnel]->GetIntValue() != 0 );
  243. pInfo->m_bHasPhong = (info.m_nPhong != -1) && ( params[info.m_nPhong]->GetIntValue() != 0 );
  244. pInfo->m_bHasPhongWarp = (info.m_nPhongWarpTexture != -1) && params[info.m_nPhongWarpTexture]->IsTexture();
  245. pInfo->m_bHasDiffuseWarp = (info.m_nDiffuseWarpTexture != -1) && params[info.m_nDiffuseWarpTexture]->IsTexture();
  246. pInfo->m_bHasDetailTexture = ( info.m_nDetail != -1 ) && params[info.m_nDetail]->IsTexture();
  247. // Rimlight must be set to non-zero to trigger rim light combo (also requires Phong)
  248. pInfo->m_bHasRimLight = r_rimlight.GetBool() && pInfo->m_bHasPhong && (info.m_nRimLight != -1) && ( params[info.m_nRimLight]->GetIntValue() != 0 );
  249. }
  250. void DrawPhong_DX9( CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI *pShaderAPI, IShaderShadow* pShaderShadow,
  251. VertexLitGeneric_DX9_Vars_t &info, VertexCompressionType_t vertexCompression, CBasePerMaterialContextData **pContextDataPtr )
  252. {
  253. CPhong_DX9_Context *pContextData = reinterpret_cast< CPhong_DX9_Context *> ( *pContextDataPtr );
  254. static ConVarRef r_staticlight_mode( "r_staticlight_mode" );
  255. bool bAvgStaticLightStreams = r_staticlight_mode.GetInt() == 1;
  256. bool bSupportsSM3 = g_pHardwareConfig->SupportsPixelShaders_3_0() && ( !bAvgStaticLightStreams );
  257. bool bUseStaticControlFlow = g_pHardwareConfig->SupportsStaticControlFlow() && ( !bAvgStaticLightStreams );
  258. bool bSFM = ( ToolsEnabled() && IsPlatformWindowsPC() && bSupportsSM3 ) ? true : false;
  259. bool bHasFlashlight = pShader->UsingFlashlight( params );
  260. bool bHasFlashlightOnly = bHasFlashlight && !IsGameConsole();
  261. #if !defined( _X360 ) && !defined( _PS3 )
  262. bool bIsDecal = IS_FLAG_SET( MATERIAL_VAR_DECAL );
  263. #endif
  264. bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0;
  265. BlendType_t nBlendType = pShader->EvaluateBlendRequirements( info.m_nBaseTexture, true );
  266. bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested && !bHasFlashlightOnly; //dest alpha is free for special use
  267. bool bHasDisplacement = (info.m_nDisplacementMap != -1) && params[info.m_nDisplacementMap]->IsTexture() && bSFM;
  268. #if !defined( _X360 ) && !defined( _PS3 )
  269. bool bHasDisplacementWrinkles = (info.m_nDisplacementWrinkleMap != -1) && params[info.m_nDisplacementWrinkleMap]->GetIntValue() && bSFM;
  270. #endif
  271. bool bHDR = g_pHardwareConfig->GetHDRType() != HDR_TYPE_NONE;
  272. #if defined( CSTRIKE15 )
  273. bool bShaderSrgbRead = ( IsX360() && r_shader_srgbread.GetBool() );
  274. #else
  275. bool bShaderSrgbRead =( IsX360() && IS_PARAM_DEFINED( info.m_nShaderSrgbRead360 ) && ( params[info.m_nShaderSrgbRead360]->GetIntValue() ) );
  276. #endif
  277. #if !defined( _X360 ) && !defined( _PS3 )
  278. bool bMorphing = ( !pShaderAPI || pShaderAPI->IsHWMorphingEnabled() ) && bSFM && g_pHardwareConfig->HasFastVertexTextures();
  279. #endif
  280. if( pShader->IsSnapshotting() )
  281. {
  282. PhongShaderInfo_t phongInfo;
  283. ComputePhongShaderInfo( pShader, params, info, bHasFlashlightOnly, &phongInfo );
  284. int nDetailBlendMode = ( info.m_nDetailTextureCombineMode == -1 ) ? 0 : params[info.m_nDetailTextureCombineMode]->GetIntValue();
  285. int nDecalBlendMode = (info.m_nDecalTextureCombineMode == -1) ? 0 : params[info.m_nDecalTextureCombineMode]->GetIntValue();
  286. bool bHasVertexColor = IS_FLAG_SET( MATERIAL_VAR_VERTEXCOLOR );
  287. bool bHasVertexAlpha = IS_FLAG_SET( MATERIAL_VAR_VERTEXALPHA );
  288. // look at color and alphamod stuff.
  289. // Unlit generic never uses the flashlight
  290. bool bHasEnvmap = !bHasFlashlightOnly && params[info.m_nEnvmap]->IsTexture();
  291. // Alpha test: FIXME: shouldn't this be handled in CBaseVSShader::SetInitialShadowState
  292. pShaderShadow->EnableAlphaTest( bIsAlphaTested );
  293. if( info.m_nAlphaTestReference != -1 && params[info.m_nAlphaTestReference]->GetFloatValue() > 0.0f )
  294. {
  295. pShaderShadow->AlphaFunc( SHADER_ALPHAFUNC_GEQUAL, params[info.m_nAlphaTestReference]->GetFloatValue() );
  296. }
  297. // Based upon vendor and device dependent formats
  298. ShadowFilterMode_t nShadowFilterMode = bHasFlashlight ? g_pHardwareConfig->GetShadowFilterMode( false /* bForceLowQuality */, bSupportsSM3 && !IsPlatformPS3() && !IsPlatformX360() /* bPS30 */ ) : SHADOWFILTERMODE_DEFAULT;
  299. if( bHasFlashlightOnly )
  300. {
  301. if (params[info.m_nBaseTexture]->IsTexture())
  302. {
  303. pShader->SetAdditiveBlendingShadowState( info.m_nBaseTexture, true );
  304. }
  305. if( bIsAlphaTested )
  306. {
  307. // disable alpha test and use the zfunc zequals since alpha isn't guaranteed to
  308. // be the same on both the regular pass and the flashlight pass.
  309. pShaderShadow->EnableAlphaTest( false );
  310. pShaderShadow->DepthFunc( SHADER_DEPTHFUNC_EQUAL );
  311. }
  312. pShaderShadow->EnableBlending( true );
  313. pShaderShadow->EnableDepthWrites( false );
  314. // Be sure not to write to dest alpha
  315. pShaderShadow->EnableAlphaWrites( false );
  316. }
  317. if ( !bHasFlashlightOnly ) // not flashlight pass
  318. {
  319. if (params[info.m_nBaseTexture]->IsTexture())
  320. {
  321. pShader->SetDefaultBlendingShadowState( info.m_nBaseTexture, true );
  322. }
  323. }
  324. unsigned int flags = VERTEX_POSITION | VERTEX_NORMAL;
  325. int userDataSize = 0;
  326. // Always enable...will bind white if nothing specified...
  327. pShaderShadow->EnableTexture( SHADER_SAMPLER0, true ); // Base (albedo) map
  328. pShaderShadow->EnableSRGBRead( SHADER_SAMPLER0, !bShaderSrgbRead );
  329. if( bHasFlashlight )
  330. {
  331. pShaderShadow->EnableTexture( SHADER_SAMPLER4, true ); // Shadow depth map
  332. //pShaderShadow->SetShadowDepthFiltering( SHADER_SAMPLER4 );
  333. pShaderShadow->EnableSRGBRead( SHADER_SAMPLER4, false );
  334. pShaderShadow->EnableTexture( SHADER_SAMPLER6, true ); // Flashlight cookie
  335. pShaderShadow->EnableSRGBRead( SHADER_SAMPLER6, true );
  336. }
  337. userDataSize = 4; // tangent S
  338. if ( phongInfo.m_bHasDetailTexture )
  339. {
  340. pShaderShadow->EnableTexture( SHADER_SAMPLER13, true );
  341. pShaderShadow->EnableSRGBRead(SHADER_SAMPLER13, IsSRGBDetailTexture(nDetailBlendMode));
  342. }
  343. if ( phongInfo.m_bHasSelfIllum )
  344. {
  345. pShaderShadow->EnableTexture( SHADER_SAMPLER14, true );
  346. }
  347. if( bHasVertexColor || bHasVertexAlpha )
  348. {
  349. flags |= VERTEX_COLOR;
  350. }
  351. // Always enable ambient occlusion sampler on PC on DX10 parts
  352. if ( IsPC() && bSupportsSM3 && bSFM )
  353. {
  354. pShaderShadow->EnableTexture( SHADER_SAMPLER15, true );
  355. }
  356. if ( bHasDisplacement && IsPC() && g_pHardwareConfig->HasFastVertexTextures() )
  357. {
  358. pShaderShadow->EnableVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, true );
  359. }
  360. if ( phongInfo.m_bHasDecalTexture )
  361. {
  362. pShaderShadow->EnableTexture( SHADER_SAMPLER10, true ); // decal overlay
  363. pShaderShadow->EnableSRGBRead( SHADER_SAMPLER10, IsSRGBDecalTexture( nDecalBlendMode ) );
  364. }
  365. if ( phongInfo.m_bHasTintMaskTexture )
  366. {
  367. pShaderShadow->EnableTexture( SHADER_SAMPLER9, true );
  368. pShaderShadow->EnableSRGBRead( SHADER_SAMPLER9, true );
  369. }
  370. pShaderShadow->EnableSRGBWrite( true );
  371. // texcoord0 : base texcoord, texcoord2 : decal hw morph delta
  372. int pTexCoordDim[3] = { 2, 0, 3 };
  373. int nTexCoordCount = 1;
  374. #if !defined( _X360 ) && !defined( _PS3 )
  375. // Special morphed decal information
  376. if ( bIsDecal && bMorphing )
  377. {
  378. nTexCoordCount = 3;
  379. }
  380. #endif
  381. // This shader supports compressed vertices, so OR in that flag:
  382. flags |= VERTEX_FORMAT_COMPRESSED;
  383. // valid for static props
  384. flags |= VERTEX_COLOR_STREAM_1;
  385. pShaderShadow->VertexShaderVertexFormat( flags, nTexCoordCount, pTexCoordDim, userDataSize );
  386. #if !defined( _X360 ) && !defined( _PS3 )
  387. bool bWorldNormal = ( ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH == ( IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER0 ) + 2 * IS_FLAG2_SET( MATERIAL_VAR2_USE_GBUFFER1 )));
  388. #endif
  389. // This is to allow phong materials to disable half lambert. Half lambert has always been forced on in phong,
  390. // so the only safe way to allow artists to disable half lambert is to create this param that disables the
  391. // default behavior of forcing half lambert on.
  392. //bool bPhongHalfLambert = false; IS_PARAM_DEFINED( info.m_nPhongDisableHalfLambert ) ? (params[info.m_nPhongDisableHalfLambert]->GetIntValue() == 0) : true;
  393. // Disabling half-lambert for CSGO (not 'compatible' with CSM's - fixes bad shadow aliasing on viewmodels in particular).
  394. bool bPhongHalfLambert = false;
  395. #if !defined( _X360 ) && !defined( _PS3 )
  396. if ( !bSupportsSM3 )
  397. #endif
  398. {
  399. DECLARE_STATIC_VERTEX_SHADER( phong_vs20 );
  400. SET_STATIC_VERTEX_SHADER_COMBO( SFM, bSFM );
  401. SET_STATIC_VERTEX_SHADER_COMBO( WORLD_NORMAL, 0 );
  402. SET_STATIC_VERTEX_SHADER_COMBO( FLATTEN_STATIC_CONTROL_FLOW, !bUseStaticControlFlow );
  403. bool bCSMEnabled_ps2b = false;
  404. SET_STATIC_VERTEX_SHADER_COMBO( CASCADED_SHADOW_MAPPING, bCSMEnabled_ps2b );
  405. SET_STATIC_VERTEX_SHADER(phong_vs20);
  406. // Assume we're only going to get in here if we support 2b
  407. DECLARE_STATIC_PIXEL_SHADER( phong_ps20b );
  408. SET_STATIC_PIXEL_SHADER_COMBO( SFM, bSFM );
  409. SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight );
  410. SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, phongInfo.m_bHasSelfIllum && !bHasFlashlightOnly );
  411. SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, phongInfo.m_bHasSelfIllumFresnel && !bHasFlashlightOnly );
  412. SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, phongInfo.m_bHasDiffuseWarp && phongInfo.m_bHasPhong );
  413. SET_STATIC_PIXEL_SHADER_COMBO( PHONGWARPTEXTURE, phongInfo.m_bHasPhongWarp && phongInfo.m_bHasPhong );
  414. SET_STATIC_PIXEL_SHADER_COMBO( WRINKLEMAP, phongInfo.m_bHasBaseTextureWrinkle );
  415. SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, phongInfo.m_bHasDetailTexture );
  416. ClampDetailBlendModeAndWarn( nDetailBlendMode, 0, 7 );
  417. SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode );
  418. ClampDecalBlendModeAndWarn( nDecalBlendMode, 0, 1 );
  419. SET_STATIC_PIXEL_SHADER_COMBO( DECAL_BLEND_MODE, phongInfo.m_bHasDecalTexture ? nDecalBlendMode : 2 );
  420. SET_STATIC_PIXEL_SHADER_COMBO( TINTMASKTEXTURE, 0 );
  421. SET_STATIC_PIXEL_SHADER_COMBO( RIMLIGHT, phongInfo.m_bHasRimLight );
  422. SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap );
  423. SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
  424. SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead );
  425. SET_STATIC_PIXEL_SHADER_COMBO( WORLD_NORMAL, 0 );
  426. SET_STATIC_PIXEL_SHADER_COMBO( PHONG_HALFLAMBERT, bPhongHalfLambert );
  427. SET_STATIC_PIXEL_SHADER_COMBO( CASCADED_SHADOW_MAPPING, g_pHardwareConfig->SupportsCascadedShadowMapping() && !bSFM && !bHasFlashlight && g_pConfig->nFullbright != 1 );
  428. SET_STATIC_PIXEL_SHADER_COMBO( CSM_MODE, 0 );
  429. SET_STATIC_PIXEL_SHADER( phong_ps20b );
  430. }
  431. #if !defined( _X360 ) && !defined( _PS3 )
  432. else
  433. {
  434. // The vertex shader uses the vertex id stream
  435. if ( bSFM )
  436. {
  437. SET_FLAGS2( MATERIAL_VAR2_USES_VERTEXID );
  438. SET_FLAGS2( MATERIAL_VAR2_SUPPORTS_TESSELLATION );
  439. }
  440. int nCSMQualityComboValue = g_pHardwareConfig->GetCSMShaderMode( materials->GetCurrentConfigForVideoCard().GetCSMQualityMode() );
  441. DECLARE_STATIC_VERTEX_SHADER( phong_vs30 );
  442. SET_STATIC_VERTEX_SHADER_COMBO( SFM, bSFM );
  443. SET_STATIC_VERTEX_SHADER_COMBO( WORLD_NORMAL, bWorldNormal );
  444. SET_STATIC_VERTEX_SHADER_COMBO( DECAL, bIsDecal );
  445. SET_STATIC_VERTEX_SHADER_COMBO( CASCADED_SHADOW_MAPPING, 0 );
  446. SET_STATIC_VERTEX_SHADER( phong_vs30 );
  447. DECLARE_STATIC_PIXEL_SHADER( phong_ps30 );
  448. SET_STATIC_PIXEL_SHADER_COMBO( SFM, bSFM );
  449. SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHT, bHasFlashlight );
  450. SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUM, phongInfo.m_bHasSelfIllum && !bHasFlashlightOnly );
  451. SET_STATIC_PIXEL_SHADER_COMBO( SELFILLUMFRESNEL, phongInfo.m_bHasSelfIllumFresnel && !bHasFlashlightOnly );
  452. SET_STATIC_PIXEL_SHADER_COMBO( LIGHTWARPTEXTURE, phongInfo.m_bHasDiffuseWarp && phongInfo.m_bHasPhong );
  453. SET_STATIC_PIXEL_SHADER_COMBO( PHONGWARPTEXTURE, phongInfo.m_bHasPhongWarp && phongInfo.m_bHasPhong );
  454. SET_STATIC_PIXEL_SHADER_COMBO( WRINKLEMAP, phongInfo.m_bHasBaseTextureWrinkle );
  455. SET_STATIC_PIXEL_SHADER_COMBO( DETAILTEXTURE, phongInfo.m_bHasDetailTexture );
  456. ClampDetailBlendModeAndWarn( nDetailBlendMode, 0, 7 );
  457. SET_STATIC_PIXEL_SHADER_COMBO( DETAIL_BLEND_MODE, nDetailBlendMode );
  458. ClampDecalBlendModeAndWarn( nDecalBlendMode, 0, 1 );
  459. SET_STATIC_PIXEL_SHADER_COMBO( DECAL_BLEND_MODE, phongInfo.m_bHasDecalTexture ? nDecalBlendMode : 2 );
  460. SET_STATIC_PIXEL_SHADER_COMBO( TINTMASKTEXTURE, phongInfo.m_bHasTintMaskTexture );
  461. SET_STATIC_PIXEL_SHADER_COMBO( RIMLIGHT, phongInfo.m_bHasRimLight );
  462. SET_STATIC_PIXEL_SHADER_COMBO( CUBEMAP, bHasEnvmap );
  463. SET_STATIC_PIXEL_SHADER_COMBO( FLASHLIGHTDEPTHFILTERMODE, nShadowFilterMode );
  464. SET_STATIC_PIXEL_SHADER_COMBO( SHADER_SRGB_READ, bShaderSrgbRead );
  465. SET_STATIC_PIXEL_SHADER_COMBO( WORLD_NORMAL, bWorldNormal );
  466. SET_STATIC_PIXEL_SHADER_COMBO( PHONG_HALFLAMBERT, bPhongHalfLambert );
  467. SET_STATIC_PIXEL_SHADER_COMBO( CASCADED_SHADOW_MAPPING, g_pHardwareConfig->SupportsCascadedShadowMapping() && !bSFM && !bHasFlashlight && g_pConfig->nFullbright != 1 );
  468. SET_STATIC_PIXEL_SHADER_COMBO( CSM_MODE, ( g_pHardwareConfig->SupportsCascadedShadowMapping() && !bSFM && !bHasFlashlight && g_pConfig->nFullbright != 1 ) ? nCSMQualityComboValue : 0 );
  469. SET_STATIC_PIXEL_SHADER( phong_ps30 );
  470. }
  471. #endif
  472. if( bHasFlashlightOnly )
  473. {
  474. pShader->FogToBlack();
  475. }
  476. else
  477. {
  478. pShader->DefaultFog();
  479. }
  480. // HACK HACK HACK - enable alpha writes all the time so that we have them for underwater stuff
  481. pShaderShadow->EnableAlphaWrites( bFullyOpaque );
  482. pShader->PI_BeginCommandBuffer();
  483. pShader->PI_SetPixelShaderAmbientLightCube( PSREG_AMBIENT_CUBE );
  484. pShader->PI_SetPixelShaderLocalLighting( PSREG_LIGHT_INFO_ARRAY );
  485. pShader->PI_SetVertexShaderAmbientLightCube();
  486. // material can opt out of per-instance modulation via $nodiffusemodulation
  487. bool bAllowDiffuseModulation = ( info.m_nAllowDiffuseModulation == -1 ) ? true : ( params[info.m_nAllowDiffuseModulation]->GetIntValue() != 0 );
  488. if ( bAllowDiffuseModulation )
  489. {
  490. pShader->PI_SetModulationPixelShaderDynamicState_LinearColorSpace( 1 );
  491. }
  492. else
  493. {
  494. pShader->PI_SetModulationPixelShaderDynamicState_Identity( 1 );
  495. }
  496. pShader->PI_EndCommandBuffer();
  497. }
  498. else // not snapshotting -- begin dynamic state
  499. {
  500. // Deal with semisatic
  501. if ( ( !pContextData ) || ( pContextData->m_bMaterialVarsChanged ) )
  502. {
  503. if ( !pContextData ) // make sure allocated
  504. {
  505. pContextData = new CPhong_DX9_Context;
  506. *pContextDataPtr = pContextData;
  507. }
  508. pContextData->m_SemiStaticCmdsOut.Reset();
  509. #ifdef _PS3
  510. pContextData->m_flashlightECB.Reset();
  511. #endif
  512. pContextData->m_bMaterialVarsChanged = false;
  513. PhongShaderInfo_t phongInfo;
  514. ComputePhongShaderInfo( pShader, params, info, bHasFlashlightOnly, &phongInfo );
  515. int nDetailBlendMode = ( info.m_nDetailTextureCombineMode == -1 ) ? 0 : params[info.m_nDetailTextureCombineMode]->GetIntValue();
  516. int nDecalBlendMode = (info.m_nDecalTextureCombineMode == -1) ? 0 : params[info.m_nDecalTextureCombineMode]->GetIntValue();
  517. bool bHasBump = (info.m_nBumpmap != -1) && params[info.m_nBumpmap]->IsTexture();
  518. bool bLightingOnly = g_pConfig->nFullbright == 2 && !IS_FLAG_SET( MATERIAL_VAR_NO_DEBUG_OVERRIDE );
  519. bool bHasSelfIllumMask = ( phongInfo.m_bHasSelfIllum ) && (info.m_nSelfIllumMask != -1) && params[info.m_nSelfIllumMask]->IsTexture();
  520. float flBlendFactorOrPhongAlbedoBoost;
  521. if ( phongInfo.m_bHasDetailTexture )
  522. {
  523. flBlendFactorOrPhongAlbedoBoost = ( info.m_nDetailTextureBlendFactor == -1 )? 1 : params[info.m_nDetailTextureBlendFactor]->GetFloatValue();
  524. }
  525. else
  526. {
  527. flBlendFactorOrPhongAlbedoBoost = ( info.m_nPhongAlbedoBoost == -1 ) ? 1.0f : params[info.m_nPhongAlbedoBoost]->GetFloatValue();
  528. }
  529. bool bHasSpecularExponentTexture = (info.m_nPhongExponentTexture != -1) && params[info.m_nPhongExponentTexture]->IsTexture();
  530. bool bHasPhongTintMap = bHasSpecularExponentTexture && (info.m_nPhongAlbedoTint != -1) && ( params[info.m_nPhongAlbedoTint]->GetIntValue() != 0 );
  531. bool bHasNormalMapAlphaEnvmapMask = IS_FLAG_SET( MATERIAL_VAR_NORMALMAPALPHAENVMAPMASK );
  532. bool bHasRimMaskMap = bHasSpecularExponentTexture && phongInfo.m_bHasRimLight && (info.m_nRimMask != -1) && ( params[info.m_nRimMask]->GetIntValue() != 0 );
  533. bool bHasSinglePassFlashlight = IsX360() || IsPS3(); // NOTE: If you change this, fix state.m_nDepthTweakConstant below! And, deal with SINGLE_PASS_FLASHLIGHT in phong_ps20b.fxc
  534. if( phongInfo.m_bHasBaseTexture )
  535. {
  536. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER0, SRGBReadMask( !bShaderSrgbRead ), info.m_nBaseTexture, info.m_nBaseTextureFrame );
  537. }
  538. else
  539. {
  540. pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, SRGBReadMask( !bShaderSrgbRead ), TEXTURE_WHITE );
  541. }
  542. if ( phongInfo.m_bHasBaseTextureWrinkle )
  543. {
  544. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER9, SRGBReadMask( !bShaderSrgbRead ), info.m_nWrinkle, info.m_nBaseTextureFrame );
  545. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER10, SRGBReadMask( !bShaderSrgbRead ), info.m_nStretch, info.m_nBaseTextureFrame );
  546. }
  547. if( phongInfo.m_bHasDiffuseWarp && phongInfo.m_bHasPhong )
  548. {
  549. if ( r_lightwarpidentity.GetBool() )
  550. {
  551. pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER2, TEXTURE_BINDFLAGS_SRGBREAD, TEXTURE_IDENTITY_LIGHTWARP ); // [mariod] - TODO why does this conflict with other shader uses of this texture (i.e. not srgb - cloak_dx9, eye_refract_dx9, vertexlitgeneric_dx9)
  552. }
  553. else
  554. {
  555. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER2, TEXTURE_BINDFLAGS_NONE, info.m_nDiffuseWarpTexture );
  556. }
  557. }
  558. if( phongInfo.m_bHasPhongWarp )
  559. {
  560. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER1, TEXTURE_BINDFLAGS_NONE, info.m_nPhongWarpTexture );
  561. }
  562. // Specular exponent map or dummy
  563. if( bHasSpecularExponentTexture && phongInfo.m_bHasPhong )
  564. {
  565. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER7, TEXTURE_BINDFLAGS_NONE, info.m_nPhongExponentTexture );
  566. }
  567. else
  568. {
  569. pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER7, TEXTURE_BINDFLAGS_NONE, TEXTURE_WHITE );
  570. }
  571. if( !g_pConfig->m_bFastNoBump )
  572. {
  573. if( bHasBump )
  574. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER3, TEXTURE_BINDFLAGS_NONE, info.m_nBumpmap, info.m_nBumpFrame );
  575. else
  576. pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_BINDFLAGS_NONE, TEXTURE_NORMALMAP_FLAT );
  577. if ( phongInfo.m_bHasBumpWrinkle )
  578. {
  579. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER11, TEXTURE_BINDFLAGS_NONE, info.m_nNormalWrinkle, info.m_nBumpFrame );
  580. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, TEXTURE_BINDFLAGS_NONE, info.m_nNormalStretch, info.m_nBumpFrame );
  581. }
  582. else if ( phongInfo.m_bHasBaseTextureWrinkle )
  583. {
  584. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER11, TEXTURE_BINDFLAGS_NONE, info.m_nBumpmap, info.m_nBumpFrame );
  585. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, TEXTURE_BINDFLAGS_NONE, info.m_nBumpmap, info.m_nBumpFrame );
  586. }
  587. }
  588. else // Just flat bump maps
  589. {
  590. if ( bHasBump )
  591. {
  592. pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER3, TEXTURE_BINDFLAGS_NONE, TEXTURE_NORMALMAP_FLAT );
  593. }
  594. if ( phongInfo.m_bHasBaseTextureWrinkle || phongInfo.m_bHasBumpWrinkle )
  595. {
  596. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER11, TEXTURE_BINDFLAGS_NONE, TEXTURE_NORMALMAP_FLAT );
  597. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER12, TEXTURE_BINDFLAGS_NONE, TEXTURE_NORMALMAP_FLAT );
  598. }
  599. }
  600. if ( phongInfo.m_bHasDetailTexture )
  601. {
  602. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER13, IsSRGBDetailTexture( nDetailBlendMode ) ? TEXTURE_BINDFLAGS_SRGBREAD : TEXTURE_BINDFLAGS_NONE, info.m_nDetail, info.m_nDetailFrame );
  603. }
  604. if ( phongInfo.m_bHasDecalTexture )
  605. {
  606. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER10, IsSRGBDecalTexture( nDecalBlendMode ) ? TEXTURE_BINDFLAGS_SRGBREAD : TEXTURE_BINDFLAGS_NONE, info.m_nDecalTexture );
  607. }
  608. if ( phongInfo.m_bHasTintMaskTexture )
  609. {
  610. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER9, TEXTURE_BINDFLAGS_SRGBREAD, info.m_nTintMaskTexture );
  611. }
  612. if ( phongInfo.m_bHasSelfIllum )
  613. {
  614. if ( bHasSelfIllumMask ) // Separate texture for self illum?
  615. {
  616. pContextData->m_SemiStaticCmdsOut.BindTexture( pShader, SHADER_SAMPLER14, TEXTURE_BINDFLAGS_NONE, info.m_nSelfIllumMask ); // Bind it
  617. }
  618. else // else
  619. {
  620. pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER14, TEXTURE_BINDFLAGS_NONE, TEXTURE_BLACK ); // Bind dummy
  621. }
  622. }
  623. if( !bHasFlashlightOnly )
  624. {
  625. if ( phongInfo.m_bHasEnvmap )
  626. {
  627. pContextData->m_SemiStaticCmdsOut.BindEnvCubemapTexture( pShader, SHADER_SAMPLER8, bHDR ? TEXTURE_BINDFLAGS_NONE : TEXTURE_BINDFLAGS_SRGBREAD, info.m_nEnvmap, info.m_nEnvmapFrame );
  628. }
  629. }
  630. pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_0, info.m_nBaseTextureTransform );
  631. if( bHasBump )
  632. {
  633. pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_2, info.m_nBumpTransform );
  634. }
  635. if ( phongInfo.m_bHasDetailTexture )
  636. {
  637. if ( IS_PARAM_DEFINED( info.m_nDetailTextureTransform ) )
  638. {
  639. pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4,
  640. info.m_nDetailTextureTransform,
  641. info.m_nDetailScale );
  642. }
  643. else
  644. {
  645. pContextData->m_SemiStaticCmdsOut.SetVertexShaderTextureScaledTransform( VERTEX_SHADER_SHADER_SPECIFIC_CONST_4,
  646. info.m_nBaseTextureTransform,
  647. info.m_nDetailScale );
  648. }
  649. }
  650. pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant_W( PSREG_SELFILLUMTINT, info.m_nSelfIllumTint, flBlendFactorOrPhongAlbedoBoost );
  651. bool bInvertPhongMask = ( info.m_nInvertPhongMask != -1 ) && ( params[info.m_nInvertPhongMask]->GetIntValue() != 0 );
  652. float fInvertPhongMask = bInvertPhongMask ? 1 : 0;
  653. bool bHasBaseAlphaPhongMask = (info.m_nBaseMapAlphaPhongMask != -1) && ( params[info.m_nBaseMapAlphaPhongMask]->GetIntValue() != 0 );
  654. float fHasBaseAlphaPhongMask = bHasBaseAlphaPhongMask ? 1 : 0;
  655. bool bBlendTintByBaseAlpha = (info.m_nBlendTintByBaseAlpha != -1) && ( params[info.m_nBlendTintByBaseAlpha]->GetIntValue() != 0 );
  656. float fBlendTintByBaseAlpha = bBlendTintByBaseAlpha ? 1 : 0;
  657. bool bNoTint = (info.m_nNoTint != -1) && ( params[info.m_nNoTint]->GetIntValue() != 0 );
  658. // Controls for lerp-style paths through shader code
  659. float vShaderControls[4] = { fHasBaseAlphaPhongMask, 0.0f, bNoTint ? -1.0f : ( 1.0f - fBlendTintByBaseAlpha ), fInvertPhongMask };
  660. pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_SHADER_CONTROLS, vShaderControls, 1 );
  661. if ( phongInfo.m_bHasSelfIllumFresnel && !bHasFlashlightOnly )
  662. {
  663. float vConstScaleBiasExp[4] = { 1.0f, 0.0f, 1.0f, 0.0f };
  664. float flMin = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[0] : 0.0f;
  665. float flMax = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[1] : 1.0f;
  666. float flExp = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelMinMaxExp ) ? params[info.m_nSelfIllumFresnelMinMaxExp]->GetVecValue()[2] : 1.0f;
  667. vConstScaleBiasExp[1] = ( flMax != 0.0f ) ? ( flMin / flMax ) : 0.0f; // Bias
  668. vConstScaleBiasExp[0] = 1.0f - vConstScaleBiasExp[1]; // Scale
  669. vConstScaleBiasExp[2] = flExp; // Exp
  670. vConstScaleBiasExp[3] = flMax; // Brightness
  671. pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_SELFILLUM_SCALE_BIAS_EXP, vConstScaleBiasExp, 1 );
  672. }
  673. if( !bHasFlashlightOnly )
  674. {
  675. pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER5, TEXTURE_BINDFLAGS_NONE, TEXTURE_NORMALIZATION_CUBEMAP_SIGNED );
  676. if( phongInfo.m_bHasEnvmap )
  677. {
  678. float vEnvMapTint_MaskControl[4] = {1.0f, 1.0f, 1.0f, 0.0f};
  679. // If we have a tint, grab it
  680. if ( (info.m_nEnvmapTint != -1) && params[info.m_nEnvmapTint]->IsDefined() )
  681. params[info.m_nEnvmapTint]->GetVecValue(vEnvMapTint_MaskControl, 3);
  682. // Set control for source of env map mask (normal alpha or base alpha)
  683. vEnvMapTint_MaskControl[3] = bHasNormalMapAlphaEnvmapMask ? 1.0f : 0.0f;
  684. // Handle mat_fullbright 2 (diffuse lighting only with 50% gamma space basetexture)
  685. if( bLightingOnly )
  686. {
  687. vEnvMapTint_MaskControl[0] = vEnvMapTint_MaskControl[1] = vEnvMapTint_MaskControl[2] = 0.0f;
  688. }
  689. pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_ENVMAP_TINT__SHADOW_TWEAKS, vEnvMapTint_MaskControl, 1 );
  690. }
  691. }
  692. // Pack Phong exponent in with the eye position
  693. float vSpecularTint[4] = {1, 1, 1, 4};
  694. float vFresnelRanges_SpecBoost[4] = {0, 0.5, 1, 1}, vRimBoost[4] = {1, 1, 1, 1};
  695. // Get the tint parameter
  696. if ( (info.m_nPhongTint != -1) && params[info.m_nPhongTint]->IsDefined() )
  697. {
  698. params[info.m_nPhongTint]->GetVecValue(vSpecularTint, 3);
  699. }
  700. // Get the rim light power (goes in w of Phong tint)
  701. if ( phongInfo.m_bHasRimLight && (info.m_nRimLightPower != -1) && params[info.m_nRimLightPower]->IsDefined() )
  702. {
  703. vSpecularTint[3] = params[info.m_nRimLightPower]->GetFloatValue();
  704. vSpecularTint[3] = MAX(vSpecularTint[3], 1.0f); // Make sure this is at least 1
  705. }
  706. // Get the rim boost (goes in w of flashlight position)
  707. if ( phongInfo.m_bHasRimLight && (info.m_nRimLightBoost != -1) && params[info.m_nRimLightBoost]->IsDefined() )
  708. {
  709. vRimBoost[3] = params[info.m_nRimLightBoost]->GetFloatValue();
  710. }
  711. // Single pass flashlight has to use a separate constant for this stuff since a flashlight constant is repurposed for rimlighting when doing multi-pass flashlight.
  712. if ( phongInfo.m_bHasRimLight )
  713. {
  714. if ( bHasSinglePassFlashlight )
  715. {
  716. float vRimParams[4] = {0, 0, 0, 0};
  717. vRimParams[0] = bHasRimMaskMap ? params[info.m_nRimMask]->GetFloatValue() : 0.0f;
  718. vRimParams[1] = params[info.m_nRimLightBoost]->GetFloatValue();
  719. // Rim mask...if this is true, use alpha channel of spec exponent texture to mask the rim term
  720. pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_RIMPARAMS, vRimParams, 1 );
  721. }
  722. else if ( !bHasFlashlight )
  723. {
  724. float vRimMaskControl[4] = {0, 0, 0, 0}; // Only x is relevant in shader code
  725. vRimMaskControl[0] = bHasRimMaskMap ? params[info.m_nRimMask]->GetFloatValue() : 0.0f;
  726. // Rim mask...if this is true, use alpha channel of spec exponent texture to mask the rim term
  727. pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_FLASHLIGHT_ATTENUATION, vRimMaskControl, 1 );
  728. }
  729. }
  730. // If it's all zeros, there was no constant tint in the vmt
  731. if ( (vSpecularTint[0] == 0.0f) && (vSpecularTint[1] == 0.0f) && (vSpecularTint[2] == 0.0f) )
  732. {
  733. if ( bHasPhongTintMap ) // If we have a map to use, tell the shader
  734. {
  735. vSpecularTint[0] = -1;
  736. }
  737. else // Otherwise, just tint with white
  738. {
  739. vSpecularTint[0] = 1.0f;
  740. vSpecularTint[1] = 1.0f;
  741. vSpecularTint[2] = 1.0f;
  742. }
  743. }
  744. // handle mat_fullbright 2 (diffuse lighting only)
  745. if( bLightingOnly )
  746. {
  747. // BASETEXTURE
  748. if( phongInfo.m_bHasSelfIllum && !bHasFlashlightOnly )
  749. {
  750. pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, SRGBReadMask( !bShaderSrgbRead ), TEXTURE_GREY_ALPHA_ZERO );
  751. if ( phongInfo.m_bHasBaseTextureWrinkle || phongInfo.m_bHasBumpWrinkle )
  752. {
  753. pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER9, SRGBReadMask( !bShaderSrgbRead ), TEXTURE_GREY_ALPHA_ZERO ); // Compressed wrinklemap
  754. pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER10, SRGBReadMask( !bShaderSrgbRead ), TEXTURE_GREY_ALPHA_ZERO ); // Stretched wrinklemap
  755. }
  756. }
  757. else
  758. {
  759. pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER0, SRGBReadMask( !bShaderSrgbRead ), TEXTURE_GREY );
  760. if ( phongInfo.m_bHasBaseTextureWrinkle || phongInfo.m_bHasBumpWrinkle )
  761. {
  762. pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER9, SRGBReadMask( !bShaderSrgbRead ), TEXTURE_GREY ); // Compressed wrinklemap
  763. pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER10, SRGBReadMask( !bShaderSrgbRead ), TEXTURE_GREY ); // Stretched wrinklemap
  764. }
  765. }
  766. // DETAILTEXTURE
  767. if ( phongInfo.m_bHasDetailTexture )
  768. {
  769. pContextData->m_SemiStaticCmdsOut.BindStandardTexture( SHADER_SAMPLER13, ( nDetailBlendMode != 0 ) ? TEXTURE_BINDFLAGS_SRGBREAD : TEXTURE_BINDFLAGS_NONE, TEXTURE_GREY );
  770. }
  771. // turn off specularity
  772. vSpecularTint[0] = vSpecularTint[1] = vSpecularTint[2] = 0.0f;
  773. }
  774. if ( (info.m_nPhongFresnelRanges != -1) && params[info.m_nPhongFresnelRanges]->IsDefined() )
  775. {
  776. params[info.m_nPhongFresnelRanges]->GetVecValue( vFresnelRanges_SpecBoost, 3 ); // Grab optional Fresnel range parameters
  777. }
  778. if ( (info.m_nPhongBoost != -1 ) && params[info.m_nPhongBoost]->IsDefined()) // Grab optional Phong boost param
  779. {
  780. vFresnelRanges_SpecBoost[3] = params[info.m_nPhongBoost]->GetFloatValue();
  781. }
  782. else
  783. {
  784. vFresnelRanges_SpecBoost[3] = 1.0f;
  785. }
  786. bool bHasBaseLuminancePhongMask = (info.m_nBaseMapLuminancePhongMask != -1) && ( params[info.m_nBaseMapLuminancePhongMask]->GetIntValue() != 0 );
  787. float fHasBaseLuminancePhongMask = bHasBaseLuminancePhongMask ? 1 : 0;
  788. float vShaderControls2[4] = {0.0f, fHasBaseLuminancePhongMask, 0.0f, 0.0f};
  789. if ( !bHasFlashlightOnly )
  790. {
  791. if ( phongInfo.m_bHasEnvmap )
  792. {
  793. if ( (info.m_nEnvmapFresnel != -1) && params[info.m_nEnvmapFresnel]->IsDefined() )
  794. {
  795. vShaderControls2[0] = params[info.m_nEnvmapFresnel]->GetFloatValue();
  796. }
  797. }
  798. }
  799. if ( (info.m_nPhongExponent != -1) && params[info.m_nPhongExponent]->IsDefined() )
  800. {
  801. vShaderControls2[2] = params[info.m_nPhongExponent]->GetFloatValue(); // This overrides the channel in the map
  802. }
  803. else
  804. {
  805. vShaderControls2[2] = 0; // Use the alpha channel of the normal map for the exponent
  806. }
  807. // Driven by the material proxy for team ID in csgo
  808. int nSelfIllumFresnelEnabledThisFrame = IS_PARAM_DEFINED( info.m_nSelfIllumFresnelEnabledThisFrame ) ? params[info.m_nSelfIllumFresnelEnabledThisFrame]->GetIntValue() : 1;
  809. vShaderControls2[3] = bHasSelfIllumMask ? 1.0f : 0.0f;
  810. if ( phongInfo.m_bHasSelfIllumFresnel && !nSelfIllumFresnelEnabledThisFrame )
  811. {
  812. vShaderControls2[3] = 0.0f;
  813. }
  814. pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_FRESNEL_SPEC_PARAMS, vFresnelRanges_SpecBoost, 1 );
  815. pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_FLASHLIGHT_POSITION_RIM_BOOST, vRimBoost, 1 ); // Rim boost in w on non-flashlight pass
  816. pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_SPEC_RIM_PARAMS, vSpecularTint, 1 );
  817. pContextData->m_SemiStaticCmdsOut.SetPixelShaderConstant( PSREG_SHADER_CONTROLS_2, vShaderControls2, 1 );
  818. #ifndef _PS3
  819. pContextData->m_SemiStaticCmdsOut.SetPixelShaderFogParams( PSREG_FOG_PARAMS );
  820. #endif
  821. if ( bHasFlashlight )
  822. {
  823. CBCmdSetPixelShaderFlashlightState_t state;
  824. state.m_LightSampler = SHADER_SAMPLER6;
  825. state.m_DepthSampler = SHADER_SAMPLER4;
  826. state.m_ShadowNoiseSampler = SHADER_SAMPLER5;
  827. state.m_nColorConstant = PSREG_FLASHLIGHT_COLOR;
  828. state.m_nAttenConstant = PSREG_FLASHLIGHT_ATTENUATION;
  829. state.m_nOriginConstant = PSREG_FLASHLIGHT_POSITION_RIM_BOOST;
  830. state.m_nDepthTweakConstant = bHasSinglePassFlashlight ? 43 : PSREG_ENVMAP_TINT__SHADOW_TWEAKS; // NOTE: Reg 43 not available on < ps3.0!
  831. state.m_nScreenScaleConstant = PSREG_FLASHLIGHT_SCREEN_SCALE;
  832. state.m_nWorldToTextureConstant = PSREG_FLASHLIGHT_TO_WORLD_TEXTURE;
  833. state.m_bFlashlightNoLambert = false;
  834. state.m_bSinglePassFlashlight = bHasSinglePassFlashlight;
  835. #ifdef _PS3
  836. pContextData->m_flashlightECB.SetPixelShaderFlashlightState( state );
  837. pContextData->m_flashlightECB.End();
  838. #else
  839. pContextData->m_SemiStaticCmdsOut.SetPixelShaderFlashlightState( state );
  840. #endif
  841. if ( !( IsX360() || IsPS3() ) && ( g_pHardwareConfig->GetDXSupportLevel() > 92 ) )
  842. {
  843. pContextData->m_SemiStaticCmdsOut.SetPixelShaderUberLightState(
  844. PSREG_UBERLIGHT_SMOOTH_EDGE_0, PSREG_UBERLIGHT_SMOOTH_EDGE_1,
  845. PSREG_UBERLIGHT_SMOOTH_EDGE_OOW, PSREG_UBERLIGHT_SHEAR_ROUND,
  846. PSREG_UBERLIGHT_AABB, PSREG_UBERLIGHT_WORLD_TO_LIGHT );
  847. }
  848. }
  849. pContextData->m_SemiStaticCmdsOut.End();
  850. }
  851. #ifdef _PS3
  852. CCommandBufferBuilder< CDynamicCommandStorageBuffer > DynamicCmdsOut;
  853. ShaderApiFast( pShaderAPI )->ExecuteCommandBuffer( pContextData->m_SemiStaticCmdsOut.Base() );
  854. if (bHasFlashlight) ShaderApiFast( pShaderAPI )->ExecuteCommandBuffer( pContextData->m_flashlightECB.Base() );
  855. #else
  856. CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut;
  857. DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() );
  858. #endif
  859. // On PC, we sample from ambient occlusion texture
  860. if ( IsPC() && bSupportsSM3 && bSFM )
  861. {
  862. ITexture *pAOTexture = ShaderApiFast( pShaderAPI )->GetTextureRenderingParameter( TEXTURE_RENDERPARM_AMBIENT_OCCLUSION );
  863. if ( pAOTexture )
  864. {
  865. DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER15, TEXTURE_BINDFLAGS_NONE, pAOTexture, 0 );
  866. }
  867. else
  868. {
  869. DynamicCmdsOut.BindStandardTexture( SHADER_SAMPLER15, TEXTURE_BINDFLAGS_NONE, TEXTURE_WHITE );
  870. }
  871. }
  872. bool bFlashlightShadows = false;
  873. bool bUberlight = false;
  874. float flAmbientOcclusionStrength = ( info.m_nAmbientOcclusion == -1 ) ? 0.0f : params[info.m_nAmbientOcclusion]->GetFloatValue();
  875. if ( bHasFlashlight )
  876. {
  877. ShaderApiFast( pShaderAPI )->GetFlashlightShaderInfo( &bFlashlightShadows, &bUberlight );
  878. flAmbientOcclusionStrength *= ShaderApiFast( pShaderAPI )->GetFlashlightAmbientOcclusion();
  879. }
  880. float vEyePos_AmbientOcclusion[4];
  881. ShaderApiFast( pShaderAPI )->GetWorldSpaceCameraPosition( vEyePos_AmbientOcclusion );
  882. vEyePos_AmbientOcclusion[3] = clamp( flAmbientOcclusionStrength, 0.0f, 1.0f );
  883. DynamicCmdsOut.SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_AmbientOcclusion, 1 );
  884. MaterialFogMode_t fogType = ShaderApiFast( pShaderAPI )->GetSceneFogMode();
  885. int numBones = ShaderApiFast( pShaderAPI )->GetCurrentNumBones();
  886. bool bWriteDepthToAlpha = false;
  887. bool bWriteWaterFogToAlpha = false;
  888. if( bFullyOpaque )
  889. {
  890. // Disable for CS:GO
  891. //bWriteDepthToAlpha = ShaderApiFast( pShaderAPI )->ShouldWriteDepthToDestAlpha();
  892. bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z);
  893. AssertMsg( !(bWriteDepthToAlpha && bWriteWaterFogToAlpha), "Can't write two values to alpha at the same time." );
  894. }
  895. LightState_t lightState = { 0, false, false };
  896. if( !bHasFlashlightOnly )
  897. {
  898. ShaderApiFast( pShaderAPI )->GetDX9LightState( &lightState );
  899. }
  900. float vTeamIdMinMax[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  901. vTeamIdMinMax[0] = cl_teamid_min.GetFloat();
  902. vTeamIdMinMax[1] = cl_teamid_max.GetFloat();
  903. if ( vTeamIdMinMax[1] <= vTeamIdMinMax[0] )
  904. {
  905. vTeamIdMinMax[1] = vTeamIdMinMax[0] + 0.01f; // Avoid a divide by zero in the shader
  906. }
  907. ShaderApiFast( pShaderAPI )->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, vTeamIdMinMax );
  908. bool bCSMEnabled = pShaderAPI->IsCascadedShadowMapping() && !bHasFlashlight && !bSFM && g_pConfig->nFullbright != 1;
  909. if ( ( !( IsGameConsole() ) ) &&
  910. ( !bSupportsSM3 || ToolsEnabled() ) )
  911. {
  912. bCSMEnabled = false;
  913. }
  914. // r_staticlight_streams (from engine.dll)
  915. // This is for the 3 color baked prop lighting.
  916. static ConVarRef r_staticlight_streams( "r_staticlight_streams", true );
  917. bool bStaticLight3Streams = (r_staticlight_streams.GetInt() == 3);
  918. #if !defined( _X360 ) && !defined( _PS3 )
  919. if ( !bSupportsSM3 )
  920. #endif
  921. {
  922. bool bIsRenderingViewModels = false;
  923. DECLARE_DYNAMIC_VERTEX_SHADER( phong_vs20 );
  924. SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, numBones > 0 );
  925. SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression );
  926. SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, 0 );
  927. SET_DYNAMIC_VERTEX_SHADER_COMBO( NUM_LIGHTS, bUseStaticControlFlow ? 0 : ( IsPS3() ) ? MIN(2, lightState.m_nNumLights) : lightState.m_nNumLights );
  928. SET_DYNAMIC_VERTEX_SHADER_COMBO( CSM_VIEWMODELQUALITY, bIsRenderingViewModels ? 1 : 0 );
  929. SET_DYNAMIC_VERTEX_SHADER_COMBO( STATICLIGHT3, lightState.m_bStaticLight && bStaticLight3Streams );
  930. SET_DYNAMIC_VERTEX_SHADER( phong_vs20 );
  931. DECLARE_DYNAMIC_PIXEL_SHADER( phong_ps20b );
  932. SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, ( IsPS3() ) ? MIN(2, lightState.m_nNumLights) : lightState.m_nNumLights );
  933. SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha );
  934. SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha );
  935. SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, bFlashlightShadows );
  936. SET_DYNAMIC_PIXEL_SHADER_COMBO( CASCADE_SIZE, ( IsGameConsole() ) ? ( bCSMEnabled ? 1 : 0 ) : 0 );
  937. SET_DYNAMIC_PIXEL_SHADER_COMBO( CSM_VIEWMODELQUALITY, bIsRenderingViewModels ? 1 : 0 );
  938. SET_DYNAMIC_PIXEL_SHADER_COMBO( STATICLIGHT3, lightState.m_bStaticLight && bStaticLight3Streams );
  939. SET_DYNAMIC_PIXEL_SHADER( phong_ps20b );
  940. }
  941. #if !defined( _X360 ) && !defined( _PS3 )
  942. else
  943. {
  944. if ( bMorphing )
  945. {
  946. pShader->SetHWMorphVertexShaderState( VERTEX_SHADER_SHADER_SPECIFIC_CONST_6, VERTEX_SHADER_SHADER_SPECIFIC_CONST_7, SHADER_VERTEXTEXTURE_SAMPLER0 );
  947. }
  948. int nLightingPreviewMode = 0;
  949. #if 0
  950. // Unused. Disabled for CS:GO -- Thorsten
  951. nLightingPreviewMode = ShaderApiFast( pShaderAPI )->GetIntRenderingParameter( INT_RENDERPARM_ENABLE_FIXED_LIGHTING );
  952. #endif
  953. if ( ( nLightingPreviewMode == ENABLE_FIXED_LIGHTING_OUTPUTNORMAL_AND_DEPTH ) && IsPC() )
  954. {
  955. float vEyeDir[4];
  956. ShaderApiFast( pShaderAPI )->GetWorldSpaceCameraDirection( vEyeDir );
  957. float flFarZ = ShaderApiFast( pShaderAPI )->GetFarZ();
  958. vEyeDir[0] /= flFarZ; // Divide by farZ for SSAO algorithm
  959. vEyeDir[1] /= flFarZ;
  960. vEyeDir[2] /= flFarZ;
  961. ShaderApiFast( pShaderAPI )->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_8, vEyeDir );
  962. }
  963. TessellationMode_t nTessellationMode = ( bSFM && g_pHardwareConfig->HasFastVertexTextures() ) ? ShaderApiFast( pShaderAPI )->GetTessellationMode() : TESSELLATION_MODE_DISABLED;
  964. if ( nTessellationMode != TESSELLATION_MODE_DISABLED )
  965. {
  966. ShaderApiFast( pShaderAPI )->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER1, TEXTURE_SUBDIVISION_PATCHES );
  967. float vSubDDimensions[4] = { 1.0f/ShaderApiFast( pShaderAPI )->GetSubDHeight(),
  968. bHasDisplacement && mat_displacementmap.GetBool() ? 1.0f : 0.0f,
  969. bHasDisplacementWrinkles && mat_displacementmap.GetBool() ? 1.0f : 0.0f, 0.0f };
  970. ShaderApiFast( pShaderAPI )->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_9, vSubDDimensions );
  971. if( bHasDisplacement )
  972. {
  973. pShader->BindVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, info.m_nDisplacementMap );
  974. }
  975. else
  976. {
  977. ShaderApiFast( pShaderAPI )->BindStandardVertexTexture( SHADER_VERTEXTEXTURE_SAMPLER2, TEXTURE_BLACK );
  978. }
  979. // Currently, tessellation is mutually exclusive with any kind of GPU-side skinning, morphing or vertex compression
  980. Assert( !ShaderApiFast( pShaderAPI )->IsHWMorphingEnabled() );
  981. Assert( numBones == 0 );
  982. Assert( vertexCompression == 0);
  983. }
  984. if ( bCSMEnabled )
  985. {
  986. ITexture *pDepthTextureAtlas = NULL;
  987. const CascadedShadowMappingState_t &cascadeState = pShaderAPI->GetCascadedShadowMappingState( &pDepthTextureAtlas );
  988. DynamicCmdsOut.BindTexture( pShader, SHADER_SAMPLER15, TEXTURE_BINDFLAGS_SHADOWDEPTH, pDepthTextureAtlas, 0 );
  989. DynamicCmdsOut.SetPixelShaderConstant( 64, &cascadeState.m_vLightColor.x, CASCADED_SHADOW_MAPPING_CONSTANT_BUFFER_SIZE );
  990. }
  991. BOOL bCSMEnabledBool = bCSMEnabled;
  992. pShaderAPI->SetBooleanPixelShaderConstant( 0, &bCSMEnabledBool, 1 );
  993. DECLARE_DYNAMIC_VERTEX_SHADER( phong_vs30 );
  994. SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, ( numBones > 0) && ( nTessellationMode == TESSELLATION_MODE_DISABLED ) );
  995. SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression && ( nTessellationMode == TESSELLATION_MODE_DISABLED ) );
  996. SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, nTessellationMode );
  997. //SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, bMorphing );
  998. SET_DYNAMIC_VERTEX_SHADER_COMBO( CSM_VIEWMODELQUALITY, 0 ); // TODO: not used in sm3.0, combo should be removed
  999. SET_DYNAMIC_VERTEX_SHADER_COMBO( STATICLIGHT3, lightState.m_bStaticLight && bStaticLight3Streams );
  1000. SET_DYNAMIC_VERTEX_SHADER( phong_vs30 );
  1001. DECLARE_DYNAMIC_PIXEL_SHADER( phong_ps30 );
  1002. SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, nLightingPreviewMode ? 0 : lightState.m_nNumLights );
  1003. SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, nLightingPreviewMode ? false : bWriteWaterFogToAlpha );
  1004. SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha );
  1005. SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, nLightingPreviewMode ? false : bFlashlightShadows );
  1006. SET_DYNAMIC_PIXEL_SHADER_COMBO( UBERLIGHT, bUberlight && bSFM );
  1007. SET_DYNAMIC_PIXEL_SHADER_COMBO( CASCADE_SIZE, 0 );
  1008. SET_DYNAMIC_PIXEL_SHADER_COMBO( CSM_VIEWMODELQUALITY, 0 ); // TODO: not used in sm3.0, combo should be removed
  1009. SET_DYNAMIC_PIXEL_SHADER_COMBO( STATICLIGHT3, lightState.m_bStaticLight && bStaticLight3Streams );
  1010. SET_DYNAMIC_PIXEL_SHADER( phong_ps30 );
  1011. bool bUnusedTexCoords[3] = { false, false, !bMorphing || !bIsDecal };
  1012. ShaderApiFast( pShaderAPI )->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords );
  1013. // Set constant to enable translation of VPOS to render target coordinates in ps_3_0
  1014. ShaderApiFast( pShaderAPI )->SetScreenSizeForVPOS();
  1015. }
  1016. #endif
  1017. DynamicCmdsOut.End();
  1018. #ifdef _PS3
  1019. ShaderApiFast( pShaderAPI )->SetPixelShaderFogParams( PSREG_FOG_PARAMS );
  1020. #endif
  1021. ShaderApiFast( pShaderAPI )->ExecuteCommandBuffer( DynamicCmdsOut.Base() );
  1022. }
  1023. pShader->Draw();
  1024. }
  1025. void DrawPhong_DX9_ExecuteFastPath( int *vsDynIndex, int *psDynIndex,
  1026. CBaseVSShader *pShader, IMaterialVar** params, IShaderDynamicAPI * pShaderAPI,
  1027. VertexLitGeneric_DX9_Vars_t &info,
  1028. VertexCompressionType_t vertexCompression,
  1029. CBasePerMaterialContextData **pContextDataPtr, BOOL bCSMEnabled )
  1030. {
  1031. pShaderAPI->BeginPerfEEvent( L"Phong_FastPath" );
  1032. CPhong_DX9_Context *pContextData = reinterpret_cast< CPhong_DX9_Context *> ( *pContextDataPtr );
  1033. CCommandBufferBuilder< CFixedCommandStorageBuffer< 1000 > > DynamicCmdsOut;
  1034. DynamicCmdsOut.Call( pContextData->m_SemiStaticCmdsOut.Base() );
  1035. DynamicCmdsOut.End();
  1036. ShaderApiFast( pShaderAPI )->ExecuteCommandBuffer( DynamicCmdsOut.Base() );
  1037. float flAmbientOcclusionStrength = ( info.m_nAmbientOcclusion == -1 ) ? 0.0f : params[info.m_nAmbientOcclusion]->GetFloatValue();
  1038. float vEyePos_AmbientOcclusion[4];
  1039. ShaderApiFast( pShaderAPI )->GetWorldSpaceCameraPosition( vEyePos_AmbientOcclusion );
  1040. vEyePos_AmbientOcclusion[3] = clamp( flAmbientOcclusionStrength, 0.0f, 1.0f );
  1041. pShaderAPI->SetPixelShaderConstant( PSREG_EYEPOS_SPEC_EXPONENT, vEyePos_AmbientOcclusion, 1 );
  1042. float vTeamIdMinMax[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
  1043. vTeamIdMinMax[0] = cl_teamid_min.GetFloat();
  1044. vTeamIdMinMax[1] = cl_teamid_max.GetFloat();
  1045. if ( vTeamIdMinMax[1] <= vTeamIdMinMax[0] )
  1046. {
  1047. vTeamIdMinMax[1] = vTeamIdMinMax[0] + 0.01f; // Avoid a divide by zero in the shader
  1048. }
  1049. pShaderAPI->SetVertexShaderConstant( VERTEX_SHADER_SHADER_SPECIFIC_CONST_10, vTeamIdMinMax );
  1050. if ( g_pConfig->nFullbright == 1 )
  1051. {
  1052. bCSMEnabled = false;
  1053. }
  1054. pShaderAPI->SetBooleanPixelShaderConstant( 0, (BOOL*)&bCSMEnabled, 1 );
  1055. if ( bCSMEnabled )
  1056. {
  1057. ITexture *pDepthTextureAtlas = NULL;
  1058. const CascadedShadowMappingState_t &cascadeState = pShaderAPI->GetCascadedShadowMappingState( &pDepthTextureAtlas );
  1059. pShader->BindTexture( SHADER_SAMPLER15, TEXTURE_BINDFLAGS_SHADOWDEPTH, pDepthTextureAtlas, 0 );
  1060. pShaderAPI->SetPixelShaderConstant( 64, &cascadeState.m_vLightColor.x, CASCADED_SHADOW_MAPPING_CONSTANT_BUFFER_SIZE );
  1061. }
  1062. int numBones = ShaderApiFast( pShaderAPI )->GetCurrentNumBones();
  1063. bool bIsRenderingViewModels = false;
  1064. if( IsGameConsole() )
  1065. {
  1066. ITexture *pDepthTextureAtlas = NULL;
  1067. const CascadedShadowMappingState_t &cascadeState = pShaderAPI->GetCascadedShadowMappingState( &pDepthTextureAtlas );
  1068. if ( pDepthTextureAtlas )
  1069. {
  1070. bIsRenderingViewModels = cascadeState.m_bIsRenderingViewModels && r_csm_viewmodelquality.GetBool();
  1071. }
  1072. }
  1073. static ConVarRef r_staticlight_streams( "r_staticlight_streams", true );
  1074. bool bStaticLight3Streams = (r_staticlight_streams.GetInt() == 3);
  1075. LightState_t lightState = {0, false, false};
  1076. ShaderApiFast( pShaderAPI )->GetDX9LightState( &lightState );
  1077. DECLARE_DYNAMIC_VERTEX_SHADER( phong_vs30 );
  1078. SET_DYNAMIC_VERTEX_SHADER_COMBO( SKINNING, ( numBones > 0) );
  1079. SET_DYNAMIC_VERTEX_SHADER_COMBO( COMPRESSED_VERTS, (int)vertexCompression);
  1080. SET_DYNAMIC_VERTEX_SHADER_COMBO( TESSELLATION, TESSELLATION_MODE_DISABLED );
  1081. //SET_DYNAMIC_VERTEX_SHADER_COMBO( MORPHING, false );
  1082. SET_DYNAMIC_VERTEX_SHADER_COMBO( CSM_VIEWMODELQUALITY, bIsRenderingViewModels ? 1 : 0 );
  1083. SET_DYNAMIC_VERTEX_SHADER_COMBO( STATICLIGHT3, lightState.m_bStaticLight && bStaticLight3Streams );
  1084. SET_DYNAMIC_VERTEX_SHADER( phong_vs30 );
  1085. bool bIsAlphaTested = IS_FLAG_SET( MATERIAL_VAR_ALPHATEST ) != 0;
  1086. BlendType_t nBlendType = pShader->EvaluateBlendRequirements( info.m_nBaseTexture, true );
  1087. bool bFullyOpaque = (nBlendType != BT_BLENDADD) && (nBlendType != BT_BLEND) && !bIsAlphaTested; //dest alpha is free for special use
  1088. MaterialFogMode_t fogType = ShaderApiFast( pShaderAPI )->GetSceneFogMode();
  1089. bool bWriteDepthToAlpha = false;
  1090. bool bWriteWaterFogToAlpha = false;
  1091. if( bFullyOpaque )
  1092. {
  1093. // Disable for CS:GO
  1094. //bWriteDepthToAlpha = ShaderApiFast( pShaderAPI )->ShouldWriteDepthToDestAlpha();
  1095. bWriteWaterFogToAlpha = (fogType == MATERIAL_FOG_LINEAR_BELOW_FOG_Z);
  1096. }
  1097. DECLARE_DYNAMIC_PIXEL_SHADER( phong_ps30 );
  1098. SET_DYNAMIC_PIXEL_SHADER_COMBO( NUM_LIGHTS, lightState.m_nNumLights );
  1099. SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITEWATERFOGTODESTALPHA, bWriteWaterFogToAlpha );
  1100. SET_DYNAMIC_PIXEL_SHADER_COMBO( WRITE_DEPTH_TO_DESTALPHA, bWriteDepthToAlpha );
  1101. SET_DYNAMIC_PIXEL_SHADER_COMBO( FLASHLIGHTSHADOWS, false );
  1102. SET_DYNAMIC_PIXEL_SHADER_COMBO( UBERLIGHT, false );
  1103. SET_DYNAMIC_PIXEL_SHADER_COMBO( CASCADE_SIZE, 0 );
  1104. SET_DYNAMIC_PIXEL_SHADER_COMBO( CSM_VIEWMODELQUALITY, 0 ); // TODO: not used in sm3.0, combo should be removed
  1105. SET_DYNAMIC_PIXEL_SHADER_COMBO( STATICLIGHT3, lightState.m_bStaticLight && bStaticLight3Streams );
  1106. SET_DYNAMIC_PIXEL_SHADER( phong_ps30 );
  1107. bool bUnusedTexCoords[3] = { false, false, TRUE };
  1108. ShaderApiFast( pShaderAPI )->MarkUnusedVertexFields( 0, 3, bUnusedTexCoords );
  1109. // Set constant to enable translation of VPOS to render target coordinates in ps_3_0
  1110. ShaderApiFast( pShaderAPI )->SetScreenSizeForVPOS();
  1111. *vsDynIndex = _vshIndex.GetIndex();
  1112. *psDynIndex = _pshIndex.GetIndex();
  1113. pShaderAPI->EndPerfEvent();
  1114. }