namespace UnityEngine.Rendering.PostProcessing { /// /// This component holds a set of debugging utilities related to post-processing. /// /// /// These utilities can be used at runtime to debug on device. /// #if UNITY_2018_3_OR_NEWER [ExecuteAlways] #else [ExecuteInEditMode] #endif [AddComponentMenu("Rendering/Post-process Debug", 1002)] public sealed class PostProcessDebug : MonoBehaviour { /// /// A reference to a to debug. /// public PostProcessLayer postProcessLayer; PostProcessLayer m_PreviousPostProcessLayer; /// /// Holds settings for the light meter. /// public bool lightMeter; /// /// Holds settings for the histogram. /// public bool histogram; /// /// Holds settings for the waveform. /// public bool waveform; /// /// Holds settings for the vectorscope. /// public bool vectorscope; /// /// The currently set overlay. /// public DebugOverlay debugOverlay = DebugOverlay.None; Camera m_CurrentCamera; CommandBuffer m_CmdAfterEverything; void OnEnable() { m_CmdAfterEverything = new CommandBuffer { name = "Post-processing Debug Overlay" }; #if UNITY_EDITOR // Update is only called on object change when ExecuteInEditMode is set, but we need it // to execute on every frame no matter what when not in play mode, so we'll use the // editor update loop instead... UnityEditor.EditorApplication.update += UpdateStates; #endif } void OnDisable() { #if UNITY_EDITOR UnityEditor.EditorApplication.update -= UpdateStates; #endif if (m_CurrentCamera != null) m_CurrentCamera.RemoveCommandBuffer(CameraEvent.AfterImageEffects, m_CmdAfterEverything); m_CurrentCamera = null; m_PreviousPostProcessLayer = null; } #if !UNITY_EDITOR void Update() { UpdateStates(); } #endif void Reset() { postProcessLayer = GetComponent(); } void UpdateStates() { if (m_PreviousPostProcessLayer != postProcessLayer) { // Remove cmdbuffer from previously set camera if (m_CurrentCamera != null) { m_CurrentCamera.RemoveCommandBuffer(CameraEvent.AfterImageEffects, m_CmdAfterEverything); m_CurrentCamera = null; } m_PreviousPostProcessLayer = postProcessLayer; // Add cmdbuffer to the currently set camera if (postProcessLayer != null) { m_CurrentCamera = postProcessLayer.GetComponent(); m_CurrentCamera.AddCommandBuffer(CameraEvent.AfterImageEffects, m_CmdAfterEverything); } } if (postProcessLayer == null || !postProcessLayer.enabled) return; // Monitors if (lightMeter) postProcessLayer.debugLayer.RequestMonitorPass(MonitorType.LightMeter); if (histogram) postProcessLayer.debugLayer.RequestMonitorPass(MonitorType.Histogram); if (waveform) postProcessLayer.debugLayer.RequestMonitorPass(MonitorType.Waveform); if (vectorscope) postProcessLayer.debugLayer.RequestMonitorPass(MonitorType.Vectorscope); // Overlay postProcessLayer.debugLayer.RequestDebugOverlay(debugOverlay); } void OnPostRender() { m_CmdAfterEverything.Clear(); if (postProcessLayer == null || !postProcessLayer.enabled || !postProcessLayer.debugLayer.debugOverlayActive) return; m_CmdAfterEverything.Blit(postProcessLayer.debugLayer.debugOverlayTarget, BuiltinRenderTextureType.CameraTarget); } void OnGUI() { if (postProcessLayer == null || !postProcessLayer.enabled) return; // Some SRPs don't unbind render targets and leave them as-is RenderTexture.active = null; var rect = new Rect(5, 5, 0, 0); var debugLayer = postProcessLayer.debugLayer; DrawMonitor(ref rect, debugLayer.lightMeter, lightMeter); DrawMonitor(ref rect, debugLayer.histogram, histogram); DrawMonitor(ref rect, debugLayer.waveform, waveform); DrawMonitor(ref rect, debugLayer.vectorscope, vectorscope); } void DrawMonitor(ref Rect rect, Monitor monitor, bool enabled) { if (!enabled || monitor.output == null) return; rect.width = monitor.output.width; rect.height = monitor.output.height; GUI.DrawTexture(rect, monitor.output); rect.x += monitor.output.width + 5f; } } }