Невозможно нарисовать треугольник в DirectX 11

#c #rendering #directx #directx-11

#c #рендеринг #directx #directx-11

Вопрос:

Я изучаю DirectX 11 и пытаюсь отобразить треугольник, но ничего не отображается, кроме цвета фона. Ошибок нет, предупреждений нет. Вот мой основной файл:

 while (true)
    {
        while (PeekMessage(amp;msg, NULL, 0, 0, PM_REMOVE) != 0)
        {
            TranslateMessage(amp;msg);
            DispatchMessage(amp;msg);
        }
        if (msg.message == WM_QUIT)
        {
            break;
        }
        // Rendering here
        ID3D11Buffer* vertex_buffer;

        const float color[] = { 0.0f, 0.0f, 0.0f, 1.0f };
        device_context->ClearRenderTargetView(render_target_view, color);

        Vertex vertices[]{
            { 0.0f, -0.5f},
            { 0.5f,  0.5f},
            {-0.5f, -0.5f}
        };

        D3D11_BUFFER_DESC vb_desc;
        ZeroMemory(amp;vb_desc, sizeof(vb_desc));
        vb_desc.ByteWidth = sizeof(vertices);
        vb_desc.Usage = D3D11_USAGE_DEFAULT;
        vb_desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
        vb_desc.CPUAccessFlags = 0;
        vb_desc.MiscFlags = 0;
        vb_desc.StructureByteStride = sizeof(Vertex);

        D3D11_SUBRESOURCE_DATA vb_data;
        ZeroMemory(amp;vb_data, sizeof(vb_data));
        vb_data.pSysMem = vertices;

        device->CreateBuffer(amp;vb_desc, amp;vb_data, amp;vertex_buffer);

        const UINT stride = sizeof(Vertex);
        const UINT offset = 0;

        device_context->IASetVertexBuffers(0, 1, amp;vertex_buffer, amp;stride, amp;offset);

        ID3D11VertexShader *vertex_shader;
        ID3D11PixelShader* pixel_shader;
        ID3DBlob* result_blob;
        ID3DBlob* error_blob;
        D3DCompileFromFile(L"PixelShader.hlsl", NULL, NULL, "main", "ps_4_0", D3DCOMPILE_DEBUG, 0, amp;result_blob, amp;error_blob);
        device->CreatePixelShader(result_blob->GetBufferPointer(), result_blob->GetBufferSize(), nullptr, amp;pixel_shader);
        device_context->PSSetShader(pixel_shader, nullptr, 0);

        D3DCompileFromFile(L"VertexShader.hlsl", NULL, NULL, "main", "vs_4_0", D3DCOMPILE_DEBUG, 0, amp;result_blob, amp;error_blob);
        
        device->CreateVertexShader(result_blob->GetBufferPointer(), result_blob->GetBufferSize(), nullptr, amp;vertex_shader);

        device_context->VSSetShader(vertex_shader, nullptr, 0);

        ID3D11InputLayout *input_layout;

        D3D11_INPUT_ELEMENT_DESC element_desc[] =
        {
            {"Position", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0}
        };

        device->CreateInputLayout(element_desc, 1, result_blob->GetBufferPointer(), result_blob->GetBufferSize(), amp;input_layout);

        device_context->IASetInputLayout(input_layout);

        result_blob->Release();
        if (error_blob != nullptr) error_blob->Release();


        device_context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

        device_context->OMSetRenderTargets(1u, amp;render_target_view, nullptr);

        D3D11_VIEWPORT vp;
        vp.Width = 800;
        vp.Height = 600;
        vp.MinDepth = 0;
        vp.MaxDepth = 1;
        vp.TopLeftX = 0;
        vp.TopLeftY = 0;
        device_context->RSSetViewports(1u, amp;vp);


        device_context->Draw(3, 0);

        vertex_buffer->Release();
        vertex_shader->Release();
        pixel_shader->Release();
        input_layout->Release();

        swap_chain->Present(1u, 0u);

    }

    ////////////////////////////////////////////////////////////////////////////////

    device->Release();
    device_context->Release();
    swap_chain->Release();
    render_target_view->Release();
 

Это вершинный шейдер (с именем VertexShader.hlsl):

 float4 main(float2 pos : Position) : SV_Position
{
    return float4(pos.x, pos.y, 0.0f, 1.0f);
}
 

И вот пиксельный шейдер (с именем PixelShader.hlsl):

 float4 main() : SV_Target
{
    return float4(0.0f, 1.0f, 0.0f, 1.0f);
}
 

Я ценю любой намек на решение этой проблемы.
Спасибо за помощь.

РЕДАКТИРОВАТЬ Спасибо @IWonderWhatThisAPIDoes за помощь в решении этой проблемы. Решение заключается в изменении координаты вершин на

     Vertex vertices[]{
            { 0.0f, 0.5f},
            { 0.5f,-0.5f},
            {-0.5f, -0.5f}
        };

 

Комментарии:

1. Вы никогда не проверяете HRESULT . Возможно, где-то происходит сбой вызова функции.

2. @IWonderWhatThisAPIDoes Ок, поэтому я попробовал. Я создаю HRESULT и проверяю СБОЙ для функций, которые возвращают HRESULT и отправляют сообщение, но ничего не отображается, просто черное окно

3. Похоже, пришло время для отладки shotgun. Еще две идеи: — Окно окрашено в черный цвет или ваш цвет фона? (т. е. попробуйте установить другой цвет bg и посмотреть, останется ли он черным или будет окрашен в этот цвет) — Я мало что знаю о D3D11 (только изучил D3D12), но вы никогда не устанавливаете явное состояние конвейера. Вы уверены, что это не обязательно / что состояния по умолчанию делают то, что вы хотите?

4. @IWonderWhatThisAPIDoes Окно окрашено в черный ClearRenderTargetView() цвет, и я могу легко изменить цвет. Я думаю, что состояние конвейера — это новая вещь в DirectX 12 (возможно, объект состояния конвейера), которого нет в DirectX 11. Я мало что знаю о DirectX 12

5. Самого объекта состояния конвейера ( ID3D12GraphicsPipelineState если я правильно помню) нет в DX11, так как здесь вам приходится обрабатывать каждый этап конвейера отдельно. Например, есть ID3D11RasterizerState только для растеризатора (может быть то, что вам нужно, учитывая, что треугольника, похоже, просто нет на вашем экране. Хотя на данный момент я предполагаю.)

Ответ №1:

Как отметил @IWonderWhatThisAPIDoes, основной причиной, по которой вы ничего не видите, является «порядок намотки» треугольников из-за отбраковки обратной стороны. Это связано с тем, что вы используете «по умолчанию» DirectX 11 «Объект состояния растеризатора», который следует из документов Microsoft:

Состояние Значение по умолчанию
Режим заполнения Сплошной
CullMode Назад
Передний счетчик против часовой стрелки ЛОЖЬ
DepthBias 0
SlopeScaledDepthBias 0.0f
DepthBiasClamp 0.0f
DepthClipEnable ВЕРНО
ScissorEnable ЛОЖЬ
Возможность множественной выборки ЛОЖЬ
Возможность сглаживания ЛОЖЬ

Вы можете сделать свой треугольник видимым с помощью:

  1. Изменение вершин, чтобы они имели другой порядок намотки
  2. Вы можете создать и установить новый объект RasterizerState с режимом отбраковки D3D11_CULL_FRONT или D3D11_CULL_NONE вместо D3D11_CULL_BACK .
  3. Вы можете создать и установить новый объект RasterizerState с параметром FrontCounterClockwise, равным TRUE, вместо FALSE.

В настоящее время ваш цикл создает и уничтожает буферы, объекты шейдеров, макет ввода для каждого кадра. Вместо этого вы должны повторно использовать их в каждом кадре.

Вам следует взглянуть на набор инструментов DirectX, а также directx-vs-templates.