You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

257 lines
11 KiB

  1. using UnityEditorInternal;
  2. using UnityEngine;
  3. using UnityEngine.PostProcessing;
  4. namespace UnityEditor.PostProcessing
  5. {
  6. public class ParadeMonitor : PostProcessingMonitor
  7. {
  8. static GUIContent s_MonitorTitle = new GUIContent("Parade");
  9. ComputeShader m_ComputeShader;
  10. ComputeBuffer m_Buffer;
  11. Material m_Material;
  12. RenderTexture m_WaveformTexture;
  13. Rect m_MonitorAreaRect;
  14. public ParadeMonitor()
  15. {
  16. m_ComputeShader = EditorResources.Load<ComputeShader>("Monitors/WaveformCompute.compute");
  17. }
  18. public override void Dispose()
  19. {
  20. GraphicsUtils.Destroy(m_Material);
  21. GraphicsUtils.Destroy(m_WaveformTexture);
  22. if (m_Buffer != null)
  23. m_Buffer.Release();
  24. m_Material = null;
  25. m_WaveformTexture = null;
  26. m_Buffer = null;
  27. }
  28. public override bool IsSupported()
  29. {
  30. return m_ComputeShader != null && GraphicsUtils.supportsDX11;
  31. }
  32. public override GUIContent GetMonitorTitle()
  33. {
  34. return s_MonitorTitle;
  35. }
  36. public override void OnMonitorSettings()
  37. {
  38. EditorGUI.BeginChangeCheck();
  39. bool refreshOnPlay = m_MonitorSettings.refreshOnPlay;
  40. float exposure = m_MonitorSettings.paradeExposure;
  41. refreshOnPlay = GUILayout.Toggle(refreshOnPlay, new GUIContent(FxStyles.playIcon, "Keep refreshing the parade in play mode; this may impact performances."), FxStyles.preButton);
  42. exposure = GUILayout.HorizontalSlider(exposure, 0.05f, 0.3f, FxStyles.preSlider, FxStyles.preSliderThumb, GUILayout.Width(40f));
  43. if (EditorGUI.EndChangeCheck())
  44. {
  45. Undo.RecordObject(m_BaseEditor.serializedObject.targetObject, "Parade Settings Changed");
  46. m_MonitorSettings.refreshOnPlay = refreshOnPlay;
  47. m_MonitorSettings.paradeExposure = exposure;
  48. InternalEditorUtility.RepaintAllViews();
  49. }
  50. }
  51. public override void OnMonitorGUI(Rect r)
  52. {
  53. if (Event.current.type == EventType.Repaint)
  54. {
  55. // If m_MonitorAreaRect isn't set the preview was just opened so refresh the render to get the waveform data
  56. if (Mathf.Approximately(m_MonitorAreaRect.width, 0) && Mathf.Approximately(m_MonitorAreaRect.height, 0))
  57. InternalEditorUtility.RepaintAllViews();
  58. // Sizing
  59. float width = m_WaveformTexture != null
  60. ? Mathf.Min(m_WaveformTexture.width, r.width - 65f)
  61. : r.width;
  62. float height = m_WaveformTexture != null
  63. ? Mathf.Min(m_WaveformTexture.height, r.height - 45f)
  64. : r.height;
  65. m_MonitorAreaRect = new Rect(
  66. Mathf.Floor(r.x + r.width / 2f - width / 2f),
  67. Mathf.Floor(r.y + r.height / 2f - height / 2f - 5f),
  68. width, height
  69. );
  70. if (m_WaveformTexture != null)
  71. {
  72. m_Material.SetFloat("_Exposure", m_MonitorSettings.paradeExposure);
  73. var oldActive = RenderTexture.active;
  74. Graphics.Blit(null, m_WaveformTexture, m_Material, 0);
  75. RenderTexture.active = oldActive;
  76. Graphics.DrawTexture(m_MonitorAreaRect, m_WaveformTexture);
  77. var color = Color.white;
  78. const float kTickSize = 5f;
  79. // Rect, lines & ticks points
  80. // A O B P C Q D
  81. // N E
  82. // M F
  83. // L G
  84. // K T J S I R H
  85. var A = new Vector3(m_MonitorAreaRect.x, m_MonitorAreaRect.y);
  86. var D = new Vector3(A.x + m_MonitorAreaRect.width + 1f, m_MonitorAreaRect.y);
  87. var H = new Vector3(D.x, D.y + m_MonitorAreaRect.height + 1f);
  88. var K = new Vector3(A.x, H.y);
  89. var F = new Vector3(D.x, D.y + (H.y - D.y) / 2f);
  90. var M = new Vector3(A.x, A.y + (K.y - A.y) / 2f);
  91. var B = new Vector3(A.x + (D.x - A.x) / 3f, A.y);
  92. var C = new Vector3(A.x + (D.x - A.x) * 2f / 3f, A.y);
  93. var I = new Vector3(K.x + (H.x - K.x) * 2f / 3f, K.y);
  94. var J = new Vector3(K.x + (H.x - K.x) / 3f, K.y);
  95. var N = new Vector3(A.x, A.y + (M.y - A.y) / 2f);
  96. var L = new Vector3(A.x, M.y + (K.y - M.y) / 2f);
  97. var E = new Vector3(D.x, D.y + (F.y - D.y) / 2f);
  98. var G = new Vector3(D.x, F.y + (H.y - F.y) / 2f);
  99. var O = new Vector3(A.x + (B.x - A.x) / 2f, A.y);
  100. var P = new Vector3(B.x + (C.x - B.x) / 2f, B.y);
  101. var Q = new Vector3(C.x + (D.x - C.x) / 2f, C.y);
  102. var R = new Vector3(I.x + (H.x - I.x) / 2f, I.y);
  103. var S = new Vector3(J.x + (I.x - J.x) / 2f, J.y);
  104. var T = new Vector3(K.x + (J.x - K.x) / 2f, K.y);
  105. // Borders
  106. Handles.color = color;
  107. Handles.DrawLine(A, D);
  108. Handles.DrawLine(D, H);
  109. Handles.DrawLine(H, K);
  110. Handles.DrawLine(K, new Vector3(A.x, A.y - 1f));
  111. Handles.DrawLine(B, J);
  112. Handles.DrawLine(C, I);
  113. // Vertical ticks
  114. Handles.DrawLine(A, new Vector3(A.x - kTickSize, A.y));
  115. Handles.DrawLine(N, new Vector3(N.x - kTickSize, N.y));
  116. Handles.DrawLine(M, new Vector3(M.x - kTickSize, M.y));
  117. Handles.DrawLine(L, new Vector3(L.x - kTickSize, L.y));
  118. Handles.DrawLine(K, new Vector3(K.x - kTickSize, K.y));
  119. Handles.DrawLine(D, new Vector3(D.x + kTickSize, D.y));
  120. Handles.DrawLine(E, new Vector3(E.x + kTickSize, E.y));
  121. Handles.DrawLine(F, new Vector3(F.x + kTickSize, F.y));
  122. Handles.DrawLine(G, new Vector3(G.x + kTickSize, G.y));
  123. Handles.DrawLine(H, new Vector3(H.x + kTickSize, H.y));
  124. // Horizontal ticks
  125. Handles.DrawLine(A, new Vector3(A.x, A.y - kTickSize));
  126. Handles.DrawLine(B, new Vector3(B.x, B.y - kTickSize));
  127. Handles.DrawLine(C, new Vector3(C.x, C.y - kTickSize));
  128. Handles.DrawLine(D, new Vector3(D.x, D.y - kTickSize));
  129. Handles.DrawLine(O, new Vector3(O.x, O.y - kTickSize));
  130. Handles.DrawLine(P, new Vector3(P.x, P.y - kTickSize));
  131. Handles.DrawLine(Q, new Vector3(Q.x, Q.y - kTickSize));
  132. Handles.DrawLine(H, new Vector3(H.x, H.y + kTickSize));
  133. Handles.DrawLine(I, new Vector3(I.x, I.y + kTickSize));
  134. Handles.DrawLine(J, new Vector3(J.x, J.y + kTickSize));
  135. Handles.DrawLine(K, new Vector3(K.x, K.y + kTickSize));
  136. Handles.DrawLine(R, new Vector3(R.x, R.y + kTickSize));
  137. Handles.DrawLine(S, new Vector3(S.x, S.y + kTickSize));
  138. Handles.DrawLine(T, new Vector3(T.x, T.y + kTickSize));
  139. // Labels
  140. GUI.color = color;
  141. GUI.Label(new Rect(A.x - kTickSize - 34f, A.y - 15f, 30f, 30f), "1.0", FxStyles.tickStyleRight);
  142. GUI.Label(new Rect(M.x - kTickSize - 34f, M.y - 15f, 30f, 30f), "0.5", FxStyles.tickStyleRight);
  143. GUI.Label(new Rect(K.x - kTickSize - 34f, K.y - 15f, 30f, 30f), "0.0", FxStyles.tickStyleRight);
  144. GUI.Label(new Rect(D.x + kTickSize + 4f, D.y - 15f, 30f, 30f), "1.0", FxStyles.tickStyleLeft);
  145. GUI.Label(new Rect(F.x + kTickSize + 4f, F.y - 15f, 30f, 30f), "0.5", FxStyles.tickStyleLeft);
  146. GUI.Label(new Rect(H.x + kTickSize + 4f, H.y - 15f, 30f, 30f), "0.0", FxStyles.tickStyleLeft);
  147. }
  148. }
  149. }
  150. public override void OnFrameData(RenderTexture source)
  151. {
  152. if (Application.isPlaying && !m_MonitorSettings.refreshOnPlay)
  153. return;
  154. if (Mathf.Approximately(m_MonitorAreaRect.width, 0) || Mathf.Approximately(m_MonitorAreaRect.height, 0))
  155. return;
  156. float ratio = ((float)source.width / (float)source.height) / 3f;
  157. int h = 384;
  158. int w = Mathf.FloorToInt(h * ratio);
  159. var rt = RenderTexture.GetTemporary(w, h, 0, source.format);
  160. Graphics.Blit(source, rt);
  161. ComputeWaveform(rt);
  162. m_BaseEditor.Repaint();
  163. RenderTexture.ReleaseTemporary(rt);
  164. }
  165. void CreateBuffer(int width, int height)
  166. {
  167. m_Buffer = new ComputeBuffer(width * height, sizeof(uint) << 2);
  168. }
  169. void ComputeWaveform(RenderTexture source)
  170. {
  171. if (m_Buffer == null)
  172. {
  173. CreateBuffer(source.width, source.height);
  174. }
  175. else if (m_Buffer.count != (source.width * source.height))
  176. {
  177. m_Buffer.Release();
  178. CreateBuffer(source.width, source.height);
  179. }
  180. var channels = m_MonitorSettings.waveformY
  181. ? new Vector4(0f, 0f, 0f, 1f)
  182. : new Vector4(m_MonitorSettings.waveformR ? 1f : 0f, m_MonitorSettings.waveformG ? 1f : 0f, m_MonitorSettings.waveformB ? 1f : 0f, 0f);
  183. var cs = m_ComputeShader;
  184. int kernel = cs.FindKernel("KWaveformClear");
  185. cs.SetBuffer(kernel, "_Waveform", m_Buffer);
  186. cs.Dispatch(kernel, source.width, 1, 1);
  187. kernel = cs.FindKernel("KWaveform");
  188. cs.SetBuffer(kernel, "_Waveform", m_Buffer);
  189. cs.SetTexture(kernel, "_Source", source);
  190. cs.SetInt("_IsLinear", GraphicsUtils.isLinearColorSpace ? 1 : 0);
  191. cs.SetVector("_Channels", channels);
  192. cs.Dispatch(kernel, source.width, 1, 1);
  193. if (m_WaveformTexture == null || m_WaveformTexture.width != (source.width * 3) || m_WaveformTexture.height != source.height)
  194. {
  195. GraphicsUtils.Destroy(m_WaveformTexture);
  196. m_WaveformTexture = new RenderTexture(source.width * 3, source.height, 0, RenderTextureFormat.ARGB32, RenderTextureReadWrite.Linear)
  197. {
  198. hideFlags = HideFlags.DontSave,
  199. wrapMode = TextureWrapMode.Clamp,
  200. filterMode = FilterMode.Bilinear
  201. };
  202. }
  203. if (m_Material == null)
  204. m_Material = new Material(Shader.Find("Hidden/Post FX/Monitors/Parade Render")) { hideFlags = HideFlags.DontSave };
  205. m_Material.SetBuffer("_Waveform", m_Buffer);
  206. m_Material.SetVector("_Size", new Vector2(m_WaveformTexture.width, m_WaveformTexture.height));
  207. m_Material.SetVector("_Channels", channels);
  208. }
  209. }
  210. }