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.

297 lines
9.9 KiB

  1. //========== Copyright (c) Valve Corporation, All rights reserved. ==========//
  2. // STATIC: "MULTITEXTURE" "0..1"
  3. // STATIC: "FRESNEL" "0..1"
  4. // STATIC: "BLEND" "0..1"
  5. // STATIC: "REFRACTALPHA" "0..1"
  6. // STATIC: "HDRTYPE" "0..2"
  7. // STATIC: "FLOWMAP" "0..1"
  8. // STATIC: "FLOW_DEBUG" "0..1"
  9. // DYNAMIC: "HDRENABLED" "0..1"
  10. #include "common_fog_ps_fxc.h"
  11. #include "common_ps_fxc.h"
  12. #include "shader_constant_register_map.h"
  13. // Constants
  14. const float3 g_WaterFogColor : register( c0 );
  15. const float4 g_CheapWaterParams : register( c1 );
  16. #define g_CheapWaterStart g_CheapWaterParams.x
  17. #define g_CheapWaterEnd g_CheapWaterParams.y
  18. #define g_CheapWaterDeltaRecip g_CheapWaterParams.z
  19. #define g_CheapWaterStartDivDelta g_CheapWaterParams.w
  20. const float4 g_ReflectTint : register( c2 );
  21. const float g_flTime : register( c10 );
  22. const float4 g_EyePos : register( PSREG_EYEPOS_SPEC_EXPONENT ); // c11
  23. const float4 g_PixelFogParams : register( PSREG_FOG_PARAMS ); // c12
  24. const float4 g_vFlowParams1 : register( c13 );
  25. #define g_flWorldUvScale ( g_vFlowParams1.x ) // 1.0f / 10.0f
  26. #define g_flNormalUvScale ( g_vFlowParams1.y ) // 1.0f / 1.15f
  27. #define g_flBumpStrength ( g_vFlowParams1.z ) // 3.0f
  28. #define g_flTimeScale ( g_vFlowParams1.w ) // 1.0f
  29. const float3 g_vFlowParams2 : register( c14 );
  30. #define g_flFlowTimeIntervalInSeconds ( g_vFlowParams2.x ) // 0.4f // Number of seconds to lerp from texture 1 to texture 2
  31. #define g_flFlowUvScrollDistance ( g_vFlowParams2.y ) // 0.25f // Distance in uv space to fetch
  32. #define g_flNoiseScale ( g_vFlowParams2.z )
  33. // Textures
  34. samplerCUBE EnvmapSampler : register( s0 );
  35. sampler NormalMapSampler : register( s1 );
  36. #if REFRACTALPHA
  37. sampler RefractSampler : register( s2 );
  38. #endif
  39. sampler FlowSampler : register( s3 );
  40. sampler FlowNoiseSampler : register( s4 );
  41. samplerCUBE NormalizeSampler : register( s6 );
  42. struct PS_INPUT
  43. {
  44. float4 worldSpaceEyeVect_normalMapX : TEXCOORD1;
  45. float3x3 tangentSpaceTranspose : TEXCOORD2;
  46. float4 vRefract_W_ProjZ : TEXCOORD5;
  47. #if MULTITEXTURE
  48. float4 vExtraBumpTexCoord : TEXCOORD6;
  49. #endif
  50. float4 worldPos_normalMapY : TEXCOORD7;
  51. };
  52. float2 UnpackNormal2D( float2 vNormal )
  53. {
  54. return ( ( vNormal.xy * 2.0 ) - 1.0 );
  55. }
  56. float3 UnpackNormal3D( float3 vNormal )
  57. {
  58. return ( ( vNormal.xyz * 2.0 ) - 1.0 );
  59. }
  60. float3 ComputeNormalFromXY( float2 vXY )
  61. {
  62. float3 vNormalTs;
  63. vNormalTs.xy = vXY.xy;
  64. vNormalTs.z = sqrt( saturate( 1.0 - dot( vNormalTs.xy, vNormalTs.xy ) ) );
  65. return vNormalTs.xyz;
  66. }
  67. float3 ComputeNormalFromRGTexture( float2 vRGPixel )
  68. {
  69. float3 vNormalTs;
  70. vNormalTs.xy = UnpackNormal2D( vRGPixel.rg );
  71. vNormalTs.z = sqrt( saturate( 1.0 - dot( vNormalTs.xy, vNormalTs.xy ) ) );
  72. return vNormalTs.xyz;
  73. }
  74. float4_color_return_type main( PS_INPUT i ) : COLOR
  75. {
  76. float2 normalMapTexCoord = float2( i.worldSpaceEyeVect_normalMapX.w, i.worldPos_normalMapY.w );
  77. float3 vNormal;
  78. #if ( FLOWMAP )
  79. {
  80. //*
  81. float flWorldUvScale = g_flWorldUvScale;
  82. float flNormalUvScale = g_flNormalUvScale;
  83. float flFlowTimeIntervalInSeconds = g_flFlowTimeIntervalInSeconds;
  84. float flFlowUvScrollDistance = g_flFlowUvScrollDistance;
  85. float flBumpStrength = g_flBumpStrength;
  86. float flTimeScale = g_flTimeScale;
  87. float flNoiseScale = g_flNoiseScale;
  88. //*/
  89. /* River
  90. float flWorldUvScale = 1.0f / 6.0f;
  91. float flNormalUvScale = 1.0f / 0.5f;
  92. float flFlowTimeIntervalInSeconds = 0.4f; // Number of seconds to lerp from texture 1 to texture 2
  93. float flFlowUvScrollDistance = 0.2f; // Distance in uv space to fetch
  94. float flBumpStrength = 1.0f;
  95. float flTimeScale = 0.75f;
  96. //*/
  97. /* Swamp - Heavy churn
  98. float flWorldUvScale = 1.0f / 10.0f;
  99. float flNormalUvScale = 1.0f / 1.15f;
  100. float flFlowTimeIntervalInSeconds = 0.4f; // Number of seconds to lerp from texture 1 to texture 2
  101. float flFlowUvScrollDistance = 0.25f; // Distance in uv space to fetch
  102. float flBumpStrength = 3.0f;
  103. float flTimeScale = 1.0f;
  104. //*/
  105. /* Swamp - Calmer
  106. float flWorldUvScale = 1.0f / 10.0f;
  107. float flNormalUvScale = 1.0f / 1.15f;
  108. float flFlowTimeIntervalInSeconds = 0.25f; // Number of seconds to lerp from texture 1 to texture 2
  109. float flFlowUvScrollDistance = 0.15f; // Distance in uv space to fetch
  110. float flBumpStrength = 1.05f;
  111. float flTimeScale = 0.35f;
  112. //*/
  113. // Input uv
  114. float2 vWorldUv = normalMapTexCoord.xy * flWorldUvScale;
  115. float2 vUv1 = float2( i.worldPos_normalMapY.x, -i.worldPos_normalMapY.y ) * flNormalUvScale;
  116. float2 vUv2 = vUv1.xy;
  117. // Noise texture is used to offset the time interval different spatially so we don't see pulsing
  118. float flNoise = tex2D( FlowNoiseSampler, float2( i.worldPos_normalMapY.x, -i.worldPos_normalMapY.y ) * flNoiseScale ).g;
  119. // Flow texel has a 2D flow vector in the rg channels of the texture
  120. float4 vFlowTexel = tex2D( FlowSampler, vWorldUv.xy );
  121. #if FLOW_DEBUG
  122. {
  123. return float4( vFlowTexel.rgb, 0 );
  124. }
  125. #endif
  126. // Unpack world flow vector from texture
  127. float2 vFlowVectorTs = ( vFlowTexel.rg * 2.0f ) - 1.0f;
  128. float flTimeInIntervals = ( ( g_flTime * flTimeScale ) + flNoise ) / ( flFlowTimeIntervalInSeconds * 2.0f );
  129. float flScrollTime1 = frac( flTimeInIntervals );
  130. float flScrollTime2 = frac( flTimeInIntervals + 0.5f ); // Half an interval off from texture 1
  131. // Every interval has a unique offset so we don't see the same bump texels repeating continuously
  132. float flOffset1 = floor( flTimeInIntervals ) * 0.311f;
  133. float flOffset2 = floor( flTimeInIntervals + 0.5f ) * 0.311f + 0.5f; // The +0.5 is to match the phase offset
  134. // Final flow uv is originalUv + interval offset + ( flowvector * scroll
  135. float2 vFlowUv1 = vUv1.xy + flOffset1 + ( flScrollTime1 * ( flFlowUvScrollDistance * vFlowVectorTs.xy ) );
  136. float2 vFlowUv2 = vUv2.xy + flOffset2 + ( flScrollTime2 * ( flFlowUvScrollDistance * vFlowVectorTs.xy ) );
  137. // Lerp values to blend between the two layers of bump
  138. float flWeight1 = abs( ( 2.0f * frac( flTimeInIntervals + 0.5f ) ) - 1.0f );
  139. float flWeight2 = abs( ( 2.0f * frac( flTimeInIntervals ) ) - 1.0f );
  140. float4 vNormalTexel1 = tex2D( NormalMapSampler, vFlowUv1.xy );
  141. float4 vNormalTexel2 = tex2D( NormalMapSampler, vFlowUv2.xy );
  142. float3 vNormal1 = ( vNormalTexel1.rgb );
  143. float3 vNormal2 = ( vNormalTexel2.rgb );
  144. // Combine both layers
  145. vNormal.xy = UnpackNormal2D( lerp( vNormal1.xy, vNormal2.xy, flWeight2 ) );
  146. // Change bump strength based on the length of the flow vector
  147. //vNormal.xy *= ( length( vFlowVectorTs.xy ) + 0.05f ) * flBumpStrength;
  148. vNormal.xy *= ( ( vFlowVectorTs.x * vFlowVectorTs.x + vFlowVectorTs.y * vFlowVectorTs.y ) + 0.05f ) * flBumpStrength;
  149. // Generate normal from 2D scaled normal
  150. vNormal.xyz = ComputeNormalFromXY( vNormal.xy );
  151. }
  152. #elif ( MULTITEXTURE )
  153. {
  154. vNormal.xyz = tex2D( NormalMapSampler, normalMapTexCoord ).xyz;
  155. float3 vNormal1 = tex2D( NormalMapSampler, i.vExtraBumpTexCoord.xy ).xyz;
  156. float3 vNormal2 = tex2D( NormalMapSampler, i.vExtraBumpTexCoord.zw ).xyz;
  157. vNormal = 0.33 * ( vNormal + vNormal1 + vNormal2 );
  158. vNormal = 2.0 * vNormal - 1.0;
  159. }
  160. #else
  161. {
  162. vNormal.xyz = DecompressNormal( NormalMapSampler, normalMapTexCoord, NORM_DECODE_NONE ).xyz;
  163. }
  164. #endif
  165. float3 worldSpaceNormal = mul( vNormal, i.tangentSpaceTranspose );
  166. float3 worldSpaceEye;
  167. float flWorldSpaceDist = 1.0f;
  168. #ifdef NV3X
  169. // for some reason, fxc doesn't convert length( half3 v ) into all _pp opcodes.
  170. #if ( BLEND )
  171. {
  172. worldSpaceEye = i.worldSpaceEyeVect_normalMapX.xyz;
  173. float worldSpaceDistSqr = dot( worldSpaceEye, worldSpaceEye );
  174. float rcpWorldSpaceDist = rsqrt( worldSpaceDistSqr );
  175. worldSpaceEye *= rcpWorldSpaceDist;
  176. flWorldSpaceDist = worldSpaceDistSqr * rcpWorldSpaceDist;
  177. }
  178. #else
  179. {
  180. worldSpaceEye = NormalizeWithCubemap( NormalizeSampler, i.worldSpaceEyeVect_normalMapX.xyz );
  181. }
  182. #endif
  183. #else // !NV3X
  184. #if ( BLEND )
  185. {
  186. worldSpaceEye = i.worldSpaceEyeVect_normalMapX.xyz;
  187. flWorldSpaceDist = length( worldSpaceEye );
  188. worldSpaceEye /= flWorldSpaceDist;
  189. }
  190. #else
  191. {
  192. worldSpaceEye = NormalizeWithCubemap( NormalizeSampler, i.worldSpaceEyeVect_normalMapX.xyz );
  193. }
  194. #endif
  195. #endif
  196. float3 reflectVect = CalcReflectionVectorUnnormalized( worldSpaceNormal, worldSpaceEye );
  197. float3 specularLighting = ENV_MAP_SCALE * texCUBE( EnvmapSampler, reflectVect ).rgb;
  198. specularLighting *= g_ReflectTint.rgb;
  199. #if FRESNEL
  200. // FIXME: It's unclear that we want to do this for cheap water
  201. // but the code did this previously and I didn't want to change it
  202. float flDotResult = dot( worldSpaceEye, worldSpaceNormal );
  203. flDotResult = 1.0f - max( 0.0f, flDotResult );
  204. float flFresnelFactor = flDotResult * flDotResult;
  205. flFresnelFactor *= flFresnelFactor;
  206. flFresnelFactor *= flDotResult;
  207. #else
  208. float flFresnelFactor = g_ReflectTint.a;
  209. #endif
  210. float flAlpha;
  211. #if ( BLEND )
  212. {
  213. float flReflectAmount = saturate( flWorldSpaceDist * g_CheapWaterDeltaRecip - g_CheapWaterStartDivDelta );
  214. flAlpha = saturate( flFresnelFactor + flReflectAmount );
  215. #if REFRACTALPHA
  216. // Perform division by W only once
  217. float ooW = 1.0f / i.vRefract_W_ProjZ.z;
  218. float2 unwarpedRefractTexCoord = i.vRefract_W_ProjZ.xy * ooW;
  219. float fogDepthValue = tex2D( RefractSampler, unwarpedRefractTexCoord ).a;
  220. // Fade on the border between the water and land.
  221. flAlpha *= saturate( ( fogDepthValue - .05f ) * 20.0f );
  222. #endif
  223. }
  224. #else
  225. {
  226. flAlpha = 1.0f;
  227. #if HDRTYPE == 0 || HDRENABLED == 0
  228. specularLighting = lerp( g_WaterFogColor, specularLighting, flFresnelFactor );
  229. #else
  230. specularLighting = lerp( GammaToLinear( g_WaterFogColor ), specularLighting, flFresnelFactor );
  231. #endif
  232. }
  233. #endif
  234. // multiply the color by alpha.since we are using alpha blending to blend against dest alpha for borders.
  235. #if (PIXELFOGTYPE == PIXEL_FOG_TYPE_RANGE)
  236. float fogFactor = CalcPixelFogFactor( PIXELFOGTYPE, g_PixelFogParams, g_EyePos.xyz, i.worldPos_normalMapY.xyz, i.vRefract_W_ProjZ.w );
  237. #else
  238. float fogFactor = 0;
  239. #endif
  240. return FinalOutput( float4( specularLighting, flAlpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR );
  241. }