本日はShaderのトラブル解消を行います。
先日MixedRealityGraphicsToolsの拡大鏡機能をHoloLensで実行した際にUV座標のV座標が反転する現象を確認しました。
取り急ぎの対処としてV座標に-1をかけ合わせてトラブルを回避しました。
この方法ではHoloLens 2実機に合わせてShaderを書き換えたため今度はUntiyEditorや他のプラットフォームでV座標が反転する問題が発生します。
〇プラットフォーム毎よってUV座標が反転する原因
今回の原因はグラフィックスAPIによる座標系の定義の違いです。
HoloLens 2ではDirectX、QuestなどのAndroidデバイスではOpenGL やVulkanなどが使用されています。
UV座標に関しての原点(0,0)はそれぞれ次のように定義されています。
〇UNITY_UV_STARTS_AT_TOP
UNITY_UV_STARTS_AT_TOPはUnityで提供されている定義済みマクロ(条件コンパイル)です。
返り値として0or1が定まっていますが、実行環境のプラットフォームによって自動的に割り振られます。
この仕組みはマルチプラットフォームでの稼働を想定して設計されているGraphicsTools/Standardシェーダーにも採用されています。
GraphicsToolsStandardシェーダーでもブラーなどのスクリーン座標の処理が行われており、同様の仕組みが実装されています、。
#if defined(_UV_SCREEN) output.uvScreen = ComputeScreenPos(output.position); // Flip vertical UV for orthographic projections (if not already flipped) to ensure the image is not upside down. #if defined(UNITY_UV_STARTS_AT_TOP) output.uvScreen.y = unity_OrthoParams.w ? (1.0 - output.uvScreen.y) : output.uvScreen.y; #else output.uvScreen.y = unity_OrthoParams.w ? output.uvScreen.y : (1.0 - output.uvScreen.y); #endif #elif (_BLUR_TEXTURE_PREBAKED_BACKGROUND) output.uvBackgroundRect = float2((vertexPosition.x - _BlurBackgroundRect.x) / (_BlurBackgroundRect.z - _BlurBackgroundRect.x), (vertexPosition.y - _BlurBackgroundRect.y) / (_BlurBackgroundRect.w - _BlurBackgroundRect.y)); #endif
DirectX環境であるHoloLensではUNITY_UV_STARTS_AT_TOPの処理が走り、スクリーン座標のV座標が反転されるようになっています。
#if defined(UNITY_UV_STARTS_AT_TOP) output.uvScreen.y = unity_OrthoParams.w ? (1.0 - output.uvScreen.y) : output.uvScreen.y; #else
unity_OrthoParamsはカメラが遠視投影を使用している場合は1,平行投影を使用している場合は0が返され、通常の場合 (1.0 - output.uvScreen.y)が実行されV座標が反転されています。
スクリーン座標を使用する場合同様の仕組みを実装することであらゆるプラットフォームで対応できるシェーダーになりそうです。
〇参考
以下の記事を参考にさせていただきました。
またUNITY_UV_STARTS_AT_TOPに関しては先日の拡大鏡機能に関するバグレポートを提出した際にリーダーのCameronさんより教えていただきました。