2012-03-02 119 views
5

我想在OpenGL ES 2.0顶点数组对象来保存从不同的缓冲区两个属性,第二缓冲正从客户端存储器(glBindBuffer(GL_ARRAY_BUFFER, 0))读但是我得到一个运行时错误:OES_vertex_array_object和客户端状态

GLuint my_vao; 
GLuint my_buffer_attrib0; 
GLfloat attrib0_data[] = { 0, 0, 0, 0 }; 
GLfloat attrib1_data[] = { 1, 1, 1, 1 }; 

void init() 
{ 
    // setup vao 
    glGenVertexArraysOES(1, &my_vao); 
    glBindVertexArrayOES(my_vao); 

    // setup attrib0 as a vbo 
    glGenBuffers(1, &my_buffer_attrib0); 
    glBindBuffer(GL_ARRAY_BUFFER, my_buffer_attrib0); 
    glBufferData(GL_ARRAY_BUFFER, sizeof(attrib0_data), attrib0_data, GL_STATIC_DRAW); 
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); 

    glEnableVertexAttribArray(0); 
    glEnableVertexAttribArray(1); 

    // "end" vao 
    glBindVertexArrayOES(0); 

} 

void draw() 
{ 

    glBindVertexArrayOES(my_vao); 
    // (now I assume attrib0 is bound to my_buffer_attrib0, 
    // and attrib1 is not bound. but is this assumption true?) 

    // setup attrib1 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, attrib1_data); 

    // draw using attrib0 and attrib1 
    glDrawArrays(GL_POINTS, 0, 1); // runtime error: Thread1: EXC_BAD_ACCESS (code=2, address=0x0) 

} 

我想实现的是包裹两个属性的结合为顶点数组缓存:

void draw_ok() 
{ 
    glBindVertexArrayOES(0); 

    // setup attrib0 
    glBindBuffer(GL_ARRAY_BUFFER, my_buffer_attrib0); 
    glVertexAttribPointer(0, 4, GL_FLOAT, GL_FALSE, 0, 0); 

    // setup attrib1 
    glBindBuffer(GL_ARRAY_BUFFER, 0); 
    glVertexAttribPointer(1, 4, GL_FLOAT, GL_FALSE, 0, attrib1_data); 

    glEnableVertexAttribArray(0); 
    glEnableVertexAttribArray(1); 

    // draw using attrib0 and attrib1 
    glDrawArrays(GL_POINTS, 0, 1); // ok 
} 

是否可以结合两个不同缓冲区的顶点数组对象? OES_vertex_array_object与(普通)OpenGL顶点数组对象不同吗?另请注意,我在运行iOS模拟器的XCode中出现此错误。这些都是相关链接:

回答

6

那么从扩展规格报价说明它很简单:

Should a vertex array object be allowed to encapsulate client vertex arrays?

RESOLVED: No. The OpenGL ES working group agreed that compatibility with OpenGL and the ability to to guide developers to more performant drawing by enforcing VBO usage were more important than the possibility of hurting adoption of VAOs.

所以,你确实可以在VAO结合两个不同的缓冲区,(当然,缓冲结合不被存储在VAO,无论如何,只有通过glVertexAttribPointer设置的各个属性的源缓冲区),但不能在VAO中使用客户端空间内存,只能使用VBOs。这对于桌面GL来说是一样的。

所以我建议你将所有的顶点数据存储在VBO中。如果你想使用客户端内存,因为数据是动态更新的,并且你认为VBOs不会向你购买任何东西,那仍然是错误的方法。只需使用具有动态使用的VBO(GL_DYNAMIC_DRAW或甚至GL_STREAM_DRAW),并使用glBuffer(Sub)DataglMapBuffer(或旧的glBufferData(..., NULL); glMapBuffer(GL_WRITE_ONLY)组合)对其进行更新。

+0

因为你不是我,所以你得到了接受的答案,如果OES-VAO与桌面-VAO相同,也会得到答案:)谢谢。 – telephone 2012-03-04 16:54:35

1

删除以下行:

glBindBuffer(GL_ARRAY_BUFFER, 0);

draw()功能

。您之前没有绑定任何缓冲区,并且可能会弄乱缓冲区状态。

+0

我想第二个属性(attrib1)从客户端内存中读取,所以GL_ARRAY_BUFFER前必须绑定调用glVertexAttribPointer。但是这似乎弄乱了事情,我不确定为什么。我想要实现的一个例子是让VAO存储几何图形,然后在绑定VAO后,将该VAO的另一个属性设置为我的自定义颜色。 – telephone 2012-03-03 23:56:43

+0

@telephone你不能在VAO上使用客户端内存,请参阅我的答案。 – 2012-03-04 16:56:06

1

经过一番挖掘(阅读),在OES_vertex_array_object发现答案。看起来OES_vertex_array_object关注服务器端的状态,并且当且仅当零对象被绑定时才使用客户端状态。如果OES_vertex_array_object与OpenGL VAO相同,它仍然可以回答。请评论,如果你知道这个答案。下面是语录OES_vertex_array_object

 This extension introduces vertex array objects which encapsulate 
    vertex array states on the server side (vertex buffer objects). 



    * Should a vertex array object be allowed to encapsulate client 
    vertex arrays? 

    RESOLVED: No. The OpenGL ES working group agreed that compatibility 
    with OpenGL and the ability to to guide developers to more 
    performant drawing by enforcing VBO usage were more important than 
    the possibility of hurting adoption of VAOs. 



    An INVALID_OPERATION error is generated if 
    VertexAttribPointer is called while a non-zero vertex array object 
    is bound, zero is bound to the <ARRAY_BUFFER> buffer object binding 
    point and the pointer argument is not NULL [fn1]. 
     [fn1: This error makes it impossible to create a vertex array 
     object containing client array pointers, while still allowing 
     buffer objects to be unbound.] 



    And the presently attached vertex array object has the following 
    impacts on the draw commands: 

     While a non-zero vertex array object is bound, if any enabled 
     array's buffer binding is zero, when DrawArrays or 
     DrawElements is called, the result is undefined. 

所以EXC_BAD_ACCESS是未定义的结果!

+1

+1“因此EXC_BAD_ACCESS是未定义的结果!”。我一直在追赶*天*的错误。出于某种原因,GL_VERTEX_ARRAY被谁知道谁在一段时间后禁用,因此在glDrawArray保存了我之后重新启用它:glEnableClientState(GL_VERTEX_ARRAY);我从来没有把EXC_BAD_ACCESS作为一个未定义的结果,但作为一个意外的内存释放,但没有,这里没有释放内存。感谢您的提示,这是非常有用的:) – 2013-09-02 06:39:01