Vulkan 顶点属性Vertex Input Description

文章详细介绍了在Vulkan图形API中,如何通过顶点缓冲区将数据从CPU传递给顶点着色器,包括VkVertexInputBindingDescription和VkVertexInputAttributeDescription的使用,以及如何在shader中定义和访问这些数据。
摘要由CSDN通过智能技术生成

感兴趣可以看看狗蛋的文章https://zhuanlan.zhihu.com/p/450157594

在这里插入图片描述
几乎所有的着色器语言,从CPU向GPU传递数据,大致有两种方式,一种是通过Uniform Buffer,可以看看这篇文章,而另一种传递方式是通过 顶点输入(Vertex Input) 来传递数据

OpenGL和Vulkan中,您可以使用顶点缓冲区来传递数据给顶点着色器。这种方法通常用于传递顶点的位置,法线,纹理坐标,
颜色,顶点的骨骼或关节信息,动画相关的权重,切线向量等

首先,一个最简单的顶点的结构体假设为

struct Vertex 
{
    glm::vec3 pos;
    glm::vec3 color;
}

CPU端给出顶点数据

const std::vector<Vertex> vertices = 
{
    {{0.0f, -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}}
};

在Vulkan,将其传递给顶点着色器,需要两个步骤(两种结构):

1. VertexInput BindingDescription

在 Vulkan 中,图形渲染管线的输入阶段需要知道如何解释顶点数据。VkVertexInputBindingDescription 结构体用于描述顶点数据在缓冲中的排列方式。

binding字段表示缓冲区的索引。pipeline可以绑定多个顶点缓冲,可以创建多个VkVertexInputBindingDescription 来描述这些顶点缓冲,binding 字段是顶点缓冲区的索引,表示这个description是针对哪个缓冲

VkVertexInputBindingDescription bindingDescription{};		
bindingDescription.binding = 0; 							// 顶点缓冲区的索引
bindingDescription.stride = sizeof(Vertex);					// 缓冲区单个顶点结构大小
bindingDescription.inputRate = VK_VERTEX_INPUT_RATE_VERTEX;	// 输入率,可以是每顶点或每实例(_INSTANCE)

在记录渲染指令到指令缓冲的时候,通过 vkCmdBindVertexBuffers 来绑定顶点缓冲。
offset参数指定了顶点属性数据在缓冲中的起始位置的偏移量一般为0

VkDeviceSize offset = 0; 
vkCmdBindVertexBuffers(commandBuffer, 0, 1, &vertexBuffer, &offset);

可以在一个顶点缓冲中存储多个模型的顶点数据。每次绘制不同的模型时,通过适当的偏移量来指定顶点数据的起始位置。这样可以用一个大的顶点缓冲区代替多个小的顶点缓冲区,虽然占用的空间不变,但是这样可以减少顶点缓冲的绑定切换,提高渲染效率。

  • 问题1: 既然一个顶点缓冲存放多个模型的顶点数据,这里vkCmdBindVertexBuffers(.... , offset)指定了一个偏移量,但是vulkan如何知道应该读取多少个顶点呢?
    • 实际上,绘制时的顶点数量是通过 vkCmdDraw(commandBuffer, vertexCount, instanceCount, firstVertex, firstInstance)vkCmdDrawIndexed( commandBuffer, indexCount, instanceCount, firstIndex, vertexOffset, firstInstance) 命令来指定的。
    • vkCmdDraw() 中的firstVertex 参数表示从顶点缓冲的哪个索引开始读取顶点数据。如果在绑定顶点缓冲时指定了偏移量(offset),那么读取的实际位置会是 firstVertex + offset。例如,如果你在绑定顶点缓冲时设置了一个偏移量为 10,然后调用 vkCmdDraw 时 firstVertex 设置为 5,那么实际上 Vulkan 会从顶点缓冲的索引 10 + 5 = 15 的位置开始读取顶点数据。

2. VertexInput AttributeDescription

顶点的属性有多少个,分别是什么格式、偏移量,就需要 VkVertexInputAttributeDescription

std::array<VkVertexInputAttributeDescription, 2> attributeDescriptions{};
// 属性1
attributeDescriptions[0].binding = 0;
attributeDescriptions[0].location = 0;
attributeDescriptions[0].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[0].offset = offsetof(Vertex, pos);	//0
// 属性2
attributeDescriptions[1].binding = 0;
attributeDescriptions[1].location = 1;
attributeDescriptions[1].format = VK_FORMAT_R32G32B32_SFLOAT;
attributeDescriptions[1].offset = offsetof(Vertex, color);	//12

此时,shader就知道每24个字节为一个顶点,前12个字节是属性1,后12个字节是属性2。

在shader中的使用, 这里的location对应于attributeDescription中的location.

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

3. VkPipelineVertexInputStateCreateInfo

上面的两个结构体合成一个VkPipelineVertexInputStateCreateInfo ,在创建管线的时候传递给管线对象,从而让渲染管线了解顶点的状态


VkPipelineVertexInputStateCreateInfo vertexInputInfo = {};
vertexInputInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO;
vertexInputInfo.vertexBindingDescriptionCount = 1; 
vertexInputInfo.vertexAttributeDescriptionCount = static_cast<uint32_t>(attributeDescriptions.size());
vertexInputInfo.pVertexBindingDescriptions = &bindingDescription;
vertexInputInfo.pVertexAttributeDescriptions = attributeDescriptions.data();

VkGraphicsPipelineCreateInfo pipelineCI;
pipelineCI.pInputAssemblyState = &inputAssemblyState;
pipelineCI.pRasterizationState = &rasterizationState;
pipelineCI.pColorBlendState = &colorBlendState;
pipelineCI.pMultisampleState = &multisampleState;
pipelineCI.pViewportState = &viewportState;
pipelineCI.pDepthStencilState = &depthStencilState;
pipelineCI.pDynamicState = &dynamicState;
pipelineCI.stageCount = static_cast<uint32_t>(shaderStages.size());
pipelineCI.pStages = shaderStages.data();
pipelineCI.subpass = 0;
pipelineCI.pVertexInputState = &vertexInputInfo;	/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

宗浩多捞

您的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值