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.

311 lines
12 KiB

  1. // STATIC: "BUMPMAP" "0..2"
  2. // STATIC: "CUBEMAP" "0..2"
  3. // STATIC: "SEAMLESS" "0..1"
  4. // STATIC: "THICKPAINT" "0..1"
  5. // DYNAMIC: "FASTPATHENVMAPCONTRAST" "0..1"
  6. // DYNAMIC: "FASTPATH" "0..1"
  7. // SKIP: ( $BUMPMAP == 0 )
  8. // Turning off 32bit lightmaps on Portal 2 to save shader perf. --Thorsten
  9. //#define USE_32BIT_LIGHTMAPS_ON_360 // be sure to keep this in sync with the same #define in materialsystem/cmatlightmaps.cpp
  10. #include "common_fog_ps_supportsvertexfog_fxc.h"
  11. #include "common_ps_fxc.h"
  12. #define PIXELSHADER
  13. #include "common_lightmappedgeneric_fxc.h"
  14. #if SEAMLESS
  15. #define USE_FAST_PATH 1
  16. #else
  17. #define USE_FAST_PATH FASTPATH
  18. #endif
  19. const float4 g_EnvmapTint : register( c0 );
  20. #if USE_FAST_PATH == 1
  21. # if FASTPATHENVMAPCONTRAST == 0
  22. static const float3 g_EnvmapContrast = { 0.0f, 0.0f, 0.0f };
  23. # else
  24. static const float3 g_EnvmapContrast = { 1.0f, 1.0f, 1.0f };
  25. # endif
  26. static const float3 g_EnvmapSaturation = { 1.0f, 1.0f, 1.0f };
  27. static const float g_FresnelReflection = 1.0f;
  28. static const float g_OneMinusFresnelReflection = 0.0f;
  29. static const float4 g_SelfIllumTint = { 1.0f, 1.0f, 1.0f, 1.0f };
  30. #else
  31. const float3 g_EnvmapContrast : register( c2 );
  32. const float3 g_EnvmapSaturation : register( c3 );
  33. const float4 g_FresnelReflectionReg : register( c4 );
  34. #define g_FresnelReflection g_FresnelReflectionReg.a
  35. #define g_OneMinusFresnelReflection g_FresnelReflectionReg.b
  36. const float4 g_SelfIllumTint : register( c7 );
  37. #endif
  38. const float3 g_EyePos : register( c10 );
  39. const float4 g_FogParams : register( c11 );
  40. const float4 g_TintValuesTimesLightmapScale : register( c12 );
  41. #define g_flAlpha2 g_TintValuesTimesLightmapScale.w
  42. #if PARALLAX_MAPPING || (CUBEMAP == 2)
  43. const float4 g_ParallaxMappingControl : register( c20 );
  44. #endif
  45. #if (CUBEMAP == 2)
  46. #define g_DiffuseCubemapScale g_ParallaxMappingControl.y
  47. #endif
  48. const float3 g_TintValuesWithoutLightmapScale : register( c21 );
  49. // These constants are used to rotate the world space water normals around the up axis to align the
  50. // normal with the camera and then give us a 2D offset vector to use for reflection and refraction uv's
  51. const float3 g_vWorldToViewRefract0 : register( c22 );
  52. const float3 g_vWorldToViewRefract1 : register( c23 );
  53. sampler LightmapSampler : register( s1 );
  54. samplerCUBE EnvmapSampler : register( s2 );
  55. sampler BubbleLayoutSampler : register( s4 );
  56. sampler BubbleSampler : register( s5 );
  57. sampler SplatNormalSampler : register( s7 );
  58. sampler PaintSampler : register( s9 );
  59. #if defined( _X360 )
  60. [maxtempreg(36)]
  61. #endif // _X360
  62. float4_color_return_type main( PS_INPUT i ) : COLOR
  63. {
  64. float3 worldPos = i.worldPos_projPosZ.xyz;
  65. float3x3 tangenttranspose = float3x3( i.tangentSpaceTranspose0_vertexBlendX.xyz, i.tangentSpaceTranspose1_bumpTexCoord2u.xyz, i.tangentSpaceTranspose2_bumpTexCoord2v.xyz );
  66. float3x3 worldToTangentSpace = transpose( tangenttranspose ); //yay, math both forwards and backwards, for kicks!
  67. float3 worldVertToEyeVector = g_EyePos - worldPos;
  68. float3 lightmapColor1 = float3( 1.0f, 1.0f, 1.0f );
  69. float3 lightmapColor2 = float3( 1.0f, 1.0f, 1.0f );
  70. float3 lightmapColor3 = float3( 1.0f, 1.0f, 1.0f );
  71. float2 bumpCoord1;
  72. float2 bumpCoord2;
  73. float2 bumpCoord3;
  74. ComputeBumpedLightmapCoordinates( i.lightmapTexCoord1And2, i.lightmapTexCoord3_bumpTexCoord.xy,
  75. bumpCoord1, bumpCoord2, bumpCoord3 );
  76. float2 paintCoord = bumpCoord1.xy - ( bumpCoord2.xy - bumpCoord1.xy ); // remove offset from 1st of the bumped coords for vanilla coords
  77. float4 paintColor = tex2D( PaintSampler, paintCoord );
  78. #if ( THICKPAINT )
  79. {
  80. lightmapColor1 = LightMapSample( LightmapSampler, bumpCoord1 ).rgb;
  81. lightmapColor2 = LightMapSample( LightmapSampler, bumpCoord2 ).rgb;
  82. lightmapColor3 = LightMapSample( LightmapSampler, bumpCoord3 ).rgb;
  83. }
  84. #else
  85. {
  86. lightmapColor1 = LightMapSample( LightmapSampler, paintCoord ).rgb; // use vanilla lightmap coords, not bumped
  87. }
  88. #endif
  89. float2 coords = paintCoord.xy * 40.0f;
  90. coords.y *= 0.5f; // paint map is built scaled in y, so must compensate in other texture fetches
  91. #if defined( SHADER_MODEL_PS_2_0 )
  92. return paintColor;
  93. #endif
  94. float alpha = paintColor.a;
  95. clip( alpha - 0.01f );
  96. //paint splat guts
  97. float3 fvNormalTs = float3( 0.0f, 0.0f, 1.0f );
  98. float4 fvSplats = tex2D( SplatNormalSampler, coords );
  99. float3 fvViewDirectionTs = normalize( mul( worldVertToEyeVector, worldToTangentSpace ) );
  100. alpha = (paintColor.a + fvSplats.a ) * 0.5f; // vanilla combined alpha
  101. float fPaintThickness = smoothstep( 0.34f, 0.63f, alpha );
  102. float4 cMixedPaint = paintColor.rgba;
  103. #if( THICKPAINT )
  104. {
  105. float4 fvSplatsPushed = tex2D( SplatNormalSampler, coords + fvViewDirectionTs * fvSplats.a * 0.01 );
  106. float bumpedPaintArea = smoothstep( 0.6f, 0.3f, alpha ); //area in which to super-bump, ie the edges of the paint
  107. bumpedPaintArea *= fPaintThickness;
  108. fvNormalTs = ( fvSplatsPushed.xyz * 2.0f ) - 1.0f ;
  109. fvNormalTs.xy *= lerp( 0.1f, 4.0f, bumpedPaintArea );
  110. float2 fvPaintCoordsDistorted = paintCoord.xy + ( 0.003 - 0.006 * alpha );
  111. cMixedPaint = tex2D( PaintSampler, fvPaintCoordsDistorted ); // use distorted UVs so that the blend between different paint colors isn't blocky
  112. cMixedPaint.rgb = lerp( paintColor.rgb, cMixedPaint.rgb, smoothstep( 0.9f, 1.0f, cMixedPaint.a ) ); // avoid fetching too far by fading out distorted paint towards edges
  113. }
  114. #else
  115. {
  116. fvNormalTs = ( fvSplats.xyz * 2.0f ) - 1.0f;
  117. }
  118. #endif
  119. // Always simulate srgb reads in shader code for the tex2Dsrgb calls since the paint textures look better when filtered in gamma space
  120. #if ( _X360 )
  121. {
  122. #if defined( CSTRIKE15 )
  123. // [mariod] - no PWL for cstrike15
  124. cMixedPaint.rgb = GammaToLinear( cMixedPaint.rgb );
  125. #else
  126. cMixedPaint.rgb = X360GammaToLinear( cMixedPaint.rgb );
  127. #endif
  128. }
  129. #else
  130. {
  131. cMixedPaint.rgb = SrgbGammaToLinear( cMixedPaint.rgb );
  132. }
  133. #endif
  134. float3 vNormalWs = mul( fvNormalTs.xyz, tangenttranspose );
  135. #if ( THICKPAINT )
  136. float4 vN;
  137. vN.x = dot( g_vWorldToViewRefract0.xyz, vNormalWs.xyz );
  138. vN.y = dot( g_vWorldToViewRefract1.xyz, vNormalWs.xyz );
  139. vN.wz = vN.xy;
  140. float flD = (paintColor.a + fvSplats.a );
  141. flD *= smoothstep( 1.0f, 2.0f, flD );
  142. float4 vDependentTexCoords = vN.xyzw * flD;
  143. float2 vRefractTexCoord = vDependentTexCoords.wz;
  144. float2 fvLayoutCoords = coords.xy * 6.5f + fvViewDirectionTs.xy * 0.0014f;
  145. float2 fvDeepLayoutCoords = fvLayoutCoords * 1.76f + fvViewDirectionTs.xy * 0.0007f;
  146. fvLayoutCoords += fvViewDirectionTs.xy * 0.03; //single-step parallax so that the bubbles look higher than the surface they're on
  147. float4 fvLayout = tex2D( BubbleLayoutSampler, fvLayoutCoords );
  148. float4 fvDeepLayout = tex2D( BubbleLayoutSampler, fvDeepLayoutCoords );
  149. fvLayout.xy -= 0.5f;
  150. fvLayout.z *= smoothstep( 0.750f, 0.80f, alpha );
  151. fvDeepLayout.xy -= 0.5f;
  152. fvDeepLayout.z *= smoothstep( 0.40f, 0.75f, alpha );
  153. // generate matrix for transforming UV coordinates to be screen-facing
  154. // used by the paint to render bubbles that act like facing particles, but are distributed
  155. // using a texture that describes the UV layout. Causing the UVs to face the camera
  156. // ensures the bubbles always appear round
  157. float3x3 matCameraFaceUVs;
  158. matCameraFaceUVs[2] = fvViewDirectionTs; // new normal
  159. matCameraFaceUVs[1] = float3( 0.0f, 1.0f, 0.0f ); // tangent
  160. matCameraFaceUVs[0] = normalize( cross( matCameraFaceUVs[1].xyz, matCameraFaceUVs[2].xyz ) ); //binormal
  161. matCameraFaceUVs[1] = normalize( cross( matCameraFaceUVs[2].xyz, matCameraFaceUVs[0].xyz ) ); //re-square tangent
  162. // Should try to do it in vertex shader but lack of tesselation means interpolation is not so pretty
  163. //float2x2 matCameraFaceUVs;
  164. //matCameraFaceUVs[0].xy = i.detailOrBumpAndEnvmapMaskTexCoord.xy;
  165. //matCameraFaceUVs[1].xy = i.detailOrBumpAndEnvmapMaskTexCoord.zw;
  166. float2 fvBubbleCoords;
  167. fvBubbleCoords.x = dot( fvLayout.xy, matCameraFaceUVs[0].xy );
  168. fvBubbleCoords.y = dot( fvLayout.xy, matCameraFaceUVs[1].xy );
  169. float2 fvDeepBubbleCoords;
  170. fvDeepBubbleCoords.x = dot( fvDeepLayout.xy, matCameraFaceUVs[0].xy );
  171. fvDeepBubbleCoords.y = dot( fvDeepLayout.xy, matCameraFaceUVs[1].xy );
  172. float2 fvBubbleSurfaceCoords = fvLayout.xy * 0.5f + 0.5f;
  173. fvBubbleCoords.xy = fvBubbleCoords.xy + 0.5f + vRefractTexCoord * 0.05;
  174. fvDeepBubbleCoords.xy = fvDeepBubbleCoords.xy + 0.5f + vRefractTexCoord * 0.2;
  175. float4 fvDeepBubbles = tex2D( BubbleSampler, fvDeepBubbleCoords.xy );
  176. fvDeepBubbles = lerp( float4( 0.5f, 0.5f, 1.0f, 0.0f ), fvDeepBubbles, fvDeepLayout.z );
  177. float4 fvBubbles = tex2D( BubbleSampler, fvBubbleCoords.xy );
  178. fvBubbles = lerp( float4( 0.5f, 0.5f, 1.0f, 0.0f ), fvBubbles, fvLayout.z );
  179. float3 fvSurfaceBubbles = tex2D( BubbleSampler, fvBubbleSurfaceCoords.xy ).xyz;
  180. fvSurfaceBubbles.xyz = ( fvSurfaceBubbles.xyz * 2.0f ) - 1.0f;
  181. fvSurfaceBubbles.xy *= -2.0f;
  182. fvNormalTs.xyz += fvSurfaceBubbles.xyz * pow( fvLayout.z, 3.5f ) * 0.4f;
  183. fvNormalTs.xyz = normalize( fvNormalTs.xyz );
  184. float4 worldSpaceBubblesNormal = lerp( fvDeepBubbles * float4( 1.0f, 1.0f, 1.0f, 0.4f ), fvBubbles, fvBubbles.a );
  185. worldSpaceBubblesNormal.xyz = mul( worldSpaceBubblesNormal.xyz * 2.0f - 1.0f, tangenttranspose );
  186. worldSpaceBubblesNormal = normalize( worldSpaceBubblesNormal );
  187. #endif
  188. float3 diffuseLighting = float3( 0.0f, 0.0f, 0.0f );
  189. #if ( THICKPAINT )
  190. {
  191. float3 dp;
  192. dp.x = saturate( dot( fvNormalTs.xyz, bumpBasis[0] ) );
  193. dp.y = saturate( dot( fvNormalTs.xyz, bumpBasis[1] ) );
  194. dp.z = saturate( dot( fvNormalTs.xyz, bumpBasis[2] ) );
  195. dp *= dp;
  196. diffuseLighting = dp.x * lightmapColor1 +
  197. dp.y * lightmapColor2 +
  198. dp.z * lightmapColor3;
  199. float sum = dot( dp, float3( 1.0f, 1.0f, 1.0f ) );
  200. diffuseLighting *= g_TintValuesTimesLightmapScale.rgb / sum;
  201. }
  202. #else
  203. {
  204. diffuseLighting = lightmapColor1 * g_TintValuesTimesLightmapScale.rgb;
  205. }
  206. #endif
  207. float3 diffuseComponent = diffuseLighting;
  208. float fLum = dot( cMixedPaint.rgb, float3( 0.299f, 0.587f, 0.114f ) ) * 0.5f; //desaturated, darken
  209. float3 cPaint = lerp( float3( fLum, fLum, fLum ), cMixedPaint.rgb, fPaintThickness ); //less thick areas should be less saturated
  210. vNormalWs.xyz = mul( fvNormalTs, tangenttranspose );
  211. float3 specularLighting = float3( 0.0f, 0.0f, 0.0f );
  212. // Calc Fresnel factor
  213. float3 eyeVect = normalize(worldVertToEyeVector);
  214. float fresnel = dot( vNormalWs, eyeVect );
  215. float3 reflectVect = CalcReflectionVectorUnnormalized( vNormalWs, worldVertToEyeVector );
  216. #if ( THICKPAINT )
  217. float3 reflectVectBubbles = CalcReflectionVectorUnnormalized( worldSpaceBubblesNormal.xyz, worldVertToEyeVector );
  218. #endif
  219. float fBubbleReflectLum = 0.0f;
  220. #if ( CUBEMAP )
  221. // Must use environment map scale to get proper behavior across platforms with different texture formats (divide by 16 because code was written on PC where env_map_scale is 16.0)
  222. specularLighting += ( ENV_MAP_SCALE / 16.0f )* texCUBE( EnvmapSampler, reflectVect ).rgb * ( 1.5f - fresnel ) * 0.67f; //TODO: remove magic numbers
  223. #if ( THICKPAINT )
  224. float3 bubbleSpecularLighting = ( ENV_MAP_SCALE / 16.0f )* texCUBE( EnvmapSampler, reflectVectBubbles ).rgb * ( cPaint ) * worldSpaceBubblesNormal.a * fresnel * 2.0f;
  225. specularLighting.rgb += bubbleSpecularLighting.rgb;
  226. #endif
  227. specularLighting *= ( 1.0f + diffuseComponent );
  228. #endif
  229. float3 result;
  230. alpha = smoothstep( 0.40f, 0.45f, alpha );
  231. #if ( THICKPAINT )
  232. float alphaBubbles = fvBubbles.a * 0.3f + fvDeepBubbles.a * 0.2f;
  233. alpha = alpha - alphaBubbles * 1.25f;
  234. #endif
  235. alpha *= 0.85f;
  236. float3 fvTotalDiffuse = ( ( diffuseComponent * 0.82f ) + 0.04f ) * cPaint.rgb; // Make paint slightly emissive so we can see paint color on darkly lit surfaces
  237. fvTotalDiffuse.rgb *= float3( 0.8f, 0.85f, 1.0f ); // This matches the code in paintblob_ps20b.fxc
  238. result = fvTotalDiffuse.rgb + specularLighting.rgb;
  239. float flVertexFogFactor = 0.0f;
  240. float fogFactor = CalcPixelFogFactorSupportsVertexFog( PIXELFOGTYPE, g_FogParams, g_EyePos.xyz, worldPos, i.worldPos_projPosZ.w, flVertexFogFactor );
  241. return FinalOutput( float4( result.rgb, alpha ), fogFactor, PIXELFOGTYPE, TONEMAP_SCALE_LINEAR, false, i.worldPos_projPosZ.w );
  242. }