You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

D3D11三角形渲染失败求助:初始化正常但无画面输出

Direct3D 11 无画面输出问题排查

问题背景

使用Direct3D 11开发三角形渲染程序,采用ComPtr管理COM资源,断点确认所有组件均正常初始化,开启D3D11调试标志未检测到错误或警告,但窗口始终无画面输出。此前已修复OMSetRenderTargets函数设置RTV为null的问题,但核心无渲染画面问题仍未解决,需在200-250行代码内实现正常渲染。

问题根源

  • 窗口类过早注销:创建窗口后立即调用UnregisterClass(wc.lpszClassName, nullptr),导致窗口的消息处理机制失效,渲染循环无法正常执行。
  • 顶点缓冲区数据传递错误:创建顶点缓冲区时,data.pSysMem = &vertices错误传递了数组指针的地址,而非数组本身,导致GPU无法读取正确的顶点数据。
  • 垂直同步可能影响画面刷新:swapchain->Present(1, 0)的第一个参数为1启用垂直同步,在部分环境下可能导致画面无法及时显示,可临时改为0测试,或确保窗口消息循环正常后保留。

修复后的完整代码

C++代码

#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 check(a) if(FAILED(a)) std::cout << "HRES ERROR!" << std::endl;

#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},
};

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(127, 127, 127));
    wc.lpfnWndProc = proc;
    wc.lpszClassName = L"class name";
    
    RegisterClass(&wc);

    RECT wndrect = {
        .left = 0, .top = 0,
        .right = 800, .bottom = 500
    };
    AdjustWindowRect(&wndrect, WS_OVERLAPPEDWINDOW, false);
    int width = wndrect.right - wndrect.left;
    int height = wndrect.bottom - wndrect.top;

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

    Microsoft::WRL::ComPtr<IDXGIFactory1> factory = nullptr; 
    Microsoft::WRL::ComPtr<ID3D11Device> device = nullptr; 
    Microsoft::WRL::ComPtr<ID3D11DeviceContext> context = nullptr; 
    {
        check(CreateDXGIFactory1(IID_PPV_ARGS(&factory)));
        Microsoft::WRL::ComPtr<IDXGIAdapter> adapter = nullptr;
        factory->EnumAdapters(0, adapter.GetAddressOf());
        check(D3D11CreateDevice(adapter.Get(), D3D_DRIVER_TYPE_UNKNOWN, 0, D3D11_CREATE_DEVICE_DEBUG, 0, 0, D3D11_SDK_VERSION, device.GetAddressOf(), 0, context.GetAddressOf()));
        DXGI_ADAPTER_DESC desc; check(adapter->GetDesc(&desc));
        std::wcout << desc.Description << std::endl;
    }

    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;
        }
        check(device->CreateBuffer(&desc, &data, &vertex_buffer));
    }

    Microsoft::WRL::ComPtr<ID3D11VertexShader> vertex_shader = nullptr;
    Microsoft::WRL::ComPtr<ID3DBlob> vs = nullptr; 
    {
        check(D3DCompileFromFile(VSFile, NULL, NULL, "vs_main", "vs_5_0", 0, 0, vs.GetAddressOf(), NULL));
        check(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;
        check(D3DCompileFromFile(FSFile, NULL, NULL, "fs_main", "ps_5_0", 0, 0, ps.GetAddressOf(), errorBlob.GetAddressOf()));
        check(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 = 2;
            desc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
            desc.BufferDesc.RefreshRate = {120, 1};
            desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
        }
                                        
        check(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;
            desc.Texture2D.MipSlice = 0;
        }
        Microsoft::WRL::ComPtr<ID3D11Texture2D> back_buffer = nullptr; 
        check(swapchain->GetBuffer(0, IID_PPV_ARGS(back_buffer.GetAddressOf())));
        check(device->CreateRenderTargetView(back_buffer.Get(), &desc, &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, sizeof(position) , D3D11_INPUT_PER_VERTEX_DATA, 0}
        };
        check(device->CreateInputLayout(desc, ARRAYSIZE(desc), vs->GetBufferPointer(), vs->GetBufferSize(), layout.GetAddressOf()));
    }

    { 
        UINT32 stride = sizeof(vertex); 
        UINT offset = 0;
        context->IASetVertexBuffers(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.GetAddressOf(), 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(0, 0);
    }

    UnregisterClass(wc.lpszClassName, nullptr);
    return 0;
}

HLSL着色器代码(shader.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);
}

内容的提问来源于stack exchange,提问作者unicus

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 03:59:50