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.

763 lines
27 KiB

  1. //===================== Copyright (c) Valve Corporation. All Rights Reserved. ======================
  2. // STATIC: "BUMPMAP" "0..2"
  3. // STATIC: "BUMPMAP2" "0..1"
  4. // STATIC: "CUBEMAP" "0..2"
  5. // STATIC: "ENVMAPMASK" "0..1"
  6. // STATIC: "BASEALPHAENVMAPMASK" "0..1"
  7. // STATIC: "SELFILLUM" "0..1"
  8. // STATIC: "SEAMLESS" "0..1"
  9. // STATIC: "ENVMAPANISOTROPY" "0..1"
  10. // STATIC: "TEXTURE3_BLENDMODE" "0..1"
  11. // STATIC: "TEXTURE4_BLENDMODE" "0..1"
  12. // diffuse bump map is always true when bumpmapping is enabled, so just set it to 1
  13. #define DIFFUSEBUMPMAP 1
  14. // STATIC: "DETAIL_BLEND_MODE" "0..12"
  15. // STATIC: "FLASHLIGHT" "0..1" [ps20b] [CONSOLE]
  16. // STATIC: "SHADER_SRGB_READ" "0..1" [XBOX]
  17. // STATIC: "SHADER_SRGB_READ" "0..0" [PC]
  18. // STATIC: "SHADER_SRGB_READ" "0..0" [SONYPS3]
  19. // STATIC: "LIGHTING_PREVIEW" "0..3" [PC]
  20. // STATIC: "LIGHTING_PREVIEW" "0..0" [CONSOLE]
  21. // STATIC: "CASCADED_SHADOW_MAPPING" "0..1" [ = g_pHardwareConfig->SupportsCascadedShadowMapping() ] [CONSOLE]
  22. // STATIC: "CASCADED_SHADOW_MAPPING" "0..0" [ = 0 ] [ps20] [PC]
  23. // STATIC: "CASCADED_SHADOW_MAPPING" "0..1" [ = g_pHardwareConfig->SupportsCascadedShadowMapping() && !ToolsEnabled() ] [ps20b] [ps30] [PC]
  24. // STATIC: "CSM_MODE" "0..0" [ = 0 ] [CONSOLE]
  25. // STATIC: "CSM_MODE" "0..0" [ = 0 ] [ps20] [ps20b] [PC]
  26. // STATIC: "CSM_MODE" "0..3" [ps30] [PC]
  27. // STATIC: "CSM_BLENDING" "0..1" // 0 is old, 1 is for new/fixed blending of CSM and baked shadows
  28. // DYNAMIC: "FASTPATHENVMAPCONTRAST" "0..1"
  29. // DYNAMIC: "FASTPATH" "0..1"
  30. // DYNAMIC: "WRITEWATERFOGTODESTALPHA" "0..1"
  31. // DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..0" [ps20b] [CONSOLE]
  32. // DYNAMIC: "WRITE_DEPTH_TO_DESTALPHA" "0..1" [ps20b] [ps30] [PC]
  33. // DYNAMIC: "FLASHLIGHTSHADOWS" "0..1" [ps20b] [CONSOLE]
  34. // DYNAMIC: "FLASHLIGHTSHADOWS" "0..0" [ps20b] [ps30] [PC]
  35. // DYNAMIC: "CASCADE_SIZE" "0..1" [ = ( pShaderAPI->IsCascadedShadowMapping() ) ? 1 : 0 ] [CONSOLE]
  36. // DYNAMIC: "CASCADE_SIZE" "0..1" [ = ( pShaderAPI->IsCascadedShadowMapping() ) ? 1 : 0 ] [ps20b] [PC]
  37. // DYNAMIC: "CASCADE_SIZE" "0..0" [ = 0 ] [ps20] [ps30] [PC]
  38. // we only support detail blend modes 0, 7, 10, 11, and 12
  39. // SKIP: ($DETAIL_BLEND_MODE == 1 )
  40. // SKIP: ($DETAIL_BLEND_MODE == 2 )
  41. // SKIP: ($DETAIL_BLEND_MODE == 3 )
  42. // SKIP: ($DETAIL_BLEND_MODE == 4 )
  43. // SKIP: ($DETAIL_BLEND_MODE == 5 )
  44. // SKIP: ($DETAIL_BLEND_MODE == 6 )
  45. // SKIP: ($DETAIL_BLEND_MODE == 8 )
  46. // SKIP: ($DETAIL_BLEND_MODE == 9 )
  47. // SKIP: ( $FLASHLIGHT == 0 ) && ( $FLASHLIGHTSHADOWS == 1 )
  48. // program too complex for ps20. Don't do darkened cubemaps and 2 bump maps at the same time. Fairly arbitrary pairing just to get the damn thing compiling
  49. // SKIP: ( $CUBEMAP == 2 ) && ( $BUMPMAP2 ) [ps20]
  50. // program slightly more complex on 360 because of shader srgb read. Eliminate coexistance of srgb read, water fog, and darkened cubemaps
  51. // SKIP: ( $CUBEMAP == 2 ) && ( $PIXELFOGTYPE == 1 ) && ( $SHADER_SRGB_READ == 1 ) [CONSOLE]
  52. // SKIP: ( $CASCADED_SHADOW_MAPPING == 0 ) && ( $CASCADE_SIZE != 0 )
  53. // SKIP: ( $CASCADED_SHADOW_MAPPING != 0 ) && ( $SFM != 0 )
  54. // SKIP: ( $CASCADED_SHADOW_MAPPING == 0 ) && ( $CSM_MODE != 0 )
  55. // SKIP: $ENVMAPMASK && $BUMPMAP
  56. // SKIP: $BASEALPHAENVMAPMASK && $ENVMAPMASK
  57. // SKIP: $BASEALPHAENVMAPMASK && $SELFILLUM
  58. // SKIP: !$FASTPATH && $FASTPATHENVMAPCONTRAST
  59. // SKIP: !$FASTPATH && $FASTPATHENVMAPTINT
  60. // SKIP: !$BUMPMAP && $BUMPMAP2
  61. // SKIP: $ENVMAPMASK && $BUMPMAP2
  62. // SKIP: $SEAMLESS && ( $DETAIL_BLEND_MODE != 12 )
  63. // SKIP: $ENVMAPANISOTROPY && !$ENVMAP && ( $BUMPMAP != 1 )
  64. // SKIP: $ENVMAPANISOTROPY && $NORMALMAPALPHAENVMAPMASK
  65. // Turning off 32bit lightmaps on Portal 2 to save shader perf. --Thorsten
  66. //#define USE_32BIT_LIGHTMAPS_ON_360 //uncomment to use 32bit lightmaps, be sure to keep this in sync with the same #define in materialsystem/cmatlightmaps.cpp
  67. // NOTE: This has to be before inclusion of common_multiblend_fxc.h to get the vertex format right!
  68. #if ( DETAIL_BLEND_MODE == 12 )
  69. #define DETAILTEXTURE 0
  70. #else
  71. #define DETAILTEXTURE 1
  72. #endif
  73. #include "common_fog_ps_supportsvertexfog_fxc.h"
  74. #include "common_ps_fxc.h"
  75. #include "common_flashlight_fxc.h"
  76. #define PIXELSHADER
  77. #include "common_4wayblend_fxc.h"
  78. #if SEAMLESS
  79. #define USE_FAST_PATH 1
  80. #else
  81. #define USE_FAST_PATH FASTPATH
  82. #endif
  83. const float4 g_EnvmapTint : register( c0 );
  84. // 4WayBlend specific constants
  85. const float3 g_BumpBlendFactors : register( c1 );
  86. const float4 g_LumStartEnd12 : register( c5 );
  87. const float4 g_LumStartEnd34 : register( c28 );
  88. const float4 g_BlendStartEnd23 : register( c15 );
  89. const float4 g_uvScales23 : register( c16 );
  90. const float4 g_BlendStartEnd4_uvScales4 : register( c17 );
  91. const float3 g_LumBlends : register( c18 );
  92. #if ( USE_FAST_PATH == 1 )
  93. #if FASTPATHENVMAPCONTRAST == 0
  94. static const float3 g_EnvmapContrast = { 0.0f, 0.0f, 0.0f };
  95. #else
  96. static const float3 g_EnvmapContrast = { 1.0f, 1.0f, 1.0f };
  97. #endif
  98. static const float3 g_EnvmapSaturation = { 1.0f, 1.0f, 1.0f };
  99. static const float g_FresnelReflection = 1.0f;
  100. static const float g_OneMinusFresnelReflection = 0.0f;
  101. static const float4 g_SelfIllumTint = { 1.0f, 1.0f, 1.0f, 1.0f };
  102. #else // ( USE_FAST_PATH == 0 )
  103. const float3 g_EnvmapContrast : register( c2 );
  104. const float3 g_EnvmapSaturation : register( c3 );
  105. const float4 g_FresnelReflectionReg : register( c4 );
  106. #define g_FresnelReflection g_FresnelReflectionReg.a
  107. #define g_OneMinusFresnelReflection g_FresnelReflectionReg.b
  108. const float4 g_SelfIllumTint : register( c7 );
  109. #endif
  110. const float3 g_DetailTint : register( c8 );
  111. const float4 g_DetailBlendFactors : register( c9 );
  112. const float3 g_EyePos : register( c10 );
  113. const float4 g_FogParams : register( c11 );
  114. const float4 g_TintValuesTimesLightmapScale : register( c12 );
  115. const float4 g_FlashlightAttenuationFactors : register( c13 );
  116. const float3 g_FlashlightPos : register( c14 );
  117. const float4 g_ShadowTweaks : register( c19 );
  118. #if !defined( SHADER_MODEL_PS_2_0 ) && ( FLASHLIGHT == 0 )
  119. #define g_cAmbientColor cFlashlightScreenScale.rgb
  120. //const float3 g_cAmbientColor : register( c31 );
  121. #endif
  122. #if ( ( CUBEMAP == 2 ) || ( ENVMAPANISOTROPY ) )
  123. const float4 g_envMapParams : register( c20 );
  124. #endif
  125. #if ( CUBEMAP == 2 )
  126. #define g_DiffuseCubemapScale g_envMapParams.y
  127. #define g_fvDiffuseCubemapMin float3( g_envMapParams.z, g_envMapParams.z, g_envMapParams.z )
  128. #define g_fvDiffuseCubemapMax float3( g_envMapParams.w, g_envMapParams.w, g_envMapParams.w )
  129. #endif
  130. #if ( ENVMAPANISOTROPY )
  131. #define g_EnvmapAnisotropyScale g_envMapParams.x
  132. #endif
  133. #if defined( SHADER_MODEL_PS_3_0 )
  134. const float3 g_TintValuesWithoutLightmapScale : register( c21 );
  135. #else
  136. const float4 g_vCSMLightColor : register( c21 );
  137. #endif
  138. // c22 - c27 available
  139. sampler BaseTextureSampler : register( s0 );
  140. sampler LightmapSampler : register( s1 );
  141. samplerCUBE EnvmapSampler : register( s2 );
  142. #if DETAILTEXTURE
  143. sampler DetailSampler : register( s12 );
  144. #endif
  145. sampler BumpmapSampler : register( s4 );
  146. #if (BUMPMAP == 1) && defined( _PS3 )
  147. // Causes the Cg compiler to automatically produce _bx2 modifier on the texture load instead of producing a MAD to range expand the vector, saving one instruction.
  148. #pragma texsign BumpmapSampler
  149. #pragma texformat BumpmapSampler RGBA8
  150. #endif
  151. #if BUMPMAP2 == 1
  152. sampler BumpmapSampler2 : register( s5 );
  153. #else
  154. sampler EnvmapMaskSampler : register( s5 );
  155. #endif
  156. sampler BaseTextureSampler2 : register( s7 );
  157. sampler BaseTextureSampler3 : register( s8 );
  158. sampler BaseTextureSampler4 : register( s11 );
  159. #if ( defined( _X360 ) || defined( _PS3 ) ) && FLASHLIGHT
  160. sampler FlashlightSampler : register( s13 );
  161. sampler ShadowDepthSampler : register( s14 );
  162. sampler RandRotSampler : register( s15 );
  163. #if defined(_PS3)
  164. // Needed for optimal shadow filter code generation on PS3.
  165. #pragma texformat ShadowDepthSampler DEPTH_COMPONENT24
  166. #endif
  167. #endif
  168. //const float g_flTime : register( c27 );
  169. float Luminance( float3 cColor )
  170. {
  171. // Formula for calculating luminance based on NTSC standard
  172. return dot( cColor.rgb, float3( 0.2125, 0.7154, 0.0721 ) );
  173. }
  174. //-----------------------------------------------------------------------------------------------------------------------------
  175. #if ( CASCADED_SHADOW_MAPPING ) && !defined( _X360 ) && !defined( _PS3 ) && !defined( SHADER_MODEL_PS_2_B )
  176. const bool g_bCSMEnabled : register(b0);
  177. #undef CASCADE_SIZE
  178. #define CASCADE_SIZE 1
  179. #endif
  180. #if ( CASCADE_SIZE > 0 )
  181. #undef CASCADE_SIZE
  182. #define CASCADE_SIZE 3
  183. #endif
  184. #if ( ( CASCADED_SHADOW_MAPPING ) && ( CASCADE_SIZE > 0 ) )
  185. sampler CSMDepthAtlasSampler : register( s15 );
  186. #if defined(_PS3)
  187. // Needed for optimal shadow filter code generation on PS3.
  188. #pragma texformat CSMDepthAtlasSampler DEPTH_COMPONENT24
  189. #endif
  190. #define CSM_LIGHTMAPPEDGENERIC
  191. #include "csm_common_fxc.h"
  192. #include "csm_blending_fxc.h"
  193. #endif
  194. //-----------------------------------------------------------------------------------------------------------------------------
  195. #if defined( _X360 )
  196. // The compiler runs out of temp registers in certain combos, increase the maximum for now
  197. #if ( (BUMPMAP == 2) && CUBEMAP && DIFFUSEBUMPMAP && FLASHLIGHT && SHADER_SRGB_READ )
  198. [maxtempreg(44)]
  199. #elif ( SHADER_SRGB_READ == 1 )
  200. [maxtempreg(41)]
  201. #else
  202. [maxtempreg(36)]
  203. #endif
  204. #endif
  205. #if LIGHTING_PREVIEW == 2
  206. LPREVIEW_PS_OUT main( PS_INPUT i )
  207. #else
  208. float4_color_return_type main( PS_INPUT i ) : COLOR
  209. #endif
  210. {
  211. bool bDetailTexture = DETAILTEXTURE ? true : false;
  212. bool bBumpmap = BUMPMAP ? true : false;
  213. bool bDiffuseBumpmap = DIFFUSEBUMPMAP ? true : false;
  214. bool bEnvmapMask = ENVMAPMASK ? true : false;
  215. bool bBaseAlphaEnvmapMask = BASEALPHAENVMAPMASK ? true : false;
  216. bool bSelfIllum = SELFILLUM ? true : false;
  217. HALF4 baseColor = 0.0h;
  218. HALF4 baseColor2 = 0.0h;
  219. HALF4 baseColor3 = 0.0h;
  220. HALF4 baseColor4 = 0.0h;
  221. HALF4 vNormal = HALF4(0, 0, 1, 1);
  222. float3 baseTexCoords = float3(0,0,0);
  223. float3 worldPos = i.worldPos_projPosZ.xyz;
  224. HALF3x3 tangenttranspose = (HALF3x3)i.tangentSpaceTranspose;
  225. float3 worldVertToEyeVector = g_EyePos - worldPos;
  226. #if SEAMLESS
  227. baseTexCoords = i.SeamlessTexCoord_fogFactorW.xyz;
  228. #else
  229. baseTexCoords.xy = i.BASETEXCOORD.xy;
  230. #endif
  231. float3 coords = baseTexCoords;
  232. float2 detailTexCoord = 0.0f;
  233. float2 bumpmapTexCoord = 0.0f;
  234. float2 bumpmap2TexCoord = 0.0f;
  235. #if ( DETAILTEXTURE == 1 )
  236. detailTexCoord = i.DETAILCOORDS;
  237. #endif
  238. #if BUMPMAP
  239. bumpmapTexCoord = i.BUMPCOORDS;
  240. #endif
  241. GetBaseTextureAndNormal( BaseTextureSampler, BaseTextureSampler2, BaseTextureSampler3, BaseTextureSampler4, BumpmapSampler,
  242. bBumpmap, coords, bumpmapTexCoord, g_uvScales23, g_BlendStartEnd4_uvScales4.zw,
  243. (HALF3)i.vertexColor.rgb, baseColor, baseColor2, baseColor3, baseColor4, vNormal );
  244. #if ( ENVMAPANISOTROPY )
  245. HALF anisotropyFactor = g_EnvmapAnisotropyScale;
  246. #endif
  247. #if BUMPMAP == 1 // not ssbump
  248. vNormal.xyz = vNormal.xyz * 2.0h - 1.0h; // make signed if we're not ssbump
  249. HALF3 vThisReallyIsANormal = vNormal.xyz;
  250. #if ( ENVMAPANISOTROPY )
  251. anisotropyFactor *= (HALF)vNormal.a;
  252. #endif
  253. #endif
  254. HALF4 lightmapColor1 = HALF4( 1.0, 1.0, 1.0, 1.0 );
  255. HALF4 lightmapColor2 = HALF4( 1.0, 1.0, 1.0, 1.0 );
  256. HALF4 lightmapColor3 = HALF4( 1.0, 1.0, 1.0, 1.0 );
  257. #if LIGHTING_PREVIEW == 0
  258. if ( bBumpmap && bDiffuseBumpmap )
  259. {
  260. float2 bumpCoord1;
  261. float2 bumpCoord2;
  262. float2 bumpCoord3;
  263. ComputeBumpedLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy,
  264. bumpCoord1, bumpCoord2, bumpCoord3 );
  265. lightmapColor1 = LightMapSample( LightmapSampler, bumpCoord1 );
  266. lightmapColor2 = LightMapSample( LightmapSampler, bumpCoord2 );
  267. lightmapColor3 = LightMapSample( LightmapSampler, bumpCoord3 );
  268. }
  269. else
  270. {
  271. float2 bumpCoord1 = ComputeLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3.xy );
  272. lightmapColor1 = LightMapSample( LightmapSampler, bumpCoord1 );
  273. }
  274. #endif
  275. float2 envmapMaskTexCoord = i.ENVMAPMASKCOORDS;
  276. HALF4 detailColor = HALF4( 1.0f, 1.0f, 1.0f, 1.0f );
  277. #if DETAILTEXTURE
  278. #if SHADER_MODEL_PS_2_0
  279. detailColor = h4tex2D( DetailSampler, detailTexCoord );
  280. #else
  281. detailColor = HALF4( g_DetailTint, 1.0h ) * h4tex2D( DetailSampler, detailTexCoord );
  282. #endif
  283. #endif
  284. float lum1 = smoothstep( g_LumStartEnd12.x, g_LumStartEnd12.y, Luminance( baseColor.rgb ) );
  285. float lum2 = smoothstep( g_LumStartEnd12.z, g_LumStartEnd12.w, Luminance( baseColor2.rgb ) );
  286. float lum3 = smoothstep( g_LumStartEnd34.x, g_LumStartEnd34.y, Luminance( baseColor3.rgb ) );
  287. float lum4 = smoothstep( g_LumStartEnd34.z, g_LumStartEnd34.w, Luminance( baseColor4.rgb ) );
  288. float lum = lerp( 1-lum1, lum2, g_LumBlends.x );
  289. float blendfactor1 = i.vertexBlend.g * lum + i.vertexBlend.g;
  290. blendfactor1 = smoothstep( g_BlendStartEnd23.x, g_BlendStartEnd23.y, blendfactor1 );
  291. float lums = lerp( lum1, lum2, blendfactor1 );
  292. lum = lerp( 1-lums, lum3, g_LumBlends.y );
  293. float blendfactor2 = i.vertexBlend.b * lum + i.vertexBlend.b;
  294. blendfactor2 = smoothstep( g_BlendStartEnd23.z, g_BlendStartEnd23.w, blendfactor2 );
  295. lums = lerp( lums, lum3, blendfactor2 );
  296. lum = lerp( 1-lums, lum4, g_LumBlends.z );
  297. float blendfactor3 = i.vertexBlend.a * lum + i.vertexBlend.a;
  298. blendfactor3 = smoothstep( g_BlendStartEnd4_uvScales4.x, g_BlendStartEnd4_uvScales4.y, blendfactor3 );
  299. //#if LIGHTING_PREVIEW == 0
  300. // return float4(blendfactor3, blendfactor3, blendfactor3, 1.0f);
  301. //#endif
  302. baseColor = lerp( baseColor, baseColor2, blendfactor1 );
  303. #if ( TEXTURE3_BLENDMODE == 0 ) // blend
  304. baseColor = lerp( baseColor, baseColor3, blendfactor2 );
  305. #endif
  306. #if ( TEXTURE3_BLENDMODE == 1 ) // multiply 2x
  307. baseColor *= lerp( 1, baseColor3 + baseColor3, blendfactor2 );
  308. #endif
  309. #if ( TEXTURE4_BLENDMODE == 0 ) // blend
  310. baseColor = lerp( baseColor, baseColor4, blendfactor3 );
  311. #endif
  312. #if ( TEXTURE4_BLENDMODE == 1 ) // multiply 2x
  313. baseColor *= lerp( 1, baseColor4 + baseColor4, blendfactor3 );
  314. #endif
  315. HALF3 specularFactor = 1.0h;
  316. if ( bBumpmap )
  317. {
  318. float fBumpBlendFactor = 1.0f;
  319. #if ( BUMPMAP2 == 1 )
  320. {
  321. float2 b2TexCoord = bumpmapTexCoord * g_uvScales23.xy;
  322. HALF4 vNormal2;
  323. #if ( BUMPMAP == 2 ) // ssbump mode
  324. {
  325. vNormal2 = h4tex2D( BumpmapSampler2, b2TexCoord );
  326. vNormal.xyz = lerp( vNormal.xyz, vNormal2.xyz, blendfactor1 );
  327. }
  328. #else
  329. {
  330. HALF4 normalTexel = h4tex2D( BumpmapSampler2, b2TexCoord );
  331. vNormal2 = HALF4( normalTexel.xyz * 2.0h - 1.0h, normalTexel.a );
  332. vNormal.xyz = normalize( lerp( vNormal.xyz, vNormal2.xyz, blendfactor1 ) );
  333. }
  334. #endif
  335. }
  336. #else
  337. fBumpBlendFactor = lerp( fBumpBlendFactor, g_BumpBlendFactors.x, blendfactor1 );
  338. #endif // BUMPMAP2 == 1
  339. fBumpBlendFactor = lerp( fBumpBlendFactor, g_BumpBlendFactors.y, blendfactor2 );
  340. fBumpBlendFactor = lerp( fBumpBlendFactor, g_BumpBlendFactors.z, blendfactor3 );
  341. #if ( BUMPMAP == 2 ) // ssbump mode
  342. {
  343. vNormal.xyz = lerp( float3( 0, 0, 0 ), vNormal.xyz, fBumpBlendFactor );
  344. }
  345. #else
  346. {
  347. vNormal.xyz = normalize( lerp( float3( 0, 0, 1 ), vNormal.xyz, fBumpBlendFactor ) );
  348. }
  349. #endif
  350. }
  351. #if ( BUMPMAP2 == 0 )
  352. if ( bEnvmapMask )
  353. {
  354. specularFactor *= h3tex2D( EnvmapMaskSampler, envmapMaskTexCoord ).xyz;
  355. }
  356. #endif
  357. if ( bBaseAlphaEnvmapMask )
  358. {
  359. specularFactor *= 1.0h - baseColor.a; // Reversing alpha blows!
  360. }
  361. HALF4 albedo = HALF4( 1.0f, 1.0f, 1.0f, 1.0f );
  362. HALF alpha = 1.0h;
  363. albedo *= baseColor;
  364. if ( !bBaseAlphaEnvmapMask && !bSelfIllum )
  365. {
  366. alpha *= baseColor.a;
  367. }
  368. float detailBlendFactor = 0.0f;
  369. if ( bDetailTexture )
  370. {
  371. float detailBlendFactor = g_DetailBlendFactors.x;
  372. detailBlendFactor = lerp( detailBlendFactor, g_DetailBlendFactors.y, blendfactor1 );
  373. detailBlendFactor = lerp( detailBlendFactor, g_DetailBlendFactors.z, blendfactor2 );
  374. detailBlendFactor = lerp( detailBlendFactor, g_DetailBlendFactors.w, blendfactor3 );
  375. albedo = TextureCombine( albedo, detailColor, DETAIL_BLEND_MODE, detailBlendFactor );
  376. #if ( ( DETAIL_BLEND_MODE == TCOMBINE_MOD2X_SELECT_TWO_PATTERNS ) && !SELFILLUM )
  377. {
  378. // don't do this in the SELFILLUM case since we don't have enough instructions in ps20
  379. specularFactor *= 2.0h * lerp( detailColor.g, detailColor.b, baseColor.a );
  380. }
  381. #endif
  382. }
  383. // The vertex color contains the modulation color + vertex color combined
  384. #if ( SEAMLESS == 0 )
  385. albedo.rgb *= i.vertexColor.rgb;
  386. #endif
  387. alpha *= i.vertexColor.a;
  388. float flShadowScalar = 0.0;
  389. float flShadow = 1.0;
  390. // Save this off for single-pass flashlight, since we'll still need the SSBump vector, not a real normal
  391. HALF3 vSSBumpVector = vNormal.xyz;
  392. HALF3 diffuseLighting;
  393. if ( bBumpmap && bDiffuseBumpmap )
  394. {
  395. // ssbump
  396. #if ( BUMPMAP == 2 )
  397. #if ( DETAIL_BLEND_MODE == TCOMBINE_SSBUMP_BUMP )
  398. vNormal.xyz *= lerp( HALF3( 1, 1, 1 ), 2 * detailColor.xyz, alpha );
  399. vSSBumpVector = vNormal.xyz;
  400. alpha = 1;
  401. #endif
  402. diffuseLighting = vNormal.x * lightmapColor1.rgb +
  403. vNormal.y * lightmapColor2.rgb +
  404. vNormal.z * lightmapColor3.rgb;
  405. #if ( ( CSM_BLENDING == 1 ) && ( CASCADED_SHADOW_MAPPING ) && ( CASCADE_SIZE > 0 ) && !defined( SHADER_MODEL_PS_2_B ) )
  406. // currently not supporting CSM's with 4wayblend in ps2b/OSX since out of instructions/consts
  407. diffuseLighting = BlendBumpDiffuseLightmapWithCSM( diffuseLighting, lightmapColor1.a, lightmapColor2.a, lightmapColor3.a, vNormal.xyz, worldPos, flShadow, flShadowScalar );
  408. #endif
  409. // SSBump textures are created assuming the shader decodes lighting for each basis vector by taking dot( N, basis )*lightmap.
  410. // But the lightmaps are created assuming that the 3 coeffs sum to 1.0 and are more like barycentric coords than visibility
  411. // along the basis vector...so the lightmap math is really just a weighted average of the 3 directional light maps. So a flat
  412. // normal should have 3 weights each = 0.333. But since ssbump textures are created assuming the other math, a flat normal
  413. // converted into an ssbump texture generates 3 weights each = 0.578, so instead of all 3 weights summing to 1.0, they sum
  414. // to 1.733. To adjust for this, I'm scaling these coefficients by 1 / 1.733 = 0.578. NOTE: I'm not scaling vNormal directly
  415. // since it is used elsewhere for flashlight computations and shouldn't be scaled for that code.
  416. diffuseLighting *= 0.57735025882720947h;
  417. diffuseLighting *= (HALF3)g_TintValuesTimesLightmapScale.rgb;
  418. // now, calculate vNormal for reflection purposes. if vNormal isn't needed, hopefully
  419. // the compiler will eliminate these calculations
  420. vNormal.xyz = normalize( bumpBasis[0]*vNormal.x + bumpBasis[1]*vNormal.y + bumpBasis[2]*vNormal.z);
  421. #else
  422. HALF3 dp;
  423. dp.x = saturate( dot( vNormal.xyz, bumpBasis[0] ) );
  424. dp.y = saturate( dot( vNormal.xyz, bumpBasis[1] ) );
  425. dp.z = saturate( dot( vNormal.xyz, bumpBasis[2] ) );
  426. dp *= dp;
  427. #if ( DETAIL_BLEND_MODE == TCOMBINE_SSBUMP_BUMP )
  428. dp *= 2*detailColor.rgb;
  429. #endif
  430. diffuseLighting = dp.x * lightmapColor1.rgb +
  431. dp.y * lightmapColor2.rgb +
  432. dp.z * lightmapColor3.rgb;
  433. HALF sum = dot( dp, HALF3( 1.0f, 1.0f, 1.0f ) );
  434. #if ( ( CSM_BLENDING == 1 ) && ( CASCADED_SHADOW_MAPPING ) && ( CASCADE_SIZE > 0 ) && !defined( SHADER_MODEL_PS_2_B ) )
  435. // currently not supporting CSM's with 4wayblend in ps2b/OSX since out of instructions/consts
  436. diffuseLighting = BlendBumpDiffuseLightmapWithCSM( diffuseLighting.rgb, lightmapColor1.a, lightmapColor2.a, lightmapColor3.a, dp, worldPos, flShadow, flShadowScalar );
  437. #endif
  438. diffuseLighting *= (HALF3)g_TintValuesTimesLightmapScale.rgb / sum;
  439. #endif
  440. }
  441. else
  442. {
  443. diffuseLighting = lightmapColor1.rgb;
  444. #if ( ( CSM_BLENDING == 1 ) && ( CASCADED_SHADOW_MAPPING ) && ( CASCADE_SIZE > 0 ) && !defined( SHADER_MODEL_PS_2_B ) )
  445. // currently not supporting CSM's with 4wayblend in ps2b/OSX since out of instructions/consts
  446. diffuseLighting = BlendDiffuseLightmapWithCSM( diffuseLighting, lightmapColor1.a, worldPos, flShadow, flShadowScalar );
  447. #endif
  448. diffuseLighting.rgb *= (HALF3)g_TintValuesTimesLightmapScale.rgb;
  449. }
  450. #if ( ( CSM_BLENDING == 0 ) && ( CASCADED_SHADOW_MAPPING ) && ( CASCADE_SIZE > 0 ) && !defined( SHADER_MODEL_PS_2_B ) )
  451. {
  452. #if !defined( _X360 ) && !defined( _PS3 ) && !defined( SHADER_MODEL_PS_2_B )
  453. if ( g_bCSMEnabled )
  454. {
  455. #endif
  456. // Can't enable dynamic jumps around the Fetch4 shader, because it can't use tex2dlod()
  457. #if ( CSM_MODE != CSM_MODE_ATI_FETCH4 ) && !defined( SHADER_MODEL_PS_2_B )
  458. [branch]
  459. #endif
  460. if ( lightmapColor1.a > 0.0f )
  461. {
  462. float flSunPercent;
  463. if ( bBumpmap && bDiffuseBumpmap )
  464. {
  465. flSunPercent = lightmapColor1.a / ( Luminance( lightmapColor1.rgb + lightmapColor2.rgb + lightmapColor3.rgb ) * 0.3333 );
  466. }
  467. else
  468. {
  469. flSunPercent = lightmapColor1.a / Luminance( lightmapColor1.rgb );
  470. }
  471. flShadow = CSMComputeShadowing( worldPos );
  472. flShadowScalar = 1.0 - ( flSunPercent * ( 1.0 - flShadow ) );
  473. /* Debug - blink full shadows
  474. if ( step( frac( g_flTime * 0.5 ), 0.5 ) )
  475. {
  476. flShadowScalar = 1.0 - lightmapColor1.a;
  477. }
  478. //*/
  479. // Apply csm shadows
  480. diffuseLighting.rgb *= flShadowScalar;
  481. // Desaturate shadow color since we only have a grayscale dim factor
  482. diffuseLighting.rgb = lerp( diffuseLighting.bgr, diffuseLighting.rgb, flShadowScalar * 0.5 + 0.5 );
  483. // debug visualization
  484. // diffuseLighting.rgb = lerp( float3(1.0f-flShadowScalar,1.0f-flShadowScalar,1.0f-flShadowScalar), CSMVisualizeSplit( worldPos ), .3f );
  485. // return float4(diffuseLighting.rgb, 1.0f);
  486. }
  487. #if !defined( _X360 ) && !defined( _PS3 )
  488. }
  489. #endif
  490. }
  491. #endif
  492. HALF3 worldSpaceNormal = mul( vNormal.xyz, tangenttranspose );
  493. #if !defined( SHADER_MODEL_PS_2_0 ) && ( FLASHLIGHT == 0 )
  494. diffuseLighting += (HALF3)g_cAmbientColor;
  495. #endif
  496. HALF3 diffuseComponent = albedo.rgb * diffuseLighting;
  497. #if ( defined( _X360 ) || defined( _PS3 ) ) && FLASHLIGHT
  498. // ssbump doesn't pass a normal to the flashlight...it computes shadowing a different way
  499. #if ( BUMPMAP == 2 )
  500. bool bHasNormal = false;
  501. float3 worldPosToLightVector = g_FlashlightPos - worldPos;
  502. HALF3 tangentPosToLightVector;
  503. tangentPosToLightVector.x = dot( worldPosToLightVector, tangenttranspose[0] );
  504. tangentPosToLightVector.y = dot( worldPosToLightVector, tangenttranspose[1] );
  505. tangentPosToLightVector.z = dot( worldPosToLightVector, tangenttranspose[2] );
  506. tangentPosToLightVector = normalize( tangentPosToLightVector );
  507. HALF nDotL = saturate( vSSBumpVector.x*dot( tangentPosToLightVector, bumpBasis[0]) +
  508. vSSBumpVector.y*dot( tangentPosToLightVector, bumpBasis[1]) +
  509. vSSBumpVector.z*dot( tangentPosToLightVector, bumpBasis[2]) );
  510. #else
  511. bool bHasNormal = true;
  512. HALF nDotL = 1.0h;
  513. #endif
  514. bool bShadows = FLASHLIGHTSHADOWS ? true : false;
  515. HALF3 flashlightColor = DoFlashlight( g_FlashlightPos, worldPos, i.flashlightSpacePos,
  516. worldSpaceNormal, g_FlashlightAttenuationFactors.xyz,
  517. g_FlashlightAttenuationFactors.w, FlashlightSampler, ShadowDepthSampler,
  518. RandRotSampler, 0, bShadows, i.vProjPos.xy / i.vProjPos.w, false, g_ShadowTweaks, bHasNormal );
  519. diffuseComponent = albedo.xyz * ( diffuseLighting + ( flashlightColor * nDotL * (HALF3)g_TintValuesWithoutLightmapScale.rgb ) );
  520. #endif
  521. if ( bSelfIllum )
  522. {
  523. HALF3 selfIllumComponent = (HALF3)g_SelfIllumTint.xyz * albedo.xyz;
  524. diffuseComponent = lerp( diffuseComponent, selfIllumComponent, baseColor.a );
  525. }
  526. HALF3 specularLighting = HALF3( 0.0f, 0.0f, 0.0f );
  527. #if ( CUBEMAP )
  528. {
  529. float3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, worldVertToEyeVector );
  530. // Calc Fresnel factor
  531. HALF3 eyeVect = normalize(worldVertToEyeVector);
  532. HALF fresnel = 1.0h - dot( worldSpaceNormal, eyeVect );
  533. #if ( ENVMAPANISOTROPY ) // For anisotropic reflections on macroscopically rough sufaces like asphalt
  534. // Orthogonalize the view vector to the surface normal, and use it as the anisotropy direction
  535. reflectVect = normalize( reflectVect );
  536. float3 rvec = cross( -eyeVect.xyz, worldSpaceNormal.xyz );
  537. float3 tang = cross( rvec, worldSpaceNormal.xyz );
  538. rvec = cross( tang, reflectVect );
  539. float3 reflectVectAniso = normalize( cross( rvec, worldSpaceNormal.xyz ) );
  540. // Anisotropy amount is influenced by the view angle to the surface. The more oblique the angle the more anisotropic the surface appears.
  541. anisotropyFactor *= dot( reflectVectAniso, -eyeVect );
  542. anisotropyFactor *= anisotropyFactor;
  543. reflectVect = normalize( lerp( reflectVect, reflectVectAniso, anisotropyFactor ) );
  544. #endif
  545. fresnel = max( 0, fresnel ); // precision issues on RSX cause this value to occasionally go negative, which results in a NaN presumably because of the exp(log(n)) operation
  546. fresnel = pow( fresnel, 4.0h ); //changing this to 4th power to save 2 cycles - visually it's very similar
  547. fresnel = fresnel * (HALF)g_OneMinusFresnelReflection + (HALF)g_FresnelReflection;
  548. specularLighting = (HALF)ENV_MAP_SCALE * h3texCUBE( EnvmapSampler, reflectVect ).rgb;
  549. #if (CUBEMAP == 2) //cubemap darkened by lightmap mode
  550. float3 cubemapLight = saturate( ( diffuseLighting - g_fvDiffuseCubemapMin ) * g_fvDiffuseCubemapMax );
  551. specularLighting = lerp( specularLighting, specularLighting * cubemapLight, (HALF)g_DiffuseCubemapScale ); //reduce the cubemap contribution when the pixel is in shadow
  552. #endif
  553. specularLighting *= specularFactor;
  554. specularLighting *= (HALF3)g_EnvmapTint.rgb;
  555. HALF3 specularLightingSquared = specularLighting * specularLighting;
  556. specularLighting = lerp( specularLighting, specularLightingSquared, (HALF)g_EnvmapContrast );
  557. HALF3 greyScale = dot( specularLighting, HALF3( 0.299f, 0.587f, 0.114f ) );
  558. specularLighting = lerp( greyScale, specularLighting, (HALF)g_EnvmapSaturation );
  559. specularLighting *= fresnel;
  560. }
  561. #endif
  562. if ( bDetailTexture )
  563. {
  564. diffuseComponent = TextureCombinePostLighting( diffuseComponent, detailColor, DETAIL_BLEND_MODE, detailBlendFactor );
  565. }
  566. HALF3 result = diffuseComponent + specularLighting;
  567. #if ( LIGHTING_PREVIEW == 3 )
  568. {
  569. return float4( worldSpaceNormal, i.worldPos_projPosZ.w );
  570. }
  571. #endif
  572. #if ( LIGHTING_PREVIEW == 1 )
  573. {
  574. float dotprod = 0.2 + abs( dot( normalize(worldSpaceNormal), normalize(worldVertToEyeVector) ) );
  575. return FinalOutput( float4( dotprod * albedo.xyz, alpha ), 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE );
  576. }
  577. #endif
  578. #if ( LIGHTING_PREVIEW == 2 )
  579. {
  580. LPREVIEW_PS_OUT ret;
  581. ret.color = float4( albedo.xyz,alpha );
  582. ret.normal = float4( worldSpaceNormal, i.worldPos_projPosZ.w );
  583. ret.position = float4( worldPos, alpha );
  584. ret.flags = float4( 1, 1, 1, alpha );
  585. return FinalOutput( ret, 0, PIXEL_FOG_TYPE_NONE, TONEMAP_SCALE_NONE );
  586. }
  587. #endif
  588. #if ( LIGHTING_PREVIEW == 0 )
  589. {
  590. bool bWriteDepthToAlpha = false;
  591. // ps_2_b and beyond
  592. #if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0))
  593. bWriteDepthToAlpha = ( WRITE_DEPTH_TO_DESTALPHA != 0 ) && ( WRITEWATERFOGTODESTALPHA == 0 );
  594. #endif
  595. HALF flVertexFogFactor = 0.0h;
  596. #if !HARDWAREFOGBLEND && !DOPIXELFOG
  597. {
  598. #if ( SEAMLESS )
  599. {
  600. flVertexFogFactor = i.SeamlessTexCoord_fogFactorW.w;
  601. }
  602. #else
  603. {
  604. flVertexFogFactor = i.baseTexCoord_fogFactorZ.z;
  605. }
  606. #endif
  607. }
  608. #endif
  609. HALF fogFactor = CalcPixelFogFactorSupportsVertexFog( PIXELFOGTYPE, g_FogParams, g_EyePos.xyz, worldPos, i.worldPos_projPosZ.w, flVertexFogFactor );
  610. #if WRITEWATERFOGTODESTALPHA && (PIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT)
  611. alpha = fogFactor;
  612. #endif
  613. float4_color_return_type vOutput = FinalOutputHalf( HALF4( result.rgb, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, bWriteDepthToAlpha, i.worldPos_projPosZ.w );
  614. #if ( defined( _X360 ) )
  615. {
  616. vOutput.xyz += ScreenSpaceOrderedDither( i.vScreenPos );
  617. }
  618. #endif
  619. return vOutput;
  620. }
  621. #endif
  622. }