Apa metode terbaik untuk memperbarui seragam shader?

10

Apa cara yang paling diterima untuk memperbarui matriks shader, dan mengapa?

Sebagai contoh, saat ini saya memiliki Shaderkelas yang menyimpan pegangan ke program & seragam shader GLSL. Setiap kali saya memindahkan kamera saya kemudian harus melewatkan view view matrix ke shader, maka setiap objek dunia yang berbeda saya harus memberikan model matrixnya ke shader.

Ini sangat membatasi saya karena saya tidak bisa melakukan apa pun tanpa memiliki akses ke objek shader itu.

Saya berpikir untuk membuat ShaderManagerkelas tunggal yang bertanggung jawab untuk memegang semua shader aktif. Saya kemudian dapat mengaksesnya dari mana saja dan objek dunia tidak perlu tahu tentang apa yang aktif shaders hanya perlu memberi ShaderManagertahu matriks yang diinginkan tapi saya tidak yakin ini adalah cara terbaik dan mungkin ada beberapa masalah yang akan timbul dari mengambil pendekatan ini.

Lerp
sumber
Mengapa tidak meneruskan data ke shader saat saatnya membuat?
Nick Caplinger
Itu yang saya maksudkan tapi bagaimana caranya? Jika satu objek menciptakan shader maka bagaimana objek dunia seharusnya tahu tentang keberadaan shader itu dan memberikannya matriks yang diperlukan?
Lerp

Jawaban:

11

Gunakan buffer seragam (yaitu buffer konstan dalam istilah D3D).

Selama semua shader Anda menyetujui tata letak dan titik pengikatan masing-masing buffer kemudian memperbarui menjadi mudah. Model tidak perlu tahu apa-apa tentang shader sama sekali. Mereka hanya perlu memperbarui model-view matrix dalam buffer konstan dan pipeline rendering akan menggunakannya secara otomatis.

Paling tidak saya berpendapat Anda harus memiliki dua buffer seperti itu. Yang pertama harus menyimpan matriks proyeksi, matriks kamera, matriks proyeksi-kamera yang digabungkan, informasi viewport, detail frustrum, dan inverses matriks. Anda hanya perlu memperbarui buffer ini sekali per adegan.

Kemudian berikan masing-masing model buffer lain untuk menyimpan model-view matrix, normal matrix, inverses, dan properti materialnya. Ini diperbarui sekali untuk masing-masing model dan dapat dilakukan dalam pass pembaruan yang berbeda (jika / bila perlu). Informasi material dapat / harus dipindahkan ke buffer spesifik material ketiga jika Anda memiliki kemampuan untuk berbagi materi antara beberapa objek.

Dalam pengaturan penerusan ke depan, masuk akal untuk menempatkan semua lampu di buffer lain dan dalam naungan ditangguhkan juga masuk akal untuk menggunakan buffer per-cahaya untuk lampu lulus (sebagai pengganti model / material buffer yang digunakan dalam lulus geometri).

Perhatikan bahwa Anda memerlukan versi GL yang cukup terbaru untuk menggunakan buffer yang sama sekali (3,1 atau ekstensi; cukup umum hari ini kecuali pada beberapa laptop yang lebih tua tetapi masih dalam layanan) dan Anda memerlukan versi yang cukup baru untuk menjadi dapat mengikat buffer seragam ke lokasi pengikatan tertentu dari dalam kode shader (4.2; masih jarang tetapi menjadi lebih baik) jika tidak, Anda harus melakukan lebih banyak pekerjaan dalam kode sisi CPU Anda untuk mengatur sesuatu (kode CPU Anda perlu mengetahui ikatan yang benar tetap menunjukkan, jadi ini lebih merupakan bau API daripada masalah serius). Sayangnya OpenGL | ES tidak menambahkan buffer yang seragam hingga 3.0 yang masih tidak didukung pada platform seluler paling populer.

Jika buffer bukan opsi maka Anda akan memerlukan tempat global untuk menyimpan lokasi indeks untuk shader aktif. Anda dapat menggunakan glGetUniformLocationsetelah memuat shader Anda untuk menemukan indeks untuk nama-nama terkenal (suka ModelViewMatrixatau sejenisnya) kemudian menyimpan indeks ini. Render Anda dapat memetakan nilai enum seperti yang MODEL_VIEWditeruskan ke SetUniformfungsi pembungkus untuk melihat ke dalam shader terikat, menemukan indeks, dan memanggil glUniformdengan benar. Ini bukan perubahan besar khusus dalam penggunaan kode klien dari buffer selain perlu mengatur setiap seragam secara terpisah jika Anda mendapatkan semuanya dibungkus dengan baik.

Lihat Blok Inteface GLSL dan Objek Penyangga Seragam .

Sean Middleditch
sumber
Saya tahu mereka akan menjadi cara bawaan. Terima kasih!
Lerp
4

Cara paling sederhana untuk melakukan ini adalah dengan membakukan nama seragam antara shader Anda dan hanya mengirim semua data tepat sebelum Anda menggambar. Overheadnya tidak gila, tetapi Anda bisa mengoptimalkannya nanti untuk tidak selalu mengirim seragam yang lebih baru.

Cara saya melakukan ini dalam permainan saya adalah bahwa saya memiliki Materialkelas abstrak . Materi bertindak sebagai jembatan antara game dan shader. Masing-masing Materialmemiliki Shaderdan berbagai properti yang dapat diatur, termasuk tekstur. Ketika tiba waktunya untuk menggambar objek, Materialitu terikat. The BindMetode memiliki GraphicsStateparameter yang berisi semua negara grafis saat ini - matriks, lampu, dll Bindmetode mengikat shader dan tekstur dan set semua seragam, menggunakan apa yang dibutuhkan dari GraphicsState.

Robert Rouhani
sumber