Study unity vertexシェーダーを使ったあれこれ練習
先日の記事で紹介しました、Vertexシェーダーを少し弄ってみたいなーというモチベーションに動かされたのが、今日のブログです。
というわけで、とりあえずベースとしましたのは unlite/Texture シェーダーです。
まずはunlite/Textureのシェーダーを作成してダブルクリックです。アセットのところで右クリックでシェーダーは作れるですが、謎めいていたら上の記事を見ていただけるとよいと思うです。
まずもとのシェーダーのvertexの部分をを見てみましょう。
となっております。
v2f vert (appdata v) を見てみます。
まず戦闘のv2fが、気になるですがこちら、上を見ますとstruct v2f と似たような記述があるです。
この struct というのは、構造体?を意味しているらしく、いろんなデータ(点の座標とかUVのやつとか)をひとまとめにして使いやすくしてるですね。
でもって、この v2f vert (appdata v) の先頭にあるv2f というのは、vertex シェーダーで計算した値を v2f の構造体に突っ込んでフラグメントシェーダーに渡すよって言ってる感じ見たいです。ちなみにこういう風に処理が終わって次に渡すための値の事を返り値とか言うらしいです。
v to f 要するに vertex から fragment へ渡すよって意味合いを込めて、v2fらしいです。toを2と読み替えるのが流行りらしいです。
でもって、次にvert ですが、こちらは、また少し上の方を見ると舌みたいなのがあるです。
こちらの #pragma vetex vert という記述で、vert が書かれています。
これは、vertex シェーダーで、vert を使うよという宣言ですね。
ちなみに下の fragment frag の方はfragment シェーダーの宣言になるです。
こんな感じで見ていくと次の v2f vert (appdata v) の appdata vも気になるですね。
また上の方にこんな記述があるです。このvertの中の()の中身は、vertexシェーダーの中の処理で使う値だよって言ってるわけですね。
要するにこのappdataにvertexシェーダーで処理するための材料が入っており、この値を使って、頂点の位置や、色を計算しよう!って感じらしいです。ただ、使うときにappdataのままだと使いまわしがきかんですので、今回はvという名前にしといて処理するよ。って雰囲気です。
次です。
v2f o;
というのがあります。v2fは先ほども出てきましたね。
構造体のv2f、これは、fragmentシェーダーに渡すものだったはずです。これをここでoという名前を付けて用意しています。
これからこの o の中に必要な計算結果を突っ込んでいって、次のfragment シェーダーに渡すわけですね。
次です。
o.vertex = UnityObjectToClipPos(v.vertex);
手前のoはわかります。そして、.vertexとなっているのは、oの中のvertexを呼び出してるわけですね。
持っぺん先ほどのですが、確かにvertexがv2fの中に入っているのがわかります。
でもって、プログラム言語では、= というのは、そこにデータを入れるという意味になるらしいです。
というわけで UnityObjectToClipPos(v.vertex) を、oのvertexに入れるって感じですね。
うん……。……?
UnityObjectToClipPos(v.vertex)ってなんですかー!
ってなるですが、調べました。
ビルトインシェーダーヘルパー機能 - Unity マニュアル
こちらからの引用になるですが、
float4 UnityObjectToClipPos(float3 pos)
同次座標において、オブジェクト空間からカメラのクリップ空間へ点を変換します。
これは、mul(UNITY_MATRIX_MVP, float4(pos, 1.0)) と同等に使用されます。
要するに、世界のここにこのモデルを置いてあっち向いてるよー!ぐらいのことをしてるみたいです。あまり細かいことはわからんですが、要するにオブジェクト、(今回で言うところの3Dモデル)を、カメラのクリップ空間(画像を作るための世界)へ、移す感じ。
次です。
o.uv = TRANSFORM_TEX(v.uv, _MainTex);
今度は oの uv に何かを入れるみたいですね。
こちらに関しては、雰囲気でもわかりました。
v.uvというのは、v(元のモデルのデータ)のuvです。uvというと、テクスチャのためのuv展開を思い出すですね。そして、後ろにあるのは _MainTex。この_MainTexは、上で宣言されたPropertiesです。要するに、unityの画面でデータを入れられる奴です。もっと要すると、unityの画面でモデルに設定するテクスチャになるですね。
そして、この二つから考えるに、o.uv = TRANSFORM_TEX(v.uv, _MainTex)では、モデルのUV展開図の座標と、それに対応したテクスチャ(_MainTex)をfragmentシェーダーに渡すために入れているということですね。
では、次です。
UNITY_TRANSFER_FOG(o,o.vertex);
こちら調べてみたですが、フォグを追加するということが書かれていました。
フォグというのがいまいちわかってないですが、遠くにあるほどぼやけるような処理を追加するというイメージでいいのでしょうかね?
とりあえずそんな感じらしいです?(?_?)(またわかったら追加するかも)
でもって最後です。
return o
これはシンプルです。要するに o を次に渡すよって感じです。
return っていうのはその処理を終えて、次に渡すよ見たいな意味らしいです。
今回で言うと、次の処理はfragmentシェーダーなので、fragmentシェーダーにoを渡す感じですね。
ここまでのまとめです。
要約すると、このvertexシェーダーでは、モデルの点を世界の座標に固定して、uv展開されたテクスチャと、そのuvのマップを用意し、フォグかけてねー!って設定を入れた、v2fのoというデータを用意して、fragmentシェーダーにぽーい!って感じです。
このあとfragmentシェーダーが、投げられたデータから画面に表示する絵を描いてくれるわけですね。
なんか思ってたよりまた長くなってしまったので、今日はこのあたりで失礼(>_<)
てっでー!
続く!
ちなみに、宣伝ですが、こちらの本はシェーダーのsampleがたくさん載ってて良いです。巻末に、出てくる謎の文字のまとめみたいなのもあり、シェーダーの雰囲気はわかたけど、どんなことできるのかな、みたいなのを知りたいときによいと思ったです。
ちなみに2018年6月9日現在では、kindle Unlimited(要するに読み放題)、一か月無料体験の対象ですのでそちら、はいってみるのもよいかと思うです。
時期によっては、外れてるかもしれんですので、一応確認されてからにしてくださいね。