餐饮美食网站模板源码,上海天华建筑设计有限公司官网,app开发工具下载,济南wordpress 建站伽马校正
B站视频#xff1a;图形 2.6 伽马校正 文章目录 伽马校正颜色空间传递函数 Gamma校正校正过程为什么需要校正#xff1f;CRT与转换函数 为什么sRGB在Gamma 0.45空间#xff1f; 人对亮度的敏感韦伯定律中灰值 线性工作流不在线性空间下进行渲染的问题统一到线性空…伽马校正
B站视频图形 2.6 伽马校正 文章目录 伽马校正颜色空间传递函数 Gamma校正校正过程为什么需要校正CRT与转换函数 为什么sRGB在Gamma 0.45空间 人对亮度的敏感韦伯定律中灰值 线性工作流不在线性空间下进行渲染的问题统一到线性空间 Unity中颜色空间硬件支持硬件特性支持 资源导出问题Substance PainterPhotoShopDocument Color Profile半透明UI 其余参考资料作业自己动手尝试进行gamma校正 颜色空间 通用sRGB
电影DCI-P3
电视Rec-709、PAL等
印刷CMYK、Adobe RGB
其他
传递函数
在已经知道了颜色空间下的三原色的值但是要将其显示到电子设备上就需要将其转换为视频信号这就需要用到传递函数。
传递函数包含两部分 光信号转为电信号OETF。例如拍视频时需要把场景中的线性的光转换到非线性的视频信号 电信号转换成光信号EOTF。例如在电脑上播放视频时需要把非线性的视频信号转换成显示在设备上的光信号 Gamma校正
Gamma可以简单定义为 V o u t V i n g a m m a V_{out} V_{in^{gamma}} VoutVingamma Gamma是指对线性三色值和非线性视频信号之间进行编码和解码的操作。 校正过程 图像经过gamma编码存储在硬盘中将获取到的物理数据做一次gamma值约为0.45的映射这样的过程叫做gamma编码。 由上图0.45曲线可知曲线形状上拱此时图像像素比实际物理像素要更亮。 在显示图像时需要将对经过了0.45映射图像的每个像素做一次gamma值约为2.2的校正一般是显示器校正使得最终结果为正确的物理数据相当于曲线拉直了。 经过显示的gamma校正之后之前偏亮的图像亮度降低。
为什么需要校正
在物理世界中如果光的强度增加一倍那么亮度也会增加一倍这是线性关系。
而历史上最早的显示器CRT阴极射线管显示图像的时候电压增加一倍亮度并不跟着增加一倍。即输出亮度和电压并不是成线性关系的而是呈亮度增加量等于电压增加量的2.2次幂的非线性关系 l u 2.2 ( l ∈ [ 0 , 1 ] , u ∈ [ 0 , 1 ] ) l u^{2.2} \space\space\space\space (l \in [0,1],u \in[0,1]) lu2.2 (l∈[0,1],u∈[0,1]) 2.2也叫做该显示器的Gamma值现代显示器的Gamma值也都大约是2.2。如果我们在显示器输出之前做一个操作把显示器的Gamma 2.2影响平衡掉那就和人眼直接观察物理世界一样了。
CRT与转换函数 左图为Gamma编码的曲线也是人眼对于一个物理光强度的一个响应曲线。
右图为早期CRT在Gamma 2.2时电压与屏幕亮度之间对应关系的一个映射曲线。
可看出这两个曲线是互为反函数的一个关系。
以物理光强0.218为例
在经过Gamma编码曲线映射之后就变成了0.5显示在CRT上时会经过Gamma 2.2的映射从0.5映射回0.218。
为什么sRGB在Gamma 0.45空间
假设你用数码相机拍一张照片你看了看照相机屏幕上显示的结果和物理世界是一样的。可是照相机要怎么保存这张图片使得它在所有显示器上都一样呢 可别忘了所有显示器都带Gamma 2.2。反推一下那照片只能保存在Gamma 0.45空间经过显示器的Gamma 2.2调整后才和你现在看到的一样。换句话说sRGB格式相当于对物理空间的颜色做了一次伽马校正。
还有另外一种解释和人眼对暗的感知更加敏感的事实有关。 如图在真实世界中第二行如果光的强度从0.0逐步增加到1.0那么亮度应该是线性增加的。但是对于人眼来说上方感知到的亮度变化却不是线性的而是在暗的地方有更多的细节。换句话说我们应该用更大的数据范围来存暗色用较小的数据范围来存亮色。这就是sRGB格式做的定义在Gamma 0.45空间。而且还有一个好处就是由于显示器自带Gamma 2.2所以我们不需要额外操作显示器就能显示回正确的颜色。
人对亮度的敏感 将自然界线性增长的亮度的一个灰阶变化和人心理上感受到的均匀灰阶做一个映射就能得到上图的曲线。
其中自然界线性增长的亮度0.2位置对应的就是人心理上感受到的一个中灰值。如果把人心理上感受到的中灰值以下称为暗部部分把中灰值以上称为亮部部分可以明显看到暗部曲线会比亮部曲线更陡峭这也就对应了上文说道的人眼在感受亮度变化时对于暗部的变化明显比亮部的变化要更敏感。
换句话说人眼在应对外界的亮度刺激均匀增长的过程中会从刚开始的比较敏感然后逐渐到越来越不敏感这种现象也符合一个定律韦伯定律。
韦伯定律
即感觉的差别阈限随原来的刺激量的变化而变化而且表现为一定的规律性。公式如下 C Δ ϕ ϕ 其中 ϕ 为原刺激量 Δ ϕ 为此时的差别阈限 C 为常数又称为韦伯率 C \frac {\Delta \phi} \phi \\ 其中\phi为原刺激量\Delta \phi为此时的差别阈限C为常数又称为韦伯率 CϕΔϕ其中ϕ为原刺激量Δϕ为此时的差别阈限C为常数又称为韦伯率 简单来说就是当所受刺激越大时需要增加的刺激也要足够大才会让人感受到明显变化但是只适用于中等强度的刺激。
中灰值
现在有一张黑白渐变图和一条纯灰图如下所示 将纯灰图移至渐变图中间原本纯灰的表现在感受上就会出现些许渐变的效果。
又比如下图 A区域的颜色和B区域的颜色在感受上明显不一致左图但如果在A和B之间用一个纯灰条进行连接右图就可以看见实际上这两个区域的颜色是一致的。
从以上表现可得出中灰值并非是一个具体的数值而是取决于人的视觉感受。
线性工作流 线性工作流就是在生产的各个环节正确使用Gamma编码以及Gamma解码使得最终得到的颜色数据与最初输入的物理数据一致。
如果是使用Gamma空间的贴图在传给着色器之前需要从Gamma空间转换到线性空间。目的是为了在着色器中进行一些渲染计算的时候使用的是线性空间的颜色值这样就不会出现一些错误的显示结果。
不在线性空间下进行渲染的问题 若不在线性空间下进行渲染计算在进行亮度叠加时左图会出现过曝的效果。这是因为Gamma空间下的值在经过Gamma编码之后此时的值是比实际的值要更大。例如原本四个亮度为0.098的值进行叠加以后应该是0.196结果由于在Gamma空间下0.098的值被编码为0.35也就是四个0.35的值进行叠加最后得出1.4超过了1就会有过曝的效果。
此外在进行颜色的混合时如果在混合前没有对非线性的颜色进行转换就会在纯色的边界出现一些黑边右图。 在进行光照渲染计算时如果我们把视觉上也就是非线性空间的中灰值0.5当成物理光强为0.5去计算就会出现上图左边的情况。
统一到线性空间 我们从橙色框的左上角出发。
第一步输入的纹理如果是sRGBGamma 0.45那我们要进行一个操作转换到线性空间。这个操作叫做Remove Gamma Correction在数学上是一个2.2的幂运算。如果输入不是sRGB而是已经在线性空间的纹理了呢那就可以跳过Remove Gamma Correction了。
注美术输出资源时都是在sRGB空间的但Normal Map等其他电脑计算出来的纹理则一般在线性空间即Linear Texture。
第二步现在输入已经在线性空间了那么进行Shader中光照、插值等计算后就是比较真实的结果了如果不对sRGB进行Remove Gamma Correction直接就进入Shader计算那算出来的就会不自然就像前面那两张球的光照结果一样。
第三步Shader计算完成后需要进行Gamma Correction从线性空间变换到Gamma 0.45空间在数学上是一个约为0.45的幂运算 。如果不进行Gamma Correction输出会怎么样那显示器就会将颜色从线性空间转换到Gamma 2.2空间接着再被你看到结果会更暗。
第四步经过了前面的Gamma Correction显示器输出在了线性空间这就和人眼看物理世界的过程是一样的了。
Unity中颜色空间
通过点击菜单Edit - Project Settings - Player页签 - Other Settings下的Rendering部分进行修改参数Color Space可以选择Gamma或Linear。 如果选择了Gamma那Unity不会对输入和输出做任何处理换句话说Remove Gamma Correction 、Gamma Correction都不会发生除非你自己手动实现;如果选了Linear那么就是上文提到的统一线性空间的流程了。对于sRGB纹理Unity在进行纹理采样之前会自动进行Remove Gamma Correction对于Linear纹理则没有这一步。而在输出前Unity会自动进行Gamma Correction再让显示器输出。
怎么告诉Unity纹理是sRGB还是Linear呢对于特定用途的纹理可以直接设置他们所属的类型如Normal Map、Light Map等都是Linear设置好类型Unity自己会处理他们。 还有一些纹理不是上面的任何类型但又已经在线性空间了比如说Mask纹理、噪声图那你需要取消sRGB这个选项让它跳过Remove Gamma Correction过程 到底什么纹理应该是sRGB什么是Linear
所有需要人眼参与被创作出来的纹理都应是sRGB如美术画出来的图。所有通过计算机计算出来的纹理如噪声MaskLight Map都应是Linear。
硬件支持
线性空间需要图形API的硬件支持目前支持的平台 Windows、Mac OS x、Linux(Standalone) Xbox one PS 4 AndroidOpenGL ES 3.0 IOSMetal WebGL
硬件特性支持
主要由两个硬件特性来支持 sRGB Frame Buffer 将Shader的计算结果输出到显示器前做Gamma校正作为纹理被读取时会自动把存储的颜色从sRGB空间转换到线性空间调用ReadPixels()、ReadBacklmage()时,会直接返回sRGB空间下的颜色;sRGB Frame Buffer只支持每通道为8 bit的格式不支持浮点格式;HDR开启后会先把渲染结果绘制到浮点格式的Frame Buffer中最后绘制到sRGB Frame Buffer上输出。 sRGB Sampler 将sRGB的贴图进行线性采样的转换。
使用硬件特性完成sRGB贴图的线性采样和shader计算结果的Gamma校正比起在shader里对贴图采样和计算结果的校正要快。
资源导出问题
Substance Painter 当Substance的贴图导出时线性的颜色值经过Gamma编码颜色被提亮了所以需要在Unity中勾选sRGB选项让它在采样时能还原回线性值。
PhotoShop 如果使用线性空间一般来说PhotoShop可以什么都不改导出的贴图只要勾上sRGB就可以了。如果调整PhotoShop的伽玛值为1导出的贴图在Unity中也不需要勾选sRGB了。
Document Color Profile
PhotoShop对颜色管理特别精确Unity里看到的颜色要经过显示器的Gamma变换而PhotoShop不会PhotoShop会读取显示器的Color Profile反向补偿回去PhotoShop有第二个Color Profile叫做Document Color Profile。通常它的默认值就是sRGB Color Profile和显示器的Color Profile一致颜色是被这个Color Profile压暗了所以PhotoShop中看到的结果才和Unity中一样。
半透明UI Unity中的混合是线性混合PhotoShop的图层和图层之间做混合的时候每个上层图层都经过了伽马变换然后才做了混合。在设置中更改选择“用灰度系数混合RGB颜色“参数设置为1这样图层才是直接混合的结果。
其余参考资料
Gamma、Linear、sRGB 和Unity Color Space你真懂了吗 - 知乎
作业
自己动手尝试进行gamma校正
主贴图 ① 将主贴图是否勾选sRGB选项进行对比
结果 可看出未勾选sRGB的主贴图将Gamma空间的颜色值直接加入渲染计算最后呈现出来的颜色比原图亮很多。
② 对未勾选sRGB的主贴图进行采样并手动转化到Linear空间 Shader
Shader TA100/2_6_GammaToLinear
{Properties{_MainTex (Texture, 2D) white {}}SubShader{Tags { RenderTypeOpaque }LOD 100Pass{CGPROGRAM#pragma vertex vert#pragma fragment frag#include UnityCG.cgincstruct appdata{float4 vertex : POSITION;float2 uv : TEXCOORD0;};struct v2f{float2 uv : TEXCOORD0;float4 vertex : SV_POSITION;};sampler2D _MainTex;float4 _MainTex_ST;v2f vert (appdata v){v2f o;o.vertex UnityObjectToClipPos(v.vertex);o.uv TRANSFORM_TEX(v.uv, _MainTex);return o;}fixed4 frag (v2f i) : SV_Target{fixed4 col tex2D(_MainTex, i.uv);//Gamma to Linear//col.rgb pow(col.rgb, 2.2);//UnityCG APIcol.rgb GammaToLinearSpace(col.rgb);return col;}ENDCG}}
}