U5.2 Stufen: Zielqualität entlang der Lanes, einfachere Randzonen

Entscheidung des Projektinhabers vom 2. Oktober 2026: Weg 2 (Stufen)
statt Gleichziehen oder Drosseln. Der Lankorridor trägt die vollen
PBR-Sätze; Berge, Kluft und ferner Hintergrund behalten Farbe und
Steinschicht.

- LuneZones: Korridor von 22 m um eine Lane-Mittellinie, ein Gebäude
  oder die Grotte. NearLane entscheidet die Stufe eines Weltknotens.
- Surface-Shader _Quality: 1 bindet Albedo, Normal und ORM triplanar;
  0 lässt die neun Map-Samples weg und behält Farbe, Vertex-Tönung,
  Steinschicht und Emission — das U2-Aussehen der Berge.
- LuneMaterialFactory: Spec.Quality, TerrainEdge.mat für die umgebenden
  Berge; Randmaterialien binden keine PBR-Sätze.
- LuneWorldBuilder.ApplyTier: jeder Weltknoten jenseits des Korridors
  bekommt _Quality 0 über einen MaterialPropertyBlock. Gebäude,
  Einheiten, Wege, Wasser und der innere Boden bleiben Lane-Stufe.
- Nachweis: screenshots/u5/edge-mountains.png (Randstufe) und
  lane-and-edge.png (Übergang Lane → Rand in einem Bild).
- Leistung (macOS-Player, 116 Einheiten): 133 fps Übersicht, 180 fps
  Mid nah — auf dem Niveau des Slices, weil die Messfenster den
  Korridor sehen. Die Ersparnis liegt in Weitwinkeln und am Rand.
- Tests: EditMode 29/29, PlayMode 13/13, Kerntests 457/457. Keine
  Regeländerung.
- Dokumentation: U5-VISUAL (Entscheidung und Umsetzung), PORT-QA,
  PORT-STATUS, KNOWN-BEHAVIOR-DIFFERENCES.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Martin Stickelbroeck 2026-10-02 17:45:51 +02:00
parent 816c127073
commit 7fa038a147
92 changed files with 59810 additions and 59532 deletions

View file

@ -53,6 +53,8 @@ namespace Luneraria.EditorTools
/// <summary>U5 PBR set name (limestone, soil, bark, leaf, rock, water) or "" for none.</summary> /// <summary>U5 PBR set name (limestone, soil, bark, leaf, rock, water) or "" for none.</summary>
public string Pbr = ""; public string Pbr = "";
public float NormalStrength = 1f; public float NormalStrength = 1f;
/// <summary>Weg 2: 1 = lane tier (full PBR), 0 = edge tier (colour + stone relief).</summary>
public float Quality = 1f;
} }
static Shader _surface; static Shader _surface;
@ -204,6 +206,10 @@ namespace Luneraria.EditorTools
{ {
name = "Terrain"; name = "Terrain";
spec = new Spec { Mode = Terrain, StoneScale = .21f }; spec = new Spec { Mode = Terrain, StoneScale = .21f };
result[index] = Create(Folder + "/World/" + name + ".mat", spec);
// Weg 2 edge tier: the surrounding mountains keep colour and stone relief only.
Create(Folder + "/World/TerrainEdge.mat", new Spec { Mode = Terrain, StoneScale = .21f, Quality = 0f });
continue;
} }
else if (shader.EndsWith("river.gdshader")) else if (shader.EndsWith("river.gdshader"))
{ {
@ -314,6 +320,7 @@ namespace Luneraria.EditorTools
material.SetFloat("_StoneScale", spec.StoneScale); material.SetFloat("_StoneScale", spec.StoneScale);
material.SetFloat("_Relief", spec.Relief); material.SetFloat("_Relief", spec.Relief);
material.SetFloat("_NormalStrength", spec.NormalStrength); material.SetFloat("_NormalStrength", spec.NormalStrength);
material.SetFloat("_Quality", spec.Quality);
material.SetFloat("_Cull", spec.DoubleSided ? 0f : 2f); material.SetFloat("_Cull", spec.DoubleSided ? 0f : 2f);
material.SetTexture("_StoneMap", _stone); material.SetTexture("_StoneMap", _stone);
ApplyPbr(material, spec); ApplyPbr(material, spec);
@ -322,14 +329,14 @@ namespace Luneraria.EditorTools
return material; return material;
} }
/// <summary>U5: bind the baked albedo/normal/ORM set of the surface family.</summary> /// <summary>U5: bind the baked albedo/normal/ORM set of the surface family (lane tier only).</summary>
static void ApplyPbr(Material material, Spec spec) static void ApplyPbr(Material material, Spec spec)
{ {
string key = spec.Pbr; string key = spec.Pbr;
if (key.Length == 0) if (key.Length == 0)
key = PbrForMode(spec.Mode); key = PbrForMode(spec.Mode);
Texture2D albedo; Texture2D albedo;
if (key.Length == 0 || !_albedo.TryGetValue(key, out albedo) || albedo == null) if (spec.Quality < .5f || key.Length == 0 || !_albedo.TryGetValue(key, out albedo) || albedo == null)
{ {
material.SetTexture("_AlbedoMap", Texture2D.whiteTexture); material.SetTexture("_AlbedoMap", Texture2D.whiteTexture);
material.SetTexture("_NormalMap", Texture2D.normalTexture); material.SetTexture("_NormalMap", Texture2D.normalTexture);

View file

@ -228,6 +228,7 @@ namespace Luneraria.EditorTools
static void Terrain(LuneWorldBake bake, Transform world, Dictionary<int, Material> materials) static void Terrain(LuneWorldBake bake, Transform world, Dictionary<int, Material> materials)
{ {
Material terrain = AssetDatabase.LoadAssetAtPath<Material>(LuneMaterialFactory.Folder + "/World/Terrain.mat"); Material terrain = AssetDatabase.LoadAssetAtPath<Material>(LuneMaterialFactory.Folder + "/World/Terrain.mat");
Material mountains = AssetDatabase.LoadAssetAtPath<Material>(LuneMaterialFactory.Folder + "/World/TerrainEdge.mat") ?? terrain;
var group = new GameObject("Terrain").transform; var group = new GameObject("Terrain").transform;
group.SetParent(world, false); group.SetParent(world, false);
foreach (string key in new[] { "inner", "outer" }) foreach (string key in new[] { "inner", "outer" })
@ -237,7 +238,8 @@ namespace Luneraria.EditorTools
(int)grid["size"], (float)grid["extent"], (float)grid["step"], (float)grid["hole"]); (int)grid["size"], (float)grid["extent"], (float)grid["step"], (float)grid["hole"]);
string label = mesh.name; string label = mesh.name;
mesh = Save(mesh); mesh = Save(mesh);
var go = Place(label, group, mesh, new[] { terrain }, key == "inner"); // Weg 2: the walkable ground is the lane tier, the surrounding mountains the edge tier.
var go = Place(label, group, mesh, new[] { key == "inner" ? terrain : mountains }, key == "inner");
go.isStatic = true; go.isStatic = true;
} }
} }
@ -299,6 +301,7 @@ namespace Luneraria.EditorTools
var meshes = new Dictionary<int, Mesh>(); var meshes = new Dictionary<int, Mesh>();
var bakedMeshes = (JArray)bake.Data["meshes"]; var bakedMeshes = (JArray)bake.Data["meshes"];
var props = PropLibrary(set); var props = PropLibrary(set);
var map = new LuneMap(new LuneBalance());
foreach (JObject node in bake.Data["nodes"]) foreach (JObject node in bake.Data["nodes"])
{ {
string name = (string)node["name"]; string name = (string)node["name"];
@ -350,6 +353,7 @@ namespace Luneraria.EditorTools
go.transform.localRotation = rotation; go.transform.localRotation = rotation;
go.transform.localScale = scale; go.transform.localScale = scale;
AddRenderer(go, mesh, materials, shadows); AddRenderer(go, mesh, materials, shadows);
ApplyTier(map, go);
go.isStatic = visible; go.isStatic = visible;
} }
group.gameObject.SetActive(visible); group.gameObject.SetActive(visible);
@ -357,6 +361,21 @@ namespace Luneraria.EditorTools
return meshes.Count + 2; return meshes.Count + 2;
} }
/// <summary>
/// Weg 2: a node beyond the lane corridor keeps the edge tier (Surface _Quality 0),
/// so the mountains and rim vegetation skip the PBR maps the slice pays for.
/// </summary>
static void ApplyTier(LuneMap map, GameObject go)
{
float quality = LuneZones.QualityOfWorld(map, go.transform.position);
if (quality > .5f)
return;
var block = new MaterialPropertyBlock();
block.SetFloat("_Quality", 0f);
foreach (Renderer renderer in go.GetComponentsInChildren<Renderer>(true))
renderer.SetPropertyBlock(block);
}
/// <summary>Prop meshes of map_props.fbx by name, with their surfaces dressed (ENV_* materials).</summary> /// <summary>Prop meshes of map_props.fbx by name, with their surfaces dressed (ENV_* materials).</summary>
static Dictionary<string, KeyValuePair<Mesh, Material[]>> PropLibrary(LuneMaterialSet set) static Dictionary<string, KeyValuePair<Mesh, Material[]>> PropLibrary(LuneMaterialSet set)
{ {

View file

@ -114,6 +114,9 @@ namespace Luneraria.EditorTools
new View { Label = "mid-lane-ancient", At = blue + new Vec2(1.5, -2.5), Zoom = 24f, YawSteps = -1 }, new View { Label = "mid-lane-ancient", At = blue + new Vec2(1.5, -2.5), Zoom = 24f, YawSteps = -1 },
new View { Label = "mid-lane-grotto", At = map.GrottoCenter(), Zoom = 22f }, new View { Label = "mid-lane-grotto", At = map.GrottoCenter(), Zoom = 22f },
new View { Label = "mid-lane-wide", At = (blue + red) * .5, Zoom = 48f, YawSteps = -1 }, new View { Label = "mid-lane-wide", At = (blue + red) * .5, Zoom = 48f, YawSteps = -1 },
// Weg 2 edge tier: the mountains beyond the lane corridor keep colour and stone relief.
new View { Label = "edge-mountains", At = new Vec2(-55, 55), Zoom = 36f, YawSteps = -1 },
new View { Label = "lane-and-edge", At = new Vec2(-28, 28), Zoom = 56f },
}; };
string folder = Path.Combine(Path.GetDirectoryName(Application.dataPath), "docs/port/screenshots/u5"); string folder = Path.Combine(Path.GetDirectoryName(Application.dataPath), "docs/port/screenshots/u5");
Directory.CreateDirectory(folder); Directory.CreateDirectory(folder);

View file

@ -0,0 +1,61 @@
using System;
using Luneraria.Core;
using Luneraria.View;
namespace Luneraria.EditorTools
{
/// <summary>
/// Weg 2 (Stufen) of the U5 map decision (docs/port/U5-VISUAL.md): target quality along the
/// lanes, simpler materials in the edge zones. A point counts as lane tier while it is within
/// LaneCorridor metres of a lane centreline, a building or the grotto — the corridor the
/// players actually look at. Everything beyond (mountains, rim cliffs, far vegetation) gets
/// the edge tier: colour and stone relief, no PBR maps (Surface _Quality 0).
/// </summary>
public static class LuneZones
{
/// <summary>Metres from a lane centreline (or a building) that still count as lane tier.</summary>
public const float LaneCorridor = 22f;
/// <summary>Distance from at to the nearest lane centreline sample.</summary>
public static double DistanceToLanes(LuneMap map, Vec2 at)
{
double best = double.MaxValue;
foreach (string lane in LuneMap.Lanes)
{
LanePath path = map.LanePaths[lane];
for (int i = 0; i < path.Points.Length; i++)
{
float distance = path.Points[i].DistanceTo(at);
if (distance < best)
best = distance;
}
}
return best;
}
/// <summary>True while at is in the target-quality corridor of the slice.</summary>
public static bool NearLane(LuneMap map, Vec2 at)
{
if (DistanceToLanes(map, at) <= LaneCorridor)
return true;
foreach (BuildingDef building in map.Buildings)
{
if (building.Position.DistanceTo(at) <= LaneCorridor)
return true;
}
return map.GrottoCenter().DistanceTo(at) <= LaneCorridor * 1.5;
}
/// <summary>Quality for the Surface shader: 1 lane tier (full PBR), 0 edge tier.</summary>
public static float QualityOf(LuneMap map, Vec2 at)
{
return NearLane(map, at) ? 1f : 0f;
}
/// <summary>Quality of a world-space point (Unity coordinates; x is mirrored).</summary>
public static float QualityOfWorld(LuneMap map, UnityEngine.Vector3 world)
{
return QualityOf(map, LuneSpace.Map(world));
}
}
}

View file

@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 245d896e048f24ec4adaab995b82b82c

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.62 - _Roughness: 0.62
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0.85 - _Metallic: 0.85
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.42 - _Roughness: 0.42
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.84 - _Roughness: 0.84
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 1 - _Roughness: 1
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.85 - _Roughness: 0.85
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.85 - _Roughness: 0.85
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.85 - _Roughness: 0.85
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 9 - _Mode: 9
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 9 - _Mode: 9
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 9 - _Mode: 9
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 9 - _Mode: 9
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 9 - _Mode: 9
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 9 - _Mode: 9
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 9 - _Mode: 9
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0.9 - _Metallic: 0.9
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.42 - _Roughness: 0.42
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0.8 - _Metallic: 0.8
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.52 - _Roughness: 0.52
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0.9 - _Metallic: 0.9
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.32 - _Roughness: 0.32
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0.9 - _Metallic: 0.9
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.32 - _Roughness: 0.32
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0.9 - _Metallic: 0.9
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.32 - _Roughness: 0.32
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 2 - _Mode: 2
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.93 - _Roughness: 0.93
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.5 - _Roughness: 0.5
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.5 - _Roughness: 0.5
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.5 - _Roughness: 0.5
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.5 - _Roughness: 0.5
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 2 - _Mode: 2
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.9 - _Roughness: 0.9
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 2 - _Mode: 2
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 2 - _Mode: 2
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.1 - _Roughness: 0.1
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.82 - _Roughness: 0.82
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 5 - _Mode: 5
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.4 - _Roughness: 0.4
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 2 - _Mode: 2
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 6 - _Mode: 6
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 6 - _Mode: 6
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 6 - _Mode: 6
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 2 - _Mode: 2
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 3 - _Mode: 3
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.8 - _Roughness: 0.8
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 2 - _Mode: 2
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 2 - _Mode: 2
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 2 - _Mode: 2
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 2 - _Mode: 2
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 2 - _Mode: 2
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 2 - _Mode: 2
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 2 - _Mode: 2
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 2 - _Mode: 2
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 3 - _Mode: 3
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 3 - _Mode: 3
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 3 - _Mode: 3
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 4 - _Mode: 4
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.3 - _Roughness: 0.3
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.3 - _Roughness: 0.3
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.3 - _Roughness: 0.3
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.2 - _Roughness: 0.2
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.3 - _Roughness: 0.3
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.3 - _Roughness: 0.3
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.3 - _Roughness: 0.3
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.3 - _Roughness: 0.3
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 0 - _Mode: 0
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.3 - _Roughness: 0.3
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 7 - _Mode: 7
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 1 - _Mode: 1
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -0,0 +1,60 @@
%YAML 1.1
%TAG !u! tag:unity3d.com,2011:
--- !u!21 &2100000
Material:
serializedVersion: 8
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_Name: TerrainEdge
m_Shader: {fileID: 4800000, guid: 9809bd5750e264586bd30e14a6f1bd4e, type: 3}
m_Parent: {fileID: 0}
m_ModifiedSerializedProperties: 0
m_ValidKeywords: []
m_InvalidKeywords: []
m_LightmapFlags: 0
m_EnableInstancingVariants: 1
m_DoubleSidedGI: 0
m_CustomRenderQueue: -1
stringTagMap: {}
disabledShaderPasses: []
m_LockedProperties:
m_SavedProperties:
serializedVersion: 3
m_TexEnvs:
- _AlbedoMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _NormalMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _OrmMap:
m_Texture: {fileID: 0}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
- _StoneMap:
m_Texture: {fileID: 2800000, guid: 2e11a30a0df8143ab84722ec0a116b6d, type: 3}
m_Scale: {x: 1, y: 1}
m_Offset: {x: 0, y: 0}
m_Ints: []
m_Floats:
- _Cull: 2
- _Energy: 1
- _Flicker: 0
- _Metallic: 0
- _Mode: 1
- _NormalStrength: 1
- _Quality: 0
- _Relief: 0.016
- _Roughness: 0.88
- _Seed: 0
- _StoneScale: 0.21
- _VertexColor: 0
m_Colors:
- _BaseColor: {r: 1, g: 1, b: 1, a: 1}
- _EmissionColor: {r: 0, g: 0, b: 0, a: 1}
m_BuildTextureStacks: []
m_AllowLocking: 1

View file

@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: a58bded89abbf41fd806e30924549b60
NativeFormatImporter:
externalObjects: {}
mainObjectFileID: 2100000
userData:
assetBundleName:
assetBundleVariant:

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 8 - _Mode: 8
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 8 - _Mode: 8
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0.37 - _Seed: 0.37

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 8 - _Mode: 8
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0.74 - _Seed: 0.74

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 8 - _Mode: 8
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 1.11 - _Seed: 1.11

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 8 - _Mode: 8
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 1.48 - _Seed: 1.48

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 8 - _Mode: 8
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0 - _Seed: 0

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 8 - _Mode: 8
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0.37 - _Seed: 0.37

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 8 - _Mode: 8
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 0.74 - _Seed: 0.74

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 8 - _Mode: 8
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 1.11 - _Seed: 1.11

View file

@ -47,6 +47,7 @@ Material:
- _Metallic: 0 - _Metallic: 0
- _Mode: 8 - _Mode: 8
- _NormalStrength: 1 - _NormalStrength: 1
- _Quality: 1
- _Relief: 0.016 - _Relief: 0.016
- _Roughness: 0.88 - _Roughness: 0.88
- _Seed: 1.48 - _Seed: 1.48

File diff suppressed because it is too large Load diff

View file

@ -32,6 +32,7 @@ Shader "Luneraria/Surface"
[HDR] _EmissionColor("Emission", Color) = (0, 0, 0, 1) [HDR] _EmissionColor("Emission", Color) = (0, 0, 0, 1)
_Relief("Relief Strength", Float) = 0.016 _Relief("Relief Strength", Float) = 0.016
_NormalStrength("Normal Strength", Float) = 1 _NormalStrength("Normal Strength", Float) = 1
_Quality("Quality (1 lane PBR, 0 edge)", Float) = 1
_Energy("Energy (veins)", Float) = 1 _Energy("Energy (veins)", Float) = 1
_Flicker("Flicker (veins)", Float) = 0 _Flicker("Flicker (veins)", Float) = 0
_Seed("Seed", Float) = 0 _Seed("Seed", Float) = 0
@ -55,6 +56,7 @@ Shader "Luneraria/Surface"
half4 _EmissionColor; half4 _EmissionColor;
float _Relief; float _Relief;
float _NormalStrength; float _NormalStrength;
float _Quality;
float _Energy; float _Energy;
float _Flicker; float _Flicker;
float _Seed; float _Seed;
@ -177,13 +179,23 @@ Shader "Luneraria/Surface"
float3 weights = pow(abs(n), 5.0); float3 weights = pow(abs(n), 5.0);
weights /= max(dot(weights, 1.0), 0.0001); weights /= max(dot(weights, 1.0), 0.0001);
float3 p = world * _StoneScale; float3 p = world * _StoneScale;
// U5 PBR set: triplanar albedo, ORM (ao, roughness, metallic) and tangent normal. // U5 PBR set (lane tier): triplanar albedo, ORM and normal. Edge tier (Weg 2
half3 texAlbedo = SAMPLE_TEXTURE2D(_AlbedoMap, sampler_AlbedoMap, p.zy).rgb * weights.x // Stufen) skips the maps and keeps the flat U2 response of colour + stone relief.
+ SAMPLE_TEXTURE2D(_AlbedoMap, sampler_AlbedoMap, p.xz).rgb * weights.y half3 texAlbedo = half3(1, 1, 1);
+ SAMPLE_TEXTURE2D(_AlbedoMap, sampler_AlbedoMap, p.xy).rgb * weights.z; half3 texOrm = half3(1.0, _Roughness, _Metallic);
half3 texOrm = SAMPLE_TEXTURE2D(_OrmMap, sampler_OrmMap, p.zy).rgb * weights.x half3 nX = half3(0, 0, 1), nY = half3(0, 0, 1), nZ = half3(0, 0, 1);
+ SAMPLE_TEXTURE2D(_OrmMap, sampler_OrmMap, p.xz).rgb * weights.y if (_Quality > 0.5)
+ SAMPLE_TEXTURE2D(_OrmMap, sampler_OrmMap, p.xy).rgb * weights.z; {
texAlbedo = SAMPLE_TEXTURE2D(_AlbedoMap, sampler_AlbedoMap, p.zy).rgb * weights.x
+ SAMPLE_TEXTURE2D(_AlbedoMap, sampler_AlbedoMap, p.xz).rgb * weights.y
+ SAMPLE_TEXTURE2D(_AlbedoMap, sampler_AlbedoMap, p.xy).rgb * weights.z;
texOrm = SAMPLE_TEXTURE2D(_OrmMap, sampler_OrmMap, p.zy).rgb * weights.x
+ SAMPLE_TEXTURE2D(_OrmMap, sampler_OrmMap, p.xz).rgb * weights.y
+ SAMPLE_TEXTURE2D(_OrmMap, sampler_OrmMap, p.xy).rgb * weights.z;
nX = UnpackNormalScale(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, p.zy), _NormalStrength);
nY = UnpackNormalScale(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, p.xz), _NormalStrength);
nZ = UnpackNormalScale(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, p.xy), _NormalStrength);
}
half3 stone = SAMPLE_TEXTURE2D(_StoneMap, sampler_StoneMap, p.zy).rgb * weights.x half3 stone = SAMPLE_TEXTURE2D(_StoneMap, sampler_StoneMap, p.zy).rgb * weights.x
+ SAMPLE_TEXTURE2D(_StoneMap, sampler_StoneMap, p.xz).rgb * weights.y + SAMPLE_TEXTURE2D(_StoneMap, sampler_StoneMap, p.xz).rgb * weights.y
+ SAMPLE_TEXTURE2D(_StoneMap, sampler_StoneMap, p.xy).rgb * weights.z; + SAMPLE_TEXTURE2D(_StoneMap, sampler_StoneMap, p.xy).rgb * weights.z;
@ -290,15 +302,15 @@ Shader "Luneraria/Surface"
} }
if (_VertexColor > 0.5) if (_VertexColor > 0.5)
albedo *= input.color.rgb; albedo *= input.color.rgb;
// Tangent-space normal of the PBR set, triplanar, on top of the geometric normal. // Tangent-space normal of the PBR set (lane tier only), triplanar, on top of the geometric normal.
half3 nX = UnpackNormalScale(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, p.zy), _NormalStrength); if (_Quality > 0.5)
half3 nY = UnpackNormalScale(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, p.xz), _NormalStrength); {
half3 nZ = UnpackNormalScale(SAMPLE_TEXTURE2D(_NormalMap, sampler_NormalMap, p.xy), _NormalStrength); // Whiteout blend of the three projections into world space.
// Whiteout blend of the three projections into world space. nX = half3(nX.xy + n.zy, abs(nX.z) * n.x);
nX = half3(nX.xy + n.zy, abs(nX.z) * n.x); nY = half3(nY.xy + n.xz, abs(nY.z) * n.y);
nY = half3(nY.xy + n.xz, abs(nY.z) * n.y); nZ = half3(nZ.xy + n.xy, abs(nZ.z) * n.z);
nZ = half3(nZ.xy + n.xy, abs(nZ.z) * n.z); n = normalize(nX.zyx * weights.x + nY.xzy * weights.y + nZ.xyz * weights.z);
n = normalize(nX.zyx * weights.x + nY.xzy * weights.y + nZ.xyz * weights.z); }
if (bump > 0.0) if (bump > 0.0)
{ {
// Relief from the pattern's screen derivatives (surface gradient, as in Godot). // Relief from the pattern's screen derivatives (surface gradient, as in Godot).

View file

@ -47,7 +47,8 @@ Die Szene ändert kein Verhalten. Der Host treibt den Kern im festen Takt; die A
| Wert | Warum kein Regelunterschied | | Wert | Warum kein Regelunterschied |
| --- | --- | | --- | --- |
| PBR-Maps über den Weltfarben | Die Regeln und die Golden-Parität lesen keine Materialien. Die Mid-Lane trägt gebackene Albedo-/Normal-/ORM-Sätze; die übrige Karte bleibt auf dem U2-Stand. | | PBR-Maps über den Weltfarben | Die Regeln und die Golden-Parität lesen keine Materialien. Der Lankorridor trägt gebackene Albedo-/Normal-/ORM-Sätze. |
| Stufen Lane/Rand (U5.2) | `LuneZones.NearLane` (22 m) trennt Zielqualität von der Randstufe (Farbe + Steinschicht). Harte Grenze je Weltknoten; Regeln lesen keine Materialien. |
| Hit- und Angriffs-Flash | Der Kern-HitFlash (0,18 s) und der Angriffs-Flash färben die Figur über einen MaterialPropertyBlock. Darstellerisch; keine Regel liest den Blitz. | | Hit- und Angriffs-Flash | Der Kern-HitFlash (0,18 s) und der Angriffs-Flash färben die Figur über einen MaterialPropertyBlock. Darstellerisch; keine Regel liest den Blitz. |
| Nebel und Farbabstimmung | `RenderSettings.fog` und das Volume (ACES, Bloom, Weißabgleich, Vignette) betreffen nur das Bild. | | Nebel und Farbabstimmung | `RenderSettings.fog` und das Volume (ACES, Bloom, Weißabgleich, Vignette) betreffen nur das Bild. |
| Turmblitze als Funke | Drei Punkte mit Breitenkurve statt des einfachen Rohrs aus U2; dieselben Angriffsereignisse (`AttackSerial`). | | Turmblitze als Funke | Drei Punkte mit Breitenkurve statt des einfachen Rohrs aus U2; dieselben Angriffsereignisse (`AttackSerial`). |

View file

@ -87,9 +87,10 @@ Hinweis: Die Projektdateien des .NET-Harness (`tools/dotnet/*/*.csproj`) fehlten
| Parität | Golden 51.221 Werte unverändert, 0 Abweichungen; Darstellung liest nur | | Parität | Golden 51.221 Werte unverändert, 0 Abweichungen; Darstellung liest nur |
| Bild | `screenshots/u5/mid-lane-*.png` (Übersicht, Türme, Ancient, Grotte, Weitwinkel); Vergleich mit `../saumwacht-godot/docs/luneraria/screenshots/g3/vorher-1920x1080/` und `zwischenstand-1920x1080/` | | Bild | `screenshots/u5/mid-lane-*.png` (Übersicht, Türme, Ancient, Grotte, Weitwinkel); Vergleich mit `../saumwacht-godot/docs/luneraria/screenshots/g3/vorher-1920x1080/` und `zwischenstand-1920x1080/` |
| Leistung | macOS-Player mit PBR+Nebel+VFX, 116 Einheiten: 132 fps (Übersicht), 182 fps (Mid nah). HUD 0,088 bzw. 0,077 ms je Bild. Gegenüber U3 −20…−25 % | | Leistung | macOS-Player mit PBR+Nebel+VFX, 116 Einheiten: 132 fps (Übersicht), 182 fps (Mid nah). HUD 0,088 bzw. 0,077 ms je Bild. Gegenüber U3 −20…−25 % |
| Bekannte Unterschiede | nur die Mid-Lane auf Zielqualität; Figuren ohne Künstler-Sculpts; keine Decals/Partikel; LOD/Draw Calls offen | | Kartenqualität | entschieden und umgesetzt: **Weg 2 (Stufen)** — Zielqualität im Lankorridor (22 m), Randstufe (Farbe + Steinschicht) in Bergen und Kluft. Nachweis `screenshots/u5/edge-mountains.png`, `lane-and-edge.png`; Leistung `logs/u5/player-benchmark-stufen.json` (133 / 180 fps) |
| Offen | Entscheidung über die ganze Karte (Gleichziehen / Stufen / Drosseln); Künstler-Sculpts für Anatomie/Gesichter/Haare; LOD und Atlanten | | Bekannte Unterschiede | Stufen statt flächiger Zielqualität (harte Grenze je Knoten); Figuren ohne Künstler-Sculpts; keine Decals/Partikel; LOD/Draw Calls offen |
| Commits | `luneraria/u5` `2c1686b` | | Offen | restliche Zonen und Einheitenmodelle auf Zielqualität; Künstler-Sculpts; LOD und Atlanten |
| Commits | `luneraria/u5` `2c1686b` (Slice), `luneraria/u5.2` (Stufen, dieser Stand) |
## Ausblick ## Ausblick

View file

@ -13,7 +13,7 @@ Zielplattformen sind Fedora 44 und Windows 11; macOS ist die Entwicklungsplattfo
| U2 · Unity-Spielwelt | **fertig**: U2A Blender→FBX-Pipeline (9 Assets geprüft), U2B G1-Karte mit Materialsystem, U2C fester Takt und Ansichten (bildratenunabhängig nachgewiesen), U2D vollständige Bot-Partien sichtbar und gleich dem Kern; danach Batch-Import aller 86 Modelle, Einheiten mit eigenen Modellen | [U2-WORLD.md](U2-WORLD.md) | | U2 · Unity-Spielwelt | **fertig**: U2A Blender→FBX-Pipeline (9 Assets geprüft), U2B G1-Karte mit Materialsystem, U2C fester Takt und Ansichten (bildratenunabhängig nachgewiesen), U2D vollständige Bot-Partien sichtbar und gleich dem Kern; danach Batch-Import aller 86 Modelle, Einheiten mit eigenen Modellen | [U2-WORLD.md](U2-WORLD.md) |
| U3 · G3-HUD portieren | **fertig** (`luneraria/u3`): UI Toolkit, Sichtmodell mit Privatsphäre, menschlicher Sitz, alle HUD-Bereiche, Eingabe und Befehle, Prüfung 718/0, 14 G3-Motive, Spieltest, Leistung mit HUD | [U3-UI.md](U3-UI.md) | | U3 · G3-HUD portieren | **fertig** (`luneraria/u3`): UI Toolkit, Sichtmodell mit Privatsphäre, menschlicher Sitz, alle HUD-Bereiche, Eingabe und Befehle, Prüfung 718/0, 14 G3-Motive, Spieltest, Leistung mit HUD | [U3-UI.md](U3-UI.md) |
| U4 · Netzwerk | **fertig** (`luneraria/u4` = `769e622`): LuneSession (Protokoll 4), TCP-Transport, Startbildschirm Host/Join, 43+12 Prüfungen, Mindestumfang M4 | [U4-NETWORK.md](U4-NETWORK.md) | | U4 · Netzwerk | **fertig** (`luneraria/u4` = `769e622`): LuneSession (Protokoll 4), TCP-Transport, Startbildschirm Host/Join, 43+12 Prüfungen, Mindestumfang M4 | [U4-NETWORK.md](U4-NETWORK.md) |
| U5 · Visuelle Neuausrichtung (Vertical Slice Mid-Lane) | **Vertical Slice fertig** (`luneraria/u5` = `2c1686b`): 6 PBR-Sätze, Surface-Shader mit Albedo/Normal/ORM, Nebel und Licht der Mid-Lane, Hit- und Turm-VFX, 132/182 fps | [U5-VISUAL.md](U5-VISUAL.md) | | U5 · Visuelle Neuausrichtung (Vertical Slice Mid-Lane) | **fertig** (`luneraria/u5` = `2c1686b`, Stufen `luneraria/u5.2`): 6 PBR-Sätze, Surface-Shader mit Albedo/Normal/ORM, Stufen Lane/Rand, Hit- und Turm-VFX, 133/180 fps | [U5-VISUAL.md](U5-VISUAL.md) |
QA je Meilenstein: [PORT-QA.md](PORT-QA.md). QA je Meilenstein: [PORT-QA.md](PORT-QA.md).
@ -38,7 +38,8 @@ Bekannte Verhaltensunterschiede, auch die bewusst übernommenen Referenzfehler:
- **Host-Schleife (U2C):** fester Takt mit Akkumulator; die Bildrate bestimmt nur die Zahl der Schritte je Bild. Nachweis über Fingerabdrücke der Partie. - **Host-Schleife (U2C):** fester Takt mit Akkumulator; die Bildrate bestimmt nur die Zahl der Schritte je Bild. Nachweis über Fingerabdrücke der Partie.
- **Schriftgewichte wie in G3 (U3D):** Die Referenz deklariert Gewichte, wendet sie aber nie an (String-Schlüssel „wght“ wird von Godot ignoriert). Der Port zeigt wie G3 Regular 400. Die Stilrollen bleiben getrennt, damit U5 echte Gewichte vergeben kann. - **Schriftgewichte wie in G3 (U3D):** Die Referenz deklariert Gewichte, wendet sie aber nie an (String-Schlüssel „wght“ wird von Godot ignoriert). Der Port zeigt wie G3 Regular 400. Die Stilrollen bleiben getrennt, damit U5 echte Gewichte vergeben kann.
- **Netzwerk über TCP (U4):** Die Referenz nutzt ENet; der Port nutzt TCP mit `LuneWire` (Nachrichten) und binären Kampfrahmen. Späte Rahmen werden über die Serial verworfen wie bei `unreliable_ordered`. Offline ist ein lokaler Host mit Bot-Plätzen (`LuneSession.HostOffline`). - **Netzwerk über TCP (U4):** Die Referenz nutzt ENet; der Port nutzt TCP mit `LuneWire` (Nachrichten) und binären Kampfrahmen. Späte Rahmen werden über die Serial verworfen wie bei `unreliable_ordered`. Offline ist ein lokaler Host mit Bot-Plätzen (`LuneSession.HostOffline`).
- **PBR-Texturen aus Blender (U5):** `tools/blender/bake_pbr.py` backt nahtlose Albedo-/Normal-/ORM-Sätze (Torus-Mapping). Der Surface-Shader legt sie triplanar über die Godot-Weltfarben. Nur die Mid-Lane trägt die Zielqualität; die übrige Karte bleibt auf dem U2-Stand, bis über den Weg entschieden ist (U5-VISUAL, Entscheidungsvorlage). - **PBR-Texturen aus Blender (U5):** `tools/blender/bake_pbr.py` backt nahtlose Albedo-/Normal-/ORM-Sätze (Torus-Mapping). Der Surface-Shader legt sie triplanar über die Godot-Weltfarben.
- **Stufen statt flächiger Zielqualität (U5.2, Entscheidung 2. Oktober 2026):** Der Lankorridor (22 m um Mittellinien, Gebäude und Grotte) trägt die vollen PBR-Sätze; Berge, Kluft und ferner Hintergrund behalten Farbe + Steinschicht (`LuneZones`, Surface `_Quality`, `TerrainEdge`). Gebäude, Einheiten, Wege und Wasser bleiben Lane-Stufe.
- **Modelle direkt in Git** (1. Oktober 2026): Auch die Modelle des Batch-Imports liegen wie die U2A-Modelle im Repository, ohne Git LFS. Keine Datei ist größer als 40 MB; das Repository wächst auf etwa 240 MB. - **Modelle direkt in Git** (1. Oktober 2026): Auch die Modelle des Batch-Imports liegen wie die U2A-Modelle im Repository, ohne Git LFS. Keine Datei ist größer als 40 MB; das Repository wächst auf etwa 240 MB.
- **Projektort außerhalb von iCloud Drive** (1. Oktober 2026): Der Arbeitsordner `TowerDefense` zieht von `~/Documents/Projekte` nach `~/Developer`. iCloud Drive synchronisierte `~/Documents` und legte Konfliktkopien an, die einen Player unbrauchbar machten (U2-WORLD.md, Batch-Import). Der Schutz in `LunePlayerBuild` bleibt. - **Projektort außerhalb von iCloud Drive** (1. Oktober 2026): Der Arbeitsordner `TowerDefense` zieht von `~/Documents/Projekte` nach `~/Developer`. iCloud Drive synchronisierte `~/Documents` und legte Konfliktkopien an, die einen Player unbrauchbar machten (U2-WORLD.md, Batch-Import). Der Schutz in `LunePlayerBuild` bleibt.

View file

@ -1,6 +1,6 @@
# U5 · Visuelle Neuausrichtung # U5 · Visuelle Neuausrichtung
Stand: 2. Oktober 2026 · **Vertical Slice fertig** (`luneraria/u5` = `2c1686b`). Stand: 2. Oktober 2026 · **Vertical Slice fertig**, Kartenqualität entschieden (**Weg 2 Stufen**).
U5 ist die eigentliche Begründung für den Unity-Wechsel. Ziel ist stilisierter Realismus wie Dota 2 und aktuelle MOBAs: PBR-Oberflächen, ausgeformte Details, glaubwürdige Proportionen. Die Silhouetten bleiben klar und aus der Draufsicht auch bei über 100 Einheiten lesbar. U5 ist die eigentliche Begründung für den Unity-Wechsel. Ziel ist stilisierter Realismus wie Dota 2 und aktuelle MOBAs: PBR-Oberflächen, ausgeformte Details, glaubwürdige Proportionen. Die Silhouetten bleiben klar und aus der Draufsicht auch bei über 100 Einheiten lesbar.
@ -104,24 +104,42 @@ Rohdaten: `logs/u5/player-benchmark-macos.json`. Befehle siehe [U2-WORLD.md](U2-
| Grenze: keine prozeduralen Gesichter/Haare/Anatomie | eingehalten — die Figuren behalten ihre Generatoren-Modelle; Sculpts bleiben vorbehalten | | Grenze: keine prozeduralen Gesichter/Haare/Anatomie | eingehalten — die Figuren behalten ihre Generatoren-Modelle; Sculpts bleiben vorbehalten |
| Vertical Slice: beide Richtungen, zwei Türme, Ancient, Fluss, Vegetation, Felsen, Einheiten, Held, Champion, Grotte, Kampf-VFX | erfüllt (siehe `screenshots/u5/`) | | Vertical Slice: beide Richtungen, zwei Türme, Ancient, Fluss, Vegetation, Felsen, Einheiten, Held, Champion, Grotte, Kampf-VFX | erfüllt (siehe `screenshots/u5/`) |
| Vorher/Nachher gegenüber Godot G3 | erfüllt: `u5/` neben `g3/vorher-*` und `g3/zwischenstand-*`; Kamera bewusst vergleichbar, Licht eigenständig | | Vorher/Nachher gegenüber Godot G3 | erfüllt: `u5/` neben `g3/vorher-*` und `g3/zwischenstand-*`; Kamera bewusst vergleichbar, Licht eigenständig |
| Leistung gemessen | erfüllt (132 / 182 fps) | | Leistung gemessen | erfüllt (133 / 180 fps mit Stufen) |
| Erst danach über die ganze Karte entscheiden | **offen** — Entscheidungsvorlage unten | | Erst danach über die ganze Karte entscheiden | entschieden: **Weg 2 (Stufen)**, umgesetzt |
## Entscheidungsvorlage für die ganze Karte ## Entscheidung für die ganze Karte: Weg 2 (Stufen)
Der Slice trägt die Zielqualität zu einem Preis von 20–25 % Bildrate. Für die ganze Karte stehen drei Wege offen: Am 2. Oktober 2026 fiel die Entscheidung des Projektinhabers: **Zielqualität entlang der Lanes, einfachere Randzonen.** Die Alternativen „Gleichziehen“ (PBR überall) und „Drosseln“ (PBR aus ab einer Schwelle) sind damit abgelehnt; „Drosseln“ bleibt als spätere Einstellung denkbar, ist aber nicht vorgesehen.
1. **Gleichziehen:** denselben PBR-Satz auf alle Zonen legen. Einfach, aber die Übersichts-Kamera fällt unter 100 fps sobald viele Einheiten im Bild sind. ### Umsetzung
2. **Stufen:** Zielqualität nur entlang der Lanes, einfachere Materialien in Randzonen und im Hintergrund (Berge, Kluft). Empfehlung des Ports.
3. **Qualität drosseln:** PBR-Aus, wenn `units_alive_max` oder Zoom eine Schwelle überschreitet. Sauber per Einstellung, aber sichtbarer Umschaltmoment.
Erst nach dieser Entscheidung werden die restlichen Zonen und die Einheitenmodelle hochgezogen. | Baustein | Ort | Inhalt |
| --- | --- | --- |
| `LuneZones` | `Assets/Luneraria/Editor/World/LuneZones.cs` | Korridor um die Lanes (22 m um eine Mittellinie, ein Gebäude oder die Grotte). `NearLane` entscheidet die Stufe eines Punkts |
| `_Quality` | `Assets/Luneraria/Shaders/LuneSurface.shader` | 1 = Lane-Stufe (Albedo, Normal, ORM triplanar), 0 = Randstufe (Farbe + Steinschicht, keine PBR-Maps, flaches PBR wie U2) |
| Materialstufen | `LuneMaterialFactory` | `Spec.Quality`; Randmaterialien binden keine PBR-Sätze. `TerrainEdge.mat` trägt die umgebenden Berge |
| Szenenaufbau | `LuneWorldBuilder.ApplyTier` | Jeder Weltknoten jenseits des Korridors bekommt `_Quality` 0 über einen `MaterialPropertyBlock`; der innere Boden bleibt Lane-Stufe, die Berge `TerrainEdge` |
| Nachweis | `screenshots/u5/edge-mountains.png`, `lane-and-edge.png` | Randstufe (Berge) und der Übergang Lane → Rand in einem Bild |
Gebäude (Türme, Ancients, Grotte), Einheiten, Wege, Wasser und der innere Boden bleiben unverrückt auf Zielqualität. Die Randstufe spart die neun triplanaren Map-Samples (Albedo, Normal, ORM) und behält Farbe, Vertex-Tönung, Steinschicht und Emission — also das U2-Aussehen der Berge.
### Leistung mit Stufen
| Ansicht | Einheiten | fps (Mittel) | Bildzeit Median | p95 | Sim | Views | UI |
| --- | ---: | ---: | ---: | ---: | ---: | ---: | ---: |
| ganze Karte (Zoom 64) | 116 | 133 | 5,05 ms | 19,33 ms | 0,119 | 0,249 | 0,086 |
| Mid-Lane nah (Zoom 22) | 63 | 180 | 4,21 ms | 13,17 ms | 0,055 | 0.353 | 0,078 |
Die Zahlen liegen auf dem Niveau des Slices (132 / 182 fps): die beiden Messfenster sehen den Korridor, also die Lane-Stufe. Die Ersparnis der Randstufe zeigt sich in Weitwinkeln und am Rand (siehe `lane-and-edge.png`), nicht in diesen Fenstern. Für die übrige Karte ist Weg 2 die Vorgabe: hohe Qualität wo gespielt wird, einfache Materialien in den Bergen und an der Kluft.
Rohdaten: `logs/u5/player-benchmark-stufen.json` (Vergleich Slice: `logs/u5/player-benchmark-macos.json`).
## Bekannte Grenzen ## Bekannte Grenzen
- **Nur die Mid-Lane** trägt die Zielqualität. Die übrige Karte bleibt auf dem U2-Stand (einfache Materialien, kein Nebel-Feinschliff). - **Stufen statt flächiger Zielqualität:** Der Korridor um die Lanes (22 m) trägt die vollen PBR-Sätze; Berge, Kluft und ferner Hintergrund behalten Farbe + Steinschicht. Die Grenze ist bewusst hart (MaterialPropertyBlock je Knoten), kein weicher Verlauf.
- **Figuren** behalten die prozeduralen Generatoren-Modelle. Anatomie, Gesichter und Haare brauchen Künstler-Sculpts oder lizenzierte Bibliotheken (Freigabe und Lizenzprüfung vorbehalten). - **Figuren** behalten die prozeduralen Generatoren-Modelle. Anatomie, Gesichter und Haare brauchen Künstler-Sculpts oder lizenzierte Bibliotheken (Freigabe und Lizenzprüfung vorbehalten).
- **Decals und Partikel** (Staub, Trefferfunken, Fußspuren) sind nicht Teil des Slice; der Hit- und Angriffs-Flash sowie der Turmfunke tragen die Kampflesbarkeit. - **Decals und Partikel** (Staub, Trefferfunken, Fußspuren) sind nicht Teil des Slice; der Hit- und Angriffs-Flash sowie der Turmfunke tragen die Kampflesbarkeit.
- **LOD und Draw Calls** sind nicht gemessen (Development-Player/Profiler); die U2-Folgerung bleibt offen. - **LOD und Draw Calls** sind nicht gemessen (Development-Player/Profiler); die U2-Folgerung bleibt offen.
- **Water Refraction / SSR** ist nicht gesetzt; der Fluss arbeitet mit Normals, Rauigkeit und Fresnel. - **Water Refraction / SSR** ist nicht gesetzt; der Fluss arbeitet mit Normals, Rauigkeit und Fresnel.
- **Godot G3** hat ein eigenes Lichtkonzept; die Bilder sind lagevergleichbar, nicht beleuchtungsgleich. - **Godot G3** hat ein eigenes Lichtkonzept; die Bilder sind lagevergleichbar, nicht beleuchtungsgleich.
- **Einheitenmodelle** sind noch nicht auf Zielqualität; sie folgen erst, wenn die Umgebung steht.

View file

@ -0,0 +1,14 @@
{
"build": "OSXPlayer player, 6000.3.20f1, release",
"device": "Mac17,2; Apple M5; Apple M5",
"graphics_api": "Metal",
"resolution": "1920x1080",
"vsync": 0,
"match": "seed 9 from round 21 (fixture high_wave_21), speed 1x, measured after 10 s of combat",
"windows": [
{"view": "overview (zoom 64)", "frames": 2668, "fps": 133.4, "frame_ms_avg": 7.50, "frame_ms_median": 5.05, "frame_ms_p95": 19.33, "frame_ms_p99": 22.78, "frame_ms_max": 32.58, "frames_over_16_7_ms": 195, "of_them_with_simulation_step": 18, "gc_collections": 28, "simulation_ms_per_frame": 0.119, "views_ms_per_frame": 0.249, "ui_ms_per_frame": 0.086, "units_alive_max": 116},
// timings overview (zoom 64): main thread avg 3.12 / median 3.03 / p95 4.23 ms, render thread avg 3.66 / median 3.66 / p95 4.12 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 4.37 / median 1.67 / p95 16.62 ms
{"view": "mid lane close (zoom 22)", "frames": 1801, "fps": 180.0, "frame_ms_avg": 5.55, "frame_ms_median": 4.21, "frame_ms_p95": 13.17, "frame_ms_p99": 17.16, "frame_ms_max": 21.57, "frames_over_16_7_ms": 31, "of_them_with_simulation_step": 1, "gc_collections": 10, "simulation_ms_per_frame": 0.055, "views_ms_per_frame": 0.353, "ui_ms_per_frame": 0.078, "units_alive_max": 63}
// timings mid lane close (zoom 22): main thread avg 2.69 / median 2.65 / p95 3.69 ms, render thread avg 3.11 / median 3.07 / p95 3.61 ms, gpu avg 0.00 / median 0.00 / p95 0.00 ms, present wait avg 2.87 / median 1.37 / p95 10.82 ms
]
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.8 MiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.5 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 MiB

After

Width:  |  Height:  |  Size: 2.2 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 MiB

After

Width:  |  Height:  |  Size: 2.1 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.4 MiB

After

Width:  |  Height:  |  Size: 2.4 MiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.8 MiB

After

Width:  |  Height:  |  Size: 1.8 MiB