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
相关产品推荐
相关产品推荐

