本节的代码是 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_binding
和vi_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
是一个顶点的大小,或者是添加到一个指向下一个顶点的指针所需要的数量。
binding
和 binding
成员在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);
请注意,您只能在一个渲染过程内部将顶点缓冲与渲染过程连接在一起;换句话说,在vkCmdBeginRenderPass
和vkCmdEndRenderPass
之间。这实际上告诉GPU在绘制时要使用什么顶点缓冲。
© Copyright 2016 LunarG, Inc