C++ Vulkan中的动态顶点缓冲区格式设置
我目前的任务是将OpenGL代码库转换为Vulkan,但现在遇到了一个问题,即该代码如何使用顶点缓冲区,因为它非常动态地改变布局,将其作为一个大的帧数组来处理 为了渲染其动画模型,它设置了一个大缓冲区,其中包含整个模型的所有数据,并调用以下函数进行设置:C++ Vulkan中的动态顶点缓冲区格式设置,c++,opengl,vulkan,opengl-4,C++,Opengl,Vulkan,Opengl 4,我目前的任务是将OpenGL代码库转换为Vulkan,但现在遇到了一个问题,即该代码如何使用顶点缓冲区,因为它非常动态地改变布局,将其作为一个大的帧数组来处理 为了渲染其动画模型,它设置了一个大缓冲区,其中包含整个模型的所有数据,并调用以下函数进行设置: void SetupVertexBufferFormat(unsigned int frame1, unsigned int frame2) { glVertexAttribPointer(PositionAttr, 3, GL_FLO
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) },
};
std::vector bindingDescriptions={
{0,sizeof(顶点),vk::VertexInputRate::eVertex},
{1,sizeof(顶点),vk::VertexInputRate::eVertex}
};
std::vector attributeDescriptions={
{PositionAttr,0,vk::Format::eR32G32B32Sfloat,offsetof(顶点,x)},
{TexcoordAttr,0,vk::Format::er32g32float,offsetof(顶点,u)},
{NormalAttr,0,vk::Format::ea2b1010r10snrompack32,offsetof(顶点,packedNormal)},
{Position2Attr,1,vk::Format::eR32G32B32Sfloat,offsetof(顶点,x)},
{Normal2Attr,1,vk::Format::ea2b1010r10snormpack32,offsetof(顶点,packedNormal)},
};
您似乎将顶点格式与顶点缓冲区绑定混为一谈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) },
};
std::vector bindingDescriptions={
{0,sizeof(顶点),vk::VertexInputRate::eVertex},
{1,sizeof(顶点),vk::VertexInputRate::eVertex}
};
std::vector attributeDescriptions={
{PositionAttr,0,vk::Format::eR32G32B32Sfloat,offsetof(顶点,x)},
{TexcoordAttr,0,vk::Format::er32g32float,offsetof(顶点,u)},
{NormalAttr,0,vk::Format::ea2b1010r10snrompack32,offsetof(顶点,packedNormal)},
{Position2Attr,1,vk::Format::eR32G32B32Sfloat,offsetof(顶点,x)},
{Normal2Attr,1,vk::Format::ea2b1010r10snormpack32,offsetof(顶点,packedNormal)},
};
来扩展杰里科的答案
如果使用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的状态。来扩展杰里科的答案 如果使用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的状态