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.

960 lines
38 KiB

  1. //========== Copyright (c) Valve Corporation, All rights reserved. ==========//
  2. // STATIC: "SFM" "0..0" [ps20b] [PC]
  3. // STATIC: "SFM" "0..1" [ps30] [PC]
  4. // STATIC: "SFM" "0..0" [CONSOLE]
  5. // STATIC: "CUBEMAP" "0..1"
  6. // STATIC: "SELFILLUM" "0..1"
  7. // STATIC: "SELFILLUMFRESNEL" "0..1"
  8. // STATIC: "FLASHLIGHT" "0..1"
  9. // STATIC: "LIGHTWARPTEXTURE" "0..1"
  10. // STATIC: "PHONGWARPTEXTURE" "0..1"
  11. // STATIC: "WRINKLEMAP" "0..1"
  12. // STATIC: "DETAIL_BLEND_MODE" "0..7"
  13. // STATIC: "DETAILTEXTURE" "0..1"
  14. // STATIC: "RIMLIGHT" "0..1"
  15. // STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..3" [ps20b] [PC]
  16. // STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..2" [ps30] [PC]
  17. // STATIC: "FLASHLIGHTDEPTHFILTERMODE" "0..0" [ps20b] [CONSOLE]
  18. // STATIC: "SHADER_SRGB_READ" "0..1" [XBOX]
  19. // STATIC: "SHADER_SRGB_READ" "0..0" [PC]
  20. // STATIC: "SHADER_SRGB_READ" "0..0" [SONYPS3]
  21. // STATIC: "WORLD_NORMAL" "0..0" [ps20b] [PC]
  22. // STATIC: "WORLD_NORMAL" "0..1" [ps30] [PC]
  23. // STATIC: "WORLD_NORMAL" "0..0" [CONSOLE]
  24. // STATIC: "PHONG_HALFLAMBERT" "0..0"
  25. // STATIC: "CASCADED_SHADOW_MAPPING" "0..1" [CONSOLE]
  26. // STATIC: "CASCADED_SHADOW_MAPPING" "0..0" [ps20] [PC]
  27. // STATIC: "CASCADED_SHADOW_MAPPING" "0..1" [ps20b] [ps30] [PC]
  28. // STATIC: "CSM_MODE" "0..0" [CONSOLE]
  29. // STATIC: "CSM_MODE" "0..0" [ps20] [ps20b] [PC]
  30. // STATIC: "CSM_MODE" "0..3" [ps30] [PC]
  31. // STATIC: "DECAL_BLEND_MODE" "0..2"
  32. // STATIC: "TINTMASKTEXTURE" "0..1" [ps30]
  33. // STATIC: "TINTMASKTEXTURE" "0..0" [ps20] [ps20b]
  34. // STATIC: "TINTMASKTEXTURE" "0..0" [CONSOLE]
  35. // DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1"
  36. #include "common_fog_ps_fxc.h"
  37. // DYNAMIC: "NUM_LIGHTS" "0..4" [CONSOLE]
  38. // DYNAMIC: "NUM_LIGHTS" "0..2" [ps20b] [PC]
  39. // DYNAMIC: "NUM_LIGHTS" "0..4" [ps30] [PC]
  40. // DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [PC]
  41. // DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [CONSOLE]
  42. // DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps30]
  43. // DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b]
  44. // DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps30]
  45. // DYNAMIC: "UBERLIGHT" "0..1" [ps30] [PC]
  46. // DYNAMIC: "CASCADE_SIZE" "0..1" [CONSOLE]
  47. // DYNAMIC: "CASCADE_SIZE" "0..1" [ps20b] [PC]
  48. // DYNAMIC: "CASCADE_SIZE" "0..0" [ps20] [ps30] [PC]
  49. // DYNAMIC: "CSM_VIEWMODELQUALITY" "0..1" [CONSOLE]
  50. // DYNAMIC: "CSM_VIEWMODELQUALITY" "0..1" [ps20b] [PC]
  51. // DYNAMIC: "CSM_VIEWMODELQUALITY" "0..0" [ps20] [ps30] [PC]
  52. // DYNAMIC: "STATICLIGHT3" "0..0" [CONSOLE]
  53. // DYNAMIC: "STATICLIGHT3" "0..0" [ps20] [PC]
  54. // DYNAMIC: "STATICLIGHT3" "0..1" [ps20b] [ps30] [PC]
  55. // SKIP: ( $SFM == 0 ) && ( $UBERLIGHT == 1 )
  56. // blend mode doesn't matter if we only have one texture
  57. // SKIP: (! $DETAILTEXTURE) && ( $DETAIL_BLEND_MODE != 0 )
  58. // SKIP: ( $DECAL_BLEND_MODE != 2 ) && ( $SELFILLUM != 0 )
  59. // We don't care about flashlight depth unless the flashlight is on
  60. // SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 )
  61. // We don't care about uberlight unless the flashlight is on
  62. // SKIP: ( $FLASHLIGHT == 0 ) && ( $UBERLIGHT == 1 ) [ps30]
  63. // Only need self illum fresnel when self illum enabled
  64. // SKIP: ( $SELFILLUM == 0 ) && ( $SELFILLUMFRESNEL == 1 )
  65. // SKIP: ( $WRINKLEMAP == 1 ) && ( $DECAL_BLEND_MODE != 2 )
  66. // SKIP: ( $WRINKLEMAP == 1 ) && ( $TINTMASKTEXTURE != 0 )
  67. // Don't skip these on 360 since we do single-pass rendering+flashlight there!
  68. // SKIP: ( $FLASHLIGHT == 1 ) && ( $SELFILLUMFRESNEL == 1 ) [PC]
  69. // SKIP: ( $FLASHLIGHT == 1 ) && ( $SELFILLUM == 1 ) [PC]
  70. // Only do world normals in constrained case
  71. // SKIP: ( $WORLD_NORMAL == 1 ) && ( $FLASHLIGHTSHADOWS == 1 ) && ( $NUM_LIGHTS != 0 ) && ( $WRITEWATERFOGTODESTALPHA == 1 )
  72. // SKIP: ( $WORLD_NORMAL == 1 ) && ( $DETAILTEXTURE == 1 )
  73. // SKIP: ( $WORLD_NORMAL == 1 ) && ( $DECAL_BLEND_MODE != 2 )
  74. // SKIP: ( $CASCADED_SHADOW_MAPPING == 0 ) && ( $CASCADE_SIZE != 0 )
  75. // SKIP: ( $CASCADED_SHADOW_MAPPING != 0 ) && ( $SFM != 0 )
  76. // SKIP: ( $CASCADED_SHADOW_MAPPING != 0 ) && ( $FLASHLIGHT != 0 )
  77. // SKIP: ( $CASCADED_SHADOW_MAPPING == 0 ) && ( $CSM_MODE != 0 )
  78. // SKIP: ( $CASCADED_SHADOW_MAPPING == 0 ) && ( $CSM_VIEWMODELQUALITY != 0 ) [CONSOLE]
  79. // SKIP: ( $CASCADE_SIZE == 0 ) && ( $CSM_VIEWMODELQUALITY != 0 ) [CONSOLE]
  80. // SKIP: ( $NUMLIGHTS > 2 ) [SONYPS3]
  81. #include "common_flashlight_fxc.h"
  82. #include "common_decaltexture_fxc.h"
  83. #include "shader_constant_register_map.h"
  84. #if defined( _X360 ) || defined( _PS3 )
  85. #define SINGLE_PASS_FLASHLIGHT 1
  86. #else
  87. #define SINGLE_PASS_FLASHLIGHT 0
  88. #endif
  89. const float4 g_SelfIllumTint_and_DetailBlendFactorOrPhongAlbedoBoost : register( PSREG_SELFILLUMTINT );
  90. #if ( SELFILLUMFRESNEL == 1 )
  91. const float4 g_SelfIllumScaleBiasExpBrightness : register( PSREG_SELFILLUM_SCALE_BIAS_EXP );
  92. #endif
  93. const float4 g_DiffuseModulation : register( PSREG_DIFFUSE_MODULATION );
  94. const float4 g_vPsConst2 : register( PSREG_ENVMAP_TINT__SHADOW_TWEAKS );
  95. #define g_vEnvmapTint ( g_vPsConst2.xyz )
  96. #define g_bHasNormalMapAlphaEnvmapMask g_vPsConst2.w
  97. #if ( SINGLE_PASS_FLASHLIGHT )
  98. const float4 g_vPsConst43 : register( c43 );
  99. #define g_vShadowTweaks g_vPsConst43
  100. #else
  101. #define g_vShadowTweaks g_vPsConst2
  102. #endif
  103. const float3 cAmbientCube[6] : register( PSREG_AMBIENT_CUBE );
  104. const float4 g_EyePos_SpecExponent : register( PSREG_EYEPOS_SPEC_EXPONENT );
  105. const float4 g_FogParams : register( PSREG_FOG_PARAMS );
  106. const float4 g_FlashlightAttenuationFactors_RimMask : register( PSREG_FLASHLIGHT_ATTENUATION ); // On non-flashlight pass, x has rim mask control
  107. const float4 g_FlashlightPos_RimBoost : register( PSREG_FLASHLIGHT_POSITION_RIM_BOOST ); // This is overridden too!
  108. const float4x4 g_FlashlightWorldToTexture : register( PSREG_FLASHLIGHT_TO_WORLD_TEXTURE );
  109. const float4 g_FresnelSpecParams : register( PSREG_FRESNEL_SPEC_PARAMS ); // xyz are fresnel, w is specular boost
  110. const float4 g_SpecularRimParams : register( PSREG_SPEC_RIM_PARAMS ); // xyz are specular tint color, w is rim power
  111. // 2 registers each - 4 registers total when using csm's and ps_2_b, 6 registers total otherwise, (4th light spread across w's)
  112. #if defined( SHADER_MODEL_PS_2_B ) && ( CASCADED_SHADOW_MAPPING )
  113. PixelShaderLightInfo cLightInfo[2] : register( PSREG_LIGHT_INFO_ARRAY );
  114. #else
  115. PixelShaderLightInfo cLightInfo[3] : register( PSREG_LIGHT_INFO_ARRAY );
  116. #endif
  117. const float4 g_ShaderControls : register( PSREG_SHADER_CONTROLS );
  118. const float4 g_ShaderControls2 : register( PSREG_SHADER_CONTROLS_2 );
  119. #if ( UBERLIGHT )
  120. const float3 g_vSmoothEdge0 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_0 ); // ps_3_0 and up (over 32 registers)
  121. const float3 g_vSmoothEdge1 : register( PSREG_UBERLIGHT_SMOOTH_EDGE_1 );
  122. const float3 g_vSmoothOneOverWidth : register( PSREG_UBERLIGHT_SMOOTH_EDGE_OOW );
  123. const float4 g_vShearRound : register( PSREG_UBERLIGHT_SHEAR_ROUND );
  124. const float4 g_aAbB : register( PSREG_UBERLIGHT_AABB );
  125. const float4x4 g_FlashlightWorldToLight : register( PSREG_UBERLIGHT_WORLD_TO_LIGHT );
  126. #endif
  127. #if ( SINGLE_PASS_FLASHLIGHT )
  128. const float4 g_RimParams : register( PSREG_RIMPARAMS );
  129. #define g_RimMaskControl g_RimParams.x
  130. #define g_fRimBoost g_RimParams.y
  131. #else
  132. #define g_RimMaskControl g_FlashlightAttenuationFactors_RimMask.x
  133. #define g_fRimBoost g_FlashlightPos_RimBoost.w
  134. #endif
  135. #define g_FlashlightPos g_FlashlightPos_RimBoost.xyz
  136. #define g_FresnelRanges g_FresnelSpecParams.xyz
  137. #define g_SpecularBoost g_FresnelSpecParams.w
  138. #define g_SpecularTint g_SpecularRimParams.xyz
  139. #define g_RimExponent g_SpecularRimParams.w
  140. #define g_FlashlightAttenuationFactors g_FlashlightAttenuationFactors_RimMask
  141. #define g_EyePos g_EyePos_SpecExponent.xyz
  142. // Could merge g_fBaseMapAlphaPhongMask and g_fBaseLumPhongMask into a single -1, 0, 1 control code with some clever negation/saturation logic
  143. //
  144. // These scalars control behavior with straight-line "control flow" using lerp operations
  145. #define g_fBaseMapAlphaPhongMask g_ShaderControls.x
  146. #define g_fInverseBlendTintByBaseAlpha g_ShaderControls.z
  147. #define g_fInvertPhongMask g_ShaderControls.w
  148. #define g_fEnvMapFresnel g_ShaderControls2.x
  149. #define g_fBaseLumPhongMask g_ShaderControls2.y
  150. #define g_fSpecExp g_ShaderControls2.z
  151. #define g_SelfIllumMaskControl g_ShaderControls2.w
  152. #define g_fAmbientOcclusionStrength g_EyePos_SpecExponent.w
  153. sampler BaseTextureSampler : register( s0 ); // Base map, selfillum in alpha
  154. sampler SpecularWarpSampler : register( s1 ); // Specular warp sampler (for iridescence etc)
  155. sampler DiffuseWarpSampler : register( s2 ); // Lighting warp sampler (1D texture for diffuse lighting modification)
  156. sampler NormalMapSampler : register( s3 ); // Normal map, specular mask in alpha
  157. sampler ShadowDepthSampler : register( s4 ); // Flashlight shadow depth map sampler
  158. sampler NormalizeRandRotSampler : register( s5 ); // Normalization / RandomRotation samplers
  159. sampler FlashlightSampler : register( s6 ); // Flashlight cookie
  160. sampler SpecExponentSampler : register( s7 ); // Specular exponent map
  161. samplerCUBE EnvmapSampler : register( s8 ); // Cubic environment map
  162. #if defined(_PS3)
  163. // Needed for optimal shadow filter code generation on PS3.
  164. #pragma texformat ShadowDepthSampler DEPTH_COMPONENT24
  165. #endif
  166. #if WRINKLEMAP
  167. sampler WrinkleSampler : register( s9 ); // Compression base
  168. sampler StretchSampler : register( s10 ); // Expansion base
  169. sampler NormalWrinkleSampler : register( s11 ); // Compression normal
  170. sampler NormalStretchSampler : register( s12 ); // Expansion normal
  171. #endif
  172. #if DETAILTEXTURE
  173. sampler DetailSampler : register( s13 ); // detail texture
  174. #endif
  175. sampler SelfIllumMaskSampler : register( s14 ); // selfillummask
  176. #if ( SFM )
  177. sampler AmbientOcclusionSampler : register( s15 ); // screen space ambient occlusion sampler on PC
  178. #endif
  179. #if ( DECAL_BLEND_MODE != 2 )
  180. sampler DecalSampler : register( s10 );
  181. #endif
  182. #if ( TINTMASKTEXTURE )
  183. sampler TintMaskSampler : register( s9 );
  184. #endif
  185. #define FLASHLIGHT_ONLY ( FLASHLIGHT && !SINGLE_PASS_FLASHLIGHT )
  186. struct PS_INPUT
  187. {
  188. #if defined( SHADER_MODEL_PS_3_0 ) || defined( _X360 )
  189. float2 vPos : VPOS; // Normalized Screenpos, call ComputeScreenPos() to get useful 2D coordinates
  190. #endif
  191. float4 baseTexCoord_baseTexCoord2 : TEXCOORD0; // Base texture coordinates in .xy and 2nd (decal) uv set in .zw
  192. float4 bumpTexCoord_detailTexCoord : TEXCOORD1;
  193. float4 vWorldNormal_flTeamIdFade : TEXCOORD2;
  194. float4 vWorldTangent : TEXCOORD3;
  195. float4 vWorldPos_vertexFogFactor : TEXCOORD4;
  196. float4 vProjPos_fWrinkleWeight : TEXCOORD5;
  197. #if defined( SHADER_MODEL_PS_3_0 )
  198. float4 staticLight0 : TEXCOORD6; // STATICLIGHT3 output basis 0 in .xyz, sun amount (if applicable) in .w
  199. float4 staticLight1 : TEXCOORD7; // STATICLIGHT3 output basis 1 in .xyz
  200. float4 staticLight2 : TEXCOORD8; // STATICLIGHT3 output basis 2 in .xyz
  201. float4 lightAtten : TEXCOORD9; // light attenuation for 4 lights
  202. #else
  203. float4 csmXform0or1_csmXform2 : TEXCOORD6;
  204. float4 staticLight_csmXform0z : TEXCOORD7; // STATICLIGHT3 average rgb in .xyz, csm lightToWorldxformcascade0.z in .w
  205. float4 lightAtten : COLOR0; // light attenuation for lights 0 and 1 in .xy (lower precision for sm2_b/OSX), sun amount (if applicable) in .w
  206. #endif
  207. };
  208. #if ( CASCADED_SHADOW_MAPPING ) && !defined( _X360 ) && !defined( _PS3 ) && !defined( SHADER_MODEL_PS_2_B )
  209. const bool g_bCSMEnabled : register(b0);
  210. #undef CASCADE_SIZE
  211. #define CASCADE_SIZE 1
  212. #endif
  213. #if ( CASCADE_SIZE > 0 )
  214. #undef CASCADE_SIZE
  215. #define CASCADE_SIZE 3
  216. #endif
  217. #if ( ( !SFM ) && ( !FLASHLIGHT_ONLY ) && ( CASCADED_SHADOW_MAPPING ) && ( CASCADE_SIZE > 0 ) )
  218. #define CSM_ENABLED 1
  219. #else
  220. #define CSM_ENABLED 0
  221. #endif
  222. #if ( CSM_ENABLED )
  223. sampler CSMDepthAtlasSampler : register( s15 );
  224. #if defined(_PS3)
  225. // Needed for optimal shadow filter code generation on PS3.
  226. #pragma texformat CSMDepthAtlasSampler DEPTH_COMPONENT24
  227. #endif
  228. #if defined( SHADER_MODEL_PS_2_B )
  229. #define CSM_PHONG
  230. #endif
  231. #include "csm_common_fxc.h"
  232. #endif
  233. #if defined( _X360 )
  234. // The compiler runs out of temp registers in certain combos, increase the maximum for now
  235. #if ( WRINKLEMAP )
  236. [maxtempreg(41)]
  237. #elif ( ( NUM_LIGHTS > 2 ) && ( RIMLIGHT == 1 ) )
  238. [maxtempreg(39)]
  239. #elif ( SHADER_SRGB_READ == 1 ) || ( SELFILLUMFRESNEL == 1 )
  240. [maxtempreg(35)]
  241. #endif
  242. #endif
  243. float3 PhotoshopOverlay( float3 cBase, float3 cBlend )
  244. {
  245. float3 cNew;
  246. cNew = step( 0.5, cBase );
  247. cNew = lerp( (cBase*cBlend*2), (1.0-(2.0*(1.0-cBase)*(1.0-cBlend))), cNew );
  248. return cNew;
  249. }
  250. //
  251. // Accumulate all dynamic lights other than the 0th/CSM light which has already been added to the static lighting term (since it was computed in bump basis space).
  252. //
  253. float3 PixelShaderDoLighting_STATIC3( const float3 worldPos, const float3 worldNormal, const float4 lightAtten,
  254. in samplerCUBE NormalizeSampler, const int nNumLights, PixelShaderLightInfo llightInfo[3], const bool bHalfLambert,
  255. const bool bDoLightingWarp, in sampler lightWarpSampler )
  256. {
  257. float3 linearColor = 0.0f;
  258. if ( nNumLights > 1 )
  259. {
  260. linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.y, worldPos, worldNormal, NormalizeSampler,
  261. llightInfo[1].pos.xyz, llightInfo[1].color.rgb, bHalfLambert,
  262. bDoLightingWarp, lightWarpSampler );
  263. if ( nNumLights > 2 )
  264. {
  265. linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.z, worldPos, worldNormal, NormalizeSampler,
  266. llightInfo[2].pos.xyz, llightInfo[2].color.rgb, bHalfLambert,
  267. bDoLightingWarp, lightWarpSampler );
  268. if ( nNumLights > 3 )
  269. {
  270. // Unpack the 4th light's data from tight constant packing
  271. float3 vLight3Color = float3( llightInfo[0].color.w, llightInfo[0].pos.w, llightInfo[1].color.w );
  272. float3 vLight3Pos = float3( llightInfo[1].pos.w, llightInfo[2].color.w, llightInfo[2].pos.w );
  273. linearColor += PixelShaderDoGeneralDiffuseLight( lightAtten.w, worldPos, worldNormal, NormalizeSampler,
  274. vLight3Pos, vLight3Color, bHalfLambert,
  275. bDoLightingWarp, lightWarpSampler );
  276. }
  277. }
  278. }
  279. return linearColor;
  280. }
  281. void SpecularAndRimTerms_STATIC3( const float3 vWorldNormal, const float3 vLightDir, const float fSpecularExponent, const float3 vEyeDir,
  282. const bool bDoSpecularWarp, in sampler specularWarpSampler, const float fFresnel,
  283. const float3 color, const bool bDoRimLighting, const float fRimExponent,
  284. // Outputs
  285. out float3 specularLighting, out float3 rimLighting )
  286. {
  287. float3 vHalfAngle = normalize( vEyeDir.xyz + vLightDir.xyz );
  288. float flNDotH = saturate( dot( vWorldNormal.xyz, vHalfAngle.xyz ) );
  289. specularLighting = pow( flNDotH, fSpecularExponent ); // Raise to specular exponent
  290. // Optionally warp as function of scalar specular and fresnel
  291. if ( bDoSpecularWarp )
  292. {
  293. specularLighting *= tex2D( specularWarpSampler, float2(specularLighting.x, fFresnel) ).rgb; // Sample at { (N.H)^k, fresnel }
  294. }
  295. // note missing modulate by n.l term
  296. specularLighting *= color; // Modulate with light color only - shadow term contain cosine softened n.l, ao, baked shadow, dynamic shadow
  297. // Optionally do rim lighting
  298. rimLighting = float3( 0.0, 0.0, 0.0 );
  299. if ( bDoRimLighting )
  300. {
  301. rimLighting = pow( flNDotH, fRimExponent ); // Raise to rim exponent
  302. // note missing modulate by n.l term
  303. rimLighting *= color; // Modulate with light color
  304. }
  305. }
  306. void PixelShaderDoSpecularLight_STATIC3( const float3 vWorldPos, const float3 vWorldNormal, const float fSpecularExponent, const float3 vEyeDir,
  307. const float fAtten, const float3 vLightColor, const float3 vLightDir,
  308. const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel,
  309. const bool bDoRimLighting, const float fRimExponent,
  310. // Outputs
  311. out float3 specularLighting, out float3 rimLighting )
  312. {
  313. // Compute Specular and rim terms
  314. SpecularAndRimTerms_STATIC3( vWorldNormal, vLightDir, fSpecularExponent, vEyeDir,
  315. bDoSpecularWarp, specularWarpSampler, fFresnel, vLightColor * fAtten,
  316. bDoRimLighting, fRimExponent, specularLighting, rimLighting );
  317. }
  318. //
  319. // Duplicate version of PixelShaderDoSpecularLighting for assets with baked indirect lighting and CSM blending term in vertex alpha
  320. // (We remove the modulation of the specular by n.l in the helpers above)
  321. // We assume flCombinedShadowingTerm contain CSM * baked shadow * ao * cosine softened n.l, giving us a more accurate term to modulate against
  322. //
  323. void PixelShaderDoSpecularLighting_STATIC3( const float3 worldPos, const float3 worldNormal, const float fSpecularExponent, const float3 vEyeDir,
  324. const float4 lightAtten, const int nNumLights, PixelShaderLightInfo cLightInfo[3],
  325. const bool bDoSpecularWarp, in sampler specularWarpSampler, float fFresnel,
  326. const bool bDoRimLighting, const float fRimExponent, const float flCombinedShadowingTerm,
  327. // Outputs
  328. out float3 specularLighting, out float3 rimLighting )
  329. {
  330. specularLighting = rimLighting = float3( 0.0f, 0.0f, 0.0f );
  331. float3 localSpecularTerm, localRimTerm;
  332. if( nNumLights > 0 )
  333. {
  334. // First local light will always be forced to a directional light in CS:GO (see CanonicalizeMaterialLightingState() in shaderapidx8.cpp) - it may be completely black.
  335. PixelShaderDoSpecularLight_STATIC3( worldPos, worldNormal, fSpecularExponent, vEyeDir,
  336. lightAtten.x, PixelShaderGetLightColor( cLightInfo, 0 ),
  337. PixelShaderGetLightVector( worldPos, cLightInfo, 0 ),
  338. bDoSpecularWarp, specularWarpSampler, fFresnel,
  339. bDoRimLighting, fRimExponent,
  340. localSpecularTerm, localRimTerm );
  341. specularLighting += localSpecularTerm * flCombinedShadowingTerm; // Accumulate specular and rim terms
  342. rimLighting += localRimTerm * flCombinedShadowingTerm;
  343. }
  344. if( nNumLights > 1 )
  345. {
  346. PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,
  347. lightAtten.y, PixelShaderGetLightColor( cLightInfo, 1 ),
  348. PixelShaderGetLightVector( worldPos, cLightInfo, 1 ),
  349. bDoSpecularWarp, specularWarpSampler, fFresnel,
  350. bDoRimLighting, fRimExponent,
  351. localSpecularTerm, localRimTerm );
  352. specularLighting += localSpecularTerm; // Accumulate specular and rim terms
  353. rimLighting += localRimTerm;
  354. }
  355. if( nNumLights > 2 )
  356. {
  357. PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,
  358. lightAtten.z, PixelShaderGetLightColor( cLightInfo, 2 ),
  359. PixelShaderGetLightVector( worldPos, cLightInfo, 2 ),
  360. bDoSpecularWarp, specularWarpSampler, fFresnel,
  361. bDoRimLighting, fRimExponent,
  362. localSpecularTerm, localRimTerm );
  363. specularLighting += localSpecularTerm; // Accumulate specular and rim terms
  364. rimLighting += localRimTerm;
  365. }
  366. if( nNumLights > 3 )
  367. {
  368. PixelShaderDoSpecularLight( worldPos, worldNormal, fSpecularExponent, vEyeDir,
  369. lightAtten.w, PixelShaderGetLightColor( cLightInfo, 3 ),
  370. PixelShaderGetLightVector( worldPos, cLightInfo, 3 ),
  371. bDoSpecularWarp, specularWarpSampler, fFresnel,
  372. bDoRimLighting, fRimExponent,
  373. localSpecularTerm, localRimTerm );
  374. specularLighting += localSpecularTerm; // Accumulate specular and rim terms
  375. rimLighting += localRimTerm;
  376. }
  377. }
  378. float4_color_return_type main( PS_INPUT i ) : COLOR
  379. {
  380. // Unpacking for convenience
  381. float fWrinkleWeight = i.vProjPos_fWrinkleWeight.w;
  382. float fSSAODepth = i.vProjPos_fWrinkleWeight.z;
  383. float3 vProjPos = i.vProjPos_fWrinkleWeight.xyz;
  384. float3 vWorldPos = i.vWorldPos_vertexFogFactor.xyz;
  385. #if ( CSM_ENABLED ) && defined( SHADER_MODEL_PS_2_B )
  386. float4 vLightAtten = float4( i.lightAtten.xy, 0.0, 0.0 );
  387. #else
  388. float4 vLightAtten = i.lightAtten;
  389. #endif
  390. float3 vWorldNormal = i.vWorldNormal_flTeamIdFade.xyz;
  391. float3 vWorldBinormal = cross( vWorldNormal, i.vWorldTangent.xyz ) * i.vWorldTangent.w;
  392. float4 baseColor = tex2Dsrgb( BaseTextureSampler, i.baseTexCoord_baseTexCoord2.xy );
  393. float flWrinkleAmount, flStretchAmount, flTextureAmount;
  394. #if ( WRINKLEMAP )
  395. {
  396. flWrinkleAmount = saturate( -fWrinkleWeight ); // One of these two is zero
  397. flStretchAmount = saturate( fWrinkleWeight ); // while the other is in the 0..1 range
  398. flTextureAmount = 1.0f - flWrinkleAmount - flStretchAmount; // These should sum to one
  399. float4 wrinkleColor = tex2Dsrgb( WrinkleSampler, i.baseTexCoord_baseTexCoord2.xy );
  400. float4 stretchColor = tex2Dsrgb( StretchSampler, i.baseTexCoord_baseTexCoord2.xy );
  401. // Apply wrinkle blend to only RGB. Alpha comes from the base texture
  402. baseColor.rgb = ( flTextureAmount * baseColor.rgb ) + ( flWrinkleAmount * wrinkleColor.rgb ) + ( flStretchAmount * stretchColor.rgb );
  403. }
  404. #endif
  405. float4 detailColor;
  406. #if ( DETAILTEXTURE )
  407. {
  408. detailColor = tex2D( DetailSampler, i.bumpTexCoord_detailTexCoord.zw );
  409. baseColor = TextureCombine( baseColor, detailColor, DETAIL_BLEND_MODE, g_SelfIllumTint_and_DetailBlendFactorOrPhongAlbedoBoost.w );
  410. }
  411. #endif
  412. float3 lumCoefficients = { 0.3, 0.59, 0.11 };
  413. float baseLum = dot( baseColor.rgb, lumCoefficients );
  414. float fSpecMask = 1.0f;
  415. float4 normalTexel = tex2D( NormalMapSampler, i.bumpTexCoord_detailTexCoord.xy );
  416. #if ( WRINKLEMAP )
  417. {
  418. float4 wrinkleNormal = tex2D( NormalWrinkleSampler, i.baseTexCoord_baseTexCoord2.xy );
  419. float4 stretchNormal = tex2D( NormalStretchSampler, i.baseTexCoord_baseTexCoord2.xy );
  420. normalTexel = flTextureAmount * normalTexel + flWrinkleAmount * wrinkleNormal + flStretchAmount * stretchNormal;
  421. }
  422. #endif
  423. float3 tangentSpaceNormal = 2.0f * normalTexel.xyz - 1.0f;
  424. fSpecMask = lerp( normalTexel.a, baseColor.a, g_fBaseMapAlphaPhongMask );
  425. fSpecMask = lerp( fSpecMask, baseLum, g_fBaseLumPhongMask );
  426. // We need a normal if we're doing any lighting
  427. float3 worldSpaceNormal;
  428. worldSpaceNormal = Vec3TangentToWorld( tangentSpaceNormal.xyz, vWorldNormal, i.vWorldTangent.xyz, vWorldBinormal );
  429. worldSpaceNormal = normalize( worldSpaceNormal );
  430. float3 vEyeDir = normalize( g_EyePos - vWorldPos );
  431. float fFresnelRanges;
  432. fFresnelRanges = Fresnel( worldSpaceNormal, vEyeDir, g_FresnelRanges );
  433. float3 diffuseLighting = float3( 0.0f, 0.0f, 0.0f );
  434. float3 envMapColor = float3( 0.0f, 0.0f, 0.0f );
  435. float flDirectionalShadow = 1.0f;
  436. #if ( CSM_ENABLED )
  437. {
  438. #if !defined( _X360 ) && !defined( _PS3 ) && !defined( SHADER_MODEL_PS_2_B )
  439. if ( g_bCSMEnabled )
  440. {
  441. #endif
  442. #if !defined( _X360 ) && !defined( _PS3 ) && defined( SHADER_MODEL_PS_2_B )
  443. flDirectionalShadow = CSMComputeShadowing( vWorldPos, i.csmXform0or1_csmXform2.xy, i.csmXform0or1_csmXform2.zw, i.staticLight_csmXform0z.w );
  444. #else
  445. flDirectionalShadow = CSMComputeShadowing( vWorldPos );
  446. #endif
  447. #if !defined( _X360 ) && !defined( _PS3 ) && !defined( SHADER_MODEL_PS_2_B )
  448. }
  449. #endif
  450. }
  451. #endif
  452. #if ( !FLASHLIGHT_ONLY ) && defined( SHADER_MODEL_PS_2_B ) && ( CASCADED_SHADOW_MAPPING )
  453. // work around overlapping registers since we're using two of the cLightInfo slots for csm data
  454. // and would like to avoid adding a number of extra protos using PixelShaderLightInfo [2] instead of [3]
  455. // copy to local
  456. PixelShaderLightInfo lightInfo[3];
  457. lightInfo[0] = cLightInfo[0];
  458. lightInfo[1] = cLightInfo[1];
  459. lightInfo[2].pos = float4( 0.0, 0.0, 0.0, 0.0 );
  460. lightInfo[2].color = float4( 0.0, 0.0, 0.0, 0.0 );
  461. #endif
  462. #if ( !FLASHLIGHT_ONLY )
  463. {
  464. float3 staticLighting = float3( 0.0f, 0.0f, 0.0f );
  465. // static lighting - assumption right now is that we're only baking indirect light here
  466. #if STATICLIGHT3
  467. float flSunAmount = 1.0f;
  468. #if defined( SHADER_MODEL_PS_3_0 )
  469. float3 dp;
  470. dp.x = saturate( dot( tangentSpaceNormal, bumpBasis[0] ) );
  471. dp.y = saturate( dot( tangentSpaceNormal, bumpBasis[1] ) );
  472. dp.z = saturate( dot( tangentSpaceNormal, bumpBasis[2] ) );
  473. dp *= dp;
  474. // indirect lighting only baked for phong
  475. staticLighting.rgb = dp.x * i.staticLight0.rgb +
  476. dp.y * i.staticLight1.rgb +
  477. dp.z * i.staticLight2.rgb;
  478. float sum = dot( dp, float3(1.0f, 1.0f, 1.0f) );
  479. #if ( CSM_ENABLED )
  480. {
  481. if ( g_bCSMEnabled )
  482. {
  483. flSunAmount = i.staticLight0.a + i.staticLight1.a + i.staticLight2.a;
  484. if ( flSunAmount > 0.0f )
  485. {
  486. // explicitly add direct term from the CSM light
  487. staticLighting.rgb += g_vCSMLightColor.rgb * ( dp.x * i.staticLight0.a + dp.y * i.staticLight1.a + dp.z * i.staticLight2.a ) * flDirectionalShadow;
  488. }
  489. }
  490. }
  491. #endif
  492. staticLighting.rgb /= sum;
  493. #else
  494. // indirect lighting only baked for phong
  495. staticLighting.rgb = i.staticLight_csmXform0z.rgb;
  496. #if ( CSM_ENABLED )
  497. {
  498. flSunAmount = i.lightAtten.w;
  499. float3 direct = flSunAmount * ( lightInfo[0].color.rgb * 3.0f ); // * 3 to compensate for data in flSunAmount
  500. // add direct term
  501. staticLighting.rgb += direct * flDirectionalShadow;
  502. }
  503. #endif
  504. #endif
  505. // Summation of diffuse illumination from all other local lights
  506. #if defined( SHADER_MODEL_PS_2_B ) && ( CASCADED_SHADOW_MAPPING )
  507. diffuseLighting = PixelShaderDoLighting_STATIC3( vWorldPos, worldSpaceNormal, vLightAtten,
  508. NormalizeRandRotSampler, NUM_LIGHTS, lightInfo, PHONG_HALFLAMBERT,
  509. LIGHTWARPTEXTURE, DiffuseWarpSampler );
  510. #else
  511. diffuseLighting = PixelShaderDoLighting_STATIC3( vWorldPos, worldSpaceNormal, vLightAtten,
  512. NormalizeRandRotSampler, NUM_LIGHTS, cLightInfo, PHONG_HALFLAMBERT,
  513. LIGHTWARPTEXTURE, DiffuseWarpSampler );
  514. #endif
  515. // sunAmount == 0 => vertex is completely occluded, ensure always shadowed as csm's 'fade out'
  516. // required for the specular term later - to avoid specular highlights becoming visible as csm's fade out
  517. flDirectionalShadow *= flSunAmount;
  518. #else
  519. // Summation of diffuse illumination from all local lights
  520. #if defined( SHADER_MODEL_PS_2_B ) && ( CASCADED_SHADOW_MAPPING )
  521. diffuseLighting = PixelShaderDoLighting( vWorldPos, worldSpaceNormal,
  522. float3( 0.0f, 0.0f, 0.0f ), false, true, vLightAtten,
  523. cAmbientCube, NormalizeRandRotSampler, NUM_LIGHTS, lightInfo, PHONG_HALFLAMBERT,
  524. LIGHTWARPTEXTURE, DiffuseWarpSampler, flDirectionalShadow );
  525. #else
  526. diffuseLighting = PixelShaderDoLighting( vWorldPos, worldSpaceNormal,
  527. float3( 0.0f, 0.0f, 0.0f ), false, true, vLightAtten,
  528. cAmbientCube, NormalizeRandRotSampler, NUM_LIGHTS, cLightInfo, PHONG_HALFLAMBERT,
  529. LIGHTWARPTEXTURE, DiffuseWarpSampler, flDirectionalShadow );
  530. #endif
  531. #endif
  532. // add to diffuse
  533. diffuseLighting.rgb += staticLighting.rgb;
  534. #if( CUBEMAP )
  535. {
  536. float3 vReflect = CalcReflectionVectorUnnormalized( worldSpaceNormal, vEyeDir );
  537. envMapColor = ENV_MAP_SCALE * texCUBE( EnvmapSampler, vReflect ).rgb * g_vEnvmapTint.rgb;
  538. // Optionally apply Fresnel to envmap
  539. envMapColor = lerp( envMapColor, fFresnelRanges * envMapColor, g_fEnvMapFresnel );
  540. float fEnvMapMask;
  541. // Mask is either base map alpha or the same as the spec mask which can come from base map, normal map, or spec exponet map
  542. #if ( SELFILLUMFRESNEL == 1 ) // This is to match the 2.0 version of vertexlitgeneric
  543. {
  544. fEnvMapMask = lerp( baseColor.a, g_fInvertPhongMask, g_bHasNormalMapAlphaEnvmapMask );
  545. }
  546. #else
  547. {
  548. fEnvMapMask = lerp( baseColor.a, fSpecMask, g_bHasNormalMapAlphaEnvmapMask );
  549. }
  550. #endif
  551. envMapColor *= lerp( fEnvMapMask, 1-fEnvMapMask, g_fInvertPhongMask );
  552. }
  553. #endif
  554. }
  555. #endif
  556. float fSpecExp = g_fSpecExp;
  557. float4 vSpecExpMap = tex2D( SpecExponentSampler, i.baseTexCoord_baseTexCoord2.xy );
  558. float fSpecExpMap = vSpecExpMap.r;
  559. float fRimMask = 0.0f;
  560. #if ( !FLASHLIGHT_ONLY )
  561. {
  562. fRimMask = lerp( 1.0f, vSpecExpMap.a, g_RimMaskControl ); // Select rim mask
  563. }
  564. #endif
  565. // If the exponent passed in as a constant is zero, use the value from the map as the exponent
  566. #if defined( _X360 )
  567. [flatten]
  568. #endif
  569. if ( fSpecExp == 0 )
  570. fSpecExp = 1.0f - fSpecExpMap + 150.0f * fSpecExpMap;
  571. float3 vSpecularTint;
  572. // If constant tint is negative, tint with albedo, based upon scalar tint map
  573. #if defined( _X360 )
  574. [flatten]
  575. #endif
  576. if ( g_SpecularTint.r < 0 )
  577. {
  578. #if ( DETAILTEXTURE )
  579. vSpecularTint = g_SpecularBoost * lerp( float3( 1.0f, 1.0f, 1.0f ), baseColor.rgb, vSpecExpMap.g );
  580. #else
  581. vSpecularTint = lerp( ( float3 )g_SpecularBoost, g_SelfIllumTint_and_DetailBlendFactorOrPhongAlbedoBoost.w * baseColor.rgb, vSpecExpMap.g );
  582. #if( CUBEMAP )
  583. envMapColor = fSpecExpMap * lerp( envMapColor, envMapColor * baseColor.rgb * g_SelfIllumTint_and_DetailBlendFactorOrPhongAlbedoBoost.w, vSpecExpMap.g );
  584. #endif
  585. #endif
  586. }
  587. else
  588. vSpecularTint = g_SpecularBoost * g_SpecularTint.rgb;
  589. #if ( PHONGWARPTEXTURE )
  590. {
  591. fFresnelRanges = Fresnel( worldSpaceNormal, vEyeDir, g_FresnelRanges );
  592. }
  593. #endif
  594. float3 albedo = baseColor.rgb;
  595. float3 specularLighting = float3( 0.0f, 0.0f, 0.0f );
  596. float3 rimLighting = float3( 0.0f, 0.0f, 0.0f );
  597. #if ( !FLASHLIGHT_ONLY )
  598. {
  599. float3 specularLightingFromPhong;
  600. // Summation of specular from all local lights besides the flashlight
  601. #if STATICLIGHT3
  602. #if defined( SHADER_MODEL_PS_2_B ) && ( CASCADED_SHADOW_MAPPING )
  603. PixelShaderDoSpecularLighting_STATIC3( vWorldPos, worldSpaceNormal,
  604. fSpecExp, vEyeDir, vLightAtten,
  605. NUM_LIGHTS, lightInfo, PHONGWARPTEXTURE, SpecularWarpSampler, fFresnelRanges, RIMLIGHT, g_RimExponent,
  606. flDirectionalShadow,
  607. // Outputs
  608. specularLightingFromPhong, rimLighting );
  609. #else
  610. PixelShaderDoSpecularLighting_STATIC3( vWorldPos, worldSpaceNormal,
  611. fSpecExp, vEyeDir, vLightAtten,
  612. NUM_LIGHTS, cLightInfo, PHONGWARPTEXTURE, SpecularWarpSampler, fFresnelRanges, RIMLIGHT, g_RimExponent,
  613. flDirectionalShadow,
  614. // Outputs
  615. specularLightingFromPhong, rimLighting );
  616. #endif
  617. #else
  618. #if defined( SHADER_MODEL_PS_2_B ) && ( CASCADED_SHADOW_MAPPING )
  619. PixelShaderDoSpecularLighting( vWorldPos, worldSpaceNormal,
  620. fSpecExp, vEyeDir, vLightAtten,
  621. NUM_LIGHTS, lightInfo, PHONGWARPTEXTURE, SpecularWarpSampler, fFresnelRanges, RIMLIGHT, g_RimExponent,
  622. flDirectionalShadow,
  623. // Outputs
  624. specularLightingFromPhong, rimLighting );
  625. #else
  626. PixelShaderDoSpecularLighting( vWorldPos, worldSpaceNormal,
  627. fSpecExp, vEyeDir, vLightAtten,
  628. NUM_LIGHTS, cLightInfo, PHONGWARPTEXTURE, SpecularWarpSampler, fFresnelRanges, RIMLIGHT, g_RimExponent,
  629. flDirectionalShadow,
  630. // Outputs
  631. specularLightingFromPhong, rimLighting );
  632. #endif
  633. #endif
  634. specularLighting += specularLightingFromPhong;
  635. }
  636. #endif
  637. #if ( FLASHLIGHT )
  638. {
  639. float4 flashlightSpacePosition = TransformFlashlightWorldToTexture( vWorldPos, g_FlashlightWorldToTexture );
  640. float3 diffuseLightingFromFlashlight;
  641. float3 specularLightingFromFlashlight;
  642. DoSpecularFlashlight( g_FlashlightPos, vWorldPos, flashlightSpacePosition, worldSpaceNormal,
  643. g_FlashlightAttenuationFactors.xyz, g_FlashlightAttenuationFactors.w,
  644. FlashlightSampler, ShadowDepthSampler, NormalizeRandRotSampler, FLASHLIGHTDEPTHFILTERMODE, FLASHLIGHTSHADOWS, vProjPos.xy / vProjPos.z,
  645. fSpecExp, vEyeDir, LIGHTWARPTEXTURE, DiffuseWarpSampler, PHONGWARPTEXTURE, SpecularWarpSampler, fFresnelRanges, g_vShadowTweaks,
  646. // These two values are output
  647. diffuseLightingFromFlashlight, specularLightingFromFlashlight );
  648. #if ( UBERLIGHT )
  649. {
  650. float4 uberLightPosition = mul( float4( vWorldPos, 1.0f ), g_FlashlightWorldToLight ).yzxw;
  651. float fUber = uberlight( uberLightPosition.xyz, g_vSmoothEdge0, g_vSmoothEdge1,
  652. g_vSmoothOneOverWidth, g_vShearRound.xy, g_aAbB, g_vShearRound.zw );
  653. diffuseLightingFromFlashlight *= fUber;
  654. specularLightingFromFlashlight *= fUber;
  655. }
  656. #endif
  657. specularLighting += specularLightingFromFlashlight;
  658. diffuseLighting += diffuseLightingFromFlashlight;
  659. }
  660. #endif
  661. // Modulate with spec mask and tint (modulated by boost above)
  662. specularLighting *= fSpecMask * vSpecularTint;
  663. // If we didn't already apply Fresnel to specular warp, modulate the specular
  664. #if ( !PHONGWARPTEXTURE )
  665. {
  666. specularLighting *= fFresnelRanges;
  667. }
  668. #endif
  669. #if ( DECAL_BLEND_MODE != 2 )
  670. float3 decalLighting = diffuseLighting;
  671. #endif
  672. #if ( TINTMASKTEXTURE )
  673. // Optionally use inverseblendtint texture to blend in the diffuse modulation (saturated add of g_fInverseBlendTintByBaseAlpha turns this on/off)
  674. float tintMask = h4tex2Dsrgb( TintMaskSampler, i.baseTexCoord_baseTexCoord2.xy ).g; // use g channel since common use will be mono or dxt1 (greater precision in g).
  675. diffuseLighting *= lerp( float3( 1.0h, 1.0h, 1.0h ), g_DiffuseModulation.rgb, saturate( tintMask + g_fInverseBlendTintByBaseAlpha ) );
  676. #else
  677. // Optionally use basealpha to blend in the diffuse modulation (saturated add of g_fInverseBlendTintByBaseAlpha turns this on/off)
  678. diffuseLighting *= lerp( float3( 1.0f, 1.0f, 1.0f ), g_DiffuseModulation.rgb, saturate( baseColor.a + g_fInverseBlendTintByBaseAlpha ) );
  679. #endif
  680. float3 diffuseComponent = albedo * diffuseLighting;
  681. #if ( SELFILLUM && !FLASHLIGHT_ONLY )
  682. {
  683. #if ( SELFILLUMFRESNEL == 1 ) // To free up the constant register...see top of file
  684. {
  685. /* CS:GO - hijacking this for team ID glows and moving later in the shader after tonemapping
  686. // This will apply a Fresnel term based on the vertex normal (not the per-pixel normal!) to help fake and internal glow look
  687. float3 vVertexNormal = normalize( float3( i.tangentSpaceTranspose[0].z, i.tangentSpaceTranspose[1].z, i.tangentSpaceTranspose[2].z ) );
  688. float3 vSelfIllumMask = tex2D( SelfIllumMaskSampler, i.baseTexCoord_baseTexCoord2.xy ).rgb;
  689. vSelfIllumMask = lerp( baseColor.aaa, vSelfIllumMask, g_SelfIllumMaskControl );
  690. float flSelfIllumFresnel = ( pow( saturate( dot( vVertexNormal.xyz, vEyeDir.xyz ) ), g_SelfIllumScaleBiasExpBrightness.z ) * g_SelfIllumScaleBiasExpBrightness.x ) + g_SelfIllumScaleBiasExpBrightness.y;
  691. diffuseComponent = lerp( diffuseComponent, g_SelfIllumTint_and_DetailBlendFactorOrPhongAlbedoBoost.rgb * albedo * g_SelfIllumScaleBiasExpBrightness.w, vSelfIllumMask.rgb * saturate( flSelfIllumFresnel ) );
  692. */
  693. }
  694. #else
  695. {
  696. float3 vSelfIllumMask = tex2D( SelfIllumMaskSampler, i.baseTexCoord_baseTexCoord2.xy ).rgb;
  697. vSelfIllumMask = lerp( baseColor.aaa, vSelfIllumMask, g_SelfIllumMaskControl );
  698. diffuseComponent = lerp( diffuseComponent, g_SelfIllumTint_and_DetailBlendFactorOrPhongAlbedoBoost.rgb * albedo, vSelfIllumMask );
  699. }
  700. #endif
  701. diffuseComponent = max( 0.0f, diffuseComponent );
  702. }
  703. #endif
  704. #if ( DETAILTEXTURE )
  705. {
  706. diffuseComponent = TextureCombinePostLighting( diffuseComponent, detailColor, DETAIL_BLEND_MODE, g_SelfIllumTint_and_DetailBlendFactorOrPhongAlbedoBoost.w );
  707. }
  708. #endif
  709. #if ( RIMLIGHT && !FLASHLIGHT_ONLY )
  710. {
  711. float fRimFresnel = Fresnel4( worldSpaceNormal, vEyeDir );
  712. // Add in rim light modulated with tint, mask and traditional Fresnel (not using Fresnel ranges)
  713. rimLighting *= fRimMask * fRimFresnel;
  714. // Fold rim lighting into specular term by using the max so that we don't really add light twice...
  715. specularLighting = max( specularLighting, rimLighting );
  716. // Add in view-ray lookup from ambient cube
  717. specularLighting += fRimFresnel * fRimMask * g_fRimBoost * PixelShaderAmbientLight( vEyeDir, cAmbientCube) * saturate(dot(worldSpaceNormal, float3(0, 0 , 1)) );
  718. }
  719. #endif
  720. // Screen-space dynamic ambient occlusion on PC
  721. float fAmbientOcclusion = 1.0f;
  722. #if ( SFM )
  723. {
  724. fAmbientOcclusion = lerp( 1.0f, tex2D( AmbientOcclusionSampler, ComputeScreenPos( i.vPos ) ).r, g_fAmbientOcclusionStrength );
  725. }
  726. #endif
  727. #if ( DECAL_BLEND_MODE != 2 )
  728. float4 decalColor = tex2D( DecalSampler, i.baseTexCoord_baseTexCoord2.zw );
  729. diffuseComponent = TextureCombineDecal( diffuseComponent, decalColor, decalLighting );
  730. #endif
  731. float3 result = (specularLighting + envMapColor + diffuseComponent) * fAmbientOcclusion;
  732. float flVertexFogFactor = 0.0f;
  733. #if ( !HARDWAREFOGBLEND && !DOPIXELFOG )
  734. {
  735. flVertexFogFactor = i.vWorldPos_vertexFogFactor.w;
  736. }
  737. #endif
  738. float fogFactor = CalcPixelFogFactorSupportsVertexFog( PIXELFOGTYPE, g_FogParams, g_EyePos_SpecExponent.xyz, vWorldPos.xyz, vProjPos.z, flVertexFogFactor );
  739. float alpha;
  740. #if ( WRITEWATERFOGTODESTALPHA && ( PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) )
  741. {
  742. alpha = fogFactor;
  743. }
  744. #else
  745. {
  746. alpha = g_DiffuseModulation.a;
  747. // Want to multiply by 1.0 if we are using base alpha for anything that isn't translucency.
  748. float fBaseAlphaIsForTranslucency = 1.0f;
  749. #if ( SELFILLUM )
  750. // If we are selfillum, base alpha can only be used for translucency if we have a separate selfillummask
  751. fBaseAlphaIsForTranslucency *= g_SelfIllumMaskControl;
  752. #endif
  753. // Can't use base alpha for translucency if it's being used for a phong mask.
  754. fBaseAlphaIsForTranslucency *= ( 1.0f - g_fBaseMapAlphaPhongMask );
  755. // Can't use base alpha for translucency if it's being used to control diffuse/alpha modulation
  756. fBaseAlphaIsForTranslucency *= g_fInverseBlendTintByBaseAlpha;
  757. // Lerp between 1.0f and baseColor.a based on if we are using the basealpha for translucency.
  758. alpha *= lerp( 1.0f, baseColor.a, fBaseAlphaIsForTranslucency );
  759. }
  760. #endif
  761. bool bWriteDepthToAlpha = ( WRITE_DEPTH_TO_DESTALPHA != 0 ) && ( WRITEWATERFOGTODESTALPHA == 0 );
  762. #if ( WORLD_NORMAL )
  763. {
  764. return float4( worldSpaceNormal, fSSAODepth );
  765. }
  766. #else
  767. {
  768. //FIXME: need to take dowaterfog into consideration
  769. float4_color_return_type vOutput = FinalOutput( float4( result, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, vProjPos.z );
  770. //----------------------------------//
  771. // CS:GO Team ID reflective patches //
  772. //----------------------------------//
  773. #if ( SELFILLUM && !FLASHLIGHT_ONLY && ( SELFILLUMFRESNEL == 1 ) )
  774. {
  775. // Purposely doing this after fog and tonemapping are applied in FinalOutput() above. We want this to be a hud-like effect.
  776. float3 vSelfIllumMask = tex2D( SelfIllumMaskSampler, i.baseTexCoord_baseTexCoord2.xy ).rgb;
  777. vSelfIllumMask *= g_SelfIllumMaskControl; // This is set by the proxy to 1 or 0 depending which team this player is on
  778. vSelfIllumMask *= ( i.vWorldNormal_flTeamIdFade.w * i.vWorldNormal_flTeamIdFade.w ) + 0.01; // Distance fade so it's brighter farther away
  779. float flSelfIllumFresnel = ( pow( saturate( dot( worldSpaceNormal.xyz, vEyeDir.xyz ) ), g_SelfIllumScaleBiasExpBrightness.z ) * g_SelfIllumScaleBiasExpBrightness.x ) + g_SelfIllumScaleBiasExpBrightness.y;
  780. vOutput.rgb = lerp( vOutput.rgb, g_SelfIllumTint_and_DetailBlendFactorOrPhongAlbedoBoost.rgb * g_SelfIllumScaleBiasExpBrightness.w, vSelfIllumMask.rgb * saturate( flSelfIllumFresnel ) );
  781. }
  782. #endif
  783. #if ( defined( _X360 ) )
  784. {
  785. vOutput.xyz += ScreenSpaceOrderedDither( i.vPos );
  786. }
  787. #endif
  788. return vOutput;
  789. }
  790. #endif
  791. }