Saya belajar OpenGL baru-baru ini. Dalam game, kita perlu memperbarui posisi objek game secara teratur, dan mereka akan keluar masuk layar terus-menerus. Jadi itu berarti dalam rendering kita perlu memperbarui buffer vertex cukup sering juga.
Dalam konteks OpenGL, salah satu cara intuitif adalah menggunakan glBufferSubData untuk memperbarui yang berubah.
Tetapi saya juga membaca secara online sebuah trik yang disebut Orphaning yang menciptakan data buffer baru dan mengunggah seluruh data simpul ke dalamnya.
Juga karena menyatakan biaya chagnes dan biaya unggah, beberapa glBufferSubData juga mungkin lebih mahal.
Ini pertanyaan saya,
- Metode mana yang lebih baik?
- Apakah warung benar-benar penting dalam kasus ini?
- Apakah perubahan negara dan biaya pengunggahan benar-benar penting dalam kasus ini?
Terima kasih!
opengl
rendering
optimization
vbo
YiFeng
sumber
sumber
Jawaban:
Ini adalah pertanyaan kompleks dengan banyak detail kecil yang sangat penting, kinerjanya akan bervariasi berdasarkan platform dan aplikasi. Jadi, Anda harus membuat profil untuk kemungkinan kemacetan sebelum berinvestasi dalam optimasi.
Yang mengatakan, pertama, saya menganggap Anda harus mengurangi unggahan dan pembaruan sebanyak yang Anda bisa, misalnya menggunakan instancing.
Kedua, perhatikan bahwa GPU tidak dapat mentransfer buffer dan render secara bersamaan, sehingga semua perintah OpenGL dalam antrian perintah diproses secara berurutan oleh perangkat. Ada berbagai cara untuk menyalin data dan / atau membuatnya tersedia untuk digunakan oleh GPU.
Ada berbagai cara untuk mengalirkan data ke GPU
1-
glBufferData
atauglBufferSubData
metodeMenggunakan
glBufferData
atauglBufferSubData
seperti memcpy. Anda melewati pointer dan operasi DMA mungkin dilakukan, saya katakan mungkin karena memori mungkin disematkan dalam memori CPU dan digunakan langsung oleh GPU tanpa benar-benar transfer memori ke GPU terjadi, tergantung pada flag penggunaan (GL_STREAM). Menurut pendapat Anda harus mencoba ini pada awalnya karena lebih mudah untuk diterapkan.2- mendapatkan pointer ke memori internal menggunakan
glMapBuffer
Jika hal di atas tidak cukup baik untuk Anda gunakan
glMapBuffer
, Anda mendapatkan pointer ke memori internal, dan Anda dapat menggunakan pointer ini untuk mengisi buffer secara langsung, ini bagus untuk operasi membaca dan menulis file, karena Anda dapat langsung memetakan data file ke memori GPU daripada menyalin ke buffer temp terlebih dahulu. Jika Anda tidak ingin memetakan seluruh buffer yang dapat Anda gunakanglMapBufferRange
yang dapat digunakan untuk memetakan sebagian buffer.Salah satu triknya adalah membuat buffer besar, gunakan bagian pertama untuk rendering dan bagian kedua untuk memperbarui.
3- Buffer Yatim Piatu
Mengenai buffer orphaning ini dapat dilakukan menggunakan glBufferData dengan null dan parameter yang sama. Pengemudi akan mengembalikan blok memori setelah tidak digunakan. Dan akan digunakan oleh panggilan glBufferData berikutnya (tidak ada memori baru akan dialokasikan).
Semua metode yang disebutkan menyebabkan banyak sinkronisasi yang mahal, sekali lagi GPU tidak dapat mentransfer buffer dan render pada saat yang sama.
4-
Unsynchronized Buffers
Metode tercepat (dan paling sulit untuk mendapatkan yang benar) adalah dengan menggunakan buffer tanpa sinkronisasi, Anda dapat menggunakan
GL_MAP_UNSYNCHRONIZED_BIT
flagglMapBufferRange
, masalahnya adalah tidak ada sinkronisasi yang dilakukan, jadi kami mungkin mengunggah data ke buffer yang mulai digunakan, dan karenanya mengacaukan semuanya. Anda dapat menggunakan beberapa buffer dengan bit yang tidak disinkronkan untuk mempermudah.sumber
Saya melakukannya dengan cara lain. Mungkin ada sesuatu yang salah di sana. Beberapa hal berbahaya tersembunyi.
(Saya menggunakan C # + OpenTK.GameWindow)
Untuk instancing objek saya menggunakan Array Buffer Object terpisah untuk set matriks model untuk setiap instance. Di dalam simpul yang dibagikan:
Dalam kode C # saya matriks disimpan dalam array float
float[] mat4_array
Lalu saya ikat array ke Array Buffer Object:
Setiap bingkai matriks model diperbarui. Untuk memperbarui,
mat4_array
saya hanya menelepon:dan membuat adegan. menggunakan
GL.DrawElementsInstanced
.Tidak ada panggilan OpenGL tambahan dan berfungsi dengan baik.
sumber