Gamma校正

Gamma校正

Gamma值

  • 每种显示设备都有自己的Gamma值,且各不相同,但都遵循:设备输出亮度=输入电压的Gamma次方
  • 阴极射线管显示器(CRT):显示出来的亮度是输入电压的2.2次方,因此CRT的Gamma值就是2.2
  • 我们可以通俗的来理解Gamma值:显示器显示出来的颜色是原来颜色的Gamma次方
  • 2.2通常是大多数显示器的大概平均值,也是家用显示设备的一个标准
  • 对于渲染来说,我们在程序中设置颜色,这些颜色的变化范围是0到255,或者0.0到1.0,并且他们是线性变化的
  • 但是当颜色在电脑显示器上显示后,由于Gamma值不会等于1,这就造成了我们看到的颜色并不是在程序中设置的颜色,而是我们设置的颜色的指数倍,他们是非线性变化的

为什么需要Gamma校正?

  • 由于我们在程序中设置的颜色值是线性的,但实际表现出来的却是非线性的,或者说是不理想的,如果我们想表达出理想中的颜色,就要对即将显示的颜色进行校正
  • Gamma校正就是将一个颜色值变换成他的Gamma分之一次方
  • 根据显示设备的特性,显示器在显示颜色时自动执行了颜色的Gamma次方,所以显示器对于进行过Gamma校正的颜色,最后恰好显示出了他本身的颜色,完美

什么时候需要Gamma校正?

  • 先看看颜色的来源
  • 线性空间中的颜色 如果程序中获取到的颜色值是基于线性的,比如说手动输入了一些颜色值,那么想把这些颜色理想的显示出来,就要对他们进行Gamma校正,这样才能保证显示器在显示出来后是原来的颜色
  • 非线性空间中的颜色 非线性的颜色指的是执行过Gamma分之一次方后的颜色,也就是已经执行过Gamma校正的颜色,如果程序获取到的是这种颜色,就不需要再进行Gamma校正,直接发送给显示器显示即可
  • 非线性空间中的颜色从何而来? 这是一个非常简单,但又非常值得细品的一个问题:
    当你在电脑上绘制完一张理想的图片后,请你再回想一下给图片设置颜色的过程;无论在任何时候,你设置的颜色都是根据你在显示器前看到的颜色,这就意味着所有创作出来的图片的颜色都是被显示器执行过Gamma次方后的颜色,而这都是你理想中的颜色,那么你给图片所设置的颜色,不恰好正是最终显示出来颜色值的Gamma分之一次方?所以你在无意识中就做出了一张经过Gamma校正过的图片,而且可以肯定的是,几乎所有图片中的颜色都是经过Gamma校正过的
  • 再总结一下:非线性空间中的颜色指的是经过Gamma校正的颜色,就是从创作出来的图片中读取的颜色,他们在一般情况下可以直接发送给显示器直接显示
  • 那么问题来了:二班情况是什么? 其实“一般情况”指的是:不需要对颜色值进行再次加工,比如说光照计算、混合等一些操作;那么“二班情况”当然就是要对颜色值进行再次加工了;比如说,当有两张图片需要混合时,就要先对他们各自进行Gamma次方计算,变换到线性空间中(变换成理想的颜色值),再进行混合,混合完之后再进行Gamma校正,最后发送给显示器显示
  • 那么问题又来了:二班的情况为什么要变换到线性空间中? 这个问题最后回答
  • 还有一个问题:上面说“几乎”所有图片中的颜色都是经过Gamma校正过的,那么有什么图片不是?举个栗子:在基于物理的渲染中(PBR),为了高效的实现光照,常常会用到漫反射贴图、镜面光照贴图和法线贴图等一系列贴图,这里的镜面光照贴图和法线贴图通常都不是,他们用的是线性空间中的颜色
  • 最后再再总结一下: 如果用线性空间中的颜色发送给显示器显示,在显示之前要进行Gamma校正;如果用非线性空间中的颜色,则可以直接发送给显示器显示;但是,如果要对非线性空间中颜色的图片进行加工,就要在加工前先进行Gamma次方计算,加工后再进行Gamma校正,之后才能发送给显示器显示

sRGB颜色空间

  • 基于Gamma2.2的颜色空间叫做sRGB颜色空间;是反应真实世界中Gamma值为2.2的显示器的效果
  • 换成人话:就是上面说的非线性空间,用这个空间中的颜色绘制的图片可以直接交给显示器显示,并且显示出理想的颜色;他是经过Gamma校正的颜色空间

怎么使用Gamma校正?

使用OpenGL内建的sRGB帧缓冲

  • 开启sRGB帧缓冲——glEnable(GL_FRAMEBUFFER_SRGB);
  • 开启是RGB帧缓冲后就告诉了OpenGL,在每个后续的绘制命令,在颜色存储到帧缓冲之前先进行Gamma校正;这样就让OpenGL自动实现了Gamma校正
  • 总结一下:这种方式虽然方便,但有局限性,就是要明确颜色的来源是在线性空间中的,否则就会对颜色进行多次Gamma校正

自己实现Gamma校正

  • 在片段着色器中,对需要校正的颜色进行Gamma校正

sRGB纹理

  • 用sRGB颜色空间中的颜色创建的纹理就是sRGB纹理
  • 通过上面“非线性空间中的颜色从何而来?”一小段可知,用电脑绘制出来的图片,几乎都可以当做sRGB纹理来使用
  • 通过上面“sRGB颜色空间”一小段可知,在使用sRGB纹理时,可以直接交给显示器显示,不用做Gamma校正
  • 需要注意的是: 如果要对sRGB纹理中的颜色值进行加工时,需要把他们先进行Gamma次方运算转换到线性颜色中间后再加工,最后再进行Gamma校正;而OpenGL为了方便我们使用,专门增加了两种内部纹理格式:GL_SRGB和GL_SRGB_ALPHA,当我们使用这两种内部纹理格式加载sRGB纹理时,OpenGL将自动把颜色转换到线性空间中,我们只用在一通加工的最后进行Gamma校正即可

光的衰减

  • 在真实的物理世界中,光照的衰减和光源距离的平方成反比;在渲染时,如果所用的颜色都是在线性空间中,然后再按这种方式计算光的衰减,最后再进行Gamma校正,最终得到的效果会很真实;因为线性空间中的颜色更符合物理世界,大多数物理公式在线性空间中才能表现出更好的效果;因此,如果要对sRGB纹理进行加工,最好先将他们转换到线性空间中
  • 下图是使用Blinn-Phong光照模型,反光度32,再加上上面提到的光照衰减和Gamma校正,得到的效果
    在这里插入图片描述
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值