Streamingle_URP/Assets/External/RadiantGI/Editor/RadiantGlobalIlluminationEditor.cs

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;
}
}
}