我目前正在对OpenGL和着色器进行一些研究,但我似乎无法弄清楚使用glBlendMode
进行混合或在着色器中编写自己的混合模式之间是否存在任何根本区别。
选择前者或后者的原因是什么?通过选择一个而不是另一个会有任何性能瓶颈吗?或者这只是个人偏好的问题?
答案 0 :(得分:13)
无法在着色器中复制与glBlendFunc的传统混合。混合需要在修改目标帧缓冲区之前对其进行采样,这不是可以在当前硬件上完成的。
目前你只能传递一种颜色,并选择一种有限的混合模式选择(glBlendFunc / glBlendEquation),这些模式将在写入帧缓冲区之前由GPU的光栅化器应用。
答案 1 :(得分:6)
当着色器在同时渲染到相同纹理的同时从纹理中读取时,结果是未定义的。这就是为什么“传统”或固定功能与glBlendFunc和glBlendEquation混合有用的原因。
要使用传统混合混合两个图像,您可以渲染第一个图像,设置混合模式,函数和方程,并渲染第二个图像。这可以保证提供正确的结果,并且通常是实现透明效果的最快方法。
要使用着色器实现相同的效果,您需要将第一个图像渲染为辅助纹理,更改着色器,并将第二个图像渲染到实际的帧缓冲区,将混合作为片段着色器中的最后一步。由于纹理读取的额外开销,这通常较慢,并且肯定会为辅助纹理使用更多的GPU内存。
在现代硬件上,两种技术之间的差异往往很小。
答案 2 :(得分:1)
在我知道的三种情况下,可以在着色器中模拟OpenGL混合:
您具有Direct3D11或OpenGL等效项,并且您将渲染目标绑定为像素着色器中的读写纹理。这可以实现任意复杂的混合操作,但在进行简单混合时不会有很高的性能,因为您绕过GPU的特殊硬件进行简单混合。
你有一个充满异国情调的“基于图块的”GPU,甚至可以通过“alpha着色器”进行简单的混合。在这种情况下,OpenGL中的简单混合和等效着色器代码之间没有性能差异。但是你不太可能拥有这样的GPU,而OpenGL也不会公开这个功能。
您可以回避整个固定功能硬件光栅化管道,并将自己编写为“计算着色器”的复合体。如果你能解决这个问题,那么类似“alpha着色器”的东西就会成为你基于磁贴的管道的一部分,但要达到这一点是非常重要的,因为alpha混合将是你最不关心的问题。
答案 3 :(得分:0)
这实际上可以使用纹理屏障功能使用gl 3.0扩展来实现:
http://www.opengl.org/registry/specs/NV/texture_barrier.txt
基本上,在编写背景后,您可以使用TextureBarrierNV()函数来确保刷新纹素,然后您可以在单个着色器阶段执行读/写操作(确保避免多重采样缓冲区,因为只需一次写入实际上允许操作)..