Ingen beskrivning
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.

UniversalRenderPipelineAssetUI.Drawers.cs 38KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679
  1. using System;
  2. using UnityEngine;
  3. using UnityEngine.Rendering;
  4. using UnityEngine.Rendering.Universal;
  5. namespace UnityEditor.Rendering.Universal
  6. {
  7. using CED = CoreEditorDrawer<SerializedUniversalRenderPipelineAsset>;
  8. internal partial class UniversalRenderPipelineAssetUI
  9. {
  10. enum Expandable
  11. {
  12. Rendering = 1 << 1,
  13. Quality = 1 << 2,
  14. Lighting = 1 << 3,
  15. Shadows = 1 << 4,
  16. PostProcessing = 1 << 5,
  17. #if ADAPTIVE_PERFORMANCE_2_0_0_OR_NEWER
  18. AdaptivePerformance = 1 << 6,
  19. #endif
  20. Volumes = 1 << 7,
  21. }
  22. enum ExpandableAdditional
  23. {
  24. Rendering = 1 << 1,
  25. Lighting = 1 << 2,
  26. PostProcessing = 1 << 3,
  27. Shadows = 1 << 4,
  28. Quality = 1 << 5,
  29. }
  30. internal static void RegisterEditor(UniversalRenderPipelineAssetEditor editor)
  31. {
  32. k_AdditionalPropertiesState.RegisterEditor(editor);
  33. }
  34. internal static void UnregisterEditor(UniversalRenderPipelineAssetEditor editor)
  35. {
  36. k_AdditionalPropertiesState.UnregisterEditor(editor);
  37. }
  38. static bool ValidateRendererGraphicsAPIsForLightLayers(UniversalRenderPipelineAsset pipelineAsset, out string unsupportedGraphicsApisMessage)
  39. {
  40. unsupportedGraphicsApisMessage = null;
  41. BuildTarget platform = EditorUserBuildSettings.activeBuildTarget;
  42. GraphicsDeviceType[] graphicsAPIs = PlayerSettings.GetGraphicsAPIs(platform);
  43. for (int apiIndex = 0; apiIndex < graphicsAPIs.Length; apiIndex++)
  44. {
  45. if (!RenderingUtils.SupportsLightLayers(graphicsAPIs[apiIndex]))
  46. {
  47. if (unsupportedGraphicsApisMessage != null)
  48. unsupportedGraphicsApisMessage += ", ";
  49. unsupportedGraphicsApisMessage += System.String.Format("{0}", graphicsAPIs[apiIndex]);
  50. }
  51. }
  52. if (unsupportedGraphicsApisMessage != null)
  53. unsupportedGraphicsApisMessage += ".";
  54. return unsupportedGraphicsApisMessage == null;
  55. }
  56. static bool ValidateRendererGraphicsAPIs(UniversalRenderPipelineAsset pipelineAsset, out string unsupportedGraphicsApisMessage)
  57. {
  58. // Check the list of Renderers against all Graphics APIs the player is built with.
  59. unsupportedGraphicsApisMessage = null;
  60. BuildTarget platform = EditorUserBuildSettings.activeBuildTarget;
  61. GraphicsDeviceType[] graphicsAPIs = PlayerSettings.GetGraphicsAPIs(platform);
  62. int rendererCount = pipelineAsset.m_RendererDataList.Length;
  63. for (int i = 0; i < rendererCount; i++)
  64. {
  65. ScriptableRenderer renderer = pipelineAsset.GetRenderer(i);
  66. if (renderer == null)
  67. continue;
  68. GraphicsDeviceType[] unsupportedAPIs = renderer.unsupportedGraphicsDeviceTypes;
  69. for (int apiIndex = 0; apiIndex < unsupportedAPIs.Length; apiIndex++)
  70. {
  71. if (Array.FindIndex(graphicsAPIs, element => element == unsupportedAPIs[apiIndex]) >= 0)
  72. unsupportedGraphicsApisMessage += $"{renderer} at index {i} does not support {unsupportedAPIs[apiIndex]}.\n";
  73. }
  74. }
  75. return unsupportedGraphicsApisMessage == null;
  76. }
  77. static readonly ExpandedState<Expandable, UniversalRenderPipelineAsset> k_ExpandedState = new(Expandable.Rendering, "URP");
  78. readonly static AdditionalPropertiesState<ExpandableAdditional, Light> k_AdditionalPropertiesState = new(0, "URP");
  79. public static readonly CED.IDrawer Inspector = CED.Group(
  80. CED.AdditionalPropertiesFoldoutGroup(Styles.renderingSettingsText, Expandable.Rendering, k_ExpandedState, ExpandableAdditional.Rendering, k_AdditionalPropertiesState, DrawRendering, DrawRenderingAdditional),
  81. CED.FoldoutGroup(Styles.qualitySettingsText, Expandable.Quality, k_ExpandedState, DrawQuality),
  82. CED.AdditionalPropertiesFoldoutGroup(Styles.lightingSettingsText, Expandable.Lighting, k_ExpandedState, ExpandableAdditional.Lighting, k_AdditionalPropertiesState, DrawLighting, DrawLightingAdditional),
  83. CED.AdditionalPropertiesFoldoutGroup(Styles.shadowSettingsText, Expandable.Shadows, k_ExpandedState, ExpandableAdditional.Shadows, k_AdditionalPropertiesState, DrawShadows, DrawShadowsAdditional),
  84. CED.FoldoutGroup(Styles.postProcessingSettingsText, Expandable.PostProcessing, k_ExpandedState, DrawPostProcessing),
  85. CED.FoldoutGroup(Styles.volumeSettingsText, Expandable.Volumes, k_ExpandedState, DrawVolumes)
  86. #if ADAPTIVE_PERFORMANCE_2_0_0_OR_NEWER
  87. , CED.FoldoutGroup(Styles.adaptivePerformanceText, Expandable.AdaptivePerformance, k_ExpandedState, CED.Group(DrawAdaptivePerformance))
  88. #endif
  89. );
  90. static void DrawRendering(SerializedUniversalRenderPipelineAsset serialized, Editor ownerEditor)
  91. {
  92. if (ownerEditor is UniversalRenderPipelineAssetEditor urpAssetEditor)
  93. {
  94. EditorGUILayout.Space();
  95. urpAssetEditor.rendererList.DoLayoutList();
  96. if (!serialized.asset.ValidateRendererData(-1))
  97. EditorGUILayout.HelpBox(Styles.rendererMissingDefaultMessage.text, MessageType.Error, true);
  98. else if (!serialized.asset.ValidateRendererDataList(true))
  99. EditorGUILayout.HelpBox(Styles.rendererMissingMessage.text, MessageType.Warning, true);
  100. else if (!ValidateRendererGraphicsAPIs(serialized.asset, out var unsupportedGraphicsApisMessage))
  101. EditorGUILayout.HelpBox(Styles.rendererUnsupportedAPIMessage.text + unsupportedGraphicsApisMessage, MessageType.Warning, true);
  102. EditorGUILayout.PropertyField(serialized.requireDepthTextureProp, Styles.requireDepthTextureText);
  103. EditorGUILayout.PropertyField(serialized.requireOpaqueTextureProp, Styles.requireOpaqueTextureText);
  104. EditorGUI.BeginDisabledGroup(!serialized.requireOpaqueTextureProp.boolValue);
  105. EditorGUILayout.PropertyField(serialized.opaqueDownsamplingProp, Styles.opaqueDownsamplingText);
  106. EditorGUI.EndDisabledGroup();
  107. EditorGUILayout.PropertyField(serialized.supportsTerrainHolesProp, Styles.supportsTerrainHolesText);
  108. EditorGUILayout.PropertyField(serialized.gpuResidentDrawerMode, Styles.gpuResidentDrawerMode);
  109. var brgStrippingError = EditorGraphicsSettings.batchRendererGroupShaderStrippingMode != BatchRendererGroupStrippingMode.KeepAll;
  110. var lightingModeError = !HasCorrectLightingModes(serialized.asset);
  111. var staticBatchingWarning = PlayerSettings.GetStaticBatchingForPlatform(EditorUserBuildSettings.activeBuildTarget);
  112. if ((GPUResidentDrawerMode)serialized.gpuResidentDrawerMode.intValue != GPUResidentDrawerMode.Disabled)
  113. {
  114. ++EditorGUI.indentLevel;
  115. serialized.smallMeshScreenPercentage.floatValue = Mathf.Clamp(EditorGUILayout.FloatField(Styles.smallMeshScreenPercentage, serialized.smallMeshScreenPercentage.floatValue), 0.0f, 20.0f);
  116. EditorGUILayout.PropertyField(serialized.gpuResidentDrawerEnableOcclusionCullingInCameras, Styles.gpuResidentDrawerEnableOcclusionCullingInCameras);
  117. --EditorGUI.indentLevel;
  118. if (brgStrippingError)
  119. EditorGUILayout.HelpBox(Styles.brgShaderStrippingErrorMessage.text, MessageType.Warning, true);
  120. if (lightingModeError)
  121. EditorGUILayout.HelpBox(Styles.lightModeErrorMessage.text, MessageType.Warning, true);
  122. if (staticBatchingWarning)
  123. EditorGUILayout.HelpBox(Styles.staticBatchingInfoMessage.text, MessageType.Info, true);
  124. if (serialized.gpuResidentDrawerEnableOcclusionCullingInCameras.boolValue && GraphicsSettings.GetRenderPipelineSettings<RenderGraphSettings>().enableRenderCompatibilityMode)
  125. EditorGUILayout.HelpBox(Styles.renderGraphNotEnabledErrorMessage.text, MessageType.Info, true);
  126. }
  127. }
  128. }
  129. private static bool HasCorrectLightingModes(UniversalRenderPipelineAsset asset)
  130. {
  131. foreach (var rendererData in asset.m_RendererDataList)
  132. {
  133. if (rendererData is not UniversalRendererData { renderingMode: RenderingMode.ForwardPlus })
  134. return false;
  135. }
  136. return true;
  137. }
  138. static void DrawRenderingAdditional(SerializedUniversalRenderPipelineAsset serialized, Editor ownerEditor)
  139. {
  140. EditorGUILayout.PropertyField(serialized.srpBatcher, Styles.srpBatcher);
  141. EditorGUILayout.PropertyField(serialized.supportsDynamicBatching, Styles.dynamicBatching);
  142. EditorGUILayout.PropertyField(serialized.debugLevelProp, Styles.debugLevel);
  143. EditorGUILayout.PropertyField(serialized.storeActionsOptimizationProperty, Styles.storeActionsOptimizationText);
  144. }
  145. static void DrawQuality(SerializedUniversalRenderPipelineAsset serialized, Editor ownerEditor)
  146. {
  147. DrawHDR(serialized, ownerEditor);
  148. EditorGUILayout.PropertyField(serialized.msaa, Styles.msaaText);
  149. serialized.renderScale.floatValue = EditorGUILayout.Slider(Styles.renderScaleText, serialized.renderScale.floatValue, UniversalRenderPipeline.minRenderScale, UniversalRenderPipeline.maxRenderScale);
  150. EditorGUILayout.PropertyField(serialized.upscalingFilter, Styles.upscalingFilterText);
  151. if (serialized.asset.upscalingFilter == UpscalingFilterSelection.FSR)
  152. {
  153. ++EditorGUI.indentLevel;
  154. EditorGUILayout.PropertyField(serialized.fsrOverrideSharpness, Styles.fsrOverrideSharpness);
  155. // We put the FSR sharpness override value behind an override checkbox so we can tell when the user intends to use a custom value rather than the default.
  156. if (serialized.fsrOverrideSharpness.boolValue)
  157. {
  158. serialized.fsrSharpness.floatValue = EditorGUILayout.Slider(Styles.fsrSharpnessText, serialized.fsrSharpness.floatValue, 0.0f, 1.0f);
  159. }
  160. --EditorGUI.indentLevel;
  161. }
  162. else if (serialized.asset.upscalingFilter == UpscalingFilterSelection.STP)
  163. {
  164. // Warn users if they attempt to enable STP without render graph
  165. if (GraphicsSettings.GetRenderPipelineSettings<RenderGraphSettings>().enableRenderCompatibilityMode)
  166. {
  167. EditorGUILayout.HelpBox(Styles.stpRequiresRenderGraph, MessageType.Warning, true);
  168. }
  169. // Warn users about performance expectations if they attempt to enable STP on a mobile platform
  170. if (PlatformAutoDetect.isShaderAPIMobileDefined)
  171. {
  172. EditorGUILayout.HelpBox(Styles.stpMobilePlatformWarning, MessageType.Warning, true);
  173. }
  174. }
  175. EditorGUILayout.PropertyField(serialized.enableLODCrossFadeProp, Styles.enableLODCrossFadeText);
  176. EditorGUI.BeginDisabledGroup(!serialized.enableLODCrossFadeProp.boolValue);
  177. EditorGUILayout.PropertyField(serialized.lodCrossFadeDitheringTypeProp, Styles.lodCrossFadeDitheringTypeText);
  178. EditorGUI.EndDisabledGroup();
  179. }
  180. static void DrawHDR(SerializedUniversalRenderPipelineAsset serialized, Editor ownerEditor)
  181. {
  182. EditorGUILayout.PropertyField(serialized.hdr, Styles.hdrText);
  183. // Nested and in-between additional property
  184. bool additionalProperties = k_ExpandedState[Expandable.Quality] && k_AdditionalPropertiesState[ExpandableAdditional.Quality];
  185. if (serialized.hdr.boolValue && additionalProperties)
  186. {
  187. EditorGUI.indentLevel++;
  188. EditorGUILayout.PropertyField(serialized.hdrColorBufferPrecisionProp, Styles.hdrColorBufferPrecisionText);
  189. EditorGUI.indentLevel--;
  190. }
  191. }
  192. static void DrawLighting(SerializedUniversalRenderPipelineAsset serialized, Editor ownerEditor)
  193. {
  194. // Main Light
  195. bool disableGroup = false;
  196. EditorGUI.BeginDisabledGroup(disableGroup);
  197. CoreEditorUtils.DrawPopup(Styles.mainLightRenderingModeText, serialized.mainLightRenderingModeProp, Styles.mainLightOptions);
  198. EditorGUI.EndDisabledGroup();
  199. EditorGUI.indentLevel++;
  200. disableGroup |= !serialized.mainLightRenderingModeProp.boolValue;
  201. EditorGUI.BeginDisabledGroup(disableGroup);
  202. EditorGUILayout.PropertyField(serialized.mainLightShadowsSupportedProp, Styles.supportsMainLightShadowsText);
  203. EditorGUI.EndDisabledGroup();
  204. disableGroup |= !serialized.mainLightShadowsSupportedProp.boolValue;
  205. EditorGUI.BeginDisabledGroup(disableGroup);
  206. EditorGUILayout.PropertyField(serialized.mainLightShadowmapResolutionProp, Styles.mainLightShadowmapResolutionText);
  207. EditorGUI.EndDisabledGroup();
  208. EditorGUI.indentLevel--;
  209. EditorGUILayout.Space();
  210. // Probe volumes
  211. EditorGUILayout.PropertyField(serialized.lightProbeSystem, Styles.lightProbeSystemContent);
  212. if (serialized.lightProbeSystem.intValue == (int)LightProbeSystem.ProbeVolumes)
  213. {
  214. EditorGUI.indentLevel++;
  215. EditorGUILayout.PropertyField(serialized.probeVolumeTextureSize, Styles.probeVolumeMemoryBudget);
  216. EditorGUILayout.PropertyField(serialized.probeVolumeSHBands, Styles.probeVolumeSHBands);
  217. EditorGUILayout.PropertyField(serialized.supportProbeVolumeGPUStreaming, Styles.supportProbeVolumeGPUStreaming);
  218. EditorGUI.BeginDisabledGroup(!serialized.supportProbeVolumeGPUStreaming.boolValue);
  219. EditorGUI.indentLevel++;
  220. EditorGUILayout.PropertyField(serialized.supportProbeVolumeDiskStreaming, Styles.supportProbeVolumeDiskStreaming);
  221. EditorGUI.indentLevel--;
  222. EditorGUI.EndDisabledGroup();
  223. EditorGUILayout.PropertyField(serialized.supportProbeVolumeScenarios, Styles.supportProbeVolumeScenarios);
  224. if (serialized.supportProbeVolumeScenarios.boolValue)
  225. {
  226. EditorGUI.indentLevel++;
  227. EditorGUILayout.PropertyField(serialized.supportProbeVolumeScenarioBlending, Styles.supportProbeVolumeScenarioBlending);
  228. if (serialized.supportProbeVolumeScenarioBlending.boolValue)
  229. {
  230. EditorGUI.indentLevel++;
  231. EditorGUILayout.PropertyField(serialized.probeVolumeBlendingTextureSize, Styles.probeVolumeBlendingMemoryBudget);
  232. EditorGUI.indentLevel--;
  233. }
  234. EditorGUI.indentLevel--;
  235. }
  236. int estimatedVMemCost = ProbeReferenceVolume.instance.GetVideoMemoryCost();
  237. if (estimatedVMemCost == 0)
  238. {
  239. EditorGUILayout.HelpBox($"Estimated GPU Memory cost: 0.\nProbe reference volume is not used in the scene and resources haven't been allocated yet.", MessageType.Info, wide: true);
  240. }
  241. else
  242. {
  243. EditorGUILayout.HelpBox($"Estimated GPU Memory cost: {estimatedVMemCost / (1000 * 1000)} MB.", MessageType.Info, wide: true);
  244. }
  245. EditorGUI.indentLevel--;
  246. EditorGUILayout.Space();
  247. }
  248. // Additional light
  249. EditorGUILayout.PropertyField(serialized.additionalLightsRenderingModeProp, Styles.addditionalLightsRenderingModeText);
  250. EditorGUI.indentLevel++;
  251. disableGroup = serialized.additionalLightsRenderingModeProp.intValue == (int)LightRenderingMode.Disabled;
  252. EditorGUI.BeginDisabledGroup(disableGroup);
  253. serialized.additionalLightsPerObjectLimitProp.intValue = EditorGUILayout.IntSlider(Styles.perObjectLimit, serialized.additionalLightsPerObjectLimitProp.intValue, 0, UniversalRenderPipeline.maxPerObjectLights);
  254. EditorGUI.EndDisabledGroup();
  255. disableGroup |= (serialized.additionalLightsPerObjectLimitProp.intValue == 0 || serialized.additionalLightsRenderingModeProp.intValue != (int)LightRenderingMode.PerPixel);
  256. EditorGUI.BeginDisabledGroup(disableGroup);
  257. EditorGUILayout.PropertyField(serialized.additionalLightShadowsSupportedProp, Styles.supportsAdditionalShadowsText);
  258. EditorGUI.EndDisabledGroup();
  259. disableGroup |= !serialized.additionalLightShadowsSupportedProp.boolValue;
  260. EditorGUI.BeginDisabledGroup(disableGroup);
  261. EditorGUILayout.PropertyField(serialized.additionalLightShadowmapResolutionProp, Styles.additionalLightsShadowmapResolution);
  262. DrawShadowResolutionTierSettings(serialized, ownerEditor);
  263. EditorGUI.EndDisabledGroup();
  264. EditorGUILayout.Space();
  265. disableGroup = serialized.additionalLightsRenderingModeProp.intValue == (int)LightRenderingMode.Disabled || !serialized.supportsLightCookies.boolValue;
  266. EditorGUI.BeginDisabledGroup(disableGroup);
  267. EditorGUILayout.PropertyField(serialized.additionalLightCookieResolutionProp, Styles.additionalLightsCookieResolution);
  268. EditorGUI.EndDisabledGroup();
  269. EditorGUI.BeginDisabledGroup(disableGroup);
  270. EditorGUILayout.PropertyField(serialized.additionalLightCookieFormatProp, Styles.additionalLightsCookieFormat);
  271. EditorGUI.EndDisabledGroup();
  272. EditorGUI.indentLevel--;
  273. EditorGUILayout.Space();
  274. // Reflection Probes
  275. EditorGUILayout.LabelField(Styles.reflectionProbesSettingsText);
  276. EditorGUI.indentLevel++;
  277. EditorGUILayout.PropertyField(serialized.reflectionProbeBlendingProp, Styles.reflectionProbeBlendingText);
  278. EditorGUILayout.PropertyField(serialized.reflectionProbeBoxProjectionProp, Styles.reflectionProbeBoxProjectionText);
  279. EditorGUI.indentLevel--;
  280. }
  281. static void DrawLightingAdditional(SerializedUniversalRenderPipelineAsset serialized, Editor ownerEditor)
  282. {
  283. EditorGUILayout.PropertyField(serialized.mixedLightingSupportedProp, Styles.mixedLightingSupportLabel);
  284. EditorGUILayout.PropertyField(serialized.useRenderingLayers, Styles.useRenderingLayers);
  285. EditorGUILayout.PropertyField(serialized.supportsLightCookies, Styles.supportsLightCookies);
  286. EditorGUILayout.PropertyField(serialized.shEvalModeProp, Styles.shEvalModeText);
  287. if (serialized.useRenderingLayers.boolValue && !ValidateRendererGraphicsAPIsForLightLayers(serialized.asset, out var unsupportedGraphicsApisMessage))
  288. EditorGUILayout.HelpBox(Styles.lightlayersUnsupportedMessage.text + unsupportedGraphicsApisMessage, MessageType.Warning, true);
  289. }
  290. static void DrawShadowResolutionTierSettings(SerializedUniversalRenderPipelineAsset serialized, Editor ownerEditor)
  291. {
  292. // UI code adapted from HDRP U.I logic implemented in com.unity.render-pipelines.high-definition/Editor/RenderPipeline/Settings/SerializedScalableSetting.cs )
  293. var rect = GUILayoutUtility.GetRect(0, float.Epsilon, EditorGUIUtility.singleLineHeight, EditorGUIUtility.singleLineHeight);
  294. var contentRect = EditorGUI.PrefixLabel(rect, Styles.additionalLightsShadowResolutionTiers);
  295. EditorGUI.BeginChangeCheck();
  296. const int k_ShadowResolutionTiersCount = 3;
  297. var values = new[] { serialized.additionalLightsShadowResolutionTierLowProp, serialized.additionalLightsShadowResolutionTierMediumProp, serialized.additionalLightsShadowResolutionTierHighProp };
  298. var num = contentRect.width / (float)k_ShadowResolutionTiersCount; // space allocated for every field including the label
  299. var indentLevel = EditorGUI.indentLevel;
  300. EditorGUI.indentLevel = 0; // Reset the indentation
  301. float pixelShift = 0; // Variable to keep track of the current pixel shift in the rectangle we were assigned for this whole section.
  302. for (var index = 0; index < k_ShadowResolutionTiersCount; ++index)
  303. {
  304. var labelWidth = Mathf.Clamp(EditorStyles.label.CalcSize(Styles.additionalLightsShadowResolutionTierNames[index]).x, 0, num);
  305. EditorGUI.LabelField(new Rect(contentRect.x + pixelShift, contentRect.y, labelWidth, contentRect.height), Styles.additionalLightsShadowResolutionTierNames[index]);
  306. pixelShift += labelWidth; // We need to remove from the position the label size that we've just drawn and shift by it's length
  307. float spaceLeft = num - labelWidth; // The amount of space left for the field
  308. if (spaceLeft > 2) // If at least two pixels are left to draw this field, draw it, otherwise, skip
  309. {
  310. var fieldSlot = new Rect(contentRect.x + pixelShift, contentRect.y, num - labelWidth, contentRect.height); // Define the rectangle for the field
  311. int value = EditorGUI.DelayedIntField(fieldSlot, values[index].intValue);
  312. values[index].intValue = Mathf.Max(UniversalAdditionalLightData.AdditionalLightsShadowMinimumResolution, Mathf.NextPowerOfTwo(value));
  313. }
  314. pixelShift += spaceLeft; // Shift by the slot that was left for the field
  315. }
  316. EditorGUI.indentLevel = indentLevel;
  317. EditorGUI.EndChangeCheck();
  318. }
  319. static void DrawShadows(SerializedUniversalRenderPipelineAsset serialized, Editor ownerEditor)
  320. {
  321. serialized.shadowDistanceProp.floatValue = Mathf.Max(0.0f, EditorGUILayout.FloatField(Styles.shadowDistanceText, serialized.shadowDistanceProp.floatValue));
  322. EditorUtils.Unit unit = EditorUtils.Unit.Metric;
  323. if (serialized.shadowCascadeCountProp.intValue != 0)
  324. {
  325. EditorGUI.BeginChangeCheck();
  326. unit = (EditorUtils.Unit)EditorGUILayout.EnumPopup(Styles.shadowWorkingUnitText, serialized.state.value);
  327. if (EditorGUI.EndChangeCheck())
  328. {
  329. serialized.state.value = unit;
  330. }
  331. }
  332. EditorGUILayout.IntSlider(serialized.shadowCascadeCountProp, UniversalRenderPipelineAsset.k_ShadowCascadeMinCount, UniversalRenderPipelineAsset.k_ShadowCascadeMaxCount, Styles.shadowCascadesText);
  333. int cascadeCount = serialized.shadowCascadeCountProp.intValue;
  334. EditorGUI.indentLevel++;
  335. bool useMetric = unit == EditorUtils.Unit.Metric;
  336. float baseMetric = serialized.shadowDistanceProp.floatValue;
  337. int cascadeSplitCount = cascadeCount - 1;
  338. DrawCascadeSliders(serialized, cascadeSplitCount, useMetric, baseMetric);
  339. EditorGUI.indentLevel--;
  340. DrawCascades(serialized, cascadeCount, useMetric, baseMetric);
  341. EditorGUI.indentLevel++;
  342. serialized.shadowDepthBiasProp.floatValue = EditorGUILayout.Slider(Styles.shadowDepthBias, serialized.shadowDepthBiasProp.floatValue, 0.0f, UniversalRenderPipeline.maxShadowBias);
  343. serialized.shadowNormalBiasProp.floatValue = EditorGUILayout.Slider(Styles.shadowNormalBias, serialized.shadowNormalBiasProp.floatValue, 0.0f, UniversalRenderPipeline.maxShadowBias);
  344. EditorGUILayout.PropertyField(serialized.softShadowsSupportedProp, Styles.supportsSoftShadows);
  345. if (serialized.softShadowsSupportedProp.boolValue)
  346. {
  347. EditorGUI.indentLevel++;
  348. DrawShadowsSoftShadowQuality(serialized, ownerEditor);
  349. EditorGUI.indentLevel--;
  350. }
  351. EditorGUI.indentLevel--;
  352. }
  353. static void DrawShadowsSoftShadowQuality(SerializedUniversalRenderPipelineAsset serialized, Editor ownerEditor)
  354. {
  355. int selectedAssetSoftShadowQuality = serialized.softShadowQualityProp.intValue;
  356. Rect r = EditorGUILayout.GetControlRect(true);
  357. EditorGUI.BeginProperty(r, Styles.softShadowsQuality, serialized.softShadowQualityProp);
  358. {
  359. using (var checkScope = new EditorGUI.ChangeCheckScope())
  360. {
  361. selectedAssetSoftShadowQuality = EditorGUI.IntPopup(r, Styles.softShadowsQuality, selectedAssetSoftShadowQuality, Styles.softShadowsQualityAssetOptions, Styles.softShadowsQualityAssetValues);
  362. if (checkScope.changed)
  363. {
  364. serialized.softShadowQualityProp.intValue = Math.Clamp(selectedAssetSoftShadowQuality, (int)SoftShadowQuality.Low, (int)SoftShadowQuality.High);
  365. }
  366. }
  367. }
  368. EditorGUI.EndProperty();
  369. }
  370. static void DrawShadowsAdditional(SerializedUniversalRenderPipelineAsset serialized, Editor ownerEditor)
  371. {
  372. EditorGUILayout.PropertyField(serialized.conservativeEnclosingSphereProp, Styles.conservativeEnclosingSphere);
  373. }
  374. static void DrawCascadeSliders(SerializedUniversalRenderPipelineAsset serialized, int splitCount, bool useMetric, float baseMetric)
  375. {
  376. Vector4 shadowCascadeSplit = Vector4.one;
  377. if (splitCount == 3)
  378. shadowCascadeSplit = new Vector4(serialized.shadowCascade4SplitProp.vector3Value.x, serialized.shadowCascade4SplitProp.vector3Value.y, serialized.shadowCascade4SplitProp.vector3Value.z, 1);
  379. else if (splitCount == 2)
  380. shadowCascadeSplit = new Vector4(serialized.shadowCascade3SplitProp.vector2Value.x, serialized.shadowCascade3SplitProp.vector2Value.y, 1, 0);
  381. else if (splitCount == 1)
  382. shadowCascadeSplit = new Vector4(serialized.shadowCascade2SplitProp.floatValue, 1, 0, 0);
  383. float splitBias = 0.001f;
  384. float invBaseMetric = baseMetric == 0 ? 0 : 1f / baseMetric;
  385. // Ensure correct split order
  386. shadowCascadeSplit[0] = Mathf.Clamp(shadowCascadeSplit[0], 0f, shadowCascadeSplit[1] - splitBias);
  387. shadowCascadeSplit[1] = Mathf.Clamp(shadowCascadeSplit[1], shadowCascadeSplit[0] + splitBias, shadowCascadeSplit[2] - splitBias);
  388. shadowCascadeSplit[2] = Mathf.Clamp(shadowCascadeSplit[2], shadowCascadeSplit[1] + splitBias, shadowCascadeSplit[3] - splitBias);
  389. EditorGUI.BeginChangeCheck();
  390. for (int i = 0; i < splitCount; ++i)
  391. {
  392. float value = shadowCascadeSplit[i];
  393. float minimum = i == 0 ? 0 : shadowCascadeSplit[i - 1] + splitBias;
  394. float maximum = i == splitCount - 1 ? 1 : shadowCascadeSplit[i + 1] - splitBias;
  395. if (useMetric)
  396. {
  397. float valueMetric = value * baseMetric;
  398. valueMetric = EditorGUILayout.Slider(EditorGUIUtility.TrTextContent($"Split {i + 1}", "The distance where this cascade ends and the next one starts."), valueMetric, 0f, baseMetric, null);
  399. shadowCascadeSplit[i] = Mathf.Clamp(valueMetric * invBaseMetric, minimum, maximum);
  400. }
  401. else
  402. {
  403. float valueProcentage = value * 100f;
  404. valueProcentage = EditorGUILayout.Slider(EditorGUIUtility.TrTextContent($"Split {i + 1}", "The distance where this cascade ends and the next one starts."), valueProcentage, 0f, 100f, null);
  405. shadowCascadeSplit[i] = Mathf.Clamp(valueProcentage * 0.01f, minimum, maximum);
  406. }
  407. }
  408. if (EditorGUI.EndChangeCheck())
  409. {
  410. switch (splitCount)
  411. {
  412. case 3:
  413. serialized.shadowCascade4SplitProp.vector3Value = shadowCascadeSplit;
  414. break;
  415. case 2:
  416. serialized.shadowCascade3SplitProp.vector2Value = shadowCascadeSplit;
  417. break;
  418. case 1:
  419. serialized.shadowCascade2SplitProp.floatValue = shadowCascadeSplit.x;
  420. break;
  421. }
  422. }
  423. var borderValue = serialized.shadowCascadeBorderProp.floatValue;
  424. EditorGUI.BeginChangeCheck();
  425. if (useMetric)
  426. {
  427. var lastCascadeSplitSize = splitCount == 0 ? baseMetric : (1.0f - shadowCascadeSplit[splitCount - 1]) * baseMetric;
  428. var invLastCascadeSplitSize = lastCascadeSplitSize == 0 ? 0 : 1f / lastCascadeSplitSize;
  429. float valueMetric = borderValue * lastCascadeSplitSize;
  430. valueMetric = EditorGUILayout.Slider(EditorGUIUtility.TrTextContent("Last Border", "The distance of the last cascade."), valueMetric, 0f, lastCascadeSplitSize, null);
  431. borderValue = valueMetric * invLastCascadeSplitSize;
  432. }
  433. else
  434. {
  435. float valueProcentage = borderValue * 100f;
  436. valueProcentage = EditorGUILayout.Slider(EditorGUIUtility.TrTextContent("Last Border", "The distance of the last cascade."), valueProcentage, 0f, 100f, null);
  437. borderValue = valueProcentage * 0.01f;
  438. }
  439. if (EditorGUI.EndChangeCheck())
  440. {
  441. serialized.shadowCascadeBorderProp.floatValue = borderValue;
  442. }
  443. }
  444. static void DrawCascades(SerializedUniversalRenderPipelineAsset serialized, int cascadeCount, bool useMetric, float baseMetric)
  445. {
  446. var cascades = new ShadowCascadeGUI.Cascade[cascadeCount];
  447. Vector3 shadowCascadeSplit = Vector3.zero;
  448. if (cascadeCount == 4)
  449. shadowCascadeSplit = serialized.shadowCascade4SplitProp.vector3Value;
  450. else if (cascadeCount == 3)
  451. shadowCascadeSplit = serialized.shadowCascade3SplitProp.vector2Value;
  452. else if (cascadeCount == 2)
  453. shadowCascadeSplit.x = serialized.shadowCascade2SplitProp.floatValue;
  454. else
  455. shadowCascadeSplit.x = serialized.shadowCascade2SplitProp.floatValue;
  456. float lastCascadePartitionSplit = 0;
  457. for (int i = 0; i < cascadeCount - 1; ++i)
  458. {
  459. cascades[i] = new ShadowCascadeGUI.Cascade()
  460. {
  461. size = i == 0 ? shadowCascadeSplit[i] : shadowCascadeSplit[i] - lastCascadePartitionSplit, // Calculate the size of cascade
  462. borderSize = 0,
  463. cascadeHandleState = ShadowCascadeGUI.HandleState.Enabled,
  464. borderHandleState = ShadowCascadeGUI.HandleState.Hidden,
  465. };
  466. lastCascadePartitionSplit = shadowCascadeSplit[i];
  467. }
  468. // Last cascade is special
  469. var lastCascade = cascadeCount - 1;
  470. cascades[lastCascade] = new ShadowCascadeGUI.Cascade()
  471. {
  472. size = lastCascade == 0 ? 1.0f : 1 - shadowCascadeSplit[lastCascade - 1], // Calculate the size of cascade
  473. borderSize = serialized.shadowCascadeBorderProp.floatValue,
  474. cascadeHandleState = ShadowCascadeGUI.HandleState.Hidden,
  475. borderHandleState = ShadowCascadeGUI.HandleState.Enabled,
  476. };
  477. EditorGUI.BeginChangeCheck();
  478. ShadowCascadeGUI.DrawCascades(ref cascades, useMetric, baseMetric);
  479. if (EditorGUI.EndChangeCheck())
  480. {
  481. if (cascadeCount == 4)
  482. serialized.shadowCascade4SplitProp.vector3Value = new Vector3(
  483. cascades[0].size,
  484. cascades[0].size + cascades[1].size,
  485. cascades[0].size + cascades[1].size + cascades[2].size
  486. );
  487. else if (cascadeCount == 3)
  488. serialized.shadowCascade3SplitProp.vector2Value = new Vector2(
  489. cascades[0].size,
  490. cascades[0].size + cascades[1].size
  491. );
  492. else if (cascadeCount == 2)
  493. serialized.shadowCascade2SplitProp.floatValue = cascades[0].size;
  494. serialized.shadowCascadeBorderProp.floatValue = cascades[lastCascade].borderSize;
  495. }
  496. }
  497. static void DrawPostProcessing(SerializedUniversalRenderPipelineAsset serialized, Editor ownerEditor)
  498. {
  499. EditorGUILayout.PropertyField(serialized.colorGradingMode, Styles.colorGradingMode);
  500. bool isHdrOn = serialized.hdr.boolValue;
  501. if (!isHdrOn && serialized.colorGradingMode.intValue == (int)ColorGradingMode.HighDynamicRange)
  502. EditorGUILayout.HelpBox(Styles.colorGradingModeWarning, MessageType.Warning);
  503. else if (isHdrOn && serialized.colorGradingMode.intValue == (int)ColorGradingMode.HighDynamicRange)
  504. EditorGUILayout.HelpBox(Styles.colorGradingModeSpecInfo, MessageType.Info);
  505. else if (isHdrOn && PlayerSettings.allowHDRDisplaySupport && serialized.colorGradingMode.intValue == (int)ColorGradingMode.LowDynamicRange)
  506. EditorGUILayout.HelpBox(Styles.colorGradingModeWithHDROutput, MessageType.Warning);
  507. EditorGUILayout.DelayedIntField(serialized.colorGradingLutSize, Styles.colorGradingLutSize);
  508. serialized.colorGradingLutSize.intValue = Mathf.Clamp(serialized.colorGradingLutSize.intValue, UniversalRenderPipelineAsset.k_MinLutSize, UniversalRenderPipelineAsset.k_MaxLutSize);
  509. if (isHdrOn && serialized.colorGradingMode.intValue == (int)ColorGradingMode.HighDynamicRange && serialized.colorGradingLutSize.intValue < 32)
  510. EditorGUILayout.HelpBox(Styles.colorGradingLutSizeWarning, MessageType.Warning);
  511. HDRColorBufferPrecision hdrPrecision = (HDRColorBufferPrecision)serialized.hdrColorBufferPrecisionProp.intValue;
  512. bool alphaEnabled = !isHdrOn /*RGBA8*/ || (isHdrOn && hdrPrecision == HDRColorBufferPrecision._64Bits); /*RGBA16Float*/
  513. EditorGUILayout.PropertyField(serialized.allowPostProcessAlphaOutput, Styles.allowPostProcessAlphaOutput);
  514. if(!alphaEnabled && serialized.allowPostProcessAlphaOutput.boolValue)
  515. EditorGUILayout.HelpBox(Styles.alphaOutputWarning, MessageType.Warning);
  516. EditorGUILayout.PropertyField(serialized.useFastSRGBLinearConversion, Styles.useFastSRGBLinearConversion);
  517. EditorGUILayout.PropertyField(serialized.supportDataDrivenLensFlare, Styles.supportDataDrivenLensFlare);
  518. EditorGUILayout.PropertyField(serialized.supportScreenSpaceLensFlare, Styles.supportScreenSpaceLensFlare);
  519. }
  520. static Editor s_VolumeProfileEditor;
  521. static void DrawVolumes(SerializedUniversalRenderPipelineAsset serialized, Editor ownerEditor)
  522. {
  523. CoreEditorUtils.DrawPopup(Styles.volumeFrameworkUpdateMode, serialized.volumeFrameworkUpdateModeProp, Styles.volumeFrameworkUpdateOptions);
  524. EditorGUI.BeginChangeCheck();
  525. EditorGUILayout.BeginHorizontal();
  526. EditorGUILayout.PropertyField(serialized.volumeProfileProp, Styles.volumeProfileLabel);
  527. var profile = serialized.volumeProfileProp.objectReferenceValue as VolumeProfile;
  528. if (EditorGUI.EndChangeCheck() && UniversalRenderPipeline.asset == serialized.serializedObject.targetObject && RenderPipelineManager.currentPipeline is UniversalRenderPipeline)
  529. VolumeManager.instance.SetQualityDefaultProfile(serialized.volumeProfileProp.objectReferenceValue as VolumeProfile);
  530. var contextMenuButtonRect = GUILayoutUtility.GetRect(CoreEditorStyles.contextMenuIcon,
  531. Styles.volumeProfileContextMenuStyle.Value);
  532. if (GUI.Button(contextMenuButtonRect, CoreEditorStyles.contextMenuIcon,
  533. Styles.volumeProfileContextMenuStyle.Value))
  534. {
  535. var profileEditor = s_VolumeProfileEditor as VolumeProfileEditor;
  536. var componentEditors = profileEditor != null ? profileEditor.componentList.editors : null;
  537. var srpAsset = serialized.serializedObject.targetObject as UniversalRenderPipelineAsset;
  538. var pos = new Vector2(contextMenuButtonRect.x, contextMenuButtonRect.yMax);
  539. VolumeProfileUtils.OnVolumeProfileContextClick(pos, srpAsset.volumeProfile, componentEditors,
  540. overrideStateOnReset: false,
  541. defaultVolumeProfilePath: $"Assets/{srpAsset.name}_VolumeProfile.asset",
  542. onNewVolumeProfileCreated: volumeProfile =>
  543. {
  544. Undo.RecordObject(srpAsset, "Set UniversalRenderPipelineAsset Volume Profile");
  545. srpAsset.volumeProfile = volumeProfile;
  546. if (UniversalRenderPipeline.asset == srpAsset)
  547. VolumeManager.instance.SetQualityDefaultProfile(volumeProfile);
  548. EditorUtility.SetDirty(srpAsset);
  549. });
  550. }
  551. EditorGUILayout.EndHorizontal();
  552. GUILayout.Space(2);
  553. if (profile != null)
  554. {
  555. Editor.CreateCachedEditor(profile, typeof(VolumeProfileEditor), ref s_VolumeProfileEditor);
  556. bool oldEnabled = GUI.enabled;
  557. GUI.enabled = AssetDatabase.IsOpenForEdit(profile);
  558. s_VolumeProfileEditor.OnInspectorGUI();
  559. GUI.enabled = oldEnabled;
  560. }
  561. else
  562. {
  563. CoreUtils.Destroy(s_VolumeProfileEditor);
  564. }
  565. }
  566. #if ADAPTIVE_PERFORMANCE_2_0_0_OR_NEWER
  567. static void DrawAdaptivePerformance(SerializedUniversalRenderPipelineAsset serialized, Editor ownerEditor)
  568. {
  569. EditorGUILayout.PropertyField(serialized.useAdaptivePerformance, Styles.useAdaptivePerformance);
  570. }
  571. #endif
  572. }
  573. }