线性空间是指物理意义上的真实颜色值,伽马空间是人眼会自动将真实世界进行一个伽马校正运算,即对数据进行1/2.2次幂,提高较暗区域细节,减弱亮区域细节。人眼处理这种细节变化是用了非常多感光细胞去识别较暗色区域的,杆细胞?而且这种存储过程是细胞自动进行的,具体细节很难摸索出来,如果没有伽马空间一说,美术人员制作图片是一直操控着软件去编辑线性空间意义上的图像数据,保存后存储到一张RGBA32位每一个像素的存储空间块,也就是一个像素有32位空间存储,每一个颜色分量8位存储即0~255代表每一个颜色值权重划分256个等级,归一化到(0~1)时它每一份等级步位是1/256,这就是目前最普通的最小色差表达?但肯定比不上人眼对色差敏感度,所以实际上存入到计算机的可能会得到一张不是你理想的图片,会丢失部分细节的问题。
因此,为了弥补这一点,人们想了一个办法,对原始数据进行数学计算,将暗色部分值精度提高,而亮色精度值会降低(为什么会降低亮色精度?我猜测是节省内存空间,毕竟人眼对亮区域敏感度不高,而伽马校正就是为此而设计出来的),那就是伽马校正 —— 所以说伽马校正其实就是让计算机去模仿人眼提高较暗区域细节进行存储起来,但是输出时要进行伽马变换,注意!伽马变换回来的不是原图!它其实依然是将色差拉大后的图片,只是整体恢复到线性空间,不然人眼会对它再次伽马校正(即2次伽马校正),导致整体变亮。
所有想对伽马校正后的图像进行渲染处理,都必须先经过伽马变换回线性空间(物理意义上的真实图像)不然效果会是错误的,因为伽马校正本身就只是为了模拟人眼使用,人眼的数据实际上也是错误的。(可能有点绕,可以说每个生物的眼球渲染出的图像都不同,现实世界的色彩你根本不知道是啥样的,我们只能知道我们所知物种的颜色空间观察情况,毕竟颜色只是波频不同。)
你可以通过对一张有较多暗色区域并且暗色区域细节较多的图片进行伽马校正和伽马变换(反复进行n次),当伽马校正和伽马变换逐渐增多时, 图像的暗色区域会越来越明显,亮色区域细节会越来越模糊。(这就能代表我所说的伽马校正之后再进行伽马变换其实并不是还原,因为这个运算本身就不是线性的!所以才有伽马空间 而非线性伽马空间一说了。)
参考:简单理解伽马校正_tkokof1的博客-CSDN博客_伽马校正是什么意思
总结:伽马校正和伽马变换算法的输入和输出值都是浮点数[0,1]范围内的RGBA分量值,按参考文章描述得出结论是两个暗色调范围浮点值,暗色调浮点范围定义在[0,0.218]内,比如0.155和0.164,它们色差是0.009,如果将0.155和0.164进行一次(1/2.02)求幂,会得到0.39735和0.40860,色差变为0.01125,即色差变大了0.00225,色差越大描边细节越明显,因此提升了暗色区域细节!反之,若取较高的2个数值进行如上操作,色差会变小,亮色区域细节会丢失!
注意:浮点数精度要足够大,不然伽马校正对一些只有1位小数的进行操作,可能色差就不是理想情况,理想情况是暗色值色差变大,亮色值色差变小,这个目的就是为了人眼适应暗色值更敏感,亮色值比较弱。
思考:假设如果我对一张图不断地进行伽马校正然后输出颜色到屏幕上,其效果应该是较暗区域的会描边情况越来越明显,较亮区域的会丢失描边(但是不会过曝!,因为即时是1进行伽马校正也还是1)
最终结论:伽马校正就是为了控制不同亮度值区域的色差变化程度,你可以自己写一个类似的伽马算法,来对色差进行控制!
伽马校正:对输入进行(1/2.2)求幂【输入是白虚线,输出是红虚线】可看到[0,0.218]暗部色会整体变化幅度很大,其他则比较小【但这并不能理解成变化幅度大,所以色差变大,反之亦然】。比如我用0.815和0.824去伽马校正(色差原本是0.009保持和暗色值上面的例子一样色差)得出0.90368和0.90861,色差变为0.00493,也就是色差变小了。(亮色值会变小色差 减少细节)
伽马变换:对输入进行(2.2)求幂
原文:原文! 相关文章:Unity Shader 伽马空间与线性空间_火锅肥牛的博客-CSDN博客
伽马空间: 美术出图是在伽马空间下,贴图本身会被进行伽马校正 一般是sRGB伽马空间【gamma = 2.02】
伽马校正算法: output = input^(1/gamma) (^是求幂运算符)
在输出显示器时,显示器会自动对它进行相应的伽马变换。
伽马变化算法:output = input^(gamma)
即在伽马空间下,若美术出图时是在伽马空间下进行的,则会先对图片像素进行(1/gamma)次方运算,在输出时由硬件自动进行gamma次方输出到显示器。
但此时的输出结果是和真实结果略有差异,但也不能说是完全错误的。
线性空间:sRGB Frame Buffer 是常用的线性颜色空间
美术出图时要在线性空间下出图,线性空间出的贴图不会进伽马校正,而是保持原始图片的颜色值输出到贴图。
然后,它会在输出到显示器前,用sRGB Frame Buffer的其中几个API进行伽马校正,然后再传给显示器做伽马变换输出,此时是效果是正确的。
PS:如果美术出的图是sRGB伽马空间下的,可以勾选贴图的sRGB(Color Texture)选项进行反向sRGB操作回到线性空间贴图即可。
为什么线性空间是真正的情况,而伽马空间不是?
我猜测可能是在线性空间时,贴图的像素颜色纸保持原始一样,进入渲染流程进行处理,仅仅在输出显示器前一步,进行了伽马校正,
伽马校正也只是为了抵消之后输出到显示器时的伽马变化,所以这里的伽马校正不会影响渲染流程!而伽马空间的情况恰恰相反,它是在
渲染流程之前就已经对贴图进行了伽马校正,从而将贴图整体颜色值拔高了,然后进行的渲染处理,这里就肯定会影响到渲染情况了,从而并非真正的情况。
为什么会有sRGB伽马空间和sRGB Frame Buffer线性空间?
个人猜测无非以下原因:
原本是只有线性空间的,即不会做伽马变换处理,但后来人们发现人眼识别黑色区域比光亮区域更敏感,所以将在显示到屏幕之前进行了一个伽马变换,伽马变换会将[0,1]的数变得更小,
即整体变暗,从而让视觉效果更好看,但这已经并非真实的效果了,后来好像有了手段不需要做这种伽马变换就能达到同样的视觉效果了,但由因为伽马变换已经根深蒂固地嵌入了硬件里,所以诞生了伽马校正。 伽马校正是伽马变换的反向操作,就是为了抵消掉伽马变换的影响的。
一开始人们想不到办法在输出之前控制渲染流程进行做伽马校正,所以有了sRGB伽马空间的做法,即将贴图的信息提前进行了一次伽马校正,然后再进入渲染流程,输出到屏幕时做伽马变换就能恢复回原图情况,但人们没想到这种效果并非真实,因为上面我所猜的情况可能就是会有影响到渲染细节问题。
紧接着就理所当然地想到了可以在渲染流程最后一步,即显示到显示器前,进行线性空间sRGB Frame Buffer相关处理,简单来说就是贴图保持原样进行渲染,将渲染结果先缓存到这个Buffer然后做伽马校正,然后再传递给显示器进行伽马变换输出到屏幕。