IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 人工智能 -> Learn OpenGL 笔记6.7 HDR(高动态范围) -> 正文阅读

[人工智能]Learn OpenGL 笔记6.7 HDR(高动态范围)

默认情况下,亮度和颜色值在存储到帧缓冲区时被限制在 0.0 和 1.0 之间。 这个起初看似无害的声明让我们总是在这个范围内的某个地方指定光线和颜色值,试图让它们适应场景。 这工作正常并给出了不错的结果,但是如果我们走在一个非常明亮的区域,有多个明亮的光源,总和超过 1.0 会发生什么? 亮度或颜色总和超过 1.0 的所有片段都会被限制为 1.0,这看起来不太好:

由于大量片段的颜色值被限制为 1.0,因此每个明亮片段在大区域内都具有完全相同的白色值,从而丢失了大量细节并使其看起来很假

这个问题的解决方案是降低光源的强度,并确保场景中的任何片段区域的亮度都不会超过 1.0; 这不是一个好的解决方案,因为这会迫使您使用不切实际的照明参数。 更好的方法是让颜色值暂时超过 1.0,并在最后一步将它们转换回原始范围 0.0 和 1.0,但不会丢失细节。

显示器(非 HDR)仅限于显示 0.0 和 1.0 范围内的颜色,但在光照方程中没有这样的限制。通过允许片段颜色超过 1.0,我们可以在称为high dynamic range高动态范围 (HDR) 的情况下使用更大范围的颜色值。高动态范围,明亮的东西可以很亮,暗的东西可以很暗,两者都可以看到细节。?

high dynamic range高动态范围最初仅用于摄影,在这种情况下,摄影师以不同的曝光水平拍摄同一场景的多张照片,捕捉大范围的颜色值。 将这些组合起来形成一个 HDR 图像,其中根据组合的曝光级别或查看它的特定曝光,可以看到大范围的细节。 例如,下图(Colin Smith 提供)在低曝光(看窗户)的明亮区域显示了很多细节,但在高曝光时这些细节消失了。 然而,高曝光现在可以在较暗的区域显示出大量以前不可见的细节

这也非常类似于人眼的工作方式和高动态范围渲染的基础。 当光线不足时,人眼会自我适应,因此较暗的部分变得更加明显,对于明亮的区域也是如此。 这就像人眼有一个基于场景亮度的自动曝光滑块。?

高动态范围渲染有点像这样。我们允许渲染更大范围的颜色值,收集场景的大范围暗部和亮部细节,最后我们将所有 HDR 值转换回 [0.0, 1.0]这种将 HDR 值转换为 LDR 值的过程称为色调映射并且存在大量色调映射算法,旨在在转换过程中保留大部分 HDR 细节。这些色调映射算法通常涉及有选择地偏向于暗区或亮区的曝光参数。

在实时渲染方面,高动态范围不仅使我们能够超过 [0.0, 1.0] 的 LDR 范围并保留更多细节,而且还使我们能够通过光源的实际强度来指定其强度。例如,太阳的强度比手电筒之类的东西要高得多,所以为什么不这样配置太阳(例如,漫射亮度为 100.0)。这使我们能够使用更逼真的照明参数更正确地配置场景的照明,这是 LDR 渲染无法实现的,因为它们会直接被限制为 1.0。

由于(非 HDR)显示器仅显示 0.0 和 1.0 之间范围内的颜色,因此我们确实需要将当前高动态范围的颜色值转换回显示器的范围。简单地用一个简单的平均值重新转换颜色对我们没有多大好处,因为更亮的区域会变得更加显着。我们可以做的是使用不同的方程和/或曲线将 HDR 值转换回 LDR,让我们可以完全控制场景的亮度。这是之前称为?tone mapping色调映射的过程,也是 HDR 渲染的最后一步。
?

1.Floating point framebuffers(浮点帧缓冲区)

为了实现高动态范围渲染,我们需要一些方法来防止片段着色器运行后颜色值被限制。 当帧缓冲区使用归一化定点颜色格式(如 GL_RGB)作为其颜色缓冲区的内部格式时,OpenGL 会在将它们存储到帧缓冲区之前自动将值限制在 0.0 和 1.0 之间。 此操作适用于大多数类型的帧缓冲区格式,浮点格式除外。

当帧缓冲区的颜色缓冲区的内部格式指定为 GL_RGB16FGL_RGBA16FGL_RGB32FGL_RGBA32F 时,帧缓冲区被称为floating point framebuffer浮点帧缓冲区,可以存储默认范围 0.0 和 1.0 之外的浮点值。 这非常适合在高动态范围内渲染!

要创建floating point framebuffer浮点帧缓冲区,我们唯一需要更改的是其颜色缓冲区的内部格式参数:

glBindTexture(GL_TEXTURE_2D, colorBuffer);
//设置格式GL_RGBA16F
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA16F, SCR_WIDTH, SCR_HEIGHT, 0, GL_RGBA, GL_FLOAT, NULL);  

OpenGL 的默认帧缓冲区(默认情况下)每个颜色分量仅占用 8 位。 对于每个颜色分量为 32 位的浮点帧缓冲区(当使用 GL_RGB32F 或 GL_RGBA32F 时),我们使用 4 倍的内存来存储颜色值。 由于 32 位并不是真正必要的(除非您需要高精度),因此使用 GL_RGBA16F 就足够了

通过附加到帧缓冲区的浮点颜色缓冲区,我们现在可以将场景渲染到该帧缓冲区中,因为知道颜色值不会被限制在 0.0 和 1.0 之间。 在本章的示例演示中,我们首先将光照场景渲染到浮点帧缓冲区中,然后在屏幕填充的四边形上显示帧缓冲区的颜色缓冲区; 它看起来有点像这样:

//常规绑定framebuffer
glBindFramebuffer(GL_FRAMEBUFFER, hdrFBO);
    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);  
    // [...] render (lit) scene 
glBindFramebuffer(GL_FRAMEBUFFER, 0);

// now render hdr color buffer to 2D screen-filling quad with tone mapping shader
hdrShader.use();
glActiveTexture(GL_TEXTURE0);
glBindTexture(GL_TEXTURE_2D, hdrColorBufferTexture);
RenderQuad();

?这里场景的颜色值被填充到浮点颜色缓冲区中,该缓冲区可以包含任何任意颜色值,可能超过 1.0。 在本章中,创建了一个简单的演示场景,其中一个大的拉伸立方体充当隧道,带有四个点光源,一个位于隧道尽头的非常明亮:

std::vector<glm::vec3> lightColors;
//超级亮的一个颜色
lightColors.push_back(glm::vec3(200.0f, 200.0f, 200.0f));
lightColors.push_back(glm::vec3(0.1f, 0.0f, 0.0f));
lightColors.push_back(glm::vec3(0.0f, 0.0f, 0.2f));
lightColors.push_back(glm::vec3(0.0f, 0.1f, 0.0f));  

渲染到浮点帧缓冲区与我们通常渲染到帧缓冲区完全相同。 新的是 hdrShader 的片段着色器,它渲染带有浮点颜色缓冲区纹理的最终 2D 四边形。 让我们首先定义一个简单的传递片段着色器:

#version 330 core
out vec4 FragColor;
  
in vec2 TexCoords;

uniform sampler2D hdrBuffer;

void main()
{             
    //常规的fragment渲染
    vec3 hdrColor = texture(hdrBuffer, TexCoords).rgb;
    FragColor = vec4(hdrColor, 1.0);
}  

这里我们直接对浮点颜色缓冲区进行采样,并将其颜色值用作片段着色器的输出。 然而,由于 2D 四边形的输出被直接渲染到默认的帧缓冲区中,所有片段着色器的输出值最终仍会被限制在 0.0 和 1.0 之间,即使我们在浮点颜色纹理中有几个值超过 1.0。

?白色部分的细节完全看不清了

很明显,隧道末端的强光值被限制为 1.0,因为它的很大一部分是完全白色的,在此过程中有效地丢失了所有照明细节。 当我们直接将 HDR 值写入 LDR 输出缓冲区时,就好像我们没有启用 HDR。 我们需要做的是在不丢失任何细节的情况下将所有浮点颜色值转换为 0.0 - 1.0 范围。 我们需要应用一个称为tone mapping色调映射的过程。

2.Tone mapping(色调映射)

Tone mapping色调映射是将浮点颜色值转换为预期的 [0.0, 1.0] 范围的过程,称为低动态范围,而不会丢失太多细节,通常伴随着特定的风格色彩平衡。

更简单的色调映射算法之一是 Reinhard Tone mapping色调映射,它涉及将整个 HDR 颜色值划分为 LDR 颜色值。 Reinhard 色调映射算法将所有亮度值均匀地平衡到 LDR 上。 我们将 Reinhard Tone mapping色调映射包含在之前的片段着色器中,并且还添加了一个gamma correction伽马校正过滤器以获得良好的度量(包括使用 sRGB 纹理):

void main()
{             
    const float gamma = 2.2;
    vec3 hdrColor = texture(hdrBuffer, TexCoords).rgb;
  
    // reinhard tone mapping
    // 简单粗暴的直接按比例映射到0-1的范围
    vec3 mapped = hdrColor / (hdrColor + vec3(1.0));
    // gamma correction 
    mapped = pow(mapped, vec3(1.0 / gamma));
  
    FragColor = vec4(mapped, 1.0);
}    

应用 Reinhard 色调映射后,我们不再丢失场景明亮区域的任何细节。 它确实倾向于稍微偏向于较亮的区域,使较暗的区域看起来不那么详细和清晰:

在这里,您可以再次看到隧道尽头的细节,因为木材纹理图案再次变得可见。 使用这种相对简单的色调映射算法,我们可以正确地看到存储在浮点帧缓冲区中的整个 HDR 值范围,从而使我们能够精确控制场景的照明而不会丢失细节。

色调映射的另一个有趣用途是允许使用exposure parameter曝光参数。 您可能还记得在介绍中,HDR 图像包含许多在不同曝光水平下可见的细节。 如果我们有一个具有昼夜循环的场景,那么在白天使用较低的曝光度并在夜间使用较高的曝光度是有意义的,类似于人眼的适应方式。 有了这样的曝光参数,我们就可以配置在白天和晚上在不同照明条件下工作的照明参数,因为我们只需要更改曝光参数。

一个相对简单的exposure tone mapping曝光色调映射算法如下所示:

uniform float exposure;

void main()
{             
    const float gamma = 2.2;
    vec3 hdrColor = texture(hdrBuffer, TexCoords).rgb;
  
    // exposure tone mapping
    //exp(x)返回x的指数,e^x ,exp(0)= 1, exp(1) = 2.7......
    //这里的exp指的是 e^(-hdrColor*exposure) ,反正就是曝光度越大,mapped越大,无限接近于1
    vec3 mapped = vec3(1.0) - exp(-hdrColor * exposure);
    // gamma correction 
    // 伽马矫正,适应人眼
    mapped = pow(mapped, vec3(1.0 / gamma));
  
    FragColor = vec4(mapped, 1.0);
} 

在这里,我们定义了默认为 1.0 的曝光统一,并允许我们更准确地指定我们是否希望更多地关注 HDR 颜色值的暗区或亮区。 例如,在高曝光值下,隧道的较暗区域显示的细节明显更多。 相比之下,低曝光在很大程度上消除了黑暗区域的细节,但让我们可以在场景的明亮区域看到更多细节。 看看下面的图片,看看在多个曝光级别的隧道:

该图像清楚地显示了高动态范围渲染的好处。 通过更改曝光级别,我们可以看到场景的许多细节,否则这些细节会因低动态范围渲染而丢失。 以隧道尽头为例。 在正常曝光下,木结构几乎看不到,但在低曝光下,详细的木纹清晰可见。 这同样适用于附近的木制图案,在高曝光下更明显。

3.More HDR(更多HDR)

所示的两种色调映射算法只是大量(更高级)色调映射算法中的一小部分,每个算法都有自己的优点和缺点。一些色调映射算法偏爱某些颜色/强度高于其他颜色,一些算法同时显示低曝光和高曝光颜色以创建更丰富多彩和更详细的图像。还有一组称为 automatic exposure adjustment?or?eye adaptation 自动曝光调整或眼睛适应技术的技术,它们确定前一帧场景的亮度并(缓慢)调整曝光参数,使场景在黑暗区域变亮或在明亮区域变暗模仿人眼。

HDR 渲染的真正优势真正体现在具有大量照明算法的大型复杂场景中。由于很难在保持可访问性的同时创建用于教学目的的如此复杂的演示场景,因此本章的演示场景很小且缺乏细节。虽然相对简单,但它确实展示了 HDR 渲染的一些好处:高光和暗区的细节不会丢失,因为它们可以通过色调映射恢复,添加多个灯不会导致区域被限制,并且可以指定光值通过不受 LDR 值限制的真实亮度值。此外,HDR 渲染还使其他几种有趣的效果更加可行和逼真;其中一个影响就是bloom,我们将在下一章讨论。

  人工智能 最新文章
2022吴恩达机器学习课程——第二课(神经网
第十五章 规则学习
FixMatch: Simplifying Semi-Supervised Le
数据挖掘Java——Kmeans算法的实现
大脑皮层的分割方法
【翻译】GPT-3是如何工作的
论文笔记:TEACHTEXT: CrossModal Generaliz
python从零学(六)
详解Python 3.x 导入(import)
【答读者问27】backtrader不支持最新版本的
上一篇文章      下一篇文章      查看所有文章
加:2022-01-08 14:00:00  更:2022-01-08 14:01:54 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年5日历 -2024/5/19 9:42:37-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码