今天下午,当我从使用VBO转到VAO / VBO时,我一直在抨击我的openGLES2.0代码。基本上我正在通过Apple关于openGLES的“专家”建议,并且转向使用Vertex Array Objects是最重要的......
我已经回顾了类似的问题和回复here,但这似乎对我没有帮助,除了再次向我保证其他人遇到类似问题:(
我的情况是我在屏幕周围移动了大约500个矩形纹理。代码一切正常,没有VAO,但是当我定义USE_VAO(我的常量)时,它会在第一个绘图元素调用时崩溃。我显然不能正确理解VAO ......但我看不出我的方式错误!
在进入渲染循环之前,setupBeforeRender方法被调用为我的设置的最后一部分。
-(void) setupBeforeRender {
glClearColor(0.6, 0.6, 0.6, 1);
glViewport(0, 0, self.frame.size.width, self.frame.size.height);
glEnable(GL_DEPTH_TEST);
glUniform1i(_textureUniform, 0);
glActiveTexture(GL_TEXTURE0);
glEnableVertexAttribArray(_positionSlot);
glEnableVertexAttribArray(_colorSlot);
glEnableVertexAttribArray(_texCoordSlot);
glGenBuffers(1, &_indexBuffer);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, _indexBuffer);
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(Indices), Indices, GL_STATIC_DRAW);
}
这是渲染方法
- (void)render:(CADisplayLink*)displayLink {
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
// Model view matrix and projection code removed for clarity
GLsizei stride = sizeof(Vertex);
const GLvoid* colourOffset = (GLvoid *) sizeof(float[3]);
const GLvoid* textureOffset = (GLvoid *) sizeof(float[7]);
for (my objectToDraw in objectToDrawArray)
{
if (objectToDraw.vertexBufferObject == 0)
{
#ifdef USE_VAO
glGenVertexArraysOES(1,&_vao);
glBindVertexArrayOES(_vao);
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, stride, 0);
glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, stride, colourOffset);
glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, GL_FALSE,stride, textureOffset);
objectToDraw.vertexBufferObject = [objectToDraw createAndBindVBO];
objectToDraw.vertexArrayObject = _vao;
glBindBuffer(GL_ARRAY_BUFFER, 0);
glBindVertexArrayOES(0);
#else
objectToDraw.vertexBufferObject = [objectToDraw createAndBindVBO];
#endif
}
// Texture binding removed for clarity
#ifdef USE_VAO
// This code crashes with EXC_BAD_ACCESS on the glDrawElements
glBindVertexArrayOES(objectToDraw.vertexArrayObject);
glDrawElements(GL_TRIANGLES, sizeof(Indices) / sizeof(Indices[0]), GL_UNSIGNED_SHORT,0);
glBindVertexArrayOES(0);
#else
// This path works fine. So turning VAO off works :(
glBindBuffer(GL_ARRAY_BUFFER, storyTile.vertexBufferObject);
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, stride, 0);
glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, stride, colourOffset);
glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, GL_FALSE, stride, textureOffset);
glDrawElements(GL_TRIANGLES, sizeof(Indices) / sizeof(Indices[0]), GL_UNSIGNED_SHORT,0);
#endif
} // End for each object
[_context presentRenderbuffer:GL_RENDERBUFFER];
}
最后,我的create和bind VBO方法看起来像这样;
-(GLuint) createAndBindVBO {
const float* rgba = CGColorGetComponents([self.colour CGColor]);
Vertex Vertices[] = {
{{0, 1, 0}, {1, 0, 1, 1}, {0,1}},
{{0, 0, 0}, {1, 0, 1, 1}, {0,0}},
{{1, 1, 0}, {1, 0, 1, 1}, {1,1}},
{{1, 0, 0}, {1, 0, 1, 1}, {1,0}}
};
// Code removed for clarity - sets up geometry and colours
GLuint vertexBuffer;
glGenBuffers(1, &vertexBuffer);
glBindBuffer(GL_ARRAY_BUFFER, vertexBuffer);
glBufferData(GL_ARRAY_BUFFER, sizeof(Vertices), Vertices, GL_STATIC_DRAW);
return vertexBuffer;
}
我已尝试过各种各样的排列,并将代码与glGetError()一起使用,以查看是否有助于指出问题出现的位置。唉,除了drawElements调用上的BAD_ACCESS崩溃外,我没有任何错误。
编辑:正如所建议的,遗憾的是,这也不起作用
objectToDraw.vertexBufferObject = [objectToDraw createVBO];
glGenVertexArraysOES(1,&_vao);
glBindVertexArrayOES(_vao);
glBindBuffer(GL_ARRAY_BUFFER, objectToDraw.vertexBufferObject);
glVertexAttribPointer(_positionSlot, 3, GL_FLOAT, GL_FALSE, stride, 0);
glVertexAttribPointer(_colorSlot, 4, GL_FLOAT, GL_FALSE, stride, colourOffset);
glVertexAttribPointer(_texCoordSlot, 2, GL_FLOAT, GL_FALSE,stride, textureOffset);
objectToDraw.vertexArrayObject = _vao;
glBindVertexArrayOES(0);
我必须对顶点数组对象做一些愚蠢的事情......但有人能弄明白问题是什么吗?
答案 0 :(得分:4)
启用顶点数组的标志是VAO状态的一部分,因此您需要在绑定VAO时使用glEnableVertexAttribArray启用顶点属性数组。
来自:http://www.khronos.org/registry/gles/extensions/OES/OES_vertex_array_object.txt
结果 顶点数组对象是一个新的状态向量,包含所有状态值(表6.2中列出,ARRAY_BUFFER_BINDING除外):
- VERTEX_ATTRIB_ARRAY_ENABLED
- VERTEX_ATTRIB_ARRAY_SIZE,
- VERTEX_ATTRIB_ARRAY_STRIDE,
- VERTEX_ATTRIB_ARRAY_TYPE,
- VERTEX_ATTRIB_ARRAY_NORMALIZED,
- VERTEX_ATTRIB_ARRAY_POINTER,
- ELEMENT_ARRAY_BUFFER_BINDING,
- VERTEX_ATTRIB_ARRAY_BUFFER_BINDING。
答案 1 :(得分:0)
您应在glVertexAttribPointer
函数调用后调用glBindBuffer
。
答案 2 :(得分:0)
我有类似的问题,不知道是什么导致它。
最终我发现我必须在glDrawArrays中放入一个const int数量的顶点。 sizeof()做得不对。