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

Posted

技术标签:

【中文标题】GLSL 问题:一个程序中有多个着色器【英文标题】:GLSL Problem: Multiple shaders in one program 【发布时间】:2011-08-29 21:01:18 【问题描述】:

我一定对着色器有误解:

我认为由于您可以将多个着色器附加到一个程序,因此您可以简单地附加多个片段着色器,例如:使用颜色调制渲染的板条箱纹理折射。

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

如何解决主要功能限制并允许在同一程序中并相互调用的多个片段着色器的任何动态组合?

【问题讨论】:

【参考方案1】:

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

void apply_diffuse();
void apply_specular();
void apply_environment();

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

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

【讨论】:

您只是没有回答主要问题 - 怎么做?如何附加单独的 GLSL 对象,它们是什么?他们是着色器吗?但我不能在一个程序中拥有多个片段着色器。 @Simon 一个 GLSL 程序从任意数量的 GLSL objects 链接。它的工作方式与链接 C 程序的方式相同:您可以有许多片段着色器,但只有一个必须有 main() 函数。【参考方案2】:

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

较新版本的 GLSL 应该支持虚拟函数,这允许您像在 CPU 代码中一样模块化构建它们 - HLSL5 就是这样做的。

【讨论】:

该死,他们为什么不从一开始就将其构建到 GLSL 中 - 这似乎非常重要.. @Nightshade:因为它非常慢,而且最近才变得有必要,因为越来越多的着色技术已经出现。 它不是很慢,至少没有使用。编译确实需要更长的时间,并且所有版本的 HLSL 和 Cg 都支持它。 GLSL 只是缺少很多功能。 @peachykeen:很有趣,因为 MSDN 网站明确将动态链接列为 HLSL5 的一项新功能。【参考方案3】:

问题在于您使用的术语。

让我打个比方:

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

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

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

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

【讨论】:

【参考方案4】:

你可以在一个着色器中拥有多个程序,但反过来不行。

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

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

【讨论】:

着色器中的程序?!从什么时候开始着色器对象可以包含程序对象? 着色器的层次结构是着色器、技术、通道、程序。每个通道都包含顶点、片段、几何体和/或曲面细分程序,并包含在着色器中的技术(创建特定效果的一组连续通道)中。 @peachykeen 你确定你说的是简单的 GLSL 着色器,而不是某种 fx 格式或某种可编程着色的思维抽象吗?

以上是关于GLSL 问题:一个程序中有多个着色器的主要内容,如果未能解决你的问题,请参考以下文章

第二篇: WebGL 着色器和GLSL

退出时删除多个着色器?

glsl qt 着色器程序

如果未绑定,统一值是不是保留在 GLSL 着色器中?

我的 GLSL 着色器程序链接正常,但是当我尝试使用它时出错——我该如何调试它?

为啥我的着色器中的 GLSL 纹理坐标不是线性的?