Vulkan顶点输入

顶点着色器:
我们将会使用内存顶点缓冲区来替换顶点着色器中的数据,接下来我们将会从最简单的方法开始创建一个CPU可见的缓冲区,并使用memcpy将顶点数据直接复制到缓冲区,之后将会使用暂存缓冲区将顶点数据赋值到高性能的内存。
首先要修改的是顶点着色器,不再包含顶点数据。顶点着色器接受顶点缓冲区的输入使用in关键字。

#version 300
#extension GL_ARB_separate_shader_objects:enable

layout(location=0) in vec2 inPosition;
layout(location=1) in vec3 inColor;

layout(location=0) out vec3 fragColor;

out gl_PerVertex{
vec4 gl_Position;
};

void mian(){
gl_Position =vec4(inPosition,0.0,1.0);
fragColor =inColor;
}
inPosition和inColor变量是顶点属性,它们被顶点缓冲区中的每一个顶点指定,就像我们使用两个数组手动指定每个顶点的position和color一样。现在确保着色器被正确的编译。

顶点数据:
我们将顶点数组从着色器代码移植到自定义的程序中的数组中,首先需要引入GLM库,它提供了如向量和矩阵之类的线性代数数据结构,我们使用这些类型指定position和color。
#include <glm/glm.hpp>
建立新的数据结构Vertex并定义两个属性,我们将会在顶点着色器内部使用:
struct Vertex{
glm::vec2 pos;
glm::vec3 color;
};
GLM提供了与C++类型匹配的可以在着色器中使用的矢量类型:
const std::vector vertices ={
{{0.5f,-0.5f},{1.0f,0.0f,0.0f}},
{{0.5f,0.5f},{0.0f,1.0f,0.0f}},
{-0.5f,0.5f},{0.0f,0.0f,1.0f}}
};
现在使用Vertex结构体作为顶点数组的元素类型,我们使用与之前完全相同的position和color值,但是现在它们被组合成一个顶点数组,这称为interleaving顶点属性。

绑定描述:
一旦数据被提交到GPU的显存中,就需要告诉Vulkan传递到顶点着色器中数据的格式,有两个结构体用于描述这部分信息:
struct Vertex{
glm::vec2 pos;
glm::vec3 color;

static VkVertexInputBindingDescription getBindingDescription(){
VkVertexInputBindingDescription bindingDescription ={};
return bindingDescription;
}
};
顶点绑定描述了在整个顶点数据从内存加载的速率,换句话说,它指定数据条目之间的间隔字节数以及是否每个顶点之后或者每个instace之后移动到下一个条目。
VkVertexInputBindingDescription bindingDescription ={};
bindingDescription.binding =0;
bindingDescription.stride =sizeof(Vertex);
bindingDescription.inputRate =VK_VERTEX_INPUT_RATE_VERTEX;
所有的顶点数据都被打包在一个数组中,所以我们需要一个绑定,binding的参数指定了数组中对应的绑定索引,stride参数指定一个条目到下一个条目的字节数,inputRate参数可以具备:
VK_VERTEX_INPUT_RATE_VERTEX:移动到每个顶点后的下一个数据条目;
VK_VERTEX_INPUT_RATE_INSTANCE:在每个instance之后移动到下一个数据条目

属性描述:
在Vertex中增加一个新的辅助函数:
#include
static std::array<VkVertexInputAttributeDescription,2>getAttributeDescriptions(){
std::array<VkVertexInputAttributeDescription,2>attributeDescriptions ={};
return attributeDescriptions;
}
一个属性描述结构体最终描述了顶点属性如何从对应的绑定描述过的顶点数据来解析数据。我们有两个属性,position和color,所以我们需要两个属性描述结构体。
attributeDescriptions[0].binding =0;
attributeDescriptions[0].location=0;
attributeDescriptions[0].format =VK_FORMAT_R32G32_SFLOAT;
attributeDescriptions[0].offset =offsetof(Vertex,pos);
binding参数告诉了Vulkan每个顶点数据的来源,location参数引用了vertex shader作为输入的location指令,顶点着色器中location为0代表position,它是32bit单精度数据。format参数描述了属性的类型。

管线顶点输入:
在createGraphicsPipeline函数中,配置图形管线可以接受重新定义的顶点数据的格式,找到vertexInputInfo结构体,修改引用之前定义的两个有关输入顶点的description结构体:
auto bindingDescription =Vertex::getBindingDescription();
auto attributeDescription =Vertex::getAttributeDescriptions();

扫描二维码关注公众号,回复: 9437196 查看本文章

vertexInputInfo.vertexBingdingDescriptionCount =1;
vertexInputInfo.vertexAttributeDescriptionCount =static_cast<uint32_t>(attributeDescriptions.size());
vertexInputInfo.pVertexBindingDescriptions =&bindingDescription;
vertexxInputInfo.pVertexAttributeDescriptions =attributeDescriptions.data();
图形管线准备接收vertices容器封装后的顶点数据,并将该格式的顶点数据传递到vertex shader,如果开启了validation layers,将会发现无顶点缓冲区绑定的提示。

发布了146 篇原创文章 · 获赞 28 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/weixin_38498942/article/details/103911471