使用带索引的 VBO 的 OpenGL

Posted

技术标签:

【中文标题】使用带索引的 VBO 的 OpenGL【英文标题】:OpenGL using VBO with index 【发布时间】:2014-05-21 13:16:59 【问题描述】:

所以我正在构建一个基本引擎来渲染模型和转换,我使用常规 VBO(没有索引)来完成它,没有任何问题,但我决定使用带有索引的 VBO。以下是我的代码的重要部分:

相关的全局变量:

GLuint *modelBuffers;
GLuint *indexBuffers;

相关数据结构:

struct databaseStruct

    int moveSize;
    int modelSize;
    int spinSize;
    int tracerSize;

    int currentMove;
    int currentSpin;
    int currentModel;
    int currentTracer;

    vector<moveNode> moveList;
    vector<modelNode> modelList;
    vector<spinNode> spinList;
    vector<tracerNode> tracerList;
    groupStruct scene;
 database;

struct modelNode

    int id;
    int numTri;
    string modelName;
    vector<GLfloat> model;
    vector<GLfloat> normals;
    vector<int> indices;
;

程序开始时的模型初始化:

void initModels()
    glEnableClientState(GL_VERTEX_ARRAY);
    modelBuffers = new GLuint[database.modelSize];
    indexBuffers = new GLuint[database.modelSize];
    glGenBuffers(database.modelSize, modelBuffers);
    glGenBuffers(database.modelSize, indexBuffers);
    vector<modelNode> mList = database.modelList;
    for (int i = 0; i < database.modelSize; i++)
        glBindBuffer(GL_ARRAY_BUFFER, modelBuffers[mList[i].id]);
        glBufferData(GL_ARRAY_BUFFER, mList[i].model.size()*sizeof(GLfloat), &(mList[i].model[0]), GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffers[mList[i].id]);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, mList[i].indices.size() * sizeof(GLint), &(mList[i].indices[0]), GL_STATIC_DRAW);
    

在渲染场景上调用:

void drawModel(element* elem)
    if (elem != NULL)
        modelNode *it = &database.modelList[elem->nodeRef];
        glBindBuffer(GL_ARRAY_BUFFER, modelBuffers[it->id]);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBuffers[it->id]);
        glVertexPointer(3, GL_FLOAT, 0, 0);
        glDrawElements(GL_TRIANGLES, it->numTri*3, GL_INT, 0);
    

程序结构有效,因为自从使用简单的 VBO 以来,我所做的只是改变了结构来托管索引和处理它们的 OpenGL 调用。 如果需要,我可以提供以前的工作版本。

【问题讨论】:

glVertexPointer,固定功能管道?这样做时还有GLGetError吗? 您正在尝试为GL_ARRAY_BUFFERGL_ELEMENT_ARRAY_BUFFER 使用相同的缓冲区 【参考方案1】:

您正在重叠缓冲区,为顶点信息和索引创建单独的缓冲区

void initModels()
    glEnableClientState(GL_VERTEX_ARRAY);
    modelBuffers = new GLuint[database.modelSize*2];//twice as large
    glGenBuffers(database.modelSize*2, modelBuffers);//creating twice as many
    vector<modelNode> mList = database.modelList;
    for (int i = 0; i < database.modelSize; i++)
        glBindBuffer(GL_ARRAY_BUFFER, modelBuffers[mList[i].id*2]);
        glBufferData(GL_ARRAY_BUFFER, mList[i].model.size()*sizeof(GLfloat), &(mList[i].model[0]), GL_STATIC_DRAW);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelBuffers[mList[i].id*2+1]);
        glBufferData(GL_ELEMENT_ARRAY_BUFFER, mList[i].indices.size() * sizeof(int), &(mList[i].indices[0]), GL_STATIC_DRAW);
    


void drawModel(element* elem)
    if (elem != NULL)
        modelNode *it = &database.modelList[elem->nodeRef];
        glBindBuffer(GL_ARRAY_BUFFER, modelBuffers[it->id*2]);
        glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, modelBuffers[it->id*2+1]);
        glVertexPointer(3, GL_FLOAT, 0, 0);
        glDrawElements(GL_TRIANGLES, it->numTri*3, GL_INT, 0);
    

你会看到我创建了两倍的缓冲区,每个数组缓冲区是modelBuffers 中的id*2,索引缓冲区是modelBuffers 中的id*2 + 1

【讨论】:

我明白了,我认为缓冲区只是为了指定顺序,所以我只是对索引和模型使用相同的(因为索引列表 1 用于模型 1,依此类推)。我将把它改写成两个单独的缓冲区,看看会发生什么。 但无论是绑定到GL_ARRAY_BUFFER 还是GL_ELEMENT_ARRAY_BUFFER 它们都会引用相同的数据,所以第二个glBufferData(GL_ELEMENT_ARRAY_BUFFER,...) 擦除了缓冲区并放入了新数据 我现在为索引使用单独的缓冲区,但它仍然没有绘制模型。我将在第一篇文章中更新代码 你初始化索引了吗? 是的,我调试了 3 个数据源(mList[i].model 中的顶点坐标信息,mList[i].indices 中的顶点索引信息和 mList[i].normals 中的法线信息)。虽然我还没有使用法线,但所有数据源都已正确填充。

以上是关于使用带索引的 VBO 的 OpenGL的主要内容,如果未能解决你的问题,请参考以下文章

带和不带着色器的 VBO OpenGL C++

iOS 上的 OpenGL ES 多个没有索引的 VBO

使用 VBO 和元素数组索引的 OpenGL 纹理

LWJGL Indexed VBO,很多混乱

opengl vbo 纹理

VAO 是不是同时记住 EBO/IBO(元素或索引)和 VBO?