MRが楽しい

MRやVRについて学習したことを書き残す

MRTKv2.xを使ってMetaQuest3向けのUnityプロジェクト作成を行う その15(MRTKv2.xのシェーダをオクルージョンに対応させる)

本日はMetaQuest3の技術調査枠です。
MRTKv2.xを使ってMetaQuest3向けのUnityプロジェクト作成を行う手順を記事にします。
本記事はMRTKv2.xのシェーダをオクルージョンに対応させる手順です。

前提条件

本記事では以下の記事で作成したUnity プロジェクトを基に設定を行います。
bluebirdofoz.hatenablog.com

MRTKv2.xのシェーダをオクルージョンに対応させる

独自のシェーダをオクルージョンで利用する場合、シェーダコードにいくつかの修正を加える必要があります。
シェーダの修正手順は以下のReadMeに解説されています。
github.com

MRTKv2.xのシェーダは以下のフォルダにインポートされています。

Assets/MRTK/Shaders

今回はボタンなどの基本UXをオクルージョンさせたいのでMixedRealityStandard.shaderを変更します。

186行目と194行目に以下を追加します。

            // DepthAPI Environment Occlusion
            #pragma multi_compile _ HARD_OCCLUSION SOFT_OCCLUSION
            #include "Packages/com.meta.xr.depthapi/Runtime/BiRP/EnvironmentOcclusionBiRP.cginc"

325行目に以下を追加します。

                META_DEPTH_VERTEX_OUTPUT(8) // the number should stand for the previous TEXCOORD# + 1

592行目に以下を追加します。

                // v.vertex (object space coordinate) might have a different name in your vert shader
                META_DEPTH_INITIALIZE_VERTEX_OUTPUT(o, v.vertex);

778行目に以下を追加します。

                UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);

1103行目に以下を追加します。

                // Third field is for environment depth bias. 0.0 means the occlusion will be calculated with depths as they are.
                META_DEPTH_OCCLUDE_OUTPUT_PREMULTIPLY(i, output, 0.0);

これでシェーダの改変は完了です。
動作確認のため、以下のMRTKのボタンUXをシーンに配置しました。

Packages/MixedRealityToolkitFoundation/SDK/Features/UX/Interactable/Prefabs/PressableButtonHoloLens2_32x96.prefab


ビルドと動作確認

これで設定は完了です。
以下の記事を参考にプロジェクトのビルドとQuest3へのデプロイを実行してください。
bluebirdofoz.hatenablog.com

アプリを起動時してボタンに手をかざすとオクルージョンが行われます。

キャプチャの通り、上記の手順だけではテキスト部分は別のシェーダが使われているため、オクルージョンが行われません。
テキスト部分もオクルージョンさせるには以下のシェーダについても同様の修正を行う必要があります。

MixedRealityTextMeshPro.shader

カスタムシェーダの実装手順

シェーダの修正手順のReadMeを日本語訳したものを以下に記述します。
github.com

カスタムシェーダーでオクルージョンを実装する

独自のシェーダーを利用する場合はいくつかの変更を適用することで、それらをオクルージョン可能なものに変換できます。
ビルドインレンダーパイプラインの場合は、次の include ステートメントを使用します。

#include "Packages/com.meta.xr.depthapi/Runtime/BiRP/EnvironmentOcclusionBiRP.cginc"

ユニバーサルレンダーパイプラインの場合は、次の include ステートメントを使用します。

#include "Packages/com.meta.xr.depthapi/Runtime/URP/EnvironmentOcclusionURP.hlsl"

1.オクルージョンキーワードを追加する

#pragma multi_compile _ HARD_OCCLUSION SOFT_OCCLUSION

2.構造体にマクロとワールド座標(SV_POSITION)を追加します。ワールド座標は既に登録済みの場合、スキップします。

struct v2f
{
   float4 vertex : SV_POSITION;


   float4 someOtherVarying : TEXCOORD0;


   META_DEPTH_VERTEX_OUTPUT(1) // the number should stand for the previous TEXCOORD# + 1


   UNITY_VERTEX_INPUT_INSTANCE_ID
   UNITY_VERTEX_OUTPUT_STEREO // required for stereo
};
v2f vert (appdata v) {
   v2f o;

   UNITY_SETUP_INSTANCE_ID(v);
   UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); // required to support stereo

   // v.vertex (object space coordinate) might have a different name in your vert shader
   META_DEPTH_INITIALIZE_VERTEX_OUTPUT(o, v.vertex);

   return o;
}

3.フラグメントシェーダでオクルージョンの計算処理を追加する

half4 frag(v2f i) {
   UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);

   // this is something your shader will return without occlusions
   half4 fragmentShaderResult = someColor;

   // Third field is for environment depth bias. 0.0 means the occlusion will be calculated with depths as they are.
   META_DEPTH_OCCLUDE_OUTPUT_PREMULTIPLY(i, fragmentShaderResult, 0.0);

   return fragmentShaderResult;
}

フラグメントシェーダーに渡されるワールド座標に変化がある場合は、次のマクロを使用できます。

META_DEPTH_OCCLUDE_OUTPUT_PREMULTIPLY_WORLDPOS(yourWorldPosition, fragmentShaderResult, 0.0);