Haruskah melepas ikatan buffer?

12

Saya membuat beberapa tes dengan OpenGL ES 2 dan mendapat beberapa pertanyaan, program saya saat ini seperti itu:

Init
-------
-> create index buffer
-> fill index buffer glBufferData 
-> create vertex buffer
-> fill vertex buffer glBufferData 

Draw
-------
 1. Apply vertex buffer

    -> Bind VAO
       -> bind vertex buffer
          - enable attributs (glVertexPointer, …)
       -> unbind vertex buffer
    -> Unbind VAO
    -> Bind VAO

 3. Apply index buffer
 4. Draw

Masalah

Kode yang diberikan macet, setelah beberapa penelitian, saya mengerti mengapa: Saya perlu melepaskan ikatan buffer indeks saya di bagian init (setelah "mengisi indeks buffer glBufferData") atau melepas ikatan sebelum "Bind VAO" pertama

Pertanyaan saya adalah:

  • Dapatkah saya menempatkan buffer indeks saya di VAO (buffer indeks saham VAO?)?
  • Apakah saya harus melepaskan ikatan buffer setelah setiap pembaruan (glBufferData)?

Dalam aplikasi saya, saya punya beberapa buffer yang diperbarui pada setiap frame (Contoh: Partikel) jadi saya punya tumpukan OpenGL seperti itu:

-> bind buffer 1
-> update buffer 1
-> close buffer 1
-> bind buffer 1
-> draw

3 baris pertama memperbarui buffer Vertex, dua objek undian terakhir, yang seharusnya seperti itu:

-> bind buffer 1
-> update buffer 1
-> draw

Terima kasih

user30088
sumber

Jawaban:

12

Anda tampaknya melakukan banyak hal pada ikatan yang tidak perlu / tidak mengikat. Jika Anda menggunakan VAO, maka Anda hanya harus mengikat VAO ketika Anda mengaturnya dan ketika menggambar geometri. Anda hanya mengikat VBO / IBO lagi saat Anda perlu memperbaruinya.

Setelah menggambar atau memperbarui buffer, Anda tidak perlu melepaskan ikatannya, meskipun mungkin itu ide yang baik untuk menghindari penulisan yang tidak disengaja ke buffer yang terikat.

Sekarang mengambil urutan operasi pertama Anda, ini adalah urutan keseluruhan yang saya harapkan untuk dilihat:

Di init:

  1. Buat & ikat VAO. VBO dan IBO apa pun yang Anda ikat dalam urutan akan dikaitkan dengan VAO saat ini (yang ini).

  2. Buat & ikat buffer indeks.

    • Isi buffer indeks dengan glBufferData/glMapBuffer.
  3. Buat & ikat penyangga dhuwur.

    • Isi buffer vertex glBufferData/glMapBuffer.
  4. Atur atribut vertex dengan glEnableVertexAttribArray/glVertexAttribPointer, dll.

  5. Secara opsional batalkan segalanya untuk menghindari modifikasi buffer dan VAO yang tidak disengaja. Ingatlah untuk melepaskan ikatan VAO terlebih dahulu . Misalnya:glBindVertexArray(0);

Sedang diundi:

  1. Jika hanya menggambar buffer :

    • Bind the VAO;
    • Lakukan panggilan undian.
  2. Jika memperbarui dan menggambar :

    • Mengikat VAO, VBO, IBO;
    • Perbarui buffer (memperbarui atribut vertex hanya diperlukan jika format vertex telah berubah);
    • Lakukan panggilan undian.
  3. Secara opsional lepaskan ikatan untuk menghindari modifikasi buffer dan VAO yang tidak disengaja.

Itu sesederhana itu. Urutan operasi ini harus berfungsi tanpa masalah.

Glampert
sumber
2
Saya ingin menambahkan bahwa dalam percobaan saya (2014) dengan kasus nyata (tetapi shader sederhana agar tidak mengalami hambatan pada GPU) Saya menemukan peningkatan kinerja menggunakan VAO tidak signifikan (<penghematan CPU 2%) setelah pemesanan yang tepat panggilan render diimplementasikan untuk sepenuhnya melewatkan pengaturan VBO ketika menggunakan VBO yang sama pada panggilan render berturut-turut (penghematan CPU 10 hingga 33%), dan saya menekan beberapa bug driver dengan VAO jadi saya akhirnya mematikannya secara default. Itu bahkan kurang signifikan ketika menggunakan shader kompleks, MSAA, dll, yang macet di GPU meninggalkan CPU diam-diam menunggu bahkan di ponsel.
Stephane Hockenhull
2
Perhatikan bahwa menyelaraskan data verteks dengan cara yang tidak didukung oleh perangkat keras akan memaksa driver GPU untuk memesan ulang data VBO pada setiap pengaturan sementara driver dapat memesan ulang satu kali dengan VAO selama tidak ada yang berubah begitu YMMV. Paling baik untuk menyejajarkan & pad data verteks.
Stephane Hockenhull
1
Mengapa VAO harus tidak terikat sebelum yang lainnya?
Daniel Safari
@DanielSafari, maksud Anda setelah pengaturan? Jika Anda akan melepaskan ikatan buffer terlebih dahulu (binding buffer 0 / null), itu akan menghapus titik mengikat di VAO saat ini. Itu sebabnya null VAO harus ditetapkan terlebih dahulu.
glampert
@ glampert - tidak, itu bukan cara kerja binding; binding buffer digunakan ketika glVertexAttribPointer dipanggil, dan bukan sebaliknya (pengecualian: GL_ELEMENT_ARRAY_BUFFER). Mengubah binding buffer setelah panggilan glVertexAttribPointer Anda tidak berpengaruh.
Maximus Minimus