目次
シェーダーの用意
まずはuGUI用のシェーダーを用意します。
UnityのビルトインシェーダーはUnityのダウンロードページから入手することが出来ます。
このシェーダーはUnityエディタのバージョンによって機能が追加されている事があるので、出来るだけ使用しているUnityエディタと一致するものを使用するのが良さそうです。
シェーダーをダウンロードしたら、解凍して中にあるUI-Default.shader (builtin_shaders-***\DefaultResourcesExtra\UI)をUnityのプロジェクトにインポート(ProjectビューへD&D)します。
これからuGUIのシェーダーをカスタマイズして色々してみます。
シェーダーのカスタマイズの準備
シェーダーをカスタマイズする前に、シェーダーの変更前に正常に動作する事の確認およびシェーダーを変更した際にどうなるか即確認できる環境を用意します。
まず改造したいシェーダーを複製します。今回の場合、UI-Default.shaderを改造するのでUI-Default.shaderが対象です。
今回は色反転(ネガ)を行うので複製したシェーダーの名前を「UI-Nega」に変更します。
ついでにシェーダーのコードを開き、"UI/Default"を"UI/Nega"に変更します。
あとはUI-Negaを設定したマテリアルを用意します。マテリアルを作成してシェーダーを設定すれば良いのですが、UI-Negaを右クリックしてCreate>Materialを選択すればシェーダーが適応されたマテリアルが作成されます。
最後にuGUIのImageを作成し、ImageのMaterialに先ほど作成したマテリアルを設定すれば準備完了です。
シェーダーの改造(色を変える)
まずはシェーダーを利用してスプライトの色を反転させます。
シェーダーは長々とありますが、とりあえず色を変更するだけなら見るべきはfragの中身、更に言えば下の図で言う所の96行目付近だけです。
まずfragの中身はピクセル(解像度)毎に何度も呼ばれる処理の認識でOKです。
で96行目ですが、テクスチャから色を取り出してUIに色を塗っています。
正確には「tex2D(_MainTex, IN.texcoord)」で_MainTex(uGUIのImageに指定したスプライト)、ピクセルの色(RGBA)を取得し、最後に戻り値として塗る色を返しています。これをピクセル毎に繰り返して全体の色を塗る訳です。GPU氏が。*1
なので、fragが戻す色を書き換えたり、色を取り出す場所を少し変えればuGUIで設定するUIにエフェクトを付与する事が出来る訳です。
例えば色を反転させてみます。
half4 color = (tex2D(_MainTex, IN.texcoord) + _TextureSampleAdd) * IN.color;
color.rgb = float3(1, 1, 1) - color.rgb;
ブラーを付けてみます。
ブラーは、ピクセルの上下左右から色を取って薄く塗る感じです。
half4 color = float4(0, 0, 0, 0);
color += tex2D(_MainTex, IN.texcoord) * 0.5f;
color += tex2D(_MainTex, IN.texcoord + float2( 0.008, 0.008)) * 0.125f;
color += tex2D(_MainTex, IN.texcoord + float2( 0.008, -0.008)) * 0.125f;
color += tex2D(_MainTex, IN.texcoord + float2(-0.008, -0.008)) * 0.125f;
color += tex2D(_MainTex, IN.texcoord + float2(-0.008, 0.008)) * 0.125f;
color *= IN.color;
無駄にピクセルアートっぽくします。
ピクセルがテクスチャから取り出す座標を「小さくして丸めて戻す」事で、より大雑把にします。
float _Range = 256;
half4 color = (tex2D(_MainTex, floor(IN.texcoord * _Range) / _Range) + _TextureSampleAdd) * IN.color;
これにブラー的な感じで解像度の異なる丸め方をしたところ、何となく味わい深い感じになりました。
ちなみにコードにエラーがある場合はピンクになります。またシェーダーやコンソールには何処にエラーがあるのか出るので、そこを治すと良さそうです。
パラメータをシェーダーの外から設定する
パラメータをシェーダー内で記述するだけだと、動作のバリエーションを作る際にシェーダーを量産する必要が出ます。それはメモリ的にもファイルサイズ的にもちょっとアレなので、パラメータを外だししてメタデータで設定出来るようにします。
今回はピクセルアートっぽい奴を何とかしてみます。
まずは_Rangeをfrag()の変数ではなくシェーダーの変数に変更します。
新しく記述する場所は「CGPROGRAM」から「ENDCG」の間です。
次に変数と同じ名前のプロパティを露出させます。
プロパティはシェーダー上の方に書いてあるPropertyスコープの中に書きます。
表記のフォーマットは「変数名(ラベル, 型) = 初期値」といった感じです。この変数名が一致してれば、シェーダー内の変数と紐づけられます。
今回は変数名は_Rangeなので一番左は_Range、次に表示名は”Range”で型が小数点なのでFloatとした…そんな感じです。
これでマテリアルを確認すると、Rangeの項目が追加されていますし、このマテリアルの内容を書き換えれば絵の荒さが動的に書き変わります。
あとはスクリプトからマテリアルの値を変更できるようにすれば、スクリプトからでもエフェクトを動かせたり出来ます。
using UnityEngine;
using System.Collections;
public class BlockRange : MonoBehaviour {
[SerializeField]
Material mat;
[Range(30, 256)]
public int range;
void Update()
{
mat.SetFloat ("_Range", range);
}
}
ちなみにuGUIやSpriteでは無ければCustomEditorを使ってマテリアルの表示内容をもっとスッキリさせたり出来ます。
その他
シェーダーは本格的にやろうと思ったら3Dに関するそれなりの知識が要求され、かつ色々な単語が飛び交い結構混乱します。
ただ正直な処、その辺り全部を知らなくとも最低限「ピクセルを動かして色々出来る」事を知っていれば結構色々な事が出来たりします。
例えばこんな感じの事とか。(マスクでアルファを減算してるだけ)*2
最初から全部覚えるより、まずは絵にエフェクトを付ける所から初めても良いかなーと。色変更ってのは分かりやすいですし、即反映されるのは楽しい(重要)。
ちなみに上はImageにしか適応できませんが、もう少し頑張るとこんな感じのエフェクトも出来ちゃったりします。
UnityでuGUIのトランジション。パターンはマスク画像(白黒画像)を使用。トランジションするUIの下にあるUIも一緒に消える pic.twitter.com/YmJPSmAowy
— 椿 (@tsubaki_t1) 2015, 10月 28