d3d11 三角形渲染失败,尽管一切都已正确初始化

问题描述 投票:0回答:1

学习如何使用 d3d11,使用 ComPtrs,没有错误检查是故意的,因为我只是使用断点来查看所有内容是否都被初始化,但没有任何内容被绘制到窗口,调试标志标记没有错误或警告,不要'不知道如何发现问题原因,据我所知一切都很好,只是想在屏幕上看到一个三角形,代码少于 200-250 行,请帮我解决这个问题。

#include <Windows.h>
#include <d3d11_1.h>
#include <wrl/client.h>
#include <d3dcompiler.h>
#pragma comment(lib, "d3dcompiler")
#pragma comment(lib, "d3d11")
#pragma comment(lib, "dxgi")

#define VSFile L"shader.sh"
#define FSFile L"shader.sh"

#include <iostream>
struct position {
    float x, y;
};
struct color {
    float r, g, b;
};

struct vertex {

    position pos;
    color col;

};

const vertex vertices[] = {


    {-1.0f,  1.0f,  0.0f, 1.0f, 0.0f},
    { 1.0f, -1.0f,  0.0f, 0.0f, 1.0f},
    {-1.0f, -1.0f,  1.0f, 0.0f, 0.0f},

};

int other(HINSTANCE hInstance);

LRESULT CALLBACK proc(HWND wnd, UINT msg, WPARAM wpr, LPARAM lpr) {
        switch (msg) {
        case WM_DESTROY: PostQuitMessage(0); break;
        default: return DefWindowProc(wnd, msg, wpr, lpr);
        }
        return 0;
    }
int main()
{
    
    WNDCLASS wc = {};
    wc.hbrBackground = (HBRUSH)CreateSolidBrush(RGB((255/2), (255 / 2), (255 / 2)));
    wc.lpfnWndProc = proc;
    wc.lpszClassName = L"class name";
    
    RegisterClass(&wc);

    HWND hwnd = CreateWindow(wc.lpszClassName, L"window name", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, 800, 500, nullptr, nullptr, nullptr, nullptr);

    UnregisterClass(wc.lpszClassName, nullptr);

    Microsoft::WRL::ComPtr<IDXGIFactory1> factory = nullptr; 
    Microsoft::WRL::ComPtr<ID3D11Device> device = nullptr; 
    Microsoft::WRL::ComPtr<ID3D11DeviceContext> context = nullptr; {

        CreateDXGIFactory1(IID_PPV_ARGS(&factory));
        Microsoft::WRL::ComPtr<IDXGIAdapter> adapter = nullptr;
        factory->EnumAdapters(0, adapter.GetAddressOf());
        D3D11CreateDevice(adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, 0, D3D11_CREATE_DEVICE_DEBUG, 0, 0, D3D11_SDK_VERSION, device.GetAddressOf(), 0, context.GetAddressOf());

    }
    Microsoft::WRL::ComPtr<ID3D11Buffer> vertex_buffer = nullptr; {

        D3D11_BUFFER_DESC desc = {}; {
            desc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
            desc.ByteWidth = sizeof(vertices);
            desc.MiscFlags = 0;
            desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
            desc.StructureByteStride = sizeof(vertex);
            desc.Usage = D3D11_USAGE_DYNAMIC;
        }
        D3D11_SUBRESOURCE_DATA data = {}; {

            data.pSysMem = &vertices;

        }
        device->CreateBuffer(&desc, &data, &vertex_buffer);
    }
    Microsoft::WRL::ComPtr<ID3D11VertexShader> vertex_shader = nullptr;
    Microsoft::WRL::ComPtr<ID3DBlob> vs = nullptr; {

        D3DCompileFromFile(VSFile, NULL, NULL, "vs_main", "vs_5_0", 0, 0, vs.GetAddressOf(), NULL);
        device->CreateVertexShader(vs->GetBufferPointer(), vs->GetBufferSize(), NULL, vertex_shader.GetAddressOf());

    }
    Microsoft::WRL::ComPtr<ID3D11PixelShader> pixel_shader = nullptr; {

        Microsoft::WRL::ComPtr<ID3DBlob> ps = nullptr;
        Microsoft::WRL::ComPtr<ID3DBlob> errorBlob = nullptr;
        HRESULT hr = D3DCompileFromFile(FSFile, NULL, NULL, "fs_main", "ps_5_0", 0, 0, ps.GetAddressOf(), errorBlob.GetAddressOf());
        hr = device->CreatePixelShader(ps->GetBufferPointer(), ps->GetBufferSize(), NULL, pixel_shader.GetAddressOf());
    }
    Microsoft::WRL::ComPtr<IDXGISwapChain> swapchain = nullptr; {

        DXGI_SWAP_CHAIN_DESC desc = {}; {

            desc.Windowed = 1;
            desc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
            desc.OutputWindow = hwnd;
            desc.SampleDesc.Count = 1;
            desc.BufferCount = 3;
            desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
            desc.BufferDesc.RefreshRate = {120, 1};
            desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;

        }

        factory->CreateSwapChain(device.Get(), &desc, swapchain.GetAddressOf());

    }
    Microsoft::WRL::ComPtr <ID3D11RenderTargetView> RTV = nullptr; {

        D3D11_RENDER_TARGET_VIEW_DESC desc = {}; {

            desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
            desc.ViewDimension = D3D11_RTV_DIMENSION_TEXTURE2D;

        }

        Microsoft::WRL::ComPtr<ID3D11Texture2D> back_buffer = nullptr; 
        swapchain->GetBuffer(0, IID_PPV_ARGS(back_buffer.GetAddressOf()));
        device->CreateRenderTargetView(back_buffer.Get(),0, &RTV);

    }
    Microsoft::WRL::ComPtr<ID3D11InputLayout> layout = nullptr; {

        const D3D11_INPUT_ELEMENT_DESC desc[] = {
        
            {"POSITION", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
            {"COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT , D3D11_INPUT_PER_VERTEX_DATA, 0}
        };
        HRESULT hr = device->CreateInputLayout(desc, ARRAYSIZE(desc), vs->GetBufferPointer(), vs->GetBufferSize(), layout.GetAddressOf());
        if(true){}
    }
    { UINT32 stride = sizeof(vertex); UINT offset = 0;
        context->IAGetVertexBuffers(0, 1, vertex_buffer.GetAddressOf(), &stride, &offset);
        context->IASetInputLayout(layout.Get());
        context->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);

        context->VSSetShader(vertex_shader.Get(), NULL, 0);
        context->PSSetShader(pixel_shader.Get(), NULL, 0);
        
        context->OMSetRenderTargets(1, &RTV, nullptr);
    }

    ShowWindow(hwnd, SW_SHOW);

    MSG msg = {};
    while (msg.message != WM_QUIT) {

        if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) {
            TranslateMessage(&msg); DispatchMessageW(&msg);
        }

        RECT winRect;
        GetClientRect(hwnd, &winRect);
        D3D11_VIEWPORT port[] = { 
            {.TopLeftX = 0, .TopLeftY = 0, 
            .Width = (FLOAT)(winRect.right - winRect.left), 
            .Height = (FLOAT)(winRect.bottom - winRect.top), 
            .MinDepth = 0, .MaxDepth = 1 } 
        }; context->RSSetViewports(1, port);

        float clearColor[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
        context->ClearRenderTargetView(RTV.Get(), clearColor);
        context->Draw(3, 0);
        swapchain->Present(1, 0);

    }
    return 0;
}
// the shader (shaders.sh)

// Input structure representing a single vertex
struct VertexInput {
    float2 Position : POSITION;
    float3 Color : COLOR;
};

// Output structure to be passed to the pixel shader
struct VertexOutput {
    float4 Position : SV_POSITION;
    float3 Color : COLOR;
};

// The main vertex shader function
VertexOutput vs_main(VertexInput input) {
    VertexOutput output;

    // Transform the vertex position to clip space
    output.Position = float4(input.Position, 0.0f, 1.0f);

    // Pass the vertex color to the pixel shader
    output.Color = input.Color;

    return output;
}

float4 fs_main(VertexOutput input) : SV_TARGET
{

    return float4(input.Color, 1.0f);

}

编辑:更新,发生错误,OMSetRenderTargets函数将RTV设置为null,但不知道为什么,msdn说如果我“尝试将相同的子资源设置为多个渲染目标插槽”,它将设置为null,我不太知道那是什么。

c++ com directx-11 direct3d
1个回答
0
投票

context->OMSetRenderTargets(1, &RTV, nullptr);

 处的 
Addressof 运算符不会执行您认为的操作。它释放存储的接口并返回一个指向(现在为空)内部指针的指针。当您想要从方法获取接口并覆盖该接口的指针时,应该使用此方法,例如
device->CreateRenderTargetView(back_buffer.Get(),0, &RTV);

这里你应该使用

GetAddressOf
方法返回一个指向内部指针的指针而不释放所持有的接口:

context->OMSetRenderTargets(1, RTV.GetAddressOf(), nullptr);

或在临时数组中存储指针:

::std::array views{RTV.Get()};
context->OMSetRenderTargets(views.size(), views.data(), nullptr);

另外“故意不进行错误检查”是搬起石头砸自己的脚。

© www.soinside.com 2019 - 2024. All rights reserved.