我一定是误解了着色器:
我认为,由于您可以将多个着色器附加到一个程序,因此您可以简单地附加多个片段着色器,例如:使用颜色调制和呈现的条带纹理折射。
但显然事实并非如此,因为每个程序只能有一个主要功能。
答案 0 :(得分:22)
您可以预先定义一组入口点。假设您的效果数量有限(漫反射,镜面反射,环境等)。它们中没有一个最多应用一次,因此您只需要创建一个像这样的管理着色器:
void apply_diffuse();
void apply_specular();
void apply_environment();
void main(){ ...
apply_diffuse();
apply_specular();
apply_environment();
...}
然后,当链接着色器程序时,将相应的实现作为单独的GLSL对象附加。如果您不想要效果,某些实现可能是假人。这种方法不需要源文本解析,并且几乎没有性能损失。
答案 1 :(得分:10)
你做不到。这被称为着色器的组合爆炸。您可以使用大型着色器 - 称为Übershader方法 - 或者我相信您可以通过弄乱预处理器并生成动态所需的着色器来实现它。
较新版本的GLSL应支持虚拟功能,允许您像在CPU代码中一样模块化地构建它们 - HLSL5。
答案 2 :(得分:1)
问题在于您使用的术语。
让我做一个相似的事情:
如您所见,着色器程序是可执行文件。它链接多个着色器对象。每个着色器对象都是从源编译的。对于通常的可执行文件,只有一个主入口点,它只由一个着色器对象定义。就像编译任何编译工具链一样。
解决方案是着色器对象组合和着色器程序数量之间的良好平衡。当然,只有一个着色器程序可以渲染,但是假装太多了:尝试对着色器功能进行分解,然后根据需要单独编译这些功能和链接。
你必须看看OpenGL Registry,我想你可能会在扩展名单中找到一些有趣的东西。
答案 3 :(得分:-3)
您可以在着色器中使用多个程序,但不能相反。
要进行多种组合,最简单的方法是将每个主要块作为带有命名入口点的片段存储,然后将它们包含在另一个程序中,或者在运行时将它们组合到一个程序中,按照您需要的顺序调用它们。在处理输入和输出时,这可能会变得混乱。
你可以使用多次传球,每次传球都有不同的效果和程序。这有一些额外的开销,但可以更容易设置。