| | |
| | | using UnityEditorInternal; |
| | | using UnityEngine; |
| | | using UnityEngine.PostProcessing; |
| | | |
| | | namespace UnityEditor.PostProcessing |
| | | { |
| | | using HistogramMode = PostProcessingProfile.MonitorSettings.HistogramMode; |
| | | |
| | | public class HistogramMonitor : PostProcessingMonitor |
| | | { |
| | | static GUIContent s_MonitorTitle = new GUIContent("Histogram"); |
| | | |
| | | ComputeShader m_ComputeShader; |
| | | ComputeBuffer m_Buffer; |
| | | Material m_Material; |
| | | RenderTexture m_HistogramTexture; |
| | | Rect m_MonitorAreaRect; |
| | | |
| | | public HistogramMonitor() |
| | | { |
| | | m_ComputeShader = EditorResources.Load<ComputeShader>("Monitors/HistogramCompute.compute"); |
| | | } |
| | | |
| | | public override void Dispose() |
| | | { |
| | | GraphicsUtils.Destroy(m_Material); |
| | | GraphicsUtils.Destroy(m_HistogramTexture); |
| | | |
| | | if (m_Buffer != null) |
| | | m_Buffer.Release(); |
| | | |
| | | m_Material = null; |
| | | m_HistogramTexture = null; |
| | | m_Buffer = null; |
| | | } |
| | | |
| | | public override bool IsSupported() |
| | | { |
| | | return m_ComputeShader != null && GraphicsUtils.supportsDX11; |
| | | } |
| | | |
| | | public override GUIContent GetMonitorTitle() |
| | | { |
| | | return s_MonitorTitle; |
| | | } |
| | | |
| | | public override void OnMonitorSettings() |
| | | { |
| | | EditorGUI.BeginChangeCheck(); |
| | | |
| | | bool refreshOnPlay = m_MonitorSettings.refreshOnPlay; |
| | | var mode = m_MonitorSettings.histogramMode; |
| | | |
| | | refreshOnPlay = GUILayout.Toggle(refreshOnPlay, new GUIContent(FxStyles.playIcon, "Keep refreshing the histogram in play mode; this may impact performances."), FxStyles.preButton); |
| | | mode = (HistogramMode)EditorGUILayout.EnumPopup(mode, FxStyles.preDropdown, GUILayout.MaxWidth(100f)); |
| | | |
| | | if (EditorGUI.EndChangeCheck()) |
| | | { |
| | | Undo.RecordObject(m_BaseEditor.serializedObject.targetObject, "Histogram Settings Changed"); |
| | | m_MonitorSettings.refreshOnPlay = refreshOnPlay; |
| | | m_MonitorSettings.histogramMode = mode; |
| | | InternalEditorUtility.RepaintAllViews(); |
| | | } |
| | | } |
| | | |
| | | public override void OnMonitorGUI(Rect r) |
| | | { |
| | | if (Event.current.type == EventType.Repaint) |
| | | { |
| | | // If m_MonitorAreaRect isn't set the preview was just opened so refresh the render to get the histogram data |
| | | if (Mathf.Approximately(m_MonitorAreaRect.width, 0) && Mathf.Approximately(m_MonitorAreaRect.height, 0)) |
| | | InternalEditorUtility.RepaintAllViews(); |
| | | |
| | | // Sizing |
| | | float width = m_HistogramTexture != null |
| | | ? Mathf.Min(m_HistogramTexture.width, r.width - 65f) |
| | | : r.width; |
| | | float height = m_HistogramTexture != null |
| | | ? Mathf.Min(m_HistogramTexture.height, r.height - 45f) |
| | | : r.height; |
| | | |
| | | m_MonitorAreaRect = new Rect( |
| | | Mathf.Floor(r.x + r.width / 2f - width / 2f), |
| | | Mathf.Floor(r.y + r.height / 2f - height / 2f - 5f), |
| | | width, height |
| | | ); |
| | | |
| | | if (m_HistogramTexture != null) |
| | | { |
| | | Graphics.DrawTexture(m_MonitorAreaRect, m_HistogramTexture); |
| | | |
| | | var color = Color.white; |
| | | const float kTickSize = 5f; |
| | | |
| | | // Rect, lines & ticks points |
| | | if (m_MonitorSettings.histogramMode == HistogramMode.RGBSplit) |
| | | { |
| | | // A B C D E |
| | | // N F |
| | | // M G |
| | | // L K J I H |
| | | |
| | | var A = new Vector3(m_MonitorAreaRect.x - 1f, m_MonitorAreaRect.y - 1f); |
| | | var E = new Vector3(A.x + m_MonitorAreaRect.width + 2f, m_MonitorAreaRect.y - 1f); |
| | | var H = new Vector3(E.x, E.y + m_MonitorAreaRect.height + 2f); |
| | | var L = new Vector3(A.x, H.y); |
| | | |
| | | var N = new Vector3(A.x, A.y + (L.y - A.y) / 3f); |
| | | var M = new Vector3(A.x, A.y + (L.y - A.y) * 2f / 3f); |
| | | var F = new Vector3(E.x, E.y + (H.y - E.y) / 3f); |
| | | var G = new Vector3(E.x, E.y + (H.y - E.y) * 2f / 3f); |
| | | |
| | | var C = new Vector3(A.x + (E.x - A.x) / 2f, A.y); |
| | | var J = new Vector3(L.x + (H.x - L.x) / 2f, L.y); |
| | | |
| | | var B = new Vector3(A.x + (C.x - A.x) / 2f, A.y); |
| | | var D = new Vector3(C.x + (E.x - C.x) / 2f, C.y); |
| | | var I = new Vector3(J.x + (H.x - J.x) / 2f, J.y); |
| | | var K = new Vector3(L.x + (J.x - L.x) / 2f, L.y); |
| | | |
| | | // Borders |
| | | Handles.color = color; |
| | | Handles.DrawLine(A, E); |
| | | Handles.DrawLine(E, H); |
| | | Handles.DrawLine(H, L); |
| | | Handles.DrawLine(L, new Vector3(A.x, A.y - 1f)); |
| | | |
| | | // Vertical ticks |
| | | Handles.DrawLine(A, new Vector3(A.x - kTickSize, A.y)); |
| | | Handles.DrawLine(N, new Vector3(N.x - kTickSize, N.y)); |
| | | Handles.DrawLine(M, new Vector3(M.x - kTickSize, M.y)); |
| | | Handles.DrawLine(L, new Vector3(L.x - kTickSize, L.y)); |
| | | |
| | | Handles.DrawLine(E, new Vector3(E.x + kTickSize, E.y)); |
| | | Handles.DrawLine(F, new Vector3(F.x + kTickSize, F.y)); |
| | | Handles.DrawLine(G, new Vector3(G.x + kTickSize, G.y)); |
| | | Handles.DrawLine(H, new Vector3(H.x + kTickSize, H.y)); |
| | | |
| | | // Horizontal ticks |
| | | Handles.DrawLine(A, new Vector3(A.x, A.y - kTickSize)); |
| | | Handles.DrawLine(B, new Vector3(B.x, B.y - kTickSize)); |
| | | Handles.DrawLine(C, new Vector3(C.x, C.y - kTickSize)); |
| | | Handles.DrawLine(D, new Vector3(D.x, D.y - kTickSize)); |
| | | Handles.DrawLine(E, new Vector3(E.x, E.y - kTickSize)); |
| | | |
| | | Handles.DrawLine(L, new Vector3(L.x, L.y + kTickSize)); |
| | | Handles.DrawLine(K, new Vector3(K.x, K.y + kTickSize)); |
| | | Handles.DrawLine(J, new Vector3(J.x, J.y + kTickSize)); |
| | | Handles.DrawLine(I, new Vector3(I.x, I.y + kTickSize)); |
| | | Handles.DrawLine(H, new Vector3(H.x, H.y + kTickSize)); |
| | | |
| | | // Separators |
| | | Handles.DrawLine(N, F); |
| | | Handles.DrawLine(M, G); |
| | | |
| | | // Labels |
| | | GUI.color = color; |
| | | GUI.Label(new Rect(L.x - 15f, L.y + kTickSize - 4f, 30f, 30f), "0.0", FxStyles.tickStyleCenter); |
| | | GUI.Label(new Rect(J.x - 15f, J.y + kTickSize - 4f, 30f, 30f), "0.5", FxStyles.tickStyleCenter); |
| | | GUI.Label(new Rect(H.x - 15f, H.y + kTickSize - 4f, 30f, 30f), "1.0", FxStyles.tickStyleCenter); |
| | | } |
| | | else |
| | | { |
| | | // A B C D E |
| | | // P F |
| | | // O G |
| | | // N H |
| | | // M L K J I |
| | | |
| | | var A = new Vector3(m_MonitorAreaRect.x, m_MonitorAreaRect.y); |
| | | var E = new Vector3(A.x + m_MonitorAreaRect.width + 1f, m_MonitorAreaRect.y); |
| | | var I = new Vector3(E.x, E.y + m_MonitorAreaRect.height + 1f); |
| | | var M = new Vector3(A.x, I.y); |
| | | |
| | | var C = new Vector3(A.x + (E.x - A.x) / 2f, A.y); |
| | | var G = new Vector3(E.x, E.y + (I.y - E.y) / 2f); |
| | | var K = new Vector3(M.x + (I.x - M.x) / 2f, M.y); |
| | | var O = new Vector3(A.x, A.y + (M.y - A.y) / 2f); |
| | | |
| | | var P = new Vector3(A.x, A.y + (O.y - A.y) / 2f); |
| | | var F = new Vector3(E.x, E.y + (G.y - E.y) / 2f); |
| | | var N = new Vector3(A.x, O.y + (M.y - O.y) / 2f); |
| | | var H = new Vector3(E.x, G.y + (I.y - G.y) / 2f); |
| | | |
| | | var B = new Vector3(A.x + (C.x - A.x) / 2f, A.y); |
| | | var L = new Vector3(M.x + (K.x - M.x) / 2f, M.y); |
| | | var D = new Vector3(C.x + (E.x - C.x) / 2f, A.y); |
| | | var J = new Vector3(K.x + (I.x - K.x) / 2f, M.y); |
| | | |
| | | // Borders |
| | | Handles.color = color; |
| | | Handles.DrawLine(A, E); |
| | | Handles.DrawLine(E, I); |
| | | Handles.DrawLine(I, M); |
| | | Handles.DrawLine(M, new Vector3(A.x, A.y - 1f)); |
| | | |
| | | // Vertical ticks |
| | | Handles.DrawLine(A, new Vector3(A.x - kTickSize, A.y)); |
| | | Handles.DrawLine(P, new Vector3(P.x - kTickSize, P.y)); |
| | | Handles.DrawLine(O, new Vector3(O.x - kTickSize, O.y)); |
| | | Handles.DrawLine(N, new Vector3(N.x - kTickSize, N.y)); |
| | | Handles.DrawLine(M, new Vector3(M.x - kTickSize, M.y)); |
| | | |
| | | Handles.DrawLine(E, new Vector3(E.x + kTickSize, E.y)); |
| | | Handles.DrawLine(F, new Vector3(F.x + kTickSize, F.y)); |
| | | Handles.DrawLine(G, new Vector3(G.x + kTickSize, G.y)); |
| | | Handles.DrawLine(H, new Vector3(H.x + kTickSize, H.y)); |
| | | Handles.DrawLine(I, new Vector3(I.x + kTickSize, I.y)); |
| | | |
| | | // Horizontal ticks |
| | | Handles.DrawLine(A, new Vector3(A.x, A.y - kTickSize)); |
| | | Handles.DrawLine(B, new Vector3(B.x, B.y - kTickSize)); |
| | | Handles.DrawLine(C, new Vector3(C.x, C.y - kTickSize)); |
| | | Handles.DrawLine(D, new Vector3(D.x, D.y - kTickSize)); |
| | | Handles.DrawLine(E, new Vector3(E.x, E.y - kTickSize)); |
| | | |
| | | Handles.DrawLine(M, new Vector3(M.x, M.y + kTickSize)); |
| | | Handles.DrawLine(L, new Vector3(L.x, L.y + kTickSize)); |
| | | Handles.DrawLine(K, new Vector3(K.x, K.y + kTickSize)); |
| | | Handles.DrawLine(J, new Vector3(J.x, J.y + kTickSize)); |
| | | Handles.DrawLine(I, new Vector3(I.x, I.y + kTickSize)); |
| | | |
| | | // Labels |
| | | GUI.color = color; |
| | | GUI.Label(new Rect(A.x - kTickSize - 34f, A.y - 15f, 30f, 30f), "1.0", FxStyles.tickStyleRight); |
| | | GUI.Label(new Rect(O.x - kTickSize - 34f, O.y - 15f, 30f, 30f), "0.5", FxStyles.tickStyleRight); |
| | | GUI.Label(new Rect(M.x - kTickSize - 34f, M.y - 15f, 30f, 30f), "0.0", FxStyles.tickStyleRight); |
| | | |
| | | GUI.Label(new Rect(E.x + kTickSize + 4f, E.y - 15f, 30f, 30f), "1.0", FxStyles.tickStyleLeft); |
| | | GUI.Label(new Rect(G.x + kTickSize + 4f, G.y - 15f, 30f, 30f), "0.5", FxStyles.tickStyleLeft); |
| | | GUI.Label(new Rect(I.x + kTickSize + 4f, I.y - 15f, 30f, 30f), "0.0", FxStyles.tickStyleLeft); |
| | | |
| | | GUI.Label(new Rect(M.x - 15f, M.y + kTickSize - 4f, 30f, 30f), "0.0", FxStyles.tickStyleCenter); |
| | | GUI.Label(new Rect(K.x - 15f, K.y + kTickSize - 4f, 30f, 30f), "0.5", FxStyles.tickStyleCenter); |
| | | GUI.Label(new Rect(I.x - 15f, I.y + kTickSize - 4f, 30f, 30f), "1.0", FxStyles.tickStyleCenter); |
| | | } |
| | | } |
| | | } |
| | | } |
| | | |
| | | public override void OnFrameData(RenderTexture source) |
| | | { |
| | | if (Application.isPlaying && !m_MonitorSettings.refreshOnPlay) |
| | | return; |
| | | |
| | | if (Mathf.Approximately(m_MonitorAreaRect.width, 0) || Mathf.Approximately(m_MonitorAreaRect.height, 0)) |
| | | return; |
| | | |
| | | float ratio = (float)source.width / (float)source.height; |
| | | int h = 512; |
| | | int w = Mathf.FloorToInt(h * ratio); |
| | | |
| | | var rt = RenderTexture.GetTemporary(w, h, 0, source.format); |
| | | Graphics.Blit(source, rt); |
| | | ComputeHistogram(rt); |
| | | m_BaseEditor.Repaint(); |
| | | RenderTexture.ReleaseTemporary(rt); |
| | | } |
| | | |
| | | void CreateBuffer(int width, int height) |
| | | { |
| | | m_Buffer = new ComputeBuffer(width * height, sizeof(uint) << 2); |
| | | } |
| | | |
| | | void ComputeHistogram(RenderTexture source) |
| | | { |
| | | if (m_Buffer == null) |
| | | { |
| | | CreateBuffer(256, 1); |
| | | } |
| | | else if (m_Buffer.count != 256) |
| | | { |
| | | m_Buffer.Release(); |
| | | CreateBuffer(256, 1); |
| | | } |
| | | |
| | | if (m_Material == null) |
| | | { |
| | | m_Material = new Material(Shader.Find("Hidden/Post FX/Monitors/Histogram Render")) { hideFlags = HideFlags.DontSave }; |
| | | } |
| | | |
| | | var channels = Vector4.zero; |
| | | switch (m_MonitorSettings.histogramMode) |
| | | { |
| | | case HistogramMode.Red: channels.x = 1f; break; |
| | | case HistogramMode.Green: channels.y = 1f; break; |
| | | case HistogramMode.Blue: channels.z = 1f; break; |
| | | case HistogramMode.Luminance: channels.w = 1f; break; |
| | | default: channels = new Vector4(1f, 1f, 1f, 0f); break; |
| | | } |
| | | |
| | | var cs = m_ComputeShader; |
| | | |
| | | int kernel = cs.FindKernel("KHistogramClear"); |
| | | cs.SetBuffer(kernel, "_Histogram", m_Buffer); |
| | | cs.Dispatch(kernel, 1, 1, 1); |
| | | |
| | | kernel = cs.FindKernel("KHistogramGather"); |
| | | cs.SetBuffer(kernel, "_Histogram", m_Buffer); |
| | | cs.SetTexture(kernel, "_Source", source); |
| | | cs.SetInt("_IsLinear", GraphicsUtils.isLinearColorSpace ? 1 : 0); |
| | | cs.SetVector("_Res", new Vector4(source.width, source.height, 0f, 0f)); |
| | | cs.SetVector("_Channels", channels); |
| | | cs.Dispatch(kernel, Mathf.CeilToInt(source.width / 16f), Mathf.CeilToInt(source.height / 16f), 1); |
| | | |
| | | kernel = cs.FindKernel("KHistogramScale"); |
| | | cs.SetBuffer(kernel, "_Histogram", m_Buffer); |
| | | cs.Dispatch(kernel, 1, 1, 1); |
| | | |
| | | if (m_HistogramTexture == null || m_HistogramTexture.width != source.width || m_HistogramTexture.height != source.height) |
| | | { |
| | | GraphicsUtils.Destroy(m_HistogramTexture); |
| | | m_HistogramTexture = new RenderTexture(source.width, source.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear) |
| | | { |
| | | hideFlags = HideFlags.DontSave, |
| | | wrapMode = TextureWrapMode.Clamp, |
| | | filterMode = FilterMode.Bilinear |
| | | }; |
| | | } |
| | | |
| | | m_Material.SetBuffer("_Histogram", m_Buffer); |
| | | m_Material.SetVector("_Size", new Vector2(m_HistogramTexture.width, m_HistogramTexture.height)); |
| | | m_Material.SetColor("_ColorR", new Color(1f, 0f, 0f, 1f)); |
| | | m_Material.SetColor("_ColorG", new Color(0f, 1f, 0f, 1f)); |
| | | m_Material.SetColor("_ColorB", new Color(0f, 0f, 1f, 1f)); |
| | | m_Material.SetColor("_ColorL", new Color(1f, 1f, 1f, 1f)); |
| | | m_Material.SetInt("_Channel", (int)m_MonitorSettings.histogramMode); |
| | | |
| | | int pass = 0; |
| | | if (m_MonitorSettings.histogramMode == HistogramMode.RGBMerged) |
| | | pass = 1; |
| | | else if (m_MonitorSettings.histogramMode == HistogramMode.RGBSplit) |
| | | pass = 2; |
| | | |
| | | Graphics.Blit(null, m_HistogramTexture, m_Material, pass); |
| | | } |
| | | } |
| | | } |
| | | using UnityEditorInternal;
|
| | | using UnityEngine;
|
| | | using UnityEngine.PostProcessing;
|
| | |
|
| | | namespace UnityEditor.PostProcessing
|
| | | {
|
| | | using HistogramMode = PostProcessingProfile.MonitorSettings.HistogramMode;
|
| | |
|
| | | public class HistogramMonitor : PostProcessingMonitor
|
| | | {
|
| | | static GUIContent s_MonitorTitle = new GUIContent("Histogram");
|
| | |
|
| | | ComputeShader m_ComputeShader;
|
| | | ComputeBuffer m_Buffer;
|
| | | Material m_Material;
|
| | | RenderTexture m_HistogramTexture;
|
| | | Rect m_MonitorAreaRect;
|
| | |
|
| | | public HistogramMonitor()
|
| | | {
|
| | | m_ComputeShader = EditorResources.Load<ComputeShader>("Monitors/HistogramCompute.compute");
|
| | | }
|
| | |
|
| | | public override void Dispose()
|
| | | {
|
| | | GraphicsUtils.Destroy(m_Material);
|
| | | GraphicsUtils.Destroy(m_HistogramTexture);
|
| | |
|
| | | if (m_Buffer != null)
|
| | | m_Buffer.Release();
|
| | |
|
| | | m_Material = null;
|
| | | m_HistogramTexture = null;
|
| | | m_Buffer = null;
|
| | | }
|
| | |
|
| | | public override bool IsSupported()
|
| | | {
|
| | | return m_ComputeShader != null && GraphicsUtils.supportsDX11;
|
| | | }
|
| | |
|
| | | public override GUIContent GetMonitorTitle()
|
| | | {
|
| | | return s_MonitorTitle;
|
| | | }
|
| | |
|
| | | public override void OnMonitorSettings()
|
| | | {
|
| | | EditorGUI.BeginChangeCheck();
|
| | |
|
| | | bool refreshOnPlay = m_MonitorSettings.refreshOnPlay;
|
| | | var mode = m_MonitorSettings.histogramMode;
|
| | |
|
| | | refreshOnPlay = GUILayout.Toggle(refreshOnPlay, new GUIContent(FxStyles.playIcon, "Keep refreshing the histogram in play mode; this may impact performances."), FxStyles.preButton);
|
| | | mode = (HistogramMode)EditorGUILayout.EnumPopup(mode, FxStyles.preDropdown, GUILayout.MaxWidth(100f));
|
| | |
|
| | | if (EditorGUI.EndChangeCheck())
|
| | | {
|
| | | Undo.RecordObject(m_BaseEditor.serializedObject.targetObject, "Histogram Settings Changed");
|
| | | m_MonitorSettings.refreshOnPlay = refreshOnPlay;
|
| | | m_MonitorSettings.histogramMode = mode;
|
| | | InternalEditorUtility.RepaintAllViews();
|
| | | }
|
| | | }
|
| | |
|
| | | public override void OnMonitorGUI(Rect r)
|
| | | {
|
| | | if (Event.current.type == EventType.Repaint)
|
| | | {
|
| | | // If m_MonitorAreaRect isn't set the preview was just opened so refresh the render to get the histogram data
|
| | | if (Mathf.Approximately(m_MonitorAreaRect.width, 0) && Mathf.Approximately(m_MonitorAreaRect.height, 0))
|
| | | InternalEditorUtility.RepaintAllViews();
|
| | |
|
| | | // Sizing
|
| | | float width = m_HistogramTexture != null
|
| | | ? Mathf.Min(m_HistogramTexture.width, r.width - 65f)
|
| | | : r.width;
|
| | | float height = m_HistogramTexture != null
|
| | | ? Mathf.Min(m_HistogramTexture.height, r.height - 45f)
|
| | | : r.height;
|
| | |
|
| | | m_MonitorAreaRect = new Rect(
|
| | | Mathf.Floor(r.x + r.width / 2f - width / 2f),
|
| | | Mathf.Floor(r.y + r.height / 2f - height / 2f - 5f),
|
| | | width, height
|
| | | );
|
| | |
|
| | | if (m_HistogramTexture != null)
|
| | | {
|
| | | Graphics.DrawTexture(m_MonitorAreaRect, m_HistogramTexture);
|
| | |
|
| | | var color = Color.white;
|
| | | const float kTickSize = 5f;
|
| | |
|
| | | // Rect, lines & ticks points
|
| | | if (m_MonitorSettings.histogramMode == HistogramMode.RGBSplit)
|
| | | {
|
| | | // A B C D E
|
| | | // N F
|
| | | // M G
|
| | | // L K J I H
|
| | |
|
| | | var A = new Vector3(m_MonitorAreaRect.x - 1f, m_MonitorAreaRect.y - 1f);
|
| | | var E = new Vector3(A.x + m_MonitorAreaRect.width + 2f, m_MonitorAreaRect.y - 1f);
|
| | | var H = new Vector3(E.x, E.y + m_MonitorAreaRect.height + 2f);
|
| | | var L = new Vector3(A.x, H.y);
|
| | |
|
| | | var N = new Vector3(A.x, A.y + (L.y - A.y) / 3f);
|
| | | var M = new Vector3(A.x, A.y + (L.y - A.y) * 2f / 3f);
|
| | | var F = new Vector3(E.x, E.y + (H.y - E.y) / 3f);
|
| | | var G = new Vector3(E.x, E.y + (H.y - E.y) * 2f / 3f);
|
| | |
|
| | | var C = new Vector3(A.x + (E.x - A.x) / 2f, A.y);
|
| | | var J = new Vector3(L.x + (H.x - L.x) / 2f, L.y);
|
| | |
|
| | | var B = new Vector3(A.x + (C.x - A.x) / 2f, A.y);
|
| | | var D = new Vector3(C.x + (E.x - C.x) / 2f, C.y);
|
| | | var I = new Vector3(J.x + (H.x - J.x) / 2f, J.y);
|
| | | var K = new Vector3(L.x + (J.x - L.x) / 2f, L.y);
|
| | |
|
| | | // Borders
|
| | | Handles.color = color;
|
| | | Handles.DrawLine(A, E);
|
| | | Handles.DrawLine(E, H);
|
| | | Handles.DrawLine(H, L);
|
| | | Handles.DrawLine(L, new Vector3(A.x, A.y - 1f));
|
| | |
|
| | | // Vertical ticks
|
| | | Handles.DrawLine(A, new Vector3(A.x - kTickSize, A.y));
|
| | | Handles.DrawLine(N, new Vector3(N.x - kTickSize, N.y));
|
| | | Handles.DrawLine(M, new Vector3(M.x - kTickSize, M.y));
|
| | | Handles.DrawLine(L, new Vector3(L.x - kTickSize, L.y));
|
| | |
|
| | | Handles.DrawLine(E, new Vector3(E.x + kTickSize, E.y));
|
| | | Handles.DrawLine(F, new Vector3(F.x + kTickSize, F.y));
|
| | | Handles.DrawLine(G, new Vector3(G.x + kTickSize, G.y));
|
| | | Handles.DrawLine(H, new Vector3(H.x + kTickSize, H.y));
|
| | |
|
| | | // Horizontal ticks
|
| | | Handles.DrawLine(A, new Vector3(A.x, A.y - kTickSize));
|
| | | Handles.DrawLine(B, new Vector3(B.x, B.y - kTickSize));
|
| | | Handles.DrawLine(C, new Vector3(C.x, C.y - kTickSize));
|
| | | Handles.DrawLine(D, new Vector3(D.x, D.y - kTickSize));
|
| | | Handles.DrawLine(E, new Vector3(E.x, E.y - kTickSize));
|
| | |
|
| | | Handles.DrawLine(L, new Vector3(L.x, L.y + kTickSize));
|
| | | Handles.DrawLine(K, new Vector3(K.x, K.y + kTickSize));
|
| | | Handles.DrawLine(J, new Vector3(J.x, J.y + kTickSize));
|
| | | Handles.DrawLine(I, new Vector3(I.x, I.y + kTickSize));
|
| | | Handles.DrawLine(H, new Vector3(H.x, H.y + kTickSize));
|
| | |
|
| | | // Separators
|
| | | Handles.DrawLine(N, F);
|
| | | Handles.DrawLine(M, G);
|
| | |
|
| | | // Labels
|
| | | GUI.color = color;
|
| | | GUI.Label(new Rect(L.x - 15f, L.y + kTickSize - 4f, 30f, 30f), "0.0", FxStyles.tickStyleCenter);
|
| | | GUI.Label(new Rect(J.x - 15f, J.y + kTickSize - 4f, 30f, 30f), "0.5", FxStyles.tickStyleCenter);
|
| | | GUI.Label(new Rect(H.x - 15f, H.y + kTickSize - 4f, 30f, 30f), "1.0", FxStyles.tickStyleCenter);
|
| | | }
|
| | | else
|
| | | {
|
| | | // A B C D E
|
| | | // P F
|
| | | // O G
|
| | | // N H
|
| | | // M L K J I
|
| | |
|
| | | var A = new Vector3(m_MonitorAreaRect.x, m_MonitorAreaRect.y);
|
| | | var E = new Vector3(A.x + m_MonitorAreaRect.width + 1f, m_MonitorAreaRect.y);
|
| | | var I = new Vector3(E.x, E.y + m_MonitorAreaRect.height + 1f);
|
| | | var M = new Vector3(A.x, I.y);
|
| | |
|
| | | var C = new Vector3(A.x + (E.x - A.x) / 2f, A.y);
|
| | | var G = new Vector3(E.x, E.y + (I.y - E.y) / 2f);
|
| | | var K = new Vector3(M.x + (I.x - M.x) / 2f, M.y);
|
| | | var O = new Vector3(A.x, A.y + (M.y - A.y) / 2f);
|
| | |
|
| | | var P = new Vector3(A.x, A.y + (O.y - A.y) / 2f);
|
| | | var F = new Vector3(E.x, E.y + (G.y - E.y) / 2f);
|
| | | var N = new Vector3(A.x, O.y + (M.y - O.y) / 2f);
|
| | | var H = new Vector3(E.x, G.y + (I.y - G.y) / 2f);
|
| | |
|
| | | var B = new Vector3(A.x + (C.x - A.x) / 2f, A.y);
|
| | | var L = new Vector3(M.x + (K.x - M.x) / 2f, M.y);
|
| | | var D = new Vector3(C.x + (E.x - C.x) / 2f, A.y);
|
| | | var J = new Vector3(K.x + (I.x - K.x) / 2f, M.y);
|
| | |
|
| | | // Borders
|
| | | Handles.color = color;
|
| | | Handles.DrawLine(A, E);
|
| | | Handles.DrawLine(E, I);
|
| | | Handles.DrawLine(I, M);
|
| | | Handles.DrawLine(M, new Vector3(A.x, A.y - 1f));
|
| | |
|
| | | // Vertical ticks
|
| | | Handles.DrawLine(A, new Vector3(A.x - kTickSize, A.y));
|
| | | Handles.DrawLine(P, new Vector3(P.x - kTickSize, P.y));
|
| | | Handles.DrawLine(O, new Vector3(O.x - kTickSize, O.y));
|
| | | Handles.DrawLine(N, new Vector3(N.x - kTickSize, N.y));
|
| | | Handles.DrawLine(M, new Vector3(M.x - kTickSize, M.y));
|
| | |
|
| | | Handles.DrawLine(E, new Vector3(E.x + kTickSize, E.y));
|
| | | Handles.DrawLine(F, new Vector3(F.x + kTickSize, F.y));
|
| | | Handles.DrawLine(G, new Vector3(G.x + kTickSize, G.y));
|
| | | Handles.DrawLine(H, new Vector3(H.x + kTickSize, H.y));
|
| | | Handles.DrawLine(I, new Vector3(I.x + kTickSize, I.y));
|
| | |
|
| | | // Horizontal ticks
|
| | | Handles.DrawLine(A, new Vector3(A.x, A.y - kTickSize));
|
| | | Handles.DrawLine(B, new Vector3(B.x, B.y - kTickSize));
|
| | | Handles.DrawLine(C, new Vector3(C.x, C.y - kTickSize));
|
| | | Handles.DrawLine(D, new Vector3(D.x, D.y - kTickSize));
|
| | | Handles.DrawLine(E, new Vector3(E.x, E.y - kTickSize));
|
| | |
|
| | | Handles.DrawLine(M, new Vector3(M.x, M.y + kTickSize));
|
| | | Handles.DrawLine(L, new Vector3(L.x, L.y + kTickSize));
|
| | | Handles.DrawLine(K, new Vector3(K.x, K.y + kTickSize));
|
| | | Handles.DrawLine(J, new Vector3(J.x, J.y + kTickSize));
|
| | | Handles.DrawLine(I, new Vector3(I.x, I.y + kTickSize));
|
| | |
|
| | | // Labels
|
| | | GUI.color = color;
|
| | | GUI.Label(new Rect(A.x - kTickSize - 34f, A.y - 15f, 30f, 30f), "1.0", FxStyles.tickStyleRight);
|
| | | GUI.Label(new Rect(O.x - kTickSize - 34f, O.y - 15f, 30f, 30f), "0.5", FxStyles.tickStyleRight);
|
| | | GUI.Label(new Rect(M.x - kTickSize - 34f, M.y - 15f, 30f, 30f), "0.0", FxStyles.tickStyleRight);
|
| | |
|
| | | GUI.Label(new Rect(E.x + kTickSize + 4f, E.y - 15f, 30f, 30f), "1.0", FxStyles.tickStyleLeft);
|
| | | GUI.Label(new Rect(G.x + kTickSize + 4f, G.y - 15f, 30f, 30f), "0.5", FxStyles.tickStyleLeft);
|
| | | GUI.Label(new Rect(I.x + kTickSize + 4f, I.y - 15f, 30f, 30f), "0.0", FxStyles.tickStyleLeft);
|
| | |
|
| | | GUI.Label(new Rect(M.x - 15f, M.y + kTickSize - 4f, 30f, 30f), "0.0", FxStyles.tickStyleCenter);
|
| | | GUI.Label(new Rect(K.x - 15f, K.y + kTickSize - 4f, 30f, 30f), "0.5", FxStyles.tickStyleCenter);
|
| | | GUI.Label(new Rect(I.x - 15f, I.y + kTickSize - 4f, 30f, 30f), "1.0", FxStyles.tickStyleCenter);
|
| | | }
|
| | | }
|
| | | }
|
| | | }
|
| | |
|
| | | public override void OnFrameData(RenderTexture source)
|
| | | {
|
| | | if (Application.isPlaying && !m_MonitorSettings.refreshOnPlay)
|
| | | return;
|
| | |
|
| | | if (Mathf.Approximately(m_MonitorAreaRect.width, 0) || Mathf.Approximately(m_MonitorAreaRect.height, 0))
|
| | | return;
|
| | |
|
| | | float ratio = (float)source.width / (float)source.height;
|
| | | int h = 512;
|
| | | int w = Mathf.FloorToInt(h * ratio);
|
| | |
|
| | | var rt = RenderTexture.GetTemporary(w, h, 0, source.format);
|
| | | Graphics.Blit(source, rt);
|
| | | ComputeHistogram(rt);
|
| | | m_BaseEditor.Repaint();
|
| | | RenderTexture.ReleaseTemporary(rt);
|
| | | }
|
| | |
|
| | | void CreateBuffer(int width, int height)
|
| | | {
|
| | | m_Buffer = new ComputeBuffer(width * height, sizeof(uint) << 2);
|
| | | }
|
| | |
|
| | | void ComputeHistogram(RenderTexture source)
|
| | | {
|
| | | if (m_Buffer == null)
|
| | | {
|
| | | CreateBuffer(256, 1);
|
| | | }
|
| | | else if (m_Buffer.count != 256)
|
| | | {
|
| | | m_Buffer.Release();
|
| | | CreateBuffer(256, 1);
|
| | | }
|
| | |
|
| | | if (m_Material == null)
|
| | | {
|
| | | m_Material = new Material(Shader.Find("Hidden/Post FX/Monitors/Histogram Render")) { hideFlags = HideFlags.DontSave };
|
| | | }
|
| | |
|
| | | var channels = Vector4.zero;
|
| | | switch (m_MonitorSettings.histogramMode)
|
| | | {
|
| | | case HistogramMode.Red: channels.x = 1f; break;
|
| | | case HistogramMode.Green: channels.y = 1f; break;
|
| | | case HistogramMode.Blue: channels.z = 1f; break;
|
| | | case HistogramMode.Luminance: channels.w = 1f; break;
|
| | | default: channels = new Vector4(1f, 1f, 1f, 0f); break;
|
| | | }
|
| | |
|
| | | var cs = m_ComputeShader;
|
| | |
|
| | | int kernel = cs.FindKernel("KHistogramClear");
|
| | | cs.SetBuffer(kernel, "_Histogram", m_Buffer);
|
| | | cs.Dispatch(kernel, 1, 1, 1);
|
| | |
|
| | | kernel = cs.FindKernel("KHistogramGather");
|
| | | cs.SetBuffer(kernel, "_Histogram", m_Buffer);
|
| | | cs.SetTexture(kernel, "_Source", source);
|
| | | cs.SetInt("_IsLinear", GraphicsUtils.isLinearColorSpace ? 1 : 0);
|
| | | cs.SetVector("_Res", new Vector4(source.width, source.height, 0f, 0f));
|
| | | cs.SetVector("_Channels", channels);
|
| | | cs.Dispatch(kernel, Mathf.CeilToInt(source.width / 16f), Mathf.CeilToInt(source.height / 16f), 1);
|
| | |
|
| | | kernel = cs.FindKernel("KHistogramScale");
|
| | | cs.SetBuffer(kernel, "_Histogram", m_Buffer);
|
| | | cs.Dispatch(kernel, 1, 1, 1);
|
| | |
|
| | | if (m_HistogramTexture == null || m_HistogramTexture.width != source.width || m_HistogramTexture.height != source.height)
|
| | | {
|
| | | GraphicsUtils.Destroy(m_HistogramTexture);
|
| | | m_HistogramTexture = new RenderTexture(source.width, source.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear)
|
| | | {
|
| | | hideFlags = HideFlags.DontSave,
|
| | | wrapMode = TextureWrapMode.Clamp,
|
| | | filterMode = FilterMode.Bilinear
|
| | | };
|
| | | }
|
| | |
|
| | | m_Material.SetBuffer("_Histogram", m_Buffer);
|
| | | m_Material.SetVector("_Size", new Vector2(m_HistogramTexture.width, m_HistogramTexture.height));
|
| | | m_Material.SetColor("_ColorR", new Color(1f, 0f, 0f, 1f));
|
| | | m_Material.SetColor("_ColorG", new Color(0f, 1f, 0f, 1f));
|
| | | m_Material.SetColor("_ColorB", new Color(0f, 0f, 1f, 1f));
|
| | | m_Material.SetColor("_ColorL", new Color(1f, 1f, 1f, 1f));
|
| | | m_Material.SetInt("_Channel", (int)m_MonitorSettings.histogramMode);
|
| | |
|
| | | int pass = 0;
|
| | | if (m_MonitorSettings.histogramMode == HistogramMode.RGBMerged)
|
| | | pass = 1;
|
| | | else if (m_MonitorSettings.histogramMode == HistogramMode.RGBSplit)
|
| | | pass = 2;
|
| | |
|
| | | Graphics.Blit(null, m_HistogramTexture, m_Material, pass);
|
| | | }
|
| | | }
|
| | | }
|