OpenGL多通道着色器如何工作?


13

在Direct3D中,多通道着色器易于使用,因为您可以从字面上定义程序中的通道。在OpenGL中,这似乎有点复杂,因为可以为着色器程序提供所需的任意数量的顶点,几何和片段着色器。

多遍着色器的流行示例是卡通着色器。一遍会产生实际的阴影效果,另一遍会创建轮廓。如果我有两个顶点着色器“ cel.vert”和“ outline.vert”,以及两个片段着色器“ cel.frag”和“ outline.frag”(类似于在HLSL中的处理方式),结合起来创建完整的卡通着色器?

我不想让您说可以使用几何着色器,因为我只想了解多通道GLSL着色器背后的理论;)


“在Direct3D中,多通道着色器易于使用,因为您可以从字面上定义程序中的通道。” 不,你不能。您可以在FX文件中定义通过,但与HLSL着色器不同。
Nicol Bolas 2012年

Answers:


11

多遍背后没有“理论”。没有“多通道着色器”。多遍非常简单:用一个程序绘制对象。然后,使用其他程序绘制对象。

您可以使用FX文件之类的D3DX素材来隐藏这些额外的通行证。但是他们仍然那样工作。OpenGL根本没有隐藏的地方。


1

使用单元着色器渲染对象,然后使用轮廓着色器重新渲染它。


1
所以我应该制作两个不同的着色器程序?为什么为什么我可以给着色器程序提供尽可能多的顶点/几何/片段着色器?必须有一种方法可以用一个程序来完成它。
jmegaffin 2012年

1
您没有为它提供多个顶点(等)着色器。只有一个主要功能,因此您没有多个入口点。它与C程序非常相似,因为您可以将多个文件链接在一起以组成一个程序。您可以在不同的程序之间共享这些文件,因此您无需重复代码,但是每个文件本身不一定是一个程序。
2012年

1
这就是方法,使用一个着色器对(顶点+片段)渲染一次,然后使用另一对着色器(或使用相同的顶点着色器+另一个片段着色器)再次渲染。有时,您渲染到缓冲区并使用(但)另一个着色器将其“混合”到最终结果中。
Valmond 2012年

1

在OpenGL 4.0中,有统一的子例程。这些使您能够定义可以在运行时交换的功能,而开销却很小。因此,您可以为每遍设置1个功能。每个着色器类型还具有1个功能。

这里有一个教程

对于较旧的OpenGL版本,最好的选择是拥有一堆不同的着色器并在它们之间进行交换。否则,您可以将乘以统一值(0.0或1.0)的值相加,以将其打开或关闭。否则,可以使用有条件的if语句,但是OpenGL将在每次执行/传递时执行所有可能的结果,因此请确保它们不太繁琐。


0

有些人对GLSL有很多了解,所以我希望他们能为您创造记录,但是根据我所看到的,您应该能够在片段着色器中执行类似的操作(伪代码,我会将实际的GLSL留给更了解它的人):

out vec4 fragment_color
vec4 final_color
final_color = flat_color
If this fragment is in shadow
    final_color = shadow_color
If this fragment is an edge
    final_color = edge_color
If this fragment is a highlight
    final_color = highlight_color
fragment_color = final_color

通过if以这种方式使用s,您会得到类似多次通过的信息。那有意义吗?

编辑:另外,希望这个关于SO的问题有助于消除一些误会。


2
需要特别注意的是,即使没有启用,GLSL也会在if分支中每遍执行if分支中的所有语句。显然,只是计算所有内容并将所有颜色加在一起,但是将值乘以1.0或0.0以启用或禁用它们会更快。
戴维·C·毕晓普(Bishop)

1
@ DavidC.Bishop:事实并非如此。至少,不能保证是真的。编译器将决定是实际分支更快还是“计算所有内容并稍后整理”方法更快。
Nicol Bolas 2012年

1
顺便说一句,@ DavidC.Bishop提到的行为几乎不特定于着色器和GPU。如果测试值尚不可用,则执行常规程序的现代CPU会推测性地执行至少一个分支。如果发现错误,则回滚并重做。最终平均产生了很大的加速。
ipeet 2012年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.