あまり使われないマイナーなマテリアル機能 その2 "Customized UV"

前回に引き続き、マテリアルのマイナーな機能を紹介するコーナー。

今回はCustomized UVです。

UVのカスタマイズと聞いて、メッシュに別のUVを割り当てる手法と思う人もいるかもしれませんが、そうではありません。

とりあえず、解説する前に使い方から提示します。

まず、マテリアルエディタを開き、詳細パネルをチェックしましょう。

[Material]カテゴリのデフォルトでは非表示になっている部分に[Num Customized UVs]という項目があります。

デフォルト値は0ですが、この状態では使用できないので2を入れてみましょう。

ue269.jpg 

すると、メインマテリアルノードに[Customized UV0], [Customized UV1]の2つのピンが出現します。

これで機能が使えるようになります。

実際に使ってみましょう。

わかりやすくするため、以下のようにつないでみます。

ue270.jpg 

UV0にはテクスチャ座標をそのまま設定、UV1には2倍したテクスチャ座標、つまり2回のタイリングを行うテクスチャ座標を設定します。

次に適当なテクスチャをテクスチャ座標でサンプリングし、ベースカラーに設定します。

ue271.jpg 

これを四角の板に貼り付けた結果は当然こうなります。

ue272.jpg 

では、テクスチャをサンプリングしているテクスチャ座標を選択し、詳細パネルで[Coordinate Index]を1に変更してみましょう。

ue273.jpg 

すると、結果がこのように変化します。

ue274.jpg 

2回のタイリング結果ですね。

ここからわかると思いますが、Customized UVの機能を利用するとCustomized UVのピンに入力した結果をテクスチャサンプルする段階でインデックス番号によって参照することが出来るというわけです。

しかし、この方法は一手間増えてしまっています。今までみたいにサンプリングする際に直接2倍したりじゃダメなのでしょうか?

もちろん、ダメじゃないです。

ただ、これにはこれで利点もあります。

では、続きからでそもそもの機能解説と制約を書いておきます。

 そもそも、今までのテクスチャをサンプリングする段階でテクスチャ座標を計算していた場合とCustomized UVを使った場合とで何が違ってくるのでしょうか?

実はCustomized UVピンに入力されたノードは処理されるステージが変わります。

通常のやり方ではテクスチャ座標の計算がピクセルシェーダで行われるのに対して、Customized UVピンでは頂点シェーダで行われます。

頂点シェーダで行う最大の利点はやはり処理速度です。

最近のハイエンドゲームではモデル1つあたりの頂点数が100万頂点とかザラになってきています。

100万頂点ということは、頂点シェーダは単純計算で100万回処理が走るということになるわけです。

これに対してピクセルシェーダはどうでしょう?

このような頂点数のモデルを描画した際に、画面全体を覆うように描画されたとします。

ピクセルは1回しか描画されなかったと仮定したとしても、HD環境で200万ピクセル以上が描画されることになります。

絶対とはいえないのですが、多くの場合で頂点シェーダよりピクセルシェーダのほうが処理が走る回数は多いのです。

タイリングの回数を変更するには掛け算を1回だけ処理すればいいわけですが、先の例を考えるとピクセルシェーダで処理するより頂点シェーダで処理したほうが100万命令ほど減らせることになるわけです。

まあ、100万命令減らせるとか言っても、超高速に並列処理されるうちの100万命令なので、現代のGPUではそれほどのアドバンテージにはならないと思います。

しかしながら、より命令数の多いテクスチャ座標計算が行われたら? GPUの処理速度がデスクトップPCより遅いモバイル環境なら?

そのような場合であれば速度的なアドバンテージが十分に出てくることでしょう。

というわけで今回作ってみたサンプルは昔懐かしい多重スクロールによる水の表現。

最近でも3DSやVitaでならやるのかもしれませんが、昔は少ないテクスチャでスクロールパターンがわかりにくくなるようにするため、

同じテクスチャを互い違いの方向に2重スクロールしてブレンド結果を表示する、という方法が好まれていました。

以下はそれを適当に実装してみた結果です。

ue275.jpg 

それなりにノード数が多くなっていて複雑っぽく見えますが、互い違いにスクロールさせてるだけです。

法線マップはどちらも同じもので、スターターコンテンツの水の法線を使っています。

結果は動画でなければわからないので、興味がある方は実装してみてください。

ちなみに、通常のピクセルシェーダで処理される方法とCustomized UVでの方法では統計情報が以下のように異なります。

ue276.jpg 

上がピクセルシェーダで行った場合、下がCustomized UVです。

Base pass~がピクセルシェーダでの処理で、こちらは減ってますが、頂点シェーダは増えてます。

微々たるもののようにも見えますが、最終的には少しは効いてくる…かも知れません。

最後に制約について。

まず、使用可能なUV数ですが、PCでは8個まで使用できます。

しかし、モバイル環境では3個までです。

まあ、モバイル環境は速度の問題もあれば電池消費の問題もあるのでそんなに大量のテクスチャサンプリングは行わないでしょうし、3つで十分だと思います。

もう1つの制約は結構重要です。

Customized UVは頂点シェーダで行われる処理ですので、頂点単位でしか計算されません。

ピクセルでのテクスチャ座標は補間された値を使用することになります。

これは、例えば単純なUVスクロールや全体的なタイリングの変化といった、頂点ごとでもピクセルごとでも一律に計算される処理であれば問題はありません。

しかし、ピクセルごとにUV値の変化が異なる場合にはうまく行きません。

例えば、以前紹介したフローマップと呼ばれる手法があります。

この手法は生のUV値から一旦テクスチャをサンプリングし、サンプリングしたテクセルからUV値の移動量を計算する手法です。

このようにテクスチャサンプリングの結果からUV値を変化させ、また別のテクスチャをサンプリングする手法を”インダイレクトテクスチャ”などと呼ぶこともあります。

というわけで、以下の動画がピクセルごとと頂点ごとのフローマップの処理結果です。

左がピクセルごとの処理で、ちゃんとピクセル単位で流れているのが見えます。

左はCustomized UVを使った場合で、この場合は頂点ごとでしかスクロールしてません。

ちょっとわかりにくいかも。

なお、Customized UVに対してもテクスチャサンプリングは可能です。

頂点が細かく割られているなら、このような手法をCustomized UVで行ってもいいかもしれませんね。