Keadaan apa yang disimpan dalam Objek OpenGL Vertex Array Object (VAO) dan bagaimana cara menggunakan VAO dengan benar?


25

Saya bertanya-tanya keadaan apa yang disimpan dalam OpenGL VAO. Saya mengerti bahwa VAO berisi status yang terkait dengan spesifikasi verteks dari simpul buffer (atribut apa yang ada di buffer, dan buffer apa yang terikat, ...). Untuk lebih memahami penggunaan VAO yang benar, saya ingin tahu persis apa yang mereka miliki.


Bagaimana saya mengasumsikan VAO harus digunakan

Dari contoh sederhana, saya mengerti bahwa penggunaan yang benar dari VAO adalah sebagai berikut:

Mendirikan

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

Rendering

Bind VAO
---- Draw
Unbind VAO

Dari ini, saya berasumsi bahwa setidaknya binding buffer vertex dan spesifikasi atribut vertex disimpan dalam VAO. Namun saya tidak yakin bagaimana pola penggunaan ini meluas ke situasi di mana (banyak) tekstur dan (banyak) program shader ikut bermain. Apakah program shader aktif disimpan di VAO? Dan apakah binding tekstur (dengan pengaturan sampling / pembungkus ) disimpan di VAO juga? Ditto untuk seragam ?


Karena itu, pertanyaan saya adalah:

  • Keadaan apa tepatnya yang disimpan dalam OpenGL VAO ? (Binding VBO, spesifikasi atribut, program shader aktif, binding tekstur, pengaturan pengambilan sampel / pembungkus tekstur, seragam ...?)
  • Bagaimana cara menggunakan VAO dengan benar dalam pengaturan render yang lebih kompleks di mana (banyak) tekstur dengan pengaturan pengambilan sampel / pembungkus terkait, (banyak) program shader dan seragam terlibat?

1
VAO menyimpan data tentang lokasi atribut simpul. Itu juga menyimpan ID VBO di mana atribut ini terkandung. Anda tidak perlu mengikat VBO ketika Anda menggambar sesuatu, Anda harus mengikatnya sebelum memanggil glVertexAttribPointer () saat Anda membuat VAO.
HolyBlackCat

Jawaban:


18

VAO menyimpan data tentang lokasi atribut simpul. (Dan beberapa data lain yang terkait dengan mereka.)
"VBO bindings, active shader program, texture bindings, texture sampling/wrapping settings, uniforms"Sama sekali tidak terkait dengan itu.

Anda mungkin bertanya mengapa tidak ingat VBO mengikat. Karena Anda tidak perlu mengikat VBO untuk menggambar sesuatu, Anda hanya perlu mengikatnya saat membuat VAO: Ketika Anda menelepon glVertexAttribPointer(...), VAO mengingat apa yang terikat VBO saat ini. Dan VAO akan mengambil atribut dari VBO ini ketika Anda menggambarnya, bahkan jika VBO ini tidak terikat saat ini.


Juga, VAO dan VBO harus digunakan sedikit berbeda:

Ini tidak akan berfungsi

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

karena Anda perlu mengikat VBO untuk menentukan lokasi atribut.

Jadi, Anda harus melakukannya seperti ini:

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

Anda dapat mengubah data VBO kapan pun Anda mau, tetapi Anda harus mengikatnya sebelumnya.

Dan gambar akan terlihat seperti ini:

Bind VAO
Draw


Seperti yang Anda perhatikan, saya menghapus unbindpanggilan dari daftar Anda. Mereka hampir sepenuhnya tidak berguna dan mereka akan sedikit memperlambat program Anda, jadi saya tidak melihat alasan untuk memanggil mereka


9
"jadi saya tidak melihat alasan untuk memanggil mereka." untuk mencegah mengubahnya secara tidak sengaja. Terutama masalah saat menggunakan perpustakaan pihak ke-3.
ratchet freak

Terima kasih atas jawaban yang bagus! Jadi singkatnya, VAO hanya menyimpan lokasi atribut vertex. VBO tidak melambung ketika mengikat VAO, karena VAO tahu buffer apa yang harus dicari atributnya. Semua negara lain terkandung dalam keadaan OpenGL global.
Jelle van Campen

@JellevanCampen Yap, benar. FYI, itu juga menyimpan off / pada keadaan atribut ( gl{Enable|Disable}VertexAttribArray()), nilai default mereka ( glVertexAttrib*()), mode instancing mereka ( glVertexAttribDivisor()) dan mungkin sesuatu yang lain.
HolyBlackCat

@HolyBlackCat apakah Anda yakin status default (glVertexAttrib ()) adalah bagian dari status VAO? Wiki OpenGL mengklaim sebaliknya, mengatakan mereka adalah keadaan konteks.
rdb

@ndb Tidak, saya tidak yakin. Saya berharap mereka menjadi bagian dari negara bagian VAO, dan saya tidak memeriksanya.
HolyBlackCat

4

Ini hanya menyimpan pengikatan simpul dan pengikatan buffer indeks

Itu semua parameter glVertexAttribPointerditambah buffer terikat ke Vertex_Array_buffer pada saat panggilan ke glVertexAttribPointerdan Element_Array_buffer terikat.

Seragam adalah bagian dari program saat ini.

Yang lainnya adalah keadaan global.

Dalam keraguan Anda dapat memeriksa tabel status dalam spesifikasi versi yang Anda gunakan.


Terima kasih atas jawabannya juga! Ini jelas bagi saya.
Jelle van Campen

4

Berikut ini adalah penjelasan yang sederhana namun efektif, pada dasarnya objek penyangga memiliki informasi yang dapat diartikan sebagai hanya bit data mentah, yang dengan sendirinya tidak berarti apa-apa, sehingga MURNI data yang dapat dilihat dengan cara apa pun

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

dan cara OpenGL dirancang untuk bekerja adalah bahwa Anda harus MENGEMBANGKAN data apa yang akan Anda sampaikan ke berbagai shader terlihat seperti ke shader

di mana Anda juga harus menentukan bagaimana ia akan membaca data itu, apa formatnya, dan apa yang harus dilakukan dengannya dan bagaimana itu akan digunakan dan untuk apa, semua informasi ini disimpan dalam VAO

misalnya Anda dapat mendeklarasikan data yang disimpan dalam array seperti ini float vbo = {11.0,2.0,3.0,4.0}

apa yang diperlukan selanjutnya pada titik ini adalah bagaimana menafsirkan data itu dari VBO di VAO, dan apa artinya itu sebagai berikut

VAO dapat diatur untuk membaca 2 float per vertex (yang akan membuatnya 2 vektor dengan dua dimensi x, y) atau Anda dapat memberitahu vao untuk menafsirkannya sebagai 1 vektor dengan 4 dimensi yaitu x, y, z, w dll

tetapi juga atribut lain dari data yang didefinisikan dan disimpan dalam VAO seperti format data (meskipun Anda mendeklarasikan array float, Anda dapat memberi tahu shader untuk membacanya sebagai integer, dengan tentu saja sistem mengubah data mentah di proses dari float ke integer dan memiliki seperangkat aturan sendiri apa yang harus dilakukan dalam keadaan seperti itu)

Jadi pada dasarnya VBO adalah datanya, dan VAO menyimpan cara menginterpretasikan data itu, karena shader dan server OpenGL dirancang untuk menjadi sangat usil dan perlu tahu segalanya sebelum memutuskan bagaimana memprosesnya dan apa yang harus dilakukan dengan itu dan di mana untuk meletakkannya

tentu saja itu tidak benar-benar usil, itu sebenarnya terlihat paling efisien karena perlu menyimpan data itu pada memori server grafis sehingga mendapatkan pemrosesan yang paling efisien dan tercepat (kecuali ia memutuskan bahwa itu tidak perlu melakukan ini jika data tidak akan diproses sedemikian rupa dan digunakan untuk beberapa informasi lain yang tidak sering diakses), dan karenanya mengapa perincian tentang apa yang harus dilakukan dengan data dan bagaimana memprosesnya diperlukan untuk disimpan dalam VAO, jadi VAO seperti header dan VBO seperti data mentah murni yang digunakan dan didefinisikan header (dalam hal ini beralih ke atribut vertex shader) dengan pengecualian bahwa VBO tidak terbatas hanya untuk digunakan oleh satu VAO, itu dapat digunakan dan digunakan kembali dan terikat pada banyak VAO misalnya:

apa yang dapat Anda lakukan adalah Anda dapat mengikat satu objek buffer ke VAO1 dan juga (secara terpisah) mengikat objek buffer yang sama ke VAO2 dengan masing-masing menginterpretasikannya secara berbeda sehingga jika shader Anda di mana memproses data, tergantung pada VAO mana yang terikat itu akan memproses data mentah yang sama secara berbeda ke frambuffer (menggambar piksel ke jendela) menghasilkan tampilan yang berbeda dari data yang sama yang akan didasarkan pada bagaimana Anda mendefinisikan penggunaannya dalam VAO


Ini jawaban terbaik!
CodingMadeEasy
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.