如何使用具有位置、纹理坐标和法线的 VAO

问题描述 投票:0回答:1

我已经运行了一个 Wavefront OBJ 解析器,但在花了无数个小时试图弄清楚如何在 OpenGL 中加载数据后,我最终不得不放弃。

这就是代码的构建方式:

struct ObjMeshVertex{
    Vector3f pos;
    Vector2f texcoord;
    Vector3f normal;
};

struct ObjMeshFace{
    ObjMeshVertex vertices[3];
};

struct ObjMesh{
    std::vector<ObjMeshFace> faces;
};

ObjMesh myMesh;

for(size_t i = 0; i < faces.size(); ++i){
    ObjMeshFace face;
    for(size_t j = 0; j < 3; ++j){
        face.vertices[j].pos        = positions[faces[i].pos_index[j] - 1];
        face.vertices[j].texcoord   = texcoords[faces[i].tex_index[j] - 1];
        face.vertices[j].normal     = normals[faces[i].nor_index[j] - 1];
    }
    myMesh.faces.push_back(face);
}

通常,当我创建一个简单的立方体时,数组看起来像这样:

{posX, posY, posZ, normX, normY, normZ}

通过使用

glVertexAttribPointer
的偏移量,加载数据非常简单。

但我不知道这是如何做到的?

编辑 设置:

glGenVertexArraysOES(1, &_boxVAO);
glBindVertexArrayOES(_boxVAO);

int sizeOfFaces = myMesh.faces.size() * sizeof(ObjMeshFace);
glGenBuffers(1, &_boxBuffer);
glBindBuffer(GL_ARRAY_BUFFER, _boxBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeOfFaces, &(myMesh.faces[0]), GL_STATIC_DRAW);


glVertexAttribPointer(0, 3, GL_FLOAT, GL_FALSE, sizeof(ObjMeshVertex), 0);
glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, sizeof(ObjMeshVertex), (void*)offsetof(ObjMeshVertex, texcoord));        
glVertexAttribPointer(2, 3, GL_FLOAT, GL_FALSE ,sizeof(ObjMeshVertex), (void*)offsetof(ObjMeshVertex, normal));

glEnableVertexAttribArray(0);
glEnableVertexAttribArray(1);
glEnableVertexAttribArray(2);

glBindVertexArrayOES(0);

画:

glBindVertexArrayOES(_boxVAO);
glDrawArrays(GL_TRIANGLES, 0, indicesize);  

其中

indicesize
=
myMesh.faces.size()

opengl-es opengl-es-2.0
1个回答
3
投票

如果您只是询问如何将数据发送到 glBufferData,那么您只需获取指向 myMesh 中第一个面的指针,并对其调用 glBufferData(假设所有内容都紧密包装)。

int sizeOfFaces = myMesh.faces.size() * sizeof(ObjMeshFace);
glBufferData(GL_ARRAY_BUFFER, sizeOfFaces, &(myMesh.faces[0]), usage);

然后你可以设置指向这个交错结构的指针:

glVertexPointer(3, GL_FLOAT, sizeof(ObjMeshVertex), 0);
glTexCoordPointer(2, GL_FLOAT, sizeof(ObjMeshVertex), (void*)(sizeof(Vector3f)));
glNormalPointer(3, GL_FLOAT, sizeof(ObjMeshVertex), (void*)(sizeof(Vector3f) + sizeof(Vector2f)));

您可能需要检查的一件事是您的结构没有被填充(我不太确定如何启用/禁用它)。

只需仔细检查并断言:

sizeof(ObjMeshVertex) == 2 * sizeOf(Vector3f) + sizeOf(Vector2f);
sizeof(ObjMeshFace) == 3 * sizeOf(ObjMeshVertex);

如果这不是真的,您可能需要对结构填充进行一些调整。

© www.soinside.com 2019 - 2024. All rights reserved.