HLSL几何着色器粗线DirectX

时间:2017-12-05 09:50:42

标签: directx shader sharpdx geometry-shader

我尝试使用这种方法绘制粗线Sinus曲线:https://forum.libcinder.org/topic/smooth-thick-lines-using-geometry-shader

我尝试将其移植到HLSL几何着色器:

  • 设置尺寸以固定500/500 atm
  • 厚度似乎不会改变问题
struct PSInput
{
    float4 Position : SV_POSITION;
};

float2 toScreenSpace(float4 vertex)
{
    float2 WIN_SCALE = { 500.0f, 500.0f };
    return float2(vertex.xy / vertex.w) * WIN_SCALE;
}

[maxvertexcount(7)]
void main(lineadj float4 vertices[4] : SV_POSITION, inout TriangleStream<PSInput> triStream)
{
    float2 WIN_SCALE = { 500.0f, 500.0f };

    float2 p0 = toScreenSpace(vertices[0]); // start of previous segment
    float2 p1 = toScreenSpace(vertices[1]); // end of previous segment, start of current segment
    float2 p2 = toScreenSpace(vertices[2]); // end of current segment, start of next segment
    float2 p3 = toScreenSpace(vertices[3]); // end of next segment


    // perform naive culling
    float2 area = WIN_SCALE * 1.2;
    if (p1.x < -area.x || p1.x > area.x)
        return;
    if (p1.y < -area.y || p1.y > area.y)
        return;
    if (p2.x < -area.x || p2.x > area.x)
        return;
    if (p2.y < -area.y || p2.y > area.y)
        return;

    float2 v0 = normalize(p1 - p0);
    float2 v1 = normalize(p2 - p1);
    float2 v2 = normalize(p3 - p2);

    // determine the normal of each of the 3 segments (previous, current, next)
    float2 n0 = { -v0.y, v0.x};
    float2 n1 = { -v1.y, v1.x};
    float2 n2 = { -v2.y, v2.x};

    // determine miter lines by averaging the normals of the 2 segments
    float2 miter_a = normalize(n0 + n1); // miter at start of current segment
    float2 miter_b = normalize(n1 + n2); // miter at end of current segment

    // determine the length of the miter by projecting it onto normal and then inverse it
    float THICKNESS = 1;
    float length_a = THICKNESS / dot(miter_a, n1);
    float length_b = THICKNESS / dot(miter_b, n1);

    float MITER_LIMIT = 0.75;
    //float MITER_LIMIT = -1;
    //float MITER_LIMIT = 0.1;

    PSInput v;
    float2 temp;

    //// prevent excessively long miters at sharp corners
    if (dot(v0, v1) < -MITER_LIMIT)
    {
        miter_a = n1;
        length_a = THICKNESS;

        // close the gap
        if (dot(v0, n1) > 0)
        {
            temp = (p1 + THICKNESS * n0) / WIN_SCALE;
            v.Position = float4(temp, 1.0, 1.0);
            triStream.Append(v);

            temp = (p1 + THICKNESS * n1) / WIN_SCALE;
            v.Position = float4(temp, 1.0, 1.0);
            triStream.Append(v);

            v.Position = float4(p1 / WIN_SCALE, 1.0, 1.0);
            triStream.Append(v);

            //triStream.RestartStrip();

        }
        else
        {
            temp = (p1 - THICKNESS * n1) / WIN_SCALE;
            v.Position = float4(temp, 1.0, 1.0);
            triStream.Append(v);

            temp = (p1 - THICKNESS * n0) / WIN_SCALE;
            v.Position = float4(temp, 1.0, 1.0);
            triStream.Append(v);

            v.Position = float4(p1 / WIN_SCALE, 1.0, 1.0);
            triStream.Append(v);

            //triStream.RestartStrip();
        }
    }

    if (dot(v1, v2) < -MITER_LIMIT)
    {
        miter_b = n1;
        length_b = THICKNESS;
    }

    // generate the triangle strip
    temp = (p1 + length_a * miter_a) / WIN_SCALE;
    v.Position = float4(temp, 1.0, 1.0);
    triStream.Append(v);

    temp = (p1 - length_a * miter_a) / WIN_SCALE;
    v.Position = float4(temp, 1.0, 1.0);
    triStream.Append(v);

    temp = (p2 + length_b * miter_b) / WIN_SCALE;
    v.Position = float4(temp, 1.0, 1.0);
    triStream.Append(v);

    temp = (p2 - length_b * miter_b) / WIN_SCALE;
    v.Position = float4(temp, 1.0, 1.0);
    triStream.Append(v);

    //triStream.RestartStrip();

}

问题是,它不会输出我给出的任何曲线作为点数。它已经很好地没有粗线,但我想拥有它。我可以为我的Sinus信号添加Noise,如果我这样做,(y值增加一点随机%)突然曲线显示并且更厚并且似乎工作,但我希望它很厚并且显示没有噪音

如果我上升频率,没有噪点,点会出现散点图样式,但不能作为连接的Sinus。

如果我使用VS Graphics Debugger调试,我可以看到在没有Noise的帧中它表示Pixel-Shader-Stage没有运行(?)。 带噪声的框架显示它运行和工作。

也许我的移植是不正确的,我忘记了一些事情,我是编程着色器的新手。也许我完全不理解这种方法。

任何帮助表示感谢。

1 个答案:

答案 0 :(得分:0)

我需要将剔除的默认行为设置为CullMode.None以获取所有绘制的三角形。