今回は”エフェクト用のシェーダに関するアイデア”の補足でGrabTextureを使用する場合のパーティクルのカラー合成をしてみます。
GrabTextureは背景からテクスチャにキャプチャした画像をカラー合成の対象にできる命令で スクリーンサイズのスナップショットをテクスチャに展開します。
GrabTexture命令で 取り込んだテクスチャにシェーダでモデルのカラーを合成をしてやれば ”エフェクト用のシェーダに関するアイデア”で使用したシェーダと同じような効果がねらえます。カラーを合成する式は
これも以前掲載した フォトショップの合成式を使用することが出来るため フォトショップ上の見た目と同等の表現が期待出来て デザイナーにとっては非常にありがたい機能です。 ただしGrabTexture命令は処理負荷が高く現在のモバイルやスマホで動作させるには重ためなので気をつけてください。
【fig1】
今回作成したサンプルシェーダコードは以下の通りです
■ 『BlendTest(GrabTex) . shader" 』
| Shader "Custom/Particles/BlendTest(GrabTex)" { Properties { _TintColor ( "Tint Color", Color ) = ( 0.5, 0.5, 0.5, 0.5 ) Category { Tags { "Queue"="Transparent" "RenderType"="Opaque" } GrabPass { CGPROGRAM struct appdata_t { struct v2f { sampler2D _MainTex; v2f vert ( appdata_t v ) { v2f o; o.vertex = mul( UNITY_MATRIX_MVP, v.vertex ); return o; } } } } |
■ GrabTextureの取得は GrabPassをk術するだけです samplerの指定とセットなので記述漏れしないようにしてください
| GrabPass { ・・・・・・・・・・・・・・・・・・・・・・・ sampler2D _GrabTexture; ・・・・・・・・・・・・・・・・・・・・・・・ o.uvgrab.xy = ( float2( o.vertex.x, ( o.vertex.y * scale ) ) + o.vertex.w ) * 0.5;o.uvgrab.zw = o.vertex.zw; |
● half4 col = tex2Dproj( _GrabTexture, UNITY_PROJ_COORD( i.uvgrab ) );
Unityのマクロ関数 UNITY_PROJ_COORD にワールド頂点座標を与えることによってカメラのプロジェクション方向から見たスクリーン座標のUV値に変換されます。
Tags { "Queue"="Transparent" "RenderType"="Opaque" } タグはレンダーキュー(Queue)に透明(Transparent)が指定してあればアルファを考慮したソートが行われるため RenderTypeは無視しても構いません。
■Blend One OneMinusSrcAlpha は <背景 1 :前景 1-alpha値> で合成を指定します。アルファ抜きの場合はこれを使用。
ZWriteをOnにするのを忘れないように depthバッファの書き込みが行われないと正確なソートが行われません。
Alphatest Greater 0.1 はしきい値(例の場合0.1)を境界にして透明部分の抜け具合を決定します。
| Blend One OneMinusSrcAlpha Alphatest Greater 0.1 ZWrite On |
■ライブラリの種類によっては取り込んだテクスチャのUV座標のV方向(スクリーン座標のY軸方向)が上下逆になることがあるので
UNITY_UV_STARTS_AT_TOP の変数を監視してテクスチャUVのV方向に−1を掛けてフリップする必要があります
| #if UNITY_UV_STARTS_AT_TOP float scale = -1.0; #else float scale = 1.0; #endif |
■カラー合成式に関してはどのような書き方してももちろん構いません 見た目でより良い結果になるようにしてください。
|
● フォトショップのブレンド式 を使用する場合 return float4( ( base.rgb < 0.5 ? (2.0 * base.rgb * col.rgb) : (1.0 - 2.0 * (1.0 - base.rgb) * (1.0 - col.rgb).rgb)).rgb , base.a ); ● 加算と乗算を組み合わせる場合 return float4( base.rgb + _TintColor * pow(base.rgb,2.0 )* col.rgb , base.a ); |
テクスチャはアルファ抜きしたものを使用しますが、 カラーの明度からアルファマスクを計算して取得することも出来ます
【Example】
float alpha =Luminance(color.rgb) ;
たとえばUnityのマクロ関数Luminanceを使用します RGB値カラーを輝度値 に変換する関数で "UnityCG.cginc"ファイルに記述されています
Luminance( ) の代入はfloat3型ですので float4型のカラーを渡すときは 「color.rgb」というようにSwizzleで記述します。
| inline fixed Luminance( fixed3 c ) { return dot( c, fixed3(0.22, 0.707, 0.071) ); } |
【追記】
リファレンスには下のように GrabPassにオプションパラメータとしてテクスチャのスケールが指定できると書いてありますが コンパイルが通ったことがありません Unity公式フォーラムでもバグ扱いされていてだれも使い方をわかってないようなんですが、どうやって使用するんでしょう? ご存じの方がいればコメント頂きたいのです。
| GrabPass { TextureScale 0.5 TextureSize 256 BorderScale 0.3 // following are regular pass commands Tags { "LightMode" = "VertexLit" } Name "BASE" } |
今回は以上です 次回はなるべくはために更新するつもりですが 少しレベルを上げるかもしれませんので頑張って読解してみてください。
質問がある方はコメント欄にどうぞ
それではまた
