角色染色方案
角色染色方案
常见的染色方案
- 直接的颜色替换
- 基于查表的颜色替换
- 基于颜色叠加的染色方式
- 基于HSV/HSL的染色方式
- 基于通道混合算法的染色
直接的颜色替换
在一些很老的游戏中,可能有这样进行染色的方式,但这种方式仅仅适用于那些整个画面效果都是完整大色块的游戏。而现实项目中,我们的贴图中一块区域即便是一种色调,也会有细节的差异,单纯的颜色替换就把原来的细节抹掉了。比如常见的会在衣物的贴图上绘制褶皱,这些褶皱很难用mask来标注,因为是用渐变的方式来制作,直接的颜色替换就把褶皱抹平了。
DyeColor = TargetColor
基于查表的颜色替换
简单暴力的颜色替换不够好用,那么就会有相应的改进方案产生,查表就是其中一种思路。Color Lookup Table是一种非常常用的变色手段,它使用表格的方式提供了从一种颜色映射到另外一种颜色的定义方式。在一些2D游戏中,这也是一种对于角色和特效实施变色的方法:
DyeColor = LookupTable(BaseColor.r, BaseColor.g, BaseColor.b)
优点:
- 可定制性强,在颜色的RGB空间中可以定义任意(当然由于要存成图,所以未必是连续的)颜色之间的映射关系,可以做到非常细致。
- 对于分区有原生的支持。在一个角色不同染色分区没有颜色相似的前提下,对于一个角色使用一张Color Lookup Table图就可以处理很多分区的染色需求。
- 性能影响相对较小,只有rgb转换到uv空间的计算过程和一次贴图采样的消耗。
缺点:
- 每种染色都要新制作一张Color Lookup Table,有较多的资源消耗,当然理论上不同角色之间相似的染色可以尝试复用Color Lookup Table,但是效果可能不够理想。
- Color Lookup Table的尺寸和染色精细度需要权衡和取舍,两者不好兼得。
- 几乎没有玩家自己定制的可能性。这种方式需要提前定制好Color Lookup Table,因此基本上只能提供给玩家定制好的染色效果。
基于颜色叠加的染色方式
颜色叠加的方式有多种,比如直接的相加,而更为常用的是乘法。在特效制作中就大量使用了这种变色方式。
DyeColor = BaseColor * TintColor
优点:简单、高效。只需要一个乘法的代价,就可以实现基本的染色效果。
缺点:由于采用的是乘法,因此颜色亮度上肯定是小于等于原始颜色的亮度的,对于同一个区域内原始颜色变化较大的情况无法调整出好的效果。
改进:
- 颜色值使用hdr,允许超过1的值,这样来解决颜色只能变暗的问题。
- 制作中,原始贴图的颜色采用灰度的方式,只保留明暗对比,所有的颜色都通过染色来做,这样可以剥离之前原始贴图颜色对于最终染色效果的影响。
基于HSV/HSL的染色方式
这几乎是目前最为主流的染色方法了,HSV分别是色相(Hue),饱和度(Saturation),明度(Value)。
就像引用中对于HSV色彩空间的描述一样,色相表示了颜色,饱和度表示了颜色的深浅,明度表现了颜色的明暗,这些概念对于人眼来说有更加直接的对应关系。比如玩家想要改变颜色,那就直接拖动色相的条就可以直观地看到颜色的变化。计算过程大致可以描述如下:
DyeColor = HSV2RGB (RGB2HSV(BaseColor) + HSVOffset)
- 染色过程无论对于美术还是玩家,都较为友好,容易理解。
- 在大部分情况下,可以染色的范围很广,几乎覆盖所有颜色区间。
- 将最常用的颜色调整和亮度、饱和度分离,实现调整颜色的时候保持亮度和饱和度变化不大,这对于染色的稳定性比较友好。
- 可以做到同一块染色区域内进行染色,保留褶皱这样的细节。
缺点:
- 计算量相对较大,需要RGB和HSV之间的互相转换,转换过程虽然可以优化,但是如果在GPU上做计算还是有一些消耗的。
- 如果原始颜色是黑色或者白色,则单纯色相的调整无法改变颜色,需要借助饱和度和明度来进行调整,虽然有些麻烦,但是依然可以得到任何颜色。
- 某些情况下,HSV的调整会让冷暖关系发生变化。
针对RGB和HSV之间多次转换导致的计算量大的问题,有一种优化是绕过吧RGB转换到HS颜色V空间的步骤,而是利用了一种叫YIQ的颜色空间:快速计算hsv染色的方法
基于通道混合算法的染色
简单来说,在我的理解里,通道混合算法基于RGB的颜色叠加的方式进行调整,通过原始颜色的通道作为选区和调整基准值。
直接来看通道混合算法的计算过程:
这里写得比较复杂,但只是把向量计算拆开了而已。选取r通道的计算过程来进行一下说明。首先输入参数Params拆分成了ParamsR、ParamsG、ParamsB三个向量,分别描述对应结果的RGB三个通道的调整参数,他们的取值范围是[-2.0, 2.0],在Photoshop里体现为一个百分比。具体来说:
- ParamsR.r的值表示对于原本红色通道上添加或者减少红色的比例,默认值是100;
- ParamsR.g则是对于原本绿色通道上添加或者减少红色的比例,默认值是0;
- ParamsR.b则是对于原本蓝色通道上添加或者减少红色的比例,默认值是0;
- ParamsR.const是对于红色调整的一个常量值,通常用于处理原本颜色是黑色或者接近黑色的情况。
以此类推ParamsG和ParamsB向量的含义,这样通过12个参数就可以将任意颜色按照不同通道的颜色选区进行调整,从而得到任意的其他颜色值。
优点:
- 可以染色的范围广泛,在添加了const值之后,理论上没有什么颜色是无法染到的。
- 解决了HSV染色之后中明暗/冷暖关系改变的问题。
- 基于矩阵做运算的话,效率比HSV要高一些。
缺点:
- 染色过程不够直观,有不少美术一开始没办法理解这个计算过程,需要一定的讲解和上手过程;
- 参数比较多,运行的时候如果在Shader中做计算的话,需要传递给Shader的参数会比较多;
- 由于染色效果不直观、参数也比较多,无法直接开放给玩家来进行自定义的染色。
染色区域定义
在染色系统中,通常不会针对于一整张贴图应用同一个参数的染色,而是要将贴图区分为多个区域,比如皮肤、头发、上衣等等,进行分别的染色,每个区域的染色参数会有所不同。
有很多方式来标定一些区域,比如颜色范围、如多边形、Photoshop里的魔棒选区等等,但是在游戏中最为常用的还是一张Mask贴图。