DebugDisplaySettingsRendering.cs 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323
  1. using System;
  2. using UnityEngine;
  3. using NameAndTooltip = UnityEngine.Rendering.DebugUI.Widget.NameAndTooltip;
  4. namespace UnityEngine.Rendering.Universal
  5. {
  6. class DebugDisplaySettingsRendering : IDebugDisplaySettingsData
  7. {
  8. // Under the hood, the implementation uses a single enum (DebugSceneOverrideMode). For UI, we have split
  9. // this enum into WireframeMode and a separate Overdraw boolean.
  10. enum WireframeMode
  11. {
  12. None,
  13. Wireframe,
  14. SolidWireframe,
  15. ShadedWireframe,
  16. }
  17. WireframeMode m_WireframeMode = WireframeMode.None;
  18. WireframeMode wireframeMode
  19. {
  20. get => m_WireframeMode;
  21. set
  22. {
  23. m_WireframeMode = value;
  24. UpdateDebugSceneOverrideMode();
  25. }
  26. }
  27. bool m_Overdraw = false;
  28. bool overdraw
  29. {
  30. get => m_Overdraw;
  31. set
  32. {
  33. m_Overdraw = value;
  34. UpdateDebugSceneOverrideMode();
  35. }
  36. }
  37. void UpdateDebugSceneOverrideMode()
  38. {
  39. switch (wireframeMode)
  40. {
  41. case WireframeMode.Wireframe:
  42. debugSceneOverrideMode = DebugSceneOverrideMode.Wireframe;
  43. break;
  44. case WireframeMode.SolidWireframe:
  45. debugSceneOverrideMode = DebugSceneOverrideMode.SolidWireframe;
  46. break;
  47. case WireframeMode.ShadedWireframe:
  48. debugSceneOverrideMode = DebugSceneOverrideMode.ShadedWireframe;
  49. break;
  50. default:
  51. debugSceneOverrideMode = overdraw ? DebugSceneOverrideMode.Overdraw : DebugSceneOverrideMode.None;
  52. break;
  53. }
  54. }
  55. internal DebugFullScreenMode debugFullScreenMode { get; private set; } = DebugFullScreenMode.None;
  56. internal int debugFullScreenModeOutputSizeScreenPercent { get; private set; } = 50;
  57. internal DebugSceneOverrideMode debugSceneOverrideMode { get; private set; } = DebugSceneOverrideMode.None;
  58. internal DebugMipInfoMode debugMipInfoMode { get; private set; } = DebugMipInfoMode.None;
  59. internal DebugPostProcessingMode debugPostProcessingMode { get; private set; } = DebugPostProcessingMode.Auto;
  60. internal bool enableMsaa { get; private set; } = true;
  61. internal bool enableHDR { get; private set; } = true;
  62. #region Pixel validation
  63. internal DebugValidationMode validationMode { get; private set; }
  64. internal PixelValidationChannels validationChannels { get; private set; } = PixelValidationChannels.RGB;
  65. internal float ValidationRangeMin { get; private set; } = 0.0f;
  66. internal float ValidationRangeMax { get; private set; } = 1.0f;
  67. static class Strings
  68. {
  69. public const string RangeValidationSettingsContainerName = "Pixel Range Settings";
  70. public static readonly NameAndTooltip MapOverlays = new() { name = "Map Overlays", tooltip = "Overlays render pipeline textures to validate the scene." };
  71. public static readonly NameAndTooltip MapSize = new() { name = "Map Size", tooltip = "Set the size of the render pipeline texture in the scene." };
  72. public static readonly NameAndTooltip AdditionalWireframeModes = new() { name = "Additional Wireframe Modes", tooltip = "Debug the scene with additional wireframe shader views that are different from those in the scene view." };
  73. public static readonly NameAndTooltip WireframeNotSupportedWarning = new() { name = "Warning: This platform might not support wireframe rendering.", tooltip = "Some platforms, for example, mobile platforms using OpenGL ES and Vulkan, might not support wireframe rendering." };
  74. public static readonly NameAndTooltip Overdraw = new() { name = "Overdraw", tooltip = "Debug anywhere pixels are overdrawn on top of each other." };
  75. public static readonly NameAndTooltip PostProcessing = new() { name = "Post-processing", tooltip = "Override the controls for Post Processing in the scene." };
  76. public static readonly NameAndTooltip MSAA = new() { name = "MSAA", tooltip = "Use the checkbox to disable MSAA in the scene." };
  77. public static readonly NameAndTooltip HDR = new() { name = "HDR", tooltip = "Use the checkbox to disable High Dynamic Range in the scene." };
  78. public static readonly NameAndTooltip PixelValidationMode = new() { name = "Pixel Validation Mode", tooltip = "Choose between modes that validate pixel on screen." };
  79. public static readonly NameAndTooltip Channels = new() { name = "Channels", tooltip = "Choose the texture channel used to validate the scene." };
  80. public static readonly NameAndTooltip ValueRangeMin = new() { name = "Value Range Min", tooltip = "Any values set below this field will be considered invalid and will appear red on screen." };
  81. public static readonly NameAndTooltip ValueRangeMax = new() { name = "Value Range Max", tooltip = "Any values set above this field will be considered invalid and will appear blue on screen." };
  82. }
  83. #endregion
  84. internal static class WidgetFactory
  85. {
  86. internal static DebugUI.Widget CreateMapOverlays(DebugDisplaySettingsRendering data) => new DebugUI.EnumField
  87. {
  88. nameAndTooltip = Strings.MapOverlays,
  89. autoEnum = typeof(DebugFullScreenMode),
  90. getter = () => (int)data.debugFullScreenMode,
  91. setter = (value) => { },
  92. getIndex = () => (int)data.debugFullScreenMode,
  93. setIndex = (value) => data.debugFullScreenMode = (DebugFullScreenMode)value
  94. };
  95. internal static DebugUI.Widget CreateMapOverlaySize(DebugDisplaySettingsRendering data) => new DebugUI.Container()
  96. {
  97. children =
  98. {
  99. new DebugUI.IntField
  100. {
  101. nameAndTooltip = Strings.MapSize,
  102. getter = () => data.debugFullScreenModeOutputSizeScreenPercent,
  103. setter = value => data.debugFullScreenModeOutputSizeScreenPercent = value,
  104. incStep = 10,
  105. min = () => 0,
  106. max = () => 100
  107. }
  108. }
  109. };
  110. internal static DebugUI.Widget CreateAdditionalWireframeShaderViews(DebugDisplaySettingsRendering data) => new DebugUI.EnumField
  111. {
  112. nameAndTooltip = Strings.AdditionalWireframeModes,
  113. autoEnum = typeof(WireframeMode),
  114. getter = () => (int)data.wireframeMode,
  115. setter = (value) => { },
  116. getIndex = () => (int)data.wireframeMode,
  117. setIndex = (value) => data.wireframeMode = (WireframeMode)value,
  118. onValueChanged = (_, _) => DebugManager.instance.ReDrawOnScreenDebug()
  119. };
  120. internal static DebugUI.Widget CreateWireframeNotSupportedWarning(DebugDisplaySettingsRendering data) => new DebugUI.MessageBox
  121. {
  122. nameAndTooltip = Strings.WireframeNotSupportedWarning,
  123. style = DebugUI.MessageBox.Style.Warning,
  124. isHiddenCallback = () =>
  125. {
  126. #if UNITY_EDITOR
  127. return true;
  128. #else
  129. switch (SystemInfo.graphicsDeviceType)
  130. {
  131. case GraphicsDeviceType.OpenGLES2:
  132. case GraphicsDeviceType.OpenGLES3:
  133. case GraphicsDeviceType.Vulkan:
  134. return data.wireframeMode == WireframeMode.None;
  135. default:
  136. return true;
  137. }
  138. #endif
  139. }
  140. };
  141. internal static DebugUI.Widget CreateOverdraw(DebugDisplaySettingsRendering data) => new DebugUI.BoolField
  142. {
  143. nameAndTooltip = Strings.Overdraw,
  144. getter = () => data.overdraw,
  145. setter = (value) => data.overdraw = value
  146. };
  147. internal static DebugUI.Widget CreatePostProcessing(DebugDisplaySettingsRendering data) => new DebugUI.EnumField
  148. {
  149. nameAndTooltip = Strings.PostProcessing,
  150. autoEnum = typeof(DebugPostProcessingMode),
  151. getter = () => (int)data.debugPostProcessingMode,
  152. setter = (value) => data.debugPostProcessingMode = (DebugPostProcessingMode)value,
  153. getIndex = () => (int)data.debugPostProcessingMode,
  154. setIndex = (value) => data.debugPostProcessingMode = (DebugPostProcessingMode)value
  155. };
  156. internal static DebugUI.Widget CreateMSAA(DebugDisplaySettingsRendering data) => new DebugUI.BoolField
  157. {
  158. nameAndTooltip = Strings.MSAA,
  159. getter = () => data.enableMsaa,
  160. setter = (value) => data.enableMsaa = value
  161. };
  162. internal static DebugUI.Widget CreateHDR(DebugDisplaySettingsRendering data) => new DebugUI.BoolField
  163. {
  164. nameAndTooltip = Strings.HDR,
  165. getter = () => data.enableHDR,
  166. setter = (value) => data.enableHDR = value
  167. };
  168. internal static DebugUI.Widget CreatePixelValidationMode(DebugDisplaySettingsRendering data) => new DebugUI.EnumField
  169. {
  170. nameAndTooltip = Strings.PixelValidationMode,
  171. autoEnum = typeof(DebugValidationMode),
  172. getter = () => (int)data.validationMode,
  173. setter = (value) => { },
  174. getIndex = () => (int)data.validationMode,
  175. setIndex = (value) => data.validationMode = (DebugValidationMode)value,
  176. onValueChanged = (_, _) => DebugManager.instance.ReDrawOnScreenDebug()
  177. };
  178. internal static DebugUI.Widget CreatePixelValidationChannels(DebugDisplaySettingsRendering data) => new DebugUI.EnumField
  179. {
  180. nameAndTooltip = Strings.Channels,
  181. autoEnum = typeof(PixelValidationChannels),
  182. getter = () => (int)data.validationChannels,
  183. setter = (value) => { },
  184. getIndex = () => (int)data.validationChannels,
  185. setIndex = (value) => data.validationChannels = (PixelValidationChannels)value
  186. };
  187. internal static DebugUI.Widget CreatePixelValueRangeMin(DebugDisplaySettingsRendering data) => new DebugUI.FloatField
  188. {
  189. nameAndTooltip = Strings.ValueRangeMin,
  190. getter = () => data.ValidationRangeMin,
  191. setter = (value) => data.ValidationRangeMin = value,
  192. incStep = 0.01f
  193. };
  194. internal static DebugUI.Widget CreatePixelValueRangeMax(DebugDisplaySettingsRendering data) => new DebugUI.FloatField
  195. {
  196. nameAndTooltip = Strings.ValueRangeMax,
  197. getter = () => data.ValidationRangeMax,
  198. setter = (value) => data.ValidationRangeMax = value,
  199. incStep = 0.01f
  200. };
  201. }
  202. private class SettingsPanel : DebugDisplaySettingsPanel
  203. {
  204. public override string PanelName => "Rendering";
  205. public SettingsPanel(DebugDisplaySettingsRendering data)
  206. {
  207. AddWidget(DebugDisplaySettingsCommon.WidgetFactory.CreateMissingDebugShadersWarning());
  208. AddWidget(new DebugUI.Foldout
  209. {
  210. displayName = "Rendering Debug",
  211. isHeader = true,
  212. opened = true,
  213. children =
  214. {
  215. WidgetFactory.CreateMapOverlays(data),
  216. WidgetFactory.CreateMapOverlaySize(data),
  217. WidgetFactory.CreateHDR(data),
  218. WidgetFactory.CreateMSAA(data),
  219. WidgetFactory.CreatePostProcessing(data),
  220. WidgetFactory.CreateAdditionalWireframeShaderViews(data),
  221. WidgetFactory.CreateWireframeNotSupportedWarning(data),
  222. WidgetFactory.CreateOverdraw(data)
  223. }
  224. });
  225. AddWidget(new DebugUI.Foldout
  226. {
  227. displayName = "Pixel Validation",
  228. isHeader = true,
  229. opened = true,
  230. children =
  231. {
  232. WidgetFactory.CreatePixelValidationMode(data),
  233. new DebugUI.Container()
  234. {
  235. displayName = Strings.RangeValidationSettingsContainerName,
  236. isHiddenCallback = () => data.validationMode != DebugValidationMode.HighlightOutsideOfRange,
  237. children =
  238. {
  239. WidgetFactory.CreatePixelValidationChannels(data),
  240. WidgetFactory.CreatePixelValueRangeMin(data),
  241. WidgetFactory.CreatePixelValueRangeMax(data)
  242. }
  243. }
  244. }
  245. });
  246. }
  247. }
  248. #region IDebugDisplaySettingsData
  249. public bool AreAnySettingsActive => (debugPostProcessingMode != DebugPostProcessingMode.Auto) ||
  250. (debugFullScreenMode != DebugFullScreenMode.None) ||
  251. (debugSceneOverrideMode != DebugSceneOverrideMode.None) ||
  252. (debugMipInfoMode != DebugMipInfoMode.None) ||
  253. (validationMode != DebugValidationMode.None) ||
  254. !enableMsaa ||
  255. !enableHDR;
  256. public bool IsPostProcessingAllowed => (debugPostProcessingMode != DebugPostProcessingMode.Disabled) &&
  257. (debugSceneOverrideMode == DebugSceneOverrideMode.None) &&
  258. (debugMipInfoMode == DebugMipInfoMode.None);
  259. public bool IsLightingActive => (debugSceneOverrideMode == DebugSceneOverrideMode.None) &&
  260. (debugMipInfoMode == DebugMipInfoMode.None);
  261. public bool TryGetScreenClearColor(ref Color color)
  262. {
  263. switch (debugSceneOverrideMode)
  264. {
  265. case DebugSceneOverrideMode.None:
  266. case DebugSceneOverrideMode.ShadedWireframe:
  267. return false;
  268. case DebugSceneOverrideMode.Overdraw:
  269. color = Color.black;
  270. return true;
  271. case DebugSceneOverrideMode.Wireframe:
  272. case DebugSceneOverrideMode.SolidWireframe:
  273. color = new Color(0.1f, 0.1f, 0.1f, 1.0f);
  274. return true;
  275. default:
  276. throw new ArgumentOutOfRangeException(nameof(color));
  277. } // End of switch.
  278. }
  279. public IDebugDisplaySettingsPanelDisposable CreatePanel()
  280. {
  281. return new SettingsPanel(this);
  282. }
  283. #endregion
  284. }
  285. }