Opengl 正向渲染多个渲染过程

Opengl 正向渲染多个渲染过程,opengl,glsl,rendering,Opengl,Glsl,Rendering,我尝试在我的简单OpenGL渲染器中实现PBR,并尝试使用多个照明过程,我使用每个灯光一个过程进行渲染,如下所示: 1-第一遍=深度 2-第二遍=环境 3-[3..n]用于场景中的所有灯光 我正在使用混合函数glBlendFuncGL_ONE,GL_ONE用于过程[3..n],并在每个片段着色器的末尾进行Gamma校正 但我仍然有一个问题,输出图像,它只是看起来噪音特别是当我使用纹理贴图 这些步骤有什么问题吗?或者这个过程有什么改进吗?因此,基本上,您要计算的是 f(x) = a^gamma +

我尝试在我的简单OpenGL渲染器中实现PBR,并尝试使用多个照明过程,我使用每个灯光一个过程进行渲染,如下所示:

1-第一遍=深度

2-第二遍=环境

3-[3..n]用于场景中的所有灯光

我正在使用混合函数glBlendFuncGL_ONE,GL_ONE用于过程[3..n],并在每个片段着色器的末尾进行Gamma校正

但我仍然有一个问题,输出图像,它只是看起来噪音特别是当我使用纹理贴图


这些步骤有什么问题吗?或者这个过程有什么改进吗?

因此,基本上,您要计算的是

f(x) = a^gamma + b^gamma + ...
然而,正如@Nicolabolas在评论中指出的那样,您真正想要的是

g(x) = (a + b + ...)^gamma
现在,fx和gx只在gamma=1这样毫无用处的情况下相等。你根本无法用这种方法对幂这样的非线性函数进行加法分解

正确的解决方案是将线性空间中的所有元素混合在一起,然后对每个光源的线性贡献的总和进行伽马校正

然而,实现这一点将导致一些技术问题。首先也是最重要的是,标准的每个通道8位精度不足以存储线性颜色值。将这种格式用于累积步骤将导致强烈可见的色带瑕疵。有两种方法可以解决此问题:

对累积帧缓冲区使用更高的每通道位格式。您将需要单独的gamma校正过程,因此需要通过FBO设置“渲染到纹理”。GL_RGBA16F是一种非常好的格式。由于使用PBR照明模型,因此还可以使用[0,1]之外的颜色值,而不是简单的gamma校正,在最终过程中应用适当的色调映射。请注意,虽然您可能不需要alpha chanell,但此处仍使用RGBA格式,但RGB格式并不是GL规范所要求的颜色缓冲区格式,因此它们可能不被普遍支持

以每组件8位格式存储数据,伽马校正。这里的关键是混合仍然必须在线性空间中进行,因此在混合之前,目标帧缓冲区颜色值必须重新线性化。这可以通过使用GL_SRGB8_ALPHA8格式的帧缓冲区并启用GL_framebuffer_SRGB来实现。在这种情况下,GPU将在将片段颜色写入帧缓冲区时自动应用标准的sRGB gamma校正(当前片段着色器会这样做),但在访问这些值(包括混合)时,它也会导致sRGB线性化。第17.3.6.1节混合方程中的状态:

如果启用了帧缓冲区\u SRGB,并且帧缓冲区附件的帧缓冲区\u附件\u颜色\u编码的值对应 目标缓冲区为SRGB,见第9.2.3节,R、G和B目标 将从定点转换为浮点后的颜色值视为 必须针对sRGB颜色空间进行编码,因此必须在使用前进行线性化 用于混合。每个R、G和B分量都以相同的方式转换 第8.24节中描述了sRGB纹理组件

方法1将是更一般的方法,而方法2有两个缺点:

线性化/去线性化要进行多次,可能会浪费一些GPU处理能力 由于仍然只使用8位整数,因此总体质量会更低。在每个混合步骤之后,结果将四舍五入到下一个可表示的数字,因此您将获得更多的量化噪声。 在[0,1]中,您仍然受限于颜色值,并且无法轻松执行更有趣的色调映射和HDR渲染效果 然而,方法2也有优点:

您不需要单独的最终gamma校正过程 如果平台/窗口系统确实支持sRGB帧缓冲区,则可以直接为窗口创建sRGB pixeformat/visual,而不需要任何渲染到纹理的步骤。基本上,请求一个sRGB帧缓冲区并启用GL_framebuffer_sRGB就足够了。
我在每个片段着色器的末尾进行Gamma校正。你不应该这样。Gamma校正将线性值转换为非线性的Gamma空间值。不应该在gamma空间中进行混合;混合应该只应用于线性值。那么@Nicolas你有什么办法解决这个问题吗?好像我没有做伽马校正,输出图像很暗。显然,最后做一次伽马校正。我看不出结果有什么理由吵闹。你能分享一个例子吗?渲染器中没有随机性,对吗?可以做的一些改进是将深度预处理过程与环境光过程结合起来,使其成为一个过程。接下来,根据物料将物料放入队列。所以你有不透明的物体,castin的物体 g阴影和对象透明。然后为所有灯光渲染每个队列最后渲染透明队列。