530 lines
30 KiB
C#
530 lines
30 KiB
C#
using UnityEngine;
|
|
using UnityEditor;
|
|
using UnityEditor.Rendering;
|
|
using DebugView = RadiantGI.Universal.RadiantGlobalIllumination.DebugView;
|
|
using System.Reflection;
|
|
using UnityEngine.Rendering;
|
|
|
|
namespace RadiantGI.Universal {
|
|
|
|
public enum PerformancePreset {
|
|
VeryFast,
|
|
Fast,
|
|
Default,
|
|
HighQuality,
|
|
Ultra
|
|
}
|
|
|
|
#if UNITY_2022_2_OR_NEWER
|
|
[CustomEditor(typeof(RadiantGlobalIllumination))]
|
|
#else
|
|
[VolumeComponentEditor(typeof(RadiantGlobalIllumination))]
|
|
#endif
|
|
public class RadiantGlobalIlluminationEditor : VolumeComponentEditor {
|
|
|
|
static PerformancePreset selectedPreset = PerformancePreset.Default;
|
|
|
|
SerializedDataParameter indirectIntensity, maxIndirectSourceBrightness, indirectDistanceAttenuation, normalMapInfluence;
|
|
SerializedDataParameter nearFieldObscurance, nearFieldObscuranceSpread, nearFieldObscuranceOccluderDistance, nearFieldObscuranceMaxCameraDistance, nearFieldObscuranceTintColor;
|
|
SerializedDataParameter virtualEmitters;
|
|
SerializedDataParameter organicLight, organicLightThreshold, organicLightNormalsInfluence, organicLightSpread, organicLightTintColor, organicLightAnimationSpeed, organicLightDistanceScaling;
|
|
SerializedDataParameter unityAmbientLighting;
|
|
SerializedDataParameter brightnessThreshold, brightnessMax, sourceBrightness, giWeight, fallbackAmbient, nearCameraAttenuation, saturation, limitToVolumeBounds, aoInfluence, occlusionIntensity;
|
|
SerializedDataParameter stencilCheck, stencilValue, stencilCompareFunction;
|
|
SerializedDataParameter rayCount, rayMaxLength, rayMaxSamples, rayJitter, thickness, rayReuse, rayBounce;
|
|
SerializedDataParameter fallbackReuseRays, fallbackReflectionProbes, probesIntensity, fallbackReflectiveShadowMap, reflectiveShadowMapIntensity, fallbackDefaultAmbient;
|
|
SerializedDataParameter blurSpread, downsampling, raytracerAccuracy;
|
|
SerializedDataParameter temporalStability, temporalResponseSpeed, darkThreshold, darkThresholdMultiplier;
|
|
SerializedDataParameter showInEditMode, showInSceneView, debugView, debugDepthMultiplier, debugMotionVectorMultiplier, compareMode, compareSameSide, comparePanning, compareLineAngle, compareLineWidth;
|
|
SerializedDataParameter transparencySupport, transparentLayerMask;
|
|
|
|
static GUIStyle sectionHeaderStyle;
|
|
|
|
const string PrefKeyPrefix = "RadiantGI.RGIEditor.";
|
|
const string PrefKeyGeneral = PrefKeyPrefix + "General";
|
|
const string PrefKeyFallbacks = PrefKeyPrefix + "Fallbacks";
|
|
const string PrefKeyRaymarch = PrefKeyPrefix + "Raymarch";
|
|
const string PrefKeyTemporal = PrefKeyPrefix + "Temporal";
|
|
const string PrefKeyArtistic = PrefKeyPrefix + "Artistic";
|
|
const string PrefKeyDebug = PrefKeyPrefix + "Debug";
|
|
|
|
bool showGeneral = true;
|
|
bool showFallbacks = true;
|
|
bool showRaymarch = true;
|
|
bool showTemporal = true;
|
|
bool showArtistic = true;
|
|
bool showDebug = true;
|
|
|
|
#if !UNITY_2021_2_OR_NEWER
|
|
public override bool hasAdvancedMode => false;
|
|
#endif
|
|
|
|
bool isAmbientProbeValid;
|
|
Light cachedDirectionalLight;
|
|
|
|
public override void OnEnable () {
|
|
base.OnEnable();
|
|
|
|
var o = new PropertyFetcher<RadiantGlobalIllumination>(serializedObject);
|
|
indirectIntensity = Unpack(o.Find(x => x.indirectIntensity));
|
|
maxIndirectSourceBrightness = Unpack(o.Find(x => x.indirectMaxSourceBrightness));
|
|
indirectDistanceAttenuation = Unpack(o.Find(x => x.indirectDistanceAttenuation));
|
|
normalMapInfluence = Unpack(o.Find(x => x.normalMapInfluence));
|
|
nearFieldObscurance = Unpack(o.Find(x => x.nearFieldObscurance));
|
|
nearFieldObscuranceSpread = Unpack(o.Find(x => x.nearFieldObscuranceSpread));
|
|
nearFieldObscuranceOccluderDistance = Unpack(o.Find(x => x.nearFieldObscuranceOccluderDistance));
|
|
nearFieldObscuranceMaxCameraDistance = Unpack(o.Find(x => x.nearFieldObscuranceMaxCameraDistance));
|
|
nearFieldObscuranceTintColor = Unpack(o.Find(x => x.nearFieldObscuranceTintColor));
|
|
virtualEmitters = Unpack(o.Find(x => x.virtualEmitters));
|
|
organicLight = Unpack(o.Find(x => x.organicLight));
|
|
organicLightThreshold = Unpack(o.Find(x => x.organicLightThreshold));
|
|
organicLightSpread = Unpack(o.Find(x => x.organicLightSpread));
|
|
organicLightNormalsInfluence = Unpack(o.Find(x => x.organicLightNormalsInfluence));
|
|
organicLightTintColor = Unpack(o.Find(x => x.organicLightTintColor));
|
|
organicLightAnimationSpeed = Unpack(o.Find(x => x.organicLightAnimationSpeed));
|
|
organicLightDistanceScaling = Unpack(o.Find(x => x.organicLightDistanceScaling));
|
|
unityAmbientLighting = Unpack(o.Find(x => x.unityAmbientLighting));
|
|
brightnessThreshold = Unpack(o.Find(x => x.brightnessThreshold));
|
|
brightnessMax = Unpack(o.Find(x => x.brightnessMax));
|
|
sourceBrightness = Unpack(o.Find(x => x.sourceBrightness));
|
|
giWeight = Unpack(o.Find(x => x.giWeight));
|
|
fallbackAmbient = Unpack(o.Find(x => x.fallbackAmbient));
|
|
nearCameraAttenuation = Unpack(o.Find(x => x.nearCameraAttenuation));
|
|
saturation = Unpack(o.Find(x => x.saturation));
|
|
limitToVolumeBounds = Unpack(o.Find(x => x.limitToVolumeBounds));
|
|
stencilCheck = Unpack(o.Find(x => x.stencilCheck));
|
|
stencilValue = Unpack(o.Find(x => x.stencilValue));
|
|
stencilCompareFunction = Unpack(o.Find(x => x.stencilCompareFunction));
|
|
aoInfluence = Unpack(o.Find(x => x.aoInfluence));
|
|
occlusionIntensity = Unpack(o.Find(x => x.occlusionIntensity));
|
|
rayCount = Unpack(o.Find(x => x.rayCount));
|
|
rayMaxLength = Unpack(o.Find(x => x.rayMaxLength));
|
|
rayMaxSamples = Unpack(o.Find(x => x.rayMaxSamples));
|
|
rayJitter = Unpack(o.Find(x => x.rayJitter));
|
|
thickness = Unpack(o.Find(x => x.thickness));
|
|
rayReuse = Unpack(o.Find(x => x.rayReuse));
|
|
rayBounce = Unpack(o.Find(x => x.rayBounce));
|
|
fallbackReuseRays = Unpack(o.Find(x => x.fallbackReuseRays));
|
|
fallbackReflectionProbes = Unpack(o.Find(x => x.fallbackReflectionProbes));
|
|
probesIntensity = Unpack(o.Find(x => x.probesIntensity));
|
|
fallbackReflectiveShadowMap = Unpack(o.Find(x => x.fallbackReflectiveShadowMap));
|
|
reflectiveShadowMapIntensity = Unpack(o.Find(x => x.reflectiveShadowMapIntensity));
|
|
fallbackDefaultAmbient = Unpack(o.Find(x => x.fallbackDefaultAmbient));
|
|
blurSpread = Unpack(o.Find(x => x.blurSpread));
|
|
downsampling = Unpack(o.Find(x => x.downsampling));
|
|
raytracerAccuracy = Unpack(o.Find(x => x.raytracerAccuracy));
|
|
temporalStability = Unpack(o.Find(x => x.temporalStabilization));
|
|
temporalResponseSpeed = Unpack(o.Find(x => x.temporalResponseSpeed));
|
|
darkThreshold = Unpack(o.Find(x => x.darkThreshold));
|
|
darkThresholdMultiplier = Unpack(o.Find(x => x.darkThresholdMultiplier));
|
|
showInEditMode = Unpack(o.Find(x => x.showInEditMode));
|
|
showInSceneView = Unpack(o.Find(x => x.showInSceneView));
|
|
debugView = Unpack(o.Find(x => x.debugView));
|
|
debugDepthMultiplier = Unpack(o.Find(x => x.debugDepthMultiplier));
|
|
debugMotionVectorMultiplier = Unpack(o.Find(x => x.debugMotionVectorMultiplier));
|
|
compareMode = Unpack(o.Find(x => x.compareMode));
|
|
compareSameSide = Unpack(o.Find(x => x.compareSameSide));
|
|
comparePanning = Unpack(o.Find(x => x.comparePanning));
|
|
compareLineAngle = Unpack(o.Find(x => x.compareLineAngle));
|
|
compareLineWidth = Unpack(o.Find(x => x.compareLineWidth));
|
|
transparencySupport = Unpack(o.Find(x => x.transparencySupport));
|
|
transparentLayerMask = Unpack(o.Find(x => x.transparentLayerMask));
|
|
|
|
isAmbientProbeValid = RadiantRenderFeature.IsAmbientProbeValid(RenderSettings.ambientProbe);
|
|
cachedDirectionalLight = GetDirectionalLight();
|
|
|
|
showGeneral = EditorPrefs.GetBool(PrefKeyGeneral, true);
|
|
showFallbacks = EditorPrefs.GetBool(PrefKeyFallbacks, true);
|
|
showRaymarch = EditorPrefs.GetBool(PrefKeyRaymarch, true);
|
|
showTemporal = EditorPrefs.GetBool(PrefKeyTemporal, true);
|
|
showArtistic = EditorPrefs.GetBool(PrefKeyArtistic, true);
|
|
showDebug = EditorPrefs.GetBool(PrefKeyDebug, true);
|
|
}
|
|
|
|
public override void OnInspectorGUI () {
|
|
|
|
var pipe = GraphicsSettings.currentRenderPipeline as UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset;
|
|
if (pipe == null) {
|
|
EditorGUILayout.HelpBox("Universal Rendering Pipeline asset is not set in Project Settings / Graphics !", MessageType.Error);
|
|
return;
|
|
}
|
|
|
|
// Check if RadiantRenderFeature is added to renderer
|
|
if (!RadiantRenderFeature.installed) {
|
|
EditorGUILayout.HelpBox("Radiant Render Feature is not currently running. Please add it to the Renderer Features list in your URP Renderer Data asset.", MessageType.Warning);
|
|
if (GUILayout.Button("Show URP Renderer Asset")) {
|
|
ShowURPRendererAsset(pipe);
|
|
}
|
|
EditorGUILayout.Separator();
|
|
}
|
|
else {
|
|
string pathName = RadiantRenderFeature.isRenderingInDeferred ? "Deferred" : "Forward";
|
|
EditorGUILayout.BeginHorizontal();
|
|
EditorGUILayout.LabelField("Radiant using " + pathName + " rendering path.", EditorStyles.miniLabel);
|
|
if (GUILayout.Button("Show URP Renderer Asset", EditorStyles.miniButton)) {
|
|
ShowURPRendererAsset(pipe);
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
|
|
Camera mainCam = Camera.main;
|
|
bool cameraHDR = mainCam != null && mainCam.allowHDR;
|
|
bool pipeHDR = pipe.supportsHDR;
|
|
bool hdrEnabled = cameraHDR && pipeHDR;
|
|
EditorGUILayout.BeginHorizontal();
|
|
string hdrStatus;
|
|
if (hdrEnabled) {
|
|
hdrStatus = "HDR: On";
|
|
}
|
|
else if (!pipeHDR) {
|
|
hdrStatus = "HDR: Off (URP Asset)";
|
|
}
|
|
else {
|
|
hdrStatus = "HDR: Off (Camera)";
|
|
}
|
|
EditorGUILayout.LabelField(hdrStatus, EditorStyles.miniLabel);
|
|
if (!hdrEnabled && pipeHDR && mainCam != null) {
|
|
if (GUILayout.Button("Show Camera Settings", EditorStyles.miniButton)) {
|
|
Selection.activeGameObject = mainCam.gameObject;
|
|
EditorGUIUtility.PingObject(mainCam.gameObject);
|
|
}
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
}
|
|
|
|
// Check depth texture mode
|
|
FieldInfo renderers = pipe.GetType().GetField("m_RendererDataList", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
|
if (renderers == null) return;
|
|
foreach (var renderer in (object[])renderers.GetValue(pipe)) {
|
|
if (renderer == null) continue;
|
|
FieldInfo depthTextureModeField = renderer.GetType().GetField("m_CopyDepthMode", BindingFlags.NonPublic | BindingFlags.Instance);
|
|
if (depthTextureModeField != null) {
|
|
int depthTextureMode = (int)depthTextureModeField.GetValue(renderer);
|
|
if (depthTextureMode == 1) { // transparent copy depth mode
|
|
EditorGUILayout.HelpBox("Depth Texture Mode in URP asset must be set to 'After Opaques' or 'Force Prepass'.", MessageType.Warning);
|
|
if (GUILayout.Button("Show Pipeline Asset")) {
|
|
Selection.activeObject = (Object)renderer;
|
|
GUIUtility.ExitGUI();
|
|
}
|
|
EditorGUILayout.Separator();
|
|
}
|
|
}
|
|
}
|
|
|
|
serializedObject.Update();
|
|
|
|
showGeneral = DrawSectionHeader("General", PrefKeyGeneral, showGeneral);
|
|
if (showGeneral) {
|
|
PropertyField(indirectIntensity, new GUIContent("Indirect Light Intensity"));
|
|
EditorGUI.indentLevel++;
|
|
PropertyField(indirectDistanceAttenuation, new GUIContent("Distance Attenuation"));
|
|
PropertyField(rayBounce, new GUIContent("One Extra Bounce", "Performs raycast over the result of the previous bounce (frame). Warning: this can cause lag when camera moves fast."));
|
|
PropertyField(sourceBrightness, new GUIContent("Source Brightness Multiplier"));
|
|
if (sourceBrightness.overrideState.boolValue && sourceBrightness.value.floatValue > 2f) {
|
|
Light sun = cachedDirectionalLight;
|
|
if (sun != null && sun.intensity < 2f) {
|
|
EditorGUILayout.HelpBox("Instead of increasing Source Brightness Multiplier, consider raising the light intensity in the scene.", MessageType.Info);
|
|
}
|
|
}
|
|
PropertyField(maxIndirectSourceBrightness, new GUIContent("Max Source Brightness"));
|
|
PropertyField(normalMapInfluence);
|
|
EditorGUI.indentLevel--;
|
|
PropertyField(nearFieldObscurance);
|
|
if (nearFieldObscurance.overrideState.boolValue && nearFieldObscurance.value.floatValue > 0f) {
|
|
EditorGUI.indentLevel++;
|
|
PropertyField(nearFieldObscuranceSpread, new GUIContent("Spread"));
|
|
PropertyField(nearFieldObscuranceOccluderDistance, new GUIContent("Occluder Distance"));
|
|
PropertyField(nearFieldObscuranceMaxCameraDistance, new GUIContent("Max Camera Distance"));
|
|
PropertyField(nearFieldObscuranceTintColor, new GUIContent("Tint color"));
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
PropertyField(virtualEmitters);
|
|
PropertyField(organicLight);
|
|
if (organicLight.overrideState.boolValue && organicLight.value.floatValue > 0f) {
|
|
EditorGUI.indentLevel++;
|
|
if (!RadiantRenderFeature.isRenderingInDeferred) {
|
|
EditorGUILayout.HelpBox("Organic Light requires deferred rendering path.", MessageType.Warning);
|
|
}
|
|
PropertyField(organicLightSpread, new GUIContent("Spread"));
|
|
PropertyField(organicLightThreshold, new GUIContent("Threshold"));
|
|
PropertyField(organicLightNormalsInfluence, new GUIContent("Normals Influence"));
|
|
PropertyField(organicLightTintColor, new GUIContent("Tint Color"));
|
|
PropertyField(organicLightAnimationSpeed, new GUIContent("Animation Speed"));
|
|
PropertyField(organicLightDistanceScaling, new GUIContent("Distance Scaling"));
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
PropertyField(unityAmbientLighting, new GUIContent("Unity Ambient Intensity", "Controls the amount of Unity ambient light. Lower values subtract more ambient light per-pixel. 0 = full subtraction (disable Unity ambient), 1 = no subtraction (keep all Unity ambient). Default 0.85 keeps 85% of ambient."));
|
|
if (!isAmbientProbeValid && unityAmbientLighting.value.floatValue < 1f) {
|
|
WarnAmbientProbeEmpty();
|
|
}
|
|
}
|
|
|
|
showFallbacks = DrawSectionHeader("Fallbacks", PrefKeyFallbacks, showFallbacks);
|
|
if (showFallbacks) {
|
|
PropertyField(fallbackReflectionProbes, new GUIContent("Reflection Probes", "Uses nearby reflection probes when rays miss"));
|
|
if (fallbackReflectionProbes.value.boolValue) {
|
|
EditorGUI.indentLevel++;
|
|
PropertyField(probesIntensity, new GUIContent("Intensity"));
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
PropertyField(fallbackAmbient, new GUIContent("APV/Sky"));
|
|
if (!isAmbientProbeValid && fallbackAmbient.value.floatValue > 0f) {
|
|
WarnAmbientProbeEmpty();
|
|
}
|
|
|
|
PropertyField(fallbackReflectiveShadowMap, new GUIContent("Reflective Shadow Map", "Separate system - works independently"));
|
|
if (fallbackReflectiveShadowMap.value.boolValue) {
|
|
EditorGUI.indentLevel++;
|
|
if (!RadiantShadowMap.installed) {
|
|
EditorGUILayout.HelpBox("Add Radiant Shadow Map script to the main directional light.", MessageType.Warning);
|
|
}
|
|
PropertyField(reflectiveShadowMapIntensity, new GUIContent("Intensity"));
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
PropertyField(fallbackReuseRays, new GUIContent("Reuse Rays", "Temporal fallback - works alongside other fallbacks"));
|
|
if (fallbackReuseRays.value.boolValue) {
|
|
EditorGUI.indentLevel++;
|
|
PropertyField(rayReuse, new GUIContent("Intensity"));
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
|
|
PropertyField(fallbackDefaultAmbient, new GUIContent("Minimum Ambient", "Default color used when other fallbacks fail."));
|
|
}
|
|
|
|
showRaymarch = DrawSectionHeader("Raymarch & Performance", PrefKeyRaymarch, showRaymarch);
|
|
if (showRaymarch) {
|
|
EditorGUILayout.BeginHorizontal();
|
|
EditorGUILayout.PrefixLabel("Sample Presets:");
|
|
selectedPreset = (PerformancePreset)EditorGUILayout.EnumPopup(selectedPreset);
|
|
if (GUILayout.Button("Apply", GUILayout.Width(50))) {
|
|
ApplyPerformancePreset(selectedPreset);
|
|
}
|
|
if (GUILayout.Button("?", GUILayout.Width(20))) {
|
|
EditorUtility.DisplayDialog("Sample Presets", "These presets are orientative and aimed for full-HD resolution (1920x1080). You may need to adjust the settings manually, for example, you can keep a max distance higher while keeping ray count to 1. You can also reduce raymarch accuracy in 2K/4K to improve performance.", "OK");
|
|
}
|
|
EditorGUILayout.EndHorizontal();
|
|
EditorGUILayout.Space(4);
|
|
|
|
PropertyField(raytracerAccuracy, new GUIContent("Raymarch Accuracy", "This option effectively downscales the input depth buffer to improve GPU cache efficiency improving performance significantly."));
|
|
PropertyField(downsampling);
|
|
PropertyField(rayCount);
|
|
PropertyField(rayMaxLength, new GUIContent("Max Distance"));
|
|
PropertyField(rayMaxSamples, new GUIContent("Max Samples"));
|
|
PropertyField(rayJitter, new GUIContent("Jittering"));
|
|
PropertyField(thickness);
|
|
|
|
PropertyField(blurSpread, new GUIContent("Blur Spread", "Multiplier for the spatial blur spread. Increase to reduce flickering at lower resolutions. A value of 2 at 1080p matches the natural blur spread at 4K."));
|
|
|
|
PropertyField(transparencySupport);
|
|
if (transparencySupport.value.boolValue) {
|
|
EditorGUI.indentLevel++;
|
|
PropertyField(transparentLayerMask, new GUIContent("Layer Mask"));
|
|
EditorGUILayout.HelpBox("RadiantTransparentSupport script can also be added to specific transparent objects in addition to use (or not) a layer mask.", MessageType.Info);
|
|
EditorGUILayout.HelpBox("GI for transparent objects is rendered before the transparent pass. Transparent shaders can read from _RadiantGITexture to add the GI on top of transparent surfaces.", MessageType.Info);
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
}
|
|
|
|
showTemporal = DrawSectionHeader("Temporal Filter", PrefKeyTemporal, showTemporal);
|
|
if (showTemporal) {
|
|
PropertyField(temporalStability, new GUIContent("Temporal Stability", "Maximum number of frames to accumulate in temporal history. Higher values provide more stability but may increase ghosting."));
|
|
PropertyField(temporalResponseSpeed, new GUIContent("Motion Response", "How quickly the temporal blend reacts to motion. Higher values reduce ghosting but increase noise during movement."));
|
|
PropertyField(darkThreshold, new GUIContent("Dark Threshold", "Brightness threshold below which dark threshold is applied. When colors are very dark (brightness is low), this threshold activates to improve stability in dark areas."));
|
|
PropertyField(darkThresholdMultiplier, new GUIContent("Dark Stability Multiplier", "Multiplier for dark threshold stability. Higher values provide more stability in dark areas but may increase ghosting."));
|
|
}
|
|
|
|
showArtistic = DrawSectionHeader("Artistic Controls", PrefKeyArtistic, showArtistic);
|
|
if (showArtistic) {
|
|
PropertyField(aoInfluence, new GUIContent("AO Influence"));
|
|
PropertyField(occlusionIntensity, new GUIContent("Occlusion Intensity", "Intensity of occlusion maps used to attenuate GI"));
|
|
PropertyField(brightnessThreshold, new GUIContent("Source Brightness Threshold"));
|
|
PropertyField(brightnessMax, new GUIContent("GI Maximum Brightness"));
|
|
PropertyField(giWeight, new GUIContent("GI Weight"));
|
|
PropertyField(saturation, new GUIContent("GI Saturation"));
|
|
PropertyField(nearCameraAttenuation);
|
|
PropertyField(limitToVolumeBounds);
|
|
PropertyField(stencilCheck);
|
|
if (stencilCheck.value.boolValue) {
|
|
PropertyField(stencilValue);
|
|
PropertyField(stencilCompareFunction);
|
|
}
|
|
}
|
|
|
|
showDebug = DrawSectionHeader("Debug", PrefKeyDebug, showDebug);
|
|
if (showDebug) {
|
|
PropertyField(showInEditMode);
|
|
PropertyField(showInSceneView);
|
|
if (showInSceneView.value.boolValue && !Application.isPlaying) {
|
|
EditorGUILayout.HelpBox("Scene View can appear noisier because motion vectors are not fully updated outside Play mode.", MessageType.Warning);
|
|
}
|
|
PropertyField(debugView);
|
|
int debugViewInt = debugView.value.intValue;
|
|
if (debugViewInt == (int)DebugView.ReflectiveShadowMap && !fallbackReflectiveShadowMap.value.boolValue) {
|
|
EditorGUILayout.HelpBox("Reflective Shadow Map fallback option is not enabled. No debug output available.", MessageType.Warning);
|
|
}
|
|
else if (debugView.value.intValue == (int)DebugView.Depth) {
|
|
PropertyField(debugDepthMultiplier);
|
|
}
|
|
else if (debugView.value.intValue == (int)DebugView.MotionVectors) {
|
|
PropertyField(debugMotionVectorMultiplier);
|
|
}
|
|
PropertyField(compareMode);
|
|
if (compareMode.value.boolValue) {
|
|
EditorGUI.indentLevel++;
|
|
PropertyField(compareSameSide, new GUIContent("Same Side"));
|
|
if (compareSameSide.value.boolValue) {
|
|
PropertyField(comparePanning, new GUIContent("Panning"));
|
|
}
|
|
else {
|
|
PropertyField(compareLineAngle, new GUIContent("Line Angle"));
|
|
PropertyField(compareLineWidth, new GUIContent("Line Width"));
|
|
}
|
|
EditorGUI.indentLevel--;
|
|
}
|
|
}
|
|
|
|
serializedObject.ApplyModifiedProperties();
|
|
}
|
|
|
|
void ShowURPRendererAsset (UnityEngine.Rendering.Universal.UniversalRenderPipelineAsset pipe) {
|
|
FieldInfo renderersField = pipe.GetType().GetField("m_RendererDataList", BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
|
|
if (renderersField == null) return;
|
|
|
|
object[] rendererDataList = renderersField.GetValue(pipe) as object[];
|
|
if (rendererDataList == null || rendererDataList.Length == 0) return;
|
|
|
|
FieldInfo defaultIndexField = pipe.GetType().GetField("m_DefaultRendererIndex", BindingFlags.NonPublic | BindingFlags.Instance);
|
|
int defaultIndex = 0;
|
|
if (defaultIndexField != null) {
|
|
defaultIndex = (int)defaultIndexField.GetValue(pipe);
|
|
}
|
|
if (defaultIndex < 0 || defaultIndex >= rendererDataList.Length) {
|
|
defaultIndex = 0;
|
|
}
|
|
|
|
Object rendererData = rendererDataList[defaultIndex] as Object;
|
|
if (rendererData != null) {
|
|
Selection.activeObject = rendererData;
|
|
EditorGUIUtility.PingObject(rendererData);
|
|
}
|
|
}
|
|
|
|
void ApplyPerformancePreset(PerformancePreset preset) {
|
|
switch (preset) {
|
|
case PerformancePreset.VeryFast:
|
|
SetOverride(raytracerAccuracy, 6);
|
|
SetOverride(downsampling, 2f);
|
|
SetOverride(rayCount, 1);
|
|
SetOverride(rayJitter, 1f);
|
|
SetOverride(rayMaxSamples, 12);
|
|
SetOverride(rayMaxLength, 6f);
|
|
SetOverride(thickness, 0.4f);
|
|
SetOverride(temporalStability, 16);
|
|
break;
|
|
case PerformancePreset.Fast:
|
|
SetOverride(raytracerAccuracy, 7);
|
|
SetOverride(downsampling, 1f);
|
|
SetOverride(rayCount, 1);
|
|
SetOverride(rayJitter, 0.7f);
|
|
SetOverride(rayMaxSamples, 16);
|
|
SetOverride(rayMaxLength, 8f);
|
|
SetOverride(thickness, 0.35f);
|
|
SetOverride(temporalStability, 14);
|
|
break;
|
|
case PerformancePreset.Default:
|
|
SetOverride(raytracerAccuracy, 8);
|
|
SetOverride(downsampling, 1f);
|
|
SetOverride(rayCount, 1);
|
|
SetOverride(rayJitter, 0.3f);
|
|
SetOverride(rayMaxSamples, 32);
|
|
SetOverride(rayMaxLength, 12f);
|
|
SetOverride(thickness, 0.25f);
|
|
SetOverride(temporalStability, 12);
|
|
break;
|
|
case PerformancePreset.HighQuality:
|
|
SetOverride(raytracerAccuracy, 7);
|
|
SetOverride(downsampling, 1f);
|
|
SetOverride(rayCount, 2);
|
|
SetOverride(rayJitter, 0.2f);
|
|
SetOverride(rayMaxSamples, 34);
|
|
SetOverride(rayMaxLength, 14f);
|
|
SetOverride(thickness, 0.2f);
|
|
SetOverride(temporalStability, 12);
|
|
break;
|
|
case PerformancePreset.Ultra:
|
|
SetOverride(raytracerAccuracy, 8);
|
|
SetOverride(downsampling, 1f);
|
|
SetOverride(rayCount, 3);
|
|
SetOverride(rayJitter, 0.2f);
|
|
SetOverride(rayMaxSamples, 36);
|
|
SetOverride(rayMaxLength, 18f);
|
|
SetOverride(thickness, 0.15f);
|
|
SetOverride(temporalStability, 12);
|
|
break;
|
|
}
|
|
}
|
|
|
|
void SetOverride(SerializedDataParameter param, int value) {
|
|
param.value.intValue = value;
|
|
param.overrideState.boolValue = true;
|
|
}
|
|
|
|
void SetOverride(SerializedDataParameter param, float value) {
|
|
param.value.floatValue = value;
|
|
param.overrideState.boolValue = true;
|
|
}
|
|
|
|
bool DrawSectionHeader (string title, string prefKey, bool expanded) {
|
|
if (sectionHeaderStyle == null) {
|
|
sectionHeaderStyle = new GUIStyle("ShurikenModuleTitle");
|
|
sectionHeaderStyle.fontStyle = FontStyle.Bold;
|
|
sectionHeaderStyle.fixedHeight = 22f;
|
|
sectionHeaderStyle.contentOffset = new Vector2(20f, -2f);
|
|
}
|
|
|
|
Rect rect = GUILayoutUtility.GetRect(16f, 22f, sectionHeaderStyle);
|
|
GUI.Box(rect, title, sectionHeaderStyle);
|
|
|
|
Rect toggleRect = new Rect(rect.x + 6f, rect.y + 2f, 13f, 13f);
|
|
if (Event.current.type == EventType.Repaint) {
|
|
EditorStyles.foldout.Draw(toggleRect, false, false, expanded, false);
|
|
}
|
|
|
|
if (Event.current.type == EventType.MouseDown && rect.Contains(Event.current.mousePosition)) {
|
|
expanded = !expanded;
|
|
EditorPrefs.SetBool(prefKey, expanded);
|
|
Event.current.Use();
|
|
}
|
|
|
|
return expanded;
|
|
}
|
|
|
|
void WarnAmbientProbeEmpty () {
|
|
EditorGUILayout.HelpBox("Ambient Probe is empty. Click Update to regenerate it from current environment lighting.", MessageType.Info);
|
|
if (GUILayout.Button("Update Ambient Probe")) {
|
|
DynamicGI.UpdateEnvironment();
|
|
isAmbientProbeValid = RadiantRenderFeature.IsAmbientProbeValid(RenderSettings.ambientProbe);
|
|
}
|
|
}
|
|
|
|
Light GetDirectionalLight () {
|
|
Light sun = RenderSettings.sun;
|
|
if (sun != null && sun.type == LightType.Directional) {
|
|
return sun;
|
|
}
|
|
#if UNITY_2022_2_OR_NEWER
|
|
Light[] lights = Object.FindObjectsByType<Light>(FindObjectsSortMode.None);
|
|
#else
|
|
Light[] lights = Object.FindObjectsOfType<Light>();
|
|
#endif
|
|
for (int i = 0; i < lights.Length; i++) {
|
|
Light light = lights[i];
|
|
if (light != null && light.type == LightType.Directional) {
|
|
return light;
|
|
}
|
|
}
|
|
return null;
|
|
}
|
|
}
|
|
}
|