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.

495 lines
14 KiB

  1. // STATIC: "ZOOM_ANIMATE_SEQ2" "0..1"
  2. // STATIC: "DUALSEQUENCE" "0..1"
  3. // STATIC: "ADDBASETEXTURE2" "0..1"
  4. // STATIC: "EXTRACTGREENALPHA" "0..1"
  5. // STATIC: "DEPTHBLEND" "0..1" [CONSOLE]
  6. // STATIC: "DEPTHBLEND" "0..1" [PC]
  7. // STATIC: "ANIMBLEND_OR_MAXLUMFRAMEBLEND1" "0..1"
  8. // STATIC: "CROP" "0..1"
  9. // STATIC: "PACKED_INTERPOLATOR" "0..1"
  10. // STATIC: "SPRITECARDVERTEXFOG" "0..1"
  11. // STATIC: "HARDWAREFOGBLEND" "0..0" [CONSOLE]
  12. // STATIC: "HARDWAREFOGBLEND" "0..1" [PC] [vs20]
  13. // STATIC: "HARDWAREFOGBLEND" "0..0" [PC] [vs30]
  14. // STATIC: "PERPARTICLEOUTLINE" "0..1"
  15. // DYNAMIC: "ORIENTATION" "0..4"
  16. // If we aren't doing any sort of fog, then assume that HARDWAREFOGBLEND is forced to zero.
  17. // SKIP: $PERPARTICLEOUTLINE && ( $ORIENTATION == 3 )
  18. // SKIP: $DUALSEQUENCE && ( $PERPARTICLEOUTLINE || ( $ORIENTATION == 3 ) )
  19. // SKIP: $HARDWAREFOGBLEND && !SPRITECARDVERTEXFOG
  20. #include "common_vs_fxc.h"
  21. // Don't want to have extra combos, so define these two to be the same base on a single combo. Bilch.
  22. #define ANIMBLEND ANIMBLEND_OR_MAXLUMFRAMEBLEND1
  23. #define MAXLUMFRAMEBLEND1 ANIMBLEND_OR_MAXLUMFRAMEBLEND1
  24. // VS_OUTPUT in a common file.
  25. #include "common_spritecard_fxc.h"
  26. const hlsl_float4x3 cModelView : register(SHADER_SPECIFIC_CONST_0);
  27. const float4x4 cProj : register(SHADER_SPECIFIC_CONST_3);
  28. #if ( ZOOM_ANIMATE_SEQ2 || SPRITECARDVERTEXFOG )
  29. const float4 ScaleParms : register(SHADER_SPECIFIC_CONST_7);
  30. #define OLDFRM_SCALE_START (ScaleParms.x)
  31. #define OLDFRM_SCALE_END (ScaleParms.y)
  32. #define FOG_SCALE_FACTOR (ScaleParms.z)
  33. #endif
  34. const float4 SizeParms : register(SHADER_SPECIFIC_CONST_8);
  35. const float4 SizeParms2 : register(SHADER_SPECIFIC_CONST_9);
  36. const float4 g_vCropFactor : register(SHADER_SPECIFIC_CONST_11);
  37. const float4 g_vDepthFeatherProjToViewZW[ 2 ] : register( SHADER_SPECIFIC_CONST_12 );
  38. #if !defined( SHADER_MODEL_VS_1_1 )
  39. const bool g_bUseInstancing : register( SHADER_SPECIFIC_BOOL_CONST_0 );
  40. #endif
  41. #if 0 // JasonM - do we want control flow? - note that we moved these slightly
  42. const bool g_bZoomAnimateSeq2 : register( SHADER_SPECIFIC_BOOL_CONST_1 );
  43. const bool g_bExtractGreenAlpha : register( SHADER_SPECIFIC_BOOL_CONST_2 );
  44. #endif
  45. #define MINIMUM_SIZE_FACTOR (SizeParms.x)
  46. #define MAXIMUM_SIZE_FACTOR (SizeParms.y)
  47. #define START_FADE_SIZE_FACTOR (SizeParms.z)
  48. #define END_FADE_SIZE_FACTOR (SizeParms.w)
  49. // alpha fade w/ distance
  50. #define START_FAR_FADE ( SizeParms2.x )
  51. #define FAR_FADE_FACTOR ( SizeParms2.y ) // alpha = 1-min(1,max(0, (dist-start_fade)*factor))
  52. // Define stuff for instancing on 360
  53. #if ( defined( _X360 ) && defined( SHADER_MODEL_VS_2_0 ) )
  54. #define CONST_PC
  55. #define VERTEX_INDEX_PARAM_360 ,int Index:INDEX
  56. #define DO_INSTANCING 1
  57. #else
  58. #define CONST_PC const
  59. #define VERTEX_INDEX_PARAM_360
  60. #endif
  61. struct VS_INPUT
  62. {
  63. // This is all of the stuff that we ever use.
  64. float4 vTint : COLOR;
  65. float4 vPos : POSITION;
  66. float4 vTexCoord0 : TEXCOORD0;
  67. float4 vTexCoord1 : TEXCOORD1;
  68. float4 vParms : TEXCOORD2; // frame blend, rot, radius, yaw
  69. // FIXME: remove this vertex element for (USE_INSTANCING == 1), need to shuffle the following elements down
  70. float2 vCornerID : TEXCOORD3; // 0,0 1,0 1,1 0,1
  71. float4 vTexCoord2 : TEXCOORD4;
  72. #if DUALSEQUENCE
  73. float4 vSeq2TexCoord0 : TEXCOORD5;
  74. float4 vSeq2TexCoord1 : TEXCOORD6;
  75. float4 vParms1 : TEXCOORD7; // second frame blend, ?,?,?
  76. #endif
  77. #if PERPARTICLEOUTLINE
  78. float4 vecOutlineTint : TEXCOORD5;
  79. #endif
  80. #if ( ORIENTATION == 3 ) // orient to normal
  81. float4 vecNormal : TEXCOORD5;
  82. #endif
  83. };
  84. #define BLENDFACTOR v.vParms.x
  85. #define ROTATION v.vParms.y
  86. #define RADIUS v.vParms.z
  87. #define YAW (v.vParms.w)
  88. #define ONE_OVER_255 0.00392156863
  89. #if ( ZOOM_ANIMATE_SEQ2 )
  90. float getlerpscaled( float l_in, float s0, float s1, float ts )
  91. {
  92. l_in = 2.0*(l_in-.5);
  93. l_in *= lerp(s0,s1,ts);
  94. return 0.5+0.5*l_in;
  95. }
  96. float getlerpscale_for_old_frame( float l_in, float ts )
  97. {
  98. return getlerpscaled( l_in, OLDFRM_SCALE_START, OLDFRM_SCALE_END, ts);
  99. }
  100. float getlerpscale_for_new_frame( float l_in, float ts )
  101. {
  102. return getlerpscaled( l_in, 1.0, OLDFRM_SCALE_START, ts );
  103. }
  104. #endif // ZOOM_ANIMATE_SEQ2
  105. #ifdef DO_INSTANCING
  106. void InstancedVertexRead( inout VS_INPUT v, int index )
  107. {
  108. // Duplicate each VB vertex 4 times (and generate vCornerID - the only thing that varies per-corner)
  109. float4 vTint;
  110. float4 vPos;
  111. float4 vTexCoord0;
  112. float4 vTexCoord1;
  113. float4 vParms;
  114. float4 vTexCoord2;
  115. float4 vSeq_TexCoord0; // NOTE: April XDK compiler barfs on var names which have a number in the middle! (i.e. vSeq2TexCoord0)
  116. float4 vSeq_TexCoord1;
  117. float4 vParms1;
  118. float4 vecOutlineTint;
  119. float4 vecNormal;
  120. int spriteIndex = index / 4;
  121. int cornerIndex = index - 4*spriteIndex;
  122. asm
  123. {
  124. // NOTE: using a computed index disables the post-transform cache, so there are VS perf ramifications
  125. vfetch vTint, spriteIndex, color0;
  126. vfetch vPos, spriteIndex, position0;
  127. vfetch vTexCoord0, spriteIndex, texcoord0;
  128. vfetch vTexCoord1, spriteIndex, texcoord1;
  129. vfetch vParms, spriteIndex, texcoord2;
  130. vfetch vTexCoord2, spriteIndex, texcoord4;
  131. #if DUALSEQUENCE
  132. vfetch vSeq_TexCoord0, spriteIndex, texcoord5;
  133. vfetch vSeq_TexCoord1, spriteIndex, texcoord6;
  134. vfetch vParms1, spriteIndex, texcoord7;
  135. #endif
  136. #if PERPARTICLEOUTLINE
  137. vfetch vecOutlineTint, spriteIndex, texcoord5;
  138. #endif
  139. #if ( ORIENTATION == 3 ) // normal-aligned
  140. vfetch vecNormal, spriteIndex, texcoord5;
  141. #endif
  142. };
  143. v.vTint = vTint;
  144. v.vPos = vPos;
  145. v.vTexCoord0 = vTexCoord0;
  146. v.vTexCoord1 = vTexCoord1;
  147. v.vParms = vParms;
  148. #if ADDBASETEXTURE2
  149. v.vTexCoord2 = vTexCoord2;
  150. #endif
  151. #if DUALSEQUENCE
  152. v.vSeq2TexCoord0 = vSeq_TexCoord0;
  153. v.vSeq2TexCoord1 = vSeq_TexCoord1;
  154. v.vParms1 = vParms1;
  155. #endif
  156. #if PERPARTICLEOUTLINE
  157. v.vecOutlineTint = vecOutlineTint;
  158. #endif
  159. #if ORIENTATION == 3
  160. v.vecNormal = vecNormal;
  161. #endif
  162. // Compute vCornerID - order is: (0,0) (1,0) (1,1) (0,1)
  163. // float2 IDs[4] = { {0,0}, {1,0}, {1,1}, {0,1} };
  164. // v.vCornerID.xy = IDs[ cornerIndex ];
  165. // This compiles to 2 ops on 360 (MADDs with abs/sat register read/write modifiers):
  166. v.vCornerID.xy = float2( 1.5f, 0.0f ) + cornerIndex*float2( -1.0f, 1.0f );
  167. v.vCornerID.xy = saturate( float2(1.5f, -3.0f) + float2( -1.0f, 2.0f )*abs( v.vCornerID.xy ) );
  168. }
  169. #endif
  170. VS_OUTPUT main( CONST_PC VS_INPUT v
  171. VERTEX_INDEX_PARAM_360 )
  172. {
  173. VS_OUTPUT o;
  174. #ifdef DO_INSTANCING
  175. if ( g_bUseInstancing )
  176. {
  177. InstancedVertexRead( v, Index );
  178. }
  179. #endif
  180. #if ( !DUALSEQUENCE )
  181. {
  182. #if ( PERPARTICLEOUTLINE )
  183. {
  184. o.vecOutlineTint = GammaToLinear( v.vecOutlineTint );
  185. }
  186. #else
  187. {
  188. o.vecOutlineTint = 1;
  189. }
  190. #endif
  191. }
  192. #endif
  193. #if SHADER_MODEL_VS_1_1
  194. float4 tint = v.vTint;
  195. #else
  196. float4 tint = GammaToLinear( v.vTint );
  197. #endif
  198. float2 sc_yaw;
  199. sincos( YAW, sc_yaw.y, sc_yaw.x );
  200. float2 sc;
  201. sincos( ROTATION, sc.y, sc.x );
  202. float2 ix = 2 * v.vCornerID.xy - 1;
  203. #if ( CROP )
  204. {
  205. ix *= g_vCropFactor.xy;
  206. }
  207. #endif
  208. float x1 = dot( ix, sc );
  209. float y1 = sc.x * ix.y - sc.y * ix.x;
  210. float4 projPos;
  211. float3 worldPos;
  212. worldPos = mul4x3( v.vPos, cModel[0] );
  213. float rad = RADIUS;
  214. float3 v2p = ( worldPos - cEyePos );
  215. float l = length(v2p);
  216. rad=max(rad, MINIMUM_SIZE_FACTOR * l);
  217. // now, perform fade out
  218. #ifndef SHADER_MODEL_VS_1_1
  219. if ( rad > START_FADE_SIZE_FACTOR * l )
  220. {
  221. if ( rad > END_FADE_SIZE_FACTOR *l )
  222. {
  223. tint = 0;
  224. rad = 0; // cull so we emit 0-sized sprite
  225. }
  226. else
  227. {
  228. tint *= 1-(rad-START_FADE_SIZE_FACTOR*l)/(END_FADE_SIZE_FACTOR*l-START_FADE_SIZE_FACTOR*l);
  229. }
  230. }
  231. #endif
  232. #ifndef SHADER_MODEL_VS_1_1
  233. // perform far fade
  234. float tscale = 1-min(1, max(0, (l-START_FAR_FADE)*FAR_FADE_FACTOR) );
  235. tint *= tscale;
  236. if ( tscale <= 0 )
  237. rad = 0; // cull so we emit 0-sized sprite
  238. #endif
  239. #if ( SPRITECARDVERTEXFOG )
  240. {
  241. // fade tint.a based upon fog amount
  242. float ffactor = 0.0f;
  243. #if ( HARDWAREFOGBLEND )
  244. {
  245. // On ps20 hardware, we use fixed-function fog blending, which has a fog factor of 1 for no fog, and 0 for fully fogged.
  246. // Note that the shader constants for fog params are different in both states of HARDWAREFOGBLEND.
  247. ffactor = CalcRangeFogFactorFixedFunction( worldPos, cEyePos, cRadialFogMaxDensity, cFogEndOverFogRange, cOOFogRange );
  248. }
  249. #else
  250. {
  251. // On ps2b and up, we blend fog in the pixel shader in such a way that we have a fog factor of 0 for no fog, and 1 for fully fogged.
  252. // We want to multiply by 1 where there is no fog, so invert.
  253. // Note that the shader constants for fog params are different in both states of HARDWAREFOGBLEND.
  254. ffactor = CalcRangeFogFactorNonFixedFunction( worldPos, cEyePos, cRadialFogMaxDensity, cFogEndOverFogRange, cOOFogRange );
  255. ffactor = 1.0f - ffactor; // map from [0,1]->[1,0] Want 0 to be fully fogged instead of 1.
  256. }
  257. #endif
  258. ffactor = lerp( 1, ffactor, FOG_SCALE_FACTOR );
  259. tint.a *= ffactor;
  260. }
  261. #endif
  262. if ( tint.a < ONE_OVER_255 )
  263. {
  264. // save fillrate by transforming completely transparent particles to a point
  265. rad = 0;
  266. }
  267. rad = min( rad, MAXIMUM_SIZE_FACTOR * l );
  268. #if ( ORIENTATION == 0 )
  269. {
  270. // Screen-aligned case
  271. float3 viewPos;
  272. viewPos = mul4x3( v.vPos, cModelView );
  273. float3 disp = float3( -x1, y1, 0 );
  274. float tmpx = disp.x * sc_yaw.x + disp.z * sc_yaw.y;
  275. disp.z = disp.z * sc_yaw.x - disp.x * sc_yaw.y;
  276. disp.x = tmpx;
  277. viewPos.xyz += disp * rad;
  278. projPos = mul( float4( viewPos, 1.0f ), cProj );
  279. }
  280. #endif
  281. #if ( ( ORIENTATION == 1 ) || ( ORIENTATION == 3 ) || ( ORIENTATION == 4 ) )
  282. {
  283. // Z-aligned case
  284. if (l > rad/2)
  285. {
  286. float3 up = float3(0,0,1);
  287. float3 right = normalize(cross(up, v2p));
  288. #if ( ORIENTATION == 4 )
  289. {
  290. up = normalize(cross(right, v2p));
  291. }
  292. #endif
  293. #if ( ORIENTATION == 3 )
  294. {
  295. float3 vNormal = v.vecNormal.xyz;
  296. float3 vTrialVector = float3( 0, 0, 1 );
  297. if ( abs( vNormal.z ) > 0.9 )
  298. {
  299. vTrialVector = float3( 1, 0, 0 );
  300. }
  301. up = normalize( cross( vNormal, vTrialVector ) );
  302. right = cross( vNormal, up );
  303. }
  304. #else // no yaw support for normal aligned
  305. {
  306. float tmpx = right.x * sc_yaw.x + right.y * sc_yaw.y;
  307. right.y = right.y * sc_yaw.x - right.x * sc_yaw.y;
  308. right.x = tmpx;
  309. }
  310. #endif
  311. worldPos += ( x1 * rad ) * right;
  312. worldPos += ( y1 * rad ) * up;
  313. #ifndef SHADER_MODEL_VS_1_1
  314. if (l < rad*2 )
  315. {
  316. tint *= smoothstep(rad/2,rad,l);
  317. }
  318. #endif
  319. }
  320. projPos = mul( float4(worldPos, 1.0f), cViewProj );
  321. }
  322. #endif // ( ( ORIENTATION == 1 ) || ( ORIENTATION == 3 ) || ( ORIENTATION == 4 ) )
  323. #if ( ORIENTATION == 2 )
  324. {
  325. // aligned with z plane case - easy
  326. // Need to rotate it into the space of the control point though
  327. // We're using cModelView to store that transformation since it's
  328. // only used as cModelView in ORIENTATION mode 0.
  329. float3 vOffset = mul3x3( float3( y1, x1, 0 ), ( float3x3 )cModelView );
  330. float3 wpos = v.vPos.xyz + RADIUS * vOffset;
  331. projPos = mul( float4(wpos, 1.0f), cModelViewProj );
  332. }
  333. #endif
  334. #if ( HAS_BLENDFACTOR0 )
  335. {
  336. o.blendfactor0 = float4( v.vParms.x, 0, 0, 0 );
  337. }
  338. #endif
  339. o.projPos = projPos;
  340. #if ( CROP )
  341. {
  342. o.texCoord0_1.xy = lerp( v.vTexCoord0.zw, v.vTexCoord0.xy, v.vCornerID.xy * g_vCropFactor.xy + g_vCropFactor.zw );
  343. o.texCoord0_1.wz = lerp( v.vTexCoord1.zw, v.vTexCoord1.xy, v.vCornerID.xy * g_vCropFactor.xy + g_vCropFactor.zw );
  344. }
  345. #else
  346. {
  347. o.texCoord0_1.xy = lerp( v.vTexCoord0.zw, v.vTexCoord0.xy, v.vCornerID.xy );
  348. o.texCoord0_1.wz = lerp( v.vTexCoord1.zw, v.vTexCoord1.xy, v.vCornerID.xy );
  349. }
  350. #endif
  351. #if ( ADDBASETEXTURE2 )
  352. {
  353. o.texCoord2.xy = lerp( v.vTexCoord2.zw, v.vTexCoord2.xy, v.vCornerID.xy );
  354. }
  355. #endif
  356. #if ( DUALSEQUENCE )
  357. {
  358. float2 lerpold = v.vCornerID.xy;
  359. float2 lerpnew = v.vCornerID.xy;
  360. #if ( ZOOM_ANIMATE_SEQ2 )
  361. {
  362. lerpold.x = getlerpscale_for_old_frame( v.vCornerID.x, v.vParms1.x );
  363. lerpold.y = getlerpscale_for_old_frame( v.vCornerID.y, v.vParms1.x );
  364. lerpnew.x = getlerpscale_for_new_frame( v.vCornerID.x, v.vParms1.x );
  365. lerpnew.y = getlerpscale_for_new_frame( v.vCornerID.y, v.vParms1.x );
  366. }
  367. #endif
  368. o.vSeq2TexCoord0_1.xy = lerp( v.vSeq2TexCoord0.zw, v.vSeq2TexCoord0.xy, lerpold.xy );
  369. o.vSeq2TexCoord0_1.wz = lerp( v.vSeq2TexCoord1.zw, v.vSeq2TexCoord1.xy, lerpnew.xy );
  370. o.blendfactor0.z = v.vParms1.x;
  371. }
  372. #endif
  373. #if ( EXTRACTGREENALPHA )
  374. {
  375. o.blendfactor1 = float4( 0.0f, 0.0f, 0.0f, 0.0f );
  376. // Input range Output range
  377. if ( v.vParms.x < 0.25f ) // 0.0 .. 0.25
  378. {
  379. o.blendfactor0.a = v.vParms.x * 2 + 0.5f; // 0.5 .. 1.0
  380. o.blendfactor0.g = 1 - o.blendfactor0.a; // 0.5 .. 0.0
  381. }
  382. else if ( v.vParms.x < 0.75f ) // 0.25 .. 0.75
  383. {
  384. o.blendfactor1.g = v.vParms.x * 2 - 0.5f; // 0.0 .. 1.0
  385. o.blendfactor0.a = 1 - o.blendfactor1.g; // 1.0 .. 0.0
  386. }
  387. else // 0.75 .. 1.0
  388. {
  389. o.blendfactor1.a = v.vParms.x * 2 - 1.5f; // 0.0 .. 0.5
  390. o.blendfactor1.g = 1 - o.blendfactor1.a; // 1.0 .. 0.5
  391. }
  392. }
  393. #endif
  394. #if DEPTHBLEND
  395. o.vProjPos = projPos;
  396. // Compute fragment's viewspace Z from its projection space coord, saves PS
  397. o.vProjPos.z = dot( projPos, g_vDepthFeatherProjToViewZW[0] );
  398. o.vProjPos.z /= dot( projPos, g_vDepthFeatherProjToViewZW[1] );
  399. #endif
  400. #if ( PACKED_INTERPOLATOR == 1 )
  401. {
  402. o.texCoord0_1.zw = tint.ra; // use red to lerp between two colors in pixel shaders, alpha to modulate opacity
  403. }
  404. #else
  405. {
  406. o.argbcolor = tint;
  407. }
  408. #endif
  409. #if ( !defined( _X360 ) && !defined( SHADER_MODEL_VS_3_0 ) )
  410. {
  411. o.fog = 1.0f;
  412. }
  413. #endif
  414. #ifdef _PS3
  415. // Account for OpenGL's flipped y coordinate and expanded z range [-1,1] instead of [0,1]
  416. o.projPos.y = -o.projPos.y;
  417. o.projPos.z = 2.0f * o.projPos.z - o.projPos.w;
  418. #endif // _PS3
  419. return o;
  420. }