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.

326 lines
9.6 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. // Purpose:
  4. //
  5. // $NoKeywords: $
  6. //
  7. //=============================================================================//
  8. #ifndef COMMON_FXC_H_
  9. #define COMMON_FXC_H_
  10. #include "common_pragmas.h"
  11. #include "common_hlsl_cpp_consts.h"
  12. #ifdef NV3X
  13. # define HALF half
  14. # define HALF2 half2
  15. # define HALF3 half3
  16. # define HALF4 half4
  17. # define HALF3x3 half3x3
  18. # define HALF3x4 half3x4
  19. # define HALF4x3 half4x3
  20. # define HALF_CONSTANT( _constant ) ((HALF)_constant)
  21. #else
  22. # define HALF float
  23. # define HALF2 float2
  24. # define HALF3 float3
  25. # define HALF4 float4
  26. # define HALF3x3 float3x3
  27. # define HALF3x4 float3x4
  28. # define HALF4x3 float4x3
  29. # define HALF_CONSTANT( _constant ) _constant
  30. #endif
  31. // This is where all common code for both vertex and pixel shaders.
  32. #define OO_SQRT_3 0.57735025882720947f
  33. static const HALF3 bumpBasis[3] = {
  34. HALF3( 0.81649661064147949f, 0.0f, OO_SQRT_3 ),
  35. HALF3( -0.40824833512306213f, 0.70710676908493042f, OO_SQRT_3 ),
  36. HALF3( -0.40824821591377258f, -0.7071068286895752f, OO_SQRT_3 )
  37. };
  38. static const HALF3 bumpBasisTranspose[3] = {
  39. HALF3( 0.81649661064147949f, -0.40824833512306213f, -0.40824833512306213f ),
  40. HALF3( 0.0f, 0.70710676908493042f, -0.7071068286895752f ),
  41. HALF3( OO_SQRT_3, OO_SQRT_3, OO_SQRT_3 )
  42. };
  43. #if defined( _X360 )
  44. #define REVERSE_DEPTH_ON_X360 //uncomment to use D3DFMT_D24FS8 with an inverted depth viewport for better performance. Keep this in sync with the same named #define in public/shaderapi/shareddefs.h
  45. //Note that the reversal happens in the viewport. So ONLY reading back from a depth texture should be affected. Projected math is unaffected.
  46. #endif
  47. HALF3 CalcReflectionVectorNormalized( HALF3 normal, HALF3 eyeVector )
  48. {
  49. // FIXME: might be better of normalizing with a normalizing cube map and
  50. // get rid of the dot( normal, normal )
  51. // compute reflection vector r = 2 * ((n dot v)/(n dot n)) n - v
  52. return 2.0 * ( dot( normal, eyeVector ) / dot( normal, normal ) ) * normal - eyeVector;
  53. }
  54. HALF3 CalcReflectionVectorUnnormalized( HALF3 normal, HALF3 eyeVector )
  55. {
  56. // FIXME: might be better of normalizing with a normalizing cube map and
  57. // get rid of the dot( normal, normal )
  58. // compute reflection vector r = 2 * ((n dot v)/(n dot n)) n - v
  59. // multiply all values through by N.N. uniformly scaling reflection vector won't affect result
  60. // since it is used in a cubemap lookup
  61. return (2.0*(dot( normal, eyeVector ))*normal) - (dot( normal, normal )*eyeVector);
  62. }
  63. float3 HuePreservingColorClamp( float3 c )
  64. {
  65. // Get the max of all of the color components and a specified maximum amount
  66. float maximum = max( max( c.x, c.y ), max( c.z, 1.0f ) );
  67. return (c / maximum);
  68. }
  69. HALF3 HuePreservingColorClamp( HALF3 c, HALF maxVal )
  70. {
  71. // Get the max of all of the color components and a specified maximum amount
  72. float maximum = max( max( c.x, c.y ), max( c.z, maxVal ) );
  73. return (c * ( maxVal / maximum ) );
  74. }
  75. #if (AA_CLAMP==1)
  76. HALF2 ComputeLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord )
  77. {
  78. HALF2 result = saturate(Lightmap1and2Coord.xy) * Lightmap1and2Coord.wz * 0.99;
  79. result += Lightmap3Coord;
  80. return result;
  81. }
  82. void ComputeBumpedLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord,
  83. out HALF2 bumpCoord1,
  84. out HALF2 bumpCoord2,
  85. out HALF2 bumpCoord3 )
  86. {
  87. HALF2 result = saturate(Lightmap1and2Coord.xy) * Lightmap1and2Coord.wz * 0.99;
  88. result += Lightmap3Coord;
  89. bumpCoord1 = result + HALF2(Lightmap1and2Coord.z, 0);
  90. bumpCoord2 = result + 2*HALF2(Lightmap1and2Coord.z, 0);
  91. bumpCoord3 = result + 3*HALF2(Lightmap1and2Coord.z, 0);
  92. }
  93. #else
  94. HALF2 ComputeLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord )
  95. {
  96. return Lightmap1and2Coord.xy;
  97. }
  98. void ComputeBumpedLightmapCoordinates( HALF4 Lightmap1and2Coord, HALF2 Lightmap3Coord,
  99. out HALF2 bumpCoord1,
  100. out HALF2 bumpCoord2,
  101. out HALF2 bumpCoord3 )
  102. {
  103. bumpCoord1 = Lightmap1and2Coord.xy;
  104. bumpCoord2 = Lightmap1and2Coord.wz; // reversed order!!!
  105. bumpCoord3 = Lightmap3Coord.xy;
  106. }
  107. #endif
  108. // Versions of matrix multiply functions which force HLSL compiler to explictly use DOTs,
  109. // not giving it the option of using MAD expansion. In a perfect world, the compiler would
  110. // always pick the best strategy, and these shouldn't be needed.. but.. well.. umm..
  111. //
  112. // lorenmcq
  113. float3 mul3x3(float3 v, float3x3 m)
  114. {
  115. #if !defined( _X360 )
  116. return float3(dot(v, transpose(m)[0]), dot(v, transpose(m)[1]), dot(v, transpose(m)[2]));
  117. #else
  118. // xbox360 fxc.exe (new back end) borks with transposes, generates bad code
  119. return mul( v, m );
  120. #endif
  121. }
  122. float3 mul4x3(float4 v, float4x3 m)
  123. {
  124. #if !defined( _X360 )
  125. return float3(dot(v, transpose(m)[0]), dot(v, transpose(m)[1]), dot(v, transpose(m)[2]));
  126. #else
  127. // xbox360 fxc.exe (new back end) borks with transposes, generates bad code
  128. return mul( v, m );
  129. #endif
  130. }
  131. float3 DecompressHDR( float4 input )
  132. {
  133. return input.rgb * input.a * MAX_HDR_OVERBRIGHT;
  134. }
  135. float4 CompressHDR( float3 input )
  136. {
  137. // FIXME: want to use min so that we clamp to white, but what happens if we
  138. // have an albedo component that's less than 1/MAX_HDR_OVERBRIGHT?
  139. // float fMax = max( max( color.r, color.g ), color.b );
  140. float4 output;
  141. float fMax = min( min( input.r, input.g ), input.b );
  142. if( fMax > 1.0f )
  143. {
  144. float oofMax = 1.0f / fMax;
  145. output.rgb = oofMax * input.rgb;
  146. output.a = min( fMax / MAX_HDR_OVERBRIGHT, 1.0f );
  147. }
  148. else
  149. {
  150. output.rgb = input.rgb;
  151. output.a = 0.0f;
  152. }
  153. return output;
  154. }
  155. float3 LinearToGamma( const float3 f3linear )
  156. {
  157. return pow( f3linear, 1.0f / 2.2f );
  158. }
  159. float4 LinearToGamma( const float4 f4linear )
  160. {
  161. return float4( pow( f4linear.xyz, 1.0f / 2.2f ), f4linear.w );
  162. }
  163. float LinearToGamma( const float f1linear )
  164. {
  165. return pow( f1linear, 1.0f / 2.2f );
  166. }
  167. float3 GammaToLinear( const float3 gamma )
  168. {
  169. return pow( gamma, 2.2f );
  170. }
  171. float4 GammaToLinear( const float4 gamma )
  172. {
  173. return float4( pow( gamma.xyz, 2.2f ), gamma.w );
  174. }
  175. float GammaToLinear( const float gamma )
  176. {
  177. return pow( gamma, 2.2f );
  178. }
  179. // These two functions use the actual sRGB math
  180. float SrgbGammaToLinear( float flSrgbGammaValue )
  181. {
  182. float x = saturate( flSrgbGammaValue );
  183. return ( x <= 0.04045f ) ? ( x / 12.92f ) : ( pow( ( x + 0.055f ) / 1.055f, 2.4f ) );
  184. }
  185. float SrgbLinearToGamma( float flLinearValue )
  186. {
  187. float x = saturate( flLinearValue );
  188. return ( x <= 0.0031308f ) ? ( x * 12.92f ) : ( 1.055f * pow( x, ( 1.0f / 2.4f ) ) ) - 0.055f;
  189. }
  190. // These twofunctions use the XBox 360's exact piecewise linear algorithm
  191. float X360GammaToLinear( float fl360GammaValue )
  192. {
  193. float flLinearValue;
  194. fl360GammaValue = saturate( fl360GammaValue );
  195. if ( fl360GammaValue < ( 96.0f / 255.0f ) )
  196. {
  197. if ( fl360GammaValue < ( 64.0f / 255.0f ) )
  198. {
  199. flLinearValue = fl360GammaValue * 255.0f;
  200. }
  201. else
  202. {
  203. flLinearValue = fl360GammaValue * ( 255.0f * 2.0f ) - 64.0f;
  204. flLinearValue += floor( flLinearValue * ( 1.0f / 512.0f ) );
  205. }
  206. }
  207. else
  208. {
  209. if( fl360GammaValue < ( 192.0f / 255.0f ) )
  210. {
  211. flLinearValue = fl360GammaValue * ( 255.0f * 4.0f ) - 256.0f;
  212. flLinearValue += floor( flLinearValue * ( 1.0f / 256.0f ) );
  213. }
  214. else
  215. {
  216. flLinearValue = fl360GammaValue * ( 255.0f * 8.0f ) - 1024.0f;
  217. flLinearValue += floor( flLinearValue * ( 1.0f / 128.0f ) );
  218. }
  219. }
  220. flLinearValue *= 1.0f / 1023.0f;
  221. flLinearValue = saturate( flLinearValue );
  222. return flLinearValue;
  223. }
  224. float X360LinearToGamma( float flLinearValue )
  225. {
  226. float fl360GammaValue;
  227. flLinearValue = saturate( flLinearValue );
  228. if ( flLinearValue < ( 128.0f / 1023.0f ) )
  229. {
  230. if ( flLinearValue < ( 64.0f / 1023.0f ) )
  231. {
  232. fl360GammaValue = flLinearValue * ( 1023.0f * ( 1.0f / 255.0f ) );
  233. }
  234. else
  235. {
  236. fl360GammaValue = flLinearValue * ( ( 1023.0f / 2.0f ) * ( 1.0f / 255.0f ) ) + ( 32.0f / 255.0f );
  237. }
  238. }
  239. else
  240. {
  241. if ( flLinearValue < ( 512.0f / 1023.0f ) )
  242. {
  243. fl360GammaValue = flLinearValue * ( ( 1023.0f / 4.0f ) * ( 1.0f / 255.0f ) ) + ( 64.0f / 255.0f );
  244. }
  245. else
  246. {
  247. fl360GammaValue = flLinearValue * ( ( 1023.0f /8.0f ) * ( 1.0f / 255.0f ) ) + ( 128.0f /255.0f ); // 1.0 -> 1.0034313725490196078431372549016
  248. if ( fl360GammaValue > 1.0f )
  249. {
  250. fl360GammaValue = 1.0f;
  251. }
  252. }
  253. }
  254. fl360GammaValue = saturate( fl360GammaValue );
  255. return fl360GammaValue;
  256. }
  257. float SrgbGammaTo360Gamma( float flSrgbGammaValue )
  258. {
  259. float flLinearValue = SrgbGammaToLinear( flSrgbGammaValue );
  260. float fl360GammaValue = X360LinearToGamma( flLinearValue );
  261. return fl360GammaValue;
  262. }
  263. float3 Vec3WorldToTangent( float3 iWorldVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal )
  264. {
  265. float3 vTangentVector;
  266. vTangentVector.x = dot( iWorldVector.xyz, iWorldTangent.xyz );
  267. vTangentVector.y = dot( iWorldVector.xyz, iWorldBinormal.xyz );
  268. vTangentVector.z = dot( iWorldVector.xyz, iWorldNormal.xyz );
  269. return vTangentVector.xyz; // Return without normalizing
  270. }
  271. float3 Vec3WorldToTangentNormalized( float3 iWorldVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal )
  272. {
  273. return normalize( Vec3WorldToTangent( iWorldVector, iWorldNormal, iWorldTangent, iWorldBinormal ) );
  274. }
  275. float3 Vec3TangentToWorld( float3 iTangentVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal )
  276. {
  277. float3 vWorldVector;
  278. vWorldVector.xyz = iTangentVector.x * iWorldTangent.xyz;
  279. vWorldVector.xyz += iTangentVector.y * iWorldBinormal.xyz;
  280. vWorldVector.xyz += iTangentVector.z * iWorldNormal.xyz;
  281. return vWorldVector.xyz; // Return without normalizing
  282. }
  283. float3 Vec3TangentToWorldNormalized( float3 iTangentVector, float3 iWorldNormal, float3 iWorldTangent, float3 iWorldBinormal )
  284. {
  285. return normalize( Vec3TangentToWorld( iTangentVector, iWorldNormal, iWorldTangent, iWorldBinormal ) );
  286. }
  287. #endif //#ifndef COMMON_FXC_H_