好记性不如乱笔头,这部分技术资料老早就看过,但是老是忘记,这里记录下来,可以帮助以后复习。
首先人的眼睛对亮度的感知并不是线性的,说的直白一点就是有些物理亮度人眼感知不到。比如:一个物体的亮度为0.4,随着时间的推移,亮度逐渐增加到了0.8,人眼能感知到的就是0.4和0.8这两个亮度,中间的亮度呢?抱歉人的肉眼感知不到。亮度增加一倍,人眼才能感知到。
显示器为了适应人眼的感知, 使用了一种指数关系(电压的2.2次幂)对输入的颜色信号做输出。 这个非线性映射的确可以让亮度在我们眼中看起来更好,但是也有一个问题:我们把线性颜色信息传递给显示器,显示器显示出来的不是线性颜色。比如( 0.5, 0.0, 0.0 )表示暗红色,我们把它翻一倍变成( 1.0, 0.0, 0.0 ),但是它们被传递到显示器显示的分别为(0.218, 0.0, 0.0),( 1.0, 0.0, 0.0 )。颜色的线性关系通过显示器显示后完全就没有了!!!
如果我们所有的工作都在线性空间中进行的,但最终还是要把所有的颜色输出到显示器上,所以我们传递给显示器的颜色信息,通过显示器很少能够正确的显示。出于这个原因,通常将颜色值设置得比本来更亮一些(由于显示器会将其亮度显示的更暗一些),这就是Gamma校正。如果不这样做,在线性空间里计算出来的颜色就会不正确。同时,还要记住,显示器所显示出来的图像和线性图像的最小亮度是相同的,它们最大的亮度也是相同的;只是中间亮度部分会被压暗。
Gamma校正的算法如下:
float gamma = 2.2;
fragColor.rgb = pow(fragColor.rgb, vec3(1.0/gamma));
这样我们传递给显示器的颜色会更亮一些,而且是非线性关系,但是显示器会将它们变暗,输出的是线性关系,这样我们就平衡回来了。
来源:oschina
链接:https://my.oschina.net/u/1273706/blog/3162634