Directx HLSL修改细分着色器以生成等边三角形?

Directx HLSL修改细分着色器以生成等边三角形?,directx,hlsl,tessellation,Directx,Hlsl,Tessellation,详情: 我正在程序化的行星生成过程中;到目前为止,我已经完成了动态LOD的工作,但是我当前的软件算法非常慢。我决定改用DX11的新镶嵌功能。 目前我的球体是一个细分的二十面体。所有等边三角形的20条边 当我使用我的软件算法进行细分时,一个三角形是 每次在父对象的中点分成四个子对象,形成Hyrule符号…如下所示: 如您所见,每个细分的三角形创建了越来越多的等边三角形,即每个三角形的形状完全相同 但现在我使用GPU在HLSL中进行细分,结果肯定不是这样 我要找的是: 问题: 在外壳和域着色器中是否

详情:

我正在程序化的行星生成过程中;到目前为止,我已经完成了动态LOD的工作,但是我当前的软件算法非常慢。我决定改用DX11的新镶嵌功能。 目前我的球体是一个细分的二十面体。所有等边三角形的20条边

当我使用我的软件算法进行细分时,一个三角形是 每次在父对象的中点分成四个子对象,形成Hyrule符号…如下所示:

如您所见,每个细分的三角形创建了越来越多的等边三角形,即每个三角形的形状完全相同

但现在我使用GPU在HLSL中进行细分,结果肯定不是这样 我要找的是:

问题:

在外壳和域着色器中是否可以执行任何操作来更改细分 这样它就可以像第一张图像那样细分成等边三角形了

我应该使用几何体着色器进行类似的操作吗?如果是的话,会是这样吗
比细分器慢?

我尝试使用细分着色器,但遇到了一个问题:当顶点的域位置为0.3、0.3时,域着色器仅传递uv坐标SV_DomainLocation和用于定位顶点的输入面片,0.3中心顶点不可能知道正确的位置,因为您需要有关其他顶点的信息或域着色器阶段未提供的迭代索引

因为这个问题,我在geometry shader中编写代码,所以该着色器对于细分非常有限,因为在shader model 5.0中,输出流的大小不能大于1024字节。我使用uv-like 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];
        }
    }
}