0
votes

I am learning DirectX 11 and trying to render a triangle, but nothing show up except the background color. There is no errors, no warnings. Here is my main file:

while (true)
    {
        while (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) != 0)
        {
            TranslateMessage(&msg);
            DispatchMessage(&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(&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(&vb_data, sizeof(vb_data));
        vb_data.pSysMem = vertices;

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

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

        device_context->IASetVertexBuffers(0, 1, &vertex_buffer, &stride, &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, &result_blob, &error_blob);
        device->CreatePixelShader(result_blob->GetBufferPointer(), result_blob->GetBufferSize(), nullptr, &pixel_shader);
        device_context->PSSetShader(pixel_shader, nullptr, 0);

        D3DCompileFromFile(L"VertexShader.hlsl", NULL, NULL, "main", "vs_4_0", D3DCOMPILE_DEBUG, 0, &result_blob, &error_blob);
        
        device->CreateVertexShader(result_blob->GetBufferPointer(), result_blob->GetBufferSize(), nullptr, &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(), &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, &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, &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();

This is the vertex shader(named VertexShader.hlsl):

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

And here is the pixel shader(named PixelShader.hlsl):

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

I appreciate any hint to solve this. Thank you for helping.

EDIT Thanks @IWonderWhatThisAPIDoes for helping me with this problem. The solution is changing the coordinate of the vertices to

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

1
You never check for HRESULT. Maybe a function call somewhere fails.IWonderWhatThisAPIDoes
@IWonderWhatThisAPIDoes Ok, so I tried it. I create a HRESULT and check FAILED for functions that return HRESULT and MessageBox it but nothing show up, just a black windowProblematic
Looks like it's time for shotgun debugging then. Two more ideas: - Is the window painted black, or your background color? (ie. try setting a different bg color, and see whether it stays black, or gets painted that color) - I don't know much about D3D11 (only learned D3D12), but you never set an explicit pipeline state. Are you sure that is not necessary / that the default states do what you want?IWonderWhatThisAPIDoes
@IWonderWhatThisAPIDoes The window is painted black usingClearRenderTargetView() and I can easily change the color. I think the pipeline state is a new thing in DirectX 12 (Pipeline state object maybe) which DirectX 11 do not have. I don't know much about DirectX 12Problematic
The pipeline state object itself (ID3D12GraphicsPipelineState, if I recall correctly) is not in DX11, as here you have to handle each stage of the pipeline separately. For example, there's a ID3D11RasterizerState solely for the rasterizer (could be what you need, considering the triangle seems to simply be not on your screen. I'm guessing at this point though.)IWonderWhatThisAPIDoes

1 Answers

0
votes

As @IWonderWhatThisAPIDoes noted, the primary reason you see nothing is the 'winding order' of the triangles due to back-face culling. This is because you are using the 'default' DirectX 11 "Rasterizer State object" which is as follows from Microsoft Docs:

State Default Value
FillMode Solid
CullMode Back
FrontCounterClockwise FALSE
DepthBias 0
SlopeScaledDepthBias 0.0f
DepthBiasClamp 0.0f
DepthClipEnable TRUE
ScissorEnable FALSE
MultisampleEnable FALSE
AntialiasedLineEnable FALSE

You can make your triangle visible by:

  1. Changing the vertices so they have a different winding-order

  2. You can create and set a new RasterizerState object with a cull mode of D3D11_CULL_FRONT or D3D11_CULL_NONE instead of D3D11_CULL_BACK.

  3. You can create and set a new RasterizerState object with a FrontCounterClockwise of TRUE instead of FALSE.

Your loop currently creates and destroys the buffers, shaders objects, input layout every frame. You should reuse them each frame instead.

You should take a look at the DirectX Tool Kit as well as directx-vs-templates.