Входы и выходы геометрического шейдера

Мне было интересно, не будет ли кто-нибудь так любезен, чтобы указать на проблему с моей программой. Я уверен, что неудача как-то связана со способом передачи данных через 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;
}

person NAKASSEIN    schedule 19.07.2017    source источник
comment
Получаете ли вы какие-либо HRESULT сбои в работе Direct3D? Вы включили устройство отладки и искали вывод в окне отладки? Используете ли вы аппаратную карту Direct3D версии 10.0 или выше? Кроме того, поскольку вы используете шейдер геометрии (требуется оборудование 10.0+), вам следует рассмотреть возможность использования Texture2DArray (требуется оборудование 10.0+), а не связывать 26 отдельных текстур....   -  person Chuck Walbourn    schedule 19.07.2017
comment
На этом шаге программа завершается ошибкой 'ID3DBlob* pVSBlob = nullptr; hr = CompileShaderFromFile(LTutorial07.fx, VS, vs_4_0, &pVSBlob); if (FAILED(hr)) { MessageBox(nullptr, LФайл FX не может быть скомпилирован. Запустите этот исполняемый файл из каталога, содержащего файл FX., LError, MB_OK); возврат час; }' из ваших руководств на MSDN. Сообщение об ошибке точно такое же, как и после буквы L.   -  person NAKASSEIN    schedule 19.07.2017
comment
Эта строка кода строит не геометрический шейдер, а вершинный шейдер. Геометрический шейдер будет GS_Line, gs_4_0. Попытка построить шейдер из командной строки Visual Studio Developer непосредственно с помощью FXC.EXE, чтобы вам было легче увидеть любые ошибки, выдаваемые компилятором.   -  person Chuck Walbourn    schedule 20.07.2017


Ответы (1)


Если вы скомпилируете свой вершинный шейдер как есть, вы получите следующую ошибку:

(строка 53): неверный индекс «Цвет»

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)
person mrvux    schedule 20.07.2017
comment
Большое спасибо! Проблема заключалась в том, как я перемещал данные через шейдеры. - person NAKASSEIN; 20.07.2017