色彩空间与带区间的色相调整

在游戏的战斗中,两军对垒,需要让玩家区分敌我,颜色是一个很重要的标识。

Blue Cavalry Red Cavalry

上图是一个蓝方骑士和一个红方骑士,可以看出他们除了标识颜色不一样外,其余完全一样。假使在游戏内的士兵用序列帧动画来实现,如果两个阵营用两套序列帧来实现的话。首先美术工序变得复杂,其次会导致游戏内存消耗增大,最后还会使包体积变大。

真实的情况是图片只有蓝方骑士,红色骑士只不过在运行时通过色相转换(Hue Shift)得到的。

在了解如何进行色相转换之前,我们有必要了解什么是色彩空间。

色彩空间

色彩空间是描述使用一组值表示颜色方法的抽象数学模型,比如绝大多数人都知道的三原色模型就是一种色彩空间。

RGB

RGB色彩空间指的是用红(Red)绿(Green)蓝(Blue)这三种原色描述任意颜色的色彩空间。

RGB Model

为什么采用红绿蓝作为三原色?是因为人的眼睛的锥形感光细胞对红绿蓝的光线比较敏感。

通常在计算机内部用8个bit来分别描述红绿蓝的强度,即数字从0到255,0表示此颜色强度最低(完全没有),而255则表示此颜色的强度最强。

RGB采用简单的加法来描述所有颜色,比如黄色为(255, 255, 0),黑色为(0, 0, 0),白色为(255, 255, 255)。

HSV

HSV是RGB的一种变形,分别用色相(Hue)饱和度(Saturation)明度(Value)三个数值来描述颜色。

HSV相较于RGB用人类更为熟悉的方式封装了关于颜色的信息:

这是什么颜色?深浅如何?明暗如何?

  • 色相指的是色彩的基本属性,回答了所问的第一个问题:这是什么颜色?通常色相表达为一个环,称为色环,对应角度为0到360度。
  • 饱和度指的是色彩的纯度,越高则表示色彩越纯,越低则逐渐变灰,回答了所问的第二个问题:深浅如何?数值为百分比,即0到1。
  • 明度指的是颜色的亮暗程度,越高则越显得发白,越低则越显得发黑,回答了所问的第三个问题:明暗如何?数值为百分比,即0到1。

HSV可以用一个圆锥来表示,有助于建立直观的理解。

HSV Model

HSV和RGB间的转换有一套比较复杂的公式,这不在本文的讨论范围内。

其它

除了RGB和HSV外,还有很多其他的色彩空间,比较知名的有与HSV相似的HSL,印刷常用的CMYK和电视常用的YUV

色相调整

在了解完色彩空间后,现在回到最开始的问题,如何在运行时将蓝方士兵渲染成红方士兵呢?

答案很简单,对蓝方士兵进行指定范围内(蓝色)的色相调整,即对色相落入一定范围内的像素的色相进行调整。

shader

关于色相调整的shader网络上有很多开源实现,譬如hsva-unity是可以直接在Unity内使用的shader

它的核心代码很简单:

其中_HSVRangeMin定义了可以被调整的色相下限,_HSVRangeMax则定义了上限。

step(edge, x)函数在x小于edge时返回0,否则返回1。

这段代码表示HSV的第一个分量(即色相)在区间[_HSVRangeMin, _HSVRangeMax]内时返回1,否则返回0,即指定了可以进行调整的色相范围。

Hue Bar

根据色相条,可以知道蓝色的色相范围大概在180到260间,如果按0-1表示,则在0.5到0.7间。

所以我们把_HSVRangeMin设置为0.5,把_HSVRangeMax设置为0.7,然后进行色相调整,可以变换出无数种颜色来。

Hue Shift in Unity

玩具Demo放在了Github,玩的开心 😎

你可能感兴趣的文章

One response

  1. 感谢分享!已推荐到《开发者头条》:https://toutiao.io/posts/bmacc3 欢迎点赞支持!
    欢迎订阅《游戏开发杂谈》https://toutiao.io/subjects/23583

发表评论

电子邮件地址不会被公开。 必填项已用*标注