Team Fortress 2 Source Code as on 22/4/2020
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.

804 lines
26 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose: Common pixel shader code
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #ifndef COMMON_PS_FXC_H_
  9. #define COMMON_PS_FXC_H_
  10. #include "common_fxc.h"
  11. // Put global skip commands here. . make sure and check that the appropriate vars are defined
  12. // so these aren't used on the wrong shaders!
  13. // --------------------------------------------------------------------------------
  14. // HDR should never be enabled if we don't aren't running in float or integer HDR mode.
  15. // SKIP: defined $HDRTYPE && defined $HDRENABLED && !$HDRTYPE && $HDRENABLED
  16. // --------------------------------------------------------------------------------
  17. // We don't ever write water fog to dest alpha if we aren't doing water fog.
  18. // SKIP: defined $PIXELFOGTYPE && defined $WRITEWATERFOGTODESTALPHA && ( $PIXELFOGTYPE != 1 ) && $WRITEWATERFOGTODESTALPHA
  19. // --------------------------------------------------------------------------------
  20. // We don't need fog in the pixel shader if we aren't in float fog mode2
  21. // NOSKIP: defined $HDRTYPE && defined $HDRENABLED && defined $PIXELFOGTYPE && $HDRTYPE != HDR_TYPE_FLOAT && $FOGTYPE != 0
  22. // --------------------------------------------------------------------------------
  23. // We don't do HDR and LIGHTING_PREVIEW at the same time since it's running LDR in hammer.
  24. // SKIP: defined $LIGHTING_PREVIEW && defined $HDRTYPE && $LIGHTING_PREVIEW && $HDRTYPE != 0
  25. // --------------------------------------------------------------------------------
  26. // Ditch all fastpath attempts if we are doing LIGHTING_PREVIEW.
  27. // SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPTINT && $LIGHTING_PREVIEW && $FASTPATHENVMAPTINT
  28. // SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPCONTRAST && $LIGHTING_PREVIEW && $FASTPATHENVMAPCONTRAST
  29. // SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH
  30. // --------------------------------------------------------------------------------
  31. // Ditch flashlight depth when flashlight is disabled
  32. // SKIP: ($FLASHLIGHT || $FLASHLIGHTSHADOWS) && $LIGHTING_PREVIEW
  33. // --------------------------------------------------------------------------------
  34. // System defined pixel shader constants
  35. #if defined( _X360 )
  36. const bool g_bHighQualityShadows : register( b0 );
  37. #endif
  38. // NOTE: w == 1.0f / (Dest alpha compressed depth range).
  39. const float4 g_LinearFogColor : register( c29 );
  40. #define OO_DESTALPHA_DEPTH_RANGE (g_LinearFogColor.w)
  41. // Linear and gamma light scale values
  42. const float4 cLightScale : register( c30 );
  43. #define LINEAR_LIGHT_SCALE (cLightScale.x)
  44. #define LIGHT_MAP_SCALE (cLightScale.y)
  45. #define ENV_MAP_SCALE (cLightScale.z)
  46. #define GAMMA_LIGHT_SCALE (cLightScale.w)
  47. // Flashlight constants
  48. #if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)
  49. const float4 cFlashlightColor : register( c28 );
  50. const float4 cFlashlightScreenScale : register( c31 ); // .zw are currently unused
  51. #define flFlashlightNoLambertValue cFlashlightColor.w // This is either 0.0 or 2.0
  52. #endif
  53. #define HDR_INPUT_MAP_SCALE 16.0f
  54. #define TONEMAP_SCALE_NONE 0
  55. #define TONEMAP_SCALE_LINEAR 1
  56. #define TONEMAP_SCALE_GAMMA 2
  57. #define PIXEL_FOG_TYPE_NONE -1 //MATERIAL_FOG_NONE is handled by PIXEL_FOG_TYPE_RANGE, this is for explicitly disabling fog in the shader
  58. #define PIXEL_FOG_TYPE_RANGE 0 //range+none packed together in ps2b. Simply none in ps20 (instruction limits)
  59. #define PIXEL_FOG_TYPE_HEIGHT 1
  60. // If you change these, make the corresponding change in hardwareconfig.cpp
  61. #define NVIDIA_PCF_POISSON 0
  62. #define ATI_NOPCF 1
  63. #define ATI_NO_PCF_FETCH4 2
  64. struct LPREVIEW_PS_OUT
  65. {
  66. float4 color : COLOR0;
  67. float4 normal : COLOR1;
  68. float4 position : COLOR2;
  69. float4 flags : COLOR3;
  70. };
  71. /*
  72. // unused
  73. HALF Luminance( HALF3 color )
  74. {
  75. return dot( color, HALF3( HALF_CONSTANT(0.30f), HALF_CONSTANT(0.59f), HALF_CONSTANT(0.11f) ) );
  76. }
  77. */
  78. /*
  79. // unused
  80. HALF LuminanceScaled( HALF3 color )
  81. {
  82. return dot( color, HALF3( HALF_CONSTANT(0.30f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.59f) / MAX_HDR_OVERBRIGHT, HALF_CONSTANT(0.11f) / MAX_HDR_OVERBRIGHT ) );
  83. }
  84. */
  85. /*
  86. // unused
  87. HALF AvgColor( HALF3 color )
  88. {
  89. return dot( color, HALF3( HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f), HALF_CONSTANT(0.33333f) ) );
  90. }
  91. */
  92. /*
  93. // unused
  94. HALF4 DiffuseBump( sampler lightmapSampler,
  95. float2 lightmapTexCoord1,
  96. float2 lightmapTexCoord2,
  97. float2 lightmapTexCoord3,
  98. HALF3 normal )
  99. {
  100. HALF3 lightmapColor1 = tex2D( lightmapSampler, lightmapTexCoord1 );
  101. HALF3 lightmapColor2 = tex2D( lightmapSampler, lightmapTexCoord2 );
  102. HALF3 lightmapColor3 = tex2D( lightmapSampler, lightmapTexCoord3 );
  103. HALF3 diffuseLighting;
  104. diffuseLighting = saturate( dot( normal, bumpBasis[0] ) ) * lightmapColor1 +
  105. saturate( dot( normal, bumpBasis[1] ) ) * lightmapColor2 +
  106. saturate( dot( normal, bumpBasis[2] ) ) * lightmapColor3;
  107. return HALF4( diffuseLighting, LuminanceScaled( diffuseLighting ) );
  108. }
  109. */
  110. /*
  111. // unused
  112. HALF Fresnel( HALF3 normal,
  113. HALF3 eye,
  114. HALF2 scaleBias )
  115. {
  116. HALF fresnel = HALF_CONSTANT(1.0f) - dot( normal, eye );
  117. fresnel = pow( fresnel, HALF_CONSTANT(5.0f) );
  118. return fresnel * scaleBias.x + scaleBias.y;
  119. }
  120. */
  121. /*
  122. // unused
  123. HALF4 GetNormal( sampler normalSampler,
  124. float2 normalTexCoord )
  125. {
  126. HALF4 normal = tex2D( normalSampler, normalTexCoord );
  127. normal.rgb = HALF_CONSTANT(2.0f) * normal.rgb - HALF_CONSTANT(1.0f);
  128. return normal;
  129. }
  130. */
  131. // Needs to match NormalDecodeMode_t enum in imaterialsystem.h
  132. #define NORM_DECODE_NONE 0
  133. #define NORM_DECODE_ATI2N 1
  134. #define NORM_DECODE_ATI2N_ALPHA 2
  135. float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode, sampler AlphaSampler )
  136. {
  137. float4 normalTexel = tex2D( NormalSampler, tc );
  138. float4 result;
  139. if ( nDecompressionMode == NORM_DECODE_NONE )
  140. {
  141. result = float4(normalTexel.xyz * 2.0f - 1.0f, normalTexel.a );
  142. }
  143. else if ( nDecompressionMode == NORM_DECODE_ATI2N )
  144. {
  145. result.xy = normalTexel.xy * 2.0f - 1.0f;
  146. result.z = sqrt( 1.0f - dot(result.xy, result.xy) );
  147. result.a = 1.0f;
  148. }
  149. else // ATI2N plus ATI1N for alpha
  150. {
  151. result.xy = normalTexel.xy * 2.0f - 1.0f;
  152. result.z = sqrt( 1.0f - dot(result.xy, result.xy) );
  153. result.a = tex2D( AlphaSampler, tc ).x; // Note that this comes in on the X channel
  154. }
  155. return result;
  156. }
  157. float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode )
  158. {
  159. return DecompressNormal( NormalSampler, tc, nDecompressionMode, NormalSampler );
  160. }
  161. HALF3 NormalizeWithCubemap( sampler normalizeSampler, HALF3 input )
  162. {
  163. // return texCUBE( normalizeSampler, input ) * 2.0f - 1.0f;
  164. return texCUBE( normalizeSampler, input );
  165. }
  166. /*
  167. HALF4 EnvReflect( sampler envmapSampler,
  168. sampler normalizeSampler,
  169. HALF3 normal,
  170. float3 eye,
  171. HALF2 fresnelScaleBias )
  172. {
  173. HALF3 normEye = NormalizeWithCubemap( normalizeSampler, eye );
  174. HALF fresnel = Fresnel( normal, normEye, fresnelScaleBias );
  175. HALF3 reflect = CalcReflectionVectorUnnormalized( normal, eye );
  176. return texCUBE( envmapSampler, reflect );
  177. }
  178. */
  179. float CalcWaterFogAlpha( const float flWaterZ, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ, const float flFogOORange )
  180. {
  181. // float flDepthFromWater = flWaterZ - flWorldPosZ + 2.0f; // hackity hack . .this is for the DF_FUDGE_UP in view_scene.cpp
  182. float flDepthFromWater = flWaterZ - flWorldPosZ;
  183. // if flDepthFromWater < 0, then set it to 0
  184. // This is the equivalent of moving the vert to the water surface if it's above the water surface
  185. // We'll do this with the saturate at the end instead.
  186. // flDepthFromWater = max( 0.0f, flDepthFromWater );
  187. // Calculate the ratio of water fog to regular fog (ie. how much of the distance from the viewer
  188. // to the vert is actually underwater.
  189. float flDepthFromEye = flEyePosZ - flWorldPosZ;
  190. float f = saturate(flDepthFromWater * (1.0/flDepthFromEye));
  191. // $tmp.w is now the distance that we see through water.
  192. return saturate(f * flProjPosZ * flFogOORange);
  193. }
  194. float CalcRangeFog( const float flProjPosZ, const float flFogStartOverRange, const float flFogMaxDensity, const float flFogOORange )
  195. {
  196. #if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b
  197. return saturate( min( flFogMaxDensity, (flProjPosZ * flFogOORange) - flFogStartOverRange ) );
  198. #else
  199. return 0.0f; //ps20 shaders will never have range fog enabled because too many ran out of slots.
  200. #endif
  201. }
  202. float CalcPixelFogFactor( int iPIXELFOGTYPE, const float4 fogParams, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ )
  203. {
  204. float retVal;
  205. if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE )
  206. {
  207. retVal = 0.0f;
  208. }
  209. if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //range fog, or no fog depending on fog parameters
  210. {
  211. retVal = CalcRangeFog( flProjPosZ, fogParams.x, fogParams.z, fogParams.w );
  212. }
  213. else if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) //height fog
  214. {
  215. retVal = CalcWaterFogAlpha( fogParams.y, flEyePosZ, flWorldPosZ, flProjPosZ, fogParams.w );
  216. }
  217. return retVal;
  218. }
  219. //g_FogParams not defined by default, but this is the same layout for every shader that does define it
  220. #define g_FogEndOverRange g_FogParams.x
  221. #define g_WaterZ g_FogParams.y
  222. #define g_FogMaxDensity g_FogParams.z
  223. #define g_FogOORange g_FogParams.w
  224. float3 BlendPixelFog( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, const int iPIXELFOGTYPE )
  225. {
  226. if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //either range fog or no fog depending on fog parameters and whether this is ps20 or ps2b
  227. {
  228. # if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b
  229. pixelFogFactor = saturate( pixelFogFactor );
  230. return lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog
  231. # else
  232. return vShaderColor;
  233. # endif
  234. }
  235. else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT )
  236. {
  237. return lerp( vShaderColor.rgb, vFogColor.rgb, saturate( pixelFogFactor ) );
  238. }
  239. else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE )
  240. {
  241. return vShaderColor;
  242. }
  243. }
  244. #if ((defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)) && ( CONVERT_TO_SRGB != 0 ) )
  245. sampler1D GammaTableSampler : register( s15 );
  246. float3 SRGBOutput( const float3 vShaderColor )
  247. {
  248. //On ps2b capable hardware we always have the linear->gamma conversion table texture in sampler s15.
  249. float3 result;
  250. result.r = tex1D( GammaTableSampler, vShaderColor.r ).r;
  251. result.g = tex1D( GammaTableSampler, vShaderColor.g ).r;
  252. result.b = tex1D( GammaTableSampler, vShaderColor.b ).r;
  253. return result;
  254. }
  255. #else
  256. float3 SRGBOutput( const float3 vShaderColor )
  257. {
  258. return vShaderColor; //ps 1.1, 1.4, and 2.0 never do srgb conversion in the pixel shader
  259. }
  260. #endif
  261. float SoftParticleDepth( float flDepth )
  262. {
  263. return flDepth * OO_DESTALPHA_DEPTH_RANGE;
  264. }
  265. float DepthToDestAlpha( const float flProjZ )
  266. {
  267. #if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b
  268. return SoftParticleDepth( flProjZ );
  269. #else
  270. return 1.0f;
  271. #endif
  272. }
  273. float4 FinalOutput( const float4 vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE, const bool bWriteDepthToDestAlpha = false, const float flProjZ = 1.0f )
  274. {
  275. float4 result;
  276. if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR )
  277. {
  278. result.rgb = vShaderColor.rgb * LINEAR_LIGHT_SCALE;
  279. }
  280. else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA )
  281. {
  282. result.rgb = vShaderColor.rgb * GAMMA_LIGHT_SCALE;
  283. }
  284. else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_NONE )
  285. {
  286. result.rgb = vShaderColor.rgb;
  287. }
  288. if( bWriteDepthToDestAlpha )
  289. result.a = DepthToDestAlpha( flProjZ );
  290. else
  291. result.a = vShaderColor.a;
  292. result.rgb = BlendPixelFog( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, iPIXELFOGTYPE );
  293. #if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b
  294. result.rgb = SRGBOutput( result.rgb ); //SRGB in pixel shader conversion
  295. #endif
  296. return result;
  297. }
  298. LPREVIEW_PS_OUT FinalOutput( const LPREVIEW_PS_OUT vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE )
  299. {
  300. LPREVIEW_PS_OUT result;
  301. result.color = FinalOutput( vShaderColor.color, pixelFogFactor, iPIXELFOGTYPE, iTONEMAP_SCALE_TYPE );
  302. result.normal.rgb = SRGBOutput( vShaderColor.normal.rgb );
  303. result.normal.a = vShaderColor.normal.a;
  304. result.position.rgb = SRGBOutput( vShaderColor.position.rgb );
  305. result.position.a = vShaderColor.position.a;
  306. result.flags.rgb = SRGBOutput( vShaderColor.flags.rgb );
  307. result.flags.a = vShaderColor.flags.a;
  308. return result;
  309. }
  310. float RemapValClamped( float val, float A, float B, float C, float D)
  311. {
  312. float cVal = (val - A) / (B - A);
  313. cVal = saturate( cVal );
  314. return C + (D - C) * cVal;
  315. }
  316. //===================================================================================//
  317. // This is based on Natasha Tatarchuk's Parallax Occlusion Mapping (ATI)
  318. //===================================================================================//
  319. // INPUT:
  320. // inTexCoord:
  321. // the texcoord for the height/displacement map before parallaxing
  322. //
  323. // vParallax:
  324. // Compute initial parallax displacement direction:
  325. // float2 vParallaxDirection = normalize( vViewTS.xy );
  326. // float fLength = length( vViewTS );
  327. // float fParallaxLength = sqrt( fLength * fLength - vViewTS.z * vViewTS.z ) / vViewTS.z;
  328. // Out.vParallax = vParallaxDirection * fParallaxLength * fProjectedBumpHeight;
  329. //
  330. // vNormal:
  331. // tangent space normal
  332. //
  333. // vViewW:
  334. // float3 vViewW = /*normalize*/(mul( matViewInverse, float4( 0, 0, 0, 1)) - inPosition );
  335. //
  336. // OUTPUT:
  337. // the new texcoord after parallaxing
  338. float2 CalcParallaxedTexCoord( float2 inTexCoord, float2 vParallax, float3 vNormal,
  339. float3 vViewW, sampler HeightMapSampler )
  340. {
  341. const int nMinSamples = 8;
  342. const int nMaxSamples = 50;
  343. // Normalize the incoming view vector to avoid artifacts:
  344. // vView = normalize( vView );
  345. vViewW = normalize( vViewW );
  346. // vLight = normalize( vLight );
  347. // Change the number of samples per ray depending on the viewing angle
  348. // for the surface. Oblique angles require smaller step sizes to achieve
  349. // more accurate precision
  350. int nNumSteps = (int) lerp( nMaxSamples, nMinSamples, dot( vViewW, vNormal ) );
  351. float4 cResultColor = float4( 0, 0, 0, 1 );
  352. //===============================================//
  353. // Parallax occlusion mapping offset computation //
  354. //===============================================//
  355. float fCurrHeight = 0.0;
  356. float fStepSize = 1.0 / (float) nNumSteps;
  357. float fPrevHeight = 1.0;
  358. float fNextHeight = 0.0;
  359. int nStepIndex = 0;
  360. // bool bCondition = true;
  361. float2 dx = ddx( inTexCoord );
  362. float2 dy = ddy( inTexCoord );
  363. float2 vTexOffsetPerStep = fStepSize * vParallax;
  364. float2 vTexCurrentOffset = inTexCoord;
  365. float fCurrentBound = 1.0;
  366. float x = 0;
  367. float y = 0;
  368. float xh = 0;
  369. float yh = 0;
  370. float2 texOffset2 = 0;
  371. bool bCondition = true;
  372. while ( bCondition == true && nStepIndex < nNumSteps )
  373. {
  374. vTexCurrentOffset -= vTexOffsetPerStep;
  375. fCurrHeight = tex2Dgrad( HeightMapSampler, vTexCurrentOffset, dx, dy ).r;
  376. fCurrentBound -= fStepSize;
  377. if ( fCurrHeight > fCurrentBound )
  378. {
  379. x = fCurrentBound;
  380. y = fCurrentBound + fStepSize;
  381. xh = fCurrHeight;
  382. yh = fPrevHeight;
  383. texOffset2 = vTexCurrentOffset - vTexOffsetPerStep;
  384. bCondition = false;
  385. }
  386. else
  387. {
  388. nStepIndex++;
  389. fPrevHeight = fCurrHeight;
  390. }
  391. } // End of while ( bCondition == true && nStepIndex > -1 )#else
  392. fCurrentBound -= fStepSize;
  393. float fParallaxAmount;
  394. float numerator = (x * (y - yh) - y * (x - xh));
  395. float denomenator = ((y - yh) - (x - xh));
  396. // avoid NaN generation
  397. if( ( numerator == 0.0f ) && ( denomenator == 0.0f ) )
  398. {
  399. fParallaxAmount = 0.0f;
  400. }
  401. else
  402. {
  403. fParallaxAmount = numerator / denomenator;
  404. }
  405. float2 vParallaxOffset = vParallax * (1 - fParallaxAmount );
  406. // Sample the height at the next possible step:
  407. fNextHeight = tex2Dgrad( HeightMapSampler, texOffset2, dx, dy ).r;
  408. // Original offset:
  409. float2 texSampleBase = inTexCoord - vParallaxOffset;
  410. return texSampleBase;
  411. #if 0
  412. cResultColor.rgb = ComputeDiffuseColor( texSampleBase, vLight );
  413. float fBound = 1.0 - fStepSize * nStepIndex;
  414. if ( fNextHeight < fCurrentBound )
  415. // if( 0 )
  416. {
  417. //void DoIteration( in float2 vParallaxJittered, in float3 vLight, inout float4 cResultColor )
  418. //cResultColor.rgb = float3(1,0,0);
  419. DoIteration( vParallax + vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );
  420. DoIteration( vParallax - vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );
  421. DoIteration( vParallax + float2( -vPixelSize.x, vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );
  422. DoIteration( vParallax + float2( vPixelSize.x, -vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );
  423. cResultColor.rgb /= 5;
  424. // cResultColor.rgb = float3( 1.0f, 0.0f, 0.0f );
  425. } // End of if ( fNextHeight < fCurrentBound )
  426. #if DOSHADOWS
  427. {
  428. //============================================//
  429. // Soft shadow and self-occlusion computation //
  430. //============================================//
  431. // Compute the blurry shadows (note that this computation takes into
  432. // account self-occlusion for shadow computation):
  433. float sh0 = tex2D( sNormalMap, texSampleBase).w;
  434. float shA = (tex2D( sNormalMap, texSampleBase + inXY * 0.88 ).w - sh0 - 0.88 ) * 1 * fShadowSoftening;
  435. float sh9 = (tex2D( sNormalMap, texSampleBase + inXY * 0.77 ).w - sh0 - 0.77 ) * 2 * fShadowSoftening;
  436. float sh8 = (tex2D( sNormalMap, texSampleBase + inXY * 0.66 ).w - sh0 - 0.66 ) * 4 * fShadowSoftening;
  437. float sh7 = (tex2D( sNormalMap, texSampleBase + inXY * 0.55 ).w - sh0 - 0.55 ) * 6 * fShadowSoftening;
  438. float sh6 = (tex2D( sNormalMap, texSampleBase + inXY * 0.44 ).w - sh0 - 0.44 ) * 8 * fShadowSoftening;
  439. float sh5 = (tex2D( sNormalMap, texSampleBase + inXY * 0.33 ).w - sh0 - 0.33 ) * 10 * fShadowSoftening;
  440. float sh4 = (tex2D( sNormalMap, texSampleBase + inXY * 0.22 ).w - sh0 - 0.22 ) * 12 * fShadowSoftening;
  441. // Compute the actual shadow strength:
  442. float fShadow = 1 - max( max( max( max( max( max( shA, sh9 ), sh8 ), sh7 ), sh6 ), sh5 ), sh4 );
  443. cResultColor.rgb *= fShadow * 0.6 + 0.4;
  444. }
  445. #endif
  446. return cResultColor;
  447. #endif
  448. }
  449. //======================================//
  450. // HSL Color space conversion routines //
  451. //======================================//
  452. #define HUE 0
  453. #define SATURATION 1
  454. #define LIGHTNESS 2
  455. // Convert from RGB to HSL color space
  456. float4 RGBtoHSL( float4 inColor )
  457. {
  458. float h, s;
  459. float flMax = max( inColor.r, max( inColor.g, inColor.b ) );
  460. float flMin = min( inColor.r, min( inColor.g, inColor.b ) );
  461. float l = (flMax + flMin) / 2.0f;
  462. if (flMax == flMin) // achromatic case
  463. {
  464. s = h = 0;
  465. }
  466. else // chromatic case
  467. {
  468. // Next, calculate the hue
  469. float delta = flMax - flMin;
  470. // First, calculate the saturation
  471. if (l < 0.5f) // If we're in the lower hexcone
  472. {
  473. s = delta/(flMax + flMin);
  474. }
  475. else
  476. {
  477. s = delta/(2 - flMax - flMin);
  478. }
  479. if ( inColor.r == flMax )
  480. {
  481. h = (inColor.g - inColor.b)/delta; // color between yellow and magenta
  482. }
  483. else if ( inColor.g == flMax )
  484. {
  485. h = 2 + (inColor.b - inColor.r)/delta; // color between cyan and yellow
  486. }
  487. else // blue must be max
  488. {
  489. h = 4 + (inColor.r - inColor.g)/delta; // color between magenta and cyan
  490. }
  491. h *= 60.0f;
  492. if (h < 0.0f)
  493. {
  494. h += 360.0f;
  495. }
  496. h /= 360.0f;
  497. }
  498. return float4 (h, s, l, 1.0f);
  499. }
  500. float HueToRGB( float v1, float v2, float vH )
  501. {
  502. float fResult = v1;
  503. vH = fmod (vH + 1.0f, 1.0f);
  504. if ( ( 6.0f * vH ) < 1.0f )
  505. {
  506. fResult = ( v1 + ( v2 - v1 ) * 6.0f * vH );
  507. }
  508. else if ( ( 2.0f * vH ) < 1.0f )
  509. {
  510. fResult = ( v2 );
  511. }
  512. else if ( ( 3.0f * vH ) < 2.0f )
  513. {
  514. fResult = ( v1 + ( v2 - v1 ) * ( ( 2.0f / 3.0f ) - vH ) * 6.0f );
  515. }
  516. return fResult;
  517. }
  518. // Convert from HSL to RGB color space
  519. float4 HSLtoRGB( float4 hsl )
  520. {
  521. float r, g, b;
  522. float h = hsl[HUE];
  523. float s = hsl[SATURATION];
  524. float l = hsl[LIGHTNESS];
  525. if ( s == 0 )
  526. {
  527. r = g = b = l;
  528. }
  529. else
  530. {
  531. float v1, v2;
  532. if ( l < 0.5f )
  533. v2 = l * ( 1.0f + s );
  534. else
  535. v2 = ( l + s ) - ( s * l );
  536. v1 = 2 * l - v2;
  537. r = HueToRGB( v1, v2, h + ( 1.0f / 3.0f ) );
  538. g = HueToRGB( v1, v2, h );
  539. b = HueToRGB( v1, v2, h - ( 1.0f / 3.0f ) );
  540. }
  541. return float4( r, g, b, 1.0f );
  542. }
  543. // texture combining modes for combining base and detail/basetexture2
  544. #define TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2 0 // original mode
  545. #define TCOMBINE_RGB_ADDITIVE 1 // base.rgb+detail.rgb*fblend
  546. #define TCOMBINE_DETAIL_OVER_BASE 2
  547. #define TCOMBINE_FADE 3 // straight fade between base and detail.
  548. #define TCOMBINE_BASE_OVER_DETAIL 4 // use base alpha for blend over detail
  549. #define TCOMBINE_RGB_ADDITIVE_SELFILLUM 5 // add detail color post lighting
  550. #define TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE 6
  551. #define TCOMBINE_MOD2X_SELECT_TWO_PATTERNS 7 // use alpha channel of base to select between mod2x channels in r+a of detail
  552. #define TCOMBINE_MULTIPLY 8
  553. #define TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA 9 // use alpha channel of detail to mask base
  554. #define TCOMBINE_SSBUMP_BUMP 10 // use detail to modulate lighting as an ssbump
  555. #define TCOMBINE_SSBUMP_NOBUMP 11 // detail is an ssbump but use it as an albedo. shader does the magic here - no user needs to specify mode 11
  556. float4 TextureCombine( float4 baseColor, float4 detailColor, int combine_mode,
  557. float fBlendFactor )
  558. {
  559. if ( combine_mode == TCOMBINE_MOD2X_SELECT_TWO_PATTERNS)
  560. {
  561. float3 dc=lerp(detailColor.r,detailColor.a, baseColor.a);
  562. baseColor.rgb*=lerp(float3(1,1,1),2.0*dc,fBlendFactor);
  563. }
  564. if ( combine_mode == TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2)
  565. baseColor.rgb*=lerp(float3(1,1,1),2.0*detailColor.rgb,fBlendFactor);
  566. if ( combine_mode == TCOMBINE_RGB_ADDITIVE )
  567. baseColor.rgb += fBlendFactor * detailColor.rgb;
  568. if ( combine_mode == TCOMBINE_DETAIL_OVER_BASE )
  569. {
  570. float fblend=fBlendFactor * detailColor.a;
  571. baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend);
  572. }
  573. if ( combine_mode == TCOMBINE_FADE )
  574. {
  575. baseColor = lerp( baseColor, detailColor, fBlendFactor);
  576. }
  577. if ( combine_mode == TCOMBINE_BASE_OVER_DETAIL )
  578. {
  579. float fblend=fBlendFactor * (1-baseColor.a);
  580. baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend );
  581. baseColor.a = detailColor.a;
  582. }
  583. if ( combine_mode == TCOMBINE_MULTIPLY )
  584. {
  585. baseColor = lerp( baseColor, baseColor*detailColor, fBlendFactor);
  586. }
  587. if (combine_mode == TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA )
  588. {
  589. baseColor.a = lerp( baseColor.a, baseColor.a*detailColor.a, fBlendFactor );
  590. }
  591. if ( combine_mode == TCOMBINE_SSBUMP_NOBUMP )
  592. {
  593. baseColor.rgb = baseColor.rgb * dot( detailColor.rgb, 2.0/3.0 );
  594. }
  595. return baseColor;
  596. }
  597. float3 lerp5(float3 f1, float3 f2, float i1, float i2, float x)
  598. {
  599. return f1+(f2-f1)*(x-i1)/(i2-i1);
  600. }
  601. float3 TextureCombinePostLighting( float3 lit_baseColor, float4 detailColor, int combine_mode,
  602. float fBlendFactor )
  603. {
  604. if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM )
  605. lit_baseColor += fBlendFactor * detailColor.rgb;
  606. if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE )
  607. {
  608. // fade in an unusual way - instead of fading out color, remap an increasing band of it from
  609. // 0..1
  610. //if (fBlendFactor > 0.5)
  611. // lit_baseColor += min(1, (1.0/fBlendFactor)*max(0, detailColor.rgb-(1-fBlendFactor) ) );
  612. //else
  613. // lit_baseColor += 2*fBlendFactor*2*max(0, detailColor.rgb-.5);
  614. float f = fBlendFactor - 0.5;
  615. float fMult = (f >= 0) ? 1.0/fBlendFactor : 4*fBlendFactor;
  616. float fAdd = (f >= 0) ? 1.0-fMult : -0.5*fMult;
  617. lit_baseColor += saturate(fMult * detailColor.rgb + fAdd);
  618. }
  619. return lit_baseColor;
  620. }
  621. //NOTE: On X360. fProjZ is expected to be pre-reversed for cheaper math here in the pixel shader
  622. float DepthFeathering( sampler DepthSampler, const float2 vScreenPos, float fProjZ, float fProjW, float4 vDepthBlendConstants )
  623. {
  624. # if ( !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) ) //minimum requirement of ps2b
  625. {
  626. float flFeatheredAlpha;
  627. float2 flDepths;
  628. #define flSceneDepth flDepths.x
  629. #define flSpriteDepth flDepths.y
  630. # if ( defined( _X360 ) )
  631. {
  632. //Get depth from the depth texture. Need to sample with the offset of (0.5, 0.5) to fix rounding errors
  633. asm {
  634. tfetch2D flDepths.x___, vScreenPos, DepthSampler, OffsetX=0.5, OffsetY=0.5, MinFilter=point, MagFilter=point, MipFilter=point
  635. };
  636. # if( !defined( REVERSE_DEPTH_ON_X360 ) )
  637. flSceneDepth = 1.0f - flSceneDepth;
  638. # endif
  639. //get the sprite depth into the same range as the texture depth
  640. flSpriteDepth = fProjZ / fProjW;
  641. //unproject to get at the pre-projection z. This value is much more linear than depth
  642. flDepths = vDepthBlendConstants.z / flDepths;
  643. flDepths = vDepthBlendConstants.y - flDepths;
  644. flFeatheredAlpha = flSceneDepth - flSpriteDepth;
  645. flFeatheredAlpha *= vDepthBlendConstants.x;
  646. flFeatheredAlpha = saturate( flFeatheredAlpha );
  647. }
  648. # else
  649. {
  650. flSceneDepth = tex2D( DepthSampler, vScreenPos ).a; // PC uses dest alpha of the frame buffer
  651. flSpriteDepth = SoftParticleDepth( fProjZ );
  652. flFeatheredAlpha = abs(flSceneDepth - flSpriteDepth) * vDepthBlendConstants.x;
  653. flFeatheredAlpha = max( smoothstep( 0.75f, 1.0f, flSceneDepth ), flFeatheredAlpha ); //as the sprite approaches the edge of our compressed depth space, the math stops working. So as the sprite approaches the far depth, smoothly remove feathering.
  654. flFeatheredAlpha = saturate( flFeatheredAlpha );
  655. }
  656. # endif
  657. #undef flSceneDepth
  658. #undef flSpriteDepth
  659. return flFeatheredAlpha;
  660. }
  661. # else
  662. {
  663. return 1.0f;
  664. }
  665. # endif
  666. }
  667. #endif //#ifndef COMMON_PS_FXC_H_