赞
踩
在物理世界中,如果光的强度增加一倍,那么亮度也会增加一倍,这是线性关系,为了模拟真实的物理世界,需要把亮度值转换到线性空间计算,这样才能得到正确的结果
Gamma的产生有两个主要原因:一个是CRT显示器非线性响应的历史原因,另一个是人眼对暗部颜色更敏感
早期CRT显示器的电压和输出的亮度是非线性的,亮度(
l
l
l)等于电压(
u
u
u)的2.2次幂,即图中下凹曲线
l = u 2.2 , l ∈ [ 0 , 1 ] , u ∈ [ 0 , 1 ] l = u^{2.2},l\in[0,1],u\in[0,1] l=u2.2,l∈[0,1],u∈[0,1]
这里的Gamma值就是2.2,现代显示器仍然使用这个Gamma值,显示器使用Gamma2.2空间意味着显示器会对每个像素进行一个2.2的幂运算,整体画面就会偏暗,为了抵消显示器的影响,需要对图像进行一个0.45的幂运算(0.45 ≈ 1 / 2.2),这个平衡的操作就叫做Gamma校正
另一个原因是人眼对暗部颜色更敏感
上方是人眼感觉到的亮度从0到1的变化,下方是真实世界中亮度从0到1的变化,人眼的感知是非线性的
RGBA中每个通道只有8位,只能存储256(
2
8
2^8
28)个级别的亮度,为了存储更多的暗部信息,会对存储的图像进行Gamma矫正(即进行0.45的幂运算),这样图像会更亮,相当于扩大暗部的范围,当然较亮的部分会丢失细节
两个颜色叠加,0.2和0.3
在线性空间直接计算,0.2 + 0.3 = 0.5
在Gamma空间中,
(
0.
2
0.45
+
0.
3
0.45
)
2.2
≈
1.15
(0.2^ {0.45} + 0.3^ {0.45} )^{2.2} ≈ 1.15
(0.20.45+0.30.45)2.2≈1.15
两个颜色混合,0.1和0.7
在线性空间直接计算,(0.1 + 0.7) / 2 = 0.4
在Gamma空间中,
(
(
0.
1
0.45
+
0.
7
0.45
)
/
2
)
2.2
≈
0.3289
((0.1^ {0.45} + 0.7^ {0.45} ) / 2)^{2.2} ≈ 0.3289
((0.10.45+0.70.45)/2)2.2≈0.3289
这就导致在Gamma空间中一些较亮的部分容易过曝
Gamma工作流,这里的Shader计算就会出现上面说的问题
适合:无光照,无透明混合
对性能无影响
线性工作流,对性能有影响
在Unity中设置色彩空间,现在主流游戏都已经转向线性空间
1996年,微软和惠普一起开发了一种标准sRGB色彩空间,s表示Standard。sRGB对应的是Gamma0.45所在的空间。
进过Gamma矫正和显示器矫正,还原到原来的亮度
(
u
0.45
)
2.2
(u^ {0.45})^{2.2}
(u0.45)2.2
线性空间下,贴图如果勾选sRGB表示移除Gamma矫正,即会对贴图做一个2.2的幂运算,就是贴图会变暗一点,具体参考上面的线性工作流,等价于在片元着色器中做了如下操作
fixed4 frag (v2f i) : SV_Target
{
float3 c = tex2D(_MainTex, i.uv);
c = pow(c, 2.2);
return float4(c, 1);
}
在变量前加[Gamma]也表示移除伽马矫正,即会对变量做一个2.2的幂运算,[Gamma]只在线性空间下有用
[Gamma]_Metallic("Metallic", Range(0,1)) = 0.5
Unity中Color Space、Gamma、Linear、sRGB都是什么?
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。