From 40be463cedfb435dea8b0be344a914957947b773 Mon Sep 17 00:00:00 2001 From: Mario Date: Tue, 21 Jul 2026 07:10:49 +0200 Subject: [PATCH] Fehler im LOD System behoben --- .../de/blight/editor/util/ImpostorUtil.java | 4 ++- .../blight/game/state/WorldObjectsState.java | 32 +++---------------- 2 files changed, 7 insertions(+), 29 deletions(-) diff --git a/blight-editor/src/main/java/de/blight/editor/util/ImpostorUtil.java b/blight-editor/src/main/java/de/blight/editor/util/ImpostorUtil.java index 141d1b7..d06fc17 100644 --- a/blight-editor/src/main/java/de/blight/editor/util/ImpostorUtil.java +++ b/blight-editor/src/main/java/de/blight/editor/util/ImpostorUtil.java @@ -186,7 +186,9 @@ public final class ImpostorUtil { // WaterFilter und andere Post-Effects sehen die korrekte Tiefe des Impostors. mat.setFloat("AlphaDiscardThreshold", 0.5f); mat.getAdditionalRenderState().setBlendMode(RenderState.BlendMode.Off); - mat.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Back); + // Billboard dreht sich per BillboardControl zur Kamera → FaceCullMode.Off ist korrekt, + // da die Winding-Order nach der Rotation nicht feststeht. + mat.getAdditionalRenderState().setFaceCullMode(RenderState.FaceCullMode.Off); Node n = new Node("lod2"); for (int d = 0; d < DIRS; d++) { diff --git a/blight-game/src/main/java/de/blight/game/state/WorldObjectsState.java b/blight-game/src/main/java/de/blight/game/state/WorldObjectsState.java index ef65de6..5b49a8d 100644 --- a/blight-game/src/main/java/de/blight/game/state/WorldObjectsState.java +++ b/blight-game/src/main/java/de/blight/game/state/WorldObjectsState.java @@ -334,23 +334,17 @@ public class WorldObjectsState extends BaseAppState { private boolean isImpostorNode(Node n) { if (n.getControl(BillboardControl.class) != null) { - log.info("[Impostor] '{}' erkannt via BillboardControl", n.getName()); return true; } if (n.getChildren().isEmpty()) { - log.info("[Impostor] '{}' hat keine Kinder → kein Impostor", n.getName()); return false; } Spatial first = n.getChild(0); - log.info("[Impostor] '{}' erstes Kind: {} ({})", n.getName(), first.getName(), first.getClass().getSimpleName()); if (!(first instanceof Geometry g)) { - log.info("[Impostor] '{}' erstes Kind ist kein Geometry → kein Impostor", n.getName()); return false; } Material mat = g.getMaterial(); - String matName = mat != null ? mat.getMaterialDef().getName() : "null"; - log.info("[Impostor] '{}' Material: '{}'", n.getName(), matName); - return mat != null && "Unshaded".equals(matName); + return mat != null && "Unshaded".equals(mat.getMaterialDef().getName()); } private void initImpostor(Node lod2Node) { @@ -365,7 +359,6 @@ public class WorldObjectsState extends BaseAppState { lod2Node.setQueueBucket(com.jme3.renderer.queue.RenderQueue.Bucket.Opaque); java.util.Set seen = new java.util.HashSet<>(); - boolean firstMat = true; for (Spatial child : lod2Node.getChildren()) { if (!(child instanceof com.jme3.scene.Geometry geo)) continue; Material mat = geo.getMaterial(); @@ -373,32 +366,15 @@ public class WorldObjectsState extends BaseAppState { mat.setFloat("AlphaDiscardThreshold", 0.5f); mat.getAdditionalRenderState().setBlendMode(com.jme3.material.RenderState.BlendMode.Off); - // FaceCullMode.Off: Billboard dreht sich immer zur Kamera → beide Seiten rendern - // ist sicherer als Back, da Winding-Order nach Billboard-Rotation nicht deterministisch ist. + // Billboard dreht sich per BillboardControl zur Kamera → FaceCullMode.Off, + // da Winding-Order nach Billboard-Rotation nicht feststeht. mat.getAdditionalRenderState().setFaceCullMode(com.jme3.material.RenderState.FaceCullMode.Off); geo.setQueueBucket(com.jme3.renderer.queue.RenderQueue.Bucket.Opaque); + // Helligkeit-Fix: Atlas wurde ohne Gamma-Korrektur gerendert (kein FPP im Editor). com.jme3.material.MatParam colorMap = mat.getParam("ColorMap"); if (colorMap != null && colorMap.getValue() instanceof com.jme3.texture.Texture t) { t.getImage().setColorSpace(com.jme3.texture.image.ColorSpace.sRGB); - log.info("[Impostor] Tex '{}': {}×{} fmt={}", - t.getName(), t.getImage().getWidth(), t.getImage().getHeight(), t.getImage().getFormat()); - // Diagnose: Alpha-Wert im Zentrum von Strip 0 prüfen (Pixel 256,256) - if (firstMat) { - firstMat = false; - java.nio.ByteBuffer imgData = t.getImage().getData(0); - if (imgData != null && imgData.capacity() >= (256 * 4096 + 256) * 4 + 4) { - int off = (256 * 4096 + 256) * 4; - int r = imgData.get(off) & 0xFF; - int g = imgData.get(off + 1) & 0xFF; - int b = imgData.get(off + 2) & 0xFF; - int a = imgData.get(off + 3) & 0xFF; - log.info("[Impostor] Atlas Pixel(256,256) Strip0: R={} G={} B={} A={}", r, g, b, a); - } else { - log.warn("[Impostor] Atlas-Daten nicht lesbar (capacity={})", - imgData != null ? imgData.capacity() : -1); - } - } } else { log.warn("[Impostor] Quad '{}' hat KEINE ColorMap!", geo.getName()); }