我正在尝试渲染一个简单的三角形,但问题是除了三角形不渲染之外一切正常:
#include <Windows.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#include <DirectXMath.h>
#include <string>
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "d3dcompiler.lib")
using namespace DirectX;
// Vertex shader source code
const std::string vertexShaderSource = R"(
float4 main(float4 pos : POSITION) : SV_Position
{
return pos;
}
)";
// Pixel shader source code
const std::string pixelShaderSource = R"(
float4 main() : SV_Target
{
return float4(0.0f, 1.0f, 0.7f, 1.0f);
}
)";
#define CHECK_HR_ERROR(msg) if (FAILED(hr)) MessageBox(nullptr, msg, L"Error", MB_ICONERROR)
LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
switch (uMsg)
{
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}
int WINAPI WinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPSTR lpCmdLine, _In_ int nCmdShow)
{
// Create the window
const wchar_t* windowClassName = L"DirectX11WindowClass";
const wchar_t* windowTitle = L"DirectX 11 Application";
const int windowWidth = 800;
const int windowHeight = 600;
WNDCLASSEX wcex = {};
wcex.cbSize = sizeof(WNDCLASSEX);
wcex.style = CS_HREDRAW | CS_VREDRAW;
wcex.lpfnWndProc = WindowProc;
wcex.hInstance = hInstance;
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
wcex.lpszClassName = windowClassName;
RegisterClassEx(&wcex);
RECT rc = { 0, 0, windowWidth, windowHeight };
AdjustWindowRect(&rc, WS_OVERLAPPEDWINDOW, false);
HWND hwnd = CreateWindowEx(
0,
windowClassName,
windowTitle,
WS_OVERLAPPEDWINDOW,
CW_USEDEFAULT, CW_USEDEFAULT,
rc.right - rc.left, rc.bottom - rc.top,
nullptr,
nullptr,
hInstance,
nullptr
);
if (!hwnd)
return -1;
ShowWindow(hwnd, nCmdShow);
// Initialize DirectX
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
swapChainDesc.BufferCount = 1;
swapChainDesc.BufferDesc.Width = windowWidth;
swapChainDesc.BufferDesc.Height = windowHeight;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.OutputWindow = hwnd;
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
swapChainDesc.Windowed = true;
ID3D11Device* device = nullptr;
ID3D11DeviceContext* deviceContext = nullptr;
IDXGISwapChain* swapChain = nullptr;
ID3D11RenderTargetView* renderTargetView = nullptr;
HRESULT hr = D3D11CreateDeviceAndSwapChain(
nullptr,
D3D_DRIVER_TYPE_HARDWARE,
nullptr,
0,
nullptr,
0,
D3D11_SDK_VERSION,
&swapChainDesc,
&swapChain,
&device,
nullptr,
&deviceContext
);
CHECK_HR_ERROR(L"failed to create the device, deviceContext and swapChain!");
// Create the render target view
ID3D11Texture2D* backBuffer = nullptr;
hr = swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<LPVOID*>(&backBuffer));
CHECK_HR_ERROR(L"failed to get the back buffer!");
hr = device->CreateRenderTargetView(backBuffer, nullptr, &renderTargetView);
CHECK_HR_ERROR(L"failed to create the render target view!");
backBuffer->Release();
D3D11_VIEWPORT viewport = {};
viewport.Width = static_cast<float>(windowWidth);
viewport.Height = static_cast<float>(windowHeight);
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
deviceContext->RSSetViewports(1, &viewport);
// Set the render target
deviceContext->OMSetRenderTargets(1, &renderTargetView, nullptr);
// Create the vertex buffer
struct VertexType
{
XMFLOAT4 position;
};
VertexType vertices[] =
{
{ XMFLOAT4(-0.5f, -0.5f, 0.0f, 1.0f) },
{ XMFLOAT4(0.5f, -0.5f, 0.0f, 1.0f) },
{ XMFLOAT4(0.0f, 0.5f, 0.0f, 1.0f) }
};
D3D11_BUFFER_DESC vertexBufferDesc = {};
vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
vertexBufferDesc.ByteWidth = sizeof(VertexType) * 3; // sizeof(vertices)
vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
vertexBufferDesc.CPUAccessFlags = 0;
D3D11_SUBRESOURCE_DATA vertexData = {};
vertexData.pSysMem = vertices;
ID3D11Buffer* vertexBuffer = nullptr;
hr = device->CreateBuffer(&vertexBufferDesc, &vertexData, &vertexBuffer);
CHECK_HR_ERROR(L"failed to create the vertex buffer!");
// Set the vertex buffer
UINT stride = sizeof(VertexType);
UINT offset = 0;
deviceContext->IASetVertexBuffers(0, 1, &vertexBuffer, &stride, &offset);
// Set the primitive topology
deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// Create the vertex shader
ID3DBlob* vertexShaderBlob = nullptr;
D3DCompile(vertexShaderSource.c_str(), vertexShaderSource.length(), nullptr, nullptr, nullptr, "main", "vs_4_0", 0, 0, &vertexShaderBlob, nullptr);
CHECK_HR_ERROR(L"failed to compile the vertex shader!");
ID3D11VertexShader* vertexShader = nullptr;
hr = device->CreateVertexShader(vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), nullptr, &vertexShader);
CHECK_HR_ERROR(L"failed to create the vertex shader!");
deviceContext->VSSetShader(vertexShader, nullptr, 0);
D3D11_INPUT_ELEMENT_DESC inputLayoutDesc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0 }
};
ID3D11InputLayout* inputLayout = nullptr;
hr = device->CreateInputLayout(inputLayoutDesc, _countof(inputLayoutDesc), vertexShaderBlob->GetBufferPointer(), vertexShaderBlob->GetBufferSize(), &inputLayout);
CHECK_HR_ERROR(L"failed to create the input layout!");
deviceContext->IASetInputLayout(inputLayout);
// Create the pixel shader
ID3DBlob* pixelShaderBlob = nullptr;
hr = D3DCompile(pixelShaderSource.c_str(), pixelShaderSource.length(), nullptr, nullptr, nullptr, "main", "ps_4_0", 0, 0, &pixelShaderBlob, nullptr);
CHECK_HR_ERROR(L"failed to compile the pixel shader!");
ID3D11PixelShader* pixelShader = nullptr;
hr = device->CreatePixelShader(pixelShaderBlob->GetBufferPointer(), pixelShaderBlob->GetBufferSize(), nullptr, &pixelShader);
CHECK_HR_ERROR(L"failed to create the pixel shader!");
deviceContext->PSSetShader(pixelShader, nullptr, 0);
// Main message loop
MSG msg = {};
while (msg.message != WM_QUIT)
{
if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE))
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
{
// Render the frame
float clearColor[] = { 0.0f, 0.0f, 1.0f, 1.0f };
deviceContext->ClearRenderTargetView(renderTargetView, clearColor);
deviceContext->Draw(3, 0);
swapChain->Present(1, 0);
}
}
// Cleanup
vertexBuffer->Release();
vertexShaderBlob->Release();
vertexShader->Release();
pixelShaderBlob->Release();
pixelShader->Release();
renderTargetView->Release();
swapChain->Release();
deviceContext->Release();
device->Release();
return static_cast<int>(msg.wParam);
}
您无需告诉 DirectX 三角形的顶点索引是什么。对于三角形,您可以按照以下方法修复它:
将其添加到您的初始化代码中:
UINT indices[] =
{
2,1,0 // order is important!
};
D3D11_BUFFER_DESC indexBufferDesc = {};
indexBufferDesc.ByteWidth = sizeof(indices);
indexBufferDesc.Usage = D3D11_USAGE_IMMUTABLE;
indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
D3D11_SUBRESOURCE_DATA indexData = { indices };
ID3D11Buffer* indexBuffer;
hr = device->CreateBuffer(&indexBufferDesc, &indexData, &indexBuffer);
CHECK_HR_ERROR(L"failed to create the index buffer!");
deviceContext->IASetIndexBuffer(indexBuffer, DXGI_FORMAT_R32_UINT, 0);
将您的 Draw 调用替换为以下调用:
deviceContext->DrawIndexed(ARRAYSIZE(indices), 0, 0);
但是您可以保持所有代码和绘制调用不变,只需反转三角形顶点 (0,1,2 => 2,1,0),如下所示:
VertexType vertices[] =
{
{ XMFLOAT4(0.0f, 0.5f, 0.0f, 1.0f) },
{ XMFLOAT4(0.5f, -0.5f, 0.0f, 1.0f) },
{ XMFLOAT4(-0.5f, -0.5f, 0.0f, 1.0f) },
};