SimpleBezier11DS.hlsl 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212
  1. // RUN: %dxc -E main -T ds_6_0 %s | FileCheck %s
  2. // CHECK: domainLocation
  3. // CHECK: domainLocation
  4. // CHECK: Rsqrt
  5. // CHECK: storeOutput
  6. //--------------------------------------------------------------------------------------
  7. // File: SimpleBezier11.hlsl
  8. //
  9. // This sample shows an simple implementation of the DirectX 11 Hardware Tessellator
  10. // for rendering a Bezier Patch.
  11. //
  12. // Copyright (c) Microsoft Corporation. All rights reserved.
  13. //--------------------------------------------------------------------------------------
  14. // This allows us to compile the shader with a #define to choose
  15. // the different partition modes for the hull shader.
  16. // See the hull shader: [partitioning(BEZIER_HS_PARTITION)]
  17. // This sample demonstrates "integer", "fractional_even", and "fractional_odd"
  18. #ifndef BEZIER_HS_PARTITION
  19. #define BEZIER_HS_PARTITION "integer"
  20. #endif // BEZIER_HS_PARTITION
  21. // The input patch size. In this sample, it is 16 control points.
  22. // This value should match the call to IASetPrimitiveTopology()
  23. #define INPUT_PATCH_SIZE 16
  24. // The output patch size. In this sample, it is also 16 control points.
  25. #define OUTPUT_PATCH_SIZE 16
  26. //--------------------------------------------------------------------------------------
  27. // Constant Buffers
  28. //--------------------------------------------------------------------------------------
  29. cbuffer cbPerFrame : register( b0 )
  30. {
  31. matrix g_mViewProjection;
  32. float3 g_vCameraPosWorld;
  33. float g_fTessellationFactor;
  34. };
  35. //--------------------------------------------------------------------------------------
  36. // Vertex shader section
  37. //--------------------------------------------------------------------------------------
  38. struct VS_CONTROL_POINT_INPUT
  39. {
  40. float3 vPosition : POSITION;
  41. };
  42. struct VS_CONTROL_POINT_OUTPUT
  43. {
  44. float3 vPosition : POSITION;
  45. };
  46. // This simple vertex shader passes the control points straight through to the
  47. // hull shader. In a more complex scene, you might transform the control points
  48. // or perform skinning at this step.
  49. // The input to the vertex shader comes from the vertex buffer.
  50. // The output from the vertex shader will go into the hull shader.
  51. VS_CONTROL_POINT_OUTPUT BezierVS( VS_CONTROL_POINT_INPUT Input )
  52. {
  53. VS_CONTROL_POINT_OUTPUT Output;
  54. Output.vPosition = Input.vPosition;
  55. return Output;
  56. }
  57. //--------------------------------------------------------------------------------------
  58. // Constant data function for the BezierHS. This is executed once per patch.
  59. //--------------------------------------------------------------------------------------
  60. struct HS_CONSTANT_DATA_OUTPUT
  61. {
  62. float Edges[4] : SV_TessFactor;
  63. float Inside[2] : SV_InsideTessFactor;
  64. };
  65. struct HS_OUTPUT
  66. {
  67. float3 vPosition : BEZIERPOS;
  68. };
  69. // This constant hull shader is executed once per patch. For the simple Mobius strip
  70. // model, it will be executed 4 times. In this sample, we set the tessellation factor
  71. // via SV_TessFactor and SV_InsideTessFactor for each patch. In a more complex scene,
  72. // you might calculate a variable tessellation factor based on the camera's distance.
  73. HS_CONSTANT_DATA_OUTPUT BezierConstantHS( InputPatch<VS_CONTROL_POINT_OUTPUT, INPUT_PATCH_SIZE> ip,
  74. uint PatchID : SV_PrimitiveID )
  75. {
  76. HS_CONSTANT_DATA_OUTPUT Output;
  77. float TessAmount = g_fTessellationFactor;
  78. Output.Edges[0] = Output.Edges[1] = Output.Edges[2] = Output.Edges[3] = TessAmount;
  79. Output.Inside[0] = Output.Inside[1] = TessAmount;
  80. return Output;
  81. }
  82. // The hull shader is called once per output control point, which is specified with
  83. // outputcontrolpoints. For this sample, we take the control points from the vertex
  84. // shader and pass them directly off to the domain shader. In a more complex scene,
  85. // you might perform a basis conversion from the input control points into a Bezier
  86. // patch, such as the SubD11 Sample.
  87. // The input to the hull shader comes from the vertex shader
  88. // The output from the hull shader will go to the domain shader.
  89. // The tessellation factor, topology, and partition mode will go to the fixed function
  90. // tessellator stage to calculate the UVW and domain points.
  91. [domain("quad")]
  92. [partitioning(BEZIER_HS_PARTITION)]
  93. [outputtopology("triangle_cw")]
  94. [outputcontrolpoints(OUTPUT_PATCH_SIZE)]
  95. [patchconstantfunc("BezierConstantHS")]
  96. HS_OUTPUT BezierHS( InputPatch<VS_CONTROL_POINT_OUTPUT, INPUT_PATCH_SIZE> p,
  97. uint i : SV_OutputControlPointID,
  98. uint PatchID : SV_PrimitiveID )
  99. {
  100. HS_OUTPUT Output;
  101. Output.vPosition = p[i].vPosition;
  102. return Output;
  103. }
  104. //--------------------------------------------------------------------------------------
  105. // Bezier evaluation domain shader section
  106. //--------------------------------------------------------------------------------------
  107. struct DS_OUTPUT
  108. {
  109. float4 vPosition : SV_POSITION;
  110. float3 vWorldPos : WORLDPOS;
  111. float3 vNormal : NORMAL;
  112. };
  113. //--------------------------------------------------------------------------------------
  114. float4 BernsteinBasis(float t)
  115. {
  116. float invT = 1.0f - t;
  117. return float4( invT * invT * invT,
  118. 3.0f * t * invT * invT,
  119. 3.0f * t * t * invT,
  120. t * t * t );
  121. }
  122. //--------------------------------------------------------------------------------------
  123. float4 dBernsteinBasis(float t)
  124. {
  125. float invT = 1.0f - t;
  126. return float4( -3 * invT * invT,
  127. 3 * invT * invT - 6 * t * invT,
  128. 6 * t * invT - 3 * t * t,
  129. 3 * t * t );
  130. }
  131. //--------------------------------------------------------------------------------------
  132. float3 EvaluateBezier( const OutputPatch<HS_OUTPUT, OUTPUT_PATCH_SIZE> bezpatch,
  133. float4 BasisU,
  134. float4 BasisV )
  135. {
  136. float3 Value = float3(0,0,0);
  137. Value = BasisV.x * ( bezpatch[0].vPosition * BasisU.x + bezpatch[1].vPosition * BasisU.y + bezpatch[2].vPosition * BasisU.z + bezpatch[3].vPosition * BasisU.w );
  138. Value += BasisV.y * ( bezpatch[4].vPosition * BasisU.x + bezpatch[5].vPosition * BasisU.y + bezpatch[6].vPosition * BasisU.z + bezpatch[7].vPosition * BasisU.w );
  139. Value += BasisV.z * ( bezpatch[8].vPosition * BasisU.x + bezpatch[9].vPosition * BasisU.y + bezpatch[10].vPosition * BasisU.z + bezpatch[11].vPosition * BasisU.w );
  140. Value += BasisV.w * ( bezpatch[12].vPosition * BasisU.x + bezpatch[13].vPosition * BasisU.y + bezpatch[14].vPosition * BasisU.z + bezpatch[15].vPosition * BasisU.w );
  141. return Value;
  142. }
  143. // The domain shader is run once per vertex and calculates the final vertex's position
  144. // and attributes. It receives the UVW from the fixed function tessellator and the
  145. // control point outputs from the hull shader. Since we are using the DirectX 11
  146. // Tessellation pipeline, it is the domain shader's responsibility to calculate the
  147. // final SV_POSITION for each vertex. In this sample, we evaluate the vertex's
  148. // position using a Bernstein polynomial and the normal is calculated as the cross
  149. // product of the U and V derivatives.
  150. // The input SV_DomainLocation to the domain shader comes from fixed function
  151. // tessellator. And the OutputPatch comes from the hull shader. From these, you
  152. // must calculate the final vertex position, color, texcoords, and other attributes.
  153. // The output from the domain shader will be a vertex that will go to the video card's
  154. // rasterization pipeline and get drawn to the screen.
  155. [domain("quad")]
  156. DS_OUTPUT main( HS_CONSTANT_DATA_OUTPUT input,
  157. float2 UV : SV_DomainLocation,
  158. const OutputPatch<HS_OUTPUT, OUTPUT_PATCH_SIZE> bezpatch )
  159. {
  160. float4 BasisU = BernsteinBasis( UV.x );
  161. float4 BasisV = BernsteinBasis( UV.y );
  162. float4 dBasisU = dBernsteinBasis( UV.x );
  163. float4 dBasisV = dBernsteinBasis( UV.y );
  164. float3 WorldPos = EvaluateBezier( bezpatch, BasisU, BasisV );
  165. float3 Tangent = EvaluateBezier( bezpatch, dBasisU, BasisV );
  166. float3 BiTangent = EvaluateBezier( bezpatch, BasisU, dBasisV );
  167. float3 Norm = normalize( cross( Tangent, BiTangent ) );
  168. DS_OUTPUT Output;
  169. Output.vPosition = mul( float4(WorldPos,1), g_mViewProjection );
  170. Output.vWorldPos = WorldPos;
  171. Output.vNormal = Norm;
  172. return Output;
  173. }