MY BLOG DIRECTORY:
YivanLee:专题概述及目录![图标](https://i-blog.csdnimg.cn/blog_migrate/b09af8aa7673f507dda5232c8fed91cd.png)
INTRODUCTION:
在游戏开发的时候,经常遇到一些概念:sRGB,AdobeRGB,HSL,HSV,HSB,GammaSpace,LinearSpace。本篇就来梳理一下他们的关系和转换方法。
MAIN CONTENT:
【1】sRGB AdobeRGB CMYK LAB HLS
![v2-a2ca5d3ccb5b74d1bb2520fa8c4dffbb_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/60825e6924ed888441d6b5d450f308e4.jpeg)
可见光颜色
当光波进入人眼后,人眼内的感光细胞接受到刺激产生电信号让大脑知道了该光线的颜色。人能感受到的光波是有范围的,称为可见光,我们看到的这些可见光的颜色就是可见光颜色范围。
LAB颜色标准
这是一个颜色范围标准,它的范围巨大,最外层的就是lab的色彩范围。
sRGB颜色标准
sRGB是惠普与微软于1996年一起开发的用于显示器、打印机以及因特网的一种标准RGB色彩空间。这种标准得到了许多业界厂商的支持,但是由于这套色彩标准制定的时间太早,很多技术和概念都不成熟,所以他只有当时CIE色域标准的30%,并且色彩还原度也不高,而且它的绿色覆盖率极低(见上图)。也是因为这样,它对显示器的要求不高,所以现在市面上大多数显示器都能达到sRGB100%,sRGB100%仅是一个入门主流水平。目前游戏开发使用的是这套标准。后面的相关论述也默认以sRGB为准。
adobeRGB颜色标准
adobeRGB是adobe公司在1998年创建的一个新的色彩标准。sRGB转Adobe RGB几乎无损,Adobe RGB转sRGB,超出部分信息丢失,相容部分有较小误差。青绿色系提升印刷行业受益。
NTSC颜色标准
NTSC是在1952年12月由美国国家电视系统委员会制定的彩色电视广播标准,这种制式的色度信号调制包括了平衡调制和正交调制两种,它目前被用来测试电视屏幕所能覆盖的色彩范围,虽然也有用它来测试显示器的,但相对来讲并不标准,因为NTSC的整体范围更偏中性,且它的出现主要是解决了当时彩色、黑白电视广播兼容问题,其色彩信号存在相位容易有损、色彩不太稳定等缺点。
HSL颜色标准
HSL色彩模式是工业界的另一种颜色标准,是通过对色相(H)、饱和度(S)、明度(L)三个颜色通道的变化以及它们相互之间的叠加来得到各式各样的颜色的,HSL即是代表色相,饱和度,明度三个通道的颜色。HSL的H(hue)分量,代表的是人眼所能感知的颜色范围,这些颜色分布在一个平面的色相环上,取值范围是0°到360°的圆心角,每个角度可以代表一种颜色。色相值的意义在于,我们可以在不改变光感的情况下,通过旋转色相环来改变颜色。在实际应用中,我们需要记住色相环上的六大主色,用作基本参照:360°/0°红、60°黄、120°绿、180°青、240°蓝、300°洋红,它们在色相环上按照60°圆心角的间隔排列。
总得来说各种LAB, sRGB,adobeRGB,NTSC是一系列色彩标准,他们的区别是支持的颜色范围不同,硬件软件的支持不同,所以应用的需求和场景也不同。
【2】GammaColorSpace and LinearColorSpace
为什么会有gamma空间和linear空间呢,因为发光二极管的发光和电压不是线性的。而数学计算是需要线性的,所以如果我们想对一个像素进行计算,那么就需要把颜色数据转换为线性的才能着手计算。要让人眼看到正确的颜色效果,需要把颜色数据转换到Gamma空间中。
所有的现代 GPU 都支持 sRGB 贴图格式。这类格式的图片虽然的像素还是经过 Gamma 校正的,但是文件里还保存了校正的 Gamma 值。作为贴图传给 GPU 时,GPU 的硬件会预先取出这个 Gamma 值,将贴图还原到线性空间中,再传给 Shader 做处理。在 NVIDIA Geforce 8 系列之后的显卡,贴图反锯齿操作中使用的采样,都会保证是在线性空间中进行采样的。这个校正是一个 IEC 标准(IEC 61966-2-1),专门这对 Gamma 值为 2.2做的校正。对于大多数 gamma 值不确切的显示器,取这个值是一个较为保险的值。Alpha 值不参与校正。
所有 8-bit 格式的贴图都可以支持 sRGB,无论是 OpenGL 还是 DirectX 。这些格式包括包括 RGB、RGBA、luminance、luminance alpha 和 DXT compressed。
Gamma转换到线性空间:
float3 LinearColor = pow(tex2D( Texture, uv), 2.2).rgb;
Linear转换到Gamma空间:
float3 GammaColor = pow(LinearColor.rgb, 1.0 / 2.2);
可以确认的是,Unreal引擎中从Material材质接口输入到Shader底层计算的值全部都是线性空间的。
![v2-cb9002c5155fd277fc0a4ccdcd03b7ae_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/cc0223004b20135ddd1797a3328a183e.jpeg)
等shading全部计算完以后会转换成gamma空间输出到屏幕上。那么问题来了,我们的贴图里有各种颜色值,有Gamma有Linear的,这怎么才能保证输入到材质接口的值全部是Linear的呢。
![v2-8c1ee4b991e5e563e41be1ab25c11965_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/1b71a75b63ee4cd375f80891d007b36e.jpeg)
![v2-e5a633a5289b2032d25a3a808498d778_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/c226aa9aab1f1e32443ef29150391579.jpeg)
对于引擎材质编辑器内的颜色全部都是线性的,拾色板允许使用gamma空间的预览,但是最终的值还是Linear的。
对于贴图来说需要选择正确的采样模式
![v2-a729cda69bca8debc81aa7d6835e58e3_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/bb61f095397ae718c5e11958872aa05c.jpeg)
先暂时不要去管贴图里的任何设置,只看这个地方,如果是LinearColor的SamplerType采出来的就是线性空间的值,如果是Color模式采出来的就是Gamma空间的。如果我们导入的图如颜色贴图,一开始就是Gamma的,只需要勾上sRGB引擎会帮忙处理,如果能硬件转换到Linear空间就会让硬件帮忙转如果不能就引擎软件转。其次3D软件输出的Normal,Rouphness,Metallic,Depth等贴图全部本来就是是线性的,所以在材质中使用的它们的时候确保Sampler是LinearColor或Normal或与之对应的正确Mode即可。
在线性空间计算完以后就会再把LinearColor转换到Gamma空间。
![v2-edb89262b9dd50985e4294d9edc2d5cf_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/6229bedd2237481f54843e89b1ac02a7.jpeg)
【3】HSV色彩模式,HSB色彩模式
HSB又称HSV,表示一种颜色模式:在HSB模式中,H(hues)表示色相,S(saturation)表示饱和度,B(brightness)表示亮度HSB模式对应的媒介是人眼。
色相(H,hue):在0~360°的标准色轮上,色相是按位置度量的。在通常的使用中,色相是由颜色名称标识的,比如红、绿或橙色。黑色和白色无色相。
饱和度(S,saturation):表示色彩的纯度,为0时为灰色。白、黑和其他灰色色彩都没有饱和度的。在最大饱和度时,每一色相具有最纯的色光。取值范围0~100%。
亮度(B,brightness或V,value):是色彩的明亮度。为0时即为黑色。最大亮度是色彩最鲜明的状态。取值范围0~100%。
![v2-ff9eae128371099b3f44e1cf0825b8c5_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/436a34d124dcd9256f82b39a28e9e3df.jpeg)
而sRGB是限制在一个立方体内的
![v2-dbdea2ff6d2f25b55cfd70e80a42b6b8_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/d2a15862f86b10adf7b7599950997976.jpeg)
它们之间的转换公式如下:
half3 RGBToHSV(half3 c)
{
half4 K = half4(0.0, -1.0 / 3.0, 2.0 / 3.0, -1.0);
half4 p = lerp(half4(c.bg, K.wz), half4(c.gb, K.xy), step(c.b, c.g));
half4 q = lerp(half4(p.xyw, c.r), half4(c.r, p.yzx), step(p.x, c.r));
half d = q.x - min(q.w, q.y);
half e = 1.0e-10;
return half3(abs(q.z + (q.w - q.y) / (6.0 * d + e)), d / (q.x + e), q.x);
}
half3 HSVToRGB(half3 c)
{
c = half3(c.x, clamp(c.yz, 0.0, 1.0));
half4 K = half4(1.0, 2.0 / 3.0, 1.0 / 3.0, 3.0);
half3 p = abs(frac(c.xxx + K.xyz) * 6.0 - K.www);
return c.z * lerp(K.xxx, clamp(p - K.xxx, 0.0, 1.0), c.y);
}
引擎中的拾色板可以看到RGB和HSV这两种颜色模式
![v2-5010616e2fd4bdf79a4ecc0493b531f7_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/66676aca9a5fc622800c6d0216ac6f18.jpeg)
说了半天HSV和RGB的转换到底怎么用呢,下面给个例子:
![v2-0b427bf872ab728304752fae89174657_b.jpg](https://i-blog.csdnimg.cn/blog_migrate/8ab12b3fbd095b2b46b96c09b0c4cd73.jpeg)
效果如下:
![v2-37231610e2fef964ce69321b72d5384a.jpg](https://i-blog.csdnimg.cn/blog_migrate/bfa96f3c559da5447f996a346e598d13.jpeg)
这样就可以做HSV颜色空间的变色,变颜色饱和度,灰度等操作了。
SUMMARY AND OUTLOOK:
至此搞清楚了各种颜色标准,颜色空间,颜色模式后就再也不会犯错了。如果文中有错误或遗漏还请巨佬斧正。
enjoy it 。。。
NEXT:
todo...
Reference
【1】https://www.zhihu.com/question/20602284