Quale stato è archiviato in un oggetto OpenGL Vertex Array Object (VAO) e come si utilizza VAO correttamente?


25

Mi chiedevo quale stato è archiviato in un VAO OpenGL. Ho capito che un VAO contiene uno stato correlato alle specifiche dei vertici dei vertici con buffer (quali attributi sono nei buffer e quali buffer sono associati, ...). Per comprendere meglio l'uso corretto dei VAO, mi piacerebbe sapere esattamente quale stato detengono.


Come presumo che VAO dovrebbe essere usato

Da semplici esempi, ho capito che l'uso corretto dei VAO è il seguente:

Impostare

Generate VAO
BindVAO
---- Specify vertex attributes
---- Generate VBO's
---- BindVBO's
-------- Buffer vertex data in VBO's
---- Unbind VBO's
Unbind VAO

interpretazione

Bind VAO
---- Draw
Unbind VAO

Da ciò, presumo che almeno le associazioni del buffer dei vertici e le specifiche degli attributi dei vertici siano archiviate nel VAO. Non sono sicuro, tuttavia, come questo modello di utilizzo si estenda a situazioni in cui (più) trame e (più) programmi shader entrano in gioco. Il programma shader attivo è memorizzato nel VAO? E anche i vincoli di trama (con le loro impostazioni di campionamento / avvolgimento ) sono memorizzati nel VAO? Idem per le uniformi ?


Pertanto, le mie domande sono:

  • Quale stato esatto è memorizzato in un VAO OpenGL ? (Collegamenti VBO, specifiche degli attributi, programma shader attivo, collegamenti trama, impostazioni campionamento / avvolgimento trama, uniformi ...?)
  • Come posso utilizzare correttamente i VAO in una configurazione di rendering più complessa in cui sono coinvolte (più) trame con impostazioni di campionamento / avvolgimento associate, (più) programmi shader e uniformi?

1
VAO memorizza i dati sulle posizioni degli attributi dei vertici. Memorizza anche gli ID dei VBO in cui sono contenuti questi attributi. Non è necessario associare VBO quando si disegna qualcosa, è necessario associarlo prima di chiamare glVertexAttribPointer () quando si crea VAO.
HolyBlackCat

Risposte:


18

VAO memorizza i dati sulle posizioni degli attributi dei vertici. (E alcuni altri dati ad essi correlati)
"VBO bindings, active shader program, texture bindings, texture sampling/wrapping settings, uniforms"sono completamente estranei ad esso.

Potresti chiedere perché non ricorda l'associazione VBO. Poiché non è necessario associare VBO per disegnare qualcosa, è necessario associarlo solo durante la creazione di VAO: quando si chiama glVertexAttribPointer(...), VAO ricorda quale VBO è attualmente associato. E VAO prenderà gli attributi da questi VBO quando lo disegnerai, anche se questi VBO non sono attualmente associati.


Inoltre, VAO e VBO devono essere usati in modo leggermente diverso:

Questo non funzionerà

Generate VAO
BindVAO
---- Specify vertex attributes
---- Generate VBO's
---- BindVBO's
-------- Buffer vertex data in VBO's
---- Unbind VBO's
Unbind VAO

perché devi associare VBO per specificare le posizioni degli attributi.

Quindi, dovresti farlo in questo modo:

Generate VAO
BindVAO
Generate VBO's
BindVBO's
Specify vertex attributes

Puoi modificare i dati di VBO ogni volta che vuoi, ma prima devi vincolarli.

E il disegno dovrebbe assomigliare a questo:

Bind VAO
Draw


Come avrai notato, ho rimosso le unbindchiamate dalle tue liste. Sono quasi completamente inutili e rallenteranno leggermente il programma, quindi non vedo alcun motivo per chiamarli.


9
"quindi non vedo alcun motivo per chiamarli." per evitare di cambiarli accidentalmente. Soprattutto un problema quando si usano librerie di terze parti.
maniaco del cricchetto,

Grazie per l'ottima risposta! Quindi, in breve, il VAO memorizza solo le posizioni degli attributi dei vertici. I VBO non vengono rimbalzati quando si associa un VAO, poiché il VAO sa in quali buffer trovare gli attributi. Tutti gli altri stati sono contenuti nello stato OpenGL globale.
Jelle van Campen,

@JellevanCampen Sì, corretto. Cordiali saluti, memorizza anche off / on stato degli attributi ( gl{Enable|Disable}VertexAttribArray()), i loro valori predefiniti ( glVertexAttrib*()), la loro modalità di istanza ( glVertexAttribDivisor()) e probabilmente qualcos'altro.
HolyBlackCat

@HolyBlackCat sei sicuro che lo stato predefinito (glVertexAttrib ()) sia parte dello stato VAO? La wiki di OpenGL afferma diversamente, dicendo che sono lo stato del contesto.
rdb,

@ndb No, non ne sono sicuro. Mi aspettavo che facessero parte dello stato VAO e non l'ho verificato.
HolyBlackCat

4

Memorizza solo l'associazione del vertice e l'associazione del buffer dell'indice

Questi sono tutti i parametri di glVertexAttribPointerpiù il buffer associato a Vertex_Array_buffer al momento della chiamata a glVertexAttribPointere Element_Array_buffer associato.

Le uniformi fanno parte del programma attuale.

Tutto il resto è stato globale.

Nel dubbio puoi controllare le tabelle di stato nelle specifiche della versione che stai usando.


Grazie anche per la risposta! Questo mi chiarisce le cose.
Jelle van Campen,

4

Ecco una spiegazione semplice ma efficace, fondamentalmente un oggetto buffer ha informazioni che possono essere interpretate come semplici bit di dati grezzi, che di per sé non significano nulla, quindi sono SOLO i dati che possono essere guardati in qualsiasi modo davvero

i.e float vbo[]={1.0,2.0,34.0...}

e il modo in cui OpenGL è stato progettato per funzionare è che DEFINI quali saranno i dati che il tuo passaggio ai vari shader assomiglierà agli shader

in quanto devi anche definire come leggerà quei dati, in che formato sono, e cosa farne e come verranno usati e per cosa, tutte queste informazioni sono archiviate nel VAO

ad esempio è possibile dichiarare i dati archiviati in un array come questo float vbo = {11.0,2.0,3.0,4.0}

ciò che è richiesto dopo a questo punto è come interpretare quei dati dal VBO nel VAO, e ciò significa che è il seguente

il VAO può essere impostato per leggere 2 float per vertice (che lo renderebbe 2 vettori con due dimensioni x, y) oppure si può dire al vao di interpretarlo come 1 vettore con 4 dimensioni cioè x, y, z, w etc

ma anche altri attributi di tali dati sono definiti e memorizzati nel VAO come il formato dei dati (nonostante abbia dichiarato un array di float, puoi dire allo shader di leggerlo come intero, con ovviamente il sistema che converte i dati grezzi in il processo da float a intero e ha un proprio set di regole cosa fare in tali circostanze)

Quindi fondamentalmente il VBO è i dati e il VAO memorizza come interpretarli, perché gli shader e il server OpenGL sono progettati per essere molto ficcanaso e devono sapere tutto prima che decida come elaborarli e cosa fare con esso e dove per dirla

ovviamente non è in realtà ficcanaso, in realtà sembra essere il più efficiente perché deve archiviare quei dati nella memoria del server grafico in modo che ottenga l'elaborazione più efficiente e rapida (a meno che non decida che non è necessario farlo se i dati non devono essere elaborati in questo modo e utilizzati per alcune altre informazioni a cui non si accede spesso), e quindi perché i dettagli di cosa fare con i dati e come elaborarli devono essere archiviati nel VAO, quindi il VAO è come un'intestazione e il VBO è come i dati grezzi puri che l'intestazione utilizza e definisce (in questo caso passa agli attributi del vertice dello shader) con l'eccezione che il VBO non è limitato solo per essere utilizzato da un VAO, esso può essere utilizzato e riutilizzato e associato a molti VAO, ad esempio:

quello che puoi fare è associare un oggetto buffer a VAO1 e anche (separatamente) associare lo stesso oggetto buffer a VAO2 con ciascuno di essi interpretandolo in modo diverso in modo che se lo shader dove elaborare i dati, a seconda di quale VAO è quello che è associato, elaborerebbe gli stessi dati grezzi in modo diverso rispetto al frambuffer (disegnando pixel sulla finestra) con conseguente diversa visualizzazione degli stessi dati che si baserebbe sul modo in cui hai definito il suo utilizzo nel VAO


Questa è la risposta migliore!
CodingMadeEasy
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.