こんにちは!トイロジックでテクニカルアーティストをやっているトリと申します。
本記事は、同時公開された「HoudiniとUnrealEngineで始めるインテリアマッピング入門【前編】」の続きとなっております。前編を読んでいないとなんのこっちゃだと思いますので、ぜひご一読いただければと思います!
目次
やってみようインテリアマッピング ~とりあえず各面の座標まで出してみる(続き)
Plane上の各点から各面までの距離を測る
前編では、「Planeの中心のrayが、正負どちらの領域を向いている場合でも立方体をなぞるように動く」というところまでやりました。
この後編では、これを「Plane上のどの点でも」成り立つように拡張するところから始めましょう。ray(視線ベクトル)について改めて確認しておきます。
上の図を見てみると、Plane上の位置が異なれば、rayの向きも異なっていることが分かります。このように、rayは場所場所によって異なる値が入っていますので、そのことを考慮して距離を測らないといけません。ちなみに考慮しないで前回までの処理を各点に拡張すると、以下のようになります。Planeの中心である(1,0,0)から出てるベクトル以外、立方体からはみだしてしまっています。
どのようにすれば望ましい結果になるか、改めて作図して考えてみます。
例えば (1,0.25,0) のピクセルを始点とするrayを考える時、位置関係は上の図のようになります。rayがPlaneの中心から上方向に移動した分、求めたい値aを斜辺とする大きな三角形の右側の辺が長くなっています。計算上もこれを考慮するようにすればよいわけです。上の図の場合、 0.25 の座標から -1.0 までの距離なので、
|(-1.0)-(0.25)|=1.25
が距離となります。
つまり、視線ベクトルの視点位置を factor.y / ray.y
の分子から引きます。
( factor.y - (ピクセルのワールド位置) ) / ray.y
x軸に関しては、ピクセル位置がx軸方向にずれることはないので、先ほどと変わらず、
(-2) / ray.x
のままでよいです。
これをHoudiniでやると下のようになります。無事に「視線ベクトルが立方体の各面のいずれかに衝突する距離」が求まったということになります! 後編に入って早々ですが、ここまで来たら、Houdiniの方はほとんど完成といっていいでしょう!
ここまで見てきた「Plane上の各点のray」
はシェーダに於いては「各ピクセルにおけるray」
とほぼ同義です。となるとUEマテリアルでもそれらしいものが見れるようになってきます。
こんな感じです。前編までの内容に水色のブロックが追加されています。ピクセル一つ一つで正しい計算が行われることで、なんとなく深度のようなものが見えているのが分かるでしょうか?
しれっと三次元でやっていますが、やることは二次元の時と何ら変わらないのでご安心ください。
ちなみに、追加された水色の部分。WorldPosition
ではなくTexCoord
を使っているのが不思議かもしれません。これは、Planeの前提条件的に、UVでWorldPosition
を代用可能なので、こうしています。
Planeの右上右下、左上左下の座標はそれぞれ、画像の通りです。この時、PlaneのUVが 0~1 の範囲ぴったりに平面投影されているならば、TexCoord
の値のレンジを- 1~1 にしてから符号反転してあげると、TexCoord
の値と実際のワールド位置のYZ座標が完全一致します(HoudiniだとZY座標)。なので、TexCoord
でWorldPosition
を代用できるというわけです。
TexCoord
で代用しておく方が、のちのちいろんなケースが出てきた場合に対応がラクそうな気がしたので、そのようにしています。
rayを伸ばして座標を描画する
一番の問題だった「視線ベクトルが立方体の各面のいずれかに衝突する距離」は求まったので、後は初めに提示した通り、
視線開始座標 + 視線ベクトル * 視線ベクトルが立方体の各面のいずれかに衝突する距離
という計算を行うだけです。シェーダは、以下のグラフのように組みます。
rayに、衝突するまでの距離を乗じることで、前項中段のGIFと同じ状態になります。その後の視線開始座標(Plane上の各点のワールド位置≒ピクセルのワールド位置)を足すのは要らないような気がしてしまいますが、これをやらないと、各ピクセルに入っている視線ベクトルがどの位置から伸びるのかが確定できません。
実際にそのピクセル上に描かれているベクトルであっても、自動的に自分の位置を考慮した計算をしてくれるわけではないんですね。視線開始座標を足すことで、初めて仮想的な部屋内での「位置座標」になるのです。これでUEマテリアル版も完成です! 実際に描画される見た目はこちら。ちゃんと部屋ができていますね!
おまけですが、ついでにHoudini版の方も3次元化&色付けしてみましょう。このような感じになります。
見にくいかもですが、UEマテリアル版と同様の部屋が描かれているのが分かると思います。カメラの位置を変えると、Planeの奥にある立方体内に収まるようにベクトルが伸びていることも確認できますね。
補足:ノード削減版
ちなみにですが、UEマテリアル版はここからさらにノード数を減らすことができます。ただ、最初からこっちのバージョンで理解しようとすると難しくなってしまうので、今回はわかりやすさ優先で解説してみました。このノード数削減版は、非削減版と同様にインテリアマッピングとして使えますが、何もしないと仮想の部屋の座標がワールド空間と反転していることに注意する必要があります。
やってみようインテリアマッピング ~実用的な使い方を目指す編
ここからは、より実用的に使えるように、「テクスチャを貼る」「部屋の数を増やす」ということをやってみます。ただし、本記事の主題は先ほどまでの基礎部分を理解することでしたので、今回は詳しい解説はしません。(気力が尽きたとも言います)
テクスチャを貼る
各面の座標が分かっているので、ここから面毎に適切な2成分を取り出して[-1,1]
を[0,1]
にリマップしてUVとすればよいです。先ほどのシェーダノードの画像に「InteriorCoord」
というNamedRerouteがあると思うので、そこからつなげて以下のように組みます。
部屋の数を増やす
画像の部分を追加するだけです。
まとめ
前編・後編の2回にわたり、インテリアマッピングの基礎の基礎を解説しました。応用部分はかなり簡略化していますので、詳細が必要な方には物足りないかもしれません。
実際にゲーム内のアセットに使用する際には、細かな調整が必要になる場合もあるかと思いますが、基本的な考え方はここで説明した通りです。理屈を知っていれば色々と応用もできる技術だと思いますので、興味を持たれた方はぜひご自身でもチャレンジしてみてください!