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.

383 lines
13 KiB

  1. //========== Copyright (c) Valve Corporation, All rights reserved. ==========//
  2. //
  3. // Purpose: Common code for tessellation
  4. //
  5. // $NoKeywords: $
  6. //
  7. //===========================================================================//
  8. #ifndef TESSELLATION_VS_FXC_H_
  9. #define TESSELLATION_VS_FXC_H_
  10. #ifdef SHADER_MODEL_VS_3_0
  11. #define TESSELLATION_MODE_ACC_PATCHES_EXTRA 1
  12. #define TESSELLATION_MODE_ACC_PATCHES_REG 2
  13. struct VS_INPUT
  14. {
  15. float2 UV : POSITION0; // Cartesian UV coordinates
  16. float4 BasisU : TEXCOORD0; // BasisU ( precalculated Bernstein basis functions for U )
  17. float4 BasisV : TEXCOORD1; // BasisV ( precalculated Bernstein basis functions for V )
  18. float4 V0_TanU : POSITION1; // Superprim vertex 0
  19. float4 V0_tc01 : TEXCOORD2;
  20. float4 V0_tc23 : TEXCOORD3;
  21. float4 V1_TanU : POSITION2; // Superprim vertex 1
  22. float4 V1_tc01 : TEXCOORD4;
  23. float4 V1_tc23 : TEXCOORD5;
  24. float4 V2_TanU : POSITION3; // Superprim vertex 2
  25. float4 V2_tc01 : TEXCOORD6;
  26. float4 V2_tc23 : TEXCOORD7;
  27. float4 V3_TanU : POSITION4; // Superprim vertex 3
  28. float4 V3_tc01 : TEXCOORD8;
  29. float4 V3_tc23 : TEXCOORD9;
  30. float PatchID : TEXCOORD10; // ID for this patch
  31. };
  32. void LoadACCPatchPos( float patchIndex, out float3 Bez[16],
  33. float flOneOverSubDHeight, sampler2D sampSubD )
  34. {
  35. float idx = ( patchIndex + 0.5 ) * flOneOverSubDHeight;
  36. [unroll]
  37. for (int i = 0; i < 4; i++)
  38. {
  39. float4 tmp[3];
  40. tmp[0] = tex2Dlod( sampSubD, float4((i * 3 + 0.5) / 30, idx, 0, 0) );
  41. tmp[1] = tex2Dlod( sampSubD, float4((i * 3 + 1.5) / 30, idx, 0, 0) );
  42. tmp[2] = tex2Dlod( sampSubD, float4((i * 3 + 2.5) / 30, idx, 0, 0) );
  43. Bez[4 * i + 0] = tmp[0].xyz;
  44. Bez[4 * i + 1] = float3( tmp[0].w, tmp[1].xy );
  45. Bez[4 * i + 2] = float3( tmp[1].zw, tmp[2].x );
  46. Bez[4 * i + 3] = tmp[2].yzw;
  47. }
  48. }
  49. void LoadACCPatchTan( float patchIndex, out float3 TanU[12], out float3 TanV[12],
  50. float flOneOverSubDHeight, sampler2D sampSubD )
  51. {
  52. float idx = ( patchIndex + 0.5 ) * flOneOverSubDHeight;
  53. // Tangents
  54. [unroll]
  55. for (int i = 0; i < 3; i++)
  56. {
  57. float4 tmp[3];
  58. tmp[0] = tex2Dlod(sampSubD, float4((i * 3 + 0.5 + 12) / 30, idx, 0, 0));
  59. tmp[1] = tex2Dlod(sampSubD, float4((i * 3 + 1.5 + 12) / 30, idx, 0, 0));
  60. tmp[2] = tex2Dlod(sampSubD, float4((i * 3 + 2.5 + 12) / 30, idx, 0, 0));
  61. TanU[4 * i + 0] = tmp[0].xyz;
  62. TanU[4 * i + 1] = float3( tmp[0].w, tmp[1].xy );
  63. TanU[4 * i + 2] = float3( tmp[1].zw, tmp[2].x );
  64. TanU[4 * i + 3] = tmp[2].yzw;
  65. }
  66. // Tangents
  67. [unroll]
  68. for (int i = 0; i < 3; i++)
  69. {
  70. float4 tmp[3];
  71. tmp[0] = tex2Dlod(sampSubD, float4((i * 3 + 0.5 + 21) / 30, idx, 0, 0));
  72. tmp[1] = tex2Dlod(sampSubD, float4((i * 3 + 1.5 + 21) / 30, idx, 0, 0));
  73. tmp[2] = tex2Dlod(sampSubD, float4((i * 3 + 2.5 + 21) / 30, idx, 0, 0));
  74. TanV[4 * i + 0] = tmp[0].xyz;
  75. TanV[4 * i + 1] = float3( tmp[0].w, tmp[1].xy );
  76. TanV[4 * i + 2] = float3( tmp[1].zw, tmp[2].x );
  77. TanV[4 * i + 3] = tmp[2].yzw;
  78. }
  79. }
  80. void EvaluateCubicACCPosPatch( in float4 BasisU, in float4 BasisV, float2 UV, float3 cpP[16], out float3 pos )
  81. {
  82. pos = (BasisU.x * cpP[ 0] + BasisU.y * cpP[ 1] + BasisU.z * cpP[ 2] + BasisU.w * cpP[ 3]) * BasisV.x +
  83. (BasisU.x * cpP[ 4] + BasisU.y * cpP[ 5] + BasisU.z * cpP[ 6] + BasisU.w * cpP[ 7]) * BasisV.y +
  84. (BasisU.x * cpP[ 8] + BasisU.y * cpP[ 9] + BasisU.z * cpP[10] + BasisU.w * cpP[11]) * BasisV.z +
  85. (BasisU.x * cpP[12] + BasisU.y * cpP[13] + BasisU.z * cpP[14] + BasisU.w * cpP[15]) * BasisV.w;
  86. }
  87. //--------------------------------------------------------------------------------------
  88. // Cubic Bernstein basis functions
  89. // http://mathworld.wolfram.com/BernsteinPolynomial.html
  90. //--------------------------------------------------------------------------------------
  91. float4 BernsteinBasis( float t )
  92. {
  93. float invT = 1.0f-t;
  94. return float4( invT*invT*invT, 3.0*t*invT*invT, 3.0*t*t*invT, t*t*t );
  95. }
  96. float3 BersteinBasisQuad( float t )
  97. {
  98. float invT = 1.0f-t;
  99. return float3( invT * invT, 2 * invT * t, t * t );
  100. }
  101. void EvaluateCubicACCTanPatches( in float4 BasisU, in float4 BasisV, float2 UV, float3 cpU[12], float3 cpV[12],
  102. out float3 tanU, out float3 tanV )
  103. {
  104. // quadratic bernstein basis functions
  105. float3 qBasisU = BersteinBasisQuad( UV.x );
  106. float3 qBasisV = BersteinBasisQuad( UV.y );
  107. tanU = (qBasisU.x * cpU[ 0] + qBasisU.y * cpU[ 1] + qBasisU.z * cpU[ 2]) * BasisV.x +
  108. (qBasisU.x * cpU[ 3] + qBasisU.y * cpU[ 4] + qBasisU.z * cpU[ 5]) * BasisV.y +
  109. (qBasisU.x * cpU[ 6] + qBasisU.y * cpU[ 7] + qBasisU.z * cpU[ 8]) * BasisV.z +
  110. (qBasisU.x * cpU[ 9] + qBasisU.y * cpU[10] + qBasisU.z * cpU[11]) * BasisV.w;
  111. tanV = (BasisU.x * cpV[ 0] + BasisU.y * cpV[ 1] + BasisU.z * cpV[ 2] + BasisU.w * cpV[ 3]) * qBasisV.x +
  112. (BasisU.x * cpV[ 4] + BasisU.y * cpV[ 5] + BasisU.z * cpV[ 6] + BasisU.w * cpV[ 7]) * qBasisV.y +
  113. (BasisU.x * cpV[ 8] + BasisU.y * cpV[ 9] + BasisU.z * cpV[10] + BasisU.w * cpV[11]) * qBasisV.z;
  114. }
  115. // We define a patch owner for each edge and vertex of the mesh.
  116. // When sampling a displacement map on the boundaries and corners, owner coords are used
  117. //
  118. // Each patch stores: The superprim verts can store
  119. // all of this data like so:
  120. // -- patch U -->
  121. // | X Y Z W
  122. // p t3|t2 t1|t3 +-----------------------------------+
  123. // a --0-----1-- | tanX | tanY | tanZ | sBWrnk | <- Binormal sign flip bit and wrinkle weight
  124. // t t1|t0 t0|t2 +-----------------------------------+
  125. // c | | | innerU | innerV | edgeVU | edgeVV |
  126. // h t2|t0 t0|t1 +-----------------------------------+
  127. // | --3-----2-- | edgeUU | edgeUV | cornerU| cornerV|
  128. // V t3|t1 t2|t3 +-----------------------------------+
  129. //
  130. float2 ComputeConsistentDisplacementUVs( float2 UV,
  131. float4 V0_tc01, float4 V0_tc23,
  132. float4 V1_tc01, float4 V1_tc23,
  133. float4 V2_tc01, float4 V2_tc23,
  134. float4 V3_tc01, float4 V3_tc23 )
  135. {
  136. // Use the tie-breaking scheme for sampling texture coordinates to avoid cracking
  137. float2 t0[4], t1[4], t2[4], t3[4];
  138. t0[0] = V0_tc01.xy;
  139. t0[1] = V0_tc01.zw;
  140. t0[2] = V0_tc23.xy;
  141. t0[3] = V0_tc23.zw;
  142. t1[0] = V1_tc01.xy;
  143. t1[1] = V1_tc01.zw;
  144. t1[2] = V1_tc23.xy;
  145. t1[3] = V1_tc23.zw;
  146. t2[0] = V2_tc01.xy;
  147. t2[1] = V2_tc01.zw;
  148. t2[2] = V2_tc23.xy;
  149. t2[3] = V2_tc23.zw;
  150. t3[0] = V3_tc01.xy;
  151. t3[1] = V3_tc01.zw;
  152. t3[2] = V3_tc23.xy;
  153. t3[3] = V3_tc23.zw;
  154. float flMaxUV = 0.99;
  155. float flMinUV = 0.01;
  156. int i0 = 2 * (UV.x < flMinUV) + (UV.y < flMinUV);
  157. int i1 = (UV.x > flMaxUV) + 2 * (UV.y < flMinUV);
  158. int i2 = 2 * (UV.x > flMaxUV) + (UV.y > flMaxUV);
  159. int i3 = (UV.x < flMinUV) + 2 * (UV.y > flMaxUV);
  160. float2 bottom = lerp( t0[i0], t1[i1], UV.x );
  161. float2 top = lerp( t3[i3], t2[i2], UV.x );
  162. return lerp( bottom, top, UV.y );
  163. }
  164. void DeCasteljau(float u, float3 p0, float3 p1, float3 p2, float3 p3, out float3 p)
  165. {
  166. float3 q0, q1, q2;
  167. float3 r0, r1;
  168. [isolate]
  169. {
  170. q0 = lerp( p0, p1, u );
  171. q1 = lerp( p1, p2, u );
  172. q2 = lerp( p2, p3, u );
  173. r0 = lerp( q0, q1, u );
  174. r1 = lerp( q1, q2, u );
  175. p = lerp( r0, r1, u );
  176. }
  177. }
  178. void DeCasteljau(float u, float3 p0, float3 p1, float3 p2, float3 p3, out float3 p, out float3 dp)
  179. {
  180. float3 q0, q1, q2;
  181. float3 r0, r1;
  182. [isolate]
  183. {
  184. q0 = lerp( p0, p1, u );
  185. q1 = lerp( p1, p2, u );
  186. q2 = lerp( p2, p3, u );
  187. r0 = lerp( q0, q1, u );
  188. r1 = lerp( q1, q2, u );
  189. p = lerp( r0, r1, u );
  190. }
  191. dp = r0 - r1;
  192. }
  193. void EvaluateBezierRegular( float2 uv, float3 p[16], out float3 pos, out float3 nor )
  194. {
  195. float3 t0, t1, t2, t3;
  196. float3 p0, p1, p2, p3;
  197. [isolate]
  198. {
  199. DeCasteljau( uv.x, p[ 0], p[ 1], p[ 2], p[ 3], p0, t0 );
  200. DeCasteljau( uv.x, p[ 4], p[ 5], p[ 6], p[ 7], p1, t1 );
  201. DeCasteljau( uv.x, p[ 8], p[ 9], p[10], p[11], p2, t2 );
  202. DeCasteljau( uv.x, p[12], p[13], p[14], p[15], p3, t3 );
  203. }
  204. float3 du, dv;
  205. DeCasteljau( uv.y, p0, p1, p2, p3, pos, dv );
  206. DeCasteljau( uv.y, t0, t1, t2, t3, du );
  207. nor = normalize( cross(3 * dv, 3 * du) );
  208. }
  209. void EvaluateBezierPosition( float2 uv, float3 p[16], out float3 pos )
  210. {
  211. float3 t0, t1, t2, t3;
  212. float3 p0, p1, p2, p3;
  213. [isolate]
  214. {
  215. DeCasteljau( uv.x, p[ 0], p[ 1], p[ 2], p[ 3], p0, t0 );
  216. DeCasteljau( uv.x, p[ 4], p[ 5], p[ 6], p[ 7], p1, t1 );
  217. DeCasteljau( uv.x, p[ 8], p[ 9], p[10], p[11], p2, t2 );
  218. DeCasteljau( uv.x, p[12], p[13], p[14], p[15], p3, t3 );
  219. }
  220. DeCasteljau( uv.y, p0, p1, p2, p3, pos );
  221. }
  222. void EvaluateSubdivisionSurface( const VS_INPUT v, float flOneOverSubDHeight, float flDoDisplacement, float flDoWrinkledDisplacements,
  223. sampler2D BezierSampler, sampler2D sampDisplacement,
  224. // Outputs
  225. out float3 vWorldNormal, out float3 vWorldPos,
  226. out float3 vWorldTangentS, out float3 vWorldTangentT, out float flBiTangentSign,
  227. out float flWrinkleWeight,
  228. out float2 vTexUV, out float2 vPatchUV,
  229. bool bTangentFrame = true )
  230. {
  231. float4 vInTan;
  232. float2 vDispUV;
  233. float3 vPatchTangent;
  234. float3 vPatchBiTangent;
  235. float4 vBasisU;
  236. float4 vBasisV;
  237. float flPatchLoadIndex;
  238. // PatchUV is passed in for us
  239. vPatchUV = v.UV;
  240. // compute values for tangent based on patchUV
  241. float4 TanUbottom = lerp( v.V0_TanU, v.V1_TanU, vPatchUV.x );
  242. float4 TanUtop = lerp( v.V3_TanU, v.V2_TanU, vPatchUV.x );
  243. vInTan = lerp( TanUbottom, TanUtop, vPatchUV.y );
  244. // compute values for texcoord based on patchUV
  245. float2 bottom = lerp( v.V0_tc01.xy, v.V1_tc01.xy, vPatchUV.x );
  246. float2 top = lerp( v.V3_tc01.xy, v.V2_tc01.xy, vPatchUV.x );
  247. vTexUV = lerp( bottom, top, vPatchUV.y );
  248. // Compute consistent displacement UVs for crack-free displacement mapping
  249. vDispUV = ComputeConsistentDisplacementUVs( vPatchUV,
  250. v.V0_tc01, v.V0_tc23,
  251. v.V1_tc01, v.V1_tc23,
  252. v.V2_tc01, v.V2_tc23,
  253. v.V3_tc01, v.V3_tc23 );
  254. // Cubic Bernstein basis coefficients are passed in for us
  255. vBasisU = v.BasisU;
  256. vBasisV = v.BasisV;
  257. // Patch load index is passed in for us
  258. flPatchLoadIndex = v.PatchID;
  259. float3 ControlPoints[16];
  260. LoadACCPatchPos( flPatchLoadIndex, ControlPoints, flOneOverSubDHeight, BezierSampler );
  261. #if ( TESSELLATION == TESSELLATION_MODE_ACC_PATCHES_REG )
  262. EvaluateBezierRegular( vPatchUV, ControlPoints, vWorldPos, vWorldNormal );
  263. #else
  264. // We split the loading and evaluation of Position patches and Tangent patches to reduce temp register pressure.
  265. // Load and evaluation position
  266. // EvaluateCubicACCPosPatch( vBasisU, vBasisV, vPatchUV, ControlPoints, vWorldPos );
  267. EvaluateBezierPosition( vPatchUV, ControlPoints, vWorldPos );
  268. // Load and evaluate tangent patches
  269. float3 ControlPointsU[12], ControlPointsV[12];
  270. LoadACCPatchTan( flPatchLoadIndex, ControlPointsU, ControlPointsV, flOneOverSubDHeight, BezierSampler );
  271. EvaluateCubicACCTanPatches( vBasisU, vBasisV, vPatchUV, ControlPointsU, ControlPointsV, vPatchTangent, vPatchBiTangent );
  272. vWorldNormal = normalize( cross( vPatchBiTangent, vPatchTangent ) ); // Compute world normal
  273. #endif
  274. // Up to three scalar displacements for { Neutral, Compress, Stretch }
  275. float3 vDisplacement = tex2Dlod( sampDisplacement, float4( vDispUV, 0, 0 ) );
  276. flBiTangentSign = sign( vInTan.w );
  277. if ( bTangentFrame )
  278. {
  279. vWorldTangentS = normalize( vInTan.xyz - ( vWorldNormal * dot( vInTan.xyz, vWorldNormal ) ) ); // Orthonormalize superprim tangent
  280. vWorldTangentT = cross( vWorldNormal, vWorldTangentS.xyz ) * flBiTangentSign; // Sign encodes Binormal flip
  281. }
  282. else
  283. {
  284. vWorldTangentS = vWorldTangentT = vWorldNormal;
  285. }
  286. flWrinkleWeight = abs( vInTan.w ) - 2.0f; // Convert wrinkle weight to -1 to 1 range for pixel shader to use
  287. float3 vDispCoeff = float3(0,0,0); // { Neutral, Compress, Stretch } Displacement Coefficients
  288. vDispCoeff.y = saturate( -flWrinkleWeight ); // One of these two is zero
  289. vDispCoeff.z = saturate( flWrinkleWeight ); // while the other is in the 0..1 range
  290. vDispCoeff *= flDoWrinkledDisplacements; // Separate control for presence of wrinkled displacements (just multiplying by 0 or 1 here)
  291. vDispCoeff.x = 1.0f - vDispCoeff.y - vDispCoeff.z; // Derive neutral weight since these all sum to one
  292. // Displace along normal, using wrinkle displacement map coefficients
  293. vWorldPos += vWorldNormal * ( flDoDisplacement * dot( vDisplacement, vDispCoeff ) );
  294. }
  295. // Wrapper for no-tangent-frame, no-wrinkle version
  296. void EvaluateSubdivisionSurface( VS_INPUT v, float flOneOverSubDHeight, float flDoDisplacement, float flDoWrinkledDisplacements,
  297. sampler2D BezierSampler, sampler2D DispSampler,
  298. // Outputs
  299. out float3 vWorldNormal, out float3 vWorldPos,
  300. out float2 vUV, out float2 vPatchUV )
  301. {
  302. float3 vDummyA, vDummyB;
  303. float flDummyWrinkle;
  304. float flDummyBinormalFlip;
  305. EvaluateSubdivisionSurface( v, flOneOverSubDHeight, flDoDisplacement, flDoWrinkledDisplacements,
  306. BezierSampler, DispSampler, vWorldNormal, vWorldPos, vDummyA, vDummyB,
  307. flDummyBinormalFlip, flDummyWrinkle, vUV, vPatchUV, false );
  308. }
  309. #endif // SHADER_MODEL_VS_3_0
  310. #endif //#ifndef TESSELLATION_VS_FXC_H_