D3D12渲染技术之几何辅助结构

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/jxw167/article/details/82697626

我们绘制一个立方体需要一组顶点和索引,将顶点和索引缓冲区组合在一起可以定义一组几何图形的结构, 此外,该结构的顶点和索引数据是在系统内存中的,以便CPU可以读取它, CPU需要访问几何数据以进行拾取和碰撞检测。 每当我们定义几何时,我们使用以下MeshGeometry(在d3dUtil.h中定义)结构。

// Defines a subrange of geometry in a MeshGeometry. This is for when
// multiple geometries are stored in one vertex and index buffer. It
// provides the offsets and data needed to draw a subset of geometry 
// stores in the vertex and index buffers so that we can implement the 
// technique described by Figure 6.3.
struct SubmeshGeometry
{
  UINT IndexCount = 0;
  UINT StartIndexLocation = 0;
  INT BaseVertexLocation = 0;
 
  // Bounding box of the geometry defined by this submesh. 
  / This is used in later chapters of the book.
  DirectX::BoundingBox Bounds;
};
 
struct MeshGeometry
{
  // Give it a name so we can look it up by name.
  std::string Name;
 
  // System memory copies. Use Blobs because the vertex/index format can 
  // be generic.
  // It is up to the client to cast appropriately. 
  Microsoft::WRL::ComPtr<ID3DBlob> VertexBufferCPU = nullptr;
  Microsoft::WRL::ComPtr<ID3DBlob> IndexBufferCPU = nullptr;
 
  Microsoft::WRL::ComPtr<ID3D12Resource> VertexBufferGPU = nullptr;
  Microsoft::WRL::ComPtr<ID3D12Resource> IndexBufferGPU = nullptr;
 
  Microsoft::WRL::ComPtr<ID3D12Resource> VertexBufferUploader = nullptr;
  Microsoft::WRL::ComPtr<ID3D12Resource> IndexBufferUploader = nullptr;
 
  // Data about the buffers.
  UINT VertexByteStride = 0;
  UINT VertexBufferByteSize = 0;
  DXGI_FORMAT IndexFormat = DXGI_FORMAT_R16_UINT;
  UINT IndexBufferByteSize = 0;
 
  // A MeshGeometry may store multiple geometries in one vertex/index 
  // buffer.
  // Use this container to define the Submesh geometries so we can draw
  // the Submeshes individually.
  std::unordered_map<std::string, SubmeshGeometry> DrawArgs;
 
  D3D12_VERTEX_BUFFER_VIEW VertexBufferView()const
  {
    D3D12_VERTEX_BUFFER_VIEW vbv;
    vbv.BufferLocation = VertexBufferGPU->GetGPUVirtualAddress();
    vbv.StrideInBytes = VertexByteStride;
    vbv.SizeInBytes = VertexBufferByteSize;
 
    return vbv;
  }
 
  D3D12_INDEX_BUFFER_VIEW IndexBufferView()const
  {
    D3D12_INDEX_BUFFER_VIEW ibv;
    ibv.BufferLocation = IndexBufferGPU->GetGPUVirtualAddress();
    ibv.Format = IndexFormat;
    ibv.SizeInBytes = IndexBufferByteSize;
 
    return ibv;
  }
 
  // We can free this memory after we finish upload to the GPU.
  void DisposeUploaders()
  {
    VertexBufferUploader = nullptr;
    IndexBufferUploader = nullptr;
  }
};

最后,我们已经介绍了足够的技术点来呈现一个简单的演示,它会生成一个彩色的盒子。 这个例子基本上将我们在前面博客讨论过的所有内容都放到了一个程序中。 读者应该研究代码并参考前面的部分,需要大家理解每一行。 请注意,该程序使用的Shader所在目录是Shaders \ color.hlsl:
这里写图片描述

链接:https://pan.baidu.com/s/1X0Vikf6qGYGPKU-Nwf-wYA 密码:h79q

小结

1、Direct3D中的顶点可以包含除空间位置之外的其他数据, 要创建自定义顶点格式,我们首先定义一个包含我们选择的顶点数据的结构, 一旦我们定义了顶点结构,通过定义输入布局描述(D3D12_INPUT_LAYOUT_DESC)将其描述为Direct3D,该描述是D3D12_INPUT_ELEMENT_DESC元素的数组,以及数组中元素的数量。 D3D12_INPUT_ELEMENT_DESC数组中的每个元素描述并对应顶点结构中的一个组件。 输入布局描述被设置为D3D12_GRAPHICS_PIPELINE_STATE_DESC结构中的字段,其中它成为PSO的一部分,并根据顶点着色器输入签名进行验证。 当PSO是绑定的一部分时,输入布局绑定到IA阶段。
2、为了使GPU能够访问顶点/索引数组,需要将它们放在称为缓冲区的资源中,该资源由ID3D12Resource接口表示。 存储顶点的缓冲区称为顶点缓冲区,存储索引的缓冲区称为索引缓冲区。 通过填写D3D12_RESOURCE_DESC结构然后调用ID3D12Device :: CreateCommittedResource方法来创建缓冲区资源。 顶点缓冲区的视图由D3D12_VERTEX_BUFFER_VIEW结构表示,索引缓冲区的视图由D3D12_INDEX_BUFFER_VIEW结构表示。 顶点缓冲区使用ID3D12GraphicsCommandList :: IASetVertexBuffers方法绑定到IA阶段,索引缓冲区使用ID3D12GraphicsCommandList :: IASetIndexBuffer方法绑定到IA阶段。 可以使用ID3D12GraphicsCommandList :: DrawInstanced绘制非索引几何体,并且可以使用ID3D12GraphicsCommandList :: DrawIndexedInstanced绘制索引几何体。
3、顶点着色器是用HLSL编写的程序,在GPU上执行,输入顶点并输出顶点, 每个绘制的顶点都通过顶点着色器。 这使程序员能够在每个顶点的基础上进行专门的工作,以实现各种渲染效果, 从顶点着色器输出的值将传递到管道中的下一个阶段。
4、常量缓冲区是GPU资源(ID3D12Resource),其数据内容可以在着色器程序中引用。 它们是在上传堆而不是默认堆中创建的,因此应用程序可以通过将系统内存复制到GPU内存来更新常量缓冲区数据。 通过这种方式,C ++应用程序可以与着色器通信并更新着色器使用的常量缓冲区中的值; 例如,C ++应用程序可以更改着色器使用的世界视图投影矩阵。 一般建议是根据需要更新其内容的频率创建常量缓冲区。 将常数缓冲区分开的动机是效率。 更新常量缓冲区时,必须更新其所有变量; 因此,基于其更新频率对它们进行分组以最小化冗余更新是有效的。
5、像素着色器是在HLSL中编写的程序,在GPU上执行,其输入内插顶点数据并输出颜色值。 作为硬件优化,在将像素片段设置到像素着色器之前,可能会使管道拒绝像素片段。 像素着色器使程序员能够基于每个像素进行专门的工作,以实现各种渲染效果, 像素着色器输出的值将传递到管道中的下一个阶段。
6、控制图形管道状态的大多数Direct3D对象被指定称为管道状态对象(PSO)的聚合,它由ID3D12PipelineState接口表示。 我们将所有这些对象指定为图形管道的聚合以提高性能, 通过将它们指定为聚合,Direct3D可以验证所有状态是否兼容,并且驱动程序可以预先生成所有代码以编程硬件状态。

猜你喜欢

转载自blog.csdn.net/jxw167/article/details/82697626
今日推荐