diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiFogFalloff.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiFogFalloff.java
index 3437cd00a..8fbe37a2a 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiFogFalloff.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiFogFalloff.java
@@ -25,7 +25,7 @@ package com.seibel.distanthorizons.api.enums.rendering;
* EXPONENTIAL_SQUARED
*
* @author Leetom
- * @version 2022-6-30
+ * @version 2024-11-09
* @since API 2.0.0
*/
public enum EDhApiFogFalloff
@@ -35,8 +35,17 @@ public enum EDhApiFogFalloff
// when removing items up the API major version
- LINEAR,
- EXPONENTIAL,
- EXPONENTIAL_SQUARED,
+ LINEAR(0),
+ EXPONENTIAL(1),
+ EXPONENTIAL_SQUARED(2);
+
+
+ /**
+ * Stable version of {@link EDhApiFogFalloff#ordinal()}
+ * @since API 4.0.0
+ */
+ public final int value;
+
+ EDhApiFogFalloff(int value) { this.value = value; }
}
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiHeightFogMode.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiHeightFogDirection.java
similarity index 68%
rename from api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiHeightFogMode.java
rename to api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiHeightFogDirection.java
index 81a847630..624b391f6 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiHeightFogMode.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiHeightFogDirection.java
@@ -31,28 +31,28 @@ package com.seibel.distanthorizons.api.enums.rendering;
* @version 2024-4-6
* @since API 2.0.0
*/
-public enum EDhApiHeightFogMode
+public enum EDhApiHeightFogDirection
{
// Reminder:
// when adding items up the API minor version
// when removing items up the API major version
- ABOVE_CAMERA(true, true, false),
- BELOW_CAMERA(true, false, true),
- ABOVE_AND_BELOW_CAMERA(true, true, true),
- ABOVE_SET_HEIGHT(false, true, false),
- BELOW_SET_HEIGHT(false, false, true),
- ABOVE_AND_BELOW_SET_HEIGHT(false, true, true);
+ ABOVE_CAMERA (true, true, false),
+ BELOW_CAMERA (true, false, true),
+ ABOVE_AND_BELOW_CAMERA (true, true, true),
+ ABOVE_SET_HEIGHT (false, true, false),
+ BELOW_SET_HEIGHT (false, false, true),
+ ABOVE_AND_BELOW_SET_HEIGHT (false, true, true);
public final boolean basedOnCamera;
- public final boolean above;
- public final boolean below;
+ public final boolean fogAppliesUp;
+ public final boolean fogAppliesDown;
- EDhApiHeightFogMode(boolean basedOnCamera, boolean above, boolean below)
+ EDhApiHeightFogDirection(boolean basedOnCamera, boolean fogAppliesUp, boolean fogAppliesDown)
{
this.basedOnCamera = basedOnCamera;
- this.above = above;
- this.below = below;
+ this.fogAppliesUp = fogAppliesUp;
+ this.fogAppliesDown = fogAppliesDown;
}
}
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiHeightFogMixMode.java b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiHeightFogMixMode.java
index 56226f2da..c2e5e7f38 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiHeightFogMixMode.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/enums/rendering/EDhApiHeightFogMixMode.java
@@ -20,10 +20,11 @@
package com.seibel.distanthorizons.api.enums.rendering;
/**
- * BASIC
- * IGNORE_HEIGHT
- * ADDITION
+ * SPHERICAL
+ * CYLINDRICAL
+ *
* MAX
+ * ADDITION
* MULTIPLY
* INVERSE_MULTIPLY
* LIMITED_ADDITION
@@ -37,14 +38,36 @@ package com.seibel.distanthorizons.api.enums.rendering;
*/
public enum EDhApiHeightFogMixMode
{
- BASIC,
- IGNORE_HEIGHT,
- ADDITION,
- MAX,
- MULTIPLY,
- INVERSE_MULTIPLY,
- LIMITED_ADDITION,
- MULTIPLY_ADDITION,
- INVERSE_MULTIPLY_ADDITION,
- AVERAGE,
+ /**
+ * Basic just means the fog will be based on the fragment depth
+ * not on any special height calculation IE spherical fog.
+ *
+ * Not to be confused with {@link EDhApiHeightFogMixMode#CYLINDRICAL}
+ * which causes fog to only apply based on horizontal distance.
+ */
+ SPHERICAL(0),
+ /**
+ * Fog is applied based on horizontal distance from the camera,
+ * IE cylindrical fog.
+ */
+ CYLINDRICAL(1),
+
+ MAX(2),
+ ADDITION(3),
+ MULTIPLY(4),
+ INVERSE_MULTIPLY(5),
+ LIMITED_ADDITION(6),
+ MULTIPLY_ADDITION(7),
+ INVERSE_MULTIPLY_ADDITION(8),
+ AVERAGE(9);
+
+
+ /**
+ * Stable version of {@link EDhApiFogFalloff#ordinal()}
+ * @since API 4.0.0
+ */
+ public final int value;
+
+ EDhApiHeightFogMixMode(int value) { this.value = value; }
+
}
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiHeightFogConfig.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiHeightFogConfig.java
index 754cc01a9..f348f94ba 100644
--- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiHeightFogConfig.java
+++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiHeightFogConfig.java
@@ -21,7 +21,7 @@ package com.seibel.distanthorizons.api.interfaces.config.client;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiFogFalloff;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiHeightFogMixMode;
-import com.seibel.distanthorizons.api.enums.rendering.EDhApiHeightFogMode;
+import com.seibel.distanthorizons.api.enums.rendering.EDhApiHeightFogDirection;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigGroup;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
@@ -42,11 +42,14 @@ public interface IDhApiHeightFogConfig extends IDhApiConfigGroup
/** Defines how the height fog mixes. */
IDhApiConfigValue heightFogMixMode();
- /** Defines how the height fog is drawn relative to the camera or world. */
- IDhApiConfigValue heightFogMode();
+ /**
+ * Defines which direction height fog is drawn relative to the world.
+ * @since API 4.0.0
+ */
+ IDhApiConfigValue heightFogDirection();
/**
- * Defines the height fog's base height if {@link IDhApiHeightFogConfig#heightFogMode()}
+ * Defines the height fog's base height if {@link IDhApiHeightFogConfig#heightFogDirection()}
* is set to use a specific height.
*/
IDhApiConfigValue heightFogBaseHeight();
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiHeightFogConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiHeightFogConfig.java
index b65925172..05f3b3e43 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiHeightFogConfig.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiHeightFogConfig.java
@@ -21,7 +21,7 @@ package com.seibel.distanthorizons.core.api.external.methods.config.client;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiFogFalloff;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiHeightFogMixMode;
-import com.seibel.distanthorizons.api.enums.rendering.EDhApiHeightFogMode;
+import com.seibel.distanthorizons.api.enums.rendering.EDhApiHeightFogDirection;
import com.seibel.distanthorizons.api.interfaces.config.IDhApiConfigValue;
import com.seibel.distanthorizons.api.interfaces.config.client.IDhApiHeightFogConfig;
import com.seibel.distanthorizons.api.objects.config.DhApiConfigValue;
@@ -40,8 +40,8 @@ public class DhApiHeightFogConfig implements IDhApiHeightFogConfig
{ return new DhApiConfigValue(Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogMixMode); }
@Override
- public IDhApiConfigValue heightFogMode()
- { return new DhApiConfigValue(Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogMode); }
+ public IDhApiConfigValue heightFogDirection()
+ { return new DhApiConfigValue(Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogDirection); }
@Override
public IDhApiConfigValue heightFogBaseHeight()
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java
index 1dd476e92..73910ed05 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java
@@ -39,7 +39,6 @@ import com.seibel.distanthorizons.coreapi.ModInfo;
import org.apache.logging.log4j.Logger;
import org.lwjgl.util.tinyfd.TinyFileDialogs;
-import javax.swing.*;
import java.awt.*;
import java.io.File;
import java.util.*;
@@ -549,40 +548,40 @@ public class Config
public static class HeightFog
{
public static ConfigEntry heightFogMixMode = new ConfigEntry.Builder()
- .set(EDhApiHeightFogMixMode.BASIC)
+ .set(EDhApiHeightFogMixMode.SPHERICAL)
.comment(""
+ "How should height effect the fog thickness? \n"
+ "Note: height fog is combined with the other fog settings. \n"
+ "\n"
- + EDhApiHeightFogMixMode.BASIC + ": No special height fog effect. Fog is calculated based on camera distance \n"
- + EDhApiHeightFogMixMode.IGNORE_HEIGHT + ": Ignore height completely. Fog is only calculated with horizontal distance \n"
- + EDhApiHeightFogMixMode.ADDITION + ": heightFog + farFog \n"
+ + EDhApiHeightFogMixMode.SPHERICAL + ": Fog is calculated based on camera distance. \n"
+ + EDhApiHeightFogMixMode.CYLINDRICAL + ": Ignore height, fog is calculated based on horizontal distance. \n"
+ + "\n"
+ EDhApiHeightFogMixMode.MAX + ": max(heightFog, farFog) \n"
+ + EDhApiHeightFogMixMode.ADDITION + ": heightFog + farFog \n"
+ EDhApiHeightFogMixMode.MULTIPLY + ": heightFog * farFog \n"
+ EDhApiHeightFogMixMode.INVERSE_MULTIPLY + ": 1 - (1-heightFog) * (1-farFog) \n"
+ EDhApiHeightFogMixMode.LIMITED_ADDITION + ": farFog + max(farFog, heightFog) \n"
+ EDhApiHeightFogMixMode.MULTIPLY_ADDITION + ": farFog + farFog * heightFog \n"
+ EDhApiHeightFogMixMode.INVERSE_MULTIPLY_ADDITION + ": farFog + 1 - (1-heightFog) * (1-farFog) \n"
+ EDhApiHeightFogMixMode.AVERAGE + ": farFog*0.5 + heightFog*0.5 \n"
- + "\n"
- + "Note: height fog settings are ignored if '" + EDhApiHeightFogMixMode.BASIC + "' or '" + EDhApiHeightFogMixMode.IGNORE_HEIGHT + "' are selected.")
+ + "\n")
.build();
- public static ConfigEntry heightFogMode = new ConfigEntry.Builder()
- .set(EDhApiHeightFogMode.ABOVE_AND_BELOW_CAMERA)
+ public static ConfigEntry heightFogDirection = new ConfigEntry.Builder()
+ .set(EDhApiHeightFogDirection.BELOW_SET_HEIGHT)
.comment(""
+ "Where should the height fog start? \n"
+ "\n"
- + EDhApiHeightFogMode.ABOVE_CAMERA + ": Height fog starts at the camera and goes towards the sky \n"
- + EDhApiHeightFogMode.BELOW_CAMERA + ": Height fog starts at the camera and goes towards the void \n"
- + EDhApiHeightFogMode.ABOVE_AND_BELOW_CAMERA + ": Height fog starts from the camera to goes towards both the sky and void \n"
- + EDhApiHeightFogMode.ABOVE_SET_HEIGHT + ": Height fog starts from a set height and goes towards the sky \n"
- + EDhApiHeightFogMode.BELOW_SET_HEIGHT + ": Height fog starts from a set height and goes towards the void \n"
- + EDhApiHeightFogMode.ABOVE_AND_BELOW_SET_HEIGHT + ": Height fog starts from a set height and goes towards both the sky and void")
+ + EDhApiHeightFogDirection.ABOVE_CAMERA + ": Height fog starts at the camera and goes towards the sky \n"
+ + EDhApiHeightFogDirection.BELOW_CAMERA + ": Height fog starts at the camera and goes towards the void \n"
+ + EDhApiHeightFogDirection.ABOVE_AND_BELOW_CAMERA + ": Height fog starts from the camera to goes towards both the sky and void \n"
+ + EDhApiHeightFogDirection.ABOVE_SET_HEIGHT + ": Height fog starts from a set height and goes towards the sky \n"
+ + EDhApiHeightFogDirection.BELOW_SET_HEIGHT + ": Height fog starts from a set height and goes towards the void \n"
+ + EDhApiHeightFogDirection.ABOVE_AND_BELOW_SET_HEIGHT + ": Height fog starts from a set height and goes towards both the sky and void")
.build();
public static ConfigEntry heightFogBaseHeight = new ConfigEntry.Builder()
- .setMinDefaultMax(-4096.0, 70.0, 4096.0)
+ .setMinDefaultMax(-4096.0, 80.0, 4096.0)
.comment("If the height fog is calculated around a set height, what is that height position?")
.build();
@@ -596,7 +595,7 @@ public class Config
.build();
public static ConfigEntry heightFogEnd = new ConfigEntry.Builder()
- .setMinDefaultMax(FOG_RANGE_MIN, 1.0, FOG_RANGE_MAX)
+ .setMinDefaultMax(FOG_RANGE_MIN, 0.6, FOG_RANGE_MAX)
.comment(""
+ "Should the end of the height fog be offset? \n"
+ "\n"
@@ -605,7 +604,7 @@ public class Config
.build();
public static ConfigEntry heightFogMin = new ConfigEntry.Builder()
- .setMinDefaultMax(-5.0, 0.0, FOG_RANGE_MAX)
+ .setMinDefaultMax(0.0, 0.0, FOG_RANGE_MAX)
.comment(""
+ "What is the minimum fog thickness? \n"
+ "\n"
@@ -633,7 +632,7 @@ public class Config
.build();
public static ConfigEntry heightFogDensity = new ConfigEntry.Builder()
- .setMinDefaultMax(0.01, 2.5, 50.0)
+ .setMinDefaultMax(0.01, 20.0, 50.0)
.comment("What is the height fog's density?")
.build();
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/fog/LodFogConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/render/fog/LodFogConfig.java
deleted file mode 100644
index 3ea6f8455..000000000
--- a/core/src/main/java/com/seibel/distanthorizons/core/render/fog/LodFogConfig.java
+++ /dev/null
@@ -1,420 +0,0 @@
-/*
- * This file is part of the Distant Horizons mod
- * licensed under the GNU LGPL v3 License.
- *
- * Copyright (C) 2020-2023 James Seibel
- *
- * This program is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, version 3.
- *
- * This program 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 Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program. If not, see .
- */
-
-package com.seibel.distanthorizons.core.render.fog;
-
-import com.seibel.distanthorizons.api.enums.rendering.*;
-import com.seibel.distanthorizons.core.config.Config;
-import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector;
-import com.seibel.distanthorizons.core.render.glObject.GLProxy;
-import com.seibel.distanthorizons.core.render.glObject.shader.Shader;
-import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IOptifineAccessor;
-
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.nio.charset.StandardCharsets;
-import java.util.Objects;
-
-/**
- * This holds fog related settings and
- * creates the fog related shader code.
- *
- * @author Leetom
- * @author James Seibel
- * @version 2022-11-24
- */
-// TODO: Move lots out of here, there should be a listener hooked onto the config to update the shader
-public class LodFogConfig
-{
- private static final IOptifineAccessor OPTIFINE = ModAccessorInjector.INSTANCE.get(IOptifineAccessor.class);
-
- public static final boolean DEBUG_DUMP_GENERATED_CODE = false;
-
- public final FogSettings farFogSetting;
- public final FogSettings heightFogSetting;
- public final EDhApiHeightFogMixMode heightFogMixMode;
- public final EDhApiHeightFogMode heightFogMode;
- public final float heightFogHeight;
-
- // TODO: Move these out of here
- public final int earthCurveRatio;
-
- // Noise Values
- public final boolean noiseEnable;
- public final int noiseSteps;
- public final float noiseIntensity;
- public final int noiseDropoff;
-
-
- public static LodFogConfig generateFogConfig() { return new LodFogConfig(); }
-
- /** sets all fog options from the config */
- private LodFogConfig()
- {
- // TODO: Move these out of here
- this.earthCurveRatio = Config.Client.Advanced.Graphics.Experimental.earthCurveRatio.get();
-
- this.noiseEnable = Config.Client.Advanced.Graphics.NoiseTexture.enableNoiseTexture.get();
- this.noiseSteps = Config.Client.Advanced.Graphics.NoiseTexture.noiseSteps.get();
- this.noiseIntensity = Config.Client.Advanced.Graphics.NoiseTexture.noiseIntensity.get().floatValue();
- this.noiseDropoff = Config.Client.Advanced.Graphics.NoiseTexture.noiseDropoff.get();
-
-
- if (Config.Client.Advanced.Graphics.Fog.enableDhFog.get())
- {
- // fog should be drawn
-
- this.farFogSetting = new FogSettings(
- Config.Client.Advanced.Graphics.Fog.farFogStart.get(),
- Config.Client.Advanced.Graphics.Fog.farFogEnd.get(),
- Config.Client.Advanced.Graphics.Fog.farFogMin.get(),
- Config.Client.Advanced.Graphics.Fog.farFogMax.get(),
- Config.Client.Advanced.Graphics.Fog.farFogDensity.get(),
- Config.Client.Advanced.Graphics.Fog.farFogFalloff.get()
- );
-
- this.heightFogMixMode = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogMixMode.get();
- if (this.heightFogMixMode == EDhApiHeightFogMixMode.IGNORE_HEIGHT
- || this.heightFogMixMode == EDhApiHeightFogMixMode.BASIC)
- {
- // basic fog mixing
-
- this.heightFogSetting = null;
- this.heightFogMode = null;
- this.heightFogHeight = 0.f;
- }
- else
- {
- // advanced fog mixing
-
- this.heightFogSetting = new FogSettings(
- Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogDensity.get(),
- Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogEnd.get(),
- Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogMin.get(),
- Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogMax.get(),
- Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogDensity.get(),
- Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogFalloff.get()
- );
-
- this.heightFogMode = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogMode.get();
-
- if (this.heightFogMode.basedOnCamera)
- {
- this.heightFogHeight = 0.f;
- }
- else
- {
- this.heightFogHeight = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogBaseHeight.get().floatValue();
- }
- }
- }
- else
- {
- // fog disabled
-
- this.farFogSetting = null;
- this.heightFogMixMode = null;
- this.heightFogMode = null;
- this.heightFogSetting = null;
- this.heightFogHeight = 0.f;
- }
- }
-
- public StringBuilder loadAndProcessFragShader(String path, boolean absoluteFilePath)
- {
- StringBuilder stringBuilder = this.makeRuntimeDefine();
- this.generateRuntimeShaderCode(Shader.loadFile(path, absoluteFilePath, stringBuilder));
-
- if (DEBUG_DUMP_GENERATED_CODE)
- {
- try (FileOutputStream file = new FileOutputStream("debugGenerated.frag", false))
- {
- file.write(stringBuilder.toString().getBytes(StandardCharsets.UTF_8));
- GLProxy.GL_LOGGER.info("Debug dumped generated code to debugGenerated.frag for {}", path);
- }
- catch (IOException e)
- {
- GLProxy.GL_LOGGER.warn("Failed to debug dump generated code to file for {}", path);
- }
- }
-
- return stringBuilder;
- }
-
- /** Generates the necessary constants for a fragment shader */
- private void generateRuntimeShaderCode(StringBuilder str)
- {
- str.append("// =======RUNTIME GENERATED CODE SECTION======== //\n");
-
- // Generate method: float getNearFogThickness(float dist);
- str.append("" +
- "float getNearFogThickness(float dist) \n" +
- "{ \n" +
- " return linearFog(dist, uNearFogStart, uNearFogLength, 0.0, 1.0); \n" +
- "} \n");
-
-
- if (this.farFogSetting == null)
- {
- str.append("\n" +
- "float getFarFogThickness(float dist) { return 0.0; } \n" +
- "float getHeightFogThickness(float dist) { return 0.0; } \n" +
- "float calculateFarFogDepth(float horizontal, float dist, float uNearFogStart) { return 0.0; } \n" +
- "float calculateHeightFogDepth(float vertical, float realY) { return 0.0; } \n" +
- "float mixFogThickness(float near, float far, float height) \n" +
- "{ \n" +
- " return 0.0; \n" +
- "} \n\n");
- }
- else
- {
- // Generate method: float getFarFogThickness(float dist);
- str.append("" +
- "float getFarFogThickness(float dist) \n" +
- "{ \n" +
- getFarFogMethod(this.farFogSetting.fogType) + "\n" +
- "} \n");
-
-
- // Generate method: float getHeightFogThickness(float dist);
- str.append("" +
- "float getHeightFogThickness(float dist) \n" +
- "{ \n" +
- (this.heightFogSetting != null ? getHeightFogMethod(this.heightFogSetting.fogType) : " return 0.0;") + "\n" +
- "} \n");
-
-
- // Generate method: float calculateHeightFogDepth(float vertical, float realY);
- str.append("" +
- "float calculateHeightFogDepth(float vertical, float realY) \n" +
- "{ \n" +
- (this.heightFogSetting != null ? getHeightDepthMethod(this.heightFogMode, this.heightFogHeight) : " return 0.0;") + "\n" +
- "} \n");
-
-
- // Generate method: calculateFarFogDepth(float horizontal, float dist, float uNearFogStart);
- str.append("" +
- "float calculateFarFogDepth(float horizontal, float dist, float uNearFogStart) \n" +
- "{ \n" +
- " return " + (this.heightFogMixMode == EDhApiHeightFogMixMode.BASIC ?
- "(dist - uNearFogStart)/(1.0 - uNearFogStart);" :
- "(horizontal - uNearFogStart)/(1.0 - uNearFogStart);") +
- "} \n");
-
- // Generate method: float mixFogThickness(float near, float far, float height);
- str.append("" +
- "float mixFogThickness(float near, float far, float height) \n" +
- "{ \n" +
- getMixFogLine(this.heightFogMixMode) + "\n" +
- "} \n");
- }
- }
-
-
-
- //=================//
- // shader creation //
- // helper methods //
- //=================//
-
- private StringBuilder makeRuntimeDefine()
- {
- StringBuilder str = new StringBuilder();
- str.append("// =======RUNTIME GENERATED DEFINE SECTION======== //\n");
- str.append("#version 150 core\n");
-
- FogSettings activeFarFogSetting = this.farFogSetting != null ? this.farFogSetting : FogSettings.EMPTY;
- FogSettings activeHeightFogSetting = this.heightFogSetting != null ? this.heightFogSetting : FogSettings.EMPTY;
-
- str.append("\n" +
- "#define farFogStart " + activeFarFogSetting.start + "\n" +
- "#define farFogLength " + (activeFarFogSetting.end - activeFarFogSetting.start) + "\n" +
- "#define farFogMin " + activeFarFogSetting.min + "\n" +
- "#define farFogRange " + (activeFarFogSetting.max - activeFarFogSetting.min) + "\n" +
- "#define farFogDensity " + activeFarFogSetting.density + "\n" +
- "\n" +
- "#define heightFogStart " + activeHeightFogSetting.start + "\n" +
- "#define heightFogLength " + (activeHeightFogSetting.end - activeHeightFogSetting.start) + "\n" +
- "#define heightFogMin " + activeHeightFogSetting.min + "\n" +
- "#define heightFogRange " + (activeHeightFogSetting.max - activeHeightFogSetting.min) + "\n" +
- "#define heightFogDensity " + activeHeightFogSetting.density + "\n" +
- "\n");
-
- str.append("// =======RUNTIME END======== //\n");
- return str;
- }
-
- private static String getFarFogMethod(EDhApiFogFalloff fogType)
- {
- switch (fogType)
- {
- case LINEAR:
- return "return linearFog(dist, farFogStart, farFogLength, farFogMin, farFogRange);\n";
- case EXPONENTIAL:
- return "return exponentialFog(dist, farFogStart, farFogLength, farFogMin, farFogRange, farFogDensity);\n";
- case EXPONENTIAL_SQUARED:
- return "return exponentialSquaredFog(dist, farFogStart, farFogLength, farFogMin, farFogRange, farFogDensity);\n";
-
- default:
- throw new IllegalArgumentException("FogType [" + fogType + "] not implemented for [getFarFogMethod].");
- }
- }
-
- private static String getHeightDepthMethod(EDhApiHeightFogMode heightMode, float heightFogHeight)
- {
- String str = "";
- if (!heightMode.basedOnCamera)
- {
- str = " vertical = realY - (" + heightFogHeight + ");\n";
- }
-
- if (heightMode.below && heightMode.above)
- {
- str += " return abs(vertical);\n";
- }
- else if (heightMode.below)
- {
- str += " return -vertical;\n";
- }
- else if (heightMode.above)
- {
- str += " return vertical;\n";
- }
- else
- {
- str += " return 0;\n";
- }
- return str;
- }
-
- /**
- * Returns the method call for the given fog type.
- * Example:
- * " return linearFog(dist, heightFogStart, heightFogLength, heightFogMin, heightFogRange);"
- */
- private static String getHeightFogMethod(EDhApiFogFalloff fogType)
- {
- switch (fogType)
- {
- case LINEAR:
- return " return linearFog(dist, heightFogStart, heightFogLength, heightFogMin, heightFogRange);\n";
- case EXPONENTIAL:
- return " return exponentialFog(dist, heightFogStart, heightFogLength, heightFogMin, heightFogRange, heightFogDensity);\n";
- case EXPONENTIAL_SQUARED:
- return " return exponentialSquaredFog(dist, heightFogStart, heightFogLength, heightFogMin, heightFogRange, heightFogDensity);\n";
-
- default:
- throw new IllegalArgumentException("FogType [" + fogType + "] not implemented for [getHeightFogMethod].");
- }
- }
-
- /**
- * creates a line in the format
- * " return max(1.0-near, far);"
- */
- private static String getMixFogLine(EDhApiHeightFogMixMode heightFogMode)
- {
- String str = " return ";
-
- switch (heightFogMode)
- {
- case BASIC:
- case IGNORE_HEIGHT:
- str += "near * far;\n";
- break;
-
- case ADDITION:
- str += "near * (far + height);\n";
- break;
-
- case MAX:
- str += "near * max(far, height);\n";
- break;
-
- case INVERSE_MULTIPLY:
- str += "near * (1.0 - (1.0-far)*(1.0-height));\n";
- break;
-
- case MULTIPLY:
- str += "near * far * height;\n";
- break;
-
- case LIMITED_ADDITION:
- str += "near * (far + max(far, height));\n";
- break;
-
- case MULTIPLY_ADDITION:
- str += "near * (far + far*height);\n";
- break;
-
- case INVERSE_MULTIPLY_ADDITION:
- str += "near * (far + 1.0 - (1.0-far)*(1.0-height));\n";
- break;
-
- case AVERAGE:
- str += "near * (far*0.5 + height*0.5);\n";
- break;
-
- default:
- throw new IllegalArgumentException("FogType [" + heightFogMode + "] not implemented for [getMixFogMethod].");
- }
-
- return str;
- }
-
-
-
-
-
-
- //========================//
- // default object methods //
- //========================//
-
- @Override
- public boolean equals(Object other)
- {
- if (this == other)
- {
- return true;
- }
- else if (other == null || this.getClass() != other.getClass())
- {
- return false;
- }
- else
- {
- LodFogConfig that = (LodFogConfig) other;
- return Float.compare(that.heightFogHeight, this.heightFogHeight) == 0 &&
- Objects.equals(this.farFogSetting, that.farFogSetting) &&
- Objects.equals(this.heightFogSetting, that.heightFogSetting) && this.heightFogMixMode == that.heightFogMixMode &&
- this.heightFogMode == that.heightFogMode
- // TODO: Move these out of here
- && this.earthCurveRatio == that.earthCurveRatio
- && this.noiseEnable == that.noiseEnable && this.noiseSteps == that.noiseSteps && this.noiseIntensity == that.noiseIntensity && this.noiseDropoff == that.noiseDropoff;
- }
- }
-
- @Override
- public int hashCode()
- {
- return Objects.hash(this.farFogSetting, this.heightFogSetting, this.heightFogMixMode, this.heightFogMode, this.heightFogHeight, this.earthCurveRatio, this.noiseEnable, this.noiseSteps, this.noiseIntensity, this.noiseDropoff);
- }
-
-}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java
index fc821a461..94c1284a1 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java
@@ -49,6 +49,8 @@ public class ShaderProgram
/** Stores the handle of the program. */
public final int id;
+
+
// TODO: A better way to set the fragData output name
/**
* Creates a shader program.
@@ -73,20 +75,20 @@ public class ShaderProgram
}
- public ShaderProgram(List> vert, List> frag, String[] attributes)
+ public ShaderProgram(List> vertSupplierList, List> fragSupplierList, String[] attributes)
{
- id = GL32.glCreateProgram();
+ this.id = GL32.glCreateProgram();
- for (Supplier v : vert)
+ for (Supplier vertSupplier : vertSupplierList)
{
- Shader vertShader = new Shader(GL32.GL_VERTEX_SHADER, v.get());
+ Shader vertShader = new Shader(GL32.GL_VERTEX_SHADER, vertSupplier.get());
GL32.glAttachShader(this.id, vertShader.id);
vertShader.free(); // important!
}
- for (Supplier f : frag)
+ for (Supplier fragSupplier : fragSupplierList)
{
- Shader fragShader = new Shader(GL32.GL_FRAGMENT_SHADER, f.get());
+ Shader fragShader = new Shader(GL32.GL_FRAGMENT_SHADER, fragSupplier.get());
GL32.glAttachShader(this.id, fragShader.id);
fragShader.free(); // important!
}
@@ -101,28 +103,22 @@ public class ShaderProgram
if (status != GL32.GL_TRUE)
{
String message = "Shader Link Error. Details: " + GL32.glGetProgramInfoLog(this.id);
- free(); // important!
+ this.free(); // important!
throw new RuntimeException(message);
}
- GL32.glUseProgram(id); // This HAVE to be a direct call to prevent calling the overloaded version
+ GL32.glUseProgram(this.id); // This HAVE to be a direct call to prevent calling the overloaded version
}
- /** This will bind ShaderProgram */
- public void bind()
- {
- GL32.glUseProgram(id);
- }
- /** This will unbind ShaderProgram */
- public void unbind()
- {
- GL32.glUseProgram(0);
- }
- // REMEMBER to always free the resource!
- public void free()
- {
- GL32.glDeleteProgram(id);
- }
+
+
+ public void bind() { GL32.glUseProgram(this.id); }
+ public void unbind() { GL32.glUseProgram(0); }
+
+ public void free() { GL32.glDeleteProgram(this.id); }
+
+
+
/**
* WARNING: Slow native call! Cache it if possible!
@@ -139,12 +135,12 @@ public class ShaderProgram
if (i == -1) throw new RuntimeException("Attribute name not found: " + name);
return i;
}
- // Same as above but without throwing errors.
- // Return -1 if attribute doesn't exist or has been optimized out
+ /**
+ * Same as above but without throwing errors.
+ * Returns -1 if the attribute doesn't exist or has been optimized out.
+ */
public int tryGetAttributeLocation(CharSequence name)
- {
- return GL32.glGetAttribLocation(id, name);
- }
+ { return GL32.glGetAttribLocation(this.id, name); }
/**
* WARNING: Slow native call! Cache it if possible!
@@ -168,41 +164,34 @@ public class ShaderProgram
// Same as above but without throwing errors.
// Return -1 if uniform doesn't exist or has been optimized out
public int tryGetUniformLocation(CharSequence name)
- {
- return GL32.glGetUniformLocation(id, name);
- }
+ { return GL32.glGetUniformLocation(this.id, name); }
- /** Requires ShaderProgram binded. */
- public void setUniform(int location, boolean value)
- {
- // This use -1 for false as that equals all one set
- GL32.glUniform1i(location, value ? 1 : 0);
- }
+ /** Requires a bound ShaderProgram. */
+ public void setUniform(int location, boolean value) { GL32.glUniform1i(location, value ? 1 : 0); }
+ /** @see ShaderProgram#setUniform(int, boolean) */
+ public void trySetUniform(int location, boolean value) { if (location != -1) { this.setUniform(location, value); } }
- /** Requires ShaderProgram binded. */
- public void setUniform(int location, int value)
- {
- GL32.glUniform1i(location, value);
- }
+ /** Requires a bound ShaderProgram. */
+ public void setUniform(int location, int value) { GL32.glUniform1i(location, value); }
+ /** @see ShaderProgram#setUniform(int, int) */
+ public void trySetUniform(int location, int value) { if (location != -1) { this.setUniform(location, value); } }
- /** Requires ShaderProgram binded. */
- public void setUniform(int location, float value)
- {
- GL32.glUniform1f(location, value);
- }
+ /** Requires a bound ShaderProgram. */
+ public void setUniform(int location, float value) { GL32.glUniform1f(location, value); }
+ /** @see ShaderProgram#setUniform(int, float) */
+ public void trySetUniform(int location, float value) { if (location != -1) { this.setUniform(location, value); } }
- /** Requires ShaderProgram binded. */
- public void setUniform(int location, Vec3f value)
- {
- GL32.glUniform3f(location, value.x, value.y, value.z);
- }
- /** Requires ShaderProgram binded. */
- public void setUniform(int location, DhApiVec3i value)
- {
- GL32.glUniform3i(location, value.x, value.y, value.z);
- }
+ /** Requires a bound ShaderProgram. */
+ public void setUniform(int location, Vec3f value) { GL32.glUniform3f(location, value.x, value.y, value.z); }
+ /** @see ShaderProgram#setUniform(int, Vec3f) */
+ public void trySetUniform(int location, Vec3f value) { if (location != -1) { this.setUniform(location, value); } }
- /** Requires ShaderProgram binded. */
+ /** Requires a bound ShaderProgram. */
+ public void setUniform(int location, DhApiVec3i value) { GL32.glUniform3i(location, value.x, value.y, value.z); }
+ /** @see ShaderProgram#setUniform(int, Mat4f) */
+ public void trySetUniform(int location, DhApiVec3i value) { if (location != -1) { this.setUniform(location, value); } }
+
+ /** Requires a bound ShaderProgram. */
public void setUniform(int location, Mat4f value)
{
try (MemoryStack stack = MemoryStack.stackPush())
@@ -212,14 +201,22 @@ public class ShaderProgram
GL32.glUniformMatrix4fv(location, false, buffer);
}
}
+ /** @see ShaderProgram#setUniform(int, Mat4f) */
+ public void trySetUniform(int location, Mat4f value) { if (location != -1) { this.setUniform(location, value); } }
/**
- * Converts the color's RGBA values into values between 0 and 1.
- * Requires ShaderProgram binded.
+ * Converts the color's RGBA values into values between 0 and 1.
+ * Requires a bound ShaderProgram.
*/
public void setUniform(int location, Color value)
{
- GL32.glUniform4f(location, value.getRed() / 256.0f, value.getGreen() / 256.0f, value.getBlue() / 256.0f, value.getAlpha() / 256.0f);
+ GL32.glUniform4f(location,
+ value.getRed() / 256.0f,
+ value.getGreen() / 256.0f,
+ value.getBlue() / 256.0f,
+ value.getAlpha() / 256.0f);
}
+ /** @see ShaderProgram#setUniform(int, Color) */
+ public void trySetUniform(int location, Color value) { if (location != -1) { this.setUniform(location, value); } }
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java
index cf91f4d5e..692fb8842 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java
@@ -44,7 +44,6 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRen
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrapper;
import com.seibel.distanthorizons.core.wrapperInterfaces.misc.ILightMapWrapper;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiFogColorMode;
-import com.seibel.distanthorizons.core.render.fog.LodFogConfig;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.AbstractOptifineAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor;
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
@@ -104,8 +103,7 @@ public class LodRenderer
// The shader program
- IDhApiShaderProgram lodRenderProgram = null;
- LodFogConfig fogConfig;
+ private IDhApiShaderProgram lodRenderProgram = null;
public QuadElementBuffer quadIBO = null;
public boolean isSetupComplete = false;
@@ -634,22 +632,6 @@ public class LodRenderer
}
else
{
- LodFogConfig newFogConfig = LodFogConfig.generateFogConfig(); // TODO use a config listener instead
- if (this.fogConfig == null)
- {
- this.fogConfig = newFogConfig;
- }
-
- if (!this.fogConfig.equals(newFogConfig))
- {
- this.fogConfig = newFogConfig;
-
- this.lodRenderProgram.free();
- this.lodRenderProgram = new DhTerrainShaderProgram();
-
- FogShader.INSTANCE.free();
- FogShader.INSTANCE = new FogShader(newFogConfig);
- }
this.lodRenderProgram.bind();
}
diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java
index f35eafc94..51666a335 100644
--- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java
+++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/FogShader.java
@@ -20,11 +20,11 @@
package com.seibel.distanthorizons.core.render.renderer.shaders;
import com.seibel.distanthorizons.api.enums.rendering.EDhApiFogColorMode;
+import com.seibel.distanthorizons.api.enums.rendering.EDhApiHeightFogDirection;
+import com.seibel.distanthorizons.api.enums.rendering.EDhApiHeightFogMixMode;
import com.seibel.distanthorizons.core.config.Config;
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
-import com.seibel.distanthorizons.core.render.fog.LodFogConfig;
import com.seibel.distanthorizons.core.render.glObject.GLState;
-import com.seibel.distanthorizons.core.render.glObject.shader.Shader;
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
import com.seibel.distanthorizons.core.render.renderer.LodRenderer;
import com.seibel.distanthorizons.core.render.renderer.ScreenQuad;
@@ -38,7 +38,7 @@ import java.awt.*;
public class FogShader extends AbstractShaderRenderer
{
- public static FogShader INSTANCE = new FogShader(LodFogConfig.generateFogConfig());
+ public static final FogShader INSTANCE = new FogShader();
private static final IMinecraftClientWrapper MC = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
private static final IVersionConstants VERSION_CONSTANTS = SingletonInjector.INSTANCE.get(IVersionConstants.class);
@@ -46,21 +46,46 @@ public class FogShader extends AbstractShaderRenderer
public int frameBuffer;
- private final LodFogConfig fogConfig;
private Mat4f inverseMvmProjMatrix;
- // Uniforms
+ //==========//
+ // Uniforms //
+ //==========//
+
+ public int uDepthMap;
+ /** Inverted Model View Projection matrix */
+ public int uInvMvmProj;
+
+ // fog uniforms
public int uFogColor;
public int uFogScale;
public int uFogVerticalScale;
- public int uNearFogStart;
- public int uNearFogLength;
public int uFullFogMode;
- /** Inverted Model View Projection matrix */
- public int uInvMvmProj;
- public int uDepthMap;
+ // far fog
+ public int uFarFogStart;
+ public int uFarFogLength;
+ public int uFarFogMin;
+ public int uFarFogRange;
+ public int uFarFogDensity;
+
+ // height fog
+ public int uHeightFogStart;
+ public int uHeightFogLength;
+ public int uHeightFogMin;
+ public int uHeightFogRange;
+ public int uHeightFogDensity;
+
+ public int uHeightFogEnabled;
+ public int uHeightFogFalloffType;
+ public int uHeightBasedOnCamera;
+ public int uHeightFogBaseHeight;
+ public int uHeightFogAppliesUp;
+ public int uHeightFogAppliesDown;
+ public int uUseSphericalFog;
+ public int uHeightFogMixingMode;
+ public int uCameraBlockYPos;
@@ -68,15 +93,13 @@ public class FogShader extends AbstractShaderRenderer
// constructor //
//=============//
- public FogShader(LodFogConfig fogConfig) { this.fogConfig = fogConfig; }
-
+ public FogShader() { }
+
@Override
public void onInit()
{
this.shader = new ShaderProgram(
- // TODO rename normal.vert to something like "postProcess.vert"
- () -> Shader.loadFile("shaders/normal.vert", false, new StringBuilder()).toString(),
- () -> this.fogConfig.loadAndProcessFragShader("shaders/fog/fog.frag", false).toString(),
+ "shaders/normal.vert", "shaders/fog/fog.frag",
"fragColor", new String[]{"vPosition"}
);
@@ -87,15 +110,35 @@ public class FogShader extends AbstractShaderRenderer
this.uInvMvmProj = this.shader.getUniformLocation("uInvMvmProj");
// Fog uniforms
- this.uFogScale = this.shader.tryGetUniformLocation("uFogScale");
- this.uFogVerticalScale = this.shader.tryGetUniformLocation("uFogVerticalScale");
- this.uFogColor = this.shader.tryGetUniformLocation("uFogColor");
- this.uFullFogMode = this.shader.tryGetUniformLocation("uFullFogMode");
+ this.uFogScale = this.shader.getUniformLocation("uFogScale");
+ this.uFogVerticalScale = this.shader.getUniformLocation("uFogVerticalScale");
+ this.uFogColor = this.shader.getUniformLocation("uFogColor");
+ this.uFullFogMode = this.shader.getUniformLocation("uFullFogMode");
- // near fog
- this.uNearFogStart = this.shader.tryGetUniformLocation("uNearFogStart");
- this.uNearFogLength = this.shader.tryGetUniformLocation("uNearFogLength");
+ // fog config
+ this.uFarFogStart = this.shader.getUniformLocation("uFarFogStart");
+ this.uFarFogLength = this.shader.getUniformLocation("uFarFogLength");
+ this.uFarFogMin = this.shader.getUniformLocation("uFarFogMin");
+ this.uFarFogRange = this.shader.getUniformLocation("uFarFogRange");
+ this.uFarFogDensity = this.shader.getUniformLocation("uFarFogDensity");
+ // height fog
+ this.uHeightFogStart = this.shader.getUniformLocation("uHeightFogStart");
+ this.uHeightFogLength = this.shader.getUniformLocation("uHeightFogLength");
+ this.uHeightFogMin = this.shader.getUniformLocation("uHeightFogMin");
+ this.uHeightFogRange = this.shader.getUniformLocation("uHeightFogRange");
+ this.uHeightFogDensity = this.shader.getUniformLocation("uHeightFogDensity");
+
+ this.uHeightFogEnabled = this.shader.getUniformLocation("uHeightFogEnabled");
+ this.uHeightFogFalloffType = this.shader.getUniformLocation("uHeightFogFalloffType");
+ this.uHeightBasedOnCamera = this.shader.getUniformLocation("uHeightBasedOnCamera");
+ this.uHeightFogBaseHeight = this.shader.getUniformLocation("uHeightFogBaseHeight");
+ this.uHeightFogAppliesUp = this.shader.getUniformLocation("uHeightFogAppliesUp");
+ this.uHeightFogAppliesDown = this.shader.getUniformLocation("uHeightFogAppliesDown");
+ this.uUseSphericalFog = this.shader.getUniformLocation("uUseSphericalFog");
+ this.uHeightFogMixingMode = this.shader.getUniformLocation("uHeightFogMixingMode");
+ this.uCameraBlockYPos = this.shader.getUniformLocation("uCameraBlockYPos");
+
}
@@ -107,22 +150,66 @@ public class FogShader extends AbstractShaderRenderer
@Override
protected void onApplyUniforms(float partialTicks)
{
+ int lodDrawDistance = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistanceRadius.get() * LodUtil.CHUNK_WIDTH;
+
+
+
if (this.inverseMvmProjMatrix != null)
{
this.shader.setUniform(this.uInvMvmProj, this.inverseMvmProjMatrix);
}
- int lodDrawDistance = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistanceRadius.get() * LodUtil.CHUNK_WIDTH;
- // Fog
- if (this.uFullFogMode != -1) this.shader.setUniform(this.uFullFogMode, MC_RENDER.isFogStateSpecial() ? 1 : 0);
- if (this.uFogColor != -1) this.shader.setUniform(this.uFogColor, MC_RENDER.isFogStateSpecial() ? this.getSpecialFogColor(partialTicks) : this.getFogColor(partialTicks));
+ // Fog uniforms
+ this.shader.setUniform(this.uFogColor, MC_RENDER.isFogStateSpecial() ? this.getSpecialFogColor(partialTicks) : this.getFogColor(partialTicks));
+ this.shader.setUniform(this.uFogScale, 1.f / lodDrawDistance);
+ this.shader.setUniform(this.uFogVerticalScale, 1.f / MC.getWrappedClientLevel().getMaxHeight());
+ this.shader.setUniform(this.uFullFogMode, MC_RENDER.isFogStateSpecial() ? 1 : 0);
+
+
+ // fog config
+ float farFogStart = Config.Client.Advanced.Graphics.Fog.farFogStart.get().floatValue();
+ float farFogEnd = Config.Client.Advanced.Graphics.Fog.farFogEnd.get().floatValue();
+ float farFogMin = Config.Client.Advanced.Graphics.Fog.farFogMin.get().floatValue();
+ float farFogMax = Config.Client.Advanced.Graphics.Fog.farFogMax.get().floatValue();
+ float farFogDensity = Config.Client.Advanced.Graphics.Fog.farFogDensity.get().floatValue();
+
+ this.shader.setUniform(this.uFarFogStart, farFogStart);
+ this.shader.setUniform(this.uFarFogLength, farFogEnd - farFogStart);
+ this.shader.setUniform(this.uFarFogMin, farFogMin);
+ this.shader.setUniform(this.uFarFogRange, farFogMax - farFogMin);
+ this.shader.setUniform(this.uFarFogDensity, farFogDensity);
+
+
+ // height config
+ EDhApiHeightFogMixMode heightFogMixingMode = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogMixMode.get();
+ boolean heightFogEnabled = heightFogMixingMode != EDhApiHeightFogMixMode.SPHERICAL && heightFogMixingMode != EDhApiHeightFogMixMode.CYLINDRICAL;
+ boolean useSphericalFog = heightFogMixingMode == EDhApiHeightFogMixMode.SPHERICAL;
+ EDhApiHeightFogDirection heightFogCameraDirection = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogDirection.get();
+
+ float heightFogStart = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogStart.get().floatValue();
+ float heightFogEnd = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogEnd.get().floatValue();
+ float heightFogMin = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogMin.get().floatValue();
+ float heightFogMax = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogMax.get().floatValue();
+ float heightFogDensity = Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogDensity.get().floatValue();
+
+ this.shader.setUniform(this.uHeightFogStart, heightFogStart);
+ this.shader.setUniform(this.uHeightFogLength, heightFogEnd - heightFogStart);
+ this.shader.setUniform(this.uHeightFogMin, heightFogMin);
+ this.shader.setUniform(this.uHeightFogRange, heightFogMax - heightFogMin);
+ this.shader.setUniform(this.uHeightFogDensity, heightFogDensity);
+
+
+ this.shader.setUniform(this.uHeightFogEnabled, heightFogEnabled);
+ this.shader.setUniform(this.uHeightFogFalloffType, Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogFalloff.get().value);
+ this.shader.setUniform(this.uHeightFogBaseHeight, Config.Client.Advanced.Graphics.Fog.HeightFog.heightFogBaseHeight.get().floatValue());
+ this.shader.setUniform(this.uHeightBasedOnCamera, heightFogCameraDirection.basedOnCamera);
+ this.shader.setUniform(this.uHeightFogAppliesUp, heightFogCameraDirection.fogAppliesUp);
+ this.shader.setUniform(this.uHeightFogAppliesDown, heightFogCameraDirection.fogAppliesDown);
+ this.shader.setUniform(this.uUseSphericalFog, useSphericalFog);
+ this.shader.setUniform(this.uHeightFogMixingMode, heightFogMixingMode.value);
+ this.shader.setUniform(this.uCameraBlockYPos, (float)MC_RENDER.getCameraExactPosition().y);
- float nearFogStart = (VERSION_CONSTANTS.isVanillaRenderedChunkSquare() ? (float) Math.sqrt(2.0) : 1.0f) / lodDrawDistance;
- if (this.uNearFogStart != -1) this.shader.setUniform(this.uNearFogStart, nearFogStart);
- if (this.uNearFogLength != -1) this.shader.setUniform(this.uNearFogLength, 0.0f);
- if (this.uFogScale != -1) this.shader.setUniform(this.uFogScale, 1.f / lodDrawDistance);
- if (this.uFogVerticalScale != -1) this.shader.setUniform(this.uFogVerticalScale, 1.f / MC.getWrappedClientLevel().getMaxHeight());
}
private Color getFogColor(float partialTicks)
{
diff --git a/core/src/main/resources/assets/distanthorizons/lang/en_us.json b/core/src/main/resources/assets/distanthorizons/lang/en_us.json
index 80675ad7b..a2940b8c9 100644
--- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json
+++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json
@@ -269,10 +269,10 @@
"distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogMixMode":
"Height Fog Mix Mode",
"distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogMixMode.@tooltip":
- "How the height should effect the fog thickness combined with the normal function? \n\nBASIC: No special height fog effect. Fog is calculated based on camera distance \nIGNORE_HEIGHT: Ignore height completely. Fog is calculated based on horizontal distance \nADDITION: heightFog + farFog \nMAX: max(heightFog, farFog) \nMULTIPLY: heightFog * farFog \nINVERSE_MULTIPLY: 1 - (1-heightFog) * (1-farFog) \nLIMITED_ADDITION: farFog + max(farFog, heightFog) \nMULTIPLY_ADDITION: farFog + farFog * heightFog \nINVERSE_MULTIPLY_ADDITION: farFog + 1 - (1-heightFog) * (1-farFog) \nAVERAGE: farFog*0.5 + heightFog*0.5 \n\nNote that for 'BASIC' mode and 'IGNORE_HEIGHT' mode, fog settings for height fog has no effect.\n",
- "distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogMode":
- "Height Fog Mode",
- "distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogMode.@tooltip":
+ "Defines how height effects fog. \nWhen in doubt start with SPHERICAL, ADDITION, or MAX. \n\nSPHERICAL: Fog is calculated based on camera distance. \nCYLINDRICAL: Ignore height, fog is calculated based on horizontal distance. \nMAX: max(heightFog, farFog) \nADDITION: heightFog + farFog \nMULTIPLY: heightFog * farFog \nINVERSE_MULTIPLY: 1 - (1-heightFog) * (1-farFog) \nLIMITED_ADDITION: farFog + max(farFog, heightFog) \nMULTIPLY_ADDITION: farFog + farFog * heightFog \nINVERSE_MULTIPLY_ADDITION: farFog + 1 - (1-heightFog) * (1-farFog) \nAVERAGE: farFog*0.5 + heightFog*0.5",
+ "distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogDirection":
+ "Height Fog Direction",
+ "distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogDirection.@tooltip":
"Where should the height fog be located? \n\nABOVE_CAMERA: Height fog starts from camera to the sky \nBELOW_CAMERA: Height fog starts from camera to the void \nABOVE_AND_BELOW_CAMERA: Height fog starts from camera to both the sky and the void \nABOVE_SET_HEIGHT: Height fog starts from a set height to the sky \nBELOW_SET_HEIGHT: Height fog starts from a set height to the void \nABOVE_AND_BELOW_SET_HEIGHT: Height fog starts from a set height to both the sky and the void \n",
"distanthorizons.config.client.advanced.graphics.fog.heightFog.heightFogBaseHeight":
"Height Fog Base Height",
@@ -805,10 +805,10 @@
"distanthorizons.config.enum.EDhApiFogFalloff.EXPONENTIAL_SQUARED":
"Exponential squared",
- "distanthorizons.config.enum.EDhApiHeightFogMixMode.BASIC":
- "Basic",
- "distanthorizons.config.enum.EDhApiHeightFogMixMode.IGNORE_HEIGHT":
- "Ignore Height",
+ "distanthorizons.config.enum.EDhApiHeightFogMixMode.SPHERICAL":
+ "Spherical",
+ "distanthorizons.config.enum.EDhApiHeightFogMixMode.CYLINDRICAL":
+ "Cylindrical",
"distanthorizons.config.enum.EDhApiHeightFogMixMode.ADDITION":
"Addition",
"distanthorizons.config.enum.EDhApiHeightFogMixMode.MAX":
@@ -826,17 +826,17 @@
"distanthorizons.config.enum.EDhApiHeightFogMixMode.AVERAGE":
"Average",
- "distanthorizons.config.enum.EDhApiHeightFogMode.ABOVE_CAMERA":
+ "distanthorizons.config.enum.EDhApiHeightFogDirection.ABOVE_CAMERA":
"Above Camera",
- "distanthorizons.config.enum.EDhApiHeightFogMode.BELOW_CAMERA":
+ "distanthorizons.config.enum.EDhApiHeightFogDirection.BELOW_CAMERA":
"Below Camera",
- "distanthorizons.config.enum.EDhApiHeightFogMode.ABOVE_AND_BELOW_CAMERA":
+ "distanthorizons.config.enum.EDhApiHeightFogDirection.ABOVE_AND_BELOW_CAMERA":
"Above And Below Camera",
- "distanthorizons.config.enum.EDhApiHeightFogMode.ABOVE_SET_HEIGHT":
+ "distanthorizons.config.enum.EDhApiHeightFogDirection.ABOVE_SET_HEIGHT":
"Above Set Height",
- "distanthorizons.config.enum.EDhApiHeightFogMode.BELOW_SET_HEIGHT":
+ "distanthorizons.config.enum.EDhApiHeightFogDirection.BELOW_SET_HEIGHT":
"Below Set Height",
- "distanthorizons.config.enum.EDhApiHeightFogMode.ABOVE_AND_BELOW_SET_HEIGHT":
+ "distanthorizons.config.enum.EDhApiHeightFogDirection.ABOVE_AND_BELOW_SET_HEIGHT":
"Above And Below Set Height",
"distanthorizons.config.enum.EDhApiVanillaOverdraw.NEVER":
diff --git a/core/src/main/resources/shaders/fog/fog.frag b/core/src/main/resources/shaders/fog/fog.frag
index eed4c6b6b..a4495bd82 100644
--- a/core/src/main/resources/shaders/fog/fog.frag
+++ b/core/src/main/resources/shaders/fog/fog.frag
@@ -1,99 +1,120 @@
+#version 150 core
in vec2 TexCoord;
out vec4 fragColor;
+
+
uniform sampler2D uDepthMap;
// inverted model view matrix and projection matrix
uniform mat4 uInvMvmProj;
+// fog uniforms
+uniform vec4 uFogColor;
uniform float uFogScale;
uniform float uFogVerticalScale;
-uniform vec4 uFogColor;
uniform int uFullFogMode;
+uniform int uFogFalloffType;
-uniform float uNearFogStart;
-uniform float uNearFogLength;
+// fog config
+uniform float uFarFogStart;
+uniform float uFarFogLength;
+uniform float uFarFogMin;
+uniform float uFarFogRange;
+uniform float uFarFogDensity;
+
+// height fog config
+uniform float uHeightFogStart;
+uniform float uHeightFogLength;
+uniform float uHeightFogMin;
+uniform float uHeightFogRange;
+uniform float uHeightFogDensity;
-/* ========MARCO DEFINED BY RUNTIME CODE GEN=========
+uniform bool uHeightFogEnabled;
+uniform int uHeightFogFalloffType;
+uniform bool uHeightBasedOnCamera;
+uniform float uHeightFogBaseHeight;
+uniform bool uHeightFogAppliesUp;
+uniform bool uHeightFogAppliesDown;
+uniform bool uUseSphericalFog;
+uniform int uHeightFogMixingMode;
+uniform float uCameraBlockYPos;
-float farFogStart;
-float farFogLength;
-float farFogMin;
-float farFogRange;
-float farFogDensity;
-
-float heightFogStart;
-float heightFogLength;
-float heightFogMin;
-float heightFogRange;
-float heightFogDensity;
-*/
-
-// method definitions
-// ==== The below 5 methods will be run-time generated. ====
-float getNearFogThickness(float dist);
-float getFarFogThickness(float dist);
-float getHeightFogThickness(float dist);
-float calculateFarFogDepth(float horizontal, float dist, float nearFogStart);
-float calculateHeightFogDepth(float vertical, float realY);
-float mixFogThickness(float near, float far, float height);
-// =========================================================
const vec3 MAGIC = vec3(0.06711056, 0.00583715, 52.9829189);
-float InterleavedGradientNoise(const in vec2 pixel) {
- float x = dot(pixel, MAGIC.xy);
- return fract(MAGIC.z * fract(x));
-}
-vec3 calcViewPosition(float fragmentDepth) {
- vec4 ndc = vec4(TexCoord.xy, fragmentDepth, 1.0);
- ndc.xyz = ndc.xyz * 2.0 - 1.0;
- vec4 eyeCoord = uInvMvmProj * ndc;
- return eyeCoord.xyz / eyeCoord.w;
-}
+//====================//
+// method definitions //
+//====================//
+
+float InterleavedGradientNoise(const in vec2 pixel);
+vec3 calcViewPosition(float fragmentDepth);
+
+float getFarFogThickness(float dist);
+float getHeightFogThickness(float dist);
+float calculateHeightFogDepth(float worldYPos);
+float mixFogThickness(float far, float height);
+
+
+
+//======//
+// main //
+//======//
/**
* Fragment shader for fog.
- * This should be passed last so it applies above other affects like AO
- *
- * version: 2023-6-21
+ * This should be run last so it applies above other affects like Ambient Occlusioning
*/
-void main()
+void main()
{
- float vertexYPos = 100.0f;
float fragmentDepth = texture(uDepthMap, TexCoord).r;
fragColor = vec4(uFogColor.rgb, 0.0);
// a fragment depth of "1" means the fragment wasn't drawn to,
// we only want to apply Fog to LODs, not to the sky outside the LODs
- if (fragmentDepth < 1.0) {
- if (uFullFogMode == 0) {
+ if (fragmentDepth < 1.0)
+ {
+ int fogMode = uFullFogMode;
+ if (fogMode == 0)
+ {
// render fog based on distance from the camera
vec3 vertexWorldPos = calcViewPosition(fragmentDepth);
- float horizontalDist = length(vertexWorldPos.xz) * uFogScale;
- float heightDist = calculateHeightFogDepth(vertexWorldPos.y, vertexYPos) * uFogVerticalScale;
- float farDist = calculateFarFogDepth(horizontalDist, length(vertexWorldPos.xyz) * uFogScale, uNearFogStart);
+ float horizontalWorldDistance = length(vertexWorldPos.xz) * uFogScale;
+ float worldDistance = length(vertexWorldPos.xyz) * uFogScale;
+ float activeDistance = uUseSphericalFog ? worldDistance : horizontalWorldDistance;
- float nearFogThickness = getNearFogThickness(horizontalDist);
- float farFogThickness = getFarFogThickness(farDist);
- float heightFogThickness = getHeightFogThickness(heightDist);
- float mixedFogThickness = mixFogThickness(nearFogThickness, farFogThickness, heightFogThickness);
+
+ // far fog
+ float farFogThickness = getFarFogThickness(activeDistance);
+
+ // height fog
+ float heightFogDepth = calculateHeightFogDepth(vertexWorldPos.y);
+ float heightFogThickness = getHeightFogThickness(heightFogDepth);
+
+ // combined fog
+ float mixedFogThickness = mixFogThickness(farFogThickness, heightFogThickness);
fragColor.a = clamp(mixedFogThickness, 0.0, 1.0);
- float dither = InterleavedGradientNoise(gl_FragCoord.xy) - 0.5;
- fragColor.a += dither / 255.0;
+ // test
+ //fragColor.a = heightFogThickness;
+
+ // dither fog (to smooth out aliasing)
+ //float dither = InterleavedGradientNoise(gl_FragCoord.xy) - 0.5;
+ //fragColor.a += dither / 255.0;
}
- else if (uFullFogMode == 1) {
+ else if (fogMode == 1)
+ {
// render everything with the fog color
fragColor.a = 1.0;
}
- else {
+ else
+ {
// test code.
// this can be fired by manually changing the fullFogMode to a (normally)
@@ -108,22 +129,174 @@ void main()
}
}
-// Are these still needed?
-float linearFog(float x, float fogStart, float fogLength, float fogMin, float fogRange) {
- x = clamp((x-fogStart)/fogLength, 0.0, 1.0);
- return fogMin + fogRange * x;
+
+//
+// methods //
+//
+
+float InterleavedGradientNoise(const in vec2 pixel)
+{
+ float x = dot(pixel, MAGIC.xy);
+ return fract(MAGIC.z * fract(x));
+}
+
+vec3 calcViewPosition(float fragmentDepth)
+{
+ vec4 ndc = vec4(TexCoord.xy, fragmentDepth, 1.0);
+ ndc.xyz = ndc.xyz * 2.0 - 1.0;
+
+ vec4 eyeCoord = uInvMvmProj * ndc;
+ return eyeCoord.xyz / eyeCoord.w;
+}
+
+
+
+float linearFog(float worldDist, float fogStart, float fogLength, float fogMin, float fogRange)
+{
+ worldDist = (worldDist - fogStart) / fogLength;
+ worldDist = clamp(worldDist, 0.0, 1.0);
+ return fogMin + fogRange * worldDist;
}
float exponentialFog(float x, float fogStart, float fogLength,
- float fogMin, float fogRange, float fogDensity)
+float fogMin, float fogRange, float fogDensity)
{
x = max((x-fogStart)/fogLength, 0.0) * fogDensity;
return fogMin + fogRange - fogRange/exp(x);
}
float exponentialSquaredFog(float x, float fogStart, float fogLength,
- float fogMin, float fogRange, float fogDensity)
+float fogMin, float fogRange, float fogDensity)
{
x = max((x-fogStart)/fogLength, 0.0) * fogDensity;
return fogMin + fogRange - fogRange/exp(x*x);
}
+
+
+
+//
+// generated methods //
+//
+
+float getFarFogThickness(float dist)
+{
+ if (uFogFalloffType == 0) // LINEAR
+ {
+ return linearFog(dist, uFarFogStart, uFarFogLength, uFarFogMin, uFarFogRange);
+ }
+ else if (uFogFalloffType == 1) // EXPONENTIAL
+ {
+ return exponentialFog(dist, uFarFogStart, uFarFogLength, uFarFogMin, uFarFogRange, uFarFogDensity);
+ }
+ else // EXPONENTIAL_SQUARED
+ {
+ return exponentialSquaredFog(dist, uFarFogStart, uFarFogLength, uFarFogMin, uFarFogRange, uFarFogDensity);
+ }
+}
+
+float getHeightFogThickness(float dist)
+{
+ if (!uHeightFogEnabled)
+ {
+ return 0.0;
+ }
+
+ if (uHeightFogFalloffType == 0) // LINEAR
+ {
+ return linearFog(dist, uHeightFogStart, uHeightFogLength, uHeightFogMin, uHeightFogRange);
+ }
+ else if (uHeightFogFalloffType == 1) // EXPONENTIAL
+ {
+ return exponentialFog(dist, uHeightFogStart, uHeightFogLength, uHeightFogMin, uHeightFogRange, uHeightFogDensity);
+ }
+ else // EXPONENTIAL_SQUARED
+ {
+ return exponentialSquaredFog(dist, uHeightFogStart, uHeightFogLength, uHeightFogMin, uHeightFogRange, uHeightFogDensity);
+ }
+}
+
+/** 1 = full fog, 0 = no fog */
+float calculateHeightFogDepth(float worldYPos)
+{
+ // worldYPos -65 - 384
+
+
+ //worldYPos = worldYPos * -1; // negative, fog below height; positive, fog above height
+ //return worldYPos * uFogVerticalScale; // "* uFogVerticalScale" is done to convert world position to a percent of the world height;
+
+ if (!uHeightFogEnabled)
+ {
+ // ignore the height
+ return 0.0;
+ }
+
+
+ if (!uHeightBasedOnCamera)
+ {
+ worldYPos -= (uHeightFogBaseHeight - uCameraBlockYPos);
+ }
+
+
+ if (uHeightFogAppliesDown && uHeightFogAppliesUp)
+ {
+ // TODO this aint right
+ return abs(worldYPos) * uFogVerticalScale;
+ }
+ else if (uHeightFogAppliesDown)
+ {
+ // apploy fog below given height
+ return -worldYPos * uFogVerticalScale;
+ }
+ else if (uHeightFogAppliesUp)
+ {
+ // apply fog above given height
+ return worldYPos * uFogVerticalScale;
+ }
+ else
+ {
+ // shouldn't happen,
+ return 0;
+ }
+
+}
+
+float mixFogThickness(float far, float height)
+{
+ switch (uHeightFogMixingMode)
+ {
+ case 0: // BASIC
+ case 1: // IGNORE_HEIGHT
+ return far;
+
+ case 2: // MAX
+ return max(far, height);
+
+ case 3: // ADDITION
+ return (far + height);
+
+ case 4: // MULTIPLY
+ return far * height;
+
+ case 5: // INVERSE_MULTIPLY
+ return (1.0 - (1.0-far)*(1.0-height));
+
+ case 6: // LIMITED_ADDITION
+ return (far + max(far, height));
+
+ case 7: // MULTIPLY_ADDITION
+ return (far + far*height);
+
+ case 8: // INVERSE_MULTIPLY_ADDITION
+ return (far + 1.0 - (1.0-far)*(1.0-height));
+
+ case 9: // AVERAGE
+ return (far*0.5 + height*0.5);
+ }
+
+ // shouldn't happen, but default to BASIC / IGNORE_HEIGHT
+ // if an invalid option is selected
+ return far;
+}
+
+
+