无法捕捉 OpenGL 和顶点数组对象的错误

Posted

技术标签:

【中文标题】无法捕捉 OpenGL 和顶点数组对象的错误【英文标题】:Trouble catching mistake with OpenGL and Vertex Array Objects 【发布时间】:2012-12-07 12:18:00 【问题描述】:

我在发现这个 OpenGL 实现的错误时遇到了麻烦。当我运行程序时,我唯一得到的是黑屏。我应该看到一个立方体。我没有收到任何错误。我怀疑罪魁祸首可能是 VAO:

// draws the view
-(void)drawRect:(NSRect)dirtyRect

// clear the viewport
glClearColor(0.0, 0.0, 0.0, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);

shaderProgramID = [self loadShaders];

// get uniform locations
uniformLocations[0] = glGetUniformLocation(shaderProgramID, "rotationX");
uniformLocations[1] = glGetUniformLocation(shaderProgramID, "rotationY");
uniformLocations[2] = glGetUniformLocation(shaderProgramID, "rotationZ");
uniformLocations[3] = glGetUniformLocation(shaderProgramID, "translation");
uniformLocations[4] = glGetUniformLocation(shaderProgramID, "projection");

// use this program
glUseProgram(shaderProgramID);

// create VAO
glGenVertexArraysAPPLE(1, &vao);
glBindVertexArrayAPPLE(vao);
glGenBuffers(3, vbo);

// bind and copy data for vertex position data
glBindBuffer(GL_ARRAY_BUFFER, vbo[0]);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubePositionData), cubePositionData, GL_STATIC_DRAW);
glVertexAttribPointer(TCV_VERTEX_POS_INDEX, TCV_NUM_POS_COMPONENTS, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(TCV_VERTEX_POS_INDEX);

// bind and copy data for vertex color data
glBindBuffer(GL_ARRAY_BUFFER, vbo[1]);
glBufferData(GL_ARRAY_BUFFER, sizeof(cubeColorData), cubeColorData, GL_STATIC_DRAW);
glVertexAttribPointer(TCV_VERTEX_COLOR_INDEX, TCV_NUM_COLOR_COMPONENTS, GL_FLOAT, GL_FALSE, 0, 0);
glEnableVertexAttribArray(TCV_VERTEX_COLOR_INDEX);

// bind and copy data for vertex indices data
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, vbo[2]);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cubeIndices), cubeIndices, GL_STATIC_DRAW);
glVertexAttribPointer(TCV_VERTEX_INDICES_INDEX, TCV_NUM_INDEX_ARRAY_COMPONENTS, GL_UNSIGNED_BYTE, GL_FALSE, 0, 0);
glEnableVertexAttribArray(TCV_VERTEX_INDICES_INDEX);

// load uniform data into shader program
glUniformMatrix4fv(uniformLocations[0], 1, GL_FALSE, rotationMatX);
glUniformMatrix4fv(uniformLocations[1], 1, GL_FALSE, rotationMatY);
glUniformMatrix4fv(uniformLocations[2], 1, GL_FALSE, rotationMatZ);
glUniformMatrix4fv(uniformLocations[3], 1, GL_FALSE, translationMat);
glUniformMatrix4fv(uniformLocations[4], 1, GL_FALSE, projectionMat);

// tell OGL to draw the cube, in this order
glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_BYTE, cubeIndices);

// unbind VAO
glBindVertexArrayAPPLE(0);

// no longer using program
glUseProgram(0);

// flush buffer
glFlush();
[[self openGLContext] flushBuffer];

【问题讨论】:

这听起来像是破纪录,但您在每次 gl 调用后检查过 glError 吗? 我会通过 OpenGL Profiler 运行它以检查所有状态在渲染时是否正确,并且没有出现错误:“/Developer/Applications/Graphics Tools/OpenGL Profiler” 【参考方案1】:

我的 OpenGL 实验也遇到过类似的问题。我还为顶点位置和顶点颜色数据使用了单独的缓冲区对象。我相信只有一个 GL_ARRAY_BUFFER 可以绑定到顶点数组对象。因此,将所有数据放入一个组合缓冲区中,然后将带有偏移量的属性指针设置到该缓冲区中。

您的 VBO / VAO 设置应类似于:

glGenVertexArrays(1, &vertexArray);
glBindVertexArray(vertexArray);

glGenBuffers(1,&vertexBuffer);
glBindBuffer(vertexBuffer);
glBindBufferData(GL_ARRAY_BUFFER, sizeof(cubePositionAndColorData), cubePositionAndColorData, GL_STATIC_DRAW);

glVertexAttribPointer(kPositionAttribute, NUM_VERTEX_COMPONENTS, GL_FLOAT, GL_FALSE, 0, 0);
// colorStartingIndex is probably just NUM_VERTEX_COMPONENTS*sizeof(GLfloat)
glVertexAttribPointer(kColorAttribute, NUM_COLOR_COMPONENTS, GL_FLOAT, GL_FALSE, 0, (void *)colorStartingIndex);

glEnableVertexAttribArray(kPositionAttribute);
glEnableVertexAttribArray(kColorAttribute);

glGenBuffers(1,&indexBuffer);
glBindBuffer(indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(cubeIndices), cubeIndices, GL_STATIC_DRAW);

glBindVertexArray(0);

然后,在您的-drawRect: 函数中,您可以使用该程序,设置您的制服并致电glDrawElements()

glUseProgram(shaderProgramID);

// do the necessary uniform configuration
glUniformMatrix4fv(...)

glBindVertexArray(vertexArray);
glDrawElements(GL_TRIANGLES, 12, GL_UNSIGNED_BYTE, 0);

glBindVertexArray(0);

glUseProgram(0);

另外两点值得注意:

    我建议将所有缓冲区初始化从-drawRect: 方法中移出,因为每次重新绘制视图时都会调用它。这意味着您要在每个-drawRect: 上将所有数据重新复制到 OpenGL 服务器。 如果您使用的是更新版本的 osx,则应考虑使用最新版本的 OpenGL (OpenGL/gl3.h)。

【讨论】:

以上是关于无法捕捉 OpenGL 和顶点数组对象的错误的主要内容,如果未能解决你的问题,请参考以下文章

我无法使用仅直接状态访问的顶点数组对象设置来显示我的 OpenGL 4.5“hello-world”三角形

Eclipse CDT 编辑器无法识别 OpenGL 扩展

无法使用 VAO 和 EBO (openGL) 绘制多个对象

使用 OpenGL 和顶点数组对象渲染两个对象

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

为啥顶点数组对象会导致错误?