利用 Direct3D 绘制几何体—10.几何图形辅助结构体

在本书中,我们通过创建一个同时存有顶点缓冲区和索引缓冲区的结构体来方便地定义多个几何体。另外,借此结构体即可将顶点和索引数据置于系统内存之中,以供 CPU 读取。例如,执行拾取(picking)和碰撞检测(collision detection)这样的工作就需要 CPU 来访问几何体数据。再者,该结构体还缓存了顶点缓冲区和索引缓冲区的一些重要属性(例如格式和每个顶点项所占用的字节数),并提供了返回缓冲区视图的方法。当需要定义多个几何体时,我们就使用下面的 MeshGeometry(定义于 d3dUtil.h头文件中)结构体。

cpp 复制代码
// d3dUtil.h 第149行
// 利用 SubmeshGeometry 来定义 MeshGeometry 中存储的单个几何体
// 此结构体适用于将多个几何体数据存于一个顶点缓冲区和一个索引缓冲区的情况
// 它提供了对存于顶点缓冲区和索引缓冲区中的单个几何体进行绘制所需的数据和偏移量,我们可以据此来
// 实现图6.3中所描绘的技术
struct SubmeshGeometry
{
  UINT IndexCount = 0;
  UINT StartIndexLocation = 0;
  INT BaseVertexLocation = 0;

  // 通过此子网格来定义当前 SubmeshGeometry 结构体中所存几何体的包围盒(bounding box)。我们
  // 将在本书的后续章节中使用此数据
  DirectX::BoundingBox Bounds;
};

struct MeshGeometry
{
  // 指定此几何体网格集合的名称,这样我们就能根据此名找到它
  std::string Name;

  // 系统内存中的副本。由于顶点/索引可以是泛型格式(具体格式依用户而定),所以用 Blob 类型来表示
  // 待用户在使用时再将其转换为适当的类型
  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;

  // 与缓冲区相关的数据
  UINT VertexByteStride = 0;
  UINT VertexBufferByteSize = 0;
  DXGI_FORMAT IndexFormat = DXGI_FORMAT_R16_UINT;
  UINT IndexBufferByteSize = 0;

  // 一个 MeshGeometry 结构体能够存储一组顶点/索引缓冲区中的多个几何体
  // 若利用下列容器来定义子网格几何体,我们就能单独地绘制出其中的子网格(单个几何体)
  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;
  }

  // 待数据上传至 GPU 后,我们就能释放这些内存了
  void DisposeUploaders()
  {
    VertexBufferUploader = nullptr;
    IndexBufferUploader = nullptr;
  }
};
相关推荐
序属秋秋秋7 小时前
《Linux系统编程之进程环境》【环境变量】
linux·运维·服务器·c语言·c++·操作系统·系统编程
泽虞7 小时前
《STM32单片机开发》p7
笔记·stm32·单片机·嵌入式硬件
乌萨奇也要立志学C++7 小时前
【洛谷】二分查找专题 告别二分死循环!模板 + 细节 + 实战
c++·算法
brave and determined7 小时前
接口通讯学习(day05):智能手机的内部高速公路:揭秘MIPI CSI与DSI技术
学习·智能手机·软件工程·制造·csi·mipi·dsi
Rock_yzh7 小时前
LeetCode算法刷题——128. 最长连续序列
数据结构·c++·算法·哈希算法
wheeldown7 小时前
【Rokid+CXR-M】基于Rokid CXR-M SDK的博物馆AR导览系统开发全解析
c++·人工智能·ar
FakeOccupational8 小时前
电路笔记(信号):网线能传多少米?网线信号传输距离
开发语言·笔记·php
利刃大大8 小时前
【c++中间件】语音识别SDK && 二次封装
开发语言·c++·中间件·语音识别
晨非辰8 小时前
C++ 波澜壮阔 40 年:从基础I/O到函数重载与引用的完整构建
运维·c++·人工智能·后端·python·深度学习·c++40周年
艾莉丝努力练剑11 小时前
【C++:C++11】C++11新特性深度解析:从可变参数模板到Lambda表达式
c++·stl·c++11·lambda·可变模版参数