【Unity】シェーダでネガポジ反転・グレースケールを実現する
色を鮮やかにしたり、明るさを調整したり。。。 最近は写真をそのままの状態で用いることはほとんど無いですよね。
スマホアプリでなら簡単に行うことが出来ますが、Unityではどうすれば良いのでしょうか。
今回は色表現について軽く学んだ後、自分で簡単なシェーダを作る方法をご紹介します。
Contents
色のお勉強
先ずは、色を表現する3つの方法をご紹介します。
RGB
赤色(Red)、緑色(Green)、青色(Blue)の度合で、色を表現する方法です。透過度を表すアルファ・チャンネルと合わせて、RGBAとすることもあります。
Unityの画面上では、下のように表示されます。度合の最大値は、255もしくは1.0を選択できます。
シェーダのコード上では、基本的に色はこのRGBAで表されます。つまり、4つの値(R、G、B、A)を1組にした変数として扱われます。
1 2 3 4 5 6 |
fixed4 color = fixed4(123, 45, 67, 89); // RGBA fixed red = color.r; // 赤色 fixed green = color.g; // 緑色 fixed blue = color.b; // 青色 fixed alpha = color.a; // アルファチャンネル |
HSV
色相(Hue;色味)、彩度(Saturation;鮮やかさ)、明度(Value;明るさ)で、色を表現する方法です。
色を混ぜ合わせるRGBより、直感的に色を設定することが出来ます。
Unityの画面上では、下のように表示されます。
コード上では、基本となるRGBAから変換して扱う必要があります。
YCbCr
輝度(Y;明るさ)、2つの色差(Cb、Cr;青色、赤色と違う度合)で、色を表現する方法です。
輝度を別個に扱えるため、画像認識の過程で必ず用いられます。
コード上では、基本となるRGBAから変換して扱う必要があります。
おまけ:色空間
もう少し詳しく説明すると、これまで見てきた3種類の色表現は、「色空間」というモデルにまとめることが出来ます。
つまり、3次元空間中での位置を3つの値(X、Y、Z)で表すように、RGB空間では色を3つの値(R、G、B)で表すというわけです。
HSVやYCbCrは、このRGB空間を変換したモデルです。
この辺りの説明は、英語版Wikipediaが分かりやすくオススメです。
シェーダで実践!
それでは、上の知識を応用して、様々なシェーダを作ってみましょう。
シェーダの基本事項を押さえたい方は、以下の記事をご覧ください。
(関連記事:【Unity】Shader Graphの使い方を分かりやすく解説!シェーダーとは?)
今回は、次の頂点-フラグメント・シェーダを使います。コメントの部分(フラグメント・シェーダ)を改変していきましょう。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
Shader "Custom/ImageEffectShader"{ Properties{ _MainTex ("Texture", 2D) = "white" {} } SubShader{ Pass{ CGPROGRAM #pragma vertex vert #pragma fragment frag #include "UnityCG.cginc" struct appdata{ float4 vertex : POSITION; float2 uv : TEXCOORD0; }; struct v2f{ float2 uv : TEXCOORD0; float4 vertex : SV_POSITION; }; v2f vert (appdata v){ v2f o; o.vertex = UnityObjectToClipPos(v.vertex); o.uv = v.uv; return o; } sampler2D _MainTex; fixed4 frag (v2f i) : SV_Target{ fixed4 color = tex2D(_MainTex, i.uv); // ここを書いていきます! return color; } ENDCG } } Fallback "Diffuse" } |
ネガポジ
やりたいのは、「RGBの値を反対にする」こと。
-1掛けるだけだと定義域から外れてしまうので、+1しましょう。
1 |
color.rgb = 1 - color.rgb; |
グレースケール
やりたいのは、「色味を無視し、明るさだけで表現する」こと。
よって、上で説明したYCbCrを用います。
1 2 |
float gray = dot(color.rgb, fixed3(0.299, 0.587, 0.114)); color = fixed4(gray, gray, gray, 1); |
※ガンマはテクスチャとして出力される際に自動的にかかるので、シェーダ中でガンマを考慮する必要はありません。
白黒
やりたいのは、「輝度に閾値を設け、そこを境に白/黒とする」こと。
よって、先ほどの続きにif文を書きます。
1 2 3 4 5 6 7 |
float gray = dot(color.rgb, fixed3(0.299, 0.587, 0.114)); if(gray<0.5){ color = fixed4(0, 0, 0, 1); } else{ color = fixed4(1, 1, 1, 1); } |
まとめ
以上、シェーダで色を調整する方法のご紹介でした。
もっと長いコードを書けば、彩度を上げたり、セピアにしたりすることも可能です。
また、今回作成したシェーダは、カメラに適用することも出来るので、ぜひ色々いじってみて下さい!
それでは、楽しいXR開発を!
この記事はいかがでしたか?
もし「参考になった」「面白かった」という場合は、応援シェアお願いします!