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.

347 lines
9.4 KiB

  1. // STATIC: "ZOOM_ANIMATE_SEQ2" "0..1" [vs20]
  2. // STATIC: "DUALSEQUENCE" "0..1" [vs20]
  3. // STATIC: "EXTRACTGREENALPHA" "0..1" [vs20]
  4. // STATIC: "ZOOM_ANIMATE_SEQ2" "0..0" [vs11]
  5. // STATIC: "DUALSEQUENCE" "0..0" [vs11]
  6. // STATIC: "EXTRACTGREENALPHA" "0..0" [vs11]
  7. // STATIC: "USE_INSTANCING" "0..1" [vs20]
  8. // DYNAMIC: "ORIENTATION" "0..2"
  9. #include "common_vs_fxc.h"
  10. const float4x3 cModelView : register(SHADER_SPECIFIC_CONST_0);
  11. const float4x4 cProj : register(SHADER_SPECIFIC_CONST_3);
  12. #if ZOOM_ANIMATE_SEQ2
  13. const float4 ScaleParms : register(SHADER_SPECIFIC_CONST_7);
  14. #define OLDFRM_SCALE_START (ScaleParms.x)
  15. #define OLDFRM_SCALE_END (ScaleParms.y)
  16. #endif
  17. const float4 SizeParms : register(SHADER_SPECIFIC_CONST_8);
  18. const float4 SizeParms2 : register(SHADER_SPECIFIC_CONST_9);
  19. const float4 ViewportTransformScaled : register(SHADER_SPECIFIC_CONST_10);
  20. #define MINIMUM_SIZE_FACTOR (SizeParms.x)
  21. #define MAXIMUM_SIZE_FACTOR (SizeParms.y)
  22. #define START_FADE_SIZE_FACTOR (SizeParms.z)
  23. #define END_FADE_SIZE_FACTOR (SizeParms.w)
  24. // alpha fade w/ distance
  25. #define START_FAR_FADE ( SizeParms2.x )
  26. #define FAR_FADE_FACTOR ( SizeParms2.y ) // alpha = 1-min(1,max(0, (dist-start_fade)*factor))
  27. // Define stuff for instancing on 360
  28. #if ( defined( _X360 ) && defined( SHADER_MODEL_VS_2_0 ) )
  29. #define CONST_PC
  30. #define VERTEX_INDEX_PARAM_360 ,int Index:INDEX
  31. #define DO_INSTANCING 1
  32. #else
  33. #define CONST_PC const
  34. #define VERTEX_INDEX_PARAM_360
  35. #endif
  36. struct VS_INPUT
  37. {
  38. // This is all of the stuff that we ever use.
  39. float4 vTint : COLOR;
  40. float4 vPos : POSITION;
  41. float4 vTexCoord0 : TEXCOORD0;
  42. float4 vTexCoord1 : TEXCOORD1;
  43. float4 vParms : TEXCOORD2; // frame blend, rot, radius, yaw
  44. // FIXME: remove this vertex element for (USE_INSTANCING == 1), need to shuffle the following elements down
  45. float2 vCornerID : TEXCOORD3; // 0,0 1,0 1,1 0,1
  46. float4 vTexCoord2 : TEXCOORD4;
  47. #if DUALSEQUENCE
  48. float4 vSeq2TexCoord0 : TEXCOORD5;
  49. float4 vSeq2TexCoord1 : TEXCOORD6;
  50. float4 vParms1 : TEXCOORD7; // second frame blend, ?,?,?
  51. #endif
  52. };
  53. struct VS_OUTPUT
  54. {
  55. float4 projPos : POSITION;
  56. float2 texCoord0 : TEXCOORD0;
  57. float2 texCoord1 : TEXCOORD1;
  58. float4 argbcolor : COLOR;
  59. float4 blendfactor0 : TEXCOORD2;
  60. float2 texCoord2 : TEXCOORD3;
  61. #if !defined( SHADER_MODEL_VS_1_1 )
  62. float4 blendfactor1 : TEXCOORD4; // for extracting green/alpha
  63. #endif
  64. #if DUALSEQUENCE
  65. float2 vSeq2TexCoord0 : TEXCOORD5;
  66. float2 vSeq2TexCoord1 : TEXCOORD6;
  67. #endif
  68. #if defined( _X360 )
  69. float4 vScreenPos_ReverseZ : TEXCOORD7;
  70. #else
  71. float4 vScreenPos : TEXCOORD7;
  72. #endif
  73. };
  74. #define BLENDFACTOR v.vParms.x
  75. #define ROTATION v.vParms.y
  76. #define RADIUS v.vParms.z
  77. #define YAW (v.vParms.w)
  78. #if ( ZOOM_ANIMATE_SEQ2 )
  79. float getlerpscaled( float l_in, float s0, float s1, float ts )
  80. {
  81. l_in = 2.0*(l_in-.5);
  82. l_in *= lerp(s0,s1,ts);
  83. return 0.5+0.5*l_in;
  84. }
  85. float getlerpscale_for_old_frame( float l_in, float ts )
  86. {
  87. return getlerpscaled( l_in, OLDFRM_SCALE_START, OLDFRM_SCALE_END, ts);
  88. }
  89. float getlerpscale_for_new_frame( float l_in, float ts )
  90. {
  91. return getlerpscaled( l_in, 1.0, OLDFRM_SCALE_START, ts );
  92. }
  93. #endif // ZOOM_ANIMATE_SEQ2
  94. #ifdef DO_INSTANCING
  95. void InstancedVertexRead( inout VS_INPUT v, int index )
  96. {
  97. // Duplicate each VB vertex 4 times (and generate vCornerID - the only thing that varies per-corner)
  98. float4 vTint;
  99. float4 vPos;
  100. float4 vTexCoord0;
  101. float4 vTexCoord1;
  102. float4 vParms;
  103. float4 vTexCoord2;
  104. float4 vSeq_TexCoord0; // NOTE: April XDK compiler barfs on var names which have a number in the middle! (i.e. vSeq2TexCoord0)
  105. float4 vSeq_TexCoord1;
  106. float4 vParms1;
  107. int spriteIndex = index / 4;
  108. int cornerIndex = index - 4*spriteIndex;
  109. asm
  110. {
  111. vfetch vTint, spriteIndex, color0;
  112. vfetch vPos, spriteIndex, position0;
  113. vfetch vTexCoord0, spriteIndex, texcoord0;
  114. vfetch vTexCoord1, spriteIndex, texcoord1;
  115. vfetch vParms, spriteIndex, texcoord2;
  116. vfetch vTexCoord2, spriteIndex, texcoord4;
  117. #if DUALSEQUENCE
  118. vfetch vSeq_TexCoord0, spriteIndex, texcoord5;
  119. vfetch vSeq_TexCoord1, spriteIndex, texcoord6;
  120. vfetch vParms1, spriteIndex, texcoord7;
  121. #endif
  122. };
  123. v.vTint = vTint;
  124. v.vPos = vPos;
  125. v.vTexCoord0 = vTexCoord0;
  126. v.vTexCoord1 = vTexCoord1;
  127. v.vParms = vParms;
  128. v.vTexCoord2 = vTexCoord2;
  129. #if DUALSEQUENCE
  130. v.vSeq2TexCoord0 = vSeq_TexCoord0;
  131. v.vSeq2TexCoord1 = vSeq_TexCoord1;
  132. v.vParms1 = vParms1;
  133. #endif
  134. // Compute vCornerID - order is: (0,0) (1,0) (1,1) (0,1)
  135. // float2 IDs[4] = { {0,0}, {1,0}, {1,1}, {0,1} };
  136. // v.vCornerID.xy = IDs[ cornerIndex ];
  137. // This compiles to 2 ops on 360 (MADDs with abs/sat register read/write modifiers):
  138. v.vCornerID.xy = float2( 1.5f, 0.0f ) + cornerIndex*float2( -1.0f, 1.0f );
  139. v.vCornerID.xy = saturate( float2(1.5f, -3.0f) + float2( -1.0f, 2.0f )*abs( v.vCornerID.xy ) );
  140. }
  141. #endif
  142. VS_OUTPUT main( CONST_PC VS_INPUT v
  143. VERTEX_INDEX_PARAM_360 )
  144. {
  145. VS_OUTPUT o;
  146. #ifdef DO_INSTANCING
  147. if ( USE_INSTANCING )
  148. {
  149. InstancedVertexRead( v, Index );
  150. }
  151. #endif
  152. #if SHADER_MODEL_VS_1_1
  153. float4 tint = v.vTint;
  154. #else
  155. float4 tint = GammaToLinear( v.vTint );
  156. #endif
  157. float2 sc_yaw;
  158. sincos( YAW, sc_yaw.y, sc_yaw.x );
  159. float2 sc;
  160. sincos( ROTATION, sc.y, sc.x );
  161. float2 ix=2*v.vCornerID.xy-1;
  162. float x1=dot(ix,sc);
  163. float y1=sc.x*ix.y-sc.y*ix.x;
  164. float4 projPos;
  165. float3 worldPos;
  166. worldPos = mul4x3( v.vPos, cModel[0] );
  167. float rad = RADIUS;
  168. float3 v2p = ( worldPos - cEyePos );
  169. float l = length(v2p);
  170. rad=max(rad, MINIMUM_SIZE_FACTOR * l);
  171. // now, perform fade out
  172. #ifndef SHADER_MODEL_VS_1_1
  173. if ( rad > START_FADE_SIZE_FACTOR * l )
  174. {
  175. if ( rad > END_FADE_SIZE_FACTOR *l )
  176. {
  177. tint = 0;
  178. rad = 0; // cull so we emit 0-sized sprite
  179. }
  180. else
  181. {
  182. tint *= 1-(rad-START_FADE_SIZE_FACTOR*l)/(END_FADE_SIZE_FACTOR*l-START_FADE_SIZE_FACTOR*l);
  183. }
  184. }
  185. #endif
  186. #ifndef SHADER_MODEL_VS_1_1
  187. // perform far fade
  188. float tscale = 1-min(1, max(0, (l-START_FAR_FADE)*FAR_FADE_FACTOR) );
  189. tint *= tscale;
  190. if ( tscale <= 0)
  191. rad = 0; // cull so we emit 0-sized sprite
  192. #endif
  193. rad=min(rad, MAXIMUM_SIZE_FACTOR * l);
  194. #if ORIENTATION == 0
  195. // Screen-aligned case
  196. float3 viewPos;
  197. viewPos = mul4x3( v.vPos, cModelView );
  198. float3 disp=float3( -x1,y1,0);
  199. float tmpx=disp.x*sc_yaw.x+disp.z*sc_yaw.y;
  200. disp.z = disp.z*sc_yaw.x-disp.x*sc_yaw.y;
  201. disp.x=tmpx;
  202. viewPos.xyz += disp * rad;
  203. projPos = mul( float4(viewPos, 1.0f), cProj );
  204. #endif
  205. #if ORIENTATION == 1
  206. // Z-aligned case
  207. if (l > rad/2)
  208. {
  209. float3 up = float3(0,0,1);
  210. float3 right = normalize(cross(up, v2p));
  211. float tmpx=right.x*sc_yaw.x+right.y*sc_yaw.y;
  212. right.y = right.y*sc_yaw.x-right.x*sc_yaw.y;
  213. right.x=tmpx;
  214. worldPos += (x1*rad)*right;
  215. worldPos.z += (y1*rad)*up.z;
  216. #ifndef SHADER_MODEL_VS_1_1
  217. if (l < rad*2 )
  218. {
  219. tint *= smoothstep(rad/2,rad,l);
  220. }
  221. #endif
  222. }
  223. projPos = mul( float4(worldPos, 1.0f), cViewProj );
  224. #endif
  225. #if ORIENTATION == 2
  226. // aligned with z plane case - easy
  227. float3 wpos=v.vPos+RADIUS*float3( y1,x1,0);
  228. projPos = mul( float4(wpos, 1.0f), cModelViewProj );
  229. #endif
  230. o.blendfactor0 = float4( v.vParms.x, 0, 0, 0 );
  231. o.projPos = projPos;
  232. o.texCoord0.x = lerp( v.vTexCoord0.z, v.vTexCoord0.x, v.vCornerID.x );
  233. o.texCoord0.y = lerp( v.vTexCoord0.w, v.vTexCoord0.y, v.vCornerID.y );
  234. o.texCoord1.x = lerp( v.vTexCoord1.z, v.vTexCoord1.x, v.vCornerID.x );
  235. o.texCoord1.y = lerp( v.vTexCoord1.w, v.vTexCoord1.y, v.vCornerID.y );
  236. o.texCoord2.x = lerp( v.vTexCoord2.z, v.vTexCoord2.x, v.vCornerID.x );
  237. o.texCoord2.y = lerp( v.vTexCoord2.w, v.vTexCoord2.y, v.vCornerID.y );
  238. #if ( DUALSEQUENCE )
  239. float2 lerpold = v.vCornerID.xy;
  240. float2 lerpnew = v.vCornerID.xy;
  241. #if ( ZOOM_ANIMATE_SEQ2 )
  242. lerpold.x = getlerpscale_for_old_frame( v.vCornerID.x, v.vParms1.x );
  243. lerpold.y = getlerpscale_for_old_frame( v.vCornerID.y, v.vParms1.x );
  244. lerpnew.x = getlerpscale_for_new_frame( v.vCornerID.x, v.vParms1.x );
  245. lerpnew.y = getlerpscale_for_new_frame( v.vCornerID.y, v.vParms1.x );
  246. #endif
  247. o.vSeq2TexCoord0.xy = lerp( v.vSeq2TexCoord0.zw, v.vSeq2TexCoord0.xy, lerpold.xy );
  248. o.vSeq2TexCoord1.xy = lerp( v.vSeq2TexCoord1.zw, v.vSeq2TexCoord1.xy, lerpnew.xy );
  249. o.blendfactor0.z = v.vParms1.x;
  250. #endif
  251. #if !defined( SHADER_MODEL_VS_1_1 )
  252. o.blendfactor1 = float4( 0.0f, 0.0f, 0.0f, 0.0f );
  253. #if ( EXTRACTGREENALPHA )
  254. // Input range Output range
  255. if ( v.vParms.x < 0.25f ) // 0.0 .. 0.25
  256. {
  257. o.blendfactor0.a = v.vParms.x * 2 + 0.5f; // 0.5 .. 1.0
  258. o.blendfactor0.g = 1 - o.blendfactor0.a; // 0.5 .. 0.0
  259. }
  260. else if ( v.vParms.x < 0.75f ) // 0.25 .. 0.75
  261. {
  262. o.blendfactor1.g = v.vParms.x * 2 - 0.5f; // 0.0 .. 1.0
  263. o.blendfactor0.a = 1 - o.blendfactor1.g; // 1.0 .. 0.0
  264. }
  265. else // 0.75 .. 1.0
  266. {
  267. o.blendfactor1.a = v.vParms.x * 2 - 1.5f; // 0.0 .. 0.5
  268. o.blendfactor1.g = 1 - o.blendfactor1.a; // 1.0 .. 0.5
  269. }
  270. #endif
  271. #endif
  272. // Map projected position to the refraction texture
  273. float2 vScreenPos;
  274. vScreenPos.x = projPos.x;
  275. vScreenPos.y = -projPos.y; // invert Y
  276. vScreenPos = (vScreenPos + projPos.w) * 0.5f;
  277. // Need to also account for the viewport transform, which matters when rendering with mat_viewportscale != 1.0
  278. vScreenPos = (vScreenPos * ViewportTransformScaled.xy) + (projPos.w * ViewportTransformScaled.zw);
  279. #if defined( _X360 )
  280. o.vScreenPos_ReverseZ = float4(vScreenPos.x, vScreenPos.y, projPos.w - projPos.z, projPos.w );
  281. #else
  282. o.vScreenPos = float4(vScreenPos.x, vScreenPos.y, projPos.z, projPos.w );
  283. #endif
  284. o.argbcolor = tint;
  285. return o;
  286. }