GLSL问题:一个程序中有多个着色器

GLSL Problem: Multiple shaders in one program

本文关键字:程序 一个 问题 GLSL      更新时间:2023-10-16

我一定是误解了shaders:

我认为,因为你可以附加多个着色器到一个程序,你可以简单地附加多个片段着色器,作为一个例子:一个板条箱纹理渲染与颜色调制折射。

但显然情况并非如此,因为每个程序只能有一个main函数。

  • 我如何才能围绕主要功能限制工作,并允许在同一程序中并相互调用的多个片段着色器的任何动态组合?

您可以预定义一组入口点。假设你有有限数量的效果(漫射、镜面、环境等)。它们最多不会应用一次,所以你只需要创建一个管理着色器,就像这样:

void apply_diffuse();
void apply_specular();
void apply_environment();
void main(){ ...
     apply_diffuse();
     apply_specular();
     apply_environment();
...}

然后,当需要链接着色器程序时,将相应的实现附加为单独的GLSL对象。如果您不想要效果,有些实现可能是假的。这种方法不需要源文本解析,并且几乎没有性能损失。

你不能。这被称为着色器的组合爆炸。要么你使用大量着色器-称为Übershader方法-或者我相信你可以通过扰乱预处理器并动态生成你需要的着色器来实现它。

新版本的GLSL应该支持虚函数,它允许你像在CPU代码中那样模块化地构建虚函数——HLSL5就是这样做的。

问题出在你使用的术语上。

让我做一个类比:

  • 可执行文件由链接的对象组成,对象从源代码编译。
  • 一个着色器程序是由链接的着色器对象组成的,着色器对象是从源代码编译的。

如你所见,着色器程序是可执行的。它链接多个着色器对象。每个着色器对象都是从一个源编译的。对于通常的可执行文件,只有一个主入口点,它只由一个着色器对象定义。就像用任何编译工具链编译一样。

解决方案是在着色器对象组合和着色器程序数量之间取得良好的平衡。当然,只有一个着色器程序用于渲染是很漂亮的,但这是假装太多了:尝试分解着色器功能,然后分别编译这些功能并根据需要链接。

你一定要看一下OpenGL Registry,我想你可能会在扩展列表中发现一些有趣的东西。

你可以在一个shader中有多个程序,但不能反过来。

要进行多个组合,最简单的方法是将每个主要块存储为带有命名入口点的片段,然后从另一个程序中包含它们,或者在运行时将它们组合到一个程序中,按您需要的顺序调用它们。但是,在处理输入和输出时,这会变得很混乱。

您可以使用多个通道,在每个通道中使用不同的效果和程序。这有一些额外的开销,但可以更容易设置。

相关文章: