我正在学习Direct3D11并且我正在尝试显示一个三角形,我遵循了所有必要的步骤,但没有显示任何内容。 这是我的代码:
#include <Windows.h>
#include <dxgi1_4.h>
#include <d3d11.h>
#include <d3dcompiler.h>
#include "Game.h"
Game *Game::game = nullptr;
Game *Game::GetInstance()
{
if (Game::game == nullptr)
Game::game = new Game();
return game;
}
Game::Game()
{
}
Game::~Game()
{
}
bool Game::Initialize(HINSTANCE hInstance)
{
if (InitializeWindow(hInstance))
return InitializeDirect3D();
return false;
}
bool Game::InitializeWindow(HINSTANCE hInstance)
{
WNDCLASS windowClass = {};
windowClass.hInstance = hInstance;
windowClass.lpfnWndProc = &WndProc;
windowClass.lpszClassName = L"wndClass";
windowClass.lpszMenuName = NULL;
windowClass.style = CS_HREDRAW | CS_VREDRAW;
windowClass.cbClsExtra = 0;
windowClass.cbWndExtra = 0;
windowClass.hCursor = LoadCursor(NULL, IDC_ARROW);
windowClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
windowClass.hbrBackground = (HBRUSH)GetStockObject(GRAY_BRUSH);
RegisterClass(&windowClass);
mWindow = CreateWindow(L"wndClass", L"DirectX 12 Engine", WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, 0, 0, hInstance, 0);
if (!mWindow)
{
MessageBox(0, L"window creation failed", L"ERROR", MB_OK);
return false;
}
ShowWindow(mWindow, SW_SHOW);
UpdateWindow(mWindow);
return true;
}
bool Game::InitializeDirect3D()
{
HRESULT hr;
// create the device and the device context
const D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_11_0 };
D3D_FEATURE_LEVEL featureLevel;
hr = D3D11CreateDevice(nullptr, D3D_DRIVER_TYPE_HARDWARE, 0, D3D11_CREATE_DEVICE_DEBUG, featureLevels, 1, D3D11_SDK_VERSION, &mDevice, &featureLevel, &mDeviceContext);
if (FAILED(hr))
{
MessageBox(mWindow, L"device creation failed", L"ERROR", MB_OK);
return false;
}
if (featureLevel != D3D_FEATURE_LEVEL_11_0)
{
MessageBox(mWindow, L"DirectX 11 not supported", L"ERROR", MB_OK);
return false;
}
// query 4X MSAA support
mDevice->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality);
if (m4xMsaaQuality <= 0)
{
MessageBox(mWindow, L"4X MSAA not supported", L"ERROR", MB_OK);
return false;
}
// describe and create the swap chain
DXGI_MODE_DESC modeDesc = {};
modeDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
modeDesc.Width = mClientWidth;
modeDesc.Height = mClientHeight;
modeDesc.RefreshRate.Denominator = 1;
modeDesc.RefreshRate.Numerator = 60;
modeDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
modeDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
swapChainDesc.BufferDesc = modeDesc;
swapChainDesc.BufferCount = 1;
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.Flags = 0;
swapChainDesc.OutputWindow = mWindow;
swapChainDesc.Windowed = true;
swapChainDesc.SampleDesc.Count = 4;
swapChainDesc.SampleDesc.Quality = m4xMsaaQuality - 1;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
IDXGIDevice *device = nullptr;
mDevice->QueryInterface(IID_PPV_ARGS(&device));
IDXGIAdapter *adapter = nullptr;
device->GetParent(IID_PPV_ARGS(&adapter));
IDXGIFactory *factory = nullptr;
adapter->GetParent(IID_PPV_ARGS(&factory));
hr = factory->CreateSwapChain(mDevice, &swapChainDesc, &mSwapChain);
if (FAILED(hr))
{
MessageBox(mWindow, L"swap chain creation failed", L"ERROR", MB_OK);
return false;
}
device->Release();
adapter->Release();
factory->Release();
// create the render target view
ID3D11Texture2D *texture = nullptr;
mSwapChain->GetBuffer(0, IID_PPV_ARGS(&texture));
mDevice->CreateRenderTargetView(texture, nullptr, &mRenderTargetView);
texture->Release();
// bind render target views to output merger stage of graphics pipeline
mDeviceContext->OMSetRenderTargets(1, &mRenderTargetView, nullptr);
// set the viewport
D3D11_VIEWPORT viewport;
viewport.TopLeftX = 0.0f;
viewport.TopLeftY = 0.0f;
viewport.Width = static_cast<float>(mClientWidth);
viewport.Height = static_cast<float>(mClientHeight);
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
mDeviceContext->RSSetViewports(1, &viewport);
CreateShaders();
CreateBuffers();
CreateInputLayout();
return true;
}
bool Game::CreateShaders()
{
HRESULT hr;
// compile shaders
ID3DBlob *error;
hr = D3DCompileFromFile(L"shaders/VertexShader.hlsl", nullptr, nullptr, "main", "vs_5_0", 0, 0, &mVertexShaderBlob, &error);
if (FAILED(hr))
{
ErrorBox(L"vertex shader compilation failed");
OutputDebugStringA((LPCSTR)error->GetBufferPointer());
return false;
}
hr = D3DCompileFromFile(L"shaders/PixelShader.hlsl", nullptr, nullptr, "main", "ps_5_0", 0, 0, &mPixelShaderBlob, &error);
if (FAILED(hr))
{
ErrorBox(L"pixel shader compilation failed");
OutputDebugStringA((LPCSTR)error->GetBufferPointer());
return false;
}
// create shaders
hr = mDevice->CreateVertexShader(mVertexShaderBlob->GetBufferPointer(), mVertexShaderBlob->GetBufferSize(), nullptr, &mVertexShader);
if (FAILED(hr))
{
ErrorBox(L"vertex shader creation failed");
return false;
}
hr = mDevice->CreatePixelShader(mPixelShaderBlob->GetBufferPointer(), mPixelShaderBlob->GetBufferSize(), nullptr, &mPixelShader);
if (FAILED(hr))
{
ErrorBox(L"pixel shader creation failed");
return false;
}
return true;
}
bool Game::CreateBuffers()
{
HRESULT hr;
// define geometry
struct Vertex
{
float position[3];
};
Vertex vertices[] = {
{-0.5f, -0.5f, 0.0f},
{-0.5f, 0.5f, 0.0f},
{0.5f, 0.0f, 0.0f}
};
// create vertex buffer
D3D11_BUFFER_DESC bufferDesc = {};
bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
bufferDesc.ByteWidth = sizeof vertices;
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
bufferDesc.MiscFlags = 0;
bufferDesc.StructureByteStride = 0;
D3D11_SUBRESOURCE_DATA data = {};
data.pSysMem = vertices;
hr = mDevice->CreateBuffer(&bufferDesc, &data, &mVertexBuffer);
if (FAILED(hr))
{
ErrorBox(L"vertex buffer creation failed");
return false;
}
return true;
}
bool Game::CreateInputLayout()
{
HRESULT hr;
// describe input layout
D3D11_INPUT_ELEMENT_DESC inputLayout[] = {
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
// create input layout
hr = mDevice->CreateInputLayout(inputLayout, 1, mVertexShaderBlob->GetBufferPointer(), mVertexShaderBlob->GetBufferSize(), &mInputLayout);
if (FAILED(hr))
{
ErrorBox(L"input layout creation failed");
return false;
}
return true;
}
int Game::Run()
{
MSG msg;
do
{
if (PeekMessage(&msg, 0, 0, 0, PM_REMOVE) != 0)
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
else
Draw();
} while (msg.message != WM_QUIT);
return (int)msg.wParam;
}
// custom vertex format
struct Vertex
{
float position[3];
unsigned char color[4];
};
void Game::Draw()
{
const float color[] = { 0.0f, 1.0f, 0.0f, 1.0f };
mDeviceContext->ClearRenderTargetView(mRenderTargetView, color);
// set shaders
mDeviceContext->VSSetShader(mVertexShader, nullptr, 0);
mDeviceContext->PSSetShader(mPixelShader, nullptr, 0);
// set vertex buffer
UINT stride = sizeof(Vertex);
UINT offset = 0;
mDeviceContext->IASetVertexBuffers(0, 1, &mVertexBuffer, &stride, &offset);
// set input layout
mDeviceContext->IASetInputLayout(mInputLayout);
// set primitive topology
mDeviceContext->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
// draw
mDeviceContext->Draw(3, 0);
mSwapChain->Present(0, 0);
}
LRESULT CALLBACK Game::GameWndProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam)
{
switch (msg)
{
case WM_LBUTTONDOWN:
MessageBox(mWindow, L"left mouse button clicked", L"CLICK", MB_OK);
return 0;
case WM_RBUTTONDOWN:
MessageBox(mWindow, L"right mouse button clicked", L"CLICK", MB_OK);
return 0;
case WM_CLOSE:
if (MessageBox(mWindow, L"are you sure you want to quit?", L"QUIT", MB_YESNO) == IDYES)
PostQuitMessage(0);
return 0;
default:
return DefWindowProc(window, msg, wParam, lParam);
}
}
LRESULT CALLBACK WndProc(HWND window, UINT msg, WPARAM wParam, LPARAM lParam)
{
return Game::GetInstance()->GameWndProc(window, msg, wParam, lParam);
}
void ErrorBox(wchar_t *message)
{
MessageBox(Game::GetInstance()->mWindow, message, L"ERROR", MB_OK);
}
我的WinMain只调用Game :: Initialize()和Game :: Run()。 顶点着色器仅输出顶点的位置,而像素着色器只绘制白色实心像素片段,但我只得到一个绿色屏幕。
我首先尝试使用DirectX12,但我被API的复杂性吓跑了,所以我转向DirectX11学习如何绘制内容然后我会考虑D3D1(我对SDL和OpenGL很熟悉)我设法用它制作简单的游戏,但我坚持使用DirectX初始化。
答案 0 :(得分:-1)
[翻译] 尝试设置光栅化器状态:
ID3D11RasterizerState* rs = 0;
D3D11_RASTERIZER_DESC r;
r.AntialiasedLineEnable = false;
r.CullMode = D3D11_CULL_BACK;
r.DepthBias = 0;
r.DepthBiasClamp = 0.0f;
r.DepthClipEnable = true;
r.FillMode = D3D11_FILL_MODE::D3D11_FILL_SOLID;
r.FrontCounterClockwise = true;
r.MultisampleEnable = false;
r.ScissorEnable = false;
r.SlopeScaledDepthBias = 0.0f;
/*if (FAILED(*/device->CreateRasterizerState(&r,&rs);
d3dcontext->RSSetState(rs);