OpenGL顶点缓冲区对象的动态打包数据

Posted

技术标签:

【中文标题】OpenGL顶点缓冲区对象的动态打包数据【英文标题】:Dynamically Packing Data for Vertex Buffer Objects of OpenGL 【发布时间】:2013-10-16 05:55:28 【问题描述】:

我正在尝试在 OOP 中为 VBO 编写一个包装器,它由 addVertex、addNormal..addX、flush() 和 render() 函数组成。起初,我将顶点、法线、索引保存在单独的向量中,例如:

std::vector<glm::vec4> vertexBuffer;
std::vector<glm::vec4> colorBuffer;
std::vector<glm::vec3> normalBuffer;
std::vector<glm::vec2> texCoordBuffer;
std::vector<unsigned int> indexBuffer;

但是当我在某处读到时,为每个人保存不同的 VBO ID 是完全低效的,因此最好将它们按 VertexNormalTexCoordColor - VNTC - VNTC... 的顺序打包,并在单个 VBO ID 中表示它们。因此,缓冲区在上传到 GPU 时可以有效地使用。所以这次我仍然将它们保存在向量中,但是当我调用 flush() 时,我想用结构体打包它们,然后将该结构体向量上传到 GPU:

struct VBOData 
    glm::vec4 vert;
    glm::vec3 normal;
    glm::vec4 color;
    glm::vec2 texcoord;
;
std::vector<VBOData> vboBuffer;

然后我在 flush() 中上传所有内容:

vboBuffer.reserve(vertexBuffer.size());

for (int i = 0; i < vertexBuffer.size(); ++i) 
    VBOData data;
    data.vert = vertexBuffer[i];
    data.color = colorBuffer[i];
    data.normal = normalBuffer[i];
    data.texcoord = texCoordBuffer[i];
    vboBuffer.push_back(data);


glGenBuffers(1, &vbo);
glBindBuffer(GL_ARRAY_BUFFER, vbo);
glBufferData(GL_ARRAY_BUFFER, vboBuffer.size() * sizeof(VBOData), (GLchar*) &vboBuffer[0], GL_STATIC_DRAW);
glBindBuffer(GL_ARRAY_BUFFER, 0);

现在有这个问题,如果我的对象不包含颜色、法线或 tex 坐标并且只包含顶点怎么办?还是仅关于顶点和法线?或者总是有顶点的不同数据组合?我可以按 V(N)(T)(C) 顺序动态打包它们以提高效率吗?

【问题讨论】:

C++ 支持结构类型:)。您能详细说明“动态打包”吗?你的意思是改变结构成员的顺序吗? 【参考方案1】:

现在有这个问题,如果我的对象不包含颜色、法线或 tex 坐标并且只包含顶点怎么办?还是只关于顶点和法线?

然后您将设置偏移量到您使用glVertexAttribPointer 获得的组件,并且not 设置您未使用的组件。

顺便说一句,你在opengl.org 上有一个关于 VBO 的很好的教程。

【讨论】:

但如果我的模型上没有法线,我将不必要地上传包含“空的、未初始化的”法线的 VBOData。 @deniz 有关系吗?听起来像是一个微优化,但如果你不想这样做,那就创建没有你需要的组件的结构 如果真的是微优化,那对我来说是没有问题的。但是高度详细的网格可能会占用比它需要的更多的空间(实际上高度详细的网格通常包含法线、切线、texcoords :P)。如果真的是那么微,这已经不是问题了。

以上是关于OpenGL顶点缓冲区对象的动态打包数据的主要内容,如果未能解决你的问题,请参考以下文章

带有附加数据的 OpenGL 索引缓冲区对象

OpenGL顶点数组对象不记录VBO和IBO绑定

OpenGL复制顶点缓冲区对象

初识OpenGL VBO顶点缓冲对象

OpenGL 顶点缓冲

OpenGL 顶点数组/缓冲区对象