2012-03-02 26 views
5

Chcę obiektu tablicy wierzchołków w OpenGL ES 2.0 trzymania dwóch atrybutów z różnych buforów, drugi bufor są odczytywane z pamięci klienta (glBindBuffer(GL_ARRAY_BUFFER, 0)), ale pojawia się błąd środowiska wykonawczego:OES_vertex_array_object i klient stan

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) 

} 

Co chcę osiągnąć jest owinąć wiązanie dwóch atrybutów jako bufor tablicy wierzchołek:

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 
} 

Czy jest możliwe aby związać dwa różne bufory w obiekcie tablicy wierzchołek? Czy obiekty OES_vertex_array_object różnią się od (zwykłych) obiektów tablicy wierzchołków OpenGL? Zauważ też, że dostaję ten błąd w XCode z symulatorem iOS. Są powiązane linki:

Odpowiedz

6

Cóż, cytat ze specyfikacji przedłużających wyjaśnia to dość prosto:

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.

Więc może rzeczywiście wiążą dwa różne bufory w vào (dobrze, wiązanie bufor nie jest przechowywany w vào, tak czy inaczej, tylko bufory źródłowe poszczególnych atrybutów, ustawione przez glVertexAttribPointer), ale nie można używać pamięci miejsca klienta w VAO, tylko VBO. To samo dotyczy pulpitu GL.

Tak więc radziłbym przechowywać wszystkie twoje dane werteksów w VBO. Jeśli chcesz używać pamięci klienckiej, ponieważ dane są aktualizowane dynamicznie i uważasz, że VBO niczego tam nie kupią, to nadal jest to złe podejście. Po prostu użyj VBO z dynamicznym użyciem (GL_DYNAMIC_DRAW lub nawet GL_STREAM_DRAW) i zaktualizuj go za pomocą glBuffer(Sub)Data lub glMapBuffer (lub dobrej starej kombinacji glBufferData(..., NULL); glMapBuffer(GL_WRITE_ONLY)).

+0

Otrzymujesz zaakceptowaną odpowiedź, ponieważ nie jesteś mną, a także odpowiedziałeś, jeśli OES-VAO są takie same jak na komputerach stacjonarnych VAO :) dziękuję. – telephone

1

Usuń następujący wiersz:

glBindBuffer(GL_ARRAY_BUFFER, 0);

z funkcji draw(). Nie wiązałeś wcześniej żadnego bufora i może to zepsuć stan bufora.

+0

chcę drugi atrybut (attrib1) do odczytu z pamięci klienta, więc GL_ARRAY_BUFFER musi być niezwiązany przed wywołanie glVertexAttribPointer. Ale wydaje się to zepsuć rzeczy i nie jestem pewien dlaczego. Przykładem tego, co chcę osiągnąć, to pozwolić geometrii sklepu VAO, a następnie ustawić inny atrybut tego VAO na moje niestandardowe kolory, po związaniu VAO. – telephone

+0

@telephone Po prostu nie możesz używać pamięci klienckiej z VAO, zobacz moją odpowiedź. –

1

Po pewnym wykopaniu (przeczytaniu) znaleziono odpowiedzi znalezione w OES_vertex_array_object. Wygląda na to, że OES_vertex_array_object skupia się na stanie po stronie serwera, a stan klienta jest używany wtedy i tylko wtedy, gdy obiekt zerowy jest związany. Pozostaje odpowiedzieć, jeśli OES_vertex_array_object są takie same jak zwykłe VAO OpenGL. Proszę o komentarz, jeśli znasz odpowiedź na to pytanie. Poniżej znajdują się cytaty z 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. 

Więc EXC_BAD_ACCESS był niezdefiniowany wynik!

+1

+1 dla "So EXC_BAD_ACCESS był niezdefiniowanym wynikiem!". Szukałem błędu przez * dni *. Z jakiegoś powodu stan klienta GL_VERTEX_ARRAY został wyłączony przez osobę, która wie, po pewnym czasie, więc ponowne włączenie go po zapisaniu glDrawArray mnie: glEnableClientState (GL_VERTEX_ARRAY); Nigdy nie miałem wyniku EXC_BAD_ACCESS jako niezdefiniowanego wyniku, ale jako nieoczekiwane wydanie pamięci, ale nie, nie było tu pamięci. Dzięki za podpowiedź, to było bardzo pomocne :) –

1

Funkcjonalność chec został zaakceptowany przez społeczność jako rozszerzenie WebGL:

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

+0

Ta odpowiedź nie wydaje się być odpowiednia dla pytania. Link wskazuje, że WebGL obsługuje teraz OES_vertex_array_object. Dobrze, ale nie odnosząc się do pytania. Przyjęta odpowiedź wyjaśnia, dlaczego VAO nie mogą być stosowane w sposób, o jaki się pytają, i udziela porad, co zrobić zamiast tego. – ToolmakerSteve