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