diff --git a/chunky/src/java/se/llbit/chunky/model/minecraft/CauldronModel.java b/chunky/src/java/se/llbit/chunky/model/minecraft/CauldronModel.java
index be240c673c..485e42fe2f 100644
--- a/chunky/src/java/se/llbit/chunky/model/minecraft/CauldronModel.java
+++ b/chunky/src/java/se/llbit/chunky/model/minecraft/CauldronModel.java
@@ -20,6 +20,7 @@
import se.llbit.chunky.block.minecraft.Lava;
import se.llbit.chunky.block.minecraft.Water;
import se.llbit.chunky.renderer.scene.Scene;
+import se.llbit.chunky.renderer.scene.StillWaterShader;
import se.llbit.chunky.resources.Texture;
import se.llbit.math.Quad;
import se.llbit.math.Ray;
@@ -413,8 +414,8 @@ public static boolean intersectWithWater(Ray ray, Scene scene, int level) {
// TODO since this water is the same block, refraction is not taken into account – still better than no water
Quad water = waterLevels[level];
if (water != null && water.intersect(ray)) {
- if (!scene.stillWaterEnabled()) {
- scene.getWaterShading().doWaterShading(ray, scene.getAnimationTime());
+ if (!(scene.getCurrentWaterShader() instanceof StillWaterShader)) {
+ scene.getCurrentWaterShader().doWaterShading(ray, scene.getAnimationTime());
} else {
ray.setNormal(water.n);
}
diff --git a/chunky/src/java/se/llbit/chunky/renderer/WaterShadingStrategy.java b/chunky/src/java/se/llbit/chunky/renderer/WaterShadingStrategy.java
new file mode 100644
index 0000000000..179d95dc4b
--- /dev/null
+++ b/chunky/src/java/se/llbit/chunky/renderer/WaterShadingStrategy.java
@@ -0,0 +1,48 @@
+/* Copyright (c) 2023 Chunky Contributors
+ *
+ * This file is part of Chunky.
+ *
+ * Chunky is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chunky is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with Chunky. If not, see .
+ */
+package se.llbit.chunky.renderer;
+
+import se.llbit.util.Registerable;
+
+public enum WaterShadingStrategy implements Registerable {
+ SIMPLEX("Simplex", "Uses configurable noise to shade the water, which prevents tiling at great distances."),
+ TILED_NORMALMAP("Tiled normal map", "Uses a built-in tiled normal map to shade the water"),
+ STILL("Still", "Renders the water surface as flat.");
+
+ private final String displayName;
+ private final String description;
+
+ WaterShadingStrategy(String displayName, String description) {
+ this.displayName = displayName;
+ this.description = description;
+ }
+
+ @Override
+ public String getName() {
+ return this.displayName;
+ }
+
+ @Override
+ public String getDescription() {
+ return this.description;
+ }
+
+ @Override
+ public String getId() {
+ return this.name();
+ }
+}
diff --git a/chunky/src/java/se/llbit/chunky/renderer/scene/LegacyWaterShader.java b/chunky/src/java/se/llbit/chunky/renderer/scene/LegacyWaterShader.java
index 83b4e42642..deff6a0ff5 100644
--- a/chunky/src/java/se/llbit/chunky/renderer/scene/LegacyWaterShader.java
+++ b/chunky/src/java/se/llbit/chunky/renderer/scene/LegacyWaterShader.java
@@ -33,7 +33,6 @@ public WaterShader clone() {
@Override
public void save(JsonObject json) {
- json.add("waterShader", "LEGACY");
}
@Override
diff --git a/chunky/src/java/se/llbit/chunky/renderer/scene/PathTracer.java b/chunky/src/java/se/llbit/chunky/renderer/scene/PathTracer.java
index 7e80122b2f..1e2127593a 100644
--- a/chunky/src/java/se/llbit/chunky/renderer/scene/PathTracer.java
+++ b/chunky/src/java/se/llbit/chunky/renderer/scene/PathTracer.java
@@ -93,10 +93,10 @@ public static boolean pathTrace(Scene scene, Ray ray, WorkerState state, int add
Material currentMat = ray.getCurrentMaterial();
Material prevMat = ray.getPrevMaterial();
- if (!scene.stillWater && ray.getNormal().y != 0 &&
+ if (!(scene.getCurrentWaterShader() instanceof StillWaterShader) && ray.getNormal().y != 0 &&
((currentMat.isWater() && prevMat == Air.INSTANCE)
|| (currentMat == Air.INSTANCE && prevMat.isWater()))) {
- scene.getWaterShading().doWaterShading(ray, scene.getAnimationTime());
+ scene.getCurrentWaterShader().doWaterShading(ray, scene.getAnimationTime());
if (currentMat == Air.INSTANCE) {
ray.invertNormal();
}
diff --git a/chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java b/chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java
index 32b6b7340a..8720f5040b 100644
--- a/chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java
+++ b/chunky/src/java/se/llbit/chunky/renderer/scene/Scene.java
@@ -221,14 +221,18 @@ public class Scene implements JsonSerializable, Refreshable {
*/
protected double waterOpacity = PersistentSettings.getWaterOpacity();
protected double waterVisibility = PersistentSettings.getWaterVisibility();
- protected boolean stillWater = PersistentSettings.getStillWater();
+ protected WaterShadingStrategy waterShadingStrategy = WaterShadingStrategy.valueOf(PersistentSettings.getWaterShadingStrategy());
+ private final StillWaterShader stillWaterShader = new StillWaterShader();
+ private final LegacyWaterShader legacyWaterShader = new LegacyWaterShader();
+ private final SimplexWaterShader simplexWaterShader = new SimplexWaterShader();
+
+ private WaterShader currentWaterShader = getWaterShader(waterShadingStrategy);
protected boolean useCustomWaterColor = PersistentSettings.getUseCustomWaterColor();
protected boolean waterPlaneEnabled = false;
protected double waterPlaneHeight = World.SEA_LEVEL;
protected boolean waterPlaneOffsetEnabled = true;
protected boolean waterPlaneChunkClip = true;
- protected WaterShader waterShading = new SimplexWaterShader();
public final Fog fog = new Fog(this);
@@ -440,7 +444,8 @@ public synchronized void copyState(Scene other, boolean copyChunks) {
exposure = other.exposure;
- stillWater = other.stillWater;
+ waterShadingStrategy = other.waterShadingStrategy;
+ currentWaterShader = other.currentWaterShader.clone();
waterOpacity = other.waterOpacity;
waterVisibility = other.waterVisibility;
useCustomWaterColor = other.useCustomWaterColor;
@@ -466,7 +471,6 @@ public synchronized void copyState(Scene other, boolean copyChunks) {
waterPlaneHeight = other.waterPlaneHeight;
waterPlaneOffsetEnabled = other.waterPlaneOffsetEnabled;
waterPlaneChunkClip = other.waterPlaneChunkClip;
- waterShading = other.waterShading.clone();
hideUnknownBlocks = other.hideUnknownBlocks;
@@ -612,16 +616,6 @@ public double getExposure() {
return exposure;
}
- /**
- * Set still water mode.
- */
- public void setStillWater(boolean value) {
- if (value != stillWater) {
- stillWater = value;
- refresh();
- }
- }
-
/**
* Set emitters enable flag.
*/
@@ -1617,13 +1611,6 @@ public synchronized void haltRender() {
}
}
- /**
- * @return true
if still water is enabled
- */
- public boolean stillWaterEnabled() {
- return stillWater;
- }
-
/**
* @return true
if biome colors are enabled
*/
@@ -2648,7 +2635,7 @@ public void setUseCustomWaterColor(boolean value) {
json.add("fancierTranslucency", fancierTranslucency);
json.add("transmissivityCap", transmissivityCap);
json.add("sunSamplingStrategy", sunSamplingStrategy.getId());
- json.add("stillWater", stillWater);
+ json.add("waterShadingStrategy", waterShadingStrategy.getId());
json.add("waterOpacity", waterOpacity);
json.add("waterVisibility", waterVisibility);
json.add("useCustomWaterColor", useCustomWaterColor);
@@ -2659,7 +2646,7 @@ public void setUseCustomWaterColor(boolean value) {
colorObj.add("blue", waterColor.z);
json.add("waterColor", colorObj);
}
- waterShading.save(json);
+ currentWaterShader.save(json);
json.add("fog", fog.toJson());
json.add("biomeColorsEnabled", biomeColors);
json.add("transparentSky", transparentSky);
@@ -2930,7 +2917,28 @@ public synchronized void importFromJson(JsonObject json) {
sunSamplingStrategy = SunSamplingStrategy.valueOf(json.get("sunSamplingStrategy").asString(SunSamplingStrategy.FAST.getId()));
}
- stillWater = json.get("stillWater").boolValue(stillWater);
+ waterShadingStrategy = WaterShadingStrategy.valueOf(json.get("waterShadingStrategy").asString(WaterShadingStrategy.SIMPLEX.getId()));
+ if (!json.get("waterShader").isUnknown()) {
+ String waterShader = json.get("waterShader").stringValue("SIMPLEX");
+ if(waterShader.equals("LEGACY"))
+ waterShadingStrategy = WaterShadingStrategy.TILED_NORMALMAP;
+ else if(waterShader.equals("SIMPLEX"))
+ waterShadingStrategy = WaterShadingStrategy.SIMPLEX;
+ else {
+ Log.infof("Unknown water shader %s, using SIMPLEX", waterShader);
+ waterShadingStrategy = WaterShadingStrategy.SIMPLEX;
+ }
+ } else {
+ waterShadingStrategy = WaterShadingStrategy.TILED_NORMALMAP;
+ }
+ if (!json.get("stillWater").isUnknown()) {
+ if (json.get("stillWater").boolValue(false)) {
+ waterShadingStrategy = WaterShadingStrategy.STILL;
+ }
+ }
+ setCurrentWaterShader(waterShadingStrategy);
+ currentWaterShader.load(json);
+
waterOpacity = json.get("waterOpacity").doubleValue(waterOpacity);
waterVisibility = json.get("waterVisibility").doubleValue(waterVisibility);
useCustomWaterColor = json.get("useCustomWaterColor").boolValue(useCustomWaterColor);
@@ -2940,16 +2948,6 @@ public synchronized void importFromJson(JsonObject json) {
waterColor.y = colorObj.get("green").doubleValue(waterColor.y);
waterColor.z = colorObj.get("blue").doubleValue(waterColor.z);
}
- String waterShader = json.get("waterShader").stringValue("SIMPLEX");
- if(waterShader.equals("LEGACY"))
- waterShading = new LegacyWaterShader();
- else if(waterShader.equals("SIMPLEX"))
- waterShading = new SimplexWaterShader();
- else {
- Log.infof("Unknown water shader %s, using SIMPLEX", waterShader);
- waterShading = new SimplexWaterShader();
- }
- waterShading.load(json);
biomeColors = json.get("biomeColorsEnabled").boolValue(biomeColors);
transparentSky = json.get("transparentSky").boolValue(transparentSky);
JsonValue fogObj = json.get("fog");
@@ -3393,18 +3391,32 @@ public World getWorld() {
return loadedWorld;
}
- /**
- * Get the water shader
- */
- public WaterShader getWaterShading() {
- return waterShading;
+ public WaterShadingStrategy getWaterShadingStrategy() {
+ return waterShadingStrategy;
}
- /**
- * Set the Water shader
- */
- public void setWaterShading(WaterShader waterShading) {
- this.waterShading = waterShading;
+ public void setWaterShadingStrategy(WaterShadingStrategy waterShadingStrategy) {
+ this.waterShadingStrategy = waterShadingStrategy;
+ setCurrentWaterShader(waterShadingStrategy);
+ refresh();
+ }
+
+ public WaterShader getCurrentWaterShader() {
+ return currentWaterShader;
+ }
+ private void setCurrentWaterShader(WaterShadingStrategy waterShadingStrategy) {
+ currentWaterShader = getWaterShader(waterShadingStrategy);
+ }
+
+ private WaterShader getWaterShader(WaterShadingStrategy waterShadingStrategy) {
+ switch (waterShadingStrategy) {
+ case STILL:
+ return stillWaterShader;
+ case TILED_NORMALMAP:
+ return legacyWaterShader;
+ default:
+ return simplexWaterShader;
+ }
}
public boolean getHideUnknownBlocks() {
diff --git a/chunky/src/java/se/llbit/chunky/renderer/scene/SimplexWaterShader.java b/chunky/src/java/se/llbit/chunky/renderer/scene/SimplexWaterShader.java
index b3dbd62deb..682a231900 100644
--- a/chunky/src/java/se/llbit/chunky/renderer/scene/SimplexWaterShader.java
+++ b/chunky/src/java/se/llbit/chunky/renderer/scene/SimplexWaterShader.java
@@ -79,7 +79,6 @@ public WaterShader clone() {
@Override
public void save(JsonObject json) {
- json.add("waterShader", "SIMPLEX");
JsonObject params = new JsonObject();
params.add("iterations", iterations);
params.add("frequency", baseFrequency);
diff --git a/chunky/src/java/se/llbit/chunky/renderer/scene/StillWaterShader.java b/chunky/src/java/se/llbit/chunky/renderer/scene/StillWaterShader.java
new file mode 100644
index 0000000000..1e3347d6ba
--- /dev/null
+++ b/chunky/src/java/se/llbit/chunky/renderer/scene/StillWaterShader.java
@@ -0,0 +1,40 @@
+/* Copyright (c) 2012-2023 Chunky contributors
+ *
+ * This file is part of Chunky.
+ *
+ * Chunky is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chunky is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ * You should have received a copy of the GNU General Public License
+ * along with Chunky. If not, see .
+ */
+package se.llbit.chunky.renderer.scene;
+
+import se.llbit.chunky.model.minecraft.WaterModel;
+import se.llbit.json.JsonObject;
+import se.llbit.math.Ray;
+
+public class StillWaterShader implements WaterShader {
+ @Override
+ public void doWaterShading(Ray ray, double animationTime) {
+ }
+
+ @Override
+ public WaterShader clone() {
+ return new StillWaterShader();
+ }
+
+ @Override
+ public void save(JsonObject json) {
+ }
+
+ @Override
+ public void load(JsonObject json) {
+ }
+}
diff --git a/chunky/src/java/se/llbit/chunky/ui/render/tabs/WaterTab.java b/chunky/src/java/se/llbit/chunky/ui/render/tabs/WaterTab.java
index 34f3a440b9..6efb2a7653 100644
--- a/chunky/src/java/se/llbit/chunky/ui/render/tabs/WaterTab.java
+++ b/chunky/src/java/se/llbit/chunky/ui/render/tabs/WaterTab.java
@@ -26,10 +26,8 @@
import javafx.scene.paint.Color;
import se.llbit.chunky.PersistentSettings;
import se.llbit.chunky.renderer.RenderController;
-import se.llbit.chunky.renderer.scene.LegacyWaterShader;
-import se.llbit.chunky.renderer.scene.Scene;
-import se.llbit.chunky.renderer.scene.SimplexWaterShader;
-import se.llbit.chunky.renderer.scene.WaterShader;
+import se.llbit.chunky.renderer.WaterShadingStrategy;
+import se.llbit.chunky.renderer.scene.*;
import se.llbit.chunky.ui.DoubleAdjuster;
import se.llbit.chunky.ui.IntegerAdjuster;
import se.llbit.chunky.ui.controller.RenderControlsFxController;
@@ -46,7 +44,7 @@
public class WaterTab extends ScrollPane implements RenderControlsTab, Initializable {
private Scene scene;
- @FXML private CheckBox stillWater;
+ @FXML private ChoiceBox waterShader;
@FXML private DoubleAdjuster waterVisibility;
@FXML private DoubleAdjuster waterOpacity;
@FXML private CheckBox useCustomWaterColor;
@@ -57,7 +55,6 @@ public class WaterTab extends ScrollPane implements RenderControlsTab, Initializ
@FXML private CheckBox waterPlaneOffsetEnabled;
@FXML private CheckBox waterPlaneClip;
@FXML private TitledPane waterWorldModeDetailsPane;
- @FXML private CheckBox useProceduralWater;
@FXML private IntegerAdjuster proceduralWaterIterations;
@FXML private DoubleAdjuster proceduralWaterFrequency;
@FXML private DoubleAdjuster proceduralWaterAmplitude;
@@ -89,7 +86,7 @@ public void setController(RenderControlsFxController controller) {
@Override
public void update(Scene scene) {
useCustomWaterColor.setSelected(scene.getUseCustomWaterColor());
- stillWater.setSelected(scene.stillWaterEnabled());
+ waterShader.getSelectionModel().select(scene.getWaterShadingStrategy());
waterVisibility.set(scene.getWaterVisibility());
waterOpacity.set(scene.getWaterOpacity());
@@ -104,15 +101,13 @@ public void update(Scene scene) {
waterPlaneOffsetEnabled.setSelected(scene.isWaterPlaneOffsetEnabled());
waterPlaneClip.setSelected(scene.getWaterPlaneChunkClip());
- if(scene.getWaterShading() instanceof SimplexWaterShader) {
- useProceduralWater.setSelected(true);
- SimplexWaterShader simplexWaterShader = (SimplexWaterShader) scene.getWaterShading();
+ if(scene.getCurrentWaterShader() instanceof SimplexWaterShader) {
+ SimplexWaterShader simplexWaterShader = (SimplexWaterShader) scene.getCurrentWaterShader();
proceduralWaterIterations.set(simplexWaterShader.iterations);
proceduralWaterFrequency.set(simplexWaterShader.baseFrequency);
proceduralWaterAmplitude.set(simplexWaterShader.baseAmplitude);
proceduralWaterAnimationSpeed.set(simplexWaterShader.animationSpeed);
} else {
- useProceduralWater.setSelected(false);
proceduralWaterIterations.set(4);
proceduralWaterFrequency.set(0.4);
proceduralWaterAmplitude.set(0.025);
@@ -144,10 +139,28 @@ public void initialize(URL location, ResourceBundle resources) {
waterOpacity.clampBoth();
waterOpacity.onValueChange(value -> scene.setWaterOpacity(value));
- stillWater.setTooltip(new Tooltip("Disable the waves on the water surface."));
- stillWater.selectedProperty().addListener((observable, oldValue, newValue) ->
- scene.setStillWater(newValue)
- );
+ waterShader.getItems().addAll(WaterShadingStrategy.values());
+ waterShader.getSelectionModel().selectedItemProperty().addListener((observable, oldValue, newValue) -> {
+ scene.setWaterShadingStrategy(newValue);
+ switch (newValue) {
+ case STILL:
+ case TILED_NORMALMAP:
+ proceduralWaterDetailsPane.setVisible(false);
+ proceduralWaterDetailsPane.setExpanded(false);
+ proceduralWaterDetailsPane.setManaged(false);
+ break;
+ case SIMPLEX:
+ proceduralWaterDetailsPane.setVisible(true);
+ proceduralWaterDetailsPane.setExpanded(true);
+ proceduralWaterDetailsPane.setManaged(true);
+ break;
+ }
+ });
+ StringBuilder waterShaderOptions = new StringBuilder("\n\n");
+ for (WaterShadingStrategy strategy : WaterShadingStrategy.values()) {
+ waterShaderOptions.append(strategy.getId()).append(": ").append(strategy.getDescription()).append("\n");
+ }
+ waterShader.setTooltip(new Tooltip("Change how the water surface is rendered." + waterShaderOptions));
useCustomWaterColor.setTooltip(new Tooltip("Disable biome tinting for water, and use a custom color instead."));
useCustomWaterColor.selectedProperty().addListener((observable, oldValue, newValue) ->
@@ -158,7 +171,7 @@ public void initialize(URL location, ResourceBundle resources) {
saveDefaults.setTooltip(new Tooltip("Save the current water settings as new defaults."));
saveDefaults.setOnAction(e -> {
- PersistentSettings.setStillWater(scene.stillWaterEnabled());
+ PersistentSettings.setWaterShadingStrategy(scene.getWaterShadingStrategy().getId());
PersistentSettings.setWaterOpacity(scene.getWaterOpacity());
PersistentSettings.setWaterVisibility(scene.getWaterVisibility());
boolean useCustomWaterColor = scene.getUseCustomWaterColor();
@@ -195,34 +208,11 @@ public void initialize(URL location, ResourceBundle resources) {
scene.setWaterPlaneChunkClip(newValue)
);
- proceduralWaterDetailsPane.setVisible(useProceduralWater.isSelected());
- proceduralWaterDetailsPane.setExpanded(useProceduralWater.isSelected());
- proceduralWaterDetailsPane.setManaged(useProceduralWater.isSelected());
-
- useProceduralWater.setTooltip(new Tooltip("Generate customized water waves using noise to prevent tiling at large distances."));
- useProceduralWater.selectedProperty().addListener((observable, oldValue, newValue) -> {
- if(newValue && scene.getWaterShading() instanceof LegacyWaterShader) {
- SimplexWaterShader shader = new SimplexWaterShader();
- scene.setWaterShading(shader);
- shader.iterations = proceduralWaterIterations.get();
- shader.baseFrequency = proceduralWaterFrequency.get();
- shader.baseAmplitude = proceduralWaterAmplitude.get();
- shader.animationSpeed = proceduralWaterAnimationSpeed.get();
- scene.refresh();
- } else if(!newValue && scene.getWaterShading() instanceof SimplexWaterShader) {
- scene.setWaterShading(new LegacyWaterShader());
- scene.refresh();
- }
- proceduralWaterDetailsPane.setVisible(newValue);
- proceduralWaterDetailsPane.setExpanded(newValue);
- proceduralWaterDetailsPane.setManaged(newValue);
- });
-
proceduralWaterIterations.setName("Iterations");
proceduralWaterIterations.setTooltip("The number of iterations (layers) of noise used");
proceduralWaterIterations.setRange(1, 10);
proceduralWaterIterations.onValueChange(iter -> {
- WaterShader shader = scene.getWaterShading();
+ WaterShader shader = scene.getCurrentWaterShader();
if(shader instanceof SimplexWaterShader) {
((SimplexWaterShader) shader).iterations = iter;
scene.refresh();
@@ -233,7 +223,7 @@ public void initialize(URL location, ResourceBundle resources) {
proceduralWaterFrequency.setTooltip("The frequency of the noise");
proceduralWaterFrequency.setRange(0, 1);
proceduralWaterFrequency.onValueChange(freq -> {
- WaterShader shader = scene.getWaterShading();
+ WaterShader shader = scene.getCurrentWaterShader();
if(shader instanceof SimplexWaterShader) {
((SimplexWaterShader) shader).baseFrequency = freq;
}
@@ -244,7 +234,7 @@ public void initialize(URL location, ResourceBundle resources) {
proceduralWaterAmplitude.setTooltip("The amplitude of the noise");
proceduralWaterAmplitude.setRange(0, 1);
proceduralWaterAmplitude.onValueChange(amp -> {
- WaterShader shader = scene.getWaterShading();
+ WaterShader shader = scene.getCurrentWaterShader();
if(shader instanceof SimplexWaterShader) {
((SimplexWaterShader) shader).baseAmplitude = amp;
}
@@ -256,7 +246,7 @@ public void initialize(URL location, ResourceBundle resources) {
+ " Only relevant when rendering animation by varying animation time.");
proceduralWaterAnimationSpeed.setRange(0, 10);
proceduralWaterAnimationSpeed.onValueChange(speed -> {
- WaterShader shader = scene.getWaterShading();
+ WaterShader shader = scene.getCurrentWaterShader();
if(shader instanceof SimplexWaterShader) {
((SimplexWaterShader) shader).animationSpeed = speed;
}
diff --git a/chunky/src/res/se/llbit/chunky/ui/render/tabs/WaterTab.fxml b/chunky/src/res/se/llbit/chunky/ui/render/tabs/WaterTab.fxml
index 39ff6f2d90..77794b11a6 100644
--- a/chunky/src/res/se/llbit/chunky/ui/render/tabs/WaterTab.fxml
+++ b/chunky/src/res/se/llbit/chunky/ui/render/tabs/WaterTab.fxml
@@ -3,18 +3,35 @@
+
+
-
-
+
+
+
-
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -34,18 +51,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/lib/src/se/llbit/chunky/PersistentSettings.java b/lib/src/se/llbit/chunky/PersistentSettings.java
index 1f38e64a0f..c72c11e53c 100644
--- a/lib/src/se/llbit/chunky/PersistentSettings.java
+++ b/lib/src/se/llbit/chunky/PersistentSettings.java
@@ -356,13 +356,18 @@ public static void setFollowCamera(boolean value) {
save();
}
- public static void setStillWater(boolean value) {
- settings.setBool("stillWater", value);
+ public static boolean getStillWater() {
+ return settings.getBool("stillWater", false);
+ }
+
+ public static void setWaterShadingStrategy(String waterShadingStrategy) {
+ settings.setString("waterShadingStrategy", waterShadingStrategy);
save();
}
- public static boolean getStillWater() {
- return settings.getBool("stillWater", false);
+ public static String getWaterShadingStrategy() {
+ String defaultValue = getStillWater() ? "STILL" : "SIMPLEX";
+ return settings.getString("waterShadingStrategy", defaultValue);
}
public static void setWaterOpacity(double value) {