繁体   English   中英

Vulkan中的动态顶点缓冲区格式设置

[英]Dynamic vertex buffer format setup in Vulkan

我目前的任务是将OpenGL代码库转换为Vulkan,但是现在偶然发现了该代码如何使用顶点缓冲区的问题,因为它非常动态地更改布局以将其作为一大堆帧来处理。

为了渲染其动画模型,它设置了一个大缓冲区,其中包含整个模型的所有数据,并调用以下函数进行设置:

void SetupVertexBufferFormat(unsigned int frame1, unsigned int frame2)
{
    glVertexAttribPointer(PositionAttr, 3, GL_FLOAT, false, sizeof(Vertex), &vNull[frame1].x);
    glVertexAttribPointer(TexcoordAttr, 2, GL_FLOAT, false, sizeof(Vertex), &vNull[frame1].u);
    glVertexAttribPointer(Position2Attr, 3, GL_FLOAT, false, sizeof(Vertex), &vNull[frame2].x);
    glVertexAttribPointer(NormalAttr, 4, GL_INT_2_10_10_10_REV, true, sizeof(Vertex), &vNull[frame1].packedNormal);
    glVertexAttribPointer(Normal2Attr, 4, GL_INT_2_10_10_10_REV, true, sizeof(Vertex), &vNull[frame2].packedNormal);
}

在OpenGL上一切都很好,但是在Vulkan上,顶点缓冲区布局是管道对象的一部分! 这意味着移植设置需要每帧创建和销毁多个管道,因为frame1和frame2值可能几乎是随机组合的。

无法执行的操作是更改缓冲区的内容,该内容是由超出限制的前端生成的,因为它仍需要与现有的OpenGL后端一起使用。

有没有解决的办法,还是某些复杂的管道管理是这里唯一的选择?

您似乎正在将顶点格式与顶点缓冲区绑定混淆。 glVertexAttrib在一次调用中将两者结合在一起,但是您似乎具有一个一致的顶点格式,该格式由两个绑定组成,一个具有3个属性,第二个具有2个属性。

看一下有关OpenGL中不同顶点格式的一些教程,并尝试重构GL后端以使用它。 等效的Vulkan管道设置应该更加明显。

与Ratchet的GL调用相对应的Vulkan顶点绑定和属性描述应如下所示

std::vector<vk::VertexInputBindingDescription> bindingDescriptions = { 
    { 0, sizeof(Vertex), vk::VertexInputRate::eVertex },
    { 1, sizeof(Vertex), vk::VertexInputRate::eVertex }
};

std::vector<vk::VertexInputAttributeDescription> attributeDescriptions = {
    { PositionAttr, 0, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, x) },
    { TexcoordAttr, 0, vk::Format::eR32G32Sfloat, offsetof(Vertex, u) },
    { NormalAttr, 0, vk::Format::eA2B10G10R10SnormPack32, offsetof(Vertex, packedNormal) },
    { Position2Attr, 1, vk::Format::eR32G32B32Sfloat, offsetof(Vertex, x) },
    { Normal2Attr, 1, vk::Format::eA2B10G10R10SnormPack32, offsetof(Vertex, packedNormal) },
};

扩展JHerico的答案。

如果您使用与opengl不同的顶点属性,则会得到以下形式:

glVertexAttribFormat( PositionAttr,  3, GL_FLOAT, false, offsetof(Vertex, x));
glVertexAttribBinding(PositionAttr,  1);
glVertexAttribFormat( TexcoordAttr,  2, GL_FLOAT, false, offsetof(Vertex, u));
glVertexAttribBinding(TexcoordAttr,  1);
glVertexAttribFormat( NormalAttr,    4, GL_INT_2_10_10_10_REV, true, offsetof(Vertex, packedNormal));
glVertexAttribBinding(NormalAttr,    1);

glVertexAttribFormat( Position2Attr, 3, GL_FLOAT, false, offsetof(Vertex, x));
glVertexAttribBinding(Position2Attr, 2);
glVertexAttribFormat( Normal2Attr,   4, GL_INT_2_10_10_10_REV, true, offsetof(Vertex, packedNormal));
glVertexAttribBinding(Normal2Attr,   2);

然后在渲染时,将绑定1的偏移设置为帧1的偏移,将绑定2的偏移设置为帧2的偏移。

void SetupVertexBufferFormat(unsigned int frame1, unsigned int frame2) {
    glBindVertexBuffer(1, vbo, &vNull[frame1], sizeof(Vertex));
    glBindVertexBuffer(2, vbo, &vNull[frame2], sizeof(Vertex));
}

您可以直接将其转换为vulkan的状态。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM