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