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.

210 lines
6.6 KiB

  1. // DYNAMIC: "DISTORT_TYPE" "0..2"
  2. #include "shader_constant_register_map.h"
  3. #include "common_ps_fxc.h"
  4. sampler BaseTextureSampler : register( s0 );
  5. // Faster, but less readable maths.
  6. #define OPTIMISED 1
  7. const float4 g_vWarpParms0 : register( c0 );
  8. #if OPTIMISED
  9. #define stereo_distortion_ScaleX g_vWarpParms0.x
  10. #define stereo_distortion_OffsetX g_vWarpParms0.y
  11. #define stereo_distortion_ScaleY g_vWarpParms0.z
  12. #define stereo_distortion_OffsetY g_vWarpParms0.w
  13. #else
  14. #define stereo_distortion_grow_outside g_vWarpParms0.x
  15. #define stereo_distortion_grow_inside g_vWarpParms0.y
  16. #define stereo_distortion_grow_above g_vWarpParms0.z
  17. #define stereo_distortion_grow_below g_vWarpParms0.w
  18. #endif
  19. const float4 g_vWarpParms1 : register( c1 );
  20. #define distortion_l_centre g_vWarpParms1.xy
  21. #define distortion_r_centre g_vWarpParms1.zw
  22. const float4 g_vWarpParms2 : register( c2 );
  23. #define distortion_l_coeff0 g_vWarpParms2.x
  24. #define distortion_l_coeff1 g_vWarpParms2.y
  25. #define distortion_l_coeff2 g_vWarpParms2.z
  26. #define distortion_red_coeff0delta g_vWarpParms2.w
  27. const float4 g_vWarpParms3 : register( c3 );
  28. #define distortion_r_coeff0 g_vWarpParms3.x
  29. #define distortion_r_coeff1 g_vWarpParms3.y
  30. #define distortion_r_coeff2 g_vWarpParms3.z
  31. #define distortion_blue_coeff0delta g_vWarpParms3.w
  32. const float4 g_vWarpParms4 : register( c4 );
  33. #define aspect_height_over_width_t2 g_vWarpParms4.x
  34. struct PS_INPUT
  35. {
  36. float2 vBaseTexCoord : TEXCOORD0;
  37. };
  38. float4 main( PS_INPUT i ) : COLOR
  39. {
  40. float2 vOriginal = i.vBaseTexCoord.xy;
  41. float BaseX;
  42. float2 centre;
  43. float dcoeff0;
  44. float dcoeff1;
  45. float dcoeff2;
  46. #if OPTIMISED
  47. float stereo_distortion_OffsetX_Corrected;
  48. #else
  49. float stereo_distortion_grow_left;
  50. float stereo_distortion_grow_right;
  51. #endif
  52. if ( vOriginal.x < 0.5 )
  53. {
  54. BaseX = 0.25;
  55. #if OPTIMISED
  56. stereo_distortion_OffsetX_Corrected = stereo_distortion_OffsetX;
  57. #else
  58. stereo_distortion_grow_left = stereo_distortion_grow_outside;
  59. stereo_distortion_grow_right = stereo_distortion_grow_inside;
  60. #endif
  61. centre = distortion_l_centre;
  62. dcoeff0 = distortion_l_coeff0;
  63. dcoeff1 = distortion_l_coeff1;
  64. dcoeff2 = distortion_l_coeff2;
  65. }
  66. else
  67. {
  68. BaseX = 0.75;
  69. #if OPTIMISED
  70. stereo_distortion_OffsetX_Corrected = -stereo_distortion_OffsetX;
  71. #else
  72. stereo_distortion_grow_left = stereo_distortion_grow_inside;
  73. stereo_distortion_grow_right = stereo_distortion_grow_outside;
  74. #endif
  75. centre = distortion_r_centre;
  76. dcoeff0 = distortion_r_coeff0;
  77. dcoeff1 = distortion_r_coeff1;
  78. dcoeff2 = distortion_r_coeff2;
  79. }
  80. float fLocalAspectHeightOverWidthTimes2 = aspect_height_over_width_t2;
  81. float2 Delta;
  82. Delta.x = ( vOriginal.x - BaseX ) * 4.0;
  83. Delta.y = ( vOriginal.y - 0.5 ) * fLocalAspectHeightOverWidthTimes2;
  84. // Delta now runs from -1.0 to +1.0, i.e. NDC, of the right/left destination (i.e. left/right half of the rendertarget).
  85. // Vertically, it has the same scale in pixels as horizontally, but because the aspect ratio is usually not 1:1, the range may be larger or smaller than [-1,+1]
  86. // Offset by the calibration center.
  87. Delta -= centre;
  88. float r2 = Delta.x * Delta.x + Delta.y * Delta.y;
  89. // case DISTORT_DPOLY3:
  90. // {
  91. // T rdistortion = T(1.0) / (T(1.0) + r2 * (T(dcoeff[0]) + r2 * (T(dcoeff[1]) + r2 * T(dcoeff[2]))));
  92. // xp = xp*rdistortion;
  93. // yp = yp*rdistortion;
  94. // }
  95. // break;
  96. float rdistortion_r = 1.0;
  97. float rdistortion_g = 1.0;
  98. float rdistortion_b = 1.0;
  99. #if ( DISTORT_TYPE == 1 )
  100. {
  101. rdistortion_r = 1.0 / (1.0 + r2 * ((dcoeff0+distortion_red_coeff0delta) + r2 * (dcoeff1 + r2 * dcoeff2)));
  102. rdistortion_g = 1.0 / (1.0 + r2 * ( dcoeff0 + r2 * (dcoeff1 + r2 * dcoeff2)));
  103. rdistortion_b = 1.0 / (1.0 + r2 * ((dcoeff0+distortion_blue_coeff0delta) + r2 * (dcoeff1 + r2 * dcoeff2)));
  104. }
  105. #elif ( DISTORT_TYPE == 2 )
  106. {
  107. rdistortion_r = (1.0 + r2 * ((dcoeff0+distortion_red_coeff0delta) + r2 * (dcoeff1 + r2 * dcoeff2)));
  108. rdistortion_g = (1.0 + r2 * ( dcoeff0 + r2 * (dcoeff1 + r2 * dcoeff2)));
  109. rdistortion_b = (1.0 + r2 * ((dcoeff0+distortion_blue_coeff0delta) + r2 * (dcoeff1 + r2 * dcoeff2)));
  110. }
  111. #endif
  112. float2 DeltaR = Delta * rdistortion_r;
  113. float2 DeltaG = Delta * rdistortion_g;
  114. float2 DeltaB = Delta * rdistortion_b;
  115. // Offset back from the calibration center.
  116. DeltaR += centre;
  117. DeltaG += centre;
  118. DeltaB += centre;
  119. float inv_aspect = 2.0 / fLocalAspectHeightOverWidthTimes2;
  120. #if OPTIMISED
  121. float stereo_distortion_ScaleY_corrected = stereo_distortion_ScaleY * inv_aspect;
  122. DeltaR.x = DeltaR.x * stereo_distortion_ScaleX + stereo_distortion_OffsetX_Corrected;
  123. DeltaR.y = DeltaR.y * stereo_distortion_ScaleY_corrected + stereo_distortion_OffsetY;
  124. DeltaG.x = DeltaG.x * stereo_distortion_ScaleX + stereo_distortion_OffsetX_Corrected;
  125. DeltaG.y = DeltaG.y * stereo_distortion_ScaleY_corrected + stereo_distortion_OffsetY;
  126. DeltaB.x = DeltaB.x * stereo_distortion_ScaleX + stereo_distortion_OffsetX_Corrected;
  127. DeltaB.y = DeltaB.y * stereo_distortion_ScaleY_corrected + stereo_distortion_OffsetY;
  128. #else
  129. // This is now in NDC of the left/right half of the source, if there was no distortion growth.
  130. // So now include the growth.
  131. float ScaleX = 2.0f / ( stereo_distortion_grow_left + stereo_distortion_grow_right + 2.0f );
  132. float ScaleY = 2.0f / ( stereo_distortion_grow_above + stereo_distortion_grow_below + 2.0f );
  133. float OffsetX = ( stereo_distortion_grow_left - stereo_distortion_grow_right ) * ScaleX * 0.5;
  134. float OffsetY = ( stereo_distortion_grow_above - stereo_distortion_grow_below ) * ScaleY * 0.5;
  135. ScaleY *= inv_aspect;
  136. DeltaR.x = DeltaR.x * ScaleX + OffsetX;
  137. DeltaR.y = DeltaR.y * ScaleY + OffsetY;
  138. DeltaG.x = DeltaG.x * ScaleX + OffsetX;
  139. DeltaG.y = DeltaG.y * ScaleY + OffsetY;
  140. DeltaB.x = DeltaB.x * ScaleX + OffsetX;
  141. DeltaB.y = DeltaB.y * ScaleY + OffsetY;
  142. #endif
  143. // Now convert back to useful texcoords.
  144. float2 PixPosR, PixPosG, PixPosB;
  145. PixPosR.x = DeltaR.x * 0.25 + BaseX;
  146. PixPosR.y = DeltaR.y * 0.5 + 0.5;
  147. PixPosG.x = DeltaG.x * 0.25 + BaseX;
  148. PixPosG.y = DeltaG.y * 0.5 + 0.5;
  149. PixPosB.x = DeltaB.x * 0.25 + BaseX;
  150. PixPosB.y = DeltaB.y * 0.5 + 0.5;
  151. float4 vFinal = 0.0;
  152. if ( ( DeltaG.x > -1.0 ) && ( DeltaG.y > -1.0 ) && ( DeltaG.x < 1.0 ) && ( DeltaG.y < 1.0 ) )
  153. {
  154. vFinal.r = tex2D( BaseTextureSampler, PixPosR ).r;
  155. vFinal.g = tex2D( BaseTextureSampler, PixPosG ).g;
  156. vFinal.b = tex2D( BaseTextureSampler, PixPosB ).b;
  157. }
  158. #if 0 // useful for checking where the center of distortion is.
  159. if ( ( r2 > 0.45*0.45 ) && ( r2 < 0.55*0.55 ) )
  160. {
  161. vFinal.g = 0.0;
  162. }
  163. #endif
  164. return vFinal;
  165. }