Die Figuren (Einheiten, Monster, Völker, Helden) bekommen den Materialweg der Welt; dazu Umgebungsverdeckung für die ganze Szene. - Surface-Materialien für alle 146 Figurenmaterialien (142 neu unter Materials/Units/, die LN_Boss_* gehörten schon zu den Gebäuden). Farbe, Rauigkeit und Emission bleiben die Blender-Werte; Metalle werden metallisch (vorher war keines der 414 Figurenmaterialien metallisch), ein Randlicht hebt die Silhouetten im Draufblick vom Boden ab. - Oberflächenstruktur je Materialfamilie im eigenen Raum der Figur, nur in den HUD-Porträts. Im Feld (30-60 px hohe Figuren) war sie nicht zu sehen und kostete rund 10 % Bildrate. - Ringborkes 4k-Satz liegt am Schnittholz (RB_Cutwood), wohin er gehört; U5.3 hatte ihn an die Rinde gebunden. Verwaistes RB_Bark.mat entfernt. - SSAO über LuneProjectSetup: nach den opaken Objekten, halbe Auflösung, Radius 0,35 m, Ausblendung ab 260 m. Standardmäßig an (Entscheidung des Projektinhabers), in den Optionen abschaltbar, -luneSsao 0 für eine Sitzung. Die Variante mit Tiefen-Normalen-Vorpass kostete 19-28 %. - Shader: Steinreliefkarte nur noch für Gelände, Stein, Pflaster, Erde. - Werkzeug: Übersichtsbilder mit LUNE_DRESS=1 eingekleidet wie im Spiel; das Materialset wird nach der leeren Vorschauszene geladen (sie entlädt unreferenzierte Assets). - Tests: EditMode 29/29, PlayMode 14/14, Verify 718/0, Player-Selbsttest 30/30 (4 neue zur SSAO-Option), Fingerabdrücke unverändert (DCE95C96556F3A1A, 7B8E43AEFC0D60C5). - Leistung (A/B mit U5.3 im selben Lauf): Mid nah 177,7 -> 148,5 fps (-16 %), Karte 127,8 -> 111,5 fps (-13 %); ohne SSAO -3,5 / -4,5 %. - Doku: U5-VISUAL (U5.4), PORT-STATUS, PORT-QA; Bilder screenshots/u5.4/. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
130 lines
6.3 KiB
C#
130 lines
6.3 KiB
C#
using System.IO;
|
||
using System.Linq;
|
||
using UnityEditor;
|
||
using UnityEngine;
|
||
using UnityEngine.Rendering;
|
||
using UnityEngine.Rendering.Universal;
|
||
|
||
namespace Luneraria.EditorTools
|
||
{
|
||
/// <summary>
|
||
/// Rendering setup of the project (URP asset and renderer, linear colour space, SSAO since
|
||
/// U5.4), idempotent.
|
||
/// Unity -batchmode -projectPath . -executeMethod Luneraria.EditorTools.LuneProjectSetup.ConfigureRendering
|
||
/// </summary>
|
||
public static class LuneProjectSetup
|
||
{
|
||
public const string SettingsFolder = "Assets/Luneraria/Settings/Rendering";
|
||
public const string PipelinePath = SettingsFolder + "/Luneraria_URP.asset";
|
||
public const string RendererPath = SettingsFolder + "/Luneraria_URP_Renderer.asset";
|
||
|
||
public static void ConfigureRendering()
|
||
{
|
||
int code = 0;
|
||
try
|
||
{
|
||
Configure();
|
||
}
|
||
catch (System.Exception error)
|
||
{
|
||
Debug.LogError("LUNE_SETUP failed: " + error);
|
||
code = 1;
|
||
}
|
||
EditorApplication.Exit(code);
|
||
}
|
||
|
||
public static UniversalRenderPipelineAsset Configure()
|
||
{
|
||
Directory.CreateDirectory(SettingsFolder);
|
||
AssetDatabase.Refresh();
|
||
var asset = AssetDatabase.LoadAssetAtPath<UniversalRenderPipelineAsset>(PipelinePath);
|
||
if (asset == null)
|
||
{
|
||
var renderer = ScriptableObject.CreateInstance<UniversalRendererData>();
|
||
AssetDatabase.CreateAsset(renderer, RendererPath);
|
||
ResourceReloader.ReloadAllNullIn(renderer, UniversalRenderPipelineAsset.packagePath);
|
||
asset = UniversalRenderPipelineAsset.Create(renderer);
|
||
AssetDatabase.CreateAsset(asset, PipelinePath);
|
||
}
|
||
// The Godot sun reaches 190 m with four splits (scripts/luneraria/view/lune_world.gd).
|
||
asset.shadowDistance = 190f;
|
||
asset.shadowCascadeCount = 4;
|
||
asset.supportsHDR = true;
|
||
asset.msaaSampleCount = 4;
|
||
asset.useSRPBatcher = true;
|
||
EditorUtility.SetDirty(asset);
|
||
Ssao(AssetDatabase.LoadAssetAtPath<UniversalRendererData>(RendererPath));
|
||
GraphicsSettings.defaultRenderPipeline = asset;
|
||
int current = QualitySettings.GetQualityLevel();
|
||
for (int level = 0; level < QualitySettings.names.Length; level++)
|
||
{
|
||
QualitySettings.SetQualityLevel(level, false);
|
||
QualitySettings.renderPipeline = asset;
|
||
}
|
||
QualitySettings.SetQualityLevel(current, false);
|
||
PlayerSettings.colorSpace = ColorSpace.Linear;
|
||
MoveInto("Assets/UniversalRenderPipelineGlobalSettings.asset", SettingsFolder + "/UniversalRenderPipelineGlobalSettings.asset");
|
||
MoveInto("Assets/DefaultVolumeProfile.asset", SettingsFolder + "/DefaultVolumeProfile.asset");
|
||
AssetDatabase.SaveAssets();
|
||
Debug.Log("LUNE_SETUP rendering: " + PipelinePath + ", colour space " + PlayerSettings.colorSpace);
|
||
return asset;
|
||
}
|
||
|
||
/// <summary>SSAO intensity, radius (m) and fade distance (m) for the top-down camera (U5.4).</summary>
|
||
public const float SsaoIntensity = 1.2f;
|
||
public const float SsaoRadius = .35f;
|
||
public const float SsaoFalloff = 260f;
|
||
|
||
/// <summary>
|
||
/// Screen-space ambient occlusion (U5.4): contact shadows of figures and buildings on the
|
||
/// ground and occlusion in crevices, the depth cue of current renderers. Radius in metres
|
||
/// for figures of 1–2 m seen from 20–100 m; it fades only beyond the overview distance.
|
||
/// The feature is a sub-asset of the renderer and listed in its feature map; updated in place.
|
||
/// </summary>
|
||
static void Ssao(UniversalRendererData renderer)
|
||
{
|
||
if (renderer == null)
|
||
return;
|
||
var feature = renderer.rendererFeatures.OfType<ScreenSpaceAmbientOcclusion>().FirstOrDefault();
|
||
if (feature == null)
|
||
{
|
||
feature = ScriptableObject.CreateInstance<ScreenSpaceAmbientOcclusion>();
|
||
feature.name = "ScreenSpaceAmbientOcclusion";
|
||
AssetDatabase.AddObjectToAsset(feature, renderer);
|
||
AssetDatabase.TryGetGUIDAndLocalFileIdentifier(feature, out string _, out long localId);
|
||
var data = new SerializedObject(renderer);
|
||
SerializedProperty list = data.FindProperty("m_RendererFeatures");
|
||
list.arraySize++;
|
||
list.GetArrayElementAtIndex(list.arraySize - 1).objectReferenceValue = feature;
|
||
SerializedProperty map = data.FindProperty("m_RendererFeatureMap");
|
||
map.arraySize++;
|
||
map.GetArrayElementAtIndex(map.arraySize - 1).longValue = localId;
|
||
data.ApplyModifiedPropertiesWithoutUndo();
|
||
}
|
||
var settings = new SerializedObject(feature);
|
||
settings.FindProperty("m_Settings.Intensity").floatValue = SsaoIntensity;
|
||
settings.FindProperty("m_Settings.Radius").floatValue = SsaoRadius;
|
||
settings.FindProperty("m_Settings.Falloff").floatValue = SsaoFalloff;
|
||
settings.FindProperty("m_Settings.DirectLightingStrength").floatValue = .25f;
|
||
// Depth source after the opaques: URP copies the depth it already has, so SSAO needs no
|
||
// second geometry pass (the depth-normals prepass cost 19–28 % frame rate on the M5).
|
||
settings.FindProperty("m_Settings.Source").enumValueIndex = 0;
|
||
settings.FindProperty("m_Settings.Downsample").boolValue = true;
|
||
settings.FindProperty("m_Settings.AfterOpaque").boolValue = true;
|
||
settings.ApplyModifiedPropertiesWithoutUndo();
|
||
feature.SetActive(System.Environment.GetEnvironmentVariable("LUNE_SSAO") != "0");
|
||
EditorUtility.SetDirty(feature);
|
||
EditorUtility.SetDirty(renderer);
|
||
}
|
||
|
||
static void MoveInto(string from, string to)
|
||
{
|
||
if (File.Exists(from) && !File.Exists(to))
|
||
{
|
||
string error = AssetDatabase.MoveAsset(from, to);
|
||
if (!string.IsNullOrEmpty(error))
|
||
Debug.LogWarning("LUNE_SETUP move " + from + ": " + error);
|
||
}
|
||
}
|
||
}
|
||
}
|