本日はUnityShader枠です。
先日SteamVR用のアプリケーションを作成していると次のように描画がおかしくなる問題がありました。
SkyBoxの描画がおかしく、スカイボックスが画像に映ると描画の画面がそのまま残ってしまう問題がありました。
〇原因
以前も本ブログで取り上げていますが、xRデバイスでは右目、左目と2つのディスプレイを描画しています。
この際に一部のシェーダーは両目の描画に対応しておらず、破断してしまうことがあります。
通常のオブジェクトの場合、右目の描画が行われなくなるため片目のみの描画が行われることが多いですが、SkyBoxの場合上記画像のように描画が破断するようです。
この現象はShader側を修正することで改善します。
〇修正
この現象を修正するためにはSkyBoxに使用されているShaderを修正します。
SkyBoxに使用されているShaderはUnity上部ワールドタブ[Window]→[Rendering]→[Lighting]から[LightingSettings]を開きます。
[Environment]タブから確認することができます。
マテリアルを選択してInspectorウィンドウからShaderを編集できます。
〇Shaderの修正点
UnityではShaderは以下のような構造をしています。
Shader "Skybox/●●" { Properties { ... } SubShader { Pass { CGPROGRAM #pragma vertex vert #pragma fragment frag struct appdata { ... }; struct v2f { ... }; v2f vert(appdata v) { v2f o; ... return o; } half4 frag(v2f i) : COLOR { ... } ENDCG } } ... }
このうち修正する箇所はCGPROGRAM~ENDCG(もしくはHLSLPROGRAM~ENDHLSL)の部分です。
①appdata構造体に以下の一文を追加します。
struct appdata { ... UNITY_VERTEX_INPUT_INSTANCE_ID//追加 };
appdata構造体は3Dモデル自体の頂点や法線などの情報を格納します。一般的にappdata、appdata_tという名前が使われます。
②次にv2f構造体に以下の一文を追加します。
struct v2f { ... UNITY_VERTEX_OUTPUT_STEREO//追加 };
v2f構造体はVertex to fragmentの略でその名のように頂点シェーダーで計算したデータを格納しフラグメントシェーダーで使用するために使用します。
一般的にv2fが使用されますが、場合によってはv2g(Vertex to Geometry)などの名前が使用されることもあります。
③最後に頂点シェーダーに次の分を追加します。
v2f vert(appdata v) { v2f o; UNITY_SETUP_INSTANCE_ID(v); //追加 UNITY_INITIALIZE_OUTPUT(v2f, o); //追加 UNITY_INITIALIZE_VERTEX_OUTPUT_STEREO(o); //追加 ... return o; }
以上で修正が完了しました。
これはシングルパスインスタンシングレンダリングといい、Steamの場合DirectX11以降で対応している手法です。(Oculus Quest、HoloLensも対応)
左右の描画のうち、共有する部分を同時に処理して処理の量を減らしパフォーマンス向上を図る技術になります。
この作業により描画がおかしくなる問題が解消しました。