Vulkan教程翻译之十四 创建 Vertex Buffer

原文链接:https://vulkan.lunarg.com/doc/sdk/1.2.131.2/windows/tutorial/html/13-init_vertex_buffer.html

创建 Vertex Buffer

本章节代码文件是 13-init_vertex_buffer.cpp

vertex buffer 是 CPU 和 GPU 都可见的缓冲区,它包含描述你想要渲染的物体网格的顶点数据。一般来说,顶点数据包含位置数据(x,y,z)和可选颜色,法线,或其他信息。像其他 3D API一样,这里的方法是用顶点数据填充缓冲区,然后在绘制操作中传递给 GPU。

创建 Vertex Buffer 对象

创建 vertex buffer 和创建 uniform buffer 几乎是一样的,就像你在 uniform 示例中做过的那样,从创建一个缓冲区对象开始。

VkBufferCreateInfo buf_info = {};
buf_info.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO;
buf_info.pNext = NULL;
buf_info.usage = VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
buf_info.size = sizeof(g_vb_solid_face_colors_Data);
buf_info.queueFamilyIndexCount = 0;
buf_info.pQueueFamilyIndices = NULL;
buf_info.sharingMode = VK_SHARING_MODE_EXCLUSIVE;
buf_info.flags = 0;
res = vkCreateBuffer(info.device, &buf_info, NULL, &info.vertex_buffer.buf);

创建一个 uniform buffer 对象和一个 vertex buffer 对象唯一真正的不同就是 usage 字段的设置。

立方体的数据(g_vb_solid_face_colors_Data)包含了36个顶点,定义了12个三角形,6个立方体面上每个面2个。每个三角形还有关联着表面颜色。你可以检查 cube_data.h 文件来看看实际的数据。

分配 Vertex Buffer 内存

这里也是,步骤和分配 uniform buffer 的步骤很相似。首先查询内存需求,包括考虑到机器限制比如内存对齐。查看示例中的代码就能看到这个过程和 uniform 示例中执行的步骤是很相似的。

把顶点数据存入缓冲区

分配完后,内存就被映射,用顶点数据初始化,再取消映射:

uint8_t *pData;
res = vkMapMemory(info.device, info.vertex_buffer.mem, 0,
                  mem_reqs.size, 0, (void **)&pData);

memcpy(pData, g_vb_solid_face_colors_Data,
       sizeof(g_vb_solid_face_colors_Data));

vkUnmapMemory(info.device, info.vertex_buffer.mem);

作为最后一步,内存被绑定到缓冲区对象上:

res = vkBindBufferMemory(info.device, info.vertex_buffer.buf,
                         info.vertex_buffer.mem, 0);

输入顶点数据的描述

示例按以下顺序排列顶点数据:

struct Vertex {
    float posX, posY, posZ, posW; // Position data
    float r, g, b, a;             // Color
};

你需要创建顶点输入绑定来向GPU描述数据排列顺序。以下的 vi_binding 和 vi_attribs 成员在这里被设置,但是稍后在 subsequent 示例中才被使用作为创建图形管道的一部分。因为你正在看顶点数据格式,最好在这里就了解一下这些代码:

info.vi_binding.binding = 0;
info.vi_binding.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;
info.vi_binding.stride = sizeof(g_vb_solid_face_colors_Data[0]);

info.vi_attribs[0].binding = 0;
info.vi_attribs[0].location = 0;
info.vi_attribs[0].format = VK_FORMAT_R32G32B32A32_SFLOAT;
info.vi_attribs[0].offset = 0;
info.vi_attribs[1].binding = 0;
info.vi_attribs[1].location = 1;
info.vi_attribs[1].format = VK_FORMAT_R32G32B32A32_SFLOAT;
info.vi_attribs[1].offset = 16;

stride 是一个顶点的大小,或者说为获取下一个顶点需要给指针增加的数量。

binding 和 location 成员指向在 GLSL shader 源码里它们各自的值。你可以回顾 shader 示例中的着色器源码来了解对应关系。

即使第一个 attribute 是位置数据,也在attribute 0 的 format 成员中用一个4字节的 float 数据格式来描述它。attribute 1 的 format 更明显是一个颜色格式,因为 atttibute 1 就是颜色。

offset 成员就简单的表明在顶点数据中每个 attribute 在哪里被找到。

绑定 Vertex Buffer 到 Render Pass

你可以先跳过设置 render pass 的大部分代码,因为你会在之后的示例中看到。但是现在,找到绑定 vertex buffer 和 render pass 的代码:

vkCmdBeginRenderPass(info.cmd, &rp_begin, VK_SUBPASS_CONTENTS_INLINE);

vkCmdBindVertexBuffers(info.cmd, 0,             /* Start Binding */
                       1,                       /* Binding Count */
                       &info.vertex_buffer.buf, /* pBuffers */
                       offsets);                /* pOffsets */

vkCmdEndRenderPass(info.cmd);

注意你只能在 render pass 内部将 vertex buffer 和 render pass进行连接;也就是说,在 vkCmdBeginRenderPass 和 vkCmdEndRenderPass 之间录入 command buffer 的时候。这实际上告诉GPU在绘制时使用什么 vertex buffer。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值