大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。
Jetbrains全系列IDE稳定放心使用
一、Gamma校正
1、颜色空间
图中可以看到,sRGB和Rec.709的色域虚线一样,三原色的位置是相同的,那么它们之间的区别就是:传递函数不同
2.传递函数
定义
知道了颜色的颜色值之后,想要在电子设备上显示,就需要把它转换为视频信号,需要一个函数来换算,传递函数就是用来做转换的。
传递函数包括两部分
光转电传递函数(OETF),把场景线性光转到非线性视频信号值。
电转光传递函数(EOTF),把非线性视频信号值转到显示光亮度。
3.Gamma校正
定义
伽马是显示器电光传递函数的一种,是指对线性三色值和非线性视频信号之间进行编码和解码的操作。
例子:
OETF:拍到的照片,存在电脑里,就是把自然界中的光信号编码为视频信号
EOTF:查看照片时,就要把视频信号还原为线性的光信号,进行解码操作
线性空间(相机捕捉到的真实世界光信号) + gamma编码 + 显示器显示 = 结果
左图为存在硬盘中,将捕获到的物理数据做一次gamma值约为0.4的映射
中间为显示图像时,需要为每一个像素做一次gamma值约为2.2的校正,来使的最终结果为正确的物理数据。
经过gamma校正好,之前偏亮的图像亮度降低了。
二、为什么用Gamma校正
概括
1、和人眼的特性有关
人眼对暗部的变化感应更敏感
2、非线性转换为了优化存储空间和带宽
我们用于显示图像数据都是8bit,要充分利用带宽,就需要使用更多位置去存储暗部值。也就是 暗部使用高精度保存,亮部使用相对较低精度保存。
伽马2.2的存在和显示器本身没有任何因果关系,伽马2.2是为了让8位图 有限的存储空间可以表达适合人眼的色彩感知特性而不产生色彩断层(因为人眼对亮部和暗部的感知是非线性的,对暗部更敏感),伽马2.2的目的是将有限的色彩信息存储空间更多地留给暗部
1、人眼特性展开
韦伯定理
当所受刺激越大时,需要增加的刺激也要足够大才会让人感觉到明显的变化,但是只适用于中等强度的刺激
全黑时增加一点亮度就能看到变化,每一次都要比上次增加更多的光照量才能看到变化,所以暗部我们感知细腻,亮部看不出变化
美术上的均匀和物理上的均匀
上边是视觉上的均匀变化,而下边是物理量上的均匀变化。
理论上上边的中灰是物理量上(下边)的21.8%,视觉上认为的美术中灰色,大约是物理中灰色的20%
Gamma校正就是一个把物理灰阶映射成美术灰阶的函数
为什么现实中看到的光强度变化是正确的,不能忠实的记录下来显示就行了,而要来回转换呢?
2、优化带宽展开
8位通道图片只能储存256种灰阶
现实有无限灰阶,8位通道图片只能储存256种灰阶有要节约使用
上一点我们知道人眼对亮部不敏感,对暗部敏感
如果用物体上物理光照强度的50%作为采样中线
按照物理光强的变化来均匀采样
可以看到人眼感知到的亮部区域用了大量灰阶来采样,而暗部却很少,因为暗部的物理变化量小
如果均匀采样物理灰阶,暗部只有56个层次可用
暗部采样灰阶不够用便会出现巨大色阶断层
均匀记录美术灰阶的样本分布
就可以解决这个问题
所以为了用有限的灰阶采集到人眼感兴趣的信息,我们需要使用伽马校正在美术灰阶和物理灰阶之间转换
三、应用
unity中的伽马设置
Unity中GAMMA校正的一些内置函数
Unity中GAMMA校正的一些内置函数
inline float GammaToLinearSpaceExact (float value)
{
if (value <= 0.04045F)
return value / 12.92F;
else if (value < 1.0F)
return pow((value + 0.055F)/1.055F, 2.4F);
else
return pow(value, 2.2F);
}
inline half3 GammaToLinearSpace (half3 sRGB)
{
// Approximate version from http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1
return sRGB * (sRGB * (sRGB * 0.305306011h + 0.682171111h) + 0.012522878h);
// Precise version, useful for debugging.
//return half3(GammaToLinearSpaceExact(sRGB.r), GammaToLinearSpaceExact(sRGB.g), GammaToLinearSpaceExact(sRGB.b));
}
inline float LinearToGammaSpaceExact (float value)
{
if (value <= 0.0F)
return 0.0F;
else if (value <= 0.0031308F)
return 12.92F * value;
else if (value < 1.0F)
return 1.055F * pow(value, 0.4166667F) - 0.055F;
else
return pow(value, 0.45454545F);
}
inline half3 LinearToGammaSpace (half3 linRGB)
{
linRGB = max(linRGB, half3(0.h, 0.h, 0.h));
// An almost-perfect approximation from http://chilliant.blogspot.com.au/2012/08/srgb-approximations-for-hlsl.html?m=1
return max(1.055h * pow(linRGB, 0.416666667h) - 0.055h, 0.h);
// Exact version, useful for debugging.
//return half3(LinearToGammaSpaceExact(linRGB.r), LinearToGammaSpaceExact(linRGB.g), LinearToGammaSpaceExact(linRGB.b))
}
Substance Painter
PS
从PS中导出图片,如果把灰度系数设为一的话,在Unity中就不需要勾选sRBG选项了;
如果PS中什么都不做设置的话,在Unity中勾选sRGB选项即可。
Document Color Profile
-
PS对于颜色的管理是很精准的,我们在Unity中看到的颜色要经过显示器的gamma变换,而PS中的不会,PS会读取显示器的Color Profile,反向补偿回去
-
-
也就是说,ps中的是真实的颜色值
-
-
PS自身有一个系统,会通过灰度值控制颜色的显示,(通常情况下这个值和显示器的gamma值一致,所以看起来会和Unity中看到效果的一样),可以通过改变灰度值来改变最终颜色显示的结果。
-
PS中8位通道 ctrl+t缩小、柔边笔刷涂抹、高斯模糊 显示结果都不是真实物理颜色
和渲染器是一个道理。
问题都处在:想做物理计算,工作环境却是8位通道的非线性色彩空间,计算结果会比预期更暗、更黑
缩小的操作
日常中影响不大,但在极端情况下会出错,例如下图情况(高频变化的信息一定会出错)
图中黑白格易拉宝,如果要ctrl+t缩小画面,图中的黑(0)白(1),就要求平均色,也就是0.5,但是在8位通道环境下,0.5对应128号灰(美术中灰);但是物理世界中,离远看如果是50%的反射率,应该是物理中灰,但是PS算出来的却是美术的中灰(物理的0.218)。
-
解决方法:图像—模式中选择32位通道即可
柔边笔刷涂抹
涉及到线性插值方程、本质上是模拟半透明物体的前后遮挡
高斯模糊
32位通道下的高斯模糊滤镜有非常自然的混合效果
下面8位通道的高斯模糊偏暗
存储的小技巧
在32位通道下完成操作(计算),最后再切换为8位通道保存
半透明效果
Unity中:
Unity进行半透明混合时,会先将它们转换到一个线性空间下然后再混合
PS中:
PS的图层和图层之间做混合时,每个上层的图层都会读取他们的Color Profile(gamma值),然后经过一个gamma变换再做混合,这样做得结果就会偏暗一些。
(可以在它的工作空间 的设置中进行更改,选择用灰度系数混合RGB颜色,参数设置为一,这样图层才是一个最终直接混合的结果
unity设置中修改
Linear空间
Gamma空间
参考资料
【技术美术百人计划】图形 2.6 伽马校正_哔哩哔哩_bilibili
Gamma校正与线性工作流入门讲解_哔哩哔哩_bilibili
发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/189745.html原文链接:https://javaforall.cn
【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛
【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...