OES_vertex_array_object и состояние клиента - PullRequest
5 голосов
/ 02 марта 2012

Я хочу, чтобы объект массива вершин в 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)

}

Чего я хочу добиться - это связать два атрибута как буфер массива вершин:

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?Также обратите внимание, что я получаю эту ошибку в XCode при запуске симулятора iOS.Это связанные ссылки:

Ответы [ 4 ]

7 голосов
/ 04 марта 2012

Ну, цитата из спецификаций расширения объясняет это довольно просто:

Разрешено ли объекту массива вершин инкапсулировать клиентские вершинные массивы?

РАЗРЕШЕНО: Нет. OpenGLРабочая группа ES согласилась с тем, что совместимость с OpenGL и возможность направлять разработчиков к более производительному рисованию путем принудительного использования VBO были более важными, чем возможность нанесения вреда принятию VAO.

Таким образом, вы действительно можете связать дваразные буферы в VAO (ну, в любом случае привязка буфера не сохраняется в VAO, только исходные буферы отдельных атрибутов, заданные через glVertexAttribPointer), но вы не можете использовать память пространства клиента в VAO, только VBO,Это то же самое для настольных компьютеров GL.

Поэтому я бы посоветовал вам хранить все ваши данные вершин в VBO.Если вы хотите использовать клиентскую память, потому что данные обновляются динамически, и вы думаете, что VBO не будут вам там ничего покупать, это все равно неправильный подход.Просто используйте VBO с динамическим использованием (GL_DYNAMIC_DRAW или даже GL_STREAM_DRAW) и обновите его с помощью glBuffer(Sub)Data или glMapBuffer (или старой доброй комбинации glBufferData(..., NULL); glMapBuffer(GL_WRITE_ONLY)).

1 голос
/ 05 ноября 2012

Функциональность, которую вы хотите, теперь принята сообществом как расширение WebGL:

http://www.khronos.org/registry/webgl/extensions/OES_vertex_array_object/

1 голос
/ 04 марта 2012

После некоторого копания (чтения), ответы были найдены в 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 голос
/ 03 марта 2012

Удалить следующую строку:

glBindBuffer( GL_ARRAY_BUFFER, 0 );

из функции draw(). Вы не связывали буфер ранее, и это может испортить состояние буфера.

...