มีวิธีการมากมาย แต่ไม่มีใครสมบูรณ์แบบ
เป็นไปได้ที่จะแบ่งปันรหัสโดยใช้glAttachShader
เพื่อรวมเฉดสี แต่มันไม่สามารถแชร์สิ่งต่าง ๆ เช่น struct declarations หรือ#define
-d constants มันใช้งานได้สำหรับฟังก์ชั่นการแบ่งปัน
บางคนชอบใช้อาเรย์ของสตริงที่ส่งไปเพื่อglShaderSource
เป็นวิธีในการเติมคำจำกัดความทั่วไปก่อนโค้ดของคุณ แต่สิ่งนี้มีข้อเสียบางประการ:
- เป็นการยากที่จะควบคุมสิ่งที่จะต้องรวมอยู่ในภายใน shader (คุณต้องมีระบบแยกต่างหากสำหรับสิ่งนี้)
- หมายความว่าผู้สร้าง shader ไม่สามารถระบุ GLSL
#version
ได้เนื่องจากคำสั่งต่อไปนี้ในข้อมูลจำเพาะ GLSL:
#versionสั่งจะต้องเกิดขึ้นใน Shader ก่อนสิ่งอื่นใดยกเว้นสำหรับความคิดเห็นและพื้นที่สีขาว
เนื่องจากคำสั่งนี้glShaderSource
ไม่สามารถใช้เพื่อเติมข้อความก่อนการ#version
ประกาศ หมายความว่า#version
บรรทัดจะต้องรวมอยู่ในglShaderSource
อาร์กิวเมนต์ของคุณซึ่งหมายความว่าอินเทอร์เฟซคอมไพเลอร์ GLSL ของคุณจำเป็นต้องได้รับการบอกกล่าวว่าควรใช้ GLSL เวอร์ชันใด นอกจากนี้การไม่ระบุ#version
จะทำให้คอมไพเลอร์ GLSL เป็นค่าเริ่มต้นเพื่อใช้ GLSL เวอร์ชัน 1.10 หากคุณต้องการให้ผู้เขียน shader ระบุ#version
สคริปต์ภายในด้วยวิธีมาตรฐานคุณต้องแทรก#include
-s หลังจาก#version
คำสั่ง สิ่งนี้สามารถทำได้โดยการแยกวิเคราะห์ GLSL shader อย่างชัดเจนเพื่อค้นหา#version
สตริง (ถ้ามี) และทำการรวมของคุณหลังจากนั้น แต่มีการเข้าถึง#include
คำสั่งอาจจะดีกว่าที่จะควบคุมได้ง่ายขึ้นเมื่อรวมสิ่งเหล่านั้นจะต้องทำ ในทางกลับกันเนื่องจาก GLSL ละเว้นความคิดเห็นก่อน#version
บรรทัดคุณสามารถเพิ่มข้อมูลเมตาสำหรับรวมไว้ในความคิดเห็นที่ด้านบนของไฟล์ของคุณ (yuck)
ตอนนี้คำถามคือ: มีวิธีแก้ปัญหามาตรฐาน#include
หรือคุณต้องการม้วนส่วนขยายตัวประมวลผลล่วงหน้าของคุณเองหรือไม่?
มีGL_ARB_shading_language_include
ส่วนขยาย แต่มีข้อเสีย:
- รองรับโดย NVIDIA เท่านั้น ( http://delphigl.de/glcapsviewer/listreports2.php?listreportsbyextension=GL_ARB_shading_language_include )
- มันทำงานได้โดยการระบุสตริงรวมก่อนเวลา ดังนั้นก่อนที่จะรวบรวมคุณจะต้องระบุว่าสตริง
"/buffers.glsl"
(ตามที่ใช้ใน#include "/buffers.glsl"
) สอดคล้องกับเนื้อหาของไฟล์buffer.glsl
(ซึ่งคุณโหลดไว้ก่อนหน้านี้)
- ดังที่คุณอาจสังเกตเห็นในจุด (2) พา ธ ของคุณต้องเริ่มต้นด้วย
"/"
เช่นพา ธ สัมบูรณ์สไตล์ Linux โดยทั่วไปแล้วสัญกรณ์นี้ไม่คุ้นเคยกับโปรแกรมเมอร์ C และหมายความว่าคุณไม่สามารถระบุเส้นทางที่สัมพันธ์กันได้
การออกแบบทั่วไปคือการใช้#include
กลไกของคุณเองแต่อาจเป็นเรื่องยุ่งยากเนื่องจากคุณต้องแยกวิเคราะห์ (และประเมิน) คำสั่ง preprocessor อื่น ๆ เช่น#if
เพื่อจัดการการคอมไพล์ที่มีเงื่อนไข (เช่น guards header)
หากคุณใช้งานของคุณเอง#include
คุณยังมีเสรีภาพในวิธีที่คุณต้องการติดตั้ง:
- คุณสามารถส่งผ่านสตริงล่วงหน้า (เช่น
GL_ARB_shading_language_include
)
- คุณสามารถระบุการโทรกลับแบบรวม (ทำได้โดยไลบรารี D3DCompiler ของ DirectX)
- คุณสามารถใช้ระบบที่อ่านได้โดยตรงจากระบบไฟล์เช่นเดียวกับที่ทำในแอพพลิเคชั่น C ทั่วไป
เพื่อให้เข้าใจง่ายคุณสามารถแทรกตัวป้องกันส่วนหัวสำหรับแต่ละรายการในเลเยอร์การประมวลผลล่วงหน้าของคุณได้ดังนั้นเลเยอร์โปรเซสเซอร์ของคุณจะมีลักษณะดังนี้:
if (#include and not_included_yet) include_file();
(Credit to Trent Reed เพื่อแสดงเทคนิคด้านบน)
โดยสรุปแล้วไม่มีวิธีการแก้ปัญหาอัตโนมัติมาตรฐานและเรียบง่าย ในการแก้ปัญหาในอนาคตคุณสามารถใช้อินเทอร์เฟซ SPIR-V OpenGL บางส่วนซึ่งในกรณีนี้คอมไพเลอร์ GLSL to SPIR-V อาจอยู่นอก GL API การมีคอมไพเลอร์นอกรันไทม์ OpenGL ช่วยลดความยุ่งยากในการนำสิ่งต่าง ๆ มาใช้เช่น#include
เนื่องจากเป็นสถานที่ที่เหมาะสมกว่าในการเชื่อมต่อกับระบบไฟล์ ฉันเชื่อว่าวิธีการที่แพร่หลายในปัจจุบันคือการใช้ตัวประมวลผลล่วงหน้าที่กำหนดเองซึ่งทำงานในลักษณะที่โปรแกรมเมอร์ C คนใดคนหนึ่งควรคุ้นเคย