几何着色器的输入和输出

时间:2017-07-19 17:00:26

标签: direct3d hlsl geometry-shader

我想知道是否有人会如此善意地指出我的程序问题。我确信挫折与数据通过GS的方式有关。例如,如果从代码中取出几何着色器(修改其他两个阶段以适应变化),我最终会得到一个操作管道。如果我修改GS的数据输入以接受PS_INPUT而不是VS_DATA,程序不会崩溃,而是输出一个空白的蓝屏。我的目的是在二维平面上创建一个正方形的集合,因此空白的蓝色屏幕并不是我想要的。

Texture2D txDiffuse[26] : register(t0);
SamplerState samLinear : register(s0); //For Texturing

#define AWR_MAX_SHADE_LAY 1024

cbuffer ConstantBuffer : register(b0)
{
    float4 Matrix_Array[30];
    matrix Screen;
    float GM;
    float GA;
    float GD;
    float epsilon;
}
// Includes Layer Data
cbuffer CBLayer : register(b1)
{
    float4 Array_Fill_Color[AWR_MAX_SHADE_LAY];
    float4 Array_Line_Color[AWR_MAX_SHADE_LAY];
    float Array_Width[AWR_MAX_SHADE_LAY];
    float Array_Line_Pattern[AWR_MAX_SHADE_LAY];
    float Array_Z[AWR_MAX_SHADE_LAY];
    float Array_Thickness[AWR_MAX_SHADE_LAY];
}

//Input for Vertex Shader
struct VS_DATA
{
    float4 Pos : POSITION;
    int M2W_index : M2W_INDEX;
    int Layer_index : LAYER_INDEX;
};

//Input for Pixel Shader
struct PS_INPUT{
    float4 Pos : SV_POSITION;
    float4 Color : COLOR;
    int Layer_index : LAYER_INDEX;
};

//Vertex Shader
VS_DATA VS(VS_DATA input)// Vertex Shader
{
    VS_DATA output = (VS_DATA)0;
    //Model to World Transform
    float xm = input.Pos.x, yw = input.Pos.y, zm = input.Pos.z, ww = input.Pos.w, xw, zw;
    float4 transformation = Matrix_Array[input.M2W_index];
    xw = ((xm)*transformation.y - (zm)*transformation.x) + transformation.z;
    zw = ((xm)*transformation.x + (zm)*transformation.y) + transformation.w;

    //set color
    int valid_index = input.Layer_index;
    output.Color = Array_Fill_Color[valid_index];
    output.Color.a = 0.0;

    //output.Vertex_index = input.Vertex_index;
    //output.Next_Vertex_index = input.Next_Vertex_index;

    //Snapping process
    float sgn_x = (xw >= 0) ? 1.0 : -1.0;                   
    float sgn_z = (zw >= 0) ? 1.0 : -1.0;
    int floored_x = (int)((xw + (sgn_x*GA) + epsilon)*GD);
    int floored_z = (int)((zw + (sgn_z*GA) + epsilon)*GD);
    output.Pos.x = ((float)floored_x)*GM;
    output.Pos.y = yw;
    output.Pos.z = ((float)floored_z)*GM;
    output.Pos.w = ww;

    int another_valid_index = input.Layer_index;
    output.Layer_index = another_valid_index;

    // Transform to Screen Space
    output.Pos = mul(output.Pos, Screen);

    return output;
}


[maxvertexcount(6)]
void GS_Line(line VS_DATA points[2], inout TriangleStream<PS_INPUT> output)
{
    float4 p0 = points[0].Pos;
    float4 p1 = points[1].Pos;

    float w0 = p0.w;
    float w1 = p1.w;

    p0.xyz /= p0.w;
    p1.xyz /= p1.w;

    float3 line01 = p1 - p0;
    float3 dir = normalize(line01);

    float3 ratio = float3(700.0, 0.0, 700.0);
    ratio = normalize(ratio);

    float3 unit_z = normalize(float3(0.0, -1.0, 0.0));

    float3 normal = normalize(cross(unit_z, dir) * ratio);
    float width = 0.01;

    PS_INPUT v[4];

    float3 dir_offset = dir * ratio * width;
    float3 normal_scaled = normal * ratio * width;

    float3 p0_ex = p0 - dir_offset;
    float3 p1_ex = p1 + dir_offset;

    v[0].Pos = float4(p0_ex - normal_scaled, 1) * w0;
    v[0].Color = float4(1.0, 1.0, 1.0, 1.0);
    v[0].Layer_index = 1;

    v[1].Pos = float4(p0_ex + normal_scaled, 1) * w0;
    v[1].Color = float4(1.0, 1.0, 1.0, 1.0);
    v[1].Layer_index = 1;

    v[2].Pos = float4(p1_ex + normal_scaled, 1) * w1;
    v[2].Color = float4(1.0, 1.0, 1.0, 1.0);
    v[2].Layer_index = 1;

    v[3].Pos = float4(p1_ex - normal_scaled, 1) * w1;
    v[3].Color = float4(1.0, 1.0, 1.0, 1.0);
    v[3].Layer_index = 1;

    output.Append(v[2]);
    output.Append(v[1]);
    output.Append(v[0]);

    output.RestartStrip();

    output.Append(v[3]);
    output.Append(v[2]);
    output.Append(v[0]);

    output.RestartStrip();
}

//Pixel Shader
float4 PS(PS_INPUT input) : SV_Target{
    float2 Tex = float2(input.Pos.x / (8.0), input.Pos.y / (8.0));
    int the_index = input.Layer_index;

    float4 tex0 = txDiffuse[25].Sample(samLinear, Tex);
        if (tex0.r > 0.0)
            tex0 = float4(1.0, 1.0, 1.0, 1.0);
        else
            tex0 = float4(0.0, 0.0, 0.0, 0.0);
    if (tex0.r == 0.0)
        discard;
    tex0 *= input.Color;
    return tex0;
}

1 个答案:

答案 0 :(得分:1)

如果按原样编译顶点着色器,则会出现以下错误:

(第53行):无效的下标'Color'

output.Color = Array_Fill_Color[valid_index];

输出的类型为VS_DATA,不包含颜色。

如果您将VS定义更改为:

PS_INPUT VS(VS_DATA input)// Vertex Shader
{
    PS_INPUT output = (PS_INPUT)0;
    //rest of the code here

然后你的vs会编译,但是你会有一个不匹配的GS布局(GS仍然期望一行VS_DATA作为输入,现在你提供PS_INPUT) 在绘制之前,这不会给你任何错误(通常运行时会无声地失败,如果调试层打开,你会有一个不匹配的消息)

因此,您还需要修改GS以接受PS_INPUT作为输入,例如:

[maxvertexcount(6)]
void GS_Line(line PS_INPUT points[2], inout TriangleStream<PS_INPUT> output)