我可以为同一个渲染作业使用不同的着色器程序吗?

Posted

技术标签:

【中文标题】我可以为同一个渲染作业使用不同的着色器程序吗?【英文标题】:Can I use different shader programs for the same rendering job? 【发布时间】:2019-01-27 14:25:46 【问题描述】:

编辑:

我的问题一开始不清楚,我会尝试改写:

如何使用不同的着色器对同一个网格多边形进行不同的渲染操作?例如,我想使用一个着色器添加照明并使用另一个着色器添加雾。我需要在计算第二个着色器时使用从第一个着色器插入的颜色,但如果我不能(或者不应该)在着色器之间传递颜色缓冲区,我不知道该怎么做。 另外(这就是我的问题开始的地方),我需要对两个着色器进行相同的世界观投影计算,所以我应该在每个着色器中分别计算它吗?我应该为所有渲染操作使用一个大着色器吗?

原问题:

假设我有两个不同的着色器程序。第一个计算顶点着色器中的顶点位置,并在片段着色器中进行一些操作。

假设我想使用片段着色器进行不同的计算,但我仍然想使用第一个顶点着色器计算的相同顶点位置。我是否必须再次计算顶点位置,或者有没有办法在不同的着色器程序之间共享状态?

【问题讨论】:

我想在不同着色器程序的不同片段着色器中使用相同的插值顶点位置,而不是每次都重新计算顶点位置。 好的,那么如何将来自不同片段着色器的颜色计算加在一起呢?例如,有一个着色器程序来计算一些光照,而另一个着色器程序来计算另一种类型的光照? @PanthersFan92:你所有的问题似乎都源于对着色器功能的根本误解。着色器是process of rendering 的一部分。 VS 计算光栅化所需的顶点数据。 FS 计算该光栅化的产品,以馈入后处理阶段(混合等)。当您渲染某些东西 时会调用这些着色器。它们是渲染管道的一部分,它们接收和生成的数据用于渲染您要求渲染的特定内容。 @PanthersFan92:然而,你刚才所说的表明你并没有真正理解我刚才所说的话。着色器不会对“缓冲区”进行“计算”;他们进行渲染。如果您想使用着色器进行“计算”,那么您必须使计算看起来像渲染。因此,您必须构建操作以在渲染管道的范围内工作。 @PanthersFan92:好的,你的意思是你想要渲染一个东西,你想让不同的程序对象负责它的不同方面渲染(照明,雾等)。这就是你说的吗?如果是这样,请在您的问题中提出。 【参考方案1】:

你有更多选择:

    多通道

    这通常首先将几何体渲染到深度和“颜色”缓冲区中,然后在下一次传递中将其用作输入纹理,以渲染覆盖整个屏幕/视图的单个矩形。 延迟着色就是一个例子,但还有许多其他效果的实现与延迟着色无关。这里是一个多通道的例子:

    How can I render an 'atmosphere' over a rendering of the Earth in Three.js?

    在第一阶段渲染行星和恒星和其他东西,第二阶段添加大气。

    您可以通过混合或直接渲染来组合通道。直接渲染要求您在每个通道中渲染到纹理并在最后一个通道中渲染。混合是在每次传递中改变输出的颜色。

    单程

    您所描述的更像是您应该将不同的着色器编码为单个片段着色器的函数......是的,如果它们兼容,您可以将更多着色器组合成一个,并将它们的结果组合成最终输出颜色。

    大着色器会影响性能,但我认为它仍然比使用多个通道做同样的事情要快。

    看看这个例子:

    Normal mapping gone horribly wrong

    这个计算环境反射、照明、几何颜色并将它们组合在一起以形成单一的输出颜色。

    奇异的着色器

    还有一些奇异的着色器可以绕过管道限制,例如:

    Reflection and refraction impossible without recursive ray tracing?

    用于被认为无法在 GL/GLSL 管道中实现的东西。无论如何,如果限制过于严格,您仍然可以使用计算着色器...

【讨论】:

以上是关于我可以为同一个渲染作业使用不同的着色器程序吗?的主要内容,如果未能解决你的问题,请参考以下文章

为两个不同的 VAOS 使用两个不同的着色器

opengl着色器程序中的重复顶点

为啥片段着色器比渲染纹理更快?

如何在 Metal 中组合使用不同着色器的渲染命令编码器

渲染二维码的着色器

带有纹理的卡通着色器。这可以优化吗?