Delegate field layer projection to EveUnity

This commit is contained in:
Meta Vens 2026-07-10 15:57:34 +01:00
commit d863c7e7e9
3 changed files with 52 additions and 200 deletions

View file

@ -1,225 +1,66 @@
using System;
using System.Collections.Generic;
using GameCult.Aetheria.State.Verse;
using Unity.Mathematics;
using GameCult.Eve.PluginFields;
using GameCult.Eve.UnityScene.Fields;
using UnityEngine;
using UnityEngine.Experimental.Rendering;
using UnityEngine.UI;
public sealed class AetheriaRenderSplatLayerRenderer : MonoBehaviour
{
[SerializeField]
private AetheriaRenderSplatRasterizer rasterizer;
[SerializeField]
private AetheriaRenderSplatLayerBinding[] bindings =
[SerializeField] private EveFieldsSplatLayerRenderer renderer;
[SerializeField] private AetheriaRenderSplatLayerBinding[] bindings =
{
new AetheriaRenderSplatLayerBinding
{
LayerKey = AetheriaRuntimeRenderSplatLayerKeys.GravityHeight,
MaterialTextureProperty = "_DetailTex",
GlobalTextureName = "_AetheriaGravityHeight"
},
new AetheriaRenderSplatLayerBinding
{
LayerKey = AetheriaRuntimeRenderSplatLayerKeys.FogTint,
MaterialTextureProperty = "_DetailTex",
GlobalTextureName = "_NebulaTint"
},
new AetheriaRenderSplatLayerBinding
{
LayerKey = AetheriaRuntimeRenderSplatLayerKeys.FogSurfaceHeight,
GlobalTextureName = "_NebulaSurfaceHeight",
WidthScale = 0.5f,
HeightScale = 0.5f
},
new AetheriaRenderSplatLayerBinding
{
LayerKey = AetheriaRuntimeRenderSplatLayerKeys.FogPatchHeight,
GlobalTextureName = "_NebulaPatchHeight",
WidthScale = 0.5f,
HeightScale = 0.5f
},
new AetheriaRenderSplatLayerBinding
{
LayerKey = AetheriaRuntimeRenderSplatLayerKeys.FogPatch,
GlobalTextureName = "_NebulaPatch",
WidthScale = 0.5f,
HeightScale = 0.5f
},
new AetheriaRenderSplatLayerBinding
{
LayerKey = AetheriaRuntimeRenderSplatLayerKeys.Influence,
MaterialTextureProperty = "_DetailTex",
GlobalTextureName = "_AetheriaInfluence"
}
Binding(EveFieldsSplatLayerKeys.GravityHeight, "_AetheriaGravityHeight"),
Binding(EveFieldsSplatLayerKeys.FogTint, "_NebulaTint"),
Binding(EveFieldsSplatLayerKeys.FogSurfaceHeight, "_NebulaSurfaceHeight", 0.5f),
Binding(EveFieldsSplatLayerKeys.FogPatchHeight, "_NebulaPatchHeight", 0.5f),
Binding(EveFieldsSplatLayerKeys.FogPatch, "_NebulaPatch", 0.5f),
Binding(EveFieldsSplatLayerKeys.Influence, "_AetheriaInfluence")
};
private readonly Dictionary<string, RenderTexture> _texturesByLayerKey =
new Dictionary<string, RenderTexture>(StringComparer.Ordinal);
private void Reset()
{
rasterizer = GetComponent<AetheriaRenderSplatRasterizer>();
}
public bool TryGetTexture(string layerKey, out RenderTexture texture)
{
return _texturesByLayerKey.TryGetValue(layerKey ?? "", out texture);
ResolveRenderer();
return renderer != null && renderer.TryGetTexture(layerKey, out texture);
}
public void Render(
AetheriaRuntimeRenderSplatsViewportDocument document,
int width,
int height)
public void Render(AetheriaRuntimeRenderSplatsViewportDocument document, int width, int height)
{
if (document == null)
return;
ResolveRasterizer();
if (rasterizer == null)
return;
var layers = document.Layers ?? Array.Empty<AetheriaRuntimeRenderSplatLayerDefinition>();
for (var layerIndex = 0; layerIndex < layers.Count; layerIndex++)
if (document == null) return;
ResolveRenderer();
if (renderer == null) return;
var targets = new EveFieldsSplatLayerTarget[bindings?.Length ?? 0];
for (var index = 0; index < targets.Length; index++) targets[index] = bindings[index]?.CreateTarget();
renderer.Render(document, targets, width, height);
for (var index = 0; index < targets.Length; index++)
{
var layer = layers[layerIndex];
if (layer == null || string.IsNullOrWhiteSpace(layer.LayerKey))
continue;
foreach (var binding in bindings ?? Array.Empty<AetheriaRenderSplatLayerBinding>())
{
if (binding == null ||
!binding.Enabled ||
!string.Equals(binding.LayerKey, layer.LayerKey, StringComparison.Ordinal))
{
continue;
}
var texture = EnsureTexture(binding, layer, width, height);
rasterizer.RenderLayerToTarget(
document,
texture,
layerIndex,
ResolveMaterialPass(layer.BlendMode),
ResolveClearColor(layer));
ApplyBinding(binding, texture);
_texturesByLayerKey[layer.LayerKey] = texture;
}
var binding = bindings[index];
var target = targets[index];
if (binding == null || target?.TargetTexture == null) continue;
binding.TargetTexture = target.TargetTexture;
ApplyBinding(binding, target.TargetTexture);
}
}
private void ResolveRasterizer()
private void ResolveRenderer()
{
if (rasterizer != null)
return;
rasterizer = GetComponent<AetheriaRenderSplatRasterizer>();
if (rasterizer == null)
rasterizer = gameObject.AddComponent<AetheriaRenderSplatRasterizer>();
if (renderer != null) return;
renderer = GetComponent<EveFieldsSplatLayerRenderer>();
if (renderer == null) renderer = gameObject.AddComponent<EveFieldsSplatLayerRenderer>();
}
private RenderTexture EnsureTexture(
AetheriaRenderSplatLayerBinding binding,
AetheriaRuntimeRenderSplatLayerDefinition layer,
int width,
int height)
{
var targetWidth = math.max(1, Mathf.RoundToInt(width * Mathf.Max(0.01f, binding.WidthScale)));
var targetHeight = math.max(1, Mathf.RoundToInt(height * Mathf.Max(0.01f, binding.HeightScale)));
var format = ResolveGraphicsFormat(binding.GraphicsFormatOverride, layer.GraphicsFormat);
var existing = binding.TargetTexture;
if (existing != null &&
existing.width == targetWidth &&
existing.height == targetHeight &&
existing.graphicsFormat == format)
{
return existing;
}
if (existing != null)
{
existing.Release();
Destroy(existing);
}
var descriptor = new RenderTextureDescriptor(targetWidth, targetHeight)
{
depthBufferBits = 0,
graphicsFormat = format,
msaaSamples = 1,
sRGB = false,
useMipMap = binding.UseMipMaps,
autoGenerateMips = binding.UseMipMaps
};
binding.TargetTexture = new RenderTexture(descriptor)
{
name = $"Aetheria {layer.LayerKey}",
filterMode = binding.FilterMode,
wrapMode = TextureWrapMode.Clamp
};
binding.TargetTexture.Create();
return binding.TargetTexture;
}
private static GraphicsFormat ResolveGraphicsFormat(string bindingOverride, string layerFormat)
{
var value = string.IsNullOrWhiteSpace(bindingOverride) ? layerFormat : bindingOverride;
return Enum.TryParse(value, out GraphicsFormat format)
? format
: GraphicsFormat.R16_SFloat;
}
private static int ResolveMaterialPass(string blendMode)
{
switch (blendMode)
{
case AetheriaRuntimeRenderSplatBlendModes.Max:
return 1;
case AetheriaRuntimeRenderSplatBlendModes.Alpha:
return 2;
default:
return 0;
}
}
private static Color ResolveClearColor(AetheriaRuntimeRenderSplatLayerDefinition layer)
{
return new Color(
(float)layer.ClearR,
(float)layer.ClearG,
(float)layer.ClearB,
(float)layer.ClearA);
}
private static AetheriaRenderSplatLayerBinding Binding(string layerKey, string globalTextureName, float scale = 1f) =>
new AetheriaRenderSplatLayerBinding { LayerKey = layerKey, GlobalTextureName = globalTextureName, WidthScale = scale, HeightScale = scale };
private static void ApplyBinding(AetheriaRenderSplatLayerBinding binding, RenderTexture texture)
{
if (binding.Display != null)
{
var material = binding.Display.material;
if (material != null && !string.IsNullOrWhiteSpace(binding.MaterialTextureProperty))
material.SetTexture(binding.MaterialTextureProperty, texture);
else
binding.Display.material.mainTexture = texture;
if (material != null && !string.IsNullOrWhiteSpace(binding.MaterialTextureProperty)) material.SetTexture(binding.MaterialTextureProperty, texture);
else binding.Display.material.mainTexture = texture;
}
if (!string.IsNullOrWhiteSpace(binding.GlobalTextureName))
Shader.SetGlobalTexture(binding.GlobalTextureName, texture);
}
private void OnDisable()
{
foreach (var binding in bindings ?? Array.Empty<AetheriaRenderSplatLayerBinding>())
{
if (binding?.TargetTexture == null)
continue;
binding.TargetTexture.Release();
Destroy(binding.TargetTexture);
binding.TargetTexture = null;
}
_texturesByLayerKey.Clear();
if (!string.IsNullOrWhiteSpace(binding.GlobalTextureName)) Shader.SetGlobalTexture(binding.GlobalTextureName, texture);
}
}
@ -232,10 +73,21 @@ public sealed class AetheriaRenderSplatLayerBinding
public string MaterialTextureProperty = "_DetailTex";
public string GlobalTextureName = "";
public string GraphicsFormatOverride = "";
public float WidthScale = 1.0f;
public float HeightScale = 1.0f;
public float WidthScale = 1f;
public float HeightScale = 1f;
public bool UseMipMaps;
public FilterMode FilterMode = FilterMode.Bilinear;
[NonSerialized]
public RenderTexture TargetTexture;
[NonSerialized] public RenderTexture TargetTexture;
public EveFieldsSplatLayerTarget CreateTarget() => new EveFieldsSplatLayerTarget
{
Enabled = Enabled,
LayerKey = LayerKey,
GraphicsFormatOverride = GraphicsFormatOverride,
WidthScale = WidthScale,
HeightScale = HeightScale,
UseMipMaps = UseMipMaps,
FilterMode = FilterMode,
TargetTexture = TargetTexture
};
}

View file

@ -24,7 +24,7 @@
"org.gamecult.cultlib": "https://github.com/GameCult/CultLib.git?path=/unity/org.gamecult.cultlib#cultlib-unity-source-v1.0.3-r2",
"org.gamecult.eve.surface": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.surface#eveunity-surface-v0.1.0",
"org.gamecult.eve.plugin-fields": "https://github.com/GameCult/EvePlugins.git?path=/plugins/eve-plugin-fields/unity/org.gamecult.eve.plugin-fields#eve-plugin-fields-unity-v0.1.1",
"org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.1.2",
"org.gamecult.eve.unity-scene": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.1.3",
"org.gamecult.eve.unity-uitoolkit": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-uitoolkit#eveunity-uitoolkit-v0.1.0",
"com.unity.modules.accessibility": "1.0.0",
"com.unity.modules.adaptiveperformance": "1.0.0",

View file

@ -340,7 +340,7 @@
"hash": "e10821f1cc81f619479c6507438f6a097d1f0ce2"
},
"org.gamecult.eve.unity-scene": {
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.1.2",
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-scene#eveunity-scene-v0.1.3",
"depth": 0,
"source": "git",
"dependencies": {
@ -348,7 +348,7 @@
"org.gamecult.eve.plugin-fields": "0.1.1",
"org.gamecult.eve.surface": "0.1.0"
},
"hash": "3e23fff486f2d29451cad59eafc7a6a2d4ac460b"
"hash": "9b1d316f68bf979acf75c5206a3733344879d1db"
},
"org.gamecult.eve.unity-uitoolkit": {
"version": "https://github.com/GameCult/EveUnity.git?path=/packages/org.gamecult.eve.unity-uitoolkit#eveunity-uitoolkit-v0.1.0",