Schatten System verbessert und Schatten qualität einstellbar gemacht
This commit is contained in:
@@ -20,7 +20,8 @@ public class GraphicsScreen extends MenuScreen {
|
||||
private static final int ROW_VSYNC = 2;
|
||||
private static final int ROW_AA = 3;
|
||||
private static final int ROW_VIEWDIST = 4;
|
||||
private static final int ROW_COUNT = 5;
|
||||
private static final int ROW_SHADOW = 5;
|
||||
private static final int ROW_COUNT = 6;
|
||||
|
||||
private final GraphicsSettings live;
|
||||
private GraphicsSettings edit;
|
||||
@@ -48,7 +49,8 @@ public class GraphicsScreen extends MenuScreen {
|
||||
edit.fullscreen = live.fullscreen;
|
||||
edit.vsync = live.vsync;
|
||||
edit.samples = live.samples;
|
||||
edit.viewDistance = live.viewDistance;
|
||||
edit.viewDistance = live.viewDistance;
|
||||
edit.shadowQuality = live.shadowQuality;
|
||||
|
||||
resIdx = 0;
|
||||
for (int i = 0; i < RESOLUTIONS.length; i++) {
|
||||
@@ -71,7 +73,8 @@ public class GraphicsScreen extends MenuScreen {
|
||||
"menu.graphics.row.fullscreen",
|
||||
"menu.graphics.row.vsync",
|
||||
"menu.graphics.row.aa",
|
||||
"menu.graphics.row.viewdist"
|
||||
"menu.graphics.row.viewdist",
|
||||
"menu.graphics.row.shadow"
|
||||
};
|
||||
|
||||
float lblX = CONT_X + 30f;
|
||||
@@ -125,6 +128,11 @@ public class GraphicsScreen extends MenuScreen {
|
||||
case NORMAL -> t("menu.graphics.val.viewdist.normal");
|
||||
case FAR -> t("menu.graphics.val.viewdist.far");
|
||||
};
|
||||
case ROW_SHADOW -> switch (edit.shadowQuality) {
|
||||
case LOW -> t("menu.graphics.val.shadow.low");
|
||||
case MEDIUM -> t("menu.graphics.val.shadow.medium");
|
||||
case HIGH -> t("menu.graphics.val.shadow.high");
|
||||
};
|
||||
default -> "";
|
||||
};
|
||||
BitmapText vt = valTexts[row];
|
||||
@@ -154,23 +162,30 @@ public class GraphicsScreen extends MenuScreen {
|
||||
GraphicsSettings.ViewDistance[] vds = GraphicsSettings.ViewDistance.values();
|
||||
edit.viewDistance = vds[(edit.viewDistance.ordinal() + dir + vds.length) % vds.length];
|
||||
break;
|
||||
case ROW_SHADOW:
|
||||
GraphicsSettings.ShadowQuality[] sqs = GraphicsSettings.ShadowQuality.values();
|
||||
edit.shadowQuality = sqs[(edit.shadowQuality.ordinal() + dir + sqs.length) % sqs.length];
|
||||
break;
|
||||
}
|
||||
refreshText(row);
|
||||
}
|
||||
|
||||
private void applyAndSave() {
|
||||
boolean needsRestart = live.width != edit.width
|
||||
|| live.height != edit.height
|
||||
|| live.fullscreen != edit.fullscreen
|
||||
|| live.vsync != edit.vsync
|
||||
|| live.samples != edit.samples;
|
||||
boolean shadowChanged = live.shadowQuality != edit.shadowQuality;
|
||||
boolean needsRestart = live.width != edit.width
|
||||
|| live.height != edit.height
|
||||
|| live.fullscreen != edit.fullscreen
|
||||
|| live.vsync != edit.vsync
|
||||
|| live.samples != edit.samples
|
||||
|| shadowChanged;
|
||||
|
||||
live.width = edit.width;
|
||||
live.height = edit.height;
|
||||
live.fullscreen = edit.fullscreen;
|
||||
live.vsync = edit.vsync;
|
||||
live.samples = edit.samples;
|
||||
live.viewDistance = edit.viewDistance;
|
||||
live.width = edit.width;
|
||||
live.height = edit.height;
|
||||
live.fullscreen = edit.fullscreen;
|
||||
live.vsync = edit.vsync;
|
||||
live.samples = edit.samples;
|
||||
live.viewDistance = edit.viewDistance;
|
||||
live.shadowQuality = edit.shadowQuality;
|
||||
GraphicsStore.save(live);
|
||||
|
||||
WeatherState ws = getApplication().getStateManager().getState(WeatherState.class);
|
||||
|
||||
@@ -1,12 +1,42 @@
|
||||
package de.blight.game.config;
|
||||
|
||||
public class GraphicsSettings {
|
||||
public int width = 1280;
|
||||
public int height = 720;
|
||||
public boolean fullscreen = false;
|
||||
public boolean vsync = false;
|
||||
public int samples = 4;
|
||||
public ViewDistance viewDistance = ViewDistance.NORMAL;
|
||||
public int width = 1280;
|
||||
public int height = 720;
|
||||
public boolean fullscreen = false;
|
||||
public boolean vsync = false;
|
||||
public int samples = 4;
|
||||
public ViewDistance viewDistance = ViewDistance.NORMAL;
|
||||
public ShadowQuality shadowQuality = ShadowQuality.MEDIUM;
|
||||
|
||||
/**
|
||||
* Schattenqualitäts-Stufen.
|
||||
* mapSize/splits sind Konstruktor-Parameter des Shadow-Filters → Neustart nötig.
|
||||
* lambda/zExtend/zFade/backface können zur Laufzeit angepasst werden.
|
||||
*/
|
||||
public enum ShadowQuality {
|
||||
// mapSize splits lambda zExtend zFade backface
|
||||
LOW ( 1024, 2, 0.70f, 40f, 5f, false),
|
||||
MEDIUM ( 2048, 3, 0.75f, 60f, 8f, true ),
|
||||
HIGH ( 4096, 4, 0.80f, 80f, 10f, true );
|
||||
|
||||
public final int shadowMapSize;
|
||||
public final int splits;
|
||||
public final float lambda;
|
||||
public final float zExtend;
|
||||
public final float zFade;
|
||||
public final boolean backface;
|
||||
|
||||
ShadowQuality(int shadowMapSize, int splits, float lambda,
|
||||
float zExtend, float zFade, boolean backface) {
|
||||
this.shadowMapSize = shadowMapSize;
|
||||
this.splits = splits;
|
||||
this.lambda = lambda;
|
||||
this.zExtend = zExtend;
|
||||
this.zFade = zFade;
|
||||
this.backface = backface;
|
||||
}
|
||||
}
|
||||
|
||||
public enum ViewDistance {
|
||||
SHORT (0.55f, 0, 2),
|
||||
|
||||
@@ -535,6 +535,15 @@ public class WorldScene extends BaseAppState {
|
||||
* Setzt Ambient=(1,1,1,1) auf allen Lighting.j3md-Materialien eines Modells,
|
||||
* damit es den globalen AmbientLight korrekt empfängt (Blender-Export setzt Ambient oft auf schwarz).
|
||||
*/
|
||||
private static void applyShadowModeRecursive(Spatial s, RenderQueue.ShadowMode mode) {
|
||||
s.setShadowMode(mode);
|
||||
if (s instanceof Node n) {
|
||||
for (Spatial child : n.getChildren()) {
|
||||
applyShadowModeRecursive(child, mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static void applyFullAmbient(Spatial s) {
|
||||
if (s instanceof Geometry g) {
|
||||
com.jme3.material.Material m = g.getMaterial();
|
||||
@@ -575,7 +584,7 @@ public class WorldScene extends BaseAppState {
|
||||
try {
|
||||
Spatial loaded = assetManager.loadModel(mc.getModelPath());
|
||||
stripEmbeddedClips(loaded, mc.getModelPath());
|
||||
loaded.setShadowMode(RenderQueue.ShadowMode.CastAndReceive);
|
||||
applyShadowModeRecursive(loaded, RenderQueue.ShadowMode.CastAndReceive);
|
||||
applyFullAmbient(loaded);
|
||||
collectPbrMaterials(loaded, characterPbrMaterials);
|
||||
log.info("[WorldScene] {} PBR-Materialien im Charakter-Modell gefunden.", characterPbrMaterials.size());
|
||||
@@ -685,8 +694,15 @@ public class WorldScene extends BaseAppState {
|
||||
// Licht, Ambient und Sky kommen von DayNightState (der wurde in initialize() attached).
|
||||
// Wir erstellen hier nur den Shadow-Filter und übergeben ihn an DayNightState,
|
||||
// damit dieser Intensität und Lichtbindung dynamisch verwaltet.
|
||||
GraphicsSettings.ShadowQuality sq = graphicsSettings.shadowQuality;
|
||||
DirectionalLightShadowFilter shadowFilter =
|
||||
new DirectionalLightShadowFilter(assetManager, 2048, 3);
|
||||
new DirectionalLightShadowFilter(assetManager, sq.shadowMapSize, sq.splits);
|
||||
shadowFilter.setEdgeFilteringMode(
|
||||
sq == GraphicsSettings.ShadowQuality.LOW ? EdgeFilteringMode.PCF4 : EdgeFilteringMode.PCFPOISSON);
|
||||
shadowFilter.setLambda(sq.lambda);
|
||||
shadowFilter.setShadowZExtend(sq.zExtend);
|
||||
shadowFilter.setShadowZFadeLength(sq.zFade);
|
||||
shadowFilter.setRenderBackFacesShadows(sq.backface);
|
||||
shadowFilter.setShadowIntensity(0.4f);
|
||||
shadowFilter.setEnabled(true);
|
||||
dayNight.setShadowFilter(shadowFilter); // bindet sun + übernimmt Intensitäts-Updates
|
||||
|
||||
@@ -45,7 +45,7 @@ public class DayNightState extends BaseAppState implements TimeListener {
|
||||
|
||||
// ── Sonnenrichtungs-Drosselung ────────────────────────────────────────────
|
||||
|
||||
private static final float SUN_DIR_INTERVAL = 0.25f;
|
||||
private static final float SUN_DIR_INTERVAL = 2.0f;
|
||||
private float sunDirTimer = SUN_DIR_INTERVAL; // sofort bereit beim ersten Aufruf
|
||||
|
||||
// ── Höhlen-Abdunkelung ────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user