Unity中颜色空间(Color)HSV,HSB,HSL

发表于2018-06-11
评论0 2.1k浏览
对于程序猿来说,也是需要了解一些美术相关的知识,可以不用了解很多了,一点点就足够了,最常见的例如HSV、HSB、HSL这些定义就OK了。

一、概念

HSL 模式和 HSV(HSB) 都是基于 RGB 的,是作为一个更方便友好的方法创建出来的。
  • HSB 为 色相,饱和度,明度,
  • HSL 为 色相,饱和度,亮度,
  • HSV 为色相,饱和度,明度。

HSB 和 HSV 是是一样的,只是叫法不同,HSL 则还有一些细微的区别:
  • 在所有的情况下,H(Hue) 代表色相,S(Saturation) 代表饱和度。Hue(色相)是指取值范围在0-360°的圆心角,每个角度可以代表一种颜色。B 在 HSB 模式中是 Brightness 的意思, V 在 HSV 中是值,但是所表述的是一个东西:对光的量或光源的功率的感知。色相和明度(值)可以在0- 1或者0% - 100%间取值。
  • HSL 稍微有一些不同,Hue(色相)和 HSB/HSV 模式中一样用数值表示,但是, S,同样代表“饱和度”,定义不一样,且需要转换。 L 代表亮度,和 Brightness/Value 不一样。Brightness(明度)是被认为是”光的量“,可以是任何颜色。而

Lightness(亮度)是作为”白的量“来理解的。Saturation(饱和度)不一样,因为在两个模型中,饱和度都按比例缩放以适应明度或亮度的定义。
两者的区别,和他们之间对于饱和度的定义的不同。其实相关的定义就是这么简单。

二、实例

我们关心的主要就是在我们平常开发游戏的时候,怎么样编写出一个shader能够让我们去调节HSB颜色空间,而不仅仅是RGB空间。其实它们之间的转换已经有前人研究出来的公式了,我们只要套用公式即可了,各种颜色空间转换的具体公式详情:
http://www.easyrgb.com/index.php?X=MATH&H=22#text22

下面给出HSB转为RGB的shader:

发现其实美术调整颜色的时候大部分都是调整的HSV,因为可以方便的分别调整色相(hue)、饱和度(saturation)和色调(value)。例如人们要将颜色调整的偏红一点,那么只需要修改色相, 如果使用RGB的话,就需要同时调整3个值,仅仅只是增加R值的话,理论上讲,只是把红色值加重了而已。就算是平时使用的调色板,大部分也是按照HSV来的,例如U3D的调色板:

注:颜色空间有很多中,RGB、HSL、HSV、CMYK……等等好多,如果有兴趣的话可以去搜搜。但我们这里只用HSV 。
比如一张贴图是红色系的,我们要改成绿色系,只需要将hue值偏移到绿色值就好了。

方法我们知道了,公式也有了,下面直接写代码。
Shader "Tornado/ColorGradation_HSV" {  
    Properties {  
        //贴图  
        _MainTex ("MainTex (RGB)", 2D) = "white" {}  
        //Hue的值范围为0-359. 其他两个为0-1 ,这里我们设置到3,因为乘以3后 都不一定能到超过.  
        _Hue ("Hue", Range(0,359)) = 0  
        _Saturation ("Saturation", Range(0,3.0)) = 1.0  
        _Value ("Value", Range(0,3.0)) = 1.0  
    }  
    SubShader {  
    Pass {  
        Tags { "RenderType"="Opaque" }  
        LOD 200  
        Lighting Off  
        CGPROGRAM  
        #pragma vertex vert_img  
        #pragma fragment frag  
        #include "UnityCG.cginc"  
        sampler2D _MainTex;  
        half _Hue;  
        half _Saturation;  
        half _Value;  
        struct Input {  
            float2 uv_MainTex;  
        };  
        //RGB to HSV  
        float3 RGBConvertToHSV(float3 rgb)  
        {  
            float R = rgb.x,G = rgb.y,B = rgb.z;  
            float3 hsv;  
            float max1=max(R,max(G,B));  
            float min1=min(R,min(G,B));  
            if (R == max1)   
            {  
                hsv.x = (G-B)/(max1-min1);  
            }  
            if (G == max1)   
            {  
                hsv.x = 2 + (B-R)/(max1-min1);  
                }  
            if (B == max1)   
            {  
                hsv.x = 4 + (R-G)/(max1-min1);  
                }  
            hsv.x = hsv.x * 60.0;     
            if (hsv.x < 0)   
                hsv.x = hsv.x + 360;  
            hsv.z=max1;  
            hsv.y=(max1-min1)/max1;  
            return hsv;  
        }  
        //HSV to RGB  
        float3 HSVConvertToRGB(float3 hsv)  
        {  
            float R,G,B;  
            //float3 rgb;  
            if( hsv.y == 0 )  
            {  
                R=G=B=hsv.z;  
            }  
            else  
            {  
                hsv.x = hsv.x/60.0;   
                int i = (int)hsv.x;  
                float f = hsv.x - (float)i;  
                float a = hsv.z * ( 1 - hsv.y );  
                float b = hsv.z * ( 1 - hsv.y * f );  
                float c = hsv.z * ( 1 - hsv.y * (1 - f ) );  
                switch(i)  
                {  
                    case 0: R = hsv.z; G = c; B = a;  
                        break;  
                    case 1: R = b; G = hsv.z; B = a;   
                        break;  
                    case 2: R = a; G = hsv.z; B = c;   
                        break;  
                    case 3: R = a; G = b; B = hsv.z;   
                        break;  
                    case 4: R = c; G = a; B = hsv.z;   
                        break;  
                    default: R = hsv.z; G = a; B = b;   
                        break;  
                }  
            }  
            return float3(R,G,B);  
        }         
        fixed4 frag (v2f_img i) : SV_Target  
        {  
            fixed4 original = tex2D(_MainTex, i.uv);    //获取贴图原始颜色  
            float3 colorHSV;      
            colorHSV.xyz = RGBConvertToHSV(original.xyz);   //转换为HSV  
            colorHSV.x += _Hue; //调整偏移Hue值  
            colorHSV.x = colorHSV.x%360;    //超过360的值从0开始  
            colorHSV.y *= _Saturation;  //调整饱和度  
            colorHSV.z *= _Value;                             
            original.xyz = HSVConvertToRGB(colorHSV.xyz);   //将调整后的HSV,转换为RGB颜色  
            return original;  
        }  
        ENDCG  
    }   
    }  
    FallBack "Diffuse"  
}  

同样的也可以应用到摄像机特效上….瞬间改变场景的氛围

如社区发表内容存在侵权行为,您可以点击这里查看侵权投诉指引

0个评论