前回に引き続きテクスチャを表示するシェーダを作成しましょう。前回はテクスチャを表示するだけの基本的なシェーダでした。
今回は、もう少し発展させてステンドグラスのような見た目のシェーダを作ってみましょう。実行結果は次の図ように、テクスチャの黒い部分は不透明ですが、カラーの部分は半透明になっています。
ステンドグラス用シェーダのアルゴリズム
今回作るシェーダは、ステンドグラスのような見た目になるように、テクスチャの色が黒色に近い場合は透明度を1にして、それ以外の場合は透明度を0.6ぐらいにして半透明にします。
テクスチャの色は前回紹介したように、tex2Dメソッドで取得できます。ただし、tex2Dメソッドで得られる色はRGBAのカラー情報なので、黒色に近いかどうかを判定するのは少々面倒です。そこで、よく使われる方法が画像のグレースケール化です。画像をグレースケールに変換することで、RGBAという4次元の値ではなく、明度という1次元の値で扱えるようになるので「明るい色か暗い色か」を判定するには非常に便利です。
画像処理ライブラリなどでは、グレースケール化のメソッドが用意されているのですが、Unityのシェーダにはグレースケール化のメソッドはありません。そこで自分でRGBの情報からグレースケールに変換する必要があります。この変換式は簡略化すると次のように書けます。覚えやすいですねー。
grayscale = 0.3 * R + 0.6 * G + 0.1 * B
もう少し正確な数式は次のサイトで紹介されています。
ここで得られたgrayscaleの値が黒色付近(0.2以下)であれば透明度を1に、grayscale > 0.2であれば透明度を0.7にすれば良さそうです。
ステンドグラスを作る
プロジェクトを作成して、ヒエラルキービューから「Create」→「3D Object」→「Panel」を選択して平面のパネルを追加します。パネルを回転してカメラから見やすくなるように調節して下さい。
次に、いま作成したパネルにマテリアルとシェーダを設定します。プロジェクトビューで右クリックから「Create」→「Shader」→「Standard Surface Shader」を選択しsampleという名前で保存します。続いてsampleシェーダを選択した状態で、右クリックから「Create」→「Material」を選択し、こちらもsampleという名前で保存します。
最後に作成したPanelのシェーダを「Custom/sample」に変更します。シェーダの詳しい作成方法と設定方法は下の記事で紹介していますので参照して下さい。
これで自前のシェーダをアタッチしたパネルのオブジェクトが作成できました。次はパネルの表面にテクスチャを表示するため、シェーダの内容を変更しましょう。
ステンドグラスシェーダのプログラム
上のアルゴリズムを実装したプログラムは次のとおりです。
Shader "Custom/sample" { Properties{ _MainTex("Texture", 2D)="white"{} } SubShader { Tags { "Queue"="Transparent" } LOD 200 CGPROGRAM #pragma surface surf Standard alpha:fade #pragma target 3.0 struct Input { float2 uv_MainTex; }; sampler2D _MainTex; void surf (Input IN, inout SurfaceOutputStandard o) { fixed4 c = tex2D(_MainTex, IN.uv_MainTex); o.Albedo = c.rgb; o.Alpha = (c.r*0.3 + c.g*0.6 + c.b*0.1 < 0.2) ? 1 : 0.7; } ENDCG } FallBack "Diffuse" }
今回は半透明のシェーダを利用するので、Tagの設定・alpha:fadeの指定・Alpha値の指定を行っています。半透明を描画するときの設定は次の記事で詳しく解説しています。
surfメソッドの中ではtex2Dメソッドを使ってテクスチャの色情報を取得し、グレースケールに変換しています。変換式は上に示したものを使っています。グレースケールの値が0.2以下の場合には透明度を1に設定して、0.2より大きい場合には透明度を0.7に設定しています。
これにより、画像の黒い部分は不透明、それ以外の部分は半透明になり、ステンドグラスのような見た目になります。
シェーダを使ってピクセルの色を操作することで、様々な映像表現が可能になります。ステンドグラスだけでなく動くテクスチャなども作ることも出来るので、後々紹介していければと思います。