首页 > 解决方案 > 假设结构数组的内存布局传递给 OpenGL 的潜在错误

问题描述

我正在关注 OpenGL 教程,在其中,将网格数据传递给视频卡的操作基本上如下:

#include <GL/glew.h>
#include <glm/glm.hpp>

struct Vertex {
    ...
private:
    glm::vec3 pos;
    glm::vec2 texCoord;
    glm::vec3 normal;
};

Mesh::Mesh(Vertex * vertices, unsigned int numVertices) {
    ...
    glBufferData(GL_ARRAY_BUFFER, numVertices * sizeof(vertices[0]), vertices, GL_STATIC_DRAW);
    ...
}

但是,我认为这可能会导致问题,因为假设顶点将完美布局。或者是否保证 Vertex 字段将在没有填充的情况下按该顺序放置?另外,我不知道 glm::vec* 类型的布局或大小是什么。

我是否正确怀疑这可能会导致问题?

应该怎么做?

什么会影响结构的布局?

标签: c++openglmemory-layout

解决方案


只要您指定正确的属性指针,这种方法没有任何问题,例如:

glVertexAttribPointer( ..., 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), offsetof(Vertex, pos));
glVertexAttribPointer( ..., 2, GL_FLOAT, GL_FALSE, sizeof(Vertex), offsetof(Vertex, texCoord));
glVertexAttribPointer( ..., 3, GL_FLOAT, GL_FALSE, sizeof(Vertex), offsetof(Vertex, normal));

两者都sizeofoffsetof考虑可能发生的任何填充。

如果您想对实际布局进行更多控制,当然也可以使用#pragma pack,它不是任何 C/C++ 标准的一部分,但被所有主要编译器所理解。实际上,存在 OpenGL 实现的平台上的实际编译器不会为您的原始结构布局添加任何填充,因此这可能是一个有争议的问题。

另外,我不知道glm::vec*类型的布局或大小是什么。

GLM 向量和矩阵是各自基本类型的紧密排列的数组,特别是float[N]对于glm::vecN.


推荐阅读