ADVANCED FOGGGGGGGGGGGGGGGG~~~~~~~~~~~~~~~~

This commit is contained in:
TomTheFurry
2022-03-16 18:50:41 +08:00
parent cf519c02be
commit 4097cf7619
13 changed files with 700 additions and 249 deletions
@@ -1,26 +1,43 @@
package com.seibel.lod.core.enums.rendering;
import java.util.Objects;
public class FogSetting {
public final double start;
public final double end;
public final double min;
public final double max;
public final double density;
public final Type type;
public final FogType fogType;
public FogSetting(double start, double end, double min, double max, double density, Type type) {
public FogSetting(double start, double end, double min, double max, double density, FogType fogType) {
this.start = start;
this.end = end;
this.min = min;
this.max = max;
this.density = density;
this.type = type;
this.fogType = fogType;
}
public enum Type {
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
FogSetting that = (FogSetting) o;
return Double.compare(that.start, start) == 0 && Double.compare(that.end, end) == 0 && Double.compare(that.min, min) == 0 && Double.compare(that.max, max) == 0 && Double.compare(that.density, density) == 0 && fogType == that.fogType;
}
@Override
public int hashCode() {
return Objects.hash(start, end, min, max, density, fogType);
}
public enum FogType {
LINEAR,
EXPONENTIAL,
EXPONENTIAL_SQUARED,
// TEXTURE_BASED, // TODO: Impl this
}
}
@@ -0,0 +1,14 @@
package com.seibel.lod.core.enums.rendering;
public enum HeightFogMixMode {
BASIC,
IGNORE_HEIGHT,
ADDITION,
MAX,
MULTIPLY,
INVERSE_MULTIPLY,
LIMITED_ADDITION,
MULTIPLY_ADDITION,
INVERSE_MULTIPLY_ADDITION,
AVERAGE,
}
@@ -1,9 +1,20 @@
package com.seibel.lod.core.enums.rendering;
public enum HeightFogMode {
BASIC,
IGNORE_HEIGHT,
ADDITION,
MAX,
SQUARED_ADDITION,
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;
HeightFogMode(boolean basedOnCamera, boolean above, boolean below) {
this.basedOnCamera = basedOnCamera;
this.above = above;
this.below = below;
}
}
@@ -109,7 +109,7 @@ public class RenderRegion implements AutoCloseable
public boolean render(LodDimension renderDim,
Vec3d cameraPos, AbstractBlockPosWrapper cameraBlockPos, Vec3f cameraDir,
Mat4f baseModelViewMatrix, boolean enableDirectionalCulling, LodRenderProgram program) {
boolean enableDirectionalCulling, LodRenderProgram program) {
if (!frontState.compareAndSet(FrontState.Unused, FrontState.Rendering)) return false;
try {
if (renderDim != lodDim) return false;
@@ -120,7 +120,7 @@ public class RenderRegion implements AutoCloseable
if (state == BackState.Complete) {
if (renderBufferBack != null) {
if (ENABLE_EVENT_LOGGING) ApiShared.LOGGER.info("RenderRegion swap @ {}", regionPos);
boolean shouldKeep = renderBufferFront==null ? false : renderBufferFront.onSwapToBack();
boolean shouldKeep = renderBufferFront != null && renderBufferFront.onSwapToBack();
RenderBuffer temp = shouldKeep ? renderBufferFront : null;
renderBufferFront = renderBufferBack;
renderBufferBack = temp;
@@ -131,12 +131,11 @@ public class RenderRegion implements AutoCloseable
}
}
if (renderBufferFront == null) return false;
Mat4f localModelViewMatrix = baseModelViewMatrix.copy();
localModelViewMatrix.multiplyTranslationMatrix(
(regionPos.x * LodUtil.REGION_WIDTH) - cameraPos.x,
LodBuilder.MIN_WORLD_HEIGHT - cameraPos.y,
(regionPos.z * LodUtil.REGION_WIDTH) - cameraPos.z);
program.fillUniformModelMatrix(localModelViewMatrix);
program.setModelPos(new Vec3f(
(float) ((regionPos.x * LodUtil.REGION_WIDTH) - cameraPos.x),
(float) (LodBuilder.MIN_WORLD_HEIGHT - cameraPos.y),
(float) ((regionPos.z * LodUtil.REGION_WIDTH) - cameraPos.z)));
return renderBufferFront.render(program);
} finally {
frontState.compareAndSet(FrontState.Rendering, FrontState.Unused);
@@ -19,11 +19,18 @@
package com.seibel.lod.core.render;
import com.seibel.lod.core.enums.rendering.FogDistance;
import com.seibel.lod.core.enums.rendering.FogDrawMode;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.enums.rendering.*;
import com.seibel.lod.core.handlers.IReflectionHandler;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.render.objects.Shader;
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.util.Objects;
/**
* This object is just a replacement for an array
* to make things easier to understand in the LodRenderer.
@@ -33,43 +40,269 @@ import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
*/
public class LodFogConfig
{
public FogDrawMode fogDrawMode;
public FogDistance fogDistance;
public float nearFogStart = 0;
public float nearFogEnd = 0;
public float farFogStart = 0;
public float farFogEnd = 0;
public LodFogConfig(ILodConfigWrapperSingleton config, IReflectionHandler reflectionHandler, int farPlaneBlockDistance, int vanillaBlockRenderedDistance) {
fogDrawMode = config.client().graphics().fogQuality().getFogDrawMode();
if (fogDrawMode == FogDrawMode.USE_OPTIFINE_SETTING)
fogDrawMode = reflectionHandler.getFogDrawMode();
// how different distances are drawn depends on the quality set
fogDistance = config.client().graphics().fogQuality().getFogDistance();
// far fog //
if (config.client().graphics().fogQuality().getFogDistance() == FogDistance.NEAR_AND_FAR)
farFogStart = farPlaneBlockDistance * 0.9f;
else
// for more realistic fog when using FAR
farFogStart = Math.min(vanillaBlockRenderedDistance * 1.5f, farPlaneBlockDistance * 0.9f);
farFogEnd = farPlaneBlockDistance;
// near fog //
// the reason that I wrote fogEnd then fogStart backwards
// is because we are using fog backwards to how
// it is normally used, hiding near objects
// instead of far objects.
nearFogEnd = vanillaBlockRenderedDistance * 1.41f;
nearFogStart = vanillaBlockRenderedDistance * 1.6f;
private static final IReflectionHandler REFLECTION_HANDLER = SingletonHandler.get(IReflectionHandler.class);
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
public static final boolean DEBUG_DUMP_GENERATED_CODE = true;
public final FogSetting farFogSetting;
public final FogSetting heightFogSetting;
public final HeightFogMixMode heightFogMixMode;
public final HeightFogMode heightFogMode;
public final float heightFogHeight;
final boolean drawNearFog;
public static LodFogConfig generateFogConfig() {
FogDrawMode doDraw = CONFIG.client().graphics().fogQuality().getFogDrawMode();
if (doDraw == FogDrawMode.USE_OPTIFINE_SETTING)
doDraw = REFLECTION_HANDLER.getFogDrawMode();
return new LodFogConfig(doDraw);
}
private LodFogConfig(FogDrawMode fogDrawMode) {
if (fogDrawMode == FogDrawMode.FOG_DISABLED) {
drawNearFog = false;
farFogSetting = null;
heightFogMixMode = null;
heightFogMode = null;
heightFogSetting = null;
heightFogHeight = 0.f;
} else {
ILodConfigWrapperSingleton.IClient.IGraphics.IFogQuality setting = CONFIG.client().graphics().fogQuality();
FogDistance fogDistance = setting.getFogDistance();
drawNearFog = (fogDistance == FogDistance.NEAR || fogDistance == FogDistance.NEAR_AND_FAR);
if (fogDistance == FogDistance.FAR || fogDistance == FogDistance.NEAR_AND_FAR) {
farFogSetting = setting.advancedFog().computeFarFogSetting();
heightFogMixMode = setting.advancedFog().heightFog().getHeightFogMixMode();
if (heightFogMixMode != HeightFogMixMode.IGNORE_HEIGHT && heightFogMixMode != HeightFogMixMode.BASIC) {
heightFogSetting = setting.advancedFog().heightFog().computeHeightFogSetting();
heightFogMode = setting.advancedFog().heightFog().getHeightFogMode();
if (heightFogMode.basedOnCamera) {
heightFogHeight = 0.f;
} else {
heightFogHeight = (float) setting.advancedFog().heightFog().getHeightFogHeight();
}
} else {
heightFogSetting = null;
heightFogMode = null;
heightFogHeight = 0.f;
}
} else {
farFogSetting = null;
heightFogSetting = null;
heightFogMode = null;
heightFogMixMode = null;
heightFogHeight = 0.f;
}
}
}
public StringBuilder loadAndProcessFragShader(String path, boolean absoluteFilePath) {
StringBuilder str = makeRuntimeDefine();
generateRuntimeShaderCode(Shader.loadFile(path, absoluteFilePath, str));
if (DEBUG_DUMP_GENERATED_CODE) {
try (FileOutputStream file = new FileOutputStream("debugGenerated.frag", false)) {
file.write(str.toString().getBytes(StandardCharsets.UTF_8));
ApiShared.LOGGER.info("Debug dumped generated code to debugGenerated.frag for {}", path);
} catch (IOException e) {
ApiShared.LOGGER.warn("Failed to debug dump generated code to file for {}", path);
}
}
return str;
}
private StringBuilder makeRuntimeDefine() {
StringBuilder str = new StringBuilder();
str.append("// =======RUNTIME GENERATED DEFINE SECTION========\n#version 150 core\n");
if (farFogSetting == null) {
str.append("""
#define farFogStart 0.0
#define farFogLength 0.0
#define farFogMin 0.0
#define farFogRange 0.0
#define farFogDensity 0.0
#define heightFogStart 0.0
#define heightFogLength 0.0
#define heightFogMin 0.0
#define heightFogRange 0.0
#define heightFogDensity 0.0
""");
} else {
str.append("\n#define farFogStart ");
str.append(farFogSetting.start);
str.append("\n#define farFogLength ");
str.append(farFogSetting.end - farFogSetting.start);
str.append("\n#define farFogMin ");
str.append(farFogSetting.min);
str.append("\n#define farFogRange ");
str.append(farFogSetting.max - farFogSetting.min);
str.append("\n#define farFogDensity ");
str.append(farFogSetting.density);
str.append("\n");
if (heightFogSetting == null) {
str.append("""
#define heightFogStart 0.0
#define heightFogLength 0.0
#define heightFogMin 0.0
#define heightFogRange 0.0
#define heightFogDensity 0.0
""");
} else {
str.append("\n#define heightFogStart ");
str.append(heightFogSetting.start);
str.append("\n#define heightFogLength ");
str.append(heightFogSetting.end - heightFogSetting.start);
str.append("\n#define heightFogMin ");
str.append(heightFogSetting.min);
str.append("\n#define heightFogRange ");
str.append(heightFogSetting.max - heightFogSetting.min);
str.append("\n#define heightFogDensity ");
str.append(heightFogSetting.density);
str.append("\n");
}
}
str.append("// =======RUNTIME END========\n");
return str;
}
private static String getFarFogMethod(FogSetting.FogType 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";
}
throw new IllegalArgumentException();
}
private static String getHeightDepthMethod(HeightFogMode mode, float heightFogHeight) {
String str = "";
if (!mode.basedOnCamera) {
str = " vertical = realY - (" + heightFogHeight + ");\n";
}
if (mode.below && mode.above) {
str += " return abs(vertical);\n";
} else if (mode.below) {
str += " return -vertical;\n";
} else if (mode.above) {
str += " return vertical;\n";
} else {
str += " return 0;\n";
}
return str;
}
private static String getHeightFogMethod(FogSetting.FogType 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";
}
throw new IllegalArgumentException();
}
private static String getMixFogMethod(HeightFogMixMode mode) {
switch (mode) {
case BASIC:
case IGNORE_HEIGHT:
return " return max(near, far);\n";
case ADDITION:
return " return max(near, far + height);\n";
case MAX:
return " return max(near, max(far, height));\n";
case INVERSE_MULTIPLY:
return " return max(near, 1.0 - (1.0-far)*(1.0-height));\n";
case MULTIPLY:
return " return max(near, far*height);\n";
case LIMITED_ADDITION:
return " return max(near, far + max(far, height));\n";
case MULTIPLY_ADDITION:
return " return max(near, far + far*height);\n";
case INVERSE_MULTIPLY_ADDITION:
return " return max(near, far + 1.0 - (1.0-far)*(1.0-height));\n";
case AVERAGE:
return " return max(near, far*0.5 + height*0.5);\n";
}
throw new IllegalArgumentException();
}
private void generateRuntimeShaderCode(StringBuilder str) {
str.append("// =======RUNTIME GENERATED CODE SECTION========\n");
// Generate method: float getNearFogThickness(float dist);
if (drawNearFog) {
str.append("""
float getNearFogThickness(float dist) {
return linearFog(dist, nearFogStart, nearFogLength, 1.0, -1.0);
}
""");
} else {
str.append("""
float getNearFogThickness(float dist) {return 0.0;}
""");
}
if (farFogSetting == null) {
str.append("""
float getFarFogThickness(float dist) { return 0.0; }
float getHeightFogThickness(float dist) { return 0.0; }
float calculateFarFogDepth(float horizontal, float dist) { return 0.0; }
float calculateHeightFogDepth(float vertical, float realY) { return 0.0; }
float mixFogThickness(float near, float far, float height) { return near; }
""");
} else {
// Generate method: float getFarFogThickness(float dist);
str.append("float getFarFogThickness(float dist) {\n");
str.append(getFarFogMethod(farFogSetting.fogType));
str.append("}\n");
// Generate method: float getHeightFogThickness(float dist);
if (heightFogSetting == null) {
str.append("""
float getHeightFogThickness(float dist) { return 0.0; }
float calculateHeightFogDepth(float vertical, float realY) { return 0.0; }
""");
} else {
str.append("float getHeightFogThickness(float dist) {\n");
str.append(getHeightFogMethod(heightFogSetting.fogType));
str.append("}\n");
str.append("float calculateHeightFogDepth(float vertical, float realY) {\n");
str.append(getHeightDepthMethod(heightFogMode, heightFogHeight));
str.append("}\n");
}
// Generate method: calculateFarFogDepth(float horizontal, float vertical, float dist);
str.append("float calculateFarFogDepth(float horizontal, float dist) {\n");
if (heightFogMixMode == HeightFogMixMode.BASIC) {
str.append(" return dist;\n");
} else {
str.append(" return horizontal;\n");
}
str.append("}\n");
// Generate method: float mixFogThickness(float near, float far, float height);
str.append("float mixFogThickness(float near, float far, float height) {\n");
str.append(getMixFogMethod(heightFogMixMode));
str.append("}\n");
}
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
LodFogConfig that = (LodFogConfig) o;
return Float.compare(that.heightFogHeight, heightFogHeight) == 0 && drawNearFog == that.drawNearFog && Objects.equals(farFogSetting, that.farFogSetting) && Objects.equals(heightFogSetting, that.heightFogSetting) && heightFogMixMode == that.heightFogMixMode && heightFogMode == that.heightFogMode;
}
@Override
public int hashCode() {
return Objects.hash(farFogSetting, heightFogSetting, heightFogMixMode, heightFogMode, heightFogHeight, drawNearFog);
}
}
@@ -23,65 +23,66 @@ import java.awt.Color;
import com.seibel.lod.core.enums.rendering.FogDistance;
import com.seibel.lod.core.enums.rendering.FogDrawMode;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.objects.math.Mat4f;
import com.seibel.lod.core.render.objects.ShaderProgram;
import com.seibel.lod.core.render.objects.VertexAttribute;
import com.seibel.lod.core.render.objects.VertexAttributePostGL43;
import com.seibel.lod.core.render.objects.VertexAttributePreGL43;
import com.seibel.lod.core.objects.math.Vec3f;
import com.seibel.lod.core.render.objects.*;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.wrapperInterfaces.IVersionConstants;
import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
public class LodRenderProgram extends ShaderProgram {
public static final String VERTEX_SHADER_PATH = "shaders/standard.vert";
public static final String FRAGMENT_SHADER_PATH = "shaders/flat_shaded.frag";
private static final IVersionConstants VERSION_CONSTANTS = SingletonHandler.get(IVersionConstants.class);
public final VertexAttribute vao;
// Attributes
public final int posAttrib;
public final int colAttrib;
//public final int lightAttrib; //Sky light then block light
// Uniforms
public final int mvmUniform;
public final int projUniform;
//public final int cameraUniform;
public final int fogColorUniform;
// public final int skyLightUniform; worldSkyLight is currently not used
public final int combinedMatUniform;
public final int modelOffsetUniform;
public final int worldYOffsetUniform;
public final int lightMapUniform;
// Fog Uniforms
public final int fogEnabledUniform;
public final int nearFogEnabledUniform;
public final int farFogEnabledUniform;
public final int fogColorUniform;
public final int fogScaleUniform;
public final int fogVerticalScaleUniform;
public final int nearFogStartUniform;
public final int nearFogEndUniform;
public final int farFogStartUniform;
public final int farFogEndUniform;
public final int nearFogLengthUniform;;
public final int fullFogModeUniform;
public final LodFogConfig fogConfig;
// This will bind VertexAttribute
public LodRenderProgram() {
super(VERTEX_SHADER_PATH, FRAGMENT_SHADER_PATH, "fragColor");
public LodRenderProgram(LodFogConfig fogConfig) {
super(() -> Shader.loadFile(VERTEX_SHADER_PATH, false, new StringBuilder()).toString(),
() -> fogConfig.loadAndProcessFragShader(FRAGMENT_SHADER_PATH, false).toString(),
"fragColor");
this.fogConfig = fogConfig;
posAttrib = getAttributeLocation("vPosition");
colAttrib = getAttributeLocation("color");
//lightAttrib = getAttributeLocation("light");
mvmUniform = getUniformLocation("modelViewMatrix");
projUniform = getUniformLocation("projectionMatrix");
//cameraUniform = getUniformLocation("cameraPos");
fogColorUniform = getUniformLocation("fogColor");
// skyLightUniform = getUniformLocation("worldSkyLight");
colAttrib = tryGetAttributeLocation("color"); // might be optimized out in some fog settings
combinedMatUniform = getUniformLocation("combinedMatrix");
modelOffsetUniform = getUniformLocation("modelOffset");
worldYOffsetUniform = tryGetUniformLocation("worldYOffset");
lightMapUniform = getUniformLocation("lightMap");
// Fog uniforms
fogEnabledUniform = getUniformLocation("fogEnabled");
nearFogEnabledUniform = getUniformLocation("nearFogEnabled");
farFogEnabledUniform = getUniformLocation("farFogEnabled");
fullFogModeUniform = getUniformLocation("fullFogMode");
fogColorUniform = getUniformLocation("fogColor");
fogScaleUniform = tryGetUniformLocation("fogScale");
fogVerticalScaleUniform = tryGetUniformLocation("fogVerticalScale");
// near
nearFogStartUniform = getUniformLocation("nearFogStart");
nearFogEndUniform = getUniformLocation("nearFogEnd");
// far
farFogStartUniform = getUniformLocation("farFogStart");
farFogEndUniform = getUniformLocation("farFogEnd");
nearFogStartUniform = tryGetUniformLocation("nearFogStart");
nearFogLengthUniform = tryGetUniformLocation("nearFogLength");
// TODO: Add better use of the LODFormat thing
int vertexByteCount = LodUtil.LOD_VERTEX_FORMAT.getByteSize();
if (GLProxy.getInstance().VertexAttributeBufferBindingSupported)
@@ -92,7 +93,7 @@ public class LodRenderProgram extends ShaderProgram {
// Now a pos+light.
vao.setVertexAttribute(0, posAttrib, VertexAttribute.VertexPointer.addUnsignedShortsPointer(4, false)); // 2+2+2+2
//vao.setVertexAttribute(0, posAttrib, VertexAttribute.VertexPointer.addVec3Pointer(false)); // 4+4+4
vao.setVertexAttribute(0, colAttrib, VertexAttribute.VertexPointer.addUnsignedBytesPointer(4, true)); // +4
vao.setVertexAttribute(0, colAttrib == -1 ? 2 : colAttrib, VertexAttribute.VertexPointer.addUnsignedBytesPointer(4, true)); // +4
//vao.setVertexAttribute(0, lightAttrib, VertexAttribute.VertexPointer.addUnsignedBytesPointer(2, false)); // +4 due to how it aligns
try {
vao.completeAndCheck(vertexByteCount);
@@ -101,6 +102,13 @@ public class LodRenderProgram extends ShaderProgram {
throw e;
}
}
// If not usable, return a new LodFogConfig to be constructed
public LodFogConfig isShaderUsable() {
LodFogConfig newConfig = LodFogConfig.generateFogConfig();
if (fogConfig.equals(newConfig)) return null;
return newConfig;
}
// Override ShaderProgram.bind()
public void bind() {
@@ -127,41 +135,33 @@ public class LodRenderProgram extends ShaderProgram {
vao.unbindBuffersFromAllBindingPoint();
}
public void fillUniformData(Mat4f projectionMatrix, Color fogColor, int skyLight, int lightmapBindPoint) {
public void fillUniformData(Mat4f combinedMatrix, Color fogColor,
int lightmapBindPoint, int worldHeight, int worldYOffset, int lodDrawDistance,
int vanillaDrawDistance, boolean fullFogMode) {
super.bind();
vanillaDrawDistance += 32; // Give it a 2 chunk boundary for near fog.
// uniforms
setUniform(projUniform, projectionMatrix);
setUniform(fogColorUniform, fogColor);
setUniform(combinedMatUniform, combinedMatrix);
// setUniform(skyLightUniform, skyLight);
setUniform(lightMapUniform, lightmapBindPoint);
if (worldYOffsetUniform != -1) setUniform(worldYOffsetUniform, (float)worldYOffset);
// Fog
setUniform(fullFogModeUniform, fullFogMode ? 1 : 0);
setUniform(fogColorUniform, fogColor);
float nearFogLen = vanillaDrawDistance * 0.2f / lodDrawDistance;
float nearFogStart = vanillaDrawDistance * (VERSION_CONSTANTS.isVanillaRenderedChunkSquare() ? (float)Math.sqrt(2.) : 1.f) / lodDrawDistance;
if (nearFogStartUniform != -1) setUniform(nearFogStartUniform, nearFogStart);
if (nearFogLengthUniform != -1) setUniform(nearFogLengthUniform, nearFogLen);
if (fogScaleUniform != -1) setUniform(fogScaleUniform, 1.f/lodDrawDistance);
if (fogVerticalScaleUniform != -1) setUniform(fogVerticalScaleUniform, 1.f/worldHeight);
}
public void fillUniformModelMatrix(Mat4f modelViewMatrix) {
super.bind();
setUniform(mvmUniform, modelViewMatrix);
}
public void fillUniformDataForFog(LodFogConfig fogSettings, boolean allFogMode) {
super.bind();
if (allFogMode) {
setUniform(fogEnabledUniform, true);
setUniform(nearFogEnabledUniform, false);
setUniform(farFogEnabledUniform, true);
setUniform(farFogStartUniform, 0.0f);
setUniform(farFogEndUniform, 0.0f);
} else if (fogSettings.fogDrawMode != FogDrawMode.FOG_DISABLED) {
setUniform(fogEnabledUniform, true);
setUniform(nearFogEnabledUniform, fogSettings.fogDistance != FogDistance.FAR);
setUniform(farFogEnabledUniform, fogSettings.fogDistance != FogDistance.NEAR);
// near
setUniform(nearFogStartUniform, fogSettings.nearFogStart);
setUniform(nearFogEndUniform, fogSettings.nearFogEnd);
// far
setUniform(farFogStartUniform, fogSettings.farFogStart);
setUniform(farFogEndUniform, fogSettings.farFogEnd);
} else {
setUniform(fogEnabledUniform, false);
}
public void setModelPos(Vec3f modelPos) {
setUniform(modelOffsetUniform, modelPos);
}
}
@@ -77,7 +77,6 @@ public class LodRenderer
private static final IMinecraftClientWrapper MC = SingletonHandler.get(IMinecraftClientWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.get(IMinecraftRenderWrapper.class);
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
private static final IReflectionHandler REFLECTION_HANDLER = SingletonHandler.get(IReflectionHandler.class);
public static final int VANILLA_REFRESH_TIMEOUT = 60;
/**
@@ -251,7 +250,6 @@ public class LodRenderer
profiler.push("LOD draw setup");
LagSpikeCatcher drawSetup = new LagSpikeCatcher();
/*---------Set GL State--------*/
// Make sure to unbind current VBO so we don't mess up vanilla settings
LagSpikeCatcher drawGLSetup = new LagSpikeCatcher();
@@ -294,6 +292,11 @@ public class LodRenderer
drawObjectSetup.end("drawObjectSetup");
} else {
LagSpikeCatcher drawShaderBind = new LagSpikeCatcher();
LodFogConfig newConfig = shaderProgram.isShaderUsable();
if (newConfig != null) {
shaderProgram.free();
shaderProgram = new LodRenderProgram(newConfig);
}
shaderProgram.bind();
drawShaderBind.end("drawShaderBind");
}
@@ -312,18 +315,18 @@ public class LodRenderer
farPlaneBlockDistance = Math.min(CONFIG.client().graphics().quality().getLodChunkRenderDistance(), LodUtil.CEILED_DIMENSION_MAX_RENDER_DISTANCE) * LodUtil.CHUNK_WIDTH;
else
farPlaneBlockDistance = CONFIG.client().graphics().quality().getLodChunkRenderDistance() * LodUtil.CHUNK_WIDTH;
LodFogConfig fogSettings = new LodFogConfig(CONFIG, REFLECTION_HANDLER, farPlaneBlockDistance, vanillaBlockRenderedDistance);
drawCalculateParams.end("drawCalculateParams");
Mat4f projectionMatrix = createProjectionMatrix(baseProjectionMatrix, vanillaBlockRenderedDistance, farPlaneBlockDistance);
Mat4f combinedMatrix = createCombinedMatrix(baseProjectionMatrix, baseModelViewMatrix, vanillaBlockRenderedDistance, farPlaneBlockDistance);
/*---------Fill uniform data--------*/
LagSpikeCatcher drawFillData = new LagSpikeCatcher();
// Fill the uniform data. Note: GL33.GL_TEXTURE0 == texture bindpoint 0
shaderProgram.fillUniformData(projectionMatrix,
shaderProgram.fillUniformData(combinedMatrix,
MC_RENDER.isFogStateSpecial() ? getSpecialFogColor(partialTicks) : getFogColor(partialTicks),
(int) (MC.getSkyDarken(partialTicks) * 15), 0);
// Previous guy said fog setting may be different from region to region, but the fogSettings never changed... soooooo...
shaderProgram.fillUniformDataForFog(fogSettings, MC_RENDER.isFogStateSpecial());
0, MC.getWrappedClientWorld().getHeight(), MC.getWrappedClientWorld().getMinHeight(), farPlaneBlockDistance,
vanillaBlockRenderedDistance, MC_RENDER.isFogStateSpecial());
// Note: Since lightmapTexture is changing every frame, it's faster to recreate it than to reuse the old one.
LagSpikeCatcher drawFillLightmap = new LagSpikeCatcher();
lightmapTexture.fillData(MC_RENDER.getLightmapTextureWidth(), MC_RENDER.getLightmapTextureHeight(), MC_RENDER.getLightmapPixels());
@@ -358,7 +361,7 @@ public class LodRenderer
RenderRegion region = regions.get(regionX, regionZ);
if (region == null) continue;
if (region.render(lodDim, cameraPos, cameraBlockPos, cameraDir,
baseModelViewMatrix, !cullingDisabled, shaderProgram)) drawCount++;
!cullingDisabled, shaderProgram)) drawCount++;
}
}
if( (ox == oy) || ((ox < 0) && (ox == -oy)) || ((ox > 0) && (ox == 1-oy))){
@@ -429,7 +432,7 @@ public class LodRenderer
}
isSetupComplete = true;
shaderProgram = new LodRenderProgram();
shaderProgram = new LodRenderProgram(LodFogConfig.generateFogConfig());
}
/** Create all buffers that will be used. */
@@ -456,18 +459,22 @@ public class LodRenderer
/**
* create and return a new projection matrix based on MC's projection matrix
* @param currentProjectionMatrix this is Minecraft's current projection matrix
* @param projMat this is Minecraft's current projection matrix
* @param modelMat this is Minecraft's current model matrix
* @param vanillaBlockRenderedDistance Minecraft's vanilla far plane distance
*/
private static Mat4f createProjectionMatrix(Mat4f currentProjectionMatrix, float vanillaBlockRenderedDistance, int farPlaneBlockDistance)
private static Mat4f createCombinedMatrix(Mat4f projMat, Mat4f modelMat, float vanillaBlockRenderedDistance, int farPlaneBlockDistance)
{
//Create a copy of the current matrix, so the current matrix isn't modified.
Mat4f lodProj = currentProjectionMatrix.copy();
Mat4f lodProj = projMat.copy();
//Set new far and near clip plane values.
lodProj.setClipPlanes(
CONFIG.client().graphics().advancedGraphics().getUseExtendedNearClipPlane() ? vanillaBlockRenderedDistance / 5 : 1,
farPlaneBlockDistance * LodUtil.CHUNK_WIDTH / 2);
CONFIG.client().graphics().advancedGraphics().getUseExtendedNearClipPlane() ?
(vanillaBlockRenderedDistance-16) : 16,
(float)((farPlaneBlockDistance+LodUtil.REGION_WIDTH) * Math.sqrt(2)));
lodProj.multiply(modelMat);
return lodProj;
}
@@ -54,7 +54,7 @@ public class Shader
ApiShared.LOGGER.info("Loading shader at "+path);
// Create an empty shader object
id = GL32.glCreateShader(type);
StringBuilder source = loadFile(path, absoluteFilePath);
StringBuilder source = loadFile(path, absoluteFilePath, new StringBuilder());
GL32.glShaderSource(id, source);
GL32.glCompileShader(id);
@@ -68,14 +68,30 @@ public class Shader
ApiShared.LOGGER.info("Shader at "+path+" loaded sucessfully.");
}
public Shader(int type, String sourceString)
{
ApiShared.LOGGER.info("Loading shader with soruceString:\n{}", sourceString);
// Create an empty shader object
id = GL32.glCreateShader(type);
GL32.glShaderSource(id, sourceString);
GL32.glCompileShader(id);
// check if the shader compiled
int status = GL32.glGetShaderi(id, GL32.GL_COMPILE_STATUS);
if (status != GL32.GL_TRUE) {
String message = "Shader compiler error. Details: "+GL32.glGetShaderInfoLog(id);
free(); // important!
throw new RuntimeException(message);
}
ApiShared.LOGGER.info("Shader loaded sucessfully.");
}
// REMEMBER to always free the resource!
public void free() {
GL32.glDeleteShader(id);
}
private StringBuilder loadFile(String path, boolean absoluteFilePath) {
StringBuilder stringBuilder = new StringBuilder();
public static StringBuilder loadFile(String path, boolean absoluteFilePath, StringBuilder stringBuilder) {
try
{
// open the file
@@ -21,6 +21,7 @@ package com.seibel.lod.core.render.objects;
import java.awt.Color;
import java.nio.FloatBuffer;
import java.util.function.Supplier;
import org.lwjgl.opengl.GL32;
import org.lwjgl.system.MemoryStack;
@@ -49,19 +50,26 @@ public class ShaderProgram
* This will bind ShaderProgram */
public ShaderProgram(String vert, String frag, String fragDataOutputName)
{
Shader vertShader = new Shader(GL32.GL_VERTEX_SHADER, vert, false);
Shader fragShader = new Shader(GL32.GL_FRAGMENT_SHADER, frag, false);
this(() -> Shader.loadFile(vert, false, new StringBuilder()).toString(),
() -> Shader.loadFile(frag, false, new StringBuilder()).toString(),
fragDataOutputName);
}
public ShaderProgram(Supplier<String> vert, Supplier<String> frag, String fragDataOutputName)
{
Shader vertShader = new Shader(GL32.GL_VERTEX_SHADER, vert.get());
Shader fragShader = new Shader(GL32.GL_FRAGMENT_SHADER, frag.get());
id = GL32.glCreateProgram();
GL32.glAttachShader(this.id, vertShader.id);
GL32.glAttachShader(this.id, fragShader.id);
//GL32.glBindFragDataLocation(id, 0, fragDataOutputName);
//GL32.glBindFragDataLocation(id, 0, fragDataOutputName);
GL32.glLinkProgram(this.id);
vertShader.free(); // important!
fragShader.free(); // important!
int status = GL32.glGetProgrami(this.id, GL32.GL_LINK_STATUS);
if (status != GL32.GL_TRUE) {
String message = "Shader Link Error. Details: "+GL32.glGetProgramInfoLog(this.id);
@@ -70,7 +78,7 @@ public class ShaderProgram
}
GL32.glUseProgram(id); // This HAVE to be a direct call to prevent calling the overloaded version
}
/** This will bind ShaderProgram */
public void bind()
{
@@ -101,7 +109,13 @@ 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
public int tryGetAttributeLocation(CharSequence name)
{
return GL32.glGetAttribLocation(id, name);
}
/** WARNING: Slow native call! Cache it if possible!
* Gets the location of a uniform variable with specified name.
* Calls GL20.glGetUniformLocation(id, name)
@@ -117,6 +131,13 @@ public class ShaderProgram
return i;
}
// 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);
}
/** Requires ShaderProgram binded. */
public void setUniform(int location, boolean value)
{
@@ -229,7 +229,7 @@ public interface ILodConfigWrapperSingleton extends IBindable
interface IAdvancedFog {
String DESC = "Advanced settings for fog rendering. Has no effect if Far Fog is not drawn \n"
+ "See https://www.desmos.com/calculator/drzzlfmur9 for how setting effect the curve.";
+ "See https://www.desmos.com/calculator/?????? for how setting effect the curve.";
MinDefaultMax<Double> FOG_RANGE = new MinDefaultMax<>(0.0,1.0, Math.sqrt(2.0));
@@ -271,16 +271,16 @@ public interface ILodConfigWrapperSingleton extends IBindable
double getFarFogMax();
void setFarFogMax(double newFarFogMax);
FogSetting.Type FAR_FOG_TYPE_DEFAULT = FogSetting.Type.EXPONENTIAL_SQUARED;
FogSetting.FogType FAR_FOG_TYPE_DEFAULT = FogSetting.FogType.EXPONENTIAL_SQUARED;
String FAR_FOG_TYPE_DESC = ""
+ " How the fog thickness should be calculated from distance? \n"
+ "\n"
+ " "+ FogSetting.Type.LINEAR + ": Linear based on distance (will ignore 'density')\n"
+ " "+ FogSetting.Type.EXPONENTIAL + ": 1/(e^(distance*density)) \n"
+ " "+ FogSetting.Type.EXPONENTIAL_SQUARED + ": 1/(e^((distance*density)^2) \n";
+ " "+ FogSetting.FogType.LINEAR + ": Linear based on distance (will ignore 'density')\n"
+ " "+ FogSetting.FogType.EXPONENTIAL + ": 1/(e^(distance*density)) \n"
+ " "+ FogSetting.FogType.EXPONENTIAL_SQUARED + ": 1/(e^((distance*density)^2) \n";
//+ " "+ FogSetting.Type.TEXTURE_BASED + ": Use a provided 1D texture mapping (will ignore 'density', 'min', and 'max')\n";
FogSetting.Type getFarFogType();
void setFarFogType(FogSetting.Type newFarFogType);
FogSetting.FogType getFarFogType();
void setFarFogType(FogSetting.FogType newFarFogType);
MinDefaultMax<Double> FAR_FOG_DENSITY_MIN_DEFAULT_MAX = new MinDefaultMax<>(0.01,2.5, 50.0);
String FAR_FOG_DENSITY_DESC = ""
@@ -293,37 +293,61 @@ public interface ILodConfigWrapperSingleton extends IBindable
String DESC = "Advanced settings for how far fog interacts with height. Has no effect if Far Fog is not drawn \n"
+ "See https://www.desmos.com/calculator/drzzlfmur9 for how setting effect the curve.";
HeightFogMode HEIGHT_FOG_MODE_DEFAULT = HeightFogMode.BASIC;
String HEIGHT_FOG_MODE_DESC = ""
HeightFogMixMode HEIGHT_FOG_MIX_MODE_DEFAULT = HeightFogMixMode.BASIC;
String HEIGHT_FOG_MIX_MODE_DESC = ""
+ " How the height should effect the fog thickness combined with the normal function? \n"
+ "\n"
+ " " + HeightFogMode.BASIC + ": No special height fog effect. Fog is calculated based on camera distance \n"
+ " " + HeightFogMode.IGNORE_HEIGHT + ": Ignore height completely. Fog is calculated based on horizontal distance \n"
+ " " + HeightFogMode.ADDITION + ": The calculated Height Fog thickness is added to Horizontal Fog thickness \n"
+ " " + HeightFogMode.MAX + ": Use the max of Height Fog thickness and Horizontal Fog thickness \n"
+ " " + HeightFogMode.SQUARED_ADDITION + ": Height Fog thickness and Horizontal Fog thickness is added via squared scaling \n"
+ " " + HeightFogMixMode.BASIC + ": No special height fog effect. Fog is calculated based on camera distance \n"
+ " " + HeightFogMixMode.IGNORE_HEIGHT + ": Ignore height completely. Fog is calculated based on horizontal distance \n"
+ " " + HeightFogMixMode.ADDITION + ": heightFog + farFog \n"
+ " " + HeightFogMixMode.MAX + ": max(heightFog, farFog) \n"
+ " " + HeightFogMixMode.MULTIPLY + ": heightFog * farFog \n"
+ " " + HeightFogMixMode.INVERSE_MULTIPLY + ": 1 - (1-heightFog) * (1-farFog) \n"
+ " " + HeightFogMixMode.LIMITED_ADDITION + ": farFog + max(farFog, heightFog) \n"
+ " " + HeightFogMixMode.MULTIPLY_ADDITION + ": farFog + farFog * heightFog \n"
+ " " + HeightFogMixMode.INVERSE_MULTIPLY_ADDITION + ": farFog + 1 - (1-heightFog) * (1-farFog) \n"
+ " " + HeightFogMixMode.AVERAGE + ": farFog*0.5 + heightFog*0.5 \n"
+ "\n"
+ " Note that for 'BASIC' mode and 'IGNORE_HEIGHT' mode, fog settings for height fog has no effect.\n";
HeightFogMixMode getHeightFogMixMode();
void setHeightFogMixMode(HeightFogMixMode newHeightFogMixMode);
HeightFogMode HEIGHT_FOG_MODE_DEFAULT = HeightFogMode.ABOVE_AND_BELOW_CAMERA;
String HEIGHT_FOG_MODE_DESC = ""
+ " Where should the height fog be located? \n"
+ "\n"
+ " " + HeightFogMode.ABOVE_CAMERA + ": Height fog starts from camera to the sky \n"
+ " " + HeightFogMode.BELOW_CAMERA + ": Height fog starts from camera to the void \n"
+ " " + HeightFogMode.ABOVE_AND_BELOW_CAMERA + ": Height fog starts from camera to both the sky and the void \n"
+ " " + HeightFogMode.ABOVE_SET_HEIGHT + ": Height fog starts from a set height to the sky \n"
+ " " + HeightFogMode.BELOW_SET_HEIGHT + ": Height fog starts from a set height to the void \n"
+ " " + HeightFogMode.ABOVE_AND_BELOW_SET_HEIGHT + ": Height fog starts from a set height to both the sky and the void \n"
+ "\n";
HeightFogMode getHeightFogMode();
void setHeightFogType(HeightFogMode newHeightFogMode);
void setHeightFogMode(HeightFogMode newHeightFogMode);
MinDefaultMax<Double> HEIGHT_FOG_HEIGHT_MIN_DEFAULT_MAX = new MinDefaultMax<>(-4096., 70., 4096.);
String HEIGHT_FOG_HEIGHT_DESC = ""
+ " If the height fog is calculated around a set height, what is that height position? \n"
+ "\n";
double getHeightFogHeight();
void setHeightFogHeight(double newHeightFogHeight);
MinDefaultMax<Double> HEIGHT_FOG_START_MIN_DEFAULT_MAX = new MinDefaultMax<>(FOG_RANGE.minValue, 0.0, FOG_RANGE.maxValue);
String HEIGHT_FOG_START_DESC = ""
+ " Where should the far fog start? \n"
+ " How far the start of height fog should offset? \n"
+ "\n"
+ " '0.0': Fog start at player's position.\n"
+ " '1.0': The fog-start's circle fit just in the lod render distance square.\n"
+ " '1.414': The lod render distance square fit just in the fog-start's circle.\n";
+ " '0.0': Fog start with no offset.\n"
+ " '1.0': Fog start with offset of the entire world's height. (Include depth)\n";
double getHeightFogStart();
void setHeightFogStart(double newHeightFogStart);
MinDefaultMax<Double> HEIGHT_FOG_END_MIN_DEFAULT_MAX = new MinDefaultMax<>(FOG_RANGE.minValue, 1.0, FOG_RANGE.maxValue);
String HEIGHT_FOG_END_DESC = ""
+ " Where should the far fog end? \n"
+ " How far the end of height fog should offset? \n"
+ "\n"
+ " '0.0': Fog end at player's position.\n"
+ " '1.0': The fog-end's circle fit just in the lod render distance square.\n"
+ " '1.414': The lod render distance square fit just in the fog-end's circle.\n";
+ " '0.0': Fog end with no offset.\n"
+ " '1.0': Fog end with offset of the entire world's height. (Include depth)\n";
double getHeightFogEnd();
void setHeightFogEnd(double newHeightFogEnd);
@@ -345,16 +369,16 @@ public interface ILodConfigWrapperSingleton extends IBindable
double getHeightFogMax();
void setHeightFogMax(double newHeightFogMax);
FogSetting.Type HEIGHT_FOG_TYPE_DEFAULT = FogSetting.Type.EXPONENTIAL_SQUARED;
FogSetting.FogType HEIGHT_FOG_TYPE_DEFAULT = FogSetting.FogType.EXPONENTIAL_SQUARED;
String HEIGHT_FOG_TYPE_DESC = ""
+ " How the fog thickness should be calculated from height? \n"
+ "\n"
+ " " + FogSetting.Type.LINEAR + ": Linear based on height (will ignore 'density')\n"
+ " " + FogSetting.Type.EXPONENTIAL + ": 1/(e^(height*density)) \n"
+ " " + FogSetting.Type.EXPONENTIAL_SQUARED + ": 1/(e^((height*density)^2) \n";
+ " " + FogSetting.FogType.LINEAR + ": Linear based on height (will ignore 'density')\n"
+ " " + FogSetting.FogType.EXPONENTIAL + ": 1/(e^(height*density)) \n"
+ " " + FogSetting.FogType.EXPONENTIAL_SQUARED + ": 1/(e^((height*density)^2) \n";
//+ " "+ FogSetting.Type.TEXTURE_BASED + ": Use a provided 1D texture mapping (will ignore 'density', 'min', and 'max')\n";
FogSetting.Type getHeightFogType();
void setHeightFogType(FogSetting.Type newFarFogType);
FogSetting.FogType getHeightFogType();
void setHeightFogType(FogSetting.FogType newFarFogType);
MinDefaultMax<Double> HEIGHT_FOG_DENSITY_MIN_DEFAULT_MAX = new MinDefaultMax<>(0.01, 2.5, 50.0);
String HEIGHT_FOG_DENSITY_DESC = ""
@@ -59,6 +59,74 @@
"Disable vanilla fog",
"DistantHorizons.config.client.graphics.fogQuality.disableVanillaFog.@tooltip":
"§6True:§r disables Minecraft's fog on vanilla chunks.\n§6False:§r Minecraft renders fog like normal.\n\nMay cause issues with other mods that edit fog.\nDisable if vanilla chunks are completely covered in fog.",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog":
"Advanced Fog Options",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.farFogStart":
"Far Fog Start",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.farFogEnd":
"Far Fog End",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.farFogMin":
"Far Fog Min",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.farFogMax":
"Far Fog Max",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.farFogType":
"Far Fog Type",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.farFogDensity":
"Far Fog Density",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.heightFog":
"Height Fog Options",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.heightFog.heightFogMixMode":
"Height Fog Mix Mode",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.heightFog.heightFogMode":
"Height Fog Mode",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.heightFog.heightFogHeight":
"Height Fog Set Height",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.heightFog.heightFogStart":
"Height Fog Start",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.heightFog.heightFogEnd":
"Height Fog End",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.heightFog.heightFogMin":
"Height Fog Min",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.heightFog.heightFogMax":
"Height Fog Max",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.heightFog.heightFogType":
"Height Fog Type",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.heightFog.heightFogDensity":
"Height Fog Density",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.farFogStart.@tooltip":
"Where should the far fog start? \n\n '0.0': Fog start at player's position.\n '1.0': The fog-start's circle fit just in the lod render distance square.\n'1.414': The lod render distance square fit just in the fog-start's circle.\n",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.farFogEnd.@tooltip":
"Where should the far fog end? \n\n '0.0': Fog end at player's position.\n '1.0': The fog-end's circle fit just in the lod render distance square.\n'1.414': The lod render distance square fit just in the fog-end's circle.\n",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.farFogMin.@tooltip":
"What is the minimum fog thickness? \n\n '0.0': No fog at all.\n '1.0': Fully fog color.\n",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.farFogMax.@tooltip":
"What is the maximum fog thickness? \n\n '0.0': No fog at all.\n '1.0': Fully fog color.\n",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.farFogType.@tooltip":
"How the fog thickness should be calculated from distance?\n\nLINEAR: Linear based on distance (will ignore 'density')\nEXPONENTIAL: 1/(e^(distance*density)) \nEXPONENTIAL_SQUARED: 1/(e^((distance*density)^2) \n",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.farFogDensity.@tooltip":
"What is the fog density? ",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.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.graphics.fogQuality.advancedFog.heightFog.heightFogMode.@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.graphics.fogQuality.advancedFog.heightFog.heightFogHeight.@tooltip":
"If the height fog is calculated around a set height, what is that height position? ",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.heightFog.heightFogStart.@tooltip":
"How far the start of height fog should offset? \n\n '0.0': Fog start with no offset.\n '1.0': Fog start with offset of the entire world's height. (Include depth)\n",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.heightFog.heightFogEnd.@tooltip":
"How far the end of height fog should offset? \n\n '0.0': Fog end with no offset.\n '1.0': Fog end with offset of the entire world's height. (Include depth)\n",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.heightFog.heightFogMin.@tooltip":
"What is the minimum fog thickness? \n\n '0.0': No fog at all.\n '1.0': Fully fog color.\n",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.heightFog.heightFogMax.@tooltip":
"What is the maximum fog thickness? \n\n '0.0': No fog at all.\n '1.0': Fully fog color.\n",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.heightFog.heightFogType.@tooltip":
"How the fog thickness should be calculated from height? \n\nLINEAR: Linear based on height (will ignore 'density')\nEXPONENTIAL: 1/(e^(height*density)) \nEXPONENTIAL_SQUARED: 1/(e^((height*density)^2) \n",
"DistantHorizons.config.client.graphics.fogQuality.advancedFog.heightFog.heightFogDensity.@tooltip":
"What is the fog density? ",
"DistantHorizons.config.client.graphics.advancedGraphics":
"Advanced quality option",
"DistantHorizons.config.client.graphics.advancedGraphics.lodTemplate":
@@ -205,6 +273,44 @@
"Use world fog",
"DistantHorizons.config.enum.FogColorMode.USE_SKY_COLOR":
"Use sky color",
"DistantHorizons.config.enum.FogType.LINEAR":
"Linear",
"DistantHorizons.config.enum.FogType.EXPONENTIAL":
"Exponential",
"DistantHorizons.config.enum.FogType.EXPONENTIAL_SQUARED":
"Exponential Squared",
"DistantHorizons.config.enum.HeightFogMode.ABOVE_CAMERA":
"Above Camera",
"DistantHorizons.config.enum.HeightFogMode.BELOW_CAMERA":
"Below Camera",
"DistantHorizons.config.enum.HeightFogMode.ABOVE_AND_BELOW_CAMERA":
"Above And Below Camera",
"DistantHorizons.config.enum.HeightFogMode.ABOVE_SET_HEIGHT":
"Above Set Height",
"DistantHorizons.config.enum.HeightFogMode.BELOW_SET_HEIGHT":
"Below Set Height",
"DistantHorizons.config.enum.HeightFogMode.ABOVE_AND_BELOW_SET_HEIGHT":
"Above And Below Set Height",
"DistantHorizons.config.enum.HeightFogMixMode.BASIC":
"Basic",
"DistantHorizons.config.enum.HeightFogMixMode.IGNORE_HEIGHT":
"Ignore Height",
"DistantHorizons.config.enum.HeightFogMixMode.ADDITION":
"Addition",
"DistantHorizons.config.enum.HeightFogMixMode.MAX":
"Max",
"DistantHorizons.config.enum.HeightFogMixMode.MULTIPLY":
"Multiply",
"DistantHorizons.config.enum.HeightFogMixMode.INVERSE_MULTIPLY":
"Inverse Multiply",
"DistantHorizons.config.enum.HeightFogMixMode.LIMITED_ADDITION":
"Limited Addition",
"DistantHorizons.config.enum.HeightFogMixMode.MULTIPLY_ADDITION":
"Multiply Addition",
"DistantHorizons.config.enum.HeightFogMixMode.INVERSE_MULTIPLY_ADDITION":
"Inverse Multiply Addition",
"DistantHorizons.config.enum.HeightFogMixMode.AVERAGE":
"Average",
"DistantHorizons.config.enum.LodTemplate.CUBIC":
"Cubic",
"DistantHorizons.config.enum.LodTemplate.TRIANGULAR":
+64 -56
View File
@@ -1,25 +1,42 @@
#version 150 core
in vec4 vertexColor;
in vec3 vertexWorldPos;
in float vertexYPos;
out vec4 fragColor;
uniform bool fogEnabled;
uniform bool nearFogEnabled;
uniform bool farFogEnabled;
uniform float fogScale;
uniform float fogVerticalScale;
uniform float nearFogStart;
uniform float nearFogEnd;
uniform float farFogStart;
uniform float farFogEnd;
uniform float nearFogLength;
uniform int fullFogMode;
/* ========MARCO DEFINED BY RUNTIME CODE GEN=========
float farFogStart;
float farFogLength;
float farFogMin;
float farFogRange;
float farFogDensity;
float heightFogStart;
float heightFogLength;
float heightFogMin;
float heightFogRange;
float heightFogDensity;
*/
uniform vec4 fogColor;
// method definitions
float getFogAlpha(float start, float end, float dist);
// ==== 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 calculateHeightFogDepth(float vertical, float realY);
float mixFogThickness(float near, float far, float height);
// =========================================================
/**
* Fragment Shader
@@ -29,55 +46,46 @@ float getFogAlpha(float start, float end, float dist);
*/
void main()
{
// TODO: add a white texture to support Optifine shaders
//vec4 textureColor = texture(texImage, textureCoord);
//fragColor = vertexColor * textureColor;
vec4 returnColor;
if (fogEnabled)
{
// add fog
// no fog by default
float fogAlpha = 0;
float dist = length(vertexWorldPos);
if (fullFogMode != 0) {
returnColor = vec4(fogColor.rgb, 1.0);
} else {
// TODO: add a white texture to support Optifine shaders
//vec4 textureColor = texture(texImage, textureCoord);
//fragColor = vertexColor * textureColor;
float horizontalDist = length(vertexWorldPos.xz) * fogScale;
float heightDist = calculateHeightFogDepth(
vertexWorldPos.y, vertexYPos) * fogVerticalScale;
float farDist = calculateFarFogDepth(horizontalDist,
length(vertexWorldPos.xyz) * fogScale);
float nearFogThickness = getNearFogThickness(horizontalDist);
float farFogThickness = getFarFogThickness(farDist);
float heightFogThickness = getHeightFogThickness(heightDist);
float mixedFogThickness = clamp(mixFogThickness(
nearFogThickness, farFogThickness, heightFogThickness), 0.0, 1.0);
returnColor = mix(vertexColor, vec4(fogColor.rgb, 1.0), mixedFogThickness);
// less than because nearFogStart is farther away than nearFogEnd
if (nearFogEnabled && dist < nearFogStart)
{
fogAlpha = getFogAlpha(nearFogStart, nearFogEnd, dist);
}
else if (farFogEnabled)
{
fogAlpha = getFogAlpha(farFogStart, farFogEnd, dist);
}
returnColor = mix(vertexColor, vec4(fogColor.xyz, 1), fogAlpha);
}
else
{
// simple flat color
returnColor = vertexColor;
}
//fragColor = vec4(0.7,0.6,0.5,1.0);
//fragColor = vec4(0.7,0.6,0.5,1.0);
fragColor = vec4(returnColor.rgb,1.0);
}
/**
* Returns the fog strength for the given fragment.
* This is the same implementation as legacy OpenGL's Linear fog option.
* 1 = completely opaque fog
* 0 = no fog
*/
float getFogAlpha(float start, float end, float dist)
{
float fogAlpha = 1 - ((end - dist) / (end - start));
return clamp(fogAlpha, 0, 1);
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;
}
float exponentialFog(float x, float fogStart, float fogLength,
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) {
x = max((x-fogStart)/fogLength, 0.0) * fogDensity;
return fogMin + fogRange - fogRange/exp(x*x);
}
+8 -13
View File
@@ -5,9 +5,11 @@ in vec4 color;
out vec4 vertexColor;
out vec3 vertexWorldPos;
out float vertexYPos;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform mat4 combinedMatrix;
uniform vec3 modelOffset;
uniform float worldYOffset;
uniform int worldSkyLight;
uniform sampler2D lightMap;
@@ -24,18 +26,11 @@ uniform sampler2D lightMap;
*/
void main()
{
vec4 worldSpacePos = modelViewMatrix * vec4(vPosition.xyz,1);
vertexWorldPos = vPosition.xyz + modelOffset;
vertexYPos = vPosition.y + worldYOffset;
float light = (vPosition.a+0.5) / 256.0;
vertexColor = color * texture(lightMap, vec2(light,0.5));
vertexWorldPos = worldSpacePos.xyz;
// vec4 pos = projectionMatrix * worldSpacePos;
gl_Position = projectionMatrix * worldSpacePos;
/*pos.a = 1.0;
if (pos.x>0) pos.x=-1; else pos.x=1;
if (pos.y>0) pos.y=-1; else pos.y=1;
pos.z = 0.5;
gl_Position = pos;*/
gl_Position = combinedMatrix * vec4(vertexWorldPos, 1.0);
}