首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >正向渲染多个渲染过程

正向渲染多个渲染过程
EN

Stack Overflow用户
提问于 2018-05-19 23:40:14
回答 1查看 353关注 0票数 0

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

1-第一遍=深度

2秒传递=环境光

3- 3 ..N表示场景中的所有灯光。

我对过程3..n使用混合函数glBlendFunc(GL_ONE,GL_ONE),并在每个片段着色器的末尾执行伽马校正。

但是我仍然有一个输出图像的问题,它看起来很嘈杂,特别是当我使用纹理贴图的时候。

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

EN

回答 1

Stack Overflow用户

发布于 2018-05-21 21:49:20

所以基本上,你计算的是

代码语言:javascript
复制
f(x) = a^gamma + b^gamma + ...

然而,您真正想要的(正如@NicolBolas已经在评论中指出的那样)是

代码语言:javascript
复制
g(x) = (a + b + ...)^gamma

现在,f(x)g(x)只有在像gamma=1这样无用的情况下才是平等的。你不能简单地以这种方式附加分解像power这样的非线性函数。

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

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

  1. 对累积帧缓冲区使用更高的位/通道格式。您将需要单独的gamma校正过程,因此需要通过FBO设置渲染到纹理。在这方面,GL_RGBA16F似乎是一种特别好的格式。由于使用PBR照明模型,因此还可以使用0,1以外的颜色值,并且在最终过程中应用适当的色调贴图,而不是简单的gamma校正。请注意,虽然您可能不需要alpha chanell,但这里仍使用RGBA格式,RGB格式根本不是GL规范所要求的颜色缓冲格式,因此它们可能不支持仍为8位/分量格式的数据,伽马校正。这里的关键是,混合仍然必须在线性空间中完成,因此目标帧缓冲区颜色值必须在混合之前重新线性化。这可以通过使用GL_SRGB8_ALPHA8格式的帧缓冲区并启用GL_FRAMEBUFFER_SRGB来实现。在这种情况下,图形处理器将在将碎片颜色写入帧缓冲区时自动应用标准sRGB gamma校正(当前您的片段着色器正在执行此操作),但在访问这些值时也会导致sRGB线性化,包括用于混合。OpenGL 4.6 core profile spec在"17.3.6.1混合方程“一节中陈述:

如果启用了FRAMEBUFFER_SRGB,并且与目标缓冲区对应的帧缓冲区附件的FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING值为SRGB (请参见9.2.3节),则RGB目标颜色值(从定点转换为浮点之后)将被视为针对sRGB颜色空间进行了编码,因此必须在将其用于混合之前进行线性化。每个RGB组件的转换方式与8.24节中为sRGB纹理组件所述的方式相同。

方法1将是更通用的方法,而方法2有几个缺点:

  • 线性化/去离子化被多次执行,由于仍然只使用8位整数,因此可能会浪费一些
  • 的处理能力,整体质量将较低。在每个混合步骤之后,结果会四舍五入到下一个可表示的数字,所以你会得到更多的量化噪声。
  • 你仍然被限制在0,1中的颜色值,并且不能(很容易)做更有趣的色调映射和HDR渲染效果

但是,方法2也有优势:

  • 不需要单独的最终gamma校正过程
  • 如果您的平台/窗口系统支持sRGB帧缓冲区,则可以直接为窗口创建sRGB像素格式/可视,并且根本不需要任何渲染到纹理的步骤。基本上,请求一个sRGB帧缓冲区并启用GL_FRAMEBUFFER_SRGB就足以实现这一点。
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/50426929

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档