【发布时间】:2012-07-24 15:14:47
【问题描述】:
我目前正在对 OpenGL 和着色器进行一些研究,但我似乎无法弄清楚使用 glBlendMode 进行混合或在着色器中编写自己的混合模式之间是否存在任何根本区别。
选择前者还是后者的原因是什么?通过选择一个而不是另一个是否存在任何性能瓶颈?还是这只是个人喜好问题?
【问题讨论】:
标签: opengl shader fragment-shader
我目前正在对 OpenGL 和着色器进行一些研究,但我似乎无法弄清楚使用 glBlendMode 进行混合或在着色器中编写自己的混合模式之间是否存在任何根本区别。
选择前者还是后者的原因是什么?通过选择一个而不是另一个是否存在任何性能瓶颈?还是这只是个人喜好问题?
【问题讨论】:
标签: opengl shader fragment-shader
使用 glBlendFunc 的传统混合无法在着色器中复制。混合需要在修改目标帧缓冲区之前对其进行采样,这在当前硬件上是无法做到的。
目前您只能传递一种颜色,并选择有限的混合模式之一(glBlendFunc/glBlendEquation),GPU 的光栅化器将在写入帧缓冲区之前应用这些混合模式。
【讨论】:
glBlendFunc 混合与在着色器中混合纹理完全不同?假设我想用“乘法”混合模式混合两张照片。这应该在着色器中完成,而不是使用 glBlendFunc?你能举一个使用glBlendFunc的例子吗?
当着色器从纹理读取同时渲染到同一纹理时,结果是不确定的。这就是为什么将“传统”或固定功能与 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 被刷新,然后你可以在单个着色器阶段执行读/写操作(一定要避免多重采样缓冲区,因为只有一次写入操作实际上是允许的)..
【讨论】: