Built-in Render Pipeline から Universal Render Pipeline(以降URPと記載)に移行した際、カメラ映像を反転させる処理が動かなくなりました。 今回は、URP プロジェクトでカメラ映像を反転させる方法のひとつをお話しします。
確認環境
- Unity バージョン:2021.3.25f1
- Universal RP バージョン:12.1.11
まとめ
- Unity 公式ドキュメントのカメラ反転のサンプルを URP 対応する
- サンプルのイベント箇所を RenderPipelineManager のイベントに差し替える
Built-in Render Pipeline でのカメラ映像の反転
今回はカメラ映像を反転させる方法の一つとして、Camera の ProjectionMatrix を変更する方法を用います。 Built-in Render Pipeline での実装は、Unity公式ドキュメントのカメラ反転のサンプルを参考にします。 MonoBehaviour-OnPreCull() - Unity スクリプトリファレンス
解説は下記の記事が参考になりました。 rdrgn.hatenablog.com ポイントは OnPreCull(), OnPreRender(), OnPostRender() といったイベントを利用していることです。
URP でのカメラ映像の反転
Built-in Render Pipeline の実装を URP で動かすと、カメラ映像を反転する処理が動かなくなります。 この問題は OnPreCull(), OnPreRender(), OnPostRender() のイベントが URP のプロジェクトで呼ばれなくなったことが原因で発生します。 そのため使用しているイベントを差し替えることで、この問題は解決できます。
URP における同様なイベントとしては、RenderPipelineManager のイベントがあります。 Rendering.RenderPipelineManager - Unity スクリプトリファレンス これらのイベントで差し替えることで、カメラ映像の反転を実現することができます。
- イベント差し替えの例
- OnPreCull() -> RenderPipelineManager.beginCameraRendering
- OnPreRender() -> RenderPipelineManager.beginCameraRendering
- OnPostRender() -> RenderPipelineManager.endCameraRendering
(参考) zenn.dev
実装例
最後に、URP プロジェクトでカメラ映像を左右反転させる実装例を掲載します。 こちらをカメラにアタッチして、動作を確認してみてください。 インスペクターから IsInvert の値を操作することで反転の有無を切り替えることができます。
using UnityEngine; using UnityEngine.Rendering; [RequireComponent(typeof(Camera))] public class InvertableCamera : MonoBehaviour { [SerializeField] bool IsInvert = true; private Camera _targetCamera = null; void Awake() { _targetCamera = GetComponent<Camera>(); } void OnEnable() { RenderPipelineManager.beginCameraRendering += OnBeginCameraRendering; RenderPipelineManager.endCameraRendering += OnEndCameraRendering; } void OnDisable() { RenderPipelineManager.beginCameraRendering -= OnBeginCameraRendering; RenderPipelineManager.endCameraRendering -= OnEndCameraRendering; } void OnBeginCameraRendering(ScriptableRenderContext context, Camera camera) { if (IsInvert) { GL.invertCulling = true; } _targetCamera.ResetWorldToCameraMatrix(); _targetCamera.ResetProjectionMatrix(); var vec = IsInvert ? new Vector3(-1f, 1f, 1f) : Vector3.one; _targetCamera.projectionMatrix = _targetCamera.projectionMatrix * Matrix4x4.Scale(vec); } void OnEndCameraRendering(ScriptableRenderContext context, Camera camera) { GL.invertCulling = false; } }
以上。
※当ブログに掲載された内容によって生じた損害等の一切の責任を負いかねますのでご了承ください。 当サイトで掲載している画像や動画の著作権・肖像権等は各権利所有者に帰属致します。