Vulkan【14】顶点缓冲区

创建顶点缓冲区

本节的代码是 13-init_vertex_buffer.cpp

顶点缓存是一个CPU可见的和GPU可见的缓冲区,它包含了描述您想要呈现的对象(s)的几何图形的顶点数据。一般来说,顶点数据由位置(x、y、z)数据和可选的颜色、法线或其他信息组成。和其他3D api一样,这里的方法是用这个顶点数据填充缓冲区,并在绘制操作期间将其传递给GPU。

创建顶点缓冲区对象

创建一个顶点缓冲几乎等同于创建一个Uniform缓冲区,它首先创建一个缓冲对象,就像在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缓冲区对象和顶点缓冲对象之间的唯一真正区别是usage字段的设置。

立方体数据(g_vb_solid_face_colors_Data)由36个顶点组成,这些顶点定义了12个三角形,每个6个立方体的每个面都有2个。每个三角形也有一个与之相关联的面的颜色。你可以检查cube_data.h文件来查看实际数据。

分配顶点缓冲区内存

同样,这些步骤与分配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_bindingvi_attribs的成员是在这里设置的,但是在随后的“创建图形管线”示例中被使用。但是由于您正在查看顶点数据格式,所以最好在这里检查以下代码:

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是一个顶点的大小,或者是添加到一个指向下一个顶点的指针所需要的数量。

bindingbinding成员在GLSL着色器源代码中引用它们各自的值。您可以在着色器样本中查看着色器源代码以查看对应关系。

第一个属性是位置数据,一个4字节的浮点格式被用来表述 attribute 0的format成员。 attribute 1的format很显然是颜色格式,因此attribute 1指代颜色。

offset成员是在顶点数据中找到每个属性的指示器。

将顶点缓冲绑定到渲染过程

您可以跳过设置渲染过程的大部分代码,因为您将在后面的示例中看到它。但是现在,找到将顶点缓冲绑定到渲染过程的代码:

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);

请注意,您只能在一个渲染过程内部将顶点缓冲与渲染过程连接在一起;换句话说,在vkCmdBeginRenderPassvkCmdEndRenderPass之间。这实际上告诉GPU在绘制时要使用什么顶点缓冲。

© Copyright 2016 LunarG, Inc

你可能感兴趣的:(Vulkan,Vulkan,图形)