OES_vertex_array_object和客户端状态

tel*_*one 5 opengl-es opengl-es-2.0

我希望OpenGL ES 2.0中的顶点数组对象保存来自不同缓冲区的两个属性,第二个缓冲区从客户端内存中读取(glBindBuffer(GL_ARRAY_BUFFER, 0))但是我得到一个运行时错误:

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)

}
Run Code Online (Sandbox Code Playgroud)

我想要实现的是将两个属性的绑定包装为顶点数组缓冲区:

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
}
Run Code Online (Sandbox Code Playgroud)

是否可以在顶点数组对象中绑定两个不同的缓冲区?OES_vertex_array_object与(普通)OpenGL顶点数组对象有什么不同?另请注意,我在运行iOS模拟器的XCode中收到此错误.这些是相关链接:

Chr*_*ica 7

那么,扩展规范的引用很简单地解释了它:

是否应允许顶点数组对象封装客户端顶点数组?

已解决:否.OpenGL ES工作组一致认为,与OpenGL的兼容性以及通过强制执行VBO来指导开发人员进行更高性能绘图的能力比伤害VAO采用的可能性更重要.

所以你确实可以在VAO中绑定两个不同的缓冲区(好吧,缓冲区绑定不存储在VAO中,无论如何,只有各个属性的源缓冲区设置通过glVertexAttribPointer)但是你不能在VAO中使用客户端空间内存,只有维也纳国际中心 桌面GL也是如此.

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