- 注意!本文是在下几年前入门期间所写(young and naive),其中许多表述可能不正确,为防止误导,请各位读者仔细鉴别。
用DX12画一个BOX
顶点与输入
可以这样定义顶点
struct Vertex
{
XMFLOAT3 Pos;
XMFLOAT4 Color;
};
需要定义D3D12_INPUT_LAYOUT_DESC来把D3D12_INPUT_ELEMENT_DESC绑定到PSO。
typedef struct D3D12_INPUT_LAYOUT_DESC
{
_Field_size_full_(NumElements) const D3D12_INPUT_ELEMENT_DESC *pInputElementDescs;
UINT NumElements;
} D3D12_INPUT_LAYOUT_DESC;
然后就是为shader声明输入变量的D3D12_INPUT_ELEMENT_DESC
typedef struct D3D12_INPUT_ELEMENT_DESC
{
LPCSTR SemanticName;//变量名字
UINT SemanticIndex;//如果有多个重名的话用这个来区分,如TEXCOORD0和TEXCOORD1,名字都是TEXCOORD,这个index分别是0和1
DXGI_FORMAT Format;
UINT InputSlot;
UINT AlignedByteOffset;//起始点从0开始算,如R32G32B32算12,则下一个变量这个值加12
D3D12_INPUT_CLASSIFICATION InputSlotClass;
UINT InstanceDataStepRate;
} D3D12_INPUT_ELEMENT_DESC;
举个例子,D3D12_INPUT_ELEMENT_DESC数组可以这样定义:
std::vector<D3D12_INPUT_ELEMENT_DESC> mInputLayout =
{
{
"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{
"COLOR", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
};
注意这里用vector的话绑定到PSO的时候要用vector::data()返回首地址。
一般顶点有两种存法,对于静态的mesh,我们把顶点存在default heap里,然后还要一个upload heap来上传顶点,这俩heap都是gpu资源,用CreateCommitedResource创建,但是cpu只对upload heap有写入权限,再提交命令让gpu从upload buffer写入到default buffer,default buffer之后就不再去改动,这样效率更高,但不能改的话就必须是静态的了。对于能动的物体我们只用一个upload buffer来存顶点和indices。书上在d3dUtil里面封装好了一个CreateDefaultBuffer来做这件事。
一个使用例如下:
std::array<Vertex, 8> vertices =
{
Vertex({
XMFLOAT3(-1.0f, -1.0f, -1.0f), XMFLOAT4(Colors::White) }),
Vertex({
XMFLOAT3(-1.0f, +1.0f, -1.0f), XMFLOAT4(Colors::Black) }),
Vertex({
XMFLOAT3(+1.0f, +1.0f, -1.0f), XMFLOAT4(Colors::Red) }),
Vertex({
XMFLOAT3(+1.0f, -1.0f, -1.0f), XMFLOAT4(Colors::Green) }),
Vertex({
XMFLOAT3(-1.0f, -1.0f, +1.0f), XMFLOAT4(Colors::Blue) }),
Vertex({
XMFLOAT3(-1.0f, +1.0f, +1.0f), XMFLOAT4(Colors::Yellow) }),
Vertex({
XMFLOAT3(+1.0f, +1.0f, +1.0f), XMFLOAT4(Colors::Cyan) }),
Vertex({
XMFLOAT3(+1.0f, -1.0f, +1.0f), XMFLOAT4(Colors::Magenta) })
};
mBoxGeo = std::make_unique<MeshGeometry>();
mBoxGeo->Name = "boxGeo";
//mBoxGeo的VertexBufferGPU和VertexBufferUploader在构造的时候都是nullptr
mBoxGeo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
mCommandList.Get(), vertices.data(), vbByteSize, mBoxGeo->VertexBufferUploader);
现在有了VertexBuffer,还要定义VertexBuferView,注意vbv和ibv比较特殊,不需要存在heap里,创建好view之后,要用ID3D12GraphicsCommandList::IASetV