Am Lightning rumgeschraubt (Nicht mc queen)

This commit is contained in:
2026-07-19 12:30:11 +02:00
parent bdd69e282c
commit ad37720edd
4 changed files with 44 additions and 22 deletions

View File

@@ -219,8 +219,11 @@ public class WorldScene extends BaseAppState {
animLib = new AnimationLibrary();
app.getStateManager().attach(animLib);
// Früh starten damit DayNightState bis onEnable() bereits initialisiert ist
// Früh starten damit DayNightState bis onEnable() bereits initialisiert ist.
// withShadows=false: Shadow-Filter wird in buildLighting() extern übergeben.
// setGameMode(true): Spiel-Beleuchtungswerte statt Editor-Werte verwenden.
dayNight = new DayNightState(false);
dayNight.setGameMode(true);
app.getStateManager().attach(dayNight);
}

View File

@@ -57,6 +57,8 @@ public class DayNightState extends BaseAppState implements TimeListener {
private ColorRGBA sunBaseColor = new ColorRGBA(1, 1, 1, 1);
private float shadowBaseIntensity = 0f;
private ColorRGBA customAmbient = new ColorRGBA();
/** true = Spiel-Beleuchtungswerte, false = Editor-Werte. Standardmäßig = withShadows. */
private boolean gameMode;
private static final float CAVE_RAY_HEIGHT = 12f;
private static final float CAVE_CHECK_INTERVAL = 0.2f;
@@ -69,7 +71,7 @@ public class DayNightState extends BaseAppState implements TimeListener {
this(new DayTime(), true);
}
/** @param withShadows false für Editor (kein Shadow-Renderer) */
/** @param withShadows false für Editor (kein Shadow-Renderer, Editor-Beleuchtungswerte) */
public DayNightState(boolean withShadows) {
this(new DayTime(), withShadows);
}
@@ -77,6 +79,15 @@ public class DayNightState extends BaseAppState implements TimeListener {
public DayNightState(DayTime dayTime, boolean withShadows) {
this.dayTime = dayTime;
this.withShadows = withShadows;
this.gameMode = withShadows;
}
/**
* Schaltet auf Spiel-Beleuchtungswerte um, unabhängig vom withShadows-Flag.
* Nützlich wenn der Shadow-Filter von außen gesetzt wird (z.B. WorldScene).
*/
public void setGameMode(boolean gameMode) {
this.gameMode = gameMode;
}
public DayTime getDayTime() { return dayTime; }
@@ -234,24 +245,28 @@ public class DayNightState extends BaseAppState implements TimeListener {
float elevC = FastMath.clamp(elevation, 0f, 1f);
// Spiel vs. Editor: unterschiedliche Helligkeitswerte aus LightingConfig
ColorRGBA ambDay = withShadows ? LightingConfig.AMB_DAY : LightingConfig.EDITOR_AMB_DAY;
ColorRGBA ambNight = withShadows ? LightingConfig.AMB_NIGHT : LightingConfig.EDITOR_AMB_NIGHT;
ColorRGBA custDay = withShadows ? LightingConfig.CUSTOM_AMB_DAY : LightingConfig.EDITOR_CUSTOM_AMB_DAY;
ColorRGBA custNight = withShadows ? LightingConfig.CUSTOM_AMB_NIGHT : LightingConfig.EDITOR_CUSTOM_AMB_NIGHT;
float sunIntensity = withShadows ? LightingConfig.SUN_INTENSITY : LightingConfig.EDITOR_SUN_INTENSITY;
ColorRGBA ambDay = gameMode ? LightingConfig.AMB_DAY : LightingConfig.EDITOR_AMB_DAY;
ColorRGBA ambNight = gameMode ? LightingConfig.AMB_NIGHT : LightingConfig.EDITOR_AMB_NIGHT;
ColorRGBA custDay = gameMode ? LightingConfig.CUSTOM_AMB_DAY : LightingConfig.EDITOR_CUSTOM_AMB_DAY;
ColorRGBA custNight = gameMode ? LightingConfig.CUSTOM_AMB_NIGHT : LightingConfig.EDITOR_CUSTOM_AMB_NIGHT;
float sunIntensity = gameMode ? LightingConfig.SUN_INTENSITY : LightingConfig.EDITOR_SUN_INTENSITY;
// ── Sonnenfarbe: Dämmerung (orange) → Tag (warm-weiß) — jedes Frame ──
float dawnFactor = 1f - FastMath.clamp(elevation * LightingConfig.SUN_DAWN_SLOPE, 0f, 1f);
ColorRGBA sunColor = LightingConfig.SUN_COLOR_DAWN.clone()
ColorRGBA sunTint = LightingConfig.SUN_COLOR_DAWN.clone()
.interpolateLocal(LightingConfig.SUN_COLOR_DAY, 1f - dawnFactor);
sunBaseColor = sunColor.mult(elevC * sunIntensity);
sunBaseColor = sunTint.mult(elevC * sunIntensity);
sun.setColor(sunBaseColor.mult(1f - caveFactor));
// ── Ambient: Nacht → Tag — jedes Frame ─────────────────────────────
// ── Ambient: Nacht (blau) → Tag (Sonnenfarbe-tinted) — jedes Frame ──
// Tages-Ambient bekommt den Farbton der Sonne: orange bei Dämmerung,
// warm-gelb tagsüber. Nachts bleibt das fixe Blau von AMB_NIGHT.
ColorRGBA ambDayTinted = ambDay.mult(sunTint);
ColorRGBA custDayTinted = custDay.mult(sunTint);
float ambFactor = FastMath.clamp(
(elevation - LightingConfig.AMB_ELEV_LOW) / LightingConfig.AMB_ELEV_RANGE, 0f, 1f);
ambient.setColor(ambNight.clone().interpolateLocal(ambDay, ambFactor));
customAmbient.set(custNight.clone().interpolateLocal(custDay, ambFactor));
ambient.setColor(ambNight.clone().interpolateLocal(ambDayTinted, ambFactor));
customAmbient.set(custNight.clone().interpolateLocal(custDayTinted, ambFactor));
shadowBaseIntensity = FastMath.clamp(
elevation * LightingConfig.SHADOW_SLOPE, 0f, LightingConfig.SHADOW_MAX);

View File

@@ -77,16 +77,17 @@ public final class LightingConfig {
/**
* AmbientLight-Farbe am Mittag.
* Skaliert den LightProbe-IBL: envLight = probeIBL × AMB_DAY.
* Hoch halten (≥ 0.7) damit PBR-Reflexionen sichtbar bleiben.
* Nicht zu hoch LightProbe bäckt bereits Mittags-Beleuchtung ein;
* bei AMB_DAY=0.90 wäre probeIBL + direkte Sonne (0.68) zu hell für weiße Flächen.
* Hat keinen Effekt solange kein LightProbe in der Szene ist.
*/
public static final ColorRGBA AMB_DAY = new ColorRGBA(0.90f, 0.90f, 0.90f, 1f);
public static final ColorRGBA AMB_DAY = new ColorRGBA(0.28f, 0.28f, 0.28f, 1f);
/**
* AmbientLight-Farbe in der Nacht (LightProbe-Multiplikator).
* Leichter Blaustich simuliert Mondlicht-Reflexionen auf PBR-Flächen.
*/
public static final ColorRGBA AMB_NIGHT = new ColorRGBA(0.10f, 0.10f, 0.25f, 1f);
public static final ColorRGBA AMB_NIGHT = new ColorRGBA(0.05f, 0.05f, 0.125f, 1f);
// ╔══════════════════════════════════════════════════════════════════════════╗
@@ -103,7 +104,7 @@ public final class LightingConfig {
* ↓ senken: mehr Kontrast, tiefere Schatten (wirkt moodiger/dramatischer).
* Empfehlung: 0.030.10 pro Kanal.
*/
public static final ColorRGBA CUSTOM_AMB_DAY = new ColorRGBA(0.04f, 0.05f, 0.08f, 1f);
public static final ColorRGBA CUSTOM_AMB_DAY = new ColorRGBA(0.03f, 0.04f, 0.06f, 1f);
/**
* Ambient-Farbe in der Nacht.
@@ -111,7 +112,7 @@ public final class LightingConfig {
* Zu hoch → Nacht wirkt grau statt dunkel.
* Empfehlung: 0.010.04 pro Kanal, Blau-Kanal darf höher sein.
*/
public static final ColorRGBA CUSTOM_AMB_NIGHT = new ColorRGBA(0.025f, 0.025f, 0.06f, 1f);
public static final ColorRGBA CUSTOM_AMB_NIGHT = new ColorRGBA(0.012f, 0.012f, 0.03f, 1f);
// ╔══════════════════════════════════════════════════════════════════════════╗

View File

@@ -291,6 +291,7 @@ public class WorldObjectsState extends BaseAppState {
geo.setMaterial(pbrMat);
} else if (spatial instanceof Node node) {
if ("lod2".equals(node.getName())) return;
for (Spatial child : new ArrayList<>(node.getChildren())) {
convertUnshadedToPbr(child);
}
@@ -303,10 +304,11 @@ public class WorldObjectsState extends BaseAppState {
if (mat == null) return;
String name = mat.getMaterialDef().getName();
if ("Tree".equals(name) || "TreeLeaf".equals(name)) {
// j3o-Loading setzt keine j3md-Defaults → Uniforms explizit setzen
// (Werte für Mittag; werden sofort in update() durch DayNightState überschrieben)
mat.setVector3("SunColor", new Vector3f(1.00f, 0.95f, 0.88f));
mat.setVector3("AmbientColor", new Vector3f(0.08f, 0.10f, 0.16f));
// j3o-Loading setzt keine j3md-Defaults → Uniforms explizit setzen.
// SunColor = SUN_COLOR_DAY × SUN_INTENSITY (wie in update() bei Mittag),
// sonst leuchten Bäume weiß bis DayNightState das erste Mal überschreibt.
mat.setVector3("SunColor", new Vector3f(0.68f, 0.65f, 0.60f));
mat.setVector3("AmbientColor", new Vector3f(0.04f, 0.05f, 0.08f));
mat.setVector3("LightDir", new Vector3f(0f, -1f, 0f));
sceneLitMaterials.add(mat);
} else if ("Fern".equals(name)) {
@@ -325,6 +327,7 @@ public class WorldObjectsState extends BaseAppState {
log.info("[WorldObjects] Material-Def '{}' an '{}' unbekannt, übersprungen.", name, geo.getName());
}
} else if (spatial instanceof Node node) {
if ("lod2".equals(node.getName())) return;
for (Spatial child : node.getChildren()) {
collectSceneLitMaterials(child);
}