テッセレーションシェーダーを使用してみましたが、問題が発生しました。頂点のドメイン位置が0.3、0.3、0.3(中心頂点)の場合、ドメインシェーダーはUV座標(SV_DomainLocation)と頂点を配置するための入力パッチのみを渡します。ドメインシェーダーステージによって提供されない他の頂点または反復のインデックス(x、y)に関する情報が必要なため、正しい位置を知るため。
この問題はジオメトリシェーダーでコードを記述しているため、出力ストリームのサイズを1024バイトより大きくすることはできないため(シェーダーモデル5.0)、このシェーダーはテッセレーションに対して非常に制限されています。uv(SV_DomainLocationなど)を使用して頂点位置の計算を実装しましたが、これは三角形をテッセレーションするだけです。正確な最終結果を作成するには、コードの一部を使用して三角形の中心に追加された位置を計算する必要があります。
これは、正三角形のテッセレーションのコードです。
// required for array
#define MAX_ITERATIONS 5
void DrawTriangle(float4 p0, float4 p1, float4 p2, inout TriangleStream<VS_OUT> stream)
{
VS_OUT v0;
v0.pos = p0;
stream.Append(v0);
VS_OUT v1;
v1.pos = p1;
stream.Append(v1);
VS_OUT v2;
v2.pos = p2;
stream.Append(v2);
stream.RestartStrip();
}
[maxvertexcount(128)] // directx rule: maxvertexcount * sizeof(VS_OUT) <= 1024
void gs(triangle VS_OUT input[3], inout TriangleStream<VS_OUT> stream)
{
int itc = min(tess, MAX_ITERATIONS);
float fitc = itc;
float4 past_pos[MAX_ITERATIONS];
float4 array_pass[MAX_ITERATIONS];
for (int pi = 0; pi < MAX_ITERATIONS; pi++)
{
past_pos[pi] = float4(0, 0, 0, 0);
array_pass[pi] = float4(0, 0, 0, 0);
}
// -------------------------------------
// Tessellation kernel for the control points
for (int x = 0; x <= itc; x++)
{
float4 last;
for (int y = 0; y <= x; y++)
{
float2 seg = float2(x / fitc, y / fitc);
float3 uv;
uv.x = 1 - seg.x;
uv.z = seg.y;
uv.y = 1 - (uv.x + uv.z);
// ---------------------------------------
// Domain Stage
// uv Domain Location
// x,y IterationIndex
float4 fpos = input[0].pos * uv.x;
fpos += input[1].pos * uv.y;
fpos += input[2].pos * uv.z;
if (x > 0 && y > 0)
{
DrawTriangle(past_pos[y - 1], last, fpos, stream);
if (y < x)
{
// add adjacent triangle
DrawTriangle(past_pos[y - 1], fpos, past_pos[y], stream);
}
}
array_pass[y] = fpos;
last = fpos;
}
for (int i = 0; i < MAX_ITERATIONS; i++)
{
past_pos[i] = array_pass[i];
}
}
}