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.

1000 lines
32 KiB

  1. //========== Copyright (c) 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. // We don't ever write water fog to dest alpha if we aren't doing water fog.
  15. // SKIP: defined $PIXELFOGTYPE && defined $WRITEWATERFOGTODESTALPHA && ( $PIXELFOGTYPE != 1 ) && $WRITEWATERFOGTODESTALPHA
  16. // --------------------------------------------------------------------------------
  17. // Ditch all fastpath attempts if we are doing LIGHTING_PREVIEW.
  18. // SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPTINT && $LIGHTING_PREVIEW && $FASTPATHENVMAPTINT
  19. // SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATHENVMAPCONTRAST && $LIGHTING_PREVIEW && $FASTPATHENVMAPCONTRAST
  20. // SKIP: defined $LIGHTING_PREVIEW && defined $FASTPATH && $LIGHTING_PREVIEW && $FASTPATH
  21. // --------------------------------------------------------------------------------
  22. // Ditch flashlight depth when flashlight is disabled
  23. // SKIP: ($FLASHLIGHT || $FLASHLIGHTSHADOWS) && $LIGHTING_PREVIEW
  24. // --------------------------------------------------------------------------------
  25. // PS3 sRGB writes require a half4 return value
  26. #if defined( _PS3 )
  27. #define float4_color_return_type half4
  28. #else // _PS3
  29. #define float4_color_return_type float4
  30. #endif // !_PS3
  31. // System defined pixel shader constants
  32. #if defined( _X360 )
  33. const bool g_bHighQualityShadows : register( b0 );
  34. #endif
  35. // NOTE: w == 1.0f / (Dest alpha compressed depth range).
  36. const float4 g_LinearFogColor : register( c29 );
  37. #define OO_DESTALPHA_DEPTH_RANGE (g_LinearFogColor.w)
  38. // Linear and gamma light scale values
  39. const float4 cLightScale : register( c30 );
  40. #define LINEAR_LIGHT_SCALE (cLightScale.x)
  41. #define LIGHT_MAP_SCALE (cLightScale.y)
  42. #define ENV_MAP_SCALE (cLightScale.z)
  43. #define GAMMA_LIGHT_SCALE (cLightScale.w)
  44. // Flashlight constants
  45. #if defined(SHADER_MODEL_PS_2_0) || defined(SHADER_MODEL_PS_2_B) || defined(SHADER_MODEL_PS_3_0)
  46. const float4 cFlashlightColor : register( c28 );
  47. #define flFlashlightNoLambertValue cFlashlightColor.w // This is either 0.0 or 2.0
  48. const float4 cFlashlightScreenScale : register( c31 );
  49. #define flFlashlightShadowBufferOneOverWidth cFlashlightScreenScale.z // 1.0f / ShadowBufferWidth
  50. #define flFlashlightShadowBufferTwoOverWidth cFlashlightScreenScale.w // 2.0f / ShadowBufferWidth
  51. #endif
  52. // 3.0 standard constants
  53. #if defined( SHADER_MODEL_PS_3_0 )
  54. const float4 cScreenSize : register( c32 ); // Used for converting VPOS to useful 2D coordinates
  55. #endif
  56. const float4 g_vDepthFeatherProjToViewZW[2] : register( c13 );
  57. const float4 g_vDepthFeatherViewportMad : register( c15 );
  58. #define HDR_INPUT_MAP_SCALE 16.0f
  59. #define TONEMAP_SCALE_NONE 0
  60. #define TONEMAP_SCALE_LINEAR 1
  61. #define TONEMAP_SCALE_GAMMA 2
  62. #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
  63. #define PIXEL_FOG_TYPE_RANGE 0 //range+none packed together in ps2b. Simply none in ps20 (instruction limits)
  64. #define PIXEL_FOG_TYPE_HEIGHT 1
  65. // If you change these, make the corresponding change in hardwareconfig.cpp
  66. #define NVIDIA_PCF 0
  67. #define ATI_NO_PCF_FETCH4 1
  68. #define NVIDIA_PCF_CHEAP 2
  69. #define ATI_NOPCF 3
  70. #define GAMECONSOLE_NINE_TAP_PCF 0
  71. #define GAMECONSOLE_SINGLE_TAP_PCF 1
  72. struct LPREVIEW_PS_OUT
  73. {
  74. float4 color : COLOR0;
  75. float4 normal : COLOR1;
  76. float4 position : COLOR2;
  77. float4 flags : COLOR3;
  78. };
  79. /*
  80. // unused
  81. float Luminance( float3 color )
  82. {
  83. return dot( color, float3( 0.30f, 0.59f, 0.11f ) );
  84. }
  85. */
  86. /*
  87. // unused
  88. float LuminanceScaled( float3 color )
  89. {
  90. return dot( color, float3( 0.30f / MAX_HDR_OVERBRIGHT, 0.59f / MAX_HDR_OVERBRIGHT, 0.11f / MAX_HDR_OVERBRIGHT ) );
  91. }
  92. */
  93. /*
  94. // unused
  95. float AvgColor( float3 color )
  96. {
  97. return dot( color, float3( 0.33333f, 0.33333f, 0.33333f ) );
  98. }
  99. */
  100. /*
  101. // unused
  102. half4 DiffuseBump( sampler lightmapSampler,
  103. float2 lightmapTexCoord1,
  104. float2 lightmapTexCoord2,
  105. float2 lightmapTexCoord3,
  106. float3 normal )
  107. {
  108. float3 lightmapColor1 = tex2D( lightmapSampler, lightmapTexCoord1 );
  109. float3 lightmapColor2 = tex2D( lightmapSampler, lightmapTexCoord2 );
  110. float3 lightmapColor3 = tex2D( lightmapSampler, lightmapTexCoord3 );
  111. float3 diffuseLighting;
  112. diffuseLighting = saturate( dot( normal, bumpBasis[0] ) ) * lightmapColor1 +
  113. saturate( dot( normal, bumpBasis[1] ) ) * lightmapColor2 +
  114. saturate( dot( normal, bumpBasis[2] ) ) * lightmapColor3;
  115. return float4( diffuseLighting, LuminanceScaled( diffuseLighting ) );
  116. }
  117. */
  118. /*
  119. // unused
  120. float Fresnel( float3 normal,
  121. float3 eye,
  122. float2 scaleBias )
  123. {
  124. float fresnel = 1.0f - dot( normal, eye );
  125. fresnel = pow( fresnel, 5.0f );
  126. return fresnel * scaleBias.x + scaleBias.y;
  127. }
  128. */
  129. /*
  130. // unused
  131. half4 GetNormal( sampler normalSampler,
  132. float2 normalTexCoord )
  133. {
  134. float4 normal = tex2D( normalSampler, normalTexCoord );
  135. normal.rgb = 2.0f * normal.rgb - 1.0f;
  136. return normal;
  137. }
  138. */
  139. // Needs to match NormalDecodeMode_t enum in imaterialsystem.h
  140. #define NORM_DECODE_NONE 0
  141. #define NORM_DECODE_ATI2N 1
  142. #define NORM_DECODE_ATI2N_ALPHA 2
  143. float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode, sampler AlphaSampler )
  144. {
  145. float4 normalTexel = tex2D( NormalSampler, tc );
  146. float4 result;
  147. if ( nDecompressionMode == NORM_DECODE_NONE )
  148. {
  149. result = float4(normalTexel.xyz * 2.0f - 1.0f, normalTexel.a );
  150. }
  151. else if ( nDecompressionMode == NORM_DECODE_ATI2N )
  152. {
  153. result.xy = normalTexel.xy * 2.0f - 1.0f;
  154. result.z = sqrt( 1.0f - dot(result.xy, result.xy) );
  155. result.a = 1.0f;
  156. }
  157. else // ATI2N plus ATI1N for alpha
  158. {
  159. result.xy = normalTexel.xy * 2.0f - 1.0f;
  160. result.z = sqrt( 1.0f - dot(result.xy, result.xy) );
  161. result.a = tex2D( AlphaSampler, tc ).x; // Note that this comes in on the X channel
  162. }
  163. return result;
  164. }
  165. float4 DecompressNormal( sampler NormalSampler, float2 tc, int nDecompressionMode )
  166. {
  167. return DecompressNormal( NormalSampler, tc, nDecompressionMode, NormalSampler );
  168. }
  169. float3 NormalizeWithCubemap( samplerCUBE normalizeSampler, float3 input )
  170. {
  171. // return texCUBE( normalizeSampler, input ) * 2.0f - 1.0f;
  172. return texCUBE( normalizeSampler, input ).xyz ;
  173. }
  174. /*
  175. half4 EnvReflect( sampler envmapSampler,
  176. sampler normalizeSampler,
  177. float3 normal,
  178. float3 eye,
  179. float2 fresnelScaleBias )
  180. {
  181. float3 normEye = NormalizeWithCubemap( normalizeSampler, eye );
  182. float fresnel = Fresnel( normal, normEye, fresnelScaleBias );
  183. float3 reflect = CalcReflectionVectorUnnormalized( normal, eye );
  184. return texCUBE( envmapSampler, reflect );
  185. }
  186. */
  187. #if defined( SHADER_MODEL_PS_3_0 )
  188. // cScreenSize.xy contains { 1.0/w, 1.0/h }
  189. // cScreenSize.zw contains { 0.5/w, 0.5/h }
  190. float2 ComputeScreenPos( float2 vPos )
  191. {
  192. return vPos * cScreenSize.xy + cScreenSize.zw;
  193. }
  194. #endif
  195. // Vectorized smoothstep for doing three smoothsteps at once. Used by uberlight
  196. float3 smoothstep3( float3 edge0, float3 edge1, float3 OneOverWidth, float3 x )
  197. {
  198. x = saturate((x - edge0) * OneOverWidth); // Scale, bias and saturate x to the range of zero to one
  199. return x*x*(3-2*x); // Evaluate polynomial
  200. }
  201. float CalcWaterFogAlpha( const float flWaterZ, const float flEyePosZ, const float flWorldPosZ, const float flProjPosZ, const float flFogOORange )
  202. {
  203. #if 0
  204. // This version is what you use if you want a line-integral throught he water for water fog.
  205. // float flDepthFromWater = flWaterZ - flWorldPosZ + 2.0f; // hackity hack . .this is for the DF_FUDGE_UP in view_scene.cpp
  206. float flDepthFromWater = flWaterZ - flWorldPosZ;
  207. // if flDepthFromWater < 0, then set it to 0
  208. // This is the equivalent of moving the vert to the water surface if it's above the water surface
  209. // We'll do this with the saturate at the end instead.
  210. // flDepthFromWater = max( 0.0f, flDepthFromWater );
  211. // Calculate the ratio of water fog to regular fog (ie. how much of the distance from the viewer
  212. // to the vert is actually underwater.
  213. float flDepthFromEye = flEyePosZ - flWorldPosZ;
  214. float f = (flDepthFromWater / flDepthFromEye) * flProjPosZ;
  215. // $tmp.w is now the distance that we see through water.
  216. return saturate( f * flFogOORange );
  217. #else
  218. // This version is simply using the depth of the water to determine fog factor,
  219. // which is cheaper than doing the line integral and also fixes some problems with having
  220. // a hard line on the shore when the water surface is viewed tangentially.
  221. // hackity hack . .the 2.0 is for the DF_FUDGE_UP in view_scene.cpp
  222. return saturate( ( flWaterZ - flWorldPosZ - 2.0f ) * flFogOORange );
  223. #endif
  224. }
  225. HALF CalcPixelFogFactor( int iPIXELFOGTYPE, const float4 fogParams, const float3 vEyePos, const float3 vWorldPos, const float flProjPosZ )
  226. {
  227. float retVal;
  228. if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE )
  229. {
  230. retVal = 0.0f;
  231. }
  232. if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //range fog, or no fog depending on fog parameters
  233. {
  234. // This is one only path that we go down for L4D.
  235. float flFogMaxDensity = fogParams.z;
  236. float flFogEndOverRange = fogParams.x;
  237. float flFogOORange = fogParams.w;
  238. retVal = CalcRangeFogFactorNonFixedFunction( vWorldPos, vEyePos, flFogMaxDensity, flFogEndOverRange, flFogOORange );
  239. }
  240. else if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT ) //height fog
  241. {
  242. retVal = CalcWaterFogAlpha( fogParams.y, vEyePos.z, vWorldPos.z, flProjPosZ, fogParams.w );
  243. }
  244. return retVal;
  245. }
  246. HALF CalcPixelFogFactorSupportsVertexFog( int iPIXELFOGTYPE, const float4 fogParams, const float3 vEyePos, const float3 vWorldPos, const float flProjPosZ, const HALF flVertexFogFactor )
  247. {
  248. #if ( DOPIXELFOG )
  249. {
  250. return CalcPixelFogFactor( iPIXELFOGTYPE, fogParams, vEyePos, vWorldPos, flProjPosZ );
  251. }
  252. #else
  253. {
  254. return flVertexFogFactor;
  255. }
  256. #endif
  257. }
  258. //g_FogParams not defined by default, but this is the same layout for every shader that does define it
  259. #define g_FogEndOverRange g_FogParams.x
  260. #define g_WaterZ g_FogParams.y
  261. #define g_FogMaxDensity g_FogParams.z
  262. #define g_FogOORange g_FogParams.w
  263. float3 BlendPixelFog( const float3 vShaderColor, float pixelFogFactor, const float3 vFogColor, const int iPIXELFOGTYPE )
  264. {
  265. if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //either range fog or no fog depending on fog parameters and whether this is ps20 or ps2b
  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 lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog
  269. #else
  270. return vShaderColor;
  271. #endif
  272. }
  273. else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT )
  274. {
  275. return lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor );
  276. }
  277. else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE )
  278. {
  279. return vShaderColor;
  280. }
  281. }
  282. HALF3 BlendPixelFogHalf( const HALF3 vShaderColor, HALF pixelFogFactor, const HALF3 vFogColor, const int iPIXELFOGTYPE )
  283. {
  284. if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE ) //either range fog or no fog depending on fog parameters and whether this is ps20 or ps2b
  285. {
  286. #if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b
  287. return lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor * pixelFogFactor ); //squaring the factor will get the middle range mixing closer to hardware fog
  288. #else
  289. return vShaderColor;
  290. #endif
  291. }
  292. else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_HEIGHT )
  293. {
  294. return lerp( vShaderColor.rgb, vFogColor.rgb, pixelFogFactor );
  295. }
  296. else if( iPIXELFOGTYPE == PIXEL_FOG_TYPE_NONE )
  297. {
  298. return vShaderColor;
  299. }
  300. }
  301. float SoftParticleDepth( float flDepth )
  302. {
  303. return flDepth * OO_DESTALPHA_DEPTH_RANGE;
  304. }
  305. float DepthToDestAlpha( const float flProjZ )
  306. {
  307. #if !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) //Minimum requirement of ps2b
  308. return SoftParticleDepth( flProjZ );
  309. #else
  310. return 1.0f;
  311. #endif
  312. }
  313. float4_color_return_type FinalOutput( const float4 vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE, const bool bWriteDepthToDestAlpha = false, const float flProjZ = 1.0f )
  314. {
  315. float4 result;
  316. if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR )
  317. {
  318. result.rgb = vShaderColor.rgb * LINEAR_LIGHT_SCALE;
  319. }
  320. else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA )
  321. {
  322. result.rgb = vShaderColor.rgb * GAMMA_LIGHT_SCALE;
  323. }
  324. else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_NONE )
  325. {
  326. result.rgb = vShaderColor.rgb;
  327. }
  328. if( bWriteDepthToDestAlpha )
  329. result.a = DepthToDestAlpha( flProjZ );
  330. else
  331. result.a = vShaderColor.a;
  332. if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE )
  333. {
  334. result.rgb = BlendPixelFog( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, iPIXELFOGTYPE );
  335. }
  336. #if defined(_X360) && defined( CSTRIKE15 )
  337. // [mariod] - is this the only path? (defintely not TONEMAP_SCALE_GAMMA)...ensure aligned with what the shaders are doing, add combo (mimic srgb write render state) if necessary and mem exists...
  338. if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR )
  339. {
  340. result.rgb = LinearToGamma( result.rgb );
  341. //result.rgb = SrgbLinearToGamma( result.rgb );
  342. }
  343. #endif
  344. return ( float4_color_return_type )result;
  345. }
  346. float4_color_return_type FinalOutputHalf( const HALF4 vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE, const bool bWriteDepthToDestAlpha = false, const float flProjZ = 1.0f )
  347. {
  348. HALF4 result;
  349. if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR )
  350. {
  351. result.rgb = vShaderColor.rgb * (HALF)LINEAR_LIGHT_SCALE;
  352. }
  353. else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_GAMMA )
  354. {
  355. result.rgb = vShaderColor.rgb * (HALF)GAMMA_LIGHT_SCALE;
  356. }
  357. else if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_NONE )
  358. {
  359. result.rgb = vShaderColor.rgb;
  360. }
  361. if( bWriteDepthToDestAlpha )
  362. result.a = DepthToDestAlpha( flProjZ );
  363. else
  364. result.a = vShaderColor.a;
  365. if ( iPIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE )
  366. {
  367. result.rgb = BlendPixelFogHalf( result.rgb, pixelFogFactor, g_LinearFogColor.rgb, iPIXELFOGTYPE );
  368. }
  369. #if defined(_X360) && defined( CSTRIKE15 )
  370. // [mariod] - should we send TONEMAP_SCALE_NONE down this path too?
  371. if( iTONEMAP_SCALE_TYPE == TONEMAP_SCALE_LINEAR )
  372. {
  373. result.rgb = LinearToGamma( result.rgb );
  374. //result.rgb = SrgbLinearToGamma( result.rgb );
  375. }
  376. #endif
  377. return ( float4_color_return_type )result;
  378. }
  379. LPREVIEW_PS_OUT FinalOutput( const LPREVIEW_PS_OUT vShaderColor, float pixelFogFactor, const int iPIXELFOGTYPE, const int iTONEMAP_SCALE_TYPE )
  380. {
  381. LPREVIEW_PS_OUT result;
  382. result.color = FinalOutput( vShaderColor.color, pixelFogFactor, iPIXELFOGTYPE, iTONEMAP_SCALE_TYPE );
  383. result.normal.rgb = vShaderColor.normal.rgb;
  384. result.normal.a = vShaderColor.normal.a;
  385. result.position.rgb = vShaderColor.position.rgb;
  386. result.position.a = vShaderColor.position.a;
  387. result.flags.rgb = vShaderColor.flags.rgb;
  388. result.flags.a = vShaderColor.flags.a;
  389. return result;
  390. }
  391. float RemapValClamped( float val, float A, float B, float C, float D)
  392. {
  393. float cVal = (val - A) / (B - A);
  394. cVal = saturate( cVal );
  395. return C + (D - C) * cVal;
  396. }
  397. //===================================================================================//
  398. // This is based on Natasha Tatarchuk's Parallax Occlusion Mapping (ATI)
  399. //===================================================================================//
  400. // INPUT:
  401. // inTexCoord:
  402. // the texcoord for the height/displacement map before parallaxing
  403. //
  404. // vParallax:
  405. // Compute initial parallax displacement direction:
  406. // float2 vParallaxDirection = normalize( vViewTS.xy );
  407. // float fLength = length( vViewTS );
  408. // float fParallaxLength = sqrt( fLength * fLength - vViewTS.z * vViewTS.z ) / vViewTS.z;
  409. // Out.vParallax = vParallaxDirection * fParallaxLength * fProjectedBumpHeight;
  410. //
  411. // vNormal:
  412. // tangent space normal
  413. //
  414. // vViewW:
  415. // float3 vViewW = /*normalize*/(mul( matViewInverse, float4( 0, 0, 0, 1)) - inPosition );
  416. //
  417. // OUTPUT:
  418. // the new texcoord after parallaxing
  419. float2 CalcParallaxedTexCoord( float2 inTexCoord, float2 vParallax, float3 vNormal,
  420. float3 vViewW, sampler HeightMapSampler )
  421. {
  422. const int nMinSamples = 8;
  423. const int nMaxSamples = 50;
  424. // Normalize the incoming view vector to avoid artifacts:
  425. // vView = normalize( vView );
  426. vViewW = normalize( vViewW );
  427. // vLight = normalize( vLight );
  428. // Change the number of samples per ray depending on the viewing angle
  429. // for the surface. Oblique angles require smaller step sizes to achieve
  430. // more accurate precision
  431. int nNumSteps = (int) lerp( nMaxSamples, nMinSamples, dot( vViewW, vNormal ) );
  432. float4 cResultColor = float4( 0, 0, 0, 1 );
  433. //===============================================//
  434. // Parallax occlusion mapping offset computation //
  435. //===============================================//
  436. float fCurrHeight = 0.0;
  437. float fStepSize = 1.0 / (float) nNumSteps;
  438. float fPrevHeight = 1.0;
  439. float fNextHeight = 0.0;
  440. int nStepIndex = 0;
  441. // bool bCondition = true;
  442. float2 dx = ddx( inTexCoord );
  443. float2 dy = ddy( inTexCoord );
  444. float2 vTexOffsetPerStep = fStepSize * vParallax;
  445. float2 vTexCurrentOffset = inTexCoord;
  446. float fCurrentBound = 1.0;
  447. float x = 0;
  448. float y = 0;
  449. float xh = 0;
  450. float yh = 0;
  451. float2 texOffset2 = 0;
  452. bool bCondition = true;
  453. while ( bCondition == true && nStepIndex < nNumSteps )
  454. {
  455. vTexCurrentOffset -= vTexOffsetPerStep;
  456. fCurrHeight = tex2Dgrad( HeightMapSampler, vTexCurrentOffset, dx, dy ).r;
  457. fCurrentBound -= fStepSize;
  458. if ( fCurrHeight > fCurrentBound )
  459. {
  460. x = fCurrentBound;
  461. y = fCurrentBound + fStepSize;
  462. xh = fCurrHeight;
  463. yh = fPrevHeight;
  464. texOffset2 = vTexCurrentOffset - vTexOffsetPerStep;
  465. bCondition = false;
  466. }
  467. else
  468. {
  469. nStepIndex++;
  470. fPrevHeight = fCurrHeight;
  471. }
  472. } // End of while ( bCondition == true && nStepIndex > -1 )#else
  473. fCurrentBound -= fStepSize;
  474. float fParallaxAmount;
  475. float numerator = (x * (y - yh) - y * (x - xh));
  476. float denomenator = ((y - yh) - (x - xh));
  477. // avoid NaN generation
  478. if( ( numerator == 0.0f ) && ( denomenator == 0.0f ) )
  479. {
  480. fParallaxAmount = 0.0f;
  481. }
  482. else
  483. {
  484. fParallaxAmount = numerator / denomenator;
  485. }
  486. float2 vParallaxOffset = vParallax * (1 - fParallaxAmount );
  487. // Sample the height at the next possible step:
  488. fNextHeight = tex2Dgrad( HeightMapSampler, texOffset2, dx, dy ).r;
  489. // Original offset:
  490. float2 texSampleBase = inTexCoord - vParallaxOffset;
  491. return texSampleBase;
  492. #if 0
  493. cResultColor.rgb = ComputeDiffuseColor( texSampleBase, vLight );
  494. float fBound = 1.0 - fStepSize * nStepIndex;
  495. if ( fNextHeight < fCurrentBound )
  496. // if( 0 )
  497. {
  498. //void DoIteration( in float2 vParallaxJittered, in float3 vLight, inout float4 cResultColor )
  499. //cResultColor.rgb = float3(1,0,0);
  500. DoIteration( vParallax + vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );
  501. DoIteration( vParallax - vPixelSize, vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );
  502. DoIteration( vParallax + float2( -vPixelSize.x, vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );
  503. DoIteration( vParallax + float2( vPixelSize.x, -vPixelSize.y ), vLight, fStepSize, inTexCoord, nStepIndex, dx, dy, fBound, cResultColor );
  504. cResultColor.rgb /= 5;
  505. // cResultColor.rgb = float3( 1.0f, 0.0f, 0.0f );
  506. } // End of if ( fNextHeight < fCurrentBound )
  507. #if DOSHADOWS
  508. {
  509. //============================================//
  510. // Soft shadow and self-occlusion computation //
  511. //============================================//
  512. // Compute the blurry shadows (note that this computation takes into
  513. // account self-occlusion for shadow computation):
  514. float sh0 = tex2D( sNormalMap, texSampleBase).w;
  515. float shA = (tex2D( sNormalMap, texSampleBase + inXY * 0.88 ).w - sh0 - 0.88 ) * 1 * fShadowSoftening;
  516. float sh9 = (tex2D( sNormalMap, texSampleBase + inXY * 0.77 ).w - sh0 - 0.77 ) * 2 * fShadowSoftening;
  517. float sh8 = (tex2D( sNormalMap, texSampleBase + inXY * 0.66 ).w - sh0 - 0.66 ) * 4 * fShadowSoftening;
  518. float sh7 = (tex2D( sNormalMap, texSampleBase + inXY * 0.55 ).w - sh0 - 0.55 ) * 6 * fShadowSoftening;
  519. float sh6 = (tex2D( sNormalMap, texSampleBase + inXY * 0.44 ).w - sh0 - 0.44 ) * 8 * fShadowSoftening;
  520. float sh5 = (tex2D( sNormalMap, texSampleBase + inXY * 0.33 ).w - sh0 - 0.33 ) * 10 * fShadowSoftening;
  521. float sh4 = (tex2D( sNormalMap, texSampleBase + inXY * 0.22 ).w - sh0 - 0.22 ) * 12 * fShadowSoftening;
  522. // Compute the actual shadow strength:
  523. float fShadow = 1 - max( max( max( max( max( max( shA, sh9 ), sh8 ), sh7 ), sh6 ), sh5 ), sh4 );
  524. cResultColor.rgb *= fShadow * 0.6 + 0.4;
  525. }
  526. #endif
  527. return cResultColor;
  528. #endif
  529. }
  530. //======================================//
  531. // HSL Color space conversion routines //
  532. //======================================//
  533. #define HUE 0
  534. #define SATURATION 1
  535. #define LIGHTNESS 2
  536. // Convert from RGB to HSL color space
  537. float4 RGBtoHSL( float4 inColor )
  538. {
  539. float h, s;
  540. float flMax = max( inColor.r, max( inColor.g, inColor.b ) );
  541. float flMin = min( inColor.r, min( inColor.g, inColor.b ) );
  542. float l = (flMax + flMin) / 2.0f;
  543. if (flMax == flMin) // achromatic case
  544. {
  545. s = h = 0;
  546. }
  547. else // chromatic case
  548. {
  549. // Next, calculate the hue
  550. float delta = flMax - flMin;
  551. // First, calculate the saturation
  552. if (l < 0.5f) // If we're in the lower hexcone
  553. {
  554. s = delta/(flMax + flMin);
  555. }
  556. else
  557. {
  558. s = delta/(2 - flMax - flMin);
  559. }
  560. if ( inColor.r == flMax )
  561. {
  562. h = (inColor.g - inColor.b)/delta; // color between yellow and magenta
  563. }
  564. else if ( inColor.g == flMax )
  565. {
  566. h = 2 + (inColor.b - inColor.r)/delta; // color between cyan and yellow
  567. }
  568. else // blue must be max
  569. {
  570. h = 4 + (inColor.r - inColor.g)/delta; // color between magenta and cyan
  571. }
  572. h *= 60.0f;
  573. if (h < 0.0f)
  574. {
  575. h += 360.0f;
  576. }
  577. h /= 360.0f;
  578. }
  579. return float4 (h, s, l, 1.0f);
  580. }
  581. float HueToRGB( float v1, float v2, float vH )
  582. {
  583. float fResult = v1;
  584. vH = fmod (vH + 1.0f, 1.0f);
  585. if ( ( 6.0f * vH ) < 1.0f )
  586. {
  587. fResult = ( v1 + ( v2 - v1 ) * 6.0f * vH );
  588. }
  589. else if ( ( 2.0f * vH ) < 1.0f )
  590. {
  591. fResult = ( v2 );
  592. }
  593. else if ( ( 3.0f * vH ) < 2.0f )
  594. {
  595. fResult = ( v1 + ( v2 - v1 ) * ( ( 2.0f / 3.0f ) - vH ) * 6.0f );
  596. }
  597. return fResult;
  598. }
  599. // Convert from HSL to RGB color space
  600. float4 HSLtoRGB( float4 hsl )
  601. {
  602. float r, g, b;
  603. float h = hsl[HUE];
  604. float s = hsl[SATURATION];
  605. float l = hsl[LIGHTNESS];
  606. if ( s == 0 )
  607. {
  608. r = g = b = l;
  609. }
  610. else
  611. {
  612. float v1, v2;
  613. if ( l < 0.5f )
  614. v2 = l * ( 1.0f + s );
  615. else
  616. v2 = ( l + s ) - ( s * l );
  617. v1 = 2 * l - v2;
  618. r = HueToRGB( v1, v2, h + ( 1.0f / 3.0f ) );
  619. g = HueToRGB( v1, v2, h );
  620. b = HueToRGB( v1, v2, h - ( 1.0f / 3.0f ) );
  621. }
  622. return float4( r, g, b, 1.0f );
  623. }
  624. // texture combining modes for combining base and detail/basetexture2
  625. #define TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2 0 // original mode
  626. #define TCOMBINE_RGB_ADDITIVE 1 // base.rgb+detail.rgb*fblend
  627. #define TCOMBINE_DETAIL_OVER_BASE 2
  628. #define TCOMBINE_FADE 3 // straight fade between base and detail.
  629. #define TCOMBINE_BASE_OVER_DETAIL 4 // use base alpha for blend over detail
  630. #define TCOMBINE_RGB_ADDITIVE_SELFILLUM 5 // add detail color post lighting
  631. #define TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE 6
  632. #define TCOMBINE_MOD2X_SELECT_TWO_PATTERNS 7 // use alpha channel of base to select between mod2x channels in r+a of detail
  633. #define TCOMBINE_MULTIPLY 8
  634. #define TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA 9 // use alpha channel of detail to mask base
  635. #define TCOMBINE_SSBUMP_BUMP 10 // use detail to modulate lighting as an ssbump
  636. #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
  637. #define TCOMBINE_NONE 12 // there is no detail texture
  638. HALF4 TextureCombine( HALF4 baseColor, HALF4 detailColor, int combine_mode,
  639. HALF fBlendFactor )
  640. {
  641. if ( combine_mode == TCOMBINE_MOD2X_SELECT_TWO_PATTERNS)
  642. {
  643. HALF3 dc=lerp(detailColor.r,detailColor.a, baseColor.a);
  644. baseColor.rgb*=lerp(HALF3(1,1,1),2.0h*dc,fBlendFactor);
  645. }
  646. if ( combine_mode == TCOMBINE_RGB_EQUALS_BASE_x_DETAILx2)
  647. baseColor.rgb*=lerp(HALF3(1,1,1),2.0h*detailColor.rgb,fBlendFactor);
  648. if ( combine_mode == TCOMBINE_RGB_ADDITIVE )
  649. baseColor.rgb += fBlendFactor * detailColor.rgb;
  650. if ( combine_mode == TCOMBINE_DETAIL_OVER_BASE )
  651. {
  652. HALF fblend=fBlendFactor * detailColor.a;
  653. baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend);
  654. }
  655. if ( combine_mode == TCOMBINE_FADE )
  656. {
  657. baseColor = lerp( baseColor, detailColor, fBlendFactor);
  658. }
  659. if ( combine_mode == TCOMBINE_BASE_OVER_DETAIL )
  660. {
  661. HALF fblend=fBlendFactor * (1-baseColor.a);
  662. baseColor.rgb = lerp( baseColor.rgb, detailColor.rgb, fblend );
  663. baseColor.a = detailColor.a;
  664. }
  665. if ( combine_mode == TCOMBINE_MULTIPLY )
  666. {
  667. baseColor = lerp( baseColor, baseColor*detailColor, fBlendFactor);
  668. }
  669. if (combine_mode == TCOMBINE_MASK_BASE_BY_DETAIL_ALPHA )
  670. {
  671. baseColor.a = lerp( baseColor.a, baseColor.a*detailColor.a, fBlendFactor );
  672. }
  673. if ( combine_mode == TCOMBINE_SSBUMP_NOBUMP )
  674. {
  675. baseColor.rgb = baseColor.rgb * dot( detailColor.rgb, 2.0h/3.0h );
  676. }
  677. return baseColor;
  678. }
  679. float3 lerp5(float3 f1, float3 f2, float i1, float i2, float x)
  680. {
  681. return f1+(f2-f1)*(x-i1)/(i2-i1);
  682. }
  683. HALF3 TextureCombinePostLighting( HALF3 lit_baseColor, HALF4 detailColor, int combine_mode,
  684. HALF fBlendFactor )
  685. {
  686. if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM )
  687. lit_baseColor += fBlendFactor * detailColor.rgb;
  688. if ( combine_mode == TCOMBINE_RGB_ADDITIVE_SELFILLUM_THRESHOLD_FADE )
  689. {
  690. // fade in an unusual way - instead of fading out color, remap an increasing band of it from
  691. // 0..1
  692. if ( fBlendFactor > 0.5h)
  693. lit_baseColor += min(1, (1.0h/fBlendFactor)*max(0, detailColor.rgb-(1-fBlendFactor) ) );
  694. else
  695. lit_baseColor += 2*fBlendFactor*2*max(0, detailColor.rgb-.5h);
  696. }
  697. return lit_baseColor;
  698. }
  699. #if ( defined( _X360 ) || defined ( _PS3 ) )
  700. float SampleHardwareDepth( sampler DepthSampler, float2 vDepthSampleCoords )
  701. {
  702. float flSceneProjZ = 0.0f;
  703. #if ( defined( _PS3 ) )
  704. {
  705. float3 vSceneDepth = tex2D( DepthSampler, vDepthSampleCoords ).xyz;
  706. // There's a slightly faster, but less precise way to recover Z here if we need it - see the Cgc docs.
  707. vSceneDepth = round( vSceneDepth.xyz * 255.0f );
  708. float3 vDepthFactorPrecise = float3( 65536.0/16777215.0, 256.0/16777215.0, 1.0/16777215.0 );
  709. flSceneProjZ = dot( vSceneDepth.xyz, vDepthFactorPrecise );
  710. }
  711. #elif ( defined( _X360 ) )
  712. {
  713. float4 vSampledDepths;
  714. asm
  715. {
  716. tfetch2D vSampledDepths.x___, vDepthSampleCoords, DepthSampler, OffsetX=0.5, OffsetY=0.5, MinFilter=point, MagFilter=point, MipFilter=point
  717. };
  718. flSceneProjZ = vSampledDepths.x;
  719. #if ( defined( REVERSE_DEPTH_ON_X360 ) )
  720. {
  721. flSceneProjZ = 1.0f - flSceneProjZ;
  722. }
  723. #endif
  724. }
  725. #endif
  726. return flSceneProjZ;
  727. }
  728. #endif
  729. HALF DepthFeathering( sampler DepthSampler, const float4 vProjPos, float4 vDepthBlendConstants )
  730. {
  731. # if ( !(defined(SHADER_MODEL_PS_1_1) || defined(SHADER_MODEL_PS_1_4) || defined(SHADER_MODEL_PS_2_0)) ) //minimum requirement of ps2b
  732. {
  733. float2 vProjPosDivW = vProjPos.xy / vProjPos.w;
  734. float2 vScreenPos = vProjPosDivW * g_vDepthFeatherViewportMad.xy + g_vDepthFeatherViewportMad.zw;
  735. float flFeatheredAlpha;
  736. # if ( defined( _X360 ) || defined ( _PS3 ) )
  737. {
  738. // This code can handle oblique projection matrices used on the PS3. The depth feathering factor is a function computed in viewspace Z.
  739. // Sample the scene's depth at the current fragment.
  740. float flSceneProjZ = SampleHardwareDepth( DepthSampler, vScreenPos );
  741. float4 vSceneProjPos = float4( vProjPosDivW.x, vProjPosDivW.y, flSceneProjZ, 1.0f );
  742. float flSceneViewZ = dot( vSceneProjPos, g_vDepthFeatherProjToViewZW[0] );
  743. float flSceneViewW = dot( vSceneProjPos, g_vDepthFeatherProjToViewZW[1] );
  744. flSceneViewZ /= flSceneViewW;
  745. // Computes the fragment's viewspace Z from its projection space coord.
  746. // We could iterate the fragment's viewspace Z to save these 2 dots and a rcp, but this would require an extra iterator
  747. // and modifications to all the vertex shaders to compute viewspace coords (which was tricky enough that this approach seems
  748. // like the best compromise of devtime+testing vs. perf).
  749. float flSurfViewZ = dot( vProjPos, g_vDepthFeatherProjToViewZW[0] );
  750. float flSurfViewW = dot( vProjPos, g_vDepthFeatherProjToViewZW[1] );
  751. flSurfViewZ /= flSurfViewW;
  752. flFeatheredAlpha = flSurfViewZ - flSceneViewZ;
  753. flFeatheredAlpha = saturate( saturate( vDepthBlendConstants.z * flFeatheredAlpha ) + vDepthBlendConstants.w );
  754. }
  755. # else
  756. {
  757. float flSceneDepth = tex2D( DepthSampler, vScreenPos ).a; // PC uses dest alpha of the frame buffer
  758. float flSpriteDepth = SoftParticleDepth( vProjPos.z );
  759. flFeatheredAlpha = abs(flSceneDepth - flSpriteDepth) * vDepthBlendConstants.x;
  760. 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.
  761. flFeatheredAlpha = saturate( flFeatheredAlpha );
  762. }
  763. # endif
  764. return flFeatheredAlpha;
  765. }
  766. # else
  767. {
  768. return 1.0h;
  769. }
  770. # endif
  771. }
  772. HALF ComputeCameraFade( float4 vProjPos, float flNearPlane = 7.0f )
  773. {
  774. #if ( defined( _X360 ) || defined ( _PS3 ) )
  775. // Compute viewspace Z and W, just like depth feathering (which is currently only supported on the consoles,
  776. // which is why I'm only computing the factor in viewspace on the consoles as well).
  777. float flSurfViewZ = dot( vProjPos, g_vDepthFeatherProjToViewZW[0] );
  778. float flSurfViewW = dot( vProjPos, g_vDepthFeatherProjToViewZW[1] );
  779. // Project to W=1.
  780. flSurfViewZ /= flSurfViewW;
  781. // Compute fade factor from viewspace Z.
  782. float flFadeFactorScale = .06f;
  783. flSurfViewZ = saturate( ( -flSurfViewZ - flNearPlane ) * flFadeFactorScale );
  784. return flSurfViewZ * flSurfViewZ;
  785. #else
  786. return smoothstep( 0.0f, 1.0f, saturate( vProjPos.z * 0.025f ) );
  787. #endif
  788. }
  789. #define ORDERED_DITHER_MAGNITUDE .008f
  790. float3 ScreenSpaceOrderedDither( float2 vScreenPos )
  791. {
  792. if (0)
  793. {
  794. // No dithering.
  795. return float3(0.0f, 0.0f, 0.0f);
  796. }
  797. else if (1)
  798. {
  799. // Iestyn's RGB dither (3 extra instructions).
  800. float3 vDither = dot( float2(171, 231), vScreenPos );
  801. vDither = frac( vDither / float3( 103, 71, 97 ) ) - 0.5f;
  802. return ( vDither / 255 ) * .175f;
  803. }
  804. else if (0)
  805. {
  806. // 2x2 ordered dither.
  807. vScreenPos = frac( vScreenPos * .5f ) * 2.0f;
  808. return ( ( vScreenPos.y * 3.0f + ( vScreenPos.y * 2.0f - 1.0f ) * vScreenPos.x * -2.0f ) - 2.0f ) * ( ORDERED_DITHER_MAGNITUDE / 4.0f );
  809. }
  810. else
  811. {
  812. // 2x2 ordered dither (unoptimized - ~5 extra instructions).
  813. float3 vOutput = float3(0, 0, 0);
  814. int2 vDitherPhase = frac(vScreenPos * .5f) * 2.0f;
  815. float flMagnitude = ORDERED_DITHER_MAGNITUDE * (1.0f/4.0f);
  816. if (vDitherPhase.x)
  817. {
  818. if (vDitherPhase.y)
  819. {
  820. // 11: 1
  821. vOutput.xyz += float3(1.0f, 1.0f, 1.0f) * flMagnitude;
  822. }
  823. else
  824. {
  825. // 10: 2
  826. vOutput.xyz += float3(2.0f, 2.0f, 2.0f) * flMagnitude;
  827. }
  828. }
  829. else
  830. {
  831. if (vDitherPhase.y)
  832. {
  833. // 01: 3
  834. vOutput.xyz += float3(3.0f, 3.0f, 3.0f) * flMagnitude;
  835. }
  836. else
  837. {
  838. // 00: 0
  839. //vOutput = float3(0.0f, 0.0f, 0.0f);
  840. }
  841. }
  842. // Output biasing to match Iestyn's dither.
  843. vOutput -= float3(2.0f, 2.0f, 2.0f) * flMagnitude;
  844. return vOutput;
  845. }
  846. }
  847. #endif //#ifndef COMMON_PS_FXC_H_