投石问路Unity内置管线升级URP之色彩空间(伽马sRGBGamma Space和Linear Space)
Posted CrisFu
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了投石问路Unity内置管线升级URP之色彩空间(伽马sRGBGamma Space和Linear Space)相关的知识,希望对你有一定的参考价值。
目录
投石问路系列寓意
希望通过投石问路的方式,让更多的读者指出笔者的问题或给予更好的方案。
本文内容
unity从推出SRP渲染管线后,相继为使用者基于SRP定制了两套渲染管线:URP和HDRP。越来越多的手游团队也开始着手于从Built-in管线升级到URP管线。那从Built-in升级到URP有个比较大的变化之一是什么呢,就是色彩空间从Gamma Space转到了Linear Space。那随之而来可能会出现些什么问题呢,比如:“相同的场景和光照,升级后变暗”、“个人定制化的PBR显示不正确了”、“特效显示不正确了”等等。本文主要讨论造成这些问题的缘由。
伽马(Gamma)
为什么要讨论Gamma这个概念,就先从人眼对光亮度的非线性感知说起。
举个例子,夜晚时,当人处于一个漆黑的房间,这时点亮1盏100瓦的灯,人眼会觉得很明显的变亮了。接着点亮第2盏100瓦的灯,人眼会觉得有亮了很多,但亮度的变化会没有第一盏灯亮强烈。然后继续依次点灯,当灯数量增长到一定多,比如50盏100瓦的灯,现在不论是熄灭一盏灯还是再点亮一盏灯,人眼都基本没有任何亮度变化的感知了。
但是呢,对于灯发射的光子数量,却还是在继续的变化。当你点亮1盏灯时,有1x的光子数量进入人眼,当2盏灯时,有2x的光子数量进入人眼,50盏灯时,就会有50x的光子数量进入人眼。
如果把光子数量和对应人眼感知看到的亮度表示成一张图片,就会有下边这样子一个光子数量线性,但肉眼看起来非线性的物理光强图。
在此图中有一个特殊地方,用于表现中间调,名为中性灰,也叫做18%的灰。高于此点的即为亮部,低于此点的即为暗部。
相机是怎么存储图像的呢?不论说是胶片相机还是数码相机,都是无法直接感知真实世界的颜色,而是通过光子数量来存储颜色(接下里主要讨论的是数码相机)。相机的光感原件通过均匀的信号采样,存储下采样到的光子数量,就得到了一张图像。
假如采样10个信号,可以发现亮部采样了大约80%个点,而暗部采样了大约20%个点。
这时会出现一个问题。亮部采样点足够多,表现充分;而暗部采样过少,表现不足,出现很明显的色阶情况,如下图一样。(注:下图色阶数值并不准确,只为表达意思)
既然暗部的采样点太少了,导致暗部变现不足,那就提高采样次数呢。10次不够,就采样1000次或者更多,这样暗部的采样点就多起来了。不错,思路是对的。但是呢,如果把所有的采样点都存储下来,图像的大小就会变得很大,带来内存和带宽的巨大压力,更加的得不偿失。
那要怎么处理才合适?提高采样次数的同时,舍弃一部分采样点。刚上边也说到了,亮部的采样点已经足够多表现细节。提高采样次数后,更多的采样点并不会给亮部带来太明显的变化,即可有可无,那就可以选择舍弃掉较多的亮部采样点(可以结合房间电量很多灯之后,加灯减灯人眼无任何感觉理解)。
可以从上图看出,舍弃了很多的亮部采样点,保留了更多的暗部采样点,就可以得到一个亮部和暗部均表现充分的且线性的采样图。
一般称这样看起来线性,光子数量非线性的图为美术灰度图。
这样的采样过程就叫做Gamma的采样。
显示设备怎么输出呢?,比如电脑显示器,如果说直接就把这样子一个采样点交给人眼识别,肯定就不正确了,因为已经把采样曲线变成了非线性,而不是线性的物理光强了。
显示器需要做的就是通过一个采样的反函数把非线性的采样还原成线性,这个操作就叫做Gamma的矫正。
好了,经过两次的Gamma操作,就可以在显示器上的充分且真实的表现物理空间的色彩了。
sRGB
有个Gamma这样的一个想法后,各厂家应该怎么处理呢。不可能说各自按照各自的想法来,制造生成图像设备的厂家制定自己采样的规则,然后制造显示设备的厂家跟着去做各种适配。1996年,微软和惠普就一起制定一种标准的色彩空间:sRGB(standard Red Green Blue)。这种标准得到了各大厂商的支持。
sRGB对应的就是Gamma0.45所在空间,对应的显示设备的就是Gamma2.2所在空间。(就如上图gamma采样曲线表现一样,约为0.45的幂函数;显示设备约为1 / 0.45 = 2.2的幂函数 )
注意:
1.sRGB只是一种主流的标准,还有其他的标准。
2.上边所说的生成图像设备并不单指相机,也包含各种dcc软件,譬如PhotoShop。
3.生成图像设备和显示设备的Gamma值并非全是0.45和2.2。譬如相机可以调整gamma效果、ps可以选择工作空间RGB定义的gamma值,好一点的显示器也会有gamma选项。还有就是电影和影院放映也是用的独特的一套gamma参数,以达到更好的效果。反正记住一点,用多少的gamma曲线存储图像,就用对应倒数的gamma曲线还原,才能达到最佳的效果。
色彩空间(Color Space)
unity提供了两套色彩空间:Gamma Space和Linear Space。
内置Built-in管线大多时候使用的都为Gamma Space,基于SRP打造的URP和HDRP管线则使用的是Linear Space。
两种色彩空间的区别在于什么呢?
Gamma Space:不会对计算前的输入和计算后的输出做任何改变,全程都是保持使用Gamma0.45空间的数值计算。
Linear Space:会对计算的输入部分进行一个Gamma2.2的处理,得到Gamma1.0这样一个线性的值来计算,对计算的输出部分进行一个Gamma0.45的处理还原到Gamma0.45空间的数值。
(为什么Linear Space要这样子进行一个处理呢?上边说过我们的色彩大部分是按照sRGB方式存储的,已经非线性了。我们计算的方式又是按照真实世界线性的方式去计算,一个非线性的输入 + 一个线性的计算方式得到的结果肯定会和真实世界不一样。解决方式就两种:计算方式的改变和输入的改变。Linear Space就是采用统一输入的方式来让计算结果更加正确)
两者的区别就在于计算时:Gamma Space的计算空间为Gammaa0.45, Linear Space的计算空间为Gamma1.0。
上边有说到,Linear Space会对部分输入进行Gamma2.2的处理,具体是哪部分呢?部分贴图的RGB值和所有shader定义的颜色的RGB值。
所有shader定义颜色就不多说了,指材质面板看到的颜色输入。(注:也包含光照的颜色)
部分贴图的RGB值是个什么意思呢?大家可以看到部分贴图的面板中有个sRGB的选项。
使用内置Built-in管线+Gamma Space的朋友应该知道,不论是否勾选此选项,对于效果来说都没有任何变化,是因为Gamma Space不会对输入进行任何处理。但是在Linear Space中,此选项就决定了该贴图的RGB值是否要进行Gamma2.2的处理。下图就可以看出,在Linear Space空间,如果不勾选sRGB,就会导致颜色偏亮。
注意:
1.上述说的贴图是普通贴图,针对如法线贴图、光照贴图等不是按照sRGB格式存储的图片,就没有sRGB选项,且不会进行Gamma2.2的处理。
2.刚一直在说自定义颜色的RGB和贴图的RGB,并未提到Alpha?所有颜色Alpha通道和贴图的Alpha通道是不会进行Gamma2.2的处理。
总结
结合上边所说,就可得到上边这样子一个表示贴图颜色从出生至显示设备的一个过程。
转色彩空间后出现问题的缘由
1.相同场景材质和光照为什么变暗了?
场景材质中经常会用到一个内容:球谐光照。
可以从其中一块看出,就是在Gamma Space输出颜色时会进行一个接近Gamma0.45的操作,而在Linear Space时,不会进行这个处理,只会在输出时统一进行Gamma0.45的操作。先加后幂会比先幂后加得到的值更低,表现出来就是场景变暗了。
2.个人定制化的PBR显示不正确了?(讨论的是金属流)
金属流有三张重要的贴图:base color + roughness + metallic。定制化PBR时,可能都会有考虑过混合图像,比如:把roughness(R通道) + metallic(G通道) + other(例: AO)(B通道)合成一张贴图使用。发现在Built-in管线 + Gamma Space显示很正确,但是升级到URP + Linear Space后,GGX部分完全显示不正常了。
问题出现的重点在于金属流几张重要贴图的的存储方式:base color(0 - 255sRGB)、metallic(0 - 255sRGB)和 roughness(0.0 - 1.0)。大部分时候,固有色和金属是使用sRGB方式存储,而粗糙度则是直接用线性的方式存储。当按照定制化的方式合成贴图后,在Gamma Space不会有任何问题,因为不会对输入和输出进行处理;在Linear Space,且勾选了sRGB选项后,roughness存储的线性值经过Gamma2.2的处理变得非线性了,从而导致GGX部分显示出错。这时就需要进行Gamma0.45的处理,还原线性。
对比说下Unity Sample中的金属图,同样是混合图像,但却是用Alpha通道来存储的roughness。
上边有说过Alpha通道一个很重要的特性:不会受到Linear Space的Gamma2.2的影响。这样子就避免了切换色彩空间带来的问题。
3.特效显示不正确
可以明显的看到两个特效(贴图、材质和特效参数均一样)的区别:左边非线性增长 、右边线性增长。该特效是使用了一个uv的v方向值灰度图来表现推进这一部分的效果。这个灰度图放在Gamma Space,不论勾选sRGB都不会对特效有影响;但是放到Linear Space后,如果勾选了sRGB,就把线性值变得不线性,导致左边不线性的情况,去掉sRGB后就能恢复右边线性的效果。
由于现在越来越多的使用通道图像代替彩色图像,就需要更加注意色彩空间的影响。
以上是关于投石问路Unity内置管线升级URP之色彩空间(伽马sRGBGamma Space和Linear Space)的主要内容,如果未能解决你的问题,请参考以下文章