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.

137 lines
4.9 KiB

  1. //========== Copyright (c) Valve Corporation, All rights reserved. ==========//
  2. // DYNAMIC: "QUALITY" "0..3"
  3. // Includes =======================================================================================
  4. #include "common_ps_fxc.h"
  5. // Texture Samplers ===============================================================================
  6. sampler g_tFullFB : register( s0 );
  7. sampler g_tSmallFB : register( s1 );
  8. // Shaders Constants and Globals ==================================================================
  9. float4 g_vDists : register( c0 );
  10. #define g_flNearBlurDist g_vDists.x
  11. #define g_flNearFocusDist g_vDists.y
  12. #define g_flFarFocusDist g_vDists.z
  13. #define g_flFarBlurDist g_vDists.w
  14. float3 g_vBlurAmounts : register( c1 );
  15. #define g_flMaxBlurRadius g_vBlurAmounts.x
  16. #define g_flNearBlurStrength g_vBlurAmounts.y
  17. #define g_flFarBlurStrength g_vBlurAmounts.z
  18. float3 g_vNearFarDists : register( c2 );
  19. #define g_flNearPlaneDist g_vNearFarDists.x
  20. #define g_flFarPlaneDist g_vNearFarDists.y
  21. #define g_flDepthConv g_vNearFarDists.z
  22. float4 g_vMagicConsts : register( c3 );
  23. #if ( QUALITY == 0 )
  24. #define NUM_SAMPLES 8 // These must match the C code
  25. #elif ( QUALITY == 1 )
  26. #define NUM_SAMPLES 16
  27. #elif ( QUALITY == 2 )
  28. #define NUM_SAMPLES 16
  29. #elif ( QUALITY == 3 )
  30. #define NUM_SAMPLES 32
  31. #endif
  32. float4 g_vPoisson[ NUM_SAMPLES/2 ] : register( c4 );
  33. // Interpolated values ============================================================================
  34. struct PS_INPUT
  35. {
  36. float2 vUv0 : TEXCOORD0;
  37. };
  38. float DestAlphaDepthToViewSpaceDepth( float flDepth )
  39. {
  40. return g_flDepthConv * flDepth + g_flNearPlaneDist;
  41. }
  42. // returns blur radius from depth as a fraction of max_blur.
  43. float BlurAmountFromDepth( float flDestAlphaDepth )
  44. {
  45. /*
  46. dist = DestAlphaDepthToViewSpaceDepth( flDestAlphaDepth );
  47. float flBlur = max( g_flNearBlurStrength * saturate( (flDestAlphaDepth - g_flNearFocusDist) / ( g_flNearBlurDist - g_flNearFocusDist ) ),
  48. g_flFarBlurStrength * saturate( (flDestAlphaDepth - g_flFarFocusDist) / ( g_flFarBlurDist - g_flFarFocusDist ) ) );
  49. */
  50. // A more optimized version that concatenates the math above and the one in DestAlphaDepthToViewSpaceDepth to a single muladd
  51. float flBlur = max( g_flNearBlurStrength * saturate( g_vMagicConsts.x * flDestAlphaDepth + g_vMagicConsts.y ),
  52. g_flFarBlurStrength * saturate( g_vMagicConsts.z * flDestAlphaDepth + g_vMagicConsts.w ) );
  53. return flBlur;
  54. }
  55. float BlurRadiusFromDepth( float flDepth )
  56. {
  57. return g_flMaxBlurRadius * BlurAmountFromDepth( flDepth );
  58. }
  59. float4 ComputeTap( float flCenterDepth, float flCenterBlurRadius, float2 vUV, float2 vPoisson )
  60. {
  61. float4 cTapSmall;
  62. float4 cTap;
  63. float2 vPoissonUV = vUV.xy + flCenterBlurRadius * vPoisson.xy;
  64. cTapSmall = tex2D( g_tSmallFB, vPoissonUV.xy );
  65. cTap = tex2D( g_tFullFB, vPoissonUV.xy );
  66. float flTapBlur = BlurAmountFromDepth( cTap.a ); // Maybe 50/50 mix between low and high here?
  67. cTap = lerp( cTap, cTapSmall, saturate( 2.2 * flTapBlur ) ); // TODO: tweak blur amount.
  68. float flLerpedTapBlur = BlurAmountFromDepth( cTap.a );
  69. float weight = ( cTap.a >= flCenterDepth ) ? 1.0 : ( flLerpedTapBlur*flLerpedTapBlur );
  70. return float4( cTap.rgb, 1 ) * weight;
  71. }
  72. float4 ComputeTapHQ( float flCenterDepth, float flCenterBlurRadius, float2 vUV, float2 vPoisson )
  73. {
  74. float4 cTap;
  75. cTap = tex2D( g_tFullFB, vUV.xy + flCenterBlurRadius * vPoisson.xy );
  76. float flTapBlur = BlurAmountFromDepth( cTap.a );
  77. float weight = ( cTap.a >= flCenterDepth ) ? 1.0 : ( flTapBlur * flTapBlur );
  78. return float4( cTap.rgb, 1 ) * weight;
  79. }
  80. // Main ===========================================================================================
  81. float4 main( PS_INPUT i ) : COLOR
  82. {
  83. // TODO: BETTER DOWNSAMPLE THAT TAKES DEPTH INTO ACCOUNT?
  84. float4 cOut = { 0, 0, 0, 0 };
  85. float4 cCenterTap = tex2D( g_tFullFB, i.vUv0 );
  86. float flCenterBlurRadius = BlurRadiusFromDepth( cCenterTap.a ); // circle of confusion radius for current pixel
  87. cCenterTap.a -= 0.001; // z-bias to avoid strange banding artifact on almost orthogonal walls
  88. #if ( QUALITY < 2 )
  89. // ATI's Ruby1-style algorithm
  90. for ( int t = 0; t < NUM_SAMPLES/2; t++ )
  91. {
  92. cOut.rgba += ComputeTap( cCenterTap.a, flCenterBlurRadius, i.vUv0, g_vPoisson[t].xy );
  93. cOut.rgba += ComputeTap( cCenterTap.a, flCenterBlurRadius, i.vUv0, g_vPoisson[t].wz );
  94. }
  95. #else
  96. // Less fancy, with less fetches per tap and less math. Needs more samples to look smooth.
  97. cOut = cCenterTap;
  98. cOut.a = 1.0; // Use the center sample we just fetched
  99. for ( int t = 0; t < NUM_SAMPLES/2; t++ )
  100. {
  101. cOut.rgba += ComputeTapHQ( cCenterTap.a, flCenterBlurRadius, i.vUv0, g_vPoisson[t].xy );
  102. cOut.rgba += ComputeTapHQ( cCenterTap.a, flCenterBlurRadius, i.vUv0, g_vPoisson[t].wz );
  103. }
  104. #endif
  105. //cOut.rgb = cOut.a / float(NUM_SAMPLES+1);
  106. //cOut = lerp( tex2D( g_tFullFB, i.vUv0 ), tex2D( g_tSmallFB, i.vUv0 ).aaaa, 0.5 );
  107. if ( cOut.a > 0.0 )
  108. cOut.rgba /= cOut.a;
  109. else
  110. cOut.rgba = cCenterTap.rgba;
  111. return cOut;
  112. }