MRが楽しい

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

シングルパスインスタンシングレンダリングを使って左右のディスプレイで異なる画像を出力する

本日は HoloLens の技術調査枠です。
シングルパスインスタンシングレンダリングを使って左右のディスプレイで異なる画像を出力してみます。

以下のページを参考に実施します。
docs.unity3d.com

マルチパスとシングルパスの違いについて

本記事ではマルチパスとシングルパスの仕組みの違いについては述べません。未だに理解が至っていないため。
以下の記事や公式ページが参考になります。
tips.hecomi.com
docs.unity3d.com
docs.unity3d.com

プロジェクトとシーンの準備

以下の記事を元にHoloLens(WindowsMR)プロジェクトを作成します。
bluebirdofoz.hatenablog.com

今回は Panel に配置した画像ファイルで動作を確認します。
このため、Sphere オブジェクトを Plane オブジェクトに差し替えています。
f:id:bluebirdofoz:20190502234255j:plain

レンダリング設定の切り替え

メニューから Edit -> ProjectSettings -> Player を選択し、PlayerSettings の Inspector ビューを開きます。
f:id:bluebirdofoz:20190502234310j:plain

[XR Settings]パネルを開き、[Stereo Rendering Method]を[Single Pass Instanced (Preview]に変更します。
これでシングルパスインスタンシングレンダリングが有効になります。
f:id:bluebirdofoz:20190502234323j:plain

カスタムシェーダの作成

インスタンシングを利用するカスタムシェーダを作成します。
Assets フォルダで右クリックから Create -> Shader -> Unlit Shader で新規シェーダを作成します。
f:id:bluebirdofoz:20190502234335j:plain

参考ページのサンプルシェーダを元に、テクスチャの右半分と左半分を右目と左目で別々に描画するシェーダを作成しました。
・UnitOffsetShader.shader

Shader "Unlit/UnitOffsetShader"
{
  Properties
  {
    _MainTex ("Texture", 2D) = "white" {}
  }
  SubShader
  {
    Tags { "RenderType"="Opaque" }
    LOD 100

    Pass
    {
      CGPROGRAM
      #pragma vertex vert
      #pragma fragment frag
      // make fog work
      #pragma multi_compile_fog
      
      #include "UnityCG.cginc"

      struct appdata
      {
        float4 vertex : POSITION;
        float2 uv : TEXCOORD0;

        // シングルパスインスタンシング対応のため挿入
        UNITY_VERTEX_INPUT_INSTANCE_ID
      };

      struct v2f
      {
        float2 uv : TEXCOORD0;
        UNITY_FOG_COORDS(1)
        float4 vertex : SV_POSITION;

        // シングルパスインスタンシング対応のため挿入
        UNITY_VERTEX_OUTPUT_STEREO
      };

      sampler2D _MainTex;
      float4 _MainTex_ST;
      
      v2f vert (appdata v)
      {
        v2f o;

        // シングルパスインスタンシング対応のため挿入
        UNITY_SETUP_INSTANCE_ID(v);
        UNITY_INITIALIZE_OUTPUT(v2f, o);
        UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o);

        o.vertex = UnityObjectToClipPos(v.vertex);
        o.uv = TRANSFORM_TEX(v.uv, _MainTex);
        // 左目と右目でテクスチャの左右の半分を分けて描画する
        o.uv.x *= .5;
        // unity_StereoEyeIndex の値は
        // 左目のレンダリングは 0、右目のレンダリングは 1
        if (unity_StereoEyeIndex != 0)
        {
          o.uv.x += .5;
        }
        UNITY_TRANSFER_FOG(o,o.vertex);
        return o;
      }
      
      fixed4 frag (v2f i) : SV_Target
      {
        // シングルパスインスタンシング対応のため挿入
        UNITY_SETUP_STEREO_EYE_INDEX_POST_VERTEX(i);

        fixed4 col = tex2D(_MainTex, i.uv);
        // apply fog
        UNITY_APPLY_FOG(i.fogCoord, col);
        return col;
      }
      ENDCG
    }
  }
}

作成したシェーダを参照するマテリアルを作成します。
Assets フォルダで右クリックから Create -> Material で新規マテリアルを作成します。
f:id:bluebirdofoz:20190502234349j:plain

作成した新規マテリアルのシェーダとして先ほど作成した Unlit/UnitOffsetShader を設定します。
f:id:bluebirdofoz:20190502234403j:plain

最後に描画するテクスチャを設定します。
左右で異なる部分が描画されていることが分かる横方向のグラデーション画像を取り込みました。
[Texture Type]を[Sprite (2D and UI)]に変更して[Apply]ボタンをクリックします。
f:id:bluebirdofoz:20190502234415j:plain

マテリアルにテクスチャを設定して、マテリアルの設定は完了です。
f:id:bluebirdofoz:20190502234428j:plain

完成したマテリアルを Plane オブジェクトに適用します。
f:id:bluebirdofoz:20190502234439j:plain

後は HoloLens 向けにプロジェクトをビルドしてインストールします。
UnityプロジェクトのビルドとHoloLensへのインストール手順については以下を参照してください。
bluebirdofoz.hatenablog.com

HoloLensでの動作確認

HoloLens 上で動作確認を行います。
成功していれば右目と左目で異なる画像が描画されています。
キャプチャを行うと、右目の映像がキャプチャされます。
f:id:bluebirdofoz:20190502234458j:plain