Ada banyak pendekatan, tetapi tidak ada yang sempurna.
Dimungkinkan untuk berbagi kode dengan menggunakan glAttachShaderuntuk menggabungkan shader, tetapi ini tidak memungkinkan untuk membagikan hal-hal seperti deklarasi struct atau #definekonstanta -d. Itu berfungsi untuk fungsi berbagi.
Beberapa orang suka menggunakan array string yang diteruskan glShaderSourcesebagai cara untuk menambahkan definisi umum sebelum kode Anda, tetapi ini memiliki beberapa kelemahan:
- Lebih sulit untuk mengontrol apa yang perlu dimasukkan dari dalam shader (Anda memerlukan sistem terpisah untuk ini.)
- Ini berarti pembuat shader tidak dapat menentukan GLSL
#version, karena pernyataan berikut dalam spesifikasi GLSL:
The # versi direktif harus terjadi dalam shader sebelum hal lain, kecuali untuk komentar dan ruang putih.
Karena pernyataan ini, glShaderSourcetidak dapat digunakan untuk menambahkan teks sebelum #versiondeklarasi. Ini berarti bahwa #versionbaris tersebut perlu dimasukkan dalam glShaderSourceargumen Anda , yang berarti bahwa antarmuka kompiler GLSL Anda perlu entah bagaimana diberitahu versi GLSL apa yang diharapkan akan digunakan. Selain itu, tidak menentukan #versionakan membuat kompiler GLSL default untuk menggunakan GLSL versi 1.10. Jika Anda ingin membiarkan penulis shader menentukan #versionskrip dalam cara standar, maka Anda harus memasukkan #include-s setelah #versionpernyataan tersebut. Ini bisa dilakukan dengan menguraikan GLSL shader secara eksplisit untuk menemukan #versionstring (jika ada) dan membuat inklusi Anda setelahnya, tetapi memiliki akses ke#includearahan mungkin lebih disukai untuk dikontrol dengan lebih mudah ketika inklusi tersebut perlu dibuat. Di sisi lain, karena GLSL mengabaikan komentar sebelum #versionbaris, Anda dapat menambahkan metadata untuk memasukkan dalam komentar di bagian atas file Anda (yuck.)
Pertanyaannya sekarang adalah: Apakah ada solusi standar untuk #include, atau Anda perlu menggulung ekstensi preprosesor Anda sendiri?
Ada GL_ARB_shading_language_includeekstensi, tetapi memiliki beberapa kelemahan:
- Ini hanya didukung oleh NVIDIA ( http://delphigl.de/glcapsviewer/listreports2.php?listreportsbyextension=GL_ARB_shading_language_include )
- Ini bekerja dengan menentukan string termasuk sebelumnya. Oleh karena itu, sebelum kompilasi, Anda perlu menentukan bahwa string
"/buffers.glsl"(seperti yang digunakan dalam #include "/buffers.glsl") sesuai dengan isi file buffer.glsl(yang telah Anda muat sebelumnya).
- Seperti yang mungkin Anda perhatikan pada poin (2), jalur Anda harus memulainya
"/", seperti jalur absolut gaya Linux. Notasi ini umumnya tidak dikenal oleh programmer C, dan berarti Anda tidak dapat menentukan jalur relatif.
Desain umum adalah untuk mengimplementasikan #includemekanisme Anda sendiri , tetapi ini bisa rumit karena Anda juga perlu mem-parsing (dan mengevaluasi) instruksi preprosesor lain seperti #ifuntuk menangani dengan benar kompilasi bersyarat (seperti pelindung kepala.)
Jika Anda menerapkan sendiri #include, Anda juga memiliki beberapa kebebasan dalam cara Anda ingin menerapkannya:
- Anda dapat melewati string sebelumnya (seperti
GL_ARB_shading_language_include).
- Anda bisa menentukan callback include (ini dilakukan oleh perpustakaan D3DCompiler DirectX.)
- Anda bisa mengimplementasikan sistem yang selalu membaca langsung dari sistem file, seperti yang dilakukan pada aplikasi C yang khas.
Sebagai penyederhanaan, Anda dapat secara otomatis memasukkan pelindung tajuk untuk masing-masing termasuk dalam lapisan preprocessing Anda, sehingga lapisan prosesor Anda terlihat seperti:
if (#include and not_included_yet) include_file();
(Penghargaan untuk Trent Reed karena menunjukkan saya teknik di atas)
Kesimpulannya , tidak ada solusi otomatis, standar, dan sederhana. Dalam solusi masa depan, Anda bisa menggunakan beberapa antarmuka OpenGL SPIR-V, dalam hal ini kompiler GLSL ke SPIR-V bisa berada di luar API GL. Memiliki kompiler di luar runtime OpenGL sangat menyederhanakan menerapkan hal-hal seperti #includekarena ini adalah tempat yang lebih tepat untuk berinteraksi dengan sistem file. Saya percaya metode luas saat ini adalah dengan hanya mengimplementasikan preprocessor kustom yang bekerja dengan cara yang harus akrab dengan programmer C.