Unityで不透明描画のオーバードローを正確に表示する方法をまとめました。
Unity2019.2.5
SceneビューのOverdrawの問題点
UnityのSceneビューにはオーバードローを見ることができる機能があります。
この機能は処理負荷を見るときに便利です。
しかしながら、このOverDrawモードは半透明描画のシェーダを使っているので、
不透明描画のオーバードローが正確に表示できていないという問題があります。
https://forum.unity.com/threads/overdraw-of-opaque-and-transparent-geometry.463962/
たとえば次のように不透明なオブジェクトを4つ重ねて配置します。
この状態でSceneビューをOverdrawモードにすると以下のような表示になります。
不透明なので本当はZテストにより重ねて描画されていないにもかかわらず、
重ねて描画されているかのような表示になってしまっています。
正確に不透明描画のオーバードローを表示する
正確に不透明描画のオーバーには、シェーダとスクリプトを書く必要があります。
まずZライトとZテストを行い、薄めの色を加算するシェーダを書きます。
Shader "OverDrawOpaque" { CGINCLUDE #pragma vertex vert #pragma fragment frag struct appdata { float4 vertex : POSITION; }; struct v2f { float4 vertex : SV_POSITION; }; v2f vert(appdata v) { v2f o; o.vertex = UnityObjectToClipPos(v.vertex); return o; } fixed4 frag(v2f i) : SV_Target { return fixed4(0.1, 0.03, 0.03, 1); } ENDCG SubShader { Tags{ "RenderType" = "Opaque" } Pass { ZWrite On ZTest LEqual Blend One One Cull Back CGPROGRAM ENDCG } } }
一点注意点として、今回は標準的な不透明シェーダを想定してカリングの設定をCull Backとしています。
もしカリングをオフにしたい場合にはこれをCull Offと書き換える必要があります。
そしてReplaced Shaderを使って描画対象のシェーダをこれに置換します。
using UnityEngine; [RequireComponent(typeof(Camera))] public class OverDrawOpaque : MonoBehaviour { private Camera _camera; private CameraClearFlags _preClearFlags; private Color _preBackgroundColor; private void OnEnable() { _camera = GetComponent<Camera>(); if (_camera != null) { _preClearFlags = _camera.clearFlags; _preBackgroundColor = _camera.backgroundColor; _camera.SetReplacementShader(Shader.Find("OverDrawOpaque"), "RenderType"); _camera.clearFlags = CameraClearFlags.SolidColor; _camera.backgroundColor = Color.black; } } private void OnDisable() { _camera?.ResetReplacementShader(); if (_camera != null) { _camera.clearFlags = _preClearFlags; _camera.backgroundColor = _preBackgroundColor; } } }
Replaced Shaderの使い方は下記にまとめているので必要に応じて参照してください。
使い方
あとはこのスクリプトをCameraにアタッチするだけで、Gameビューに不透明オブジェクトのオーバードロー情報が表示されます。
重なり部分のオーバードローが正確に表示できるようになったことが確認できます。
ちなみに今回は不透明なオブジェクト以外は描画しないようにしています。