首页 > 代码库 > DX12龙书第6章习题

DX12龙书第6章习题

1.

{
        { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0,  D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
        { "TANGENT",  0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
        { "NORMAL",   0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
        { "TEXTURE",  0, DXGI_FORMAT_R32G32_FLOAT,    0, 36, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
        { "TEXTURE",  1, DXGI_FORMAT_R32G32_FLOAT,    0, 44, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
        { "COLOR",    0, DXGI_FORMAT_R8G8B8A8_SINT,   0, 52, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
};

 

2.

先是一些准备性的东西,这样描述不太直觉,但是有利于你找到代码位置。

在BoxApp.cpp的前端,先把这个结构改了:

//struct Vertex
//{
//    XMFLOAT3 Pos;
//    XMFLOAT4 Color;
//};

//change end
struct VPosData
{
    XMFLOAT3 Pos;
};

struct VColorData
{
    XMFLOAT4 Color;
};

然后是 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, 1, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 } //change end
    };

在应用里有一个几何体类MeshGeometry

这个类是用来记录渲染集合体数据的,还有辅助创建buffer的数据和方法,这些都要修改:

//Microsoft::WRL::ComPtr<ID3DBlob> VertexBufferCPU = nullptr;
    //change end
    Microsoft::WRL::ComPtr<ID3DBlob> VertexPosBufferCPU = nullptr;
    Microsoft::WRL::ComPtr<ID3DBlob> VertexColorBufferCPU = nullptr;
//Microsoft::WRL::ComPtr<ID3D12Resource> VertexBufferGPU = nullptr;
    //change end
    Microsoft::WRL::ComPtr<ID3D12Resource> VertexPosBufferGPU = nullptr;
    Microsoft::WRL::ComPtr<ID3D12Resource> VertexColorBufferGPU = nullptr;
//Microsoft::WRL::ComPtr<ID3D12Resource> VertexBufferUploader = nullptr;
    //change end
    Microsoft::WRL::ComPtr<ID3D12Resource> VertexPosBufferUploader = nullptr;
    Microsoft::WRL::ComPtr<ID3D12Resource> VertexColorBufferUploader = nullptr;
// Data about the buffers.
    //UINT VertexByteStride = 0;
    //UINT VertexBufferByteSize = 0;
    //change end
    UINT VertexPosByteStride = 0;
    UINT VertexPosBufferByteSize = 0;
    UINT VertexColorByteStride = 0;
    UINT VertexColorBufferByteSize = 0;

//D3D12_VERTEX_BUFFER_VIEW VertexBufferView()const
    //{
    //    D3D12_VERTEX_BUFFER_VIEW vbv;
    //    vbv.BufferLocation = VertexBufferGPU->GetGPUVirtualAddress();
    //    vbv.StrideInBytes = VertexByteStride;
    //    vbv.SizeInBytes = VertexBufferByteSize;


    //    return vbv;
    //}
    //change end
    D3D12_VERTEX_BUFFER_VIEW VertexPosBufferView()const
    {
        D3D12_VERTEX_BUFFER_VIEW vbv;
        vbv.BufferLocation = VertexPosBufferGPU->GetGPUVirtualAddress();
        vbv.StrideInBytes = VertexPosByteStride;
        vbv.SizeInBytes = VertexPosBufferByteSize;


        return vbv;
    }

    D3D12_VERTEX_BUFFER_VIEW VertexColorBufferView()const
    {
        D3D12_VERTEX_BUFFER_VIEW vbv;
        vbv.BufferLocation = VertexColorBufferGPU->GetGPUVirtualAddress();
        vbv.StrideInBytes = VertexColorByteStride;
        vbv.SizeInBytes = VertexColorBufferByteSize;


        return vbv;
    }
void DisposeUploaders()
    {
        //VertexBufferUploader = nullptr;
        //change end
        VertexPosBufferUploader = nullptr;
        VertexColorBufferUploader = nullptr;

        IndexBufferUploader = nullptr;
    }
这些描述输入数据的结构处理完以后就是渲染流程里的工作了,D3D12创建buffer的时候先是在主存里建一个数据段,用于将来做碰撞检测,拾取一类的功能,然后再在内存里建buffer,而且这个buffer还是很讲究的,它是一个不可以cpu随便修改的内存,那为了保持这个buffer和cpu的隔离,它还要建个中间内存叫做上传缓冲器。那下面就改这三个地方:

这段其实是准备一些基础数据的,给我们说的第二和第三个地方用

//const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
    //change end
    const UINT vpbByteSize = (UINT)verticesPos.size() * sizeof(VPosData);
    const UINT vcbByteSize = (UINT)verticesColor.size() * sizeof(VColorData);

下面一段就是主存的数据段,之所以叫CPUBlob是为了指明它是给CPU用的

//ThrowIfFailed(D3DCreateBlob(vbByteSize, &mBoxGeo->VertexBufferCPU));
    //CopyMemory(mBoxGeo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
    //change end
    ThrowIfFailed(D3DCreateBlob(vpbByteSize, &mBoxGeo->VertexPosBufferCPU));
    CopyMemory(mBoxGeo->VertexPosBufferCPU->GetBufferPointer(), verticesPos.data(), vpbByteSize);
    ThrowIfFailed(D3DCreateBlob(vcbByteSize, &mBoxGeo->VertexColorBufferCPU));
    CopyMemory(mBoxGeo->VertexColorBufferCPU->GetBufferPointer(), verticesColor.data(), vcbByteSize);

下面这段糅合了uploadbuffer和最终的vertexbuffer:

//mBoxGeo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
    //    mCommandList.Get(), vertices.data(), vbByteSize, mBoxGeo->VertexBufferUploader);
    //change end
    mBoxGeo->VertexPosBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
        mCommandList.Get(), verticesPos.data(), vpbByteSize, mBoxGeo->VertexPosBufferUploader);
    mBoxGeo->VertexColorBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
        mCommandList.Get(), verticesColor.data(), vcbByteSize, mBoxGeo->VertexColorBufferUploader);

以上就是构建集合体及其数据的代码,如果你渲染多集合体多物体的话,你还要注意修改那些集合体顶点位置在整个内存中的位置下标:

//mBoxGeo->VertexByteStride = sizeof(Vertex);
    //mBoxGeo->VertexBufferByteSize = vbByteSize;
    //change end
    mBoxGeo->VertexPosByteStride = sizeof(VPosData);
    mBoxGeo->VertexPosBufferByteSize = vpbByteSize;
    mBoxGeo->VertexColorByteStride = sizeof(VColorData);
    mBoxGeo->VertexColorBufferByteSize = vcbByteSize;

然后就到了真正的Draw阶段,将buffer设置到渲染pipleline

//mCommandList->IASetVertexBuffers(0, 1, &mBoxGeo->VertexBufferView());
    //change end
    mCommandList->IASetVertexBuffers(0, 1, &mBoxGeo->VertexPosBufferView());
    mCommandList->IASetVertexBuffers(1, 1, &mBoxGeo->VertexColorBufferView());

以上都准备好以后就输入你们的数据吧,我的数据是hardcore进代码的,非常ugly:

//  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) })
  //  };
    //change end
    std::array<VPosData,8> verticesPos = 
    {
        VPosData({ XMFLOAT3(-1.0f, -1.0f, -1.0f) }),
        VPosData({ XMFLOAT3(-1.0f, +1.0f, -1.0f) }),
        VPosData({ XMFLOAT3(+1.0f, +1.0f, -1.0f) }),
        VPosData({ XMFLOAT3(+1.0f, -1.0f, -1.0f) }),
        VPosData({ XMFLOAT3(-1.0f, -1.0f, +1.0f) }),
        VPosData({ XMFLOAT3(-1.0f, +1.0f, +1.0f) }),
        VPosData({ XMFLOAT3(+1.0f, +1.0f, +1.0f) }),
        VPosData({ XMFLOAT3(+1.0f, -1.0f, +1.0f) })
    };

    std::array<VColorData,8> verticesColor =
    {
        VColorData({ XMFLOAT4(Colors::White) }),
        VColorData({ XMFLOAT4(Colors::Black) }),
        VColorData({ XMFLOAT4(Colors::Red)  }),
        VColorData({ XMFLOAT4(Colors::Green) }),
        VColorData({ XMFLOAT4(Colors::Blue) }),
        VColorData({ XMFLOAT4(Colors::Yellow) }),
        VColorData({ XMFLOAT4(Colors::Cyan)  }),
        VColorData({ XMFLOAT4(Colors::Magenta) })
    };

然后重新编译,运行一下就可以了。

DX12龙书第6章习题