うにてぃブログ

主にUnityとC#に関する記事を書いていきます

【Unity】画像の HSV 変換シェーダー

シェーダーを用いて色の加算・乗算は容易にできるがHSV変換をする場合変換用のメソッドを容易してやる必要があるため
こちらにシェーダをメモ

HSVのカラーシフトの式はこちらを参考にしました

HSV Shader with Alpha - Unity Answers

シェーダー

Shader "Custom/Unlit/hsv" 
{
    Properties 
    {
        [NoScaleOffset] _MainTex ("Base (RGB)", 2D) = "white" {}
        _Hue ("Hue", Range(0.0, 360)) = 0
        _Sat ("Saturation", Range(0, 1)) = 1
        _Val ("Value", Range(0, 1.0)) = 1
    }
    SubShader 
    {
        Tags { "RenderType"="Opaque" }
 
        Pass
        {
            CGPROGRAM
 
            #include "UnityCG.cginc"
            #pragma vertex vert
            #pragma fragment frag
             
            sampler2D _MainTex;
            half _Hue, _Sat, _Val;
             
            struct appdata
            {
                half4 vertex : POSITION;
                fixed2 uv : TEXCOORD0;
            };
 
            struct v2f
            {
                half4 pos : SV_POSITION;
                fixed2 uv : TEXCOORD0;
            };
                         
            fixed4 shift(fixed4 color, fixed3 shift)
            {
                half VSU = shift.z * shift.y * cos(shift.x * .017453292);
                half VSW = shift.z * shift.y * sin(shift.x * .017453292);
                    
                return fixed4(
                    (0.299 * shift.z + 0.701 * VSU + 0.168 * VSW) * color.r + (0.587 * shift.z - 0.587 * VSU + 0.330 * VSW) * color.g + (0.114 * shift.z - 0.114 * VSU - 0.497 * VSW) * color.b,
                    (0.299 * shift.z - 0.299 * VSU - 0.328 * VSW) * color.r + (0.587 * shift.z + 0.413 * VSU + 0.035 * VSW) * color.g + (0.114 * shift.z - 0.114 * VSU + 0.292 * VSW) * color.b,
                    (0.299 * shift.z - 0.300 * VSU + 1.25 * VSW)  * color.r + (0.587 * shift.z - 0.588 * VSU - 1.05 * VSW)  * color.g + (0.114 * shift.z + 0.886 * VSU - .203 * VSW) * color.b,
                    color.a
                );
            }
 
            v2f vert(appdata v)
            {
                v2f o;
                o.pos = UnityObjectToClipPos(v.vertex);
                o.uv = v.uv;
                return o;
            }
 
            half4 frag(v2f i) : SV_Target
            {
                return fixed4(shift(tex2D(_MainTex, i.uv), fixed3(_Hue, _Sat, _Val)));
            }
 
            ENDCG
        }
    }
}

shiftの計算量が多いので、もしHSVの値が固定なら計算してしまって色を変換してしまった方がいいです。

変換してみた

こちらの画像を変換してみる
www.irasutoya.com

HSVを変えると色味が変わることが確認できた
f:id:hacchi_man:20200115133131p:plain