OpenGL混合模式vs着色器混合

问题描述:

我目前正在做一些关于OpenGL和着色器的研究,但我似乎无法弄清楚在混合使用glBlendMode或在着色器中编写自己的混合模式之间是否存在任何根本区别。OpenGL混合模式vs着色器混合

什么是选择前者还是后者的原因是什么?是否有任何性能瓶颈,通过选择其中一个?或者这只是个人喜好的问题?

与glBlendFunc传统的混合不能在着色器进行复制。混合需要在对目标帧缓冲区进行修改之前对其进行采样,而这在目前的硬件上是无法完成的。

当前,您只能传递一种颜色,并且选择一种有限的混合模式选择(glBlendFunc/glBlendEquation)之一,在写入帧缓冲之前,GPU的光栅器将应用这些模式。

+1

这是否意味着着色器不能混合两个纹理并将混合模式应用于它们并输出1个新纹理?如果人们在Web上发布Photoshop混合模式着色器,我觉得有点奇怪。你能否详细说明一下?谢谢! – polyclick 2012-07-25 08:16:35

+0

不,您仍然可以在着色器中混合两种纹理,但这不是混合。混合将当前像素与帧缓冲区混合。您仍然可以通过其他方式实现相同的效果(绘制纹理和混合)。 @bartcla – Tim 2012-07-25 15:52:51

+0

好吧,如果我理解正确:通过'glBlendFunc'进行混合与在着色器中混合纹理完全不同。假设我想用“乘法”混合模式混合两张照片。这应该在着色器中完成,而不是使用'glBlendFunc'?你能举一个例子,说明使用'glBlendFunc'吗? – polyclick 2012-07-26 09:24:29

它可以模拟的OpenGL在三种情况下的着色器内混合我所知道的:

  1. 你有Direct3D11或OpenGL相当,绑定渲染目标的读取写入纹理在你的像素着色器中。这可以实现任意复杂的混合操作,但在进行简单混合时性能不高,因为您绕过GPU的专用硬件进行简单混合。

  2. 你有一个奇特的“瓦为本”的GPU,甚至简单的混合是通过做“阿尔法着色器。”在这种情况下,OpenGL中的简单混合与等效着色器代码之间没有性能差异。但是你不太可能拥有这样的GPU,而且OpenGL也不会公开这个功能。

  3. 你回避整个固定功能硬件光栅化管道,并编写您自己作为一个复杂的“计算着色器。”如果你能解决这个问题,像“alpha shader”这样的东西就会成为你的基于tile的管道的一部分,但是到那时为止,如此多的工作以至于Alpha混合将成为你关注的最少部分。

+0

1:更不用说,如果多个着色器调用访问同一像素,则必须明确同步访问。 – 2012-07-24 19:13:58

+0

平铺光栅化的一个很好的方面是,通常像素之间不存在竞争条件的可能性。但是,如果您正在谈论的是1,那么您是对的:在这种情况下,保证三角栅格化将连续完成。 – bmcnett 2012-07-24 22:49:12

当着色器从纹理中读取同时呈现相同纹理的纹理时,结果未定义。这就是为什么与glBlendFunc和glBlendEquation混合的“传统”或固定功能是有用的。

为了混合使用传统的混合两个图像,则呈现第一图像,设置混合模式,功能和方程,并呈现第二图像。这是保证给出正确的结果,并且通常是实现透明度等效果的最快方式。

为了达到与着色器相同的效果,您需要将第一个图像渲染到辅助纹理,更改着色器,并将第二个图像渲染到实际的帧缓冲区,将混合作为片段着色器中的最后一步。由于纹理读取的额外开销,这通常会更慢,并且会为辅助纹理使用更多的GPU内存。

在现代化的硬件,这两种技术之间的差异变小。

这实际上可以使用gl 3来完成。0扩展使用纹理屏障功能:

http://www.opengl.org/registry/specs/NV/texture_barrier.txt

基本上,你写的背景后,可以将TextureBarrierNV()函数,以确保纹理像素被刷新,那么就可以在一个执行读/写操作单一着色器阶段(确保避免多重采样缓冲器,因为实际上只允许一次写入操作)。