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.

340 lines
10 KiB

  1. //======= Copyright © 1996-2015, Valve Corporation, All rights reserved. ======
  2. // STATIC: "COMBINE_MODE" "0..6" // See below for meanings of combine modes.
  3. // DYNAMIC: "DEBUG_MODE" "0..0" [ps20]
  4. // DYNAMIC: "DEBUG_MODE" "0..1" [ps20b] [ps30]
  5. // Lerps are implemented by a multiply / blend / multiply inverse on ps20
  6. // SKIP: ( $COMBINE_MODE == 2 ) [ps20]
  7. // SKIP: ( $COMBINE_MODE == 4 || $COMBINE_MODE == 5 ) [ps20b]
  8. // SKIP: ( $COMBINE_MODE == 4 || $COMBINE_MODE == 5 ) [ps30]
  9. // SKIP: ( $COMBINE_MODE != 6 && $DEBUG_MODE == 1 )
  10. #include "common_ps_fxc.h"
  11. struct PS_INPUT
  12. {
  13. float4 texCoord01 : TEXCOORD0;
  14. float4 texCoord23 : TEXCOORD1;
  15. };
  16. #define COMBINE_MODE_MULTIPLY 0
  17. #define COMBINE_MODE_ADD 1
  18. #define COMBINE_MODE_LERP 2
  19. #define COMBINE_MODE_SELECTOR 3
  20. #define COMBINE_MODE_LERP_TEX_FIRST 4
  21. #define COMBINE_MODE_LERP_TEX_SECOND 5
  22. #define COMBINE_MODE_BLEND 6
  23. #if ( !defined( SHADER_MODEL_PS_2_0 ) )
  24. #define SKIP_SRGB_ENC_DEC 0
  25. #define ALLOW_FOUR_TEX_LOOKUPS_PER_STAGE 1
  26. #else
  27. #define SKIP_SRGB_ENC_DEC 1
  28. #define ALLOW_FOUR_TEX_LOOKUPS_PER_STAGE 0
  29. #endif
  30. const float4 cAdjustInLevel[4] : register( c2 );
  31. const int cNumTextures : register( c6 );
  32. const float4 cSelectValues[4] : register( c7 );
  33. sampler InSampler0 : register( s0 );
  34. sampler InSampler1 : register( s1 );
  35. #if ( ALLOW_FOUR_TEX_LOOKUPS_PER_STAGE )
  36. sampler InSampler2 : register( s2 );
  37. sampler InSampler3 : register( s3 );
  38. #endif
  39. #define texCoord0 texCoord01.xy
  40. #define texCoord1 texCoord01.zw
  41. #if ( ALLOW_FOUR_TEX_LOOKUPS_PER_STAGE )
  42. #define texCoord2 texCoord23.xy
  43. #define texCoord3 texCoord23.zw
  44. #endif
  45. #define g_AdjustInBlack(n) cAdjustInLevel[n].x
  46. #define g_AdjustInWhite(n) cAdjustInLevel[n].y
  47. #define g_AdjustGamma(n) cAdjustInLevel[n].z
  48. static const float4 cErrColor = float4( 0.0, 1.0, 0.0, 1.0 );
  49. #if ( COMBINE_MODE == COMBINE_MODE_MULTIPLY )
  50. static const float4 cSafeColor = float4( 1.0, 1.0, 1.0, 1.0 );
  51. #elif ( COMBINE_MODE == COMBINE_MODE_ADD )
  52. static const float4 cSafeColor = float4( 0.0, 0.0, 0.0, 0.0 );
  53. #elif ( COMBINE_MODE == COMBINE_MODE_LERP )
  54. static const float4 cSafeColor = float4( 1.0, 1.0, 1.0, 1.0 );
  55. #elif ( COMBINE_MODE == COMBINE_MODE_SELECTOR )
  56. static const float4 cSafeColor = float4( 0.0, 0.0, 0.0, 0.0 );
  57. #elif ( COMBINE_MODE == COMBINE_MODE_LERP_TEX_FIRST ) || ( COMBINE_MODE == COMBINE_MODE_LERP_TEX_SECOND )
  58. #elif ( COMBINE_MODE == COMBINE_MODE_BLEND )
  59. static const float4 cSafeColor = float4( 0.0, 0.0, 0.0, 0.0 );
  60. #else
  61. #error "Need to add mode selection here."
  62. #endif
  63. float invlerp( float x, float y, float r )
  64. {
  65. return ( r - x ) / ( y - x );
  66. }
  67. float4 invlerp( float x, float y, float4 r )
  68. {
  69. return ( r - x ) / ( y - x );
  70. }
  71. float4 ConvertLinearTosRGB( float4 lin )
  72. {
  73. #if ( SKIP_SRGB_ENC_DEC )
  74. // If we're in ps 2.0, we don't have the instruction slots to do this correctly
  75. return lin;
  76. #else
  77. float3 col_lin = lin.xyz;
  78. float3 col_srgb;
  79. for (int i = 0; i < 3; ++i)
  80. {
  81. if ( col_lin[i] <= 0.0031308f )
  82. col_srgb[i] = 12.92 * col_lin[i];
  83. else
  84. col_srgb[i] = 1.055 * pow( col_lin[i], 1.0 / 2.4 ) - 0.055;
  85. }
  86. return float4( col_srgb.xyz, lin.a );
  87. #endif
  88. }
  89. float4 ConvertsRGBToLinear( float4 srgb )
  90. {
  91. #if ( SKIP_SRGB_ENC_DEC )
  92. // If we're in ps 2.0, we don't have the instruction slots to do this correctly
  93. return srgb;
  94. #else
  95. float3 col_srgb = srgb.xyz;
  96. float3 col_lin;
  97. for (int i = 0; i < 3; ++i)
  98. {
  99. if ( col_srgb[i] <= 0.04045 )
  100. col_lin[i] = col_srgb[i] / 12.92;
  101. else
  102. col_lin[i] = pow( ( col_srgb[i] + 0.055 ) / 1.055, 2.4 );
  103. }
  104. return float4( col_lin.xyz, srgb.a );
  105. #endif
  106. }
  107. // Uses photoshop math to perform level adjustment.
  108. // Note: Photoshop does this math in sRGB space, even though that is mathematically wrong.
  109. // To match photoshop, we have to convert our textures from linear space (they're always linear in the shader)
  110. // to sRGB, perform the calculations and then return to linear space for output from the shader.
  111. // Yuck.
  112. float AdjustLevels( float inSrc, float inBlackPoint, float inWhitePoint, float inGammaValue )
  113. {
  114. if ( inBlackPoint == 0.0 && inWhitePoint == 1.0 && inGammaValue == 1.0 )
  115. return inSrc;
  116. else
  117. {
  118. inSrc = ConvertLinearTosRGB( inSrc );
  119. float pcg = saturate( invlerp( inBlackPoint, inWhitePoint, inSrc ) );
  120. float gammaAdjusted = pow( pcg, inGammaValue );
  121. gammaAdjusted = ConvertsRGBToLinear( gammaAdjusted );
  122. return saturate( gammaAdjusted );
  123. }
  124. }
  125. float4 AdjustLevels( float4 inSrc, float inBlackPoint, float inWhitePoint, float inGammaValue )
  126. {
  127. if ( inBlackPoint == 0.0 && inWhitePoint == 1.0 && inGammaValue == 1.0 )
  128. return inSrc;
  129. else
  130. {
  131. inSrc = ConvertLinearTosRGB( inSrc );
  132. float4 pcg = saturate( invlerp( inBlackPoint, inWhitePoint, inSrc ) );
  133. float4 gammaAdjusted = pow( pcg, inGammaValue );
  134. gammaAdjusted = ConvertsRGBToLinear( gammaAdjusted );
  135. return saturate( gammaAdjusted );
  136. }
  137. }
  138. #if ( COMBINE_MODE == COMBINE_MODE_MULTIPLY || COMBINE_MODE == COMBINE_MODE_ADD ) || ( COMBINE_MODE == COMBINE_MODE_BLEND )
  139. float4 main_simple( PS_INPUT i )
  140. {
  141. float4 color0 = cNumTextures > 0 ? tex2D( InSampler0, i.texCoord0 ) : cSafeColor;
  142. float4 color1 = cNumTextures > 1 ? tex2D( InSampler1, i.texCoord1 ) : cSafeColor;
  143. #if ALLOW_FOUR_TEX_LOOKUPS_PER_STAGE
  144. float4 color2 = cNumTextures > 2 ? tex2D( InSampler2, i.texCoord2 ) : cSafeColor;
  145. float4 color3 = cNumTextures > 3 ? tex2D( InSampler3, i.texCoord3 ) : cSafeColor;
  146. #endif
  147. color0 = cNumTextures > 0 ? AdjustLevels( color0, g_AdjustInBlack(0), g_AdjustInWhite(0), g_AdjustGamma(0) ) : cSafeColor;
  148. color1 = cNumTextures > 1 ? AdjustLevels( color1, g_AdjustInBlack(1), g_AdjustInWhite(1), g_AdjustGamma(1) ) : cSafeColor;
  149. #if ALLOW_FOUR_TEX_LOOKUPS_PER_STAGE
  150. color2 = cNumTextures > 2 ? AdjustLevels( color2, g_AdjustInBlack(2), g_AdjustInWhite(2), g_AdjustGamma(2) ) : cSafeColor;
  151. color3 = cNumTextures > 3 ? AdjustLevels( color3, g_AdjustInBlack(3), g_AdjustInWhite(3), g_AdjustGamma(3) ) : cSafeColor;
  152. #endif
  153. #if ( COMBINE_MODE == COMBINE_MODE_MULTIPLY )
  154. return color0
  155. * color1
  156. #if ALLOW_FOUR_TEX_LOOKUPS_PER_STAGE
  157. * color2
  158. * color3
  159. #endif
  160. ;
  161. #elif ( COMBINE_MODE == COMBINE_MODE_ADD )
  162. return color0
  163. + color1
  164. #if ALLOW_FOUR_TEX_LOOKUPS_PER_STAGE
  165. + color2
  166. + color3
  167. #endif
  168. ;
  169. #elif ( COMBINE_MODE == COMBINE_MODE_BLEND )
  170. // color0 is the previous frame's data.
  171. // color1 is the sticker's data, with alpha as transparency.
  172. // If we're on PS 2.0b, color2 has specular info as a grayscale texture--make sure to write that out.
  173. #if ( DEBUG_MODE == 0 )
  174. #if ALLOW_FOUR_TEX_LOOKUPS_PER_STAGE
  175. float srcSpecular = color2.r;
  176. #else
  177. float srcSpecular = 1;
  178. #endif
  179. float3 tmpColor = ( 1.0 - color1.a ) * color0.xyz
  180. + ( color1.a ) * color1.xyz;
  181. float tmpSpecular = ( 1.0 - color1.a ) * color0.w
  182. + ( color1.a ) * srcSpecular;
  183. return float4( tmpColor.xyz, tmpSpecular );
  184. #else
  185. if ( i.texCoord1.x < 0 || i.texCoord1.y < 0
  186. || i.texCoord1.x > 1 || i.texCoord1.y > 1 )
  187. {
  188. return color0;
  189. }
  190. else
  191. return float4( i.texCoord1.xy, 0, color0.a );
  192. #endif
  193. #else
  194. #error "Surprising combine mode in function, update code."
  195. #endif
  196. }
  197. #endif
  198. #if ( COMBINE_MODE == COMBINE_MODE_LERP )
  199. float4 main_lerp( PS_INPUT i )
  200. {
  201. if (cNumTextures == 3)
  202. {
  203. float4 color0 = tex2D( InSampler0, i.texCoord0 );
  204. float4 color1 = tex2D( InSampler1, i.texCoord1 );
  205. float4 colSel = tex2D( InSampler2, i.texCoord2 );
  206. color0 = AdjustLevels( color0, g_AdjustInBlack(0), g_AdjustInWhite(0), g_AdjustGamma(0) );
  207. color1 = AdjustLevels( color1, g_AdjustInBlack(1), g_AdjustInWhite(1), g_AdjustGamma(1) );
  208. colSel = AdjustLevels( colSel, g_AdjustInBlack(2), g_AdjustInWhite(2), g_AdjustGamma(2) );
  209. #if ( COMBINE_MODE == COMBINE_MODE_LERP )
  210. return lerp( color0, color1, colSel.xxxx );
  211. #else
  212. #error "Surprising combine mode in function, update code."
  213. #endif
  214. }
  215. else
  216. {
  217. return float4( 1, 0, 0, 1 );
  218. }
  219. }
  220. #endif
  221. #if ( COMBINE_MODE == COMBINE_MODE_SELECTOR )
  222. float4 main_selector( PS_INPUT i )
  223. {
  224. if ( cNumTextures == 1 )
  225. {
  226. float fNormalizedColor = tex2D( InSampler0, i.texCoord0 ).x;
  227. float fTestColor = round( ( fNormalizedColor * 255.0 / 16.0f ) );
  228. bool4 bTestVec[4];
  229. for ( int i = 0; i < 4; ++i )
  230. {
  231. bTestVec[i] = cSelectValues[i] != 0
  232. ? round( cSelectValues[i] ) == fTestColor
  233. : false;
  234. }
  235. bool4 bAny = bool4(
  236. any( bTestVec[0] ),
  237. any( bTestVec[1] ),
  238. any( bTestVec[2] ),
  239. any( bTestVec[3] )
  240. );
  241. #if ( COMBINE_MODE == COMBINE_MODE_SELECTOR )
  242. return any( bAny )
  243. ? float4( 1, 1, 1, 1 )
  244. : float4( 0, 0, 0, 0 );
  245. #else
  246. #error "Surprising combine mode in function, update code."
  247. #endif
  248. }
  249. else
  250. {
  251. return float4( 1, 1, 0, 1 );
  252. }
  253. }
  254. #endif
  255. #if ( COMBINE_MODE == COMBINE_MODE_LERP_TEX_FIRST || COMBINE_MODE == COMBINE_MODE_LERP_TEX_SECOND )
  256. float4 main_lerp_multipass( PS_INPUT i )
  257. {
  258. if (cNumTextures == 2)
  259. {
  260. float4 colorN = tex2D( InSampler0, i.texCoord0 );
  261. float4 colSel = tex2D( InSampler1, i.texCoord1 );
  262. colorN = AdjustLevels( colorN, g_AdjustInBlack(0), g_AdjustInWhite(0), g_AdjustGamma(0) );
  263. colSel = AdjustLevels( colSel, g_AdjustInBlack(1), g_AdjustInWhite(1), g_AdjustGamma(1) );
  264. #if ( COMBINE_MODE == COMBINE_MODE_LERP_TEX_FIRST )
  265. return colorN * ( 1.0 - colSel.xxxx );
  266. #elif ( COMBINE_MODE == COMBINE_MODE_LERP_TEX_SECOND )
  267. return colorN * ( colSel.xxxx );
  268. #else
  269. #error "Surprising combine mode in function, update code."
  270. #endif
  271. }
  272. else
  273. {
  274. return float4( 1, 0, 0, 1 );
  275. }
  276. }
  277. #endif
  278. float4 main( PS_INPUT i ) : COLOR
  279. {
  280. #if ( COMBINE_MODE == COMBINE_MODE_MULTIPLY )
  281. return main_simple( i );
  282. #elif ( COMBINE_MODE == COMBINE_MODE_ADD )
  283. return main_simple( i );
  284. #elif ( COMBINE_MODE == COMBINE_MODE_LERP )
  285. return main_lerp( i );
  286. #elif ( COMBINE_MODE == COMBINE_MODE_SELECTOR )
  287. return main_selector( i );
  288. #elif ( COMBINE_MODE == COMBINE_MODE_LERP_TEX_FIRST || COMBINE_MODE == COMBINE_MODE_LERP_TEX_SECOND )
  289. return main_lerp_multipass( i );
  290. #elif ( COMBINE_MODE == COMBINE_MODE_BLEND )
  291. return main_simple( i );
  292. #else
  293. #error "Need to add mode selection here."
  294. #endif
  295. }