Merge branch 'main' of https://gitlab.com/jeseibel/distant-horizons-core
This commit is contained in:
@@ -19,16 +19,12 @@
|
||||
|
||||
package com.seibel.lod.core.builders.bufferBuilding;
|
||||
|
||||
import java.awt.Color;
|
||||
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.objects.opengl.LodBox;
|
||||
import com.seibel.lod.core.objects.opengl.LodQuadBuilder;
|
||||
import com.seibel.lod.core.util.DataPointUtil;
|
||||
import com.seibel.lod.core.util.LevelPosUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
|
||||
/**
|
||||
* Builds LODs as rectangular prisms.
|
||||
@@ -36,14 +32,10 @@ import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
* @author James Seibel
|
||||
* @version 12-8-2021
|
||||
*/
|
||||
public class CubicLodTemplate
|
||||
{
|
||||
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
|
||||
|
||||
|
||||
public class CubicLodTemplate {
|
||||
|
||||
public static void addLodToBuffer(long data, long topData, long botData, long[][][] adjData, byte detailLevel,
|
||||
int offsetPosX, int offsetOosZ, LodQuadBuilder quadBuilder, DebugMode debugging)
|
||||
{
|
||||
int offsetPosX, int offsetOosZ, LodQuadBuilder quadBuilder, DebugMode debugging) {
|
||||
short width = (short) (1 << detailLevel);
|
||||
short x = (short) LevelPosUtil.convert(detailLevel, offsetPosX, LodUtil.BLOCK_DETAIL_LEVEL);
|
||||
short y = DataPointUtil.getDepth(data);
|
||||
@@ -51,28 +43,17 @@ public class CubicLodTemplate
|
||||
short dy = (short) (DataPointUtil.getHeight(data) - y);
|
||||
if (dy == 0)
|
||||
return;
|
||||
|
||||
|
||||
int color;
|
||||
if (debugging != DebugMode.OFF && debugging != DebugMode.SHOW_WIREFRAME)
|
||||
{
|
||||
if (debugging != DebugMode.OFF && debugging != DebugMode.SHOW_WIREFRAME) {
|
||||
if (debugging == DebugMode.SHOW_DETAIL || debugging == DebugMode.SHOW_DETAIL_WIREFRAME)
|
||||
color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[detailLevel].getRGB();
|
||||
else /// if (debugging == DebugMode.SHOW_GENMODE || debugging ==
|
||||
/// DebugMode.SHOW_GENMODE_WIREFRAME)
|
||||
color = LodUtil.DEBUG_DETAIL_LEVEL_COLORS[DataPointUtil.getGenerationMode(data)].getRGB();
|
||||
}
|
||||
else
|
||||
{
|
||||
double saturationMultiplier = CONFIG.client().graphics().advancedGraphics().getSaturationMultiplier();
|
||||
double brightnessMultiplier = CONFIG.client().graphics().advancedGraphics().getBrightnessMultiplier();
|
||||
|
||||
Color colorObject = LodUtil.intToColor(DataPointUtil.getColor(data));
|
||||
|
||||
float[] hsb = Color.RGBtoHSB(colorObject.getRed(), colorObject.getGreen(), colorObject.getBlue(), null);
|
||||
color = LodUtil.colorToInt(Color.getHSBColor(hsb[0], (float) LodUtil.clamp(0.0f, hsb[1] * saturationMultiplier, 1.0f), (float) LodUtil.clamp(0.0f, hsb[2] * brightnessMultiplier, 1.0f)));
|
||||
|
||||
}
|
||||
|
||||
} else
|
||||
color = DataPointUtil.getColor(data);
|
||||
|
||||
LodBox.addBoxQuadsToBuilder(quadBuilder, // buffer
|
||||
width, dy, width, // setWidth
|
||||
x, y, z, // setOffset
|
||||
|
||||
+2
-4
@@ -273,15 +273,13 @@ public class LodBufferBuilderFactory {
|
||||
ApiShared.LOGGER.error("LodBufferBuilder timed out: ", te);
|
||||
resetThreadPools(true);
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
} catch (Exception e) {
|
||||
ApiShared.LOGGER.error("\"LodNodeBufferBuilder.generateLodBuffersAsync\" ran into trouble: ", e);
|
||||
} finally {
|
||||
if (ENABLE_EVENT_LOGGING) ApiShared.LOGGER.info("BufferBuilderStarter unlocked the region lock!");
|
||||
regionsListLock.unlock();
|
||||
}
|
||||
} catch (InterruptedException ie) {
|
||||
} finally {
|
||||
regionsListLock.unlock();
|
||||
if (ENABLE_EVENT_LOGGING) ApiShared.LOGGER.info("BufferBuilderStarter unlocked the region lock!");
|
||||
builderThreadRunning = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -364,11 +364,7 @@ public class LodBuilder
|
||||
|
||||
private boolean hasCliffFace(IChunkWrapper chunk, int x, int y, int z) {
|
||||
for (LodDirection dir : DIRECTIONS) {
|
||||
int cx = x+dir.getNormal().x;
|
||||
int cy = y+dir.getNormal().y;
|
||||
int cz = z+dir.getNormal().z;
|
||||
if (!chunk.blockPosInsideChunk(cx, cy, cz)) return true;
|
||||
IBlockDetailWrapper block = chunk.getBlockDetail(cx, cy, cz);
|
||||
IBlockDetailWrapper block = chunk.getBlockDetailAtFace(x, y, z, dir);
|
||||
if (block == null || !block.hasFaceCullingFor(LodDirection.OPPOSITE_DIRECTIONS[dir.ordinal()]))
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -0,0 +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 FogType fogType;
|
||||
|
||||
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.fogType = fogType;
|
||||
}
|
||||
|
||||
@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,
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
package com.seibel.lod.core.enums.rendering;
|
||||
|
||||
public enum HeightFogMode {
|
||||
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;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ public class LodQuadBuilder {
|
||||
static final int MAX_QUADS_PER_BUFFER = MAX_BUFFER_SIZE / QUAD_BYTE_SIZE;
|
||||
//static final int MAX_MERGED_QUAD_SIZE = 64;
|
||||
|
||||
public boolean skipSkylight0Quads = true;
|
||||
|
||||
static class Quad {
|
||||
final short x;
|
||||
final short y;
|
||||
@@ -232,33 +234,40 @@ public class LodQuadBuilder {
|
||||
byte blocklight) {
|
||||
if (dir.ordinal() <= LodDirection.DOWN.ordinal())
|
||||
throw new IllegalArgumentException("addQuadAdj() is only for adj direction! Not UP or Down!");
|
||||
if (skipSkylight0Quads && skylight==0) return;
|
||||
quads[dir.ordinal()].add(new Quad(x, y, z, w0, wy, color, skylight, blocklight, dir));
|
||||
}
|
||||
|
||||
// XZ
|
||||
public void addQuadUp(short x, short y, short z, short wx, short wz, int color, byte skylight, byte blocklight) {
|
||||
if (skipSkylight0Quads && skylight==0) return;
|
||||
quads[LodDirection.UP.ordinal()].add(new Quad(x, y, z, wx, wz, color, skylight, blocklight, LodDirection.UP));
|
||||
}
|
||||
|
||||
public void addQuadDown(short x, short y, short z, short wx, short wz, int color, byte skylight, byte blocklight) {
|
||||
if (skipSkylight0Quads && skylight==0) return;
|
||||
quads[LodDirection.DOWN.ordinal()].add(new Quad(x, y, z, wx, wz, color, skylight, blocklight, LodDirection.DOWN));
|
||||
}
|
||||
|
||||
// XY
|
||||
public void addQuadN(short x, short y, short z, short wx, short wy, int color, byte skylight, byte blocklight) {
|
||||
if (skipSkylight0Quads && skylight==0) return;
|
||||
quads[LodDirection.NORTH.ordinal()].add(new Quad(x, y, z, wx, wy, color, skylight, blocklight, LodDirection.NORTH));
|
||||
}
|
||||
|
||||
public void addQuadS(short x, short y, short z, short wx, short wy, int color, byte skylight, byte blocklight) {
|
||||
if (skipSkylight0Quads && skylight==0) return;
|
||||
quads[LodDirection.SOUTH.ordinal()].add(new Quad(x, y, z, wx, wy, color, skylight, blocklight, LodDirection.SOUTH));
|
||||
}
|
||||
|
||||
// ZY
|
||||
public void addQuadW(short x, short y, short z, short wz, short wy, int color, byte skylight, byte blocklight) {
|
||||
if (skipSkylight0Quads && skylight==0) return;
|
||||
quads[LodDirection.WEST.ordinal()].add(new Quad(x, y, z, wz, wy, color, skylight, blocklight, LodDirection.WEST));
|
||||
}
|
||||
|
||||
public void addQuadE(short x, short y, short z, short wz, short wy, int color, byte skylight, byte blocklight) {
|
||||
if (skipSkylight0Quads && skylight==0) return;
|
||||
quads[LodDirection.EAST.ordinal()].add(new Quad(x, y, z, wz, wy, color, skylight, blocklight, LodDirection.EAST));
|
||||
}
|
||||
|
||||
|
||||
@@ -199,4 +199,10 @@ public class LodVertexBuffer implements AutoCloseable
|
||||
GL32.glUnmapBuffer(GL32.GL_ARRAY_BUFFER);
|
||||
isMapped = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return (isBufferStorage ? "VertexBufferStorage" : "BufferStorage")+
|
||||
"[vboId:"+id+", size:"+size+", vertCount:"+vertexCount+(isMapped?", MAPPED" : "")+"]";
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
@@ -4,6 +4,8 @@ import java.nio.ByteBuffer;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.seibel.lod.core.render.LodRenderer;
|
||||
import com.seibel.lod.core.util.SpamReducedLogger;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
@@ -47,18 +49,21 @@ public class SimpleRenderBuffer extends RenderBuffer
|
||||
|
||||
// public void onSwapToFront() {}
|
||||
// public void onSwapToBack() {}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean render(LodRenderProgram shaderProgram)
|
||||
{
|
||||
boolean hasRendered = false;
|
||||
for (LodVertexBuffer vbo : vbos) {
|
||||
if (vbo == null) continue;
|
||||
if (vbo.vertexCount == 0) continue;
|
||||
hasRendered = true;
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, vbo.id);
|
||||
shaderProgram.bindVertexBuffer(vbo.id);
|
||||
GL32.glDrawArrays(GL32.GL_TRIANGLES, 0, vbo.vertexCount);
|
||||
//LodRenderer.tickLogger.info("Vertex buffer: {}", vbo);
|
||||
}
|
||||
return true;
|
||||
return hasRendered;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -62,12 +62,7 @@ import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
*/
|
||||
public class GLProxy
|
||||
{
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
public static final boolean OVERWIDE_VANILLA_GL_LOGGER = true;
|
||||
|
||||
private static final IMinecraftClientWrapper MC = SingletonHandler.get(IMinecraftClientWrapper.class);
|
||||
|
||||
@@ -106,7 +101,8 @@ public class GLProxy
|
||||
public final boolean mapBufferRangeSupported = true;
|
||||
|
||||
private final GpuUploadMethod preferredUploadMethod;
|
||||
|
||||
|
||||
public final GLMessage.Builder vanillaDebugMessageBuilder;
|
||||
public final GLMessage.Builder lodBuilderDebugMessageBuilder;
|
||||
public final GLMessage.Builder proxyWorkerDebugMessageBuilder;
|
||||
|
||||
@@ -216,7 +212,19 @@ public class GLProxy
|
||||
return true;
|
||||
},null
|
||||
);
|
||||
|
||||
vanillaDebugMessageBuilder = new GLMessage.Builder(
|
||||
(type) -> {
|
||||
if (type == GLMessage.Type.POP_GROUP) return false;
|
||||
if (type == GLMessage.Type.PUSH_GROUP) return false;
|
||||
if (type == GLMessage.Type.MARKER) return false;
|
||||
// if (type == GLMessage.Type.PERFORMANCE) return false;
|
||||
return true;
|
||||
}
|
||||
,(severity) -> {
|
||||
if (severity == GLMessage.Severity.NOTIFICATION) return false;
|
||||
return true;
|
||||
},null
|
||||
);
|
||||
|
||||
|
||||
// this must be created on minecraft's render context to work correctly
|
||||
@@ -251,7 +259,12 @@ public class GLProxy
|
||||
MC.crashMinecraft(errorMessage, new UnsupportedOperationException("This GPU doesn't support OpenGL 3.2."));
|
||||
}
|
||||
ApiShared.LOGGER.info("minecraftGlCapabilities:\n"+getVersionInfo(minecraftGlCapabilities));
|
||||
|
||||
|
||||
if (OVERWIDE_VANILLA_GL_LOGGER)
|
||||
GLUtil.setupDebugMessageCallback(new PrintStream(new GLMessageOutputStream((msg) -> {
|
||||
logMessage(msg);
|
||||
}, vanillaDebugMessageBuilder), true));
|
||||
|
||||
GLFW.glfwMakeContextCurrent(0L);
|
||||
|
||||
// context creation setup
|
||||
@@ -267,6 +280,7 @@ public class GLProxy
|
||||
GLFW.glfwWindowHint(GLFW.GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_FORWARD_COMPAT, GLFW.GLFW_TRUE);
|
||||
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_PROFILE, GLFW.GLFW_OPENGL_CORE_PROFILE);
|
||||
GLFW.glfwWindowHint(GLFW.GLFW_OPENGL_DEBUG_CONTEXT, GLFW.GLFW_TRUE);
|
||||
|
||||
// create the LodBuilder context
|
||||
lodBuilderGlContext = GLFW.glfwCreateWindow(64, 48, "LOD Builder Window", 0L, minecraftGlContext);
|
||||
@@ -362,8 +376,7 @@ public class GLProxy
|
||||
// we don't have to change the context, we are already there.
|
||||
if (currentContext == newContext)
|
||||
return;
|
||||
|
||||
|
||||
|
||||
long contextPointer;
|
||||
GLCapabilities newGlCapabilities = null;
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import java.time.Duration;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.seibel.lod.core.util.*;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
@@ -39,10 +40,6 @@ import com.seibel.lod.core.objects.math.Vec3d;
|
||||
import com.seibel.lod.core.objects.math.Vec3f;
|
||||
import com.seibel.lod.core.objects.opengl.RenderRegion;
|
||||
import com.seibel.lod.core.render.objects.LightmapTexture;
|
||||
import com.seibel.lod.core.util.DetailDistanceUtil;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.util.MovableGridRingList;
|
||||
import com.seibel.lod.core.util.MovableGridList;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
|
||||
@@ -80,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;
|
||||
/**
|
||||
@@ -136,13 +132,30 @@ public class LodRenderer
|
||||
{
|
||||
lodBufferBuilderFactory = newLodNodeBufferBuilder;
|
||||
}
|
||||
|
||||
public static SpamReducedLogger tickLogger = new SpamReducedLogger(1);
|
||||
|
||||
public static void dumpGLState(String str) {
|
||||
int currentProgram = GL32.glGetInteger(GL32.GL_CURRENT_PROGRAM);
|
||||
int currentVBO = GL32.glGetInteger(GL32.GL_ARRAY_BUFFER_BINDING);
|
||||
int currentVAO = GL32.glGetInteger(GL32.GL_VERTEX_ARRAY_BINDING);
|
||||
int currentActiveText = GL32.glGetInteger(GL32.GL_ACTIVE_TEXTURE);
|
||||
int currentFrameBuffer = GL32.glGetInteger(GL32.GL_FRAMEBUFFER_BINDING);
|
||||
boolean currentBlend = GL32.glGetBoolean(GL32.GL_BLEND);
|
||||
int currentDepthFunc = GL32.glGetInteger(GL32.GL_DEPTH_FUNC);
|
||||
int[] currentView = new int[4];
|
||||
GL32.glGetIntegerv(GL32.GL_VIEWPORT, currentView);
|
||||
tickLogger.info(str + ": [Prog:{}, VAO:{}, VBO:{}, Text:{}, FBO:{}, blend:{}, dpFunc:{}, view:{}]",
|
||||
currentProgram, currentVAO, currentVBO, currentActiveText, currentFrameBuffer,
|
||||
currentBlend, currentDepthFunc, currentView);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Besides drawing the LODs this method also starts
|
||||
* the async process of generating the Buffers that hold those LODs.
|
||||
* @param lodDim The dimension to draw, if null doesn't replace the current dimension.
|
||||
* @param mcModelViewMatrix This matrix stack should come straight from MC's renderChunkLayer (or future equivalent) method
|
||||
* @param mcProjectionMatrix
|
||||
* @param baseModelViewMatrix This matrix stack should come straight from MC's renderChunkLayer (or future equivalent) method
|
||||
* @param baseProjectionMatrix
|
||||
* @param partialTicks how far into the current tick this method was called.
|
||||
*/
|
||||
public void drawLODs(LodDimension lodDim, Mat4f baseModelViewMatrix, Mat4f baseProjectionMatrix, float partialTicks, IProfilerWrapper profiler)
|
||||
@@ -173,9 +186,15 @@ public class LodRenderer
|
||||
int currentVBO = GL32.glGetInteger(GL32.GL_ARRAY_BUFFER_BINDING);
|
||||
int currentVAO = GL32.glGetInteger(GL32.GL_VERTEX_ARRAY_BINDING);
|
||||
int currentActiveText = GL32.glGetInteger(GL32.GL_ACTIVE_TEXTURE);
|
||||
int currentFrameBuffer = GL32.glGetInteger(GL32.GL_FRAMEBUFFER_BINDING);
|
||||
boolean currentBlend = GL32.glGetBoolean(GL32.GL_BLEND);
|
||||
int currentDepthFunc = GL32.glGetInteger(GL32.GL_DEPTH_FUNC);
|
||||
int[] currentView = new int[4];
|
||||
GL32.glGetIntegerv(GL32.GL_VIEWPORT, currentView);
|
||||
dumpGLState("PRE_LOD-DRAW");
|
||||
|
||||
drawSaveGLState.end("drawSaveGLState");
|
||||
|
||||
|
||||
GLProxy glProxy = GLProxy.getInstance();
|
||||
if (canVanillaFogBeDisabled && CONFIG.client().graphics().fogQuality().getDisableVanillaFog())
|
||||
if (!MC_RENDER.tryDisableVanillaFog())
|
||||
@@ -231,11 +250,12 @@ 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();
|
||||
LagSpikeCatcher drawBindBuff = new LagSpikeCatcher();
|
||||
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer());
|
||||
GL32.glViewport(0,0, MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight());
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, 0);
|
||||
drawBindBuff.end("drawBindBuff");
|
||||
// set the required open GL settings
|
||||
@@ -253,13 +273,16 @@ public class LodRenderer
|
||||
drawSetPolygon.end("drawSetPolygon");
|
||||
LagSpikeCatcher drawEnableDepth = new LagSpikeCatcher();
|
||||
GL32.glEnable(GL32.GL_DEPTH_TEST);
|
||||
//GL32.glDisable(GL32.GL_DEPTH_TEST);
|
||||
// GL32.glDisable(GL32.GL_DEPTH_TEST);
|
||||
GL32.glDepthFunc(GL32.GL_LESS);
|
||||
drawEnableDepth.end("drawEnableDepth");
|
||||
drawGLSetup.end("drawGLSetup");
|
||||
// enable transparent rendering
|
||||
// GL32.glBlendFunc(GL32.GL_SRC_ALPHA, GL32.GL_ONE_MINUS_SRC_ALPHA);
|
||||
// GL32.glEnable(GL32.GL_BLEND);
|
||||
|
||||
GL32.glDisable(GL32.GL_BLEND);
|
||||
GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT);
|
||||
|
||||
/*---------Bind required objects--------*/
|
||||
// Setup LodRenderProgram and the LightmapTexture if it has not yet been done
|
||||
// also binds LightmapTexture, VAO, and ShaderProgram
|
||||
@@ -269,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");
|
||||
}
|
||||
@@ -287,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());
|
||||
@@ -315,6 +343,7 @@ public class LodRenderer
|
||||
Vec3d cameraPos = MC_RENDER.getCameraExactPosition();
|
||||
AbstractBlockPosWrapper cameraBlockPos = MC_RENDER.getCameraBlockPosition();
|
||||
Vec3f cameraDir = MC_RENDER.getLookAtVector();
|
||||
int drawCount = 0;
|
||||
|
||||
{
|
||||
int ox,oy,dx,dy;
|
||||
@@ -331,8 +360,8 @@ public class LodRenderer
|
||||
{
|
||||
RenderRegion region = regions.get(regionX, regionZ);
|
||||
if (region == null) continue;
|
||||
region.render(lodDim, cameraPos, cameraBlockPos, cameraDir,
|
||||
baseModelViewMatrix, !cullingDisabled, shaderProgram);
|
||||
if (region.render(lodDim, cameraPos, cameraBlockPos, cameraDir,
|
||||
!cullingDisabled, shaderProgram)) drawCount++;
|
||||
}
|
||||
}
|
||||
if( (ox == oy) || ((ox < 0) && (ox == -oy)) || ((ox > 0) && (ox == 1-oy))){
|
||||
@@ -344,8 +373,9 @@ public class LodRenderer
|
||||
oy += dy;
|
||||
}
|
||||
}
|
||||
dumpGLState("Post Lod Draw Before Cleanup");
|
||||
//if (drawCall==0)
|
||||
// ApiShared.LOGGER.info("DrawCall Count: "+drawCall+"("+vCount0+")");
|
||||
tickLogger.info("DrawCall Count: {}", drawCount);
|
||||
|
||||
//================//
|
||||
// render cleanup //
|
||||
@@ -369,8 +399,11 @@ public class LodRenderer
|
||||
// if this cleanup isn't done MC will crash
|
||||
// when trying to render its own terrain
|
||||
// And may causes mod compat issue
|
||||
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, currentFrameBuffer);
|
||||
GL32.glViewport(currentView[0], currentView[1],currentView[2],currentView[3]);
|
||||
GL32.glUseProgram(currentProgram);
|
||||
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, currentVBO);
|
||||
GL32.glDepthFunc(currentDepthFunc);
|
||||
GL32.glBindVertexArray(currentVAO);
|
||||
GL32.glActiveTexture(currentActiveText);
|
||||
|
||||
@@ -380,6 +413,7 @@ public class LodRenderer
|
||||
drawCleanup.end("LodDrawCleanup");
|
||||
// end of internal LOD profiling
|
||||
profiler.pop();
|
||||
tickLogger.incLogTries();
|
||||
}
|
||||
|
||||
//=================//
|
||||
@@ -398,7 +432,7 @@ public class LodRenderer
|
||||
}
|
||||
|
||||
isSetupComplete = true;
|
||||
shaderProgram = new LodRenderProgram();
|
||||
shaderProgram = new LodRenderProgram(LodFogConfig.generateFogConfig());
|
||||
}
|
||||
|
||||
/** Create all buffers that will be used. */
|
||||
@@ -425,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)
|
||||
{
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
package com.seibel.lod.core.util;
|
||||
|
||||
import com.seibel.lod.core.api.ApiShared;
|
||||
import org.lwjgl.system.CallbackI;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -10,6 +13,32 @@ public final class GLMessage {
|
||||
public final GLMessage.Source source;
|
||||
public final String id;
|
||||
public final String message;
|
||||
|
||||
// This is needed since gl callback will not have the correct class loader set, and causes issues.
|
||||
static void initLoadClass() {
|
||||
Builder dummy = new Builder();
|
||||
dummy.add(GLMessage.HEADER);
|
||||
dummy.add("ID");
|
||||
dummy.add(":");
|
||||
dummy.add("dummyId");
|
||||
dummy.add("Source");
|
||||
dummy.add(":");
|
||||
dummy.add(Source.API.str);
|
||||
dummy.add("Type");
|
||||
dummy.add(":");
|
||||
dummy.add(Type.OTHER.str);
|
||||
dummy.add("Severity");
|
||||
dummy.add(":");
|
||||
dummy.add(Severity.LOW.str);
|
||||
dummy.add("Message");
|
||||
dummy.add(":");
|
||||
dummy.add("dummyMessage");
|
||||
}
|
||||
|
||||
static {
|
||||
initLoadClass();
|
||||
}
|
||||
|
||||
GLMessage(GLMessage.Type t, GLMessage.Severity s, GLMessage.Source sr, String id, String ms) {
|
||||
this.type = t;
|
||||
this.source = sr;
|
||||
@@ -21,8 +50,7 @@ public final class GLMessage {
|
||||
public String toString() {
|
||||
return "[level:"+severity+", type:"+type+", source:"+source+", id:"+id+", msg:{"+message+"}]";
|
||||
}
|
||||
|
||||
|
||||
|
||||
public enum Type {
|
||||
ERROR,
|
||||
DEPRECATED_BEHAVIOR,
|
||||
@@ -34,7 +62,7 @@ public final class GLMessage {
|
||||
POP_GROUP,
|
||||
OTHER;
|
||||
public final String str;
|
||||
private Type() {
|
||||
Type() {
|
||||
str = super.toString().toUpperCase();
|
||||
}
|
||||
@Override
|
||||
@@ -93,6 +121,9 @@ public final class GLMessage {
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
static {
|
||||
initLoadClass();
|
||||
}
|
||||
GLMessage.Type type;
|
||||
GLMessage.Severity severity;
|
||||
GLMessage.Source source;
|
||||
@@ -121,10 +152,14 @@ public final class GLMessage {
|
||||
boolean b = runStage(str);
|
||||
if (b && stage >= 16) {
|
||||
stage = 0;
|
||||
return new GLMessage(type, severity, source, id, message);
|
||||
} else {
|
||||
return null;
|
||||
GLMessage msg = new GLMessage(type, severity, source, id, message);
|
||||
if (filterMessage(msg)) {
|
||||
return msg;
|
||||
}
|
||||
} else if (!b) {
|
||||
ApiShared.LOGGER.warn("Failed to parse GLMessage line '{}' at stage {}", str, stage);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setTypeFilter(Function<Type, Boolean> typeFilter) {
|
||||
@@ -136,7 +171,14 @@ public final class GLMessage {
|
||||
public void setSourceFilter(Function<Source, Boolean> sourceFilter) {
|
||||
this.sourceFilter = sourceFilter;
|
||||
}
|
||||
|
||||
|
||||
private boolean filterMessage(GLMessage msg) {
|
||||
if (sourceFilter!=null && !sourceFilter.apply(msg.source)) return false;
|
||||
if (typeFilter!=null && !typeFilter.apply(msg.type)) return false;
|
||||
if (severityFilter!=null && !severityFilter.apply(msg.severity)) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean runStage(String str) {
|
||||
switch (stage) {
|
||||
case 0:
|
||||
@@ -155,7 +197,6 @@ public final class GLMessage {
|
||||
return checkAndIncStage(str, ":");
|
||||
case 6:
|
||||
source = Source.get(str);
|
||||
if (sourceFilter!=null && !sourceFilter.apply(source)) stage = -1;
|
||||
stage++;
|
||||
return true;
|
||||
case 7:
|
||||
@@ -164,7 +205,6 @@ public final class GLMessage {
|
||||
return checkAndIncStage(str, ":");
|
||||
case 9:
|
||||
type = Type.get(str);
|
||||
if (typeFilter!=null && !typeFilter.apply(type)) stage = -1;
|
||||
stage++;
|
||||
return true;
|
||||
case 10:
|
||||
@@ -173,7 +213,6 @@ public final class GLMessage {
|
||||
return checkAndIncStage(str, ":");
|
||||
case 12:
|
||||
severity = Severity.get(str);
|
||||
if (severityFilter!=null && !severityFilter.apply(severity)) stage = -1;
|
||||
stage++;
|
||||
return true;
|
||||
case 13:
|
||||
|
||||
@@ -32,24 +32,17 @@ public class MovableGridRingList<T> extends ArrayList<T> implements List<T> {
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
moveLock.writeLock().lock();
|
||||
try {
|
||||
super.clear();
|
||||
super.ensureCapacity(size*size);
|
||||
for (int i=0; i<size*size; i++) {
|
||||
super.add(null);
|
||||
}
|
||||
} finally {
|
||||
moveLock.writeLock().unlock();
|
||||
}
|
||||
clear(null);
|
||||
}
|
||||
|
||||
public void clear(Consumer<? super T> d) {
|
||||
moveLock.writeLock().lock();
|
||||
try {
|
||||
super.forEach((t) -> {
|
||||
if (t!=null) d.accept(t);
|
||||
});
|
||||
if (d != null) {
|
||||
super.forEach((t) -> {
|
||||
if (t!=null) d.accept(t);
|
||||
});
|
||||
}
|
||||
super.clear();
|
||||
super.ensureCapacity(size*size);
|
||||
for (int i=0; i<size*size; i++) {
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
|
||||
package com.seibel.lod.core.wrapperInterfaces.chunk;
|
||||
|
||||
import com.seibel.lod.core.enums.LodDirection;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
|
||||
import com.seibel.lod.core.util.LodUtil;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.IBlockDetailWrapper;
|
||||
@@ -41,6 +42,9 @@ public interface IChunkWrapper extends IBindable
|
||||
IBiomeWrapper getBiome(int x, int y, int z);
|
||||
|
||||
IBlockDetailWrapper getBlockDetail(int x, int y, int z);
|
||||
|
||||
// Returns null if block doesn't exist. Note that this can cross chunk boundaries.
|
||||
IBlockDetailWrapper getBlockDetailAtFace(int x, int y, int z, LodDirection dir);
|
||||
|
||||
int getChunkPosX();
|
||||
int getChunkPosZ();
|
||||
|
||||
+199
-26
@@ -31,10 +31,7 @@ import com.seibel.lod.core.enums.config.LightGenerationMode;
|
||||
import com.seibel.lod.core.enums.config.ServerFolderNameMode;
|
||||
import com.seibel.lod.core.enums.config.VanillaOverdraw;
|
||||
import com.seibel.lod.core.enums.config.VerticalQuality;
|
||||
import com.seibel.lod.core.enums.rendering.DebugMode;
|
||||
import com.seibel.lod.core.enums.rendering.FogColorMode;
|
||||
import com.seibel.lod.core.enums.rendering.FogDistance;
|
||||
import com.seibel.lod.core.enums.rendering.FogDrawMode;
|
||||
import com.seibel.lod.core.enums.rendering.*;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.IBindable;
|
||||
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
|
||||
import com.seibel.lod.core.objects.MinDefaultMax;
|
||||
@@ -169,7 +166,19 @@ public interface ILodConfigWrapperSingleton extends IBindable
|
||||
DropoffQuality.SMOOTH_DROPOFF : DropoffQuality.PERFORMANCE_FOCUSED;
|
||||
return dropoffQuality;
|
||||
}
|
||||
|
||||
|
||||
MinDefaultMax<Integer> LOD_BIOME_BLENDING_MIN_DEFAULT_MAX = new MinDefaultMax<Integer>(0,1,7);
|
||||
String LOD_BIOME_BLENDING_DESC = ""
|
||||
+ " This is the same as vanilla Biome Blending settings for Lod area. \n" +
|
||||
" Note that anything other than '0' will greatly effect Lod building time \n" +
|
||||
" and increase triangle count. The cost on chunk generation speed is also \n" +
|
||||
" quite large if set too high.\n" +
|
||||
"\n" +
|
||||
" '0' equals to Vanilla Biome Blending of '1x1' or 'OFF', \n" +
|
||||
" '1' equals to Vanilla Biome Blending of '3x3', \n" +
|
||||
" '2' equals to Vanilla Biome Blending of '5x5'... \n";
|
||||
int getLodBiomeBlending();
|
||||
void setLodBiomeBlending(int newLodBiomeBlending);
|
||||
}
|
||||
|
||||
interface IFogQuality
|
||||
@@ -183,7 +192,7 @@ public interface ILodConfigWrapperSingleton extends IBindable
|
||||
+ " This setting shouldn't affect performance.";
|
||||
FogDistance getFogDistance();
|
||||
void setFogDistance(FogDistance newFogDistance);
|
||||
|
||||
|
||||
FogDrawMode FOG_DRAW_MODE_DEFAULT = FogDrawMode.FOG_ENABLED;
|
||||
String FOG_DRAW_MODE_DESC = ""
|
||||
+ " When should fog be drawn? \n"
|
||||
@@ -215,6 +224,190 @@ public interface ILodConfigWrapperSingleton extends IBindable
|
||||
+ " Experimental! Mod support is not guarantee.";
|
||||
boolean getDisableVanillaFog();
|
||||
void setDisableVanillaFog(boolean newDisableVanillaFog);
|
||||
|
||||
IAdvancedFog advancedFog();
|
||||
|
||||
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/?????? for how setting effect the curve.";
|
||||
|
||||
MinDefaultMax<Double> FOG_RANGE = new MinDefaultMax<>(0.0,1.0, Math.sqrt(2.0));
|
||||
|
||||
MinDefaultMax<Double> FAR_FOG_START_MIN_DEFAULT_MAX = new MinDefaultMax<>(FOG_RANGE.minValue,0.0, FOG_RANGE.maxValue);
|
||||
String FAR_FOG_START_DESC = ""
|
||||
+ " 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";
|
||||
double getFarFogStart();
|
||||
void setFarFogStart(double newFarFogStart);
|
||||
|
||||
MinDefaultMax<Double> FAR_FOG_END_MIN_DEFAULT_MAX = new MinDefaultMax<>(FOG_RANGE.minValue,1.0, FOG_RANGE.maxValue);
|
||||
String FAR_FOG_END_DESC = ""
|
||||
+ " 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";
|
||||
double getFarFogEnd();
|
||||
void setFarFogEnd(double newFarFogEnd);
|
||||
|
||||
MinDefaultMax<Double> FAR_FOG_MIN_MIN_DEFAULT_MAX = new MinDefaultMax<>(-5.0,0.0, FOG_RANGE.maxValue);
|
||||
String FAR_FOG_MIN_DESC = ""
|
||||
+ " What is the minimum fog thickness? \n"
|
||||
+ "\n"
|
||||
+ " '0.0': No fog at all.\n"
|
||||
+ " '1.0': Fully fog color.\n";
|
||||
double getFarFogMin();
|
||||
void setFarFogMin(double newFarFogMin);
|
||||
|
||||
MinDefaultMax<Double> FAR_FOG_MAX_MIN_DEFAULT_MAX = new MinDefaultMax<>(FOG_RANGE.minValue,1.0, 5.0);
|
||||
String FAR_FOG_MAX_DESC = ""
|
||||
+ " What is the maximum fog thickness? \n"
|
||||
+ "\n"
|
||||
+ " '0.0': No fog at all.\n"
|
||||
+ " '1.0': Fully fog color.\n";
|
||||
double getFarFogMax();
|
||||
void setFarFogMax(double newFarFogMax);
|
||||
|
||||
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.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.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 = ""
|
||||
+ " What is the fog density? \n";
|
||||
double getFarFogDensity();
|
||||
void setFarFogDensity(double newFarFogDensity);
|
||||
|
||||
IHeightFog heightFog();
|
||||
interface IHeightFog {
|
||||
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.";
|
||||
|
||||
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"
|
||||
+ " " + 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 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 = ""
|
||||
+ " 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";
|
||||
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 = ""
|
||||
+ " 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";
|
||||
double getHeightFogEnd();
|
||||
void setHeightFogEnd(double newHeightFogEnd);
|
||||
|
||||
MinDefaultMax<Double> HEIGHT_FOG_MIN_MIN_DEFAULT_MAX = new MinDefaultMax<>(-5.0, 0.0, FOG_RANGE.maxValue);
|
||||
String HEIGHT_FOG_MIN_DESC = ""
|
||||
+ " What is the minimum fog thickness? \n"
|
||||
+ "\n"
|
||||
+ " '0.0': No fog at all.\n"
|
||||
+ " '1.0': Fully fog color.\n";
|
||||
double getHeightFogMin();
|
||||
void setHeightFogMin(double newHeightFogMin);
|
||||
|
||||
MinDefaultMax<Double> HEIGHT_FOG_MAX_MIN_DEFAULT_MAX = new MinDefaultMax<>(FOG_RANGE.minValue, 1.0, 5.0);
|
||||
String HEIGHT_FOG_MAX_DESC = ""
|
||||
+ " What is the maximum fog thickness? \n"
|
||||
+ "\n"
|
||||
+ " '0.0': No fog at all.\n"
|
||||
+ " '1.0': Fully fog color.\n";
|
||||
double getHeightFogMax();
|
||||
void setHeightFogMax(double newHeightFogMax);
|
||||
|
||||
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.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.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 = ""
|
||||
+ " What is the fog density? \n";
|
||||
double getHeightFogDensity();
|
||||
void setHeightFogDensity(double newHeightFogDensity);
|
||||
|
||||
default FogSetting computeHeightFogSetting() {
|
||||
return new FogSetting(
|
||||
getHeightFogStart(),
|
||||
getHeightFogEnd(),
|
||||
getHeightFogMin(),
|
||||
getHeightFogMax(),
|
||||
getHeightFogDensity(),
|
||||
getHeightFogType()
|
||||
);
|
||||
}
|
||||
}
|
||||
default FogSetting computeFarFogSetting() {
|
||||
return new FogSetting(
|
||||
getFarFogStart(),
|
||||
getFarFogEnd(),
|
||||
getFarFogMin(),
|
||||
getFarFogMax(),
|
||||
getFarFogDensity(),
|
||||
getFarFogType()
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -310,26 +503,6 @@ public interface ILodConfigWrapperSingleton extends IBindable
|
||||
+ " This setting shouldn't affect performance. \n";
|
||||
boolean getUseExtendedNearClipPlane();
|
||||
void setUseExtendedNearClipPlane(boolean newUseExtendedNearClipPlane);
|
||||
|
||||
double BRIGHTNESS_MULTIPLIER_DEFAULT = 1.0;
|
||||
String BRIGHTNESS_MULTIPLIER_DESC = ""
|
||||
+ " How bright fake chunk colors are. \n"
|
||||
+ "\n"
|
||||
+ " 0 = black \n"
|
||||
+ " 1 = normal \n"
|
||||
+ " 2 = near white \n";
|
||||
double getBrightnessMultiplier();
|
||||
void setBrightnessMultiplier(double newBrightnessMultiplier);
|
||||
|
||||
double SATURATION_MULTIPLIER_DEFAULT = 1.0;
|
||||
String SATURATION_MULTIPLIER_DESC = ""
|
||||
+ " How saturated fake chunk colors are. \n"
|
||||
+ "\n"
|
||||
+ " 0 = black and white \n"
|
||||
+ " 1 = normal \n"
|
||||
+ " 2 = very saturated \n";
|
||||
double getSaturationMultiplier();
|
||||
void setSaturationMultiplier(double newSaturationMultiplier);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+19
-5
@@ -33,6 +33,7 @@ import com.seibel.lod.core.wrapperInterfaces.IWrapperFactory;
|
||||
import com.seibel.lod.core.wrapperInterfaces.block.AbstractBlockPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.chunk.AbstractChunkPosWrapper;
|
||||
import com.seibel.lod.core.wrapperInterfaces.modAccessor.ISodiumAccessor;
|
||||
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
|
||||
|
||||
/**
|
||||
* Contains everything related to
|
||||
@@ -70,6 +71,10 @@ public interface IMinecraftRenderWrapper extends IBindable
|
||||
|
||||
int getScreenWidth();
|
||||
int getScreenHeight();
|
||||
|
||||
int getTargetFrameBuffer();
|
||||
int getTargetFrameBufferViewportWidth();
|
||||
int getTargetFrameBufferViewportHeight();
|
||||
|
||||
/**
|
||||
* This method returns the ChunkPos of all chunks that Minecraft
|
||||
@@ -82,7 +87,13 @@ public interface IMinecraftRenderWrapper extends IBindable
|
||||
ISodiumAccessor sodium = ModAccessorHandler.get(ISodiumAccessor.class);
|
||||
return sodium==null ? getMaximumRenderedChunks() : sodium.getNormalRenderedChunks();
|
||||
}
|
||||
|
||||
|
||||
private static boolean correctedCheckRadius(int dx, int dz, int radius2Mul4) {
|
||||
dx = dx*2;// + (dx < 0 ? -1 : 1);
|
||||
dz = dz*2;// + (dz < 0 ? -1 : 1);
|
||||
return (dx*dx + dz*dz <= radius2Mul4);
|
||||
}
|
||||
|
||||
/**
|
||||
* <strong>Doesn't need to be implemented.</strong> <br>
|
||||
* Returns every chunk position within the vanilla render distance.
|
||||
@@ -92,13 +103,15 @@ public interface IMinecraftRenderWrapper extends IBindable
|
||||
IMinecraftClientWrapper mcWrapper = SingletonHandler.get(IMinecraftClientWrapper.class);
|
||||
IWrapperFactory factory = SingletonHandler.get(IWrapperFactory.class);
|
||||
IVersionConstants versionConstants = SingletonHandler.get(IVersionConstants.class);
|
||||
|
||||
int chunkDist = this.getRenderDistance();
|
||||
IMinecraftClientWrapper minecraft = SingletonHandler.get(IMinecraftClientWrapper.class);
|
||||
IWorldWrapper clientWorld = minecraft.getWrappedClientWorld();
|
||||
|
||||
int chunkDist = this.getRenderDistance() + 1; // For some reason having '+1' is actually closer to real value
|
||||
|
||||
AbstractChunkPosWrapper centerChunkPos = mcWrapper.getPlayerChunkPos();
|
||||
int centerChunkX = centerChunkPos.getX();
|
||||
int centerChunkZ = centerChunkPos.getZ();
|
||||
int chunkDist2 = chunkDist*chunkDist;
|
||||
int chunkDist2Mul4 = chunkDist*chunkDist*4;
|
||||
|
||||
// add every position within render distance
|
||||
HashSet<AbstractChunkPosWrapper> renderedPos = new HashSet<AbstractChunkPosWrapper>();
|
||||
@@ -107,9 +120,10 @@ public interface IMinecraftRenderWrapper extends IBindable
|
||||
for(int deltaChunkZ = -chunkDist; deltaChunkZ <= chunkDist; deltaChunkZ++)
|
||||
{
|
||||
if (!versionConstants.isVanillaRenderedChunkSquare() &&
|
||||
deltaChunkX*deltaChunkX+deltaChunkZ*deltaChunkZ > chunkDist2) {
|
||||
!correctedCheckRadius(deltaChunkX,deltaChunkZ,chunkDist2Mul4)) {
|
||||
continue;
|
||||
}
|
||||
if (!clientWorld.hasChunkLoaded(centerChunkX + deltaChunkX, centerChunkZ + deltaChunkZ)) continue;
|
||||
renderedPos.add(factory.createChunkPos(centerChunkX + deltaChunkX, centerChunkZ + deltaChunkZ));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,5 +60,5 @@ public interface IWorldWrapper extends IBindable
|
||||
|
||||
default IChunkWrapper tryGetChunk(AbstractChunkPosWrapper pos) {return null;}
|
||||
|
||||
|
||||
boolean hasChunkLoaded(int chunkX, int chunkZ);
|
||||
}
|
||||
|
||||
@@ -37,6 +37,10 @@
|
||||
"Dropoff quality",
|
||||
"DistantHorizons.config.client.graphics.quality.dropoffQuality.@tooltip":
|
||||
"How detail dropoff is calculated.\n\nHigher settings will make the drop-off less noticeable\nbut will increase how often the geometry has to be rebuilt,\nincreasing CPU usage and the chance of stuttering.",
|
||||
"DistantHorizons.config.client.graphics.quality.lodBiomeBlending":
|
||||
"Biome Blending",
|
||||
"DistantHorizons.config.client.graphics.quality.lodBiomeBlending.@tooltip":
|
||||
"This is the same as vanilla Biome Blending settings for Lod area. \n\nNote that anything other than '0' will greatly effect Lod building time\nand increase triangle count. The cost on chunk generation speed is also \nquite large if set to too high.\n\n'0' equals to Vanilla Biome Blending of '1x1', \n'1' equals to Vanilla Biome Blending of '3x3', \n'2' equals to Vanilla Biome Blending of '5x5'... \n",
|
||||
"DistantHorizons.config.client.graphics.fogQuality":
|
||||
"Fog options",
|
||||
"DistantHorizons.config.client.graphics.fogQuality.fogDistance":
|
||||
@@ -55,8 +59,76 @@
|
||||
"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 Graphics",
|
||||
"Advanced quality option",
|
||||
"DistantHorizons.config.client.graphics.advancedGraphics.lodTemplate":
|
||||
"LOD template",
|
||||
"DistantHorizons.config.client.graphics.advancedGraphics.lodTemplate.@tooltip":
|
||||
@@ -81,14 +153,6 @@
|
||||
"Backside Culling Range",
|
||||
"DistantHorizons.config.client.graphics.advancedGraphics.backsideCullingRange.@tooltip":
|
||||
"The distance where the back side of fake chunks aren't rendered to improve performance.",
|
||||
"DistantHorizons.config.client.graphics.advancedGraphics.brightnessMultiplier":
|
||||
"Brightness Multiplier",
|
||||
"DistantHorizons.config.client.graphics.advancedGraphics.brightnessMultiplier.@tooltip":
|
||||
"How bright fake chunk colors are.\n\n0 = black \n1 = normal \n2 = near white",
|
||||
"DistantHorizons.config.client.graphics.advancedGraphics.saturationMultiplier":
|
||||
"Saturation Multiplier",
|
||||
"DistantHorizons.config.client.graphics.advancedGraphics.saturationMultiplier.@tooltip":
|
||||
"How saturated fake chunk colors are.\n\n0 = black and white \n1 = normal \n2 = vibrant",
|
||||
"DistantHorizons.config.client.worldGenerator":
|
||||
"World generator",
|
||||
"DistantHorizons.config.client.worldGenerator.generationPriority":
|
||||
@@ -126,7 +190,7 @@
|
||||
"DistantHorizons.config.client.multiplayer.multiDimensionRequiredSimilarity.@tooltip":
|
||||
"When matching worlds of the same dimension type the\nchunks tested must be at least this percent the same\nin order to be considered the same world.\n\n§61:§r the chunks must be identical.\n§60.5:§r the chunks must be half the same.\n§60:§r almost any world will match.",
|
||||
"DistantHorizons.config.client.advanced":
|
||||
"Advanced Options",
|
||||
"Advance options",
|
||||
"DistantHorizons.config.client.advanced.threading":
|
||||
"Threading",
|
||||
"DistantHorizons.config.client.advanced.threading.numberOfWorldGenerationThreads":
|
||||
@@ -213,6 +277,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":
|
||||
|
||||
@@ -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,56 +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 = returnColor;
|
||||
//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);
|
||||
}
|
||||
@@ -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,12 +26,11 @@ uniform sampler2D lightMap;
|
||||
*/
|
||||
void main()
|
||||
{
|
||||
vec4 worldSpacePos = modelViewMatrix * vec4(vPosition.xyz,1);
|
||||
float light = (vPosition.a+0.5) / 256.0;
|
||||
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;
|
||||
|
||||
gl_Position = projectionMatrix * worldSpacePos;
|
||||
|
||||
gl_Position = combinedMatrix * vec4(vertexWorldPos, 1.0);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user