天天看点

颜色 /About Color --图形学的B面(二)

                                                                                                                                                                                        --图形学的B面(二)

本文谈论“颜色”,是图形学的B面系列文章第二篇,这首先是一篇技术文章,和艺术无关,要深入探讨颜色背后的问题,颜色不是RGB,不是一个数字。本文要解决下面几个问题。

What is a Color?

What Causes a Color?

How to Measure a Color?

  • What Is a Color?

颜色是在特定观察条件下进入视网膜中的一束光线经过视网膜的反应产生的人类感受。颜色是对光的感受。一束光是由各种不同强度不同波长的光波组成的(或者叫做光谱spectrum)。所以颜色是视网膜对光谱的感受。无法客观度量视网膜的主观感受,所以我们度量光波的组成。更直接的说,颜色是光谱组成。一个光谱,一个颜色。

每种单波长的光都也都会对应一个颜色,人可以感知的光波的范围在350-750nm之间,下面是一个单波长光的颜色对应。

颜色 /About Color --图形学的B面(二)

当然大部分光是由这些基础单波长光复合组成的。

  • 光谱

颜色的背后是光谱。我们来探讨光谱的意义。

  • 光谱能量分布

下面图是一个光谱的表示,光谱即Spectrum Power Distribution,它描述一束光中每个波长的光所辐射的能量(Intensity,每秒每个立体角的能量通过),这个曲线的积分就是这束光的强度。(有时会以560nm光的强度归为1来绘制这个图,这样只要知道这光的总强度,也能知道每个光波的强度)。

颜色 /About Color --图形学的B面(二)

                          光谱能量分布SPD(w)

  • 光波能量

我们知道光波的能量更波长呈反比,即下面图的曲线样子

颜色 /About Color --图形学的B面(二)

                       光波能量随波长的变化 (Energy(w))

因此我们可以从SPD(w)和Energy(w)算出这束光中没个波长的光波的数量SPD(W)/Energy(w)

  • 材质

光存在光谱,但是经过物质的反射,其中一些光谱被吸收多,一些反射的多,因此我们看到的物质反射后的光(即物质的外观)又和原始的光源不一样,这里通常也会存在一个物质对光谱的反射曲线,如下图,他叫做表面光谱反射曲线srf,他表示了不同光谱的光在物体表面被反射的情况,它决定了物质的外观或颜色。

颜色 /About Color --图形学的B面(二)
  • 光度(Photometry)

然而SPD并不能反应出人眼的感知强度,也就是说光能越强,不一定人眼看上去越强,因为颜色是人的感知的结果。这里面存在一个简单的对应关系,下图是CIE(国际照明组织)的光度曲线,反应不同波长的光的感知强度。

颜色 /About Color --图形学的B面(二)

                                       Photometry(w)

我们可以看到能量最强的蓝光感知起来其实很弱,能量中间的绿光对人眼感受器的效果最强。这也是为什么绿色的彩色照片转换成黑白后要比蓝紫更白一些。我们把SPD(W)*SRF(w)/Energy(w)

同Photometry(w)相乘的积分可以拿到人对这束光的感知强度Intensity,这个Intensity是个标量(即黑白)的强度。记住光能强不代表看上去强。

  • 色度(Colorimetry)

色度是人眼除了光度之外对颜色的另一种概念,即除了强弱,还有外观的区别,即赤橙黄绿青蓝紫。如何度量色度,这是要讨论的重点问题。

  • 度量颜色

怎样度量一个颜色?学过图形学的人会说是用RGB么?

理论上给出一个光的光谱组成,就可以确定它的颜色。所以度量一个色度的真正方式应该是用它的光谱。

然而这极其不便,尤其用于图形学计算时极其复杂,光谱是多种光复合而来的,组元众多。计算效率表达起来都有问题。怎么办?我们先理解下异谱同色的概念。

颜色 /About Color --图形学的B面(二)

上面是两个完全不同的光谱,然而他们给视网膜造成的反应是一致的,即你看到了同样的颜色,这种情况很多。所以人眼很可怜,你能看到两个相同颜色的光,但是你可能看不到他们是完全不同的光波,即人天生是只能看到表象的动物,这物理现象叫异谱同色。但是

表达颜色的方法就有了转机,即我们为了表达光谱A这个颜色,通过构造另外一个光谱B,使得B只有少数的N(n1,n2,n3)个单波长的光组成,这样我们通过表达n1,n2,n3的强度值(或百分比)就能表达这个颜色了。而且表达除A外的其他任意光谱,都要用这一组波长的N(n1,n2,n3)来模拟。n1,n2,n3的强度值就是我们对光谱降到N维后对颜色的表示。例如下面左边这个组元众多的光谱和右边这个只有少数光波有值的颜色一致。我们就用后者的几个光的比例表达这个颜色。

颜色 /About Color --图形学的B面(二)
颜色 /About Color --图形学的B面(二)

N(n1,n2,n3)可以随便挑选几个单波长的光么?可以,但是问题是误差会很大,如果你不精心挑选,会发现无论怎样都无法用N(n1,n2,n3)来模拟一个可见光谱。于是人们精心靠“人肉”尝试挑选了3个单光谱光,分别是444nm  526nm 和645nm,他们的光谱的颜色对应于人类所称为的蓝色附近,绿色附近和红色附近。如果用这三种单波长光表达所有单波长的可见光,图表会变成下面这样

颜色 /About Color --图形学的B面(二)

单波长可见光的RGB波长(异谱同色)的表示 RGB(W)

这里看到为何人肉挑出来的是这三个光,它们组合的特点是恰好在其中一个波长光取极大值时另外两个光近似为0,这很符合正交基的特性,适合作为一个度量坐标系。

那么如何计算一个光谱的rgb颜色,用前面的SPD(W) *SRF(w)/Energy(w)同RGB(W)的三个元素为别相乘求积分即可获得。

但是即使看上去这么完美的RGB也不能很好的表达所有的可见光。比如430-510nm左右的一些蓝光的r为负值,即这些光不能被rgb的体系表达。所以颜色不是RGB,rgb是一种对光谱降维到3个主元后对颜色的近似表达。RGB是对颜色的降维表达,光谱才是颜色。

  • 标准照明体和色温

除了rgb这种单波长光谱的组合表达之外,还有一种用色温表示光谱颜色的方式。人们首先通过定义一些预先定义的标准化光谱来定义一些标准化颜色。这些标准化光谱假设这些光是从一个标准的不吸收光源的黑体发射出来的(black body)。这些黑体也称为标准照明体,大多数标准照明体是自然或人工的常见光源,如:白炽灯源,中午太阳等等。

因为根据普朗克的黑体辐射定律,黑体的辐射和它的温度存在对应关系,所以又一般可以一个温度来描述一个标准照明体的颜色,这就是色温的来源,每个光谱都有一个色温,但值得注意的是,色温是对光谱能量的度量,而非感知能量的度量,不同的光谱,色温可能是相同的,色温的度量角度是光谱本身的辐射能,而不是从感知角度出发的,所以色温的大小和感知的强度大小没有关系,色温和标准照明体通常是为了定义一个光源基线。

色温一般随光的辐射能量的增长而增长,色温能量越高,颜色也趋于蓝色,否则趋于红色。

颜色 /About Color --图形学的B面(二)

简单说,人们预先定义了一些标准化的光谱来表示一些重要的复杂光源产生的颜色,并且可以用色温来更简单的对应这些标准化光谱。如

CIE的A系列表示白炽灯,2856k

CIE的C系列表示北半球的白天光6774k

CIE的D65表示北半球的中午天光 6504k

下图表示两种荧光灯的标准照明体的光谱。

  • 全色域

Rgb不能表达所有的可见光颜色。怎么办?人类发现不可能找到有限的几种单波长的光的叠加来表达所有颜色,于是提出了一组(3种)虚假的波长的光,称为X Y Z,所有单波长可见光在XYZ叠加模拟下的曲线是如下图的

颜色 /About Color --图形学的B面(二)

                            XYZ(W)

这里面XYZ这三种单波长光是不存在的,它纯粹为了让人类能够书面表达所有可见光(因为这里没有负值)。XYZ是怎么算出来的?用前面的SPD(W) *SRF(w)/Energy(w)

同上面的xyz色度曲线XYZ(W)相乘积分即可以得到。

XYZ其实是对RGB的简单线性变换,而且有个特点,上图的xyz曲线的覆盖区域是相同的,并且Y恰好等于前面说的光度(即亮度)。XYZ是理论上表达所有可见光的颜色模型。

  • Spectrum Lotus光谱迹

当把所有单波长的可见光的在xyz空间坐标系下的坐标点连成线,会变成下图,这被称为可见光的单光谱迹。

颜色 /About Color --图形学的B面(二)

单波长可见光的xyz坐标系下的表示

随着光强的增强,它会长成一个缺口的圆锥性(Cone),这里为什么会有一个“缺口”,那是因为在380的蓝光和780的红光不是首尾相接的。即没有任何单波长的可见光的xyz处于缺口处。(那么缺口处是否有可见颜色呢?有,但那不是单波长光,是多种波长复合出来的,这些颜色叫做超谱色extra-spectrum color,典型的如紫色,紫色区段是少数不能靠单一一种波长的光表现出来的颜色,而这个缺口处的直线也被称为purple line,即紫线)

所有单波长可见光围成的cone。

颜色 /About Color --图形学的B面(二)
  • 没有光度的色度

人们为了单纯的讨论颜色的色度,会把颜色中的光度变量解耦出去,单纯的讨论没有亮度概念的色度,就会把这个所有可见色的xyz同x+y+Z=1的平面相截取(这个平面可看做覆盖了所有色度),然后因为xyz三者相加定值,所以可以删去其中一个变量,即将被截的xyz再投影到xy平面,上面这个Cone就会变成下面这个拍扁了的马蹄形。

颜色 /About Color --图形学的B面(二)

从xyz投影全色域图

颜色 /About Color --图形学的B面(二)

                                                   全色域图

         这个马蹄形的只有xy两个维度的图就很容易看了,它的边界是表示了所有的单波长可见光,依次从左下角的380nm顺时针到右上角的780nm。然后其余的颜色都是靠多种波长的光复合出来的,右下角的那条是我们前面提到的紫线,紫色就在紫线的右下部分。(注意千万不要以为所有可见颜色都在这个马蹄形内,大量的紫色就不在,它只是单波长光的颜色的合围)

  • 色域

虽然人类的所有可见光不只在这个马蹄形内,但是很遗憾人类现有物理设备能够表示的颜色却确实都在这个马蹄形围成的范围内,或者只是其中的部分子集。例如广泛使用的sRGB表示的颜色范围是里的一个三角形,用于印刷行业的AdobeRGB则色域更广一些

颜色 /About Color --图形学的B面(二)

从这里看来虽然马蹄形只是可见光的一部分,但是rgb空间能表达的颜色(RGB色域)在整个人类可见颜色的(全色域)中又只占更小的一部分,世间的大部分颜色(那些各种饱和度的绿,还有那大量的多种多样的紫)都不能被你的物理设备展现。很遗憾吧。

那么我们为什么不能使用一种基于xyz的物理设备,不就能表达所有的颜色了么,因为前面说了xyz是不真实存在的单波长光,没有设备能够发出x,y,z的单波长光并将它们复合,xyz只能用来做理论的度量。

这里可以再讨论下上面这个问题,为何人类现有物理设备能够表示的颜色都在这个马蹄形里,只能无限逼近它。原因就在于物理设备的颜色表现方式都是基于color additive的,即将N种单色光波叠加来通过异谱同色的原理模拟任意颜色,即还是像前面说的你用N个主要维度的光叠加是不能完全获得所有的光谱的。除了用完整光谱(即完整的所有维度的波长的光)模拟颜色不可能表达所有可见光。这是一个低维不能完整模拟高维的问题。所以理论上,用更多种单波长颜色的光叠加,就能获得更多的颜色,例如一些高级的显示器用了4色光叠加。而大多数设备基于硬件的制约还只能支持发射rgb三种原色。

那么设备如何模拟支持色域之外的颜色,一般只能通过降低饱和度等方式使其强行变成色域内的一个颜色,这叫做gamut mapping。

  • 光谱渲染

当游戏的图形渲染进入了PBR的时候,似乎很多人发现原来我们找到了更贴近物理的表达光线,颜色的方式。但是PBR只解决了光线传递的物理模拟,当pbr还在使用基于rgb这种低微的颜色的量化方式的时候,就还不能说是真正的物理,真正的物理要基于光谱的量化,基于光谱的辐射强度表达,基于光谱的材质,基于光谱的反射,吸收,折射,因此有些领域已经进入了光谱渲染,虽然做不到模拟全光谱的量化,但是选取更主要的4道,6道,8道波长的光也会提高真实度,或者说现有基于rgb的光照计算体系是使用了3道主元波长的光谱渲染。看几个光谱渲染的对比。下面的茶壶在rgb的渲染下甚至得到的颜色都是完全错误的。

颜色 /About Color --图形学的B面(二)
颜色 /About Color --图形学的B面(二)
  • 色度和色度感知

正如本文正文的第一句话,研究颜色有一个大的前提是在特定的观察条件下,只有当观察环境,光照固定的情况下,用色度去预测人的颜色感受才是合理的。因为人对颜色的感受还受颜色周围的环境对比,人眼的自适应性,颜色的同化作用等影响,如下图,你感受到的是一种颜色么

颜色 /About Color --图形学的B面(二)

然而在游戏渲染业界,人们也开发了各种方式来模拟这些因素对颜色的影响。图形渲染领域说到底都是在为颜色而打工,你的一切工作只是为了计算一个降了维的颜色值。因为渲染领域的一个终极目标就是,使物理设备对你视网膜的刺激和真实物体对你视网膜的刺激是一样的。

本文内容参考了大量siggraph2018 course的相关内容。作为知识记录和分享整理与此。

继续阅读