接上文:OpenGL基础44:光照矫正(上)

四、Gamma矫正

4.1、人的视觉特性

和很多错视图一样,对于下面这张灰阶图,如果1表示纯白,0表示纯黑,那么这张图片的哪个位置代表的是0.5,也就是自然界的平均亮度(中灰)呢?

我想看到这里的你可能会毫不犹豫的选中间,并心想:这个问题不是zz嘛?

然而事实上,自然界的平均亮度0.5在这张图3/4的位置而并非正中间,也就是说,平均色在人眼中是偏白的,尽管这确实看上去有点颠覆认知、不可思议

正如上图,上面是我们所真实感受的灰度变化,而下方才是物理世界真实的灰度变化

为了更适应环境提高生存能力,人类的视觉系统随着进化出了一个特性:黑暗环境下的辨识能力要强于明亮环境,这可能有助于我们及时发现黑暗中隐藏的危险,因此,人类的黑色的感知能力要远高于对白色的感知

换句话说,假设当前真实颜色是偏黑色(0.1亮度),这个时候环境发生了变化,亮度提高了0.01至0.11,尽管这个变化很细微,但是人仍能察觉的出来环境“变亮了”,但若当前真实颜色是偏白色(0.9亮度),此时环境又发生了变化,亮度提高了0.02至0.92,尽管这个变化量是之前的两倍,但这个时候人眼就察觉不出颜色变化了

一句话总结:人类对黑色的敏感程度高于对白色的敏感程度,认为的平均色(中灰)其实不在灰度为0.5的地方,而是在大约灰度为0.18~0.22的地方

4.2、Gamma神话

现在已经是21世纪了,聪明的科学家们当然早就发现了这一点:人眼对自然亮度感知是非线性的,既然这样,如果说现实世界的亮度为自然亮度,而人们的视觉感受为主观灰阶感受,那么这两者之间是否存在着关系?

在此,Gamma就出现了:

其中横轴代表着自然界线性增长的亮度,竖轴表示人实际感受到均匀亮度,红色的虚线就是Gamma矫正曲线,图中0.218到0.5的箭头,就代表着屏幕实际显示的亮度为0.5,其对应着自然环境颜色就为0.218

是的,存储在你硬盘上的图像,都是矫正过的,也就是对于显示器的实际亮度数值,其2.2次方才等于自然亮度数值

那么问题又来了,Gamma值为什么是2.2?其实这个值就是约定俗成而已,如果硬要是拿2.3或者2.1,其实差距也不大,过去大多数监视器是阴极射线管显示器(CRT),这些监视器有一个物理特性就是两倍的输入电压产生的不是两倍的亮度,输入电压产生约为输入电压的2.2次幂的亮度,这叫做监视器Gamma,而选择2.2的倒数进行图像矫正,正是为了迎合这个特性

一句话结论:计算机显示的颜色正是迎合我们的主观灰阶感受,而不是自然亮度,想要映射到对应的自然亮度需要经过Gamma校准

4.3、Gamma与颜色向量

为什么计算机显示的图象颜色要用校正后的主观灰阶感受,而不是自然亮度呢?

其实主要也不是为了迎合人眼,因为理论上只要计算机能表示出所有的颜色段,那么其实是否要进行Gamma校验根本不重要,但问题就出现在这里:《OpenGL基础17:颜色》已经提到过了计算机的显示颜色的规范,目前主流(99%)都是RGB-8bit,也就是三原色都由0~255来描述。就和像素一样,计算机总共也只能展现出  种不同的颜色,是离散的。如果只考虑灰阶(RGB三原色值相等),那么计算机总共就只能描述出256种不同的灰阶

不过现在科技发达,已经有支持10-bit的显示器(能展现出更多种不同的颜色)

这样的话,这256个灰阶就显得非常宝贵,为了能展示更丰富的颜色,在这种情况下就必须要迎合人的主观灰阶感受。否则就会出现如下情况:亮度高的两个相邻灰度【例如#RGB(220, 220, 220)和#RGB(221, 221, 221)】,人们从中根本看不出区别,而亮度低的两个灰度【例如#RGB(18, 18, 18)和#RGB(19, 19, 19)】,它们在人眼中的差别又显得不小,这样如果想表示比前者颜色更亮,却比后者暗的亮度就是一件完全不可能的事

一句话结论:归根结底就是精度问题,因为计算机能表示的颜色数量是有限的,而人类又对黑暗更为敏感,因此一定要在表示黑暗片段上使用更高精度

4.4、Gamma矫正和渲染的关系

所有的光照计算(之前的漫反射和镜面反射等)都一定是在线性空间计算的,这也意味着,如果你在计算物体最终颜色之前就进行过了Gamma矫正(进入了非线性空间),那么这个计算结果肯定就不对了(特别是颜色之间的混合),毕竟次方运算根本不是线性运算,更不可能遵循交换律,遗憾的是,这种错误在很多地方都有……

很多纹理,都已经进行过了gamma矫正!除非能确保纹理制作者是在线性空间中进行创作的,然而事实上就是:大多数纹理制作者并不知道什么是gamma校正,它们都是在sRGB空间中进行创作的(上面提过,sRGB空间定义的gamma接近于2.2,不属于线性空间)

这样的话,对于sRGB空间制作的纹理,我们就必须要在进行光照计算前进行重校,也就是拉回线性空间,不过还好,如果在glTexImage2D()时指定纹理格式为GL_SRGB或GL_SRGB_ALPHA,那么openGL内部就会自动帮你重校

注意!在指定纹理格式前一定要确定纹理类型,不是所有纹理都进行过gamma矫正的,举个例子:对于专业的美术,制作specular贴图和法线贴图几乎肯定是在线性空间中的,这主要是为了确定更准确的光照参数

不过如果转到了线性空间,那么在最后输出的时候就需要进行一次Gamma矫正了,有两种方法:

  • glEnable(GL_FRAMEBUFFER_SRGB)
  • 在着色器中手动计算,记得一定要在最后进行

图为线性空间计算光照的结果,会显得比之前亮,代码就不放了

OpenGL基础45:光照矫正(下)之Gamma校正相关推荐

  1. OpenGL基础50:HDR

    一.HDR与LDR 由于显示器只能显示值为0.0到1.0间的颜色,因此当数据存储在帧缓冲(Framebuffer)中时,亮度和颜色的值也是默认被限制在0.0到1.0之间的,这个颜色范围即是LDR(Lo ...

  2. gamma校正到底是个什么玩意儿

    一. 在哪见过.听说过Gamma? * 还用说,Adobe Gamma * 常听说MAC的默认Gamma是1.8,PC的是2.2 * 我的显卡驱动程序里有Gamma调节 * 我下载了一个软件,也可以调 ...

  3. OpenGL基础44:光照矫正(上)

    对于openGL的API,倒是没有必要花太多时间,重点应该还是在着色器上 一.采样器.glActiveTexture和glBindTexture 在之前测试简单光照时可能出现的两个问题,尽管它们可能不 ...

  4. OpenGL基础53:阴影映射(下)

    接上文:OpenGL基础52:阴影映射(上) 五.阴影失真 按照上文的计算的结果,一个很明显的问题是:对于参与计算深度贴图的物体,其表面可以看到这样的栅格状的阴影,这种常见的错误表现也叫做阴影失真(S ...

  5. opengl高级光照之gamma校正

    官方文章 gamma校正 gamma校正概念 一个渐变的效果 通过以下网站调整Gamma值可以观察到效果 色彩管理网 gamma校正 Gamma校正(Gamma Correction)的思路是在最终的 ...

  6. OpenGL基础35:帧缓冲(下)之简单图像处理

    在之前的章节,所有的物体都是中规中矩的显示的,只考虑了光照对物体的影响,那假设想要显示特殊的效果该怎么操作呢?例如马赛克风.将所有的物体都显示为黑白色,就像上世纪80年代的灰白电视一样,又或者说将整个 ...

  7. OpenGL基础20:镜面光照

    前置:OpenGL基础19:法向量与漫反射 一.镜面光照 前面物体已经拥有了环境光和漫反射光,现在再加上镜面光照就完美了,镜面光照的效果是:当我们去看光被物体所反射的那个方向的时候,会看到一个高光 和 ...

  8. OpenGL 基础光照ColorsBasic Lighting

    OpenGL 基础光照ColorsBasic Lighting 基础光照ColorsBasic Lighting简介 环境光照 漫反射光照 法向量 计算漫反射光照 最后一件事 镜面光照 基础光照Col ...

  9. OpenGL基础49:高度贴图(下)

    接上文:OpenGL基础48:高度贴图(上) 四.陡峭视差映射 上文计算纹理偏移的方法是最简单的,但问题也比较大:当你斜视贴图的时候可以看到非常明显的错误 这里有另一种方法,这种方法类似于找连续函数在 ...

最新文章

  1. iOS 10、Xcode 8 遇到部分问题解决记录(包括控制台日志不输出)
  2. 各种AJAX方法的使用比较
  3. 在Repeater控件,Repeater1控件中都有FooterTemplate模板.但你在后台中如何去找FooterTemplate中的控件呢?...
  4. Jquery获取DOM绑定事件
  5. Outlook 获取联系人名片对象为空
  6. Markdown语法补充
  7. matlab编程数学基础,数学软件 Matlab ——编程基础(脚本).ppt
  8. C++基础复习——C++语言数据类型
  9. 对Kalman Filter的理解
  10. iOS 升级https的方案选择
  11. lua虚拟机字节码修改_Java虚拟机(JVM)面试题大集合
  12. ES报错:Connection reset by peer 解决经历
  13. java 过滤脚本_我写的得到天气的Java代码,其中有过滤脚本和过滤HTMLtag的函数。...
  14. ICLR2020 | 如何判断两个神经网络学到的知识是否一致
  15. Grafana、M3DB、Prometheus 集成 关于M3DB集成的文章本就不多,快来瞅瞅吧!!!说不定有用呢?
  16. mysql dbuild_config_技术分享 | MySQL Test 初探
  17. 【计算机图形学】画线算法——Bresenham算法(任意斜率)
  18. 无法读源文件或磁盘_磁盘阵列RAID1+0和RAID0+1的区别
  19. python爬取谷歌学术_JS反爬绕过思路之--谷歌学术镜像网链接抓取
  20. Python pandas.DataFrame.combine_first函数方法的使用

热门文章

  1. python简单代码-python实现顺序表的简单代码
  2. python怎么读-Python中怎么读写文件
  3. python语言入门-分分钟入门python语言
  4. 金属100寸“电视”却无屏,语音识别+DTS+1080P,微鲸M1测评
  5. 日语+AI语音黑科技,早道开启小语种AI智能时代!
  6. php for 每次增加2,php – 为什么foreach会将refcount增加2而不是1?
  7. linux安装pdo mysql扩展_linux下php安装pdo_mysql扩展
  8. 我与CSDN的2020年
  9. python自定义变量名有哪些_Python学习第161课——自定义变量和导出变量
  10. 制作好的app需要服务器吗,在直播app制作过程中,服务器是如何配置的?