我正在学习 DirectX 11,我正在尝试渲染一个简单的立方体,不幸的是我的代码不起作用,它根本没有渲染任何内容......没有错误,没有警告......唯一显示的是窗口具有指定的清晰颜色。我也非常确定代码已完全执行。
这是我的专业课的标题:
#pragma once
#include "DirectxApp.h"
#include <DirectXMath.h>
#include "DirectxUtils.h"
struct Vertex
{
DirectX::XMFLOAT3 Position;
DirectX::XMFLOAT4 Color;
};
struct TransformationMatrix
{
DirectX::XMMATRIX worldViewProjMatrix;
};
class MyDirectxApp : public DirectxApp
{
private:
ID3D11Buffer* m_vertexBuffer;
ID3D11Buffer* m_indexBuffer;
ID3D11Buffer* m_worldViewProjBuffer;
ID3D11RasterizerState* m_rasterizerState;
ID3D11InputLayout* m_inputLayout;
ID3D11VertexShader* m_vertexShader;
ID3D11PixelShader* m_pixelShader;
DirectX::XMMATRIX m_worldMatrix;
DirectX::XMMATRIX m_viewMatrix;
DirectX::XMMATRIX m_projMatrix;
TransformationMatrix m_transformationMatrix;
float m_theta;
float m_phi;
float m_radius;
public:
MyDirectxApp(HINSTANCE hInstance,
int width,
int height,
LPWSTR windowName = L"",
bool enable4xMsaa = true,
int xCoord = CW_USEDEFAULT,
int yCoord = CW_USEDEFAULT
);
virtual bool Init();
virtual void OnFrame();
virtual ~MyDirectxApp(void);
};
而这就是cpp(超类的init方法初始化窗口和DirectX的基本组件,见后文):
#include "MyDirectxApp.h"
using namespace DirectX;
MyDirectxApp::MyDirectxApp(HINSTANCE hInstance,
int width,
int height,
LPWSTR windowName,
bool enable4xMsaa,
int xCoord,
int yCoord
) : DirectxApp(hInstance, width, height, windowName, enable4xMsaa, xCoord, yCoord)
{
m_vertexBuffer = 0;
m_indexBuffer = 0;
m_inputLayout = 0;
m_rasterizerState = 0;
m_vertexShader = 0;
m_pixelShader = 0;
m_worldViewProjBuffer = 0;
XMMATRIX matrixIdentity = XMMatrixIdentity();
m_worldMatrix = matrixIdentity;
m_viewMatrix = matrixIdentity;
m_projMatrix = matrixIdentity;
m_transformationMatrix.worldViewProjMatrix = matrixIdentity;
m_theta = 1.5f * DirectX::XM_PI;
m_phi = 0.25f* DirectX::XM_PI;
m_radius = 5.0f;
}
bool MyDirectxApp::Init()
{
if(!DirectxApp::Init())
{
return false;
}
HRESULT hResult;
//////////////////////////////////////
// CreateVertexBuffer
//////////////////////////////////////
Vertex cubeVertexArray[] = {
// Position Color
{XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f)}, //white
{XMFLOAT3(-1.0f, +1.0f, -1.0f), XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f)}, //black
{XMFLOAT3(+1.0f, +1.0f, -1.0f), XMFLOAT4(1.0f, 0.0f, 0.0f, 1.0f)}, //red
{XMFLOAT3(+1.0f, -1.0f, -1.0f), XMFLOAT4(0.0f, 1.0f, 0.0f, 1.0f)}, //green
{XMFLOAT3(-1.0f, -1.0f, +1.0f), XMFLOAT4(0.0f, 0.0f, 1.0f, 1.0f)}, //blue
{XMFLOAT3(-1.0f, +1.0f, +1.0f), XMFLOAT4(1.0f, 1.0f, 0.0f, 1.0f)}, //yellow
{XMFLOAT3(+1.0f, +1.0f, +1.0f), XMFLOAT4(0.0f, 1.0f, 1.0f, 1.0f)}, //cyan
{XMFLOAT3(+1.0f, -1.0f, +1.0f), XMFLOAT4(1.0f, 0.0f, 1.0f, 1.0f)} //magenta
};
hResult = DirectxUtils::CreateVertexBuffer(m_d3dDevice, &cubeVertexArray, sizeof(cubeVertexArray), &m_vertexBuffer);
if (FAILED(hResult))
{
MessageBox(0, L"CreateVertexBuffer FAILED", 0, 0);
return false;
}
//////////////////////////////////////
// CreateIndexBuffer
//////////////////////////////////////
UINT indices[] = {
0, 1, 2, // front face
0, 2, 3,
4, 6, 5, // back face
4, 7, 6,
4, 5, 1, // left face
4, 1, 0,
3, 2, 6, // right face
3, 6, 7,
1, 5, 6, // top face
1, 6, 2,
4, 0, 3, // bottom face
4, 3, 7
};
hResult = DirectxUtils::CreateIndexBuffer(m_d3dDevice, &indices, sizeof(indices), &m_indexBuffer);
if (FAILED(hResult))
{
MessageBox(0, L"CreateIndexBuffer FAILED", 0, 0);
return false;
}
//////////////////////////////////////
// CreateVertexShader
//////////////////////////////////////
D3D11_INPUT_ELEMENT_DESC inputLayoutDesc[] = {
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT , 0, 0, D3D11_INPUT_PER_VERTEX_DATA, 0},
{"COLOR" , 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D11_INPUT_PER_VERTEX_DATA, 0},
};
hResult = DirectxUtils::CreateVertexShader(m_d3dDevice, L"VertexShader.hlsl", "main", inputLayoutDesc, 2, &m_vertexShader, &m_inputLayout);
if (FAILED(hResult))
{
MessageBox(0, L"CreateVertexShader FAILED", 0, 0);
return false;
}
//////////////////////////////////////
// CreatePixelShader
//////////////////////////////////////
hResult = DirectxUtils::CreatePixelShader(m_d3dDevice, L"PixelShader.hlsl", "main", &m_pixelShader);
if (FAILED(hResult))
{
MessageBox(0, L"CreatePixelShader FAILED", 0, 0);
return false;
}
//////////////////////////////////////
// create world\view\proj matrix
//////////////////////////////////////
XMVECTOR cameraPos = XMVectorSet(0.0f, 3.0f, -5.0f, 1.0f);
XMVECTOR cameraTarget = XMVectorZero();
XMVECTOR cameraUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
m_worldMatrix = XMMatrixIdentity();
m_projMatrix = XMMatrixPerspectiveFovLH(XMConvertToRadians(45.0f), AspectRatio(), 0.1f, 100.0f);
m_viewMatrix = XMMatrixLookAtLH(cameraPos, cameraTarget, cameraUp);
hResult = DirectxUtils::CreateConstantBuffer(m_d3dDevice, sizeof(TransformationMatrix), &m_worldViewProjBuffer);
if (FAILED(hResult))
{
MessageBox(0, L"CreateConstantBuffer FAILED", 0, 0);
return false;
}
//////////////////////////////////////
// CreateRasterizerState
//////////////////////////////////////
D3D11_RASTERIZER_DESC rasterizerDesc;
rasterizerDesc.FillMode = D3D11_FILL_SOLID;
rasterizerDesc.CullMode = D3D11_CULL_BACK;
rasterizerDesc.FrontCounterClockwise = false;
rasterizerDesc.DepthClipEnable = true;
hResult = m_d3dDevice->CreateRasterizerState(&rasterizerDesc, &m_rasterizerState);
if (FAILED(hResult))
{
MessageBox(0, L"CreateRasterizerState FAILED", 0, 0);
return false;
}
return true;
}
void MyDirectxApp::OnFrame()
{
///////////////////////////////////
// update worldViewProj matrix
///////////////////////////////////
XMVECTOR cameraPos = XMVectorSet(0.0f, 3.0f, -5.0f, 1.0f);
XMVECTOR cameraTarget = XMVectorZero();
XMVECTOR cameraUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
m_viewMatrix = XMMatrixLookAtLH(cameraPos, cameraTarget, cameraUp);
m_transformationMatrix.worldViewProjMatrix = m_worldMatrix * m_viewMatrix * m_projMatrix;
///////////////////////////////////
// drawing
///////////////////////////////////
static const FLOAT clearColor[4] = {0.0f, 0.0f, 0.0f, 0.0f};
m_d3dDeviceContext->OMSetRenderTargets(1, &m_renderTargetView, m_depthStencilBufferView);
m_d3dDeviceContext->ClearRenderTargetView(m_renderTargetView, clearColor);
m_d3dDeviceContext->ClearDepthStencilView(m_depthStencilBufferView, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, 1.0f, 0);
m_d3dDeviceContext->IASetInputLayout(m_inputLayout);
m_d3dDeviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
UINT stride = sizeof(Vertex);
UINT offset = 0;
m_d3dDeviceContext->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset);
m_d3dDeviceContext->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
m_d3dDeviceContext->VSSetShader(m_vertexShader, nullptr, 0);
m_d3dDeviceContext->PSSetShader(m_pixelShader, nullptr, 0);
m_d3dDeviceContext->RSSetState(m_rasterizerState);
m_d3dDeviceContext->UpdateSubresource(m_worldViewProjBuffer, 0, nullptr, &m_transformationMatrix, 0, 0);
m_d3dDeviceContext->VSSetConstantBuffers(0, 1, &m_worldViewProjBuffer);
m_d3dDeviceContext->DrawIndexed(36, 0, 0);
m_swapChain->Present(0, 0);
}
MyDirectxApp::~MyDirectxApp(void)
{
m_vertexBuffer->Release();
m_indexBuffer->Release();
m_inputLayout->Release();
m_rasterizerState->Release();
m_vertexShader->Release();
m_pixelShader->Release();
m_worldViewProjBuffer->Release();
}
VertexShader真的很简单,它只做世界观投影转换:
cbuffer cbPerObject
{
float4x4 worldViewProjection;
};
//input data structure
struct VertexInput
{
float3 iPosition : POSITION;
float4 iColor : COLOR;
};
//output data
struct VertexOutput
{
float4 oPosition : SV_POSITION; //system-value-position is a special semantic name
float4 oColor : COLOR;
};
VertexOutput main(VertexInput vertexInput)
{
VertexOutput vertexOutput;
//transform world-view-projection
vertexOutput.oPosition = mul(float4(vertexInput.iPosition, 1.0f), worldViewProjection);
vertexOutput.oColor = vertexInput.iColor;
return vertexOutput;
}
PixelShader更简单:
//input data structure
//must match the vertexShader output
struct PixelShaderInput
{
float4 iPosition : SV_POSITION;
float4 iColor : COLOR;
};
float4 main(PixelShaderInput pixelShaderInput) : SV_TARGET //system-value-target means the output must match the renderTarget format
{
return pixelShaderInput.iColor;
}
如上所述,Directx 的基本组件是由超类(DirectxApp)创建的,代码如下:
bool DirectxApp::InitDirectx()
{
//////////////////////////////////////
// device creation
//////////////////////////////////////
UINT creationDeviceFlags = 0;
#if defined(DEBUG)
creationDeviceFlags = D3D11_CREATE_DEVICE_DEBUG;
#endif
D3D_FEATURE_LEVEL featureLevel;
HRESULT hResult = D3D11CreateDevice(0, //display adapter
D3D_DRIVER_TYPE_HARDWARE, //drier type
0, //software driver
creationDeviceFlags, //device flag
0, //array of feature levels (NULL means choose the greatest)
0, //number of feature levels
D3D11_SDK_VERSION, //sdk version
&m_d3dDevice,
&featureLevel,
&m_d3dDeviceContext);
if (FAILED(hResult))
{
MessageBox(0, L"D3D11CreateDevice FAILED", 0, 0);
return false;
}
if (featureLevel != D3D_FEATURE_LEVEL_11_0)
{
MessageBox(0, L"D3D_FEATURE_LEVEL_11_0 not supported", 0, 0);
return false;
}
//////////////////////////////////////
// check 4xMSAA
//////////////////////////////////////
UINT m4xMsaaQuality;
m_d3dDevice->CheckMultisampleQualityLevels(DXGI_FORMAT_R8G8B8A8_UNORM, 4, &m4xMsaaQuality);
assert(m4xMsaaQuality > 0); //m4xMsaaQuality is always > 0
//////////////////////////////////////
// swap chain creation
//////////////////////////////////////
DXGI_SWAP_CHAIN_DESC swapChainDesc;
swapChainDesc.BufferDesc.Width = m_windowWidth;
swapChainDesc.BufferDesc.Height = m_windowHeight;
swapChainDesc.BufferDesc.RefreshRate.Numerator = 60;
swapChainDesc.BufferDesc.RefreshRate.Denominator = 1;
swapChainDesc.BufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
swapChainDesc.BufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
swapChainDesc.BufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
if (m_enable4xMsaa)
{
swapChainDesc.SampleDesc.Count = 4;
swapChainDesc.SampleDesc.Quality = m4xMsaaQuality -1;
}
else
{
swapChainDesc.SampleDesc.Count = 1;
swapChainDesc.SampleDesc.Quality = 0;
}
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
swapChainDesc.BufferCount = 1; //means double buffering
swapChainDesc.OutputWindow = m_mainWindow;
swapChainDesc.Windowed = true;
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
swapChainDesc.Flags = 0;
IDXGIDevice* dxgiDevice = 0;
m_d3dDevice->QueryInterface(__uuidof(IDXGIDevice), reinterpret_cast<void**>(&dxgiDevice));
IDXGIAdapter* dxgiAdapter = 0;
dxgiDevice->GetParent(__uuidof(IDXGIAdapter), reinterpret_cast<void**>(&dxgiAdapter));
IDXGIFactory* dxgiFactory = 0;
dxgiAdapter->GetParent(__uuidof(IDXGIFactory), reinterpret_cast<void**>(&dxgiFactory));
HRESULT hResultSwapChain = dxgiFactory->CreateSwapChain(m_d3dDevice, &swapChainDesc, &m_swapChain);
dxgiDevice->Release();
dxgiAdapter->Release();
dxgiFactory->Release();
if (FAILED(hResultSwapChain))
{
MessageBox(0, L"CreateSwapChain FAILED", 0, 0);
return false;
}
//////////////////////////////////////
// render target creation
//////////////////////////////////////
ID3D11Texture2D* backBufferTexture2D = 0;
m_swapChain->GetBuffer(0, __uuidof(ID3D11Texture2D), reinterpret_cast<void**>(&backBufferTexture2D));
HRESULT hResultRenderTarget = m_d3dDevice->CreateRenderTargetView(backBufferTexture2D, 0, &m_renderTargetView);
backBufferTexture2D->Release();
if (FAILED(hResultRenderTarget))
{
MessageBox(0, L"CreateRenderTargetView FAILED", 0, 0);
return false;
}
//////////////////////////////////////
// depth-stencil buffer creation
//////////////////////////////////////
D3D11_TEXTURE2D_DESC depthStencilBufferTexture2D;
depthStencilBufferTexture2D.Width = m_windowWidth;
depthStencilBufferTexture2D.Height = m_windowHeight;
depthStencilBufferTexture2D.MipLevels = 1;
depthStencilBufferTexture2D.ArraySize = 1;
depthStencilBufferTexture2D.Format = DXGI_FORMAT_D24_UNORM_S8_UINT;
if (m_enable4xMsaa)
{
depthStencilBufferTexture2D.SampleDesc.Count = 4;
depthStencilBufferTexture2D.SampleDesc.Quality = m4xMsaaQuality -1;
}
else
{
depthStencilBufferTexture2D.SampleDesc.Count = 1;
depthStencilBufferTexture2D.SampleDesc.Quality = 0;
}
depthStencilBufferTexture2D.Usage = D3D11_USAGE_DEFAULT;
depthStencilBufferTexture2D.BindFlags = D3D11_BIND_DEPTH_STENCIL;
depthStencilBufferTexture2D.CPUAccessFlags = 0;
depthStencilBufferTexture2D.MiscFlags = 0;
HRESULT hResultDepthStencil = m_d3dDevice->CreateTexture2D(&depthStencilBufferTexture2D, 0, &m_depthStencilBufferTexture2D);
if (FAILED(hResultDepthStencil))
{
MessageBox(0, L"CreateTexture2D depthStencil FAILED", 0, 0);
return false;
}
HRESULT hResultDepthStencilView = m_d3dDevice->CreateDepthStencilView(m_depthStencilBufferTexture2D, 0, &m_depthStencilBufferView);
if (FAILED(hResultDepthStencilView))
{
MessageBox(0, L"CreateDepthStencilView FAILED", 0, 0);
return false;
}
//////////////////////////////////////
// viewport creation
//////////////////////////////////////
D3D11_VIEWPORT viewport;
viewport.TopLeftX = 0;
viewport.TopLeftY = 0;
viewport.Width = float(m_windowWidth);
viewport.Height = float(m_windowHeight);
viewport.MinDepth = 0.0f;
viewport.MaxDepth = 1.0f;
m_d3dDeviceContext->RSSetViewports(1, &viewport);
return true;
}
我很感激任何解决这个问题的提示!
提前致谢
编辑
到渲染管道只到达一个三角形,执行 VertexShader 但不执行 PixelShader,然后死掉......