🎥

PolySpatialでの簡易ポータル表現

2024/07/21に公開

image

概要

visionOSのRealityKitにはPortalMaterialという、奥に別の空間があるような表現ができる機能があるのですが、PolySpatialでは使用できるようになっていません。
そのため、今回はPortalMaterialの代わりにインテリアマッピングを使用して、Unityでも簡易的に奥行き感が出るような表現を行なっていきたいと思います。

image

インテリアマッピングとは

インテリアマッピングとは視線位置から擬似的に奥行きのある空間を描画する方法です。
スパイダーマンのゲームで使用されており話題になっていました。
描画しているのは平面ポリゴンのみなので、ポリゴン数が削減できつつ、部屋の中の表現もテクスチャを切り替えることで違った見た目にすることができます。

https://twitter.com/Papapishu/status/1038317456044052480

詳しいインテリアマッピングの実装につきましてはコポコポさんの記事を参考にさせていただきました。
インテリアマッピングについてわかりやすく解説されています。
https://coposuke.hateblo.jp/entry/2018/12/11/064755
https://coposuke.hateblo.jp/entry/2020/12/24/003734

窓から見える面を計算

インテリアマッピングはカメラから奥に見える面を求めて表示しています。
視線方向から奥に見える面は、窓となる面から視線方向へ伸ばした時に、一番最初に壁に当たる部分となります。

image

奥の面が1立方メートルの大きさだとすると、窓の位置から視線方向へ伸ばした時のX, Y, Z 成分のベクトルが一番早く1に到達する面が窓の位置から見える面になります。

image

下記の部分ではX成分は3つ分で面に到着し、Z成分は6つで面に到着するため、この場合はX成分の面が一番近い面になります。
image

X,Y,Z軸の各面までの距離は開始位置によって異なってきます。
視線ベクトルがプラスの時、X座標の位置が 0.6 の位置では、残りの距離が 1 - 0.6 = 0.4になるため、0.4に到着するまでのベクトルの長さが最短距離となります。
image

視線ベクトルがマイナス方向に進んでいる場合は、マイナス方向の面が当たる位置を求める必要があるため、マイナス方向に進む場合とプラス方向に進む場合で残り距離の計算を変える必要があります。
0.4 の位置では 0.4 が残りの距離になります。
image

視線ベクトルのX成分がプラスの時は1から引くことで距離が求められるため、このような計算式になります。

StartDistance.x = 1 - StartPoint.x \\ DistanceVec.x = StartDistance.x / ViewDirection.x

視線ベクトルのX成分がマイナスの時は、0から引くことでStartDistanceをマイナスとして、視線ベクトルで割る時に マイナスとマイナスで割ることでプラスとなり 必要な距離を求めることができます。

StartDistance.x = 0 - StartPoint.x \\ DistanceVec.x = StartDistance.x / ViewDirection.x

これを視線ベクトルをStep関数を使用して 0以下だったら0、0以上だったら1となるようにまとめます。

DistanceVec = (Step(0, ViewDirection.x) - StartPoint) / ViewDirection \\ MinDistance = Min(DistanceVec.x, Min(DistanceVec.y, DistanceVec.z))

求めた MinDistance を 視線ベクトルにかけることで 一番近い面に到達した時のポイントがわかるようになります。

InteractPoint = StartPoint + MinDistance * ViewDirection

複数の面からの対応

上記の計算をワールドスペースで行うと正面を向いている面が窓の時は正しく計算ができるのですが、ビルのように正面以外の面にも窓をつけたい場合は、軸が変わってしまうのでうまくいきません。

これをどの面から見ても計算できるように、タンジェント空間(TangentSpace)での計算にしていきます。

TangentSpaceは法線方向をZ軸とした座標系で、ポリゴンの面に沿ってX軸とY軸が存在します。
ポリゴンのX,Y軸がポリゴンの面に沿うため、テクスチャを貼るUV座標を計算する時に使用されます。

image

視線方向のベクトルをTangetSpaceへ変換を行い、開始地点をUV座標の位置を使用することで、TangentSpaceで一番近い面の計算を行います。

カメラへの向きである ShaderGraphではViewDirectionノードのSpace をTangentに変更することでTangentSpaceでのカメラ方向へのベクトルを取得することができます。

しかし、ViewDirectionはポジションからカメラへのベクトルになるので逆向きにして視線方向のベクトルに変換する必要があります。
この時、TangentSpaceでは右手座標系でUnityの左手座標系とはZ軸の方向が反対になるため、Z軸だけは向きを変えずに使用します。

image

CubeMapへの対応

TangentSpaceでの一番近い面との交点を求めたら、CubeMapの向きに変換していきます。

CubeMapはこのような構造のテクスチャになっており、各面の情報が割り当てられています。
image

+Zの方向が正面、-Zが背面、+Yが上面などに割り当てられているため、交点の位置のベクトルの成分の大きさが 1となっている面を選択し、それ以外の成分をUVとして使用することで、テクスチャの色を選択していきます。

ShaderGraphではDirectionを渡すことでサンプリングすることができるので、交点のベクトルを渡してテクスチャを拾います。

TangentSpaceで計算したものは 0〜1 の範囲で計算しているので、-1〜1 となるようにRemapを行い、Direction として使用します。

ShaderGraphの構築

それではインテリアマッピングのShaderGraphを構築していきます。

まずは、UVをタイリングして複数の部屋を作れるようにします。
Fractionは少数部分を取得することができるため0~1を繰り返すことができるようになります。
image

次に視線方向のベクトルを取得します。
ViewDirectionSpaceTangentに変更して、視線方向となるようにX,Y軸を反転させます。
image

次に開始地点から視線方向のベクトルが面に到達するまでの距離を求めています。
UV座標を開始地点として使用して、視線方向のベクトルの向きに合わせて計算方法をStepによって切り替えています。

DistanceVec = (Step(0, ViewDirection.x) - StartPoint) / ViewDirection

image

次に一番近い面までの距離を求めていきます。
SplitによってX,Y,Z成分に分解を行いその中で、一番低い値を取得します。

MinDistance = Min(DistanceVec.x, Min(DistanceVec.y, DistanceVec.z))

image

次に面にヒットする位置のポイントを求めます。

InteractPoint = StartPoint + MinDistance * ViewDirection

image

次にCubeMapのサンプリングを行います。
Remapノードを使用して0〜1の範囲から-1〜1に変換しています。
image

サンプリングの結果をFragmentのBase Color に入れることで完成です!
image

ビルのように見せるために、窓枠のテクスチャをつけたり、タイルごとに色合いやテクスチャを変えたりすることでより自然になってきます。
image

まとめ

これでPortalMaterialがなくても奥行きがある表現が作成できました!
visionOS2 のPortalMaterialでは空間から飛び出てくるような表現も使えるようになっているので、PolySpatialでも使用できるようになってくれると嬉しいですね。
image

エンジニア絶賛募集中!

MESONではUnityエンジニアを絶賛募集中です! XRのプロジェクトに関わってみたい! 開発したい! という方はぜひご応募ください!
また最近ではAIの活用も積極的に進めており、XR x AIに興味があるエンジニアの方もぜひご応募ください!

MESONのメンバーページからご応募いただくか、TwitterのDMなどでご連絡ください。

書いた人

ひー

佐藤 寿樹

株式会社コナミデジタルエンタテインメントに入社し5年間ウイニングイレブンのオンライン実装に携わる。
その後、株式会社コロプラで9年間エンジニアとしてアプリ開発・運用を行い、位置情報やARを使用したARゲーム開発、OculusRiftやPSVRなどのVRゲーム開発を経験しMESONへ入社。

Twitter

MESON Works

MESONの制作実績一覧もあります。ご興味ある方はぜひ見てみてください。

MESON Cases

Discussion