308 lines
12 KiB
C#
308 lines
12 KiB
C#
|
using System;
|
||
|
using System.Collections.Generic;
|
||
|
using UnityEngine;
|
||
|
using UnityEngine.Rendering;
|
||
|
using UnityEngine.Rendering.Universal;
|
||
|
using ShadowQuality = UnityEngine.ShadowQuality;
|
||
|
using ShadowResolution = UnityEngine.ShadowResolution;
|
||
|
|
||
|
namespace UnityEditor.Rendering.Universal
|
||
|
{
|
||
|
internal class RenderSettingsConverter : RenderPipelineConverter
|
||
|
{
|
||
|
public override int priority => -9000;
|
||
|
public override string name => "Rendering Settings";
|
||
|
|
||
|
public override string info =>
|
||
|
"This converter will look at creating Universal Render Pipeline assets and respective Renderer Assets and configure" +
|
||
|
" their settings based on equivalent settings from builtin renderer.";
|
||
|
|
||
|
public override Type container => typeof(BuiltInToURPConverterContainer);
|
||
|
|
||
|
// Used to store settings specific to Graphics Tiers
|
||
|
GraphicsTierSettings m_GraphicsTierSettings;
|
||
|
|
||
|
// Settings items, currently tracks Quality settings only
|
||
|
List<SettingsItem> m_SettingsItems;
|
||
|
|
||
|
// List of the rendering modes required
|
||
|
List<RenderingMode> m_RenderingModes;
|
||
|
|
||
|
const string k_PipelineAssetPath = "Settings";
|
||
|
|
||
|
public override void OnInitialize(InitializeConverterContext context, Action callback)
|
||
|
{
|
||
|
m_SettingsItems = new List<SettingsItem>();
|
||
|
m_RenderingModes = new List<RenderingMode>();
|
||
|
|
||
|
// check graphics tiers
|
||
|
GatherGraphicsTiers();
|
||
|
|
||
|
// check quality levels
|
||
|
GatherQualityLevels(ref context);
|
||
|
|
||
|
callback?.Invoke();
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Grabs the 3rd tier from the Graphics Tier Settings based off the current build platform
|
||
|
/// </summary>
|
||
|
private void GatherGraphicsTiers()
|
||
|
{
|
||
|
var targetGrp = BuildPipeline.GetBuildTargetGroup(EditorUserBuildSettings.activeBuildTarget);
|
||
|
var tier = EditorGraphicsSettings.GetTierSettings(targetGrp, GraphicsTier.Tier3);
|
||
|
|
||
|
// Add the Graphic Tier Render Path settings as the first rendering mode
|
||
|
m_RenderingModes.Add(GetEquivalentRenderMode(tier.renderingPath));
|
||
|
|
||
|
m_GraphicsTierSettings.RenderingPath = tier.renderingPath;
|
||
|
m_GraphicsTierSettings.ReflectionProbeBlending = tier.reflectionProbeBlending;
|
||
|
m_GraphicsTierSettings.ReflectionProbeBoxProjection = tier.reflectionProbeBoxProjection;
|
||
|
m_GraphicsTierSettings.CascadeShadows = tier.cascadedShadowMaps;
|
||
|
m_GraphicsTierSettings.HDR = tier.hdr;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Iterates over all Quality Settings and saves relevant settings to a RenderSettingsItem.
|
||
|
/// This will also create the required information for the Render Pipeline Converter UI.
|
||
|
/// </summary>
|
||
|
/// <param name="context">Converter context to add elements to.</param>
|
||
|
private void GatherQualityLevels(ref InitializeConverterContext context)
|
||
|
{
|
||
|
var currentQuality = QualitySettings.GetQualityLevel();
|
||
|
var id = 0;
|
||
|
foreach (var levelName in QualitySettings.names)
|
||
|
{
|
||
|
QualitySettings.SetQualityLevel(id);
|
||
|
|
||
|
var projectSettings = new RenderSettingItem
|
||
|
{
|
||
|
Index = id,
|
||
|
LevelName = levelName,
|
||
|
PixelLightCount = QualitySettings.pixelLightCount,
|
||
|
MSAA = QualitySettings.antiAliasing,
|
||
|
Shadows = QualitySettings.shadows,
|
||
|
ShadowResolution = QualitySettings.shadowResolution,
|
||
|
ShadowDistance = QualitySettings.shadowDistance,
|
||
|
ShadowCascadeCount = QualitySettings.shadowCascades,
|
||
|
CascadeSplit2 = QualitySettings.shadowCascade2Split,
|
||
|
CascadeSplit4 = QualitySettings.shadowCascade4Split,
|
||
|
SoftParticles = QualitySettings.softParticles,
|
||
|
};
|
||
|
m_SettingsItems.Add(projectSettings);
|
||
|
|
||
|
var setting = QualitySettings.GetRenderPipelineAssetAt(id);
|
||
|
var item = new ConverterItemDescriptor { name = $"Quality Level {id}: {levelName}" };
|
||
|
|
||
|
if (setting != null)
|
||
|
{
|
||
|
item.warningMessage = setting.GetType() == typeof(UniversalRenderPipelineAsset)
|
||
|
? "Contains URP Asset, will override existing asset."
|
||
|
: "Contains SRP Asset, will override existing asset with URP asset.";
|
||
|
}
|
||
|
|
||
|
context.AddAssetToConvert(item);
|
||
|
id++;
|
||
|
}
|
||
|
|
||
|
QualitySettings.SetQualityLevel(currentQuality);
|
||
|
}
|
||
|
|
||
|
public override void OnRun(ref RunItemContext context)
|
||
|
{
|
||
|
var item = context.item;
|
||
|
// is quality item
|
||
|
if (m_SettingsItems[item.index].GetType() == typeof(RenderSettingItem))
|
||
|
{
|
||
|
GeneratePipelineAsset(m_SettingsItems[item.index] as RenderSettingItem);
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private void GeneratePipelineAsset(RenderSettingItem settings)
|
||
|
{
|
||
|
// store current quality level
|
||
|
var currentQualityLevel = QualitySettings.GetQualityLevel();
|
||
|
|
||
|
//creating pipeline asset
|
||
|
var asset =
|
||
|
ScriptableObject.CreateInstance(typeof(UniversalRenderPipelineAsset)) as UniversalRenderPipelineAsset;
|
||
|
if (!AssetDatabase.IsValidFolder($"Assets/{k_PipelineAssetPath}"))
|
||
|
AssetDatabase.CreateFolder("Assets", k_PipelineAssetPath);
|
||
|
var path = $"Assets/{k_PipelineAssetPath}/{settings.LevelName}_PipelineAsset.asset";
|
||
|
|
||
|
// Setting Pipeline Asset settings
|
||
|
SetPipelineSettings(asset, settings);
|
||
|
|
||
|
// Create Renderers
|
||
|
var defaultIndex = 0;
|
||
|
var renderers = new List<ScriptableRendererData>();
|
||
|
if (m_RenderingModes.Contains(RenderingMode.Forward))
|
||
|
{
|
||
|
renderers.Add(CreateRendererDataAsset(path, RenderingPath.Forward, "ForwardRenderer"));
|
||
|
if (GetEquivalentRenderMode(m_GraphicsTierSettings.RenderingPath) == RenderingMode.Forward)
|
||
|
defaultIndex = m_RenderingModes.IndexOf(RenderingMode.Forward);
|
||
|
}
|
||
|
|
||
|
if (m_RenderingModes.Contains(RenderingMode.Deferred))
|
||
|
{
|
||
|
renderers.Add(CreateRendererDataAsset(path, RenderingPath.DeferredShading, "DeferredRenderer"));
|
||
|
if (GetEquivalentRenderMode(m_GraphicsTierSettings.RenderingPath) == RenderingMode.Deferred)
|
||
|
defaultIndex = m_RenderingModes.IndexOf(RenderingMode.Deferred);
|
||
|
}
|
||
|
|
||
|
asset.m_RendererDataList = renderers.ToArray();
|
||
|
asset.m_DefaultRendererIndex = defaultIndex;
|
||
|
|
||
|
// Create Pipeline asset on disk
|
||
|
AssetDatabase.CreateAsset(asset, path);
|
||
|
// Assign asset
|
||
|
QualitySettings.SetQualityLevel(settings.Index);
|
||
|
QualitySettings.renderPipeline = asset;
|
||
|
|
||
|
// return to original quality level
|
||
|
QualitySettings.SetQualityLevel(currentQualityLevel);
|
||
|
// Set graphics settings
|
||
|
if (currentQualityLevel == settings.Index || GraphicsSettings.defaultRenderPipeline == null || GraphicsSettings.defaultRenderPipeline.GetType() !=
|
||
|
typeof(UniversalRenderPipelineAsset))
|
||
|
{
|
||
|
GraphicsSettings.defaultRenderPipeline = asset;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private ScriptableRendererData CreateRendererDataAsset(string assetPath, RenderingPath renderingPath,
|
||
|
string fileName)
|
||
|
{
|
||
|
var rendererAsset =
|
||
|
UniversalRenderPipelineAsset.CreateRendererAsset(assetPath, RendererType.UniversalRenderer, true, fileName)
|
||
|
as UniversalRendererData;
|
||
|
//Missing API to set deferred or forward
|
||
|
rendererAsset.renderingMode =
|
||
|
renderingPath == RenderingPath.Forward ? RenderingMode.Forward : RenderingMode.Deferred;
|
||
|
//missing API to assign to pipeline asset
|
||
|
return rendererAsset;
|
||
|
}
|
||
|
|
||
|
/// <summary>
|
||
|
/// Sets all relevant RP settings in order they appear in URP
|
||
|
/// </summary>
|
||
|
/// <param name="asset">Pipeline asset to set</param>
|
||
|
/// <param name="settings">The ProjectSettingItem with stored settings</param>
|
||
|
private void SetPipelineSettings(UniversalRenderPipelineAsset asset, RenderSettingItem settings)
|
||
|
{
|
||
|
// General
|
||
|
asset.supportsCameraDepthTexture = settings.SoftParticles;
|
||
|
|
||
|
// Quality
|
||
|
asset.supportsHDR = m_GraphicsTierSettings.HDR;
|
||
|
asset.msaaSampleCount = settings.MSAA == 0 ? 1 : settings.MSAA;
|
||
|
|
||
|
// Main Light
|
||
|
asset.mainLightRenderingMode = settings.PixelLightCount == 0
|
||
|
? LightRenderingMode.Disabled
|
||
|
: LightRenderingMode.PerPixel;
|
||
|
asset.supportsMainLightShadows = settings.Shadows != ShadowQuality.Disable;
|
||
|
asset.mainLightShadowmapResolution =
|
||
|
GetEquivalentMainlightShadowResolution((int)settings.ShadowResolution);
|
||
|
|
||
|
// Additional Lights
|
||
|
asset.additionalLightsRenderingMode = settings.PixelLightCount == 0
|
||
|
? LightRenderingMode.PerVertex
|
||
|
: LightRenderingMode.PerPixel;
|
||
|
asset.maxAdditionalLightsCount = settings.PixelLightCount != 0 ? Mathf.Max(0, settings.PixelLightCount) : 4;
|
||
|
asset.supportsAdditionalLightShadows = settings.Shadows != ShadowQuality.Disable;
|
||
|
asset.additionalLightsShadowmapResolution =
|
||
|
GetEquivalentAdditionalLightAtlasShadowResolution((int)settings.ShadowResolution);
|
||
|
|
||
|
// Reflection Probes
|
||
|
asset.reflectionProbeBlending = m_GraphicsTierSettings.ReflectionProbeBlending;
|
||
|
asset.reflectionProbeBoxProjection = m_GraphicsTierSettings.ReflectionProbeBoxProjection;
|
||
|
|
||
|
// Shadows
|
||
|
asset.shadowDistance = settings.ShadowDistance;
|
||
|
asset.shadowCascadeCount = m_GraphicsTierSettings.CascadeShadows ? settings.ShadowCascadeCount : 1;
|
||
|
asset.cascade2Split = settings.CascadeSplit2;
|
||
|
asset.cascade4Split = settings.CascadeSplit4;
|
||
|
asset.supportsSoftShadows = settings.Shadows == ShadowQuality.All;
|
||
|
}
|
||
|
|
||
|
#region HelperFunctions
|
||
|
|
||
|
private static int GetEquivalentMainlightShadowResolution(int value)
|
||
|
{
|
||
|
return GetEquivalentShadowResolution(value);
|
||
|
}
|
||
|
|
||
|
private static int GetEquivalentAdditionalLightAtlasShadowResolution(int value)
|
||
|
{
|
||
|
return GetEquivalentShadowResolution(value);
|
||
|
}
|
||
|
|
||
|
private static int GetEquivalentShadowResolution(int value)
|
||
|
{
|
||
|
switch (value)
|
||
|
{
|
||
|
case 0: // low
|
||
|
return 1024;
|
||
|
case 1: // med
|
||
|
return 2048;
|
||
|
case 2: // high
|
||
|
return 4096;
|
||
|
case 3: // very high
|
||
|
return 4096;
|
||
|
default: // backup
|
||
|
return 1024;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
private RenderingMode GetEquivalentRenderMode(RenderingPath path)
|
||
|
{
|
||
|
switch (path)
|
||
|
{
|
||
|
case RenderingPath.VertexLit:
|
||
|
case RenderingPath.Forward:
|
||
|
return RenderingMode.Forward;
|
||
|
case RenderingPath.DeferredShading:
|
||
|
return RenderingMode.Deferred;
|
||
|
default:
|
||
|
return RenderingMode.Forward;
|
||
|
}
|
||
|
}
|
||
|
|
||
|
#endregion
|
||
|
|
||
|
#region Data
|
||
|
|
||
|
private struct GraphicsTierSettings
|
||
|
{
|
||
|
public bool ReflectionProbeBoxProjection;
|
||
|
public bool ReflectionProbeBlending;
|
||
|
public bool CascadeShadows;
|
||
|
public bool HDR;
|
||
|
public RenderingPath RenderingPath;
|
||
|
}
|
||
|
|
||
|
private class SettingsItem { }
|
||
|
|
||
|
private class RenderSettingItem : SettingsItem
|
||
|
{
|
||
|
// General
|
||
|
public int Index;
|
||
|
|
||
|
public string LevelName;
|
||
|
|
||
|
// Settings
|
||
|
public int PixelLightCount;
|
||
|
public int MSAA;
|
||
|
public ShadowQuality Shadows;
|
||
|
public ShadowResolution ShadowResolution;
|
||
|
public float ShadowDistance;
|
||
|
public int ShadowCascadeCount;
|
||
|
public float CascadeSplit2;
|
||
|
public Vector3 CascadeSplit4;
|
||
|
public bool SoftParticles;
|
||
|
}
|
||
|
|
||
|
#endregion
|
||
|
}
|
||
|
}
|