Add RendererType & Debug Renderer + fix Logger bug

This commit is contained in:
TomTheFurry
2022-03-28 17:04:06 +08:00
parent 21d8f1124c
commit 11982d701c
18 changed files with 545 additions and 120 deletions
@@ -23,8 +23,10 @@ import java.time.Duration;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.TimeUnit;
import com.seibel.lod.core.enums.rendering.RendererType;
import com.seibel.lod.core.logging.ConfigBasedLogger;
import com.seibel.lod.core.logging.ConfigBasedSpamLogger;
import com.seibel.lod.core.render.RenderSystemTest;
import org.apache.logging.log4j.Level;
import com.seibel.lod.core.handlers.LodDimensionFinder;
import org.lwjgl.glfw.GLFW;
@@ -63,6 +65,7 @@ public class ClientApi
public static final LodBufferBuilderFactory lodBufferBuilderFactory = new LodBufferBuilderFactory();
public static LodRenderer renderer = new LodRenderer(lodBufferBuilderFactory);
public static RenderSystemTest testRenderer = new RenderSystemTest();
private static final IMinecraftClientWrapper MC = SingletonHandler.get(IMinecraftClientWrapper.class);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.get(IMinecraftRenderWrapper.class);
@@ -250,7 +253,7 @@ public class ClientApi
if (CONFIG.client().advanced().debugging().getDrawLods())
if (CONFIG.client().advanced().debugging().getRendererType() == RendererType.DEFAULT)
{
// Note to self:
// if "unspecified" shows up in the pie chart, it is
@@ -271,15 +274,20 @@ public class ClientApi
+ " renderer has encountered an exception!");
MC.sendChatMessage("\u00A74Renderer is now disabled to prevent futher issues.");
MC.sendChatMessage("\u00A74Exception detail: "+e.toString());
} catch (RuntimeException noMessagesThen) {}
} catch (RuntimeException ignored) {}
}
}
profiler.pop(); // end LOD
profiler.push("terrain"); // go back into "terrain"
} else if (CONFIG.client().advanced().debugging().getRendererType() == RendererType.DEBUG) {
IProfilerWrapper profiler = MC.getProfiler();
profiler.pop(); // get out of "terrain"
profiler.push("LODTestRendering");
ClientApi.testRenderer.render();
profiler.pop(); // end LODTestRendering
profiler.push("terrain"); // go back into "terrain"
}
// these can't be set until after the buffers are built (in renderer.drawLODs)
// otherwise the buffers may be set to the wrong size, or not changed at all
ApiShared.previousChunkRenderDistance = MC_RENDER.getRenderDistance();
@@ -337,8 +345,8 @@ public class ClientApi
if (glfwKey == GLFW.GLFW_KEY_F6) {
CONFIG.client().advanced().debugging()
.setDrawLods(!CONFIG.client().advanced().debugging().getDrawLods());
MC.sendChatMessage("F6: Set rendering to " + CONFIG.client().advanced().debugging().getDrawLods());
.setRendererType(RendererType.next(CONFIG.client().advanced().debugging().getRendererType()));
MC.sendChatMessage("F6: Set rendering to " + CONFIG.client().advanced().debugging().getRendererType());
}
if (glfwKey == GLFW.GLFW_KEY_P) {
@@ -42,6 +42,7 @@ import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import org.apache.logging.log4j.LogManager;
/**
* This object is in charge of creating Lod related objects.
@@ -58,7 +59,8 @@ public class LodBuilder
private static final IWrapperFactory FACTORY = SingletonHandler.get(IWrapperFactory.class);
private static final ILodConfigWrapperSingleton config = SingletonHandler.get(ILodConfigWrapperSingleton.class);
public static final ConfigBasedLogger EVENT_LOGGER = new ConfigBasedLogger(() -> config.client().advanced().debugging().debugSwitch().getLogLodBuilderEvent());
public static final ConfigBasedLogger EVENT_LOGGER = new ConfigBasedLogger(LogManager.getLogger(LodBuilder.class),
() -> config.client().advanced().debugging().debugSwitch().getLogLodBuilderEvent());
/** This cannot be final! Different world have different height, and in menu, this causes Null Exceptions*/
//public static final short MIN_WORLD_HEIGHT = MC.getWrappedClientWorld().getMinHeight();
@@ -0,0 +1,24 @@
package com.seibel.lod.core.enums.rendering;
public enum RendererType {
DEFAULT,
DEBUG,
DISABLED,
;
public static RendererType next(RendererType type) {
return switch (type) {
case DEFAULT -> DEBUG;
case DEBUG -> DISABLED;
default -> DEFAULT;
};
}
public static RendererType previous(RendererType type) {
return switch (type) {
case DEFAULT -> DISABLED;
case DEBUG -> DEFAULT;
default -> DEBUG;
};
}
}
@@ -22,7 +22,6 @@ package com.seibel.lod.core.handlers;
import java.io.*;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.security.Signature;
import java.time.Duration;
import java.time.Instant;
import java.util.ArrayList;
@@ -52,6 +51,7 @@ import com.seibel.lod.core.util.LodThreadFactory;
import com.seibel.lod.core.util.LodUtil;
import com.seibel.lod.core.logging.SpamReducedLogger;
import com.seibel.lod.core.util.UnitBytes;
import org.apache.logging.log4j.LogManager;
/**
@@ -66,7 +66,8 @@ import com.seibel.lod.core.util.UnitBytes;
public class LodDimensionFileHandler
{
private static final ILodConfigWrapperSingleton config = SingletonHandler.get(ILodConfigWrapperSingleton.class);
public static final ConfigBasedLogger LOGGER = new ConfigBasedLogger(() -> config.client().advanced().debugging().debugSwitch().getLogFileReadWriteEvent());
public static final ConfigBasedLogger LOGGER = new ConfigBasedLogger(LogManager.getLogger(LodDimensionFileHandler.class),
() -> config.client().advanced().debugging().debugSwitch().getLogFileReadWriteEvent());
public static final boolean ENABLE_SAVE_THREAD_LOGGING = true;
public static final boolean ENABLE_SAVE_REGION_LOGGING = false;
@@ -23,7 +23,7 @@ import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IDimensionTypeWrapper;
import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
import net.minecraft.world.level.dimension.DimensionType;
import org.apache.logging.log4j.LogManager;
import java.io.File;
import java.io.IOException;
@@ -41,7 +41,8 @@ public class LodDimensionFinder
private static final IMinecraftClientWrapper MC = SingletonHandler.get(IMinecraftClientWrapper.class);
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
private static final IWrapperFactory FACTORY = SingletonHandler.get(IWrapperFactory.class);
public static final ConfigBasedLogger LOGGER = new ConfigBasedLogger(() -> CONFIG.client().advanced().debugging().debugSwitch().getLogFileSubDimEvent());
public static final ConfigBasedLogger LOGGER = new ConfigBasedLogger(LogManager.getLogger(LodDimensionFinder.class),
() -> CONFIG.client().advanced().debugging().debugSwitch().getLogFileSubDimEvent());
/** Increasing this will increase accuracy but increase calculation time */
private static final VerticalQuality VERTICAL_QUALITY_TO_TEST_WITH = VerticalQuality.LOW;
@@ -1,12 +1,13 @@
package com.seibel.lod.core.logging;
import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.enums.config.LoggerMode;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.Message;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
@@ -23,11 +24,13 @@ public class ConfigBasedLogger {
});
}
LoggerMode mode;
final Supplier<LoggerMode> getter;
public ConfigBasedLogger(Supplier<LoggerMode> configQuery) {
private LoggerMode mode;
private final Supplier<LoggerMode> getter;
private final Logger logger;
public ConfigBasedLogger(Logger logger, Supplier<LoggerMode> configQuery) {
getter = configQuery;
mode = getter.get();
this.logger = logger;
loggers.add(new WeakReference<>(this));
}
public void update() {
@@ -37,17 +40,17 @@ public class ConfigBasedLogger {
public void log(Level level, String str, Object... param) {
Message msg = ApiShared.LOGGER.getMessageFactory().newMessage(str, param);
Message msg = logger.getMessageFactory().newMessage(str, param);
String msgStr = msg.getFormattedMessage();
if (mode.levelForFile.isLessSpecificThan(level)) {
Level logLevel = level.isLessSpecificThan(Level.INFO) ? Level.INFO : level;
if (param.length > 0 && param[param.length-1] instanceof Throwable)
ApiShared.LOGGER.atLevel(logLevel).withLocation().withThrowable((Throwable)param[param.length-1]).log(msgStr);
else ApiShared.LOGGER.atLevel(logLevel).withLocation().log(msgStr);
logger.atLevel(logLevel).withLocation().withThrowable((Throwable)param[param.length-1]).log(msgStr);
else logger.atLevel(logLevel).withLocation().log(msgStr);
}
if (mode.levelForChat.isLessSpecificThan(level)) {
if (param.length > 0 && param[param.length-1] instanceof Throwable)
ClientApi.logToChat(level, msgStr + "\nat\n" + ((Throwable) param[param.length-1]).getStackTrace().toString());
ClientApi.logToChat(level, msgStr + "\nat\n" + Arrays.toString(((Throwable) param[param.length - 1]).getStackTrace()));
ClientApi.logToChat(level, msgStr);
}
}
@@ -4,6 +4,7 @@ import com.seibel.lod.core.api.ApiShared;
import com.seibel.lod.core.api.ClientApi;
import com.seibel.lod.core.enums.config.LoggerMode;
import org.apache.logging.log4j.Level;
import org.apache.logging.log4j.Logger;
import org.apache.logging.log4j.message.Message;
import java.lang.ref.WeakReference;
@@ -26,15 +27,17 @@ public class ConfigBasedSpamLogger {
});
}
LoggerMode mode;
final Supplier<LoggerMode> getter;
private LoggerMode mode;
private final Supplier<LoggerMode> getter;
private final int maxLogCount;
private final AtomicInteger logTries = new AtomicInteger(0);
private final Logger logger;
public ConfigBasedSpamLogger(Supplier<LoggerMode> configQuery, int maxLogPerSec) {
public ConfigBasedSpamLogger(Logger logger, Supplier<LoggerMode> configQuery, int maxLogPerSec) {
getter = configQuery;
mode = getter.get();
maxLogCount = maxLogPerSec;
this.logger = logger;
loggers.add(new WeakReference<>(this));
}
public void reset() {logTries.set(0);}
@@ -45,17 +48,18 @@ public class ConfigBasedSpamLogger {
public void log(Level level, String str, Object... param) {
if (logTries.get() >= maxLogCount) return;
Message msg = ApiShared.LOGGER.getMessageFactory().newMessage(str, param);
Message msg = logger.getMessageFactory().newMessage(str, param);
String msgStr = msg.getFormattedMessage();
if (mode.levelForFile.isLessSpecificThan(level)) {
Level logLevel = level.isLessSpecificThan(Level.INFO) ? Level.INFO : level;
if (param.length > 0 && param[param.length-1] instanceof Throwable)
ApiShared.LOGGER.atLevel(logLevel).withLocation().withThrowable((Throwable)param[param.length-1]).log(msgStr);
else ApiShared.LOGGER.atLevel(logLevel).withLocation().log(msgStr);
logger.atLevel(logLevel).withLocation().withThrowable((Throwable)param[param.length-1]).log(msgStr);
else logger.atLevel(logLevel).withLocation().log(msgStr);
}
if (mode.levelForChat.isLessSpecificThan(level)) {
if (param.length > 0 && param[param.length-1] instanceof Throwable)
ClientApi.logToChat(level, msgStr + "\nat\n" + ((Throwable) param[param.length-1]).getStackTrace().toString());
if (param.length > 0 && param[param.length - 1] instanceof Throwable)
ClientApi.logToChat(level, msgStr + "\nat\n" + Arrays.toString(((Throwable) param[param.length - 1]).getStackTrace()));
ClientApi.logToChat(level, msgStr);
}
}
@@ -82,16 +86,17 @@ public class ConfigBasedSpamLogger {
public void logInc(Level level, String str, Object... param) {
if (logTries.getAndIncrement() >= maxLogCount) return;
Message msg = ApiShared.LOGGER.getMessageFactory().newMessage(str, param);
Message msg = logger.getMessageFactory().newMessage(str, param);
String msgStr = msg.getFormattedMessage();
if (mode.levelForFile.isLessSpecificThan(level)) {
Level logLevel = level.isLessSpecificThan(Level.INFO) ? Level.INFO : level;
if (param.length > 0 && param[param.length-1] instanceof Throwable)
ApiShared.LOGGER.atLevel(logLevel).withLocation().withThrowable((Throwable)param[param.length-1]).log(msgStr);
else ApiShared.LOGGER.atLevel(logLevel).withLocation().log(msgStr);
logger.atLevel(logLevel).withLocation().withThrowable((Throwable)param[param.length-1]).log(msgStr);
else logger.atLevel(logLevel).withLocation().log(msgStr);
}
if (mode.levelForChat.isLessSpecificThan(level)) {
if (param.length > 0 && param[param.length-1] instanceof Throwable)
if (param.length > 0 && param[param.length - 1] instanceof Throwable)
ClientApi.logToChat(level, msgStr + "\nat\n" + Arrays.toString(((Throwable) param[param.length - 1]).getStackTrace()));
ClientApi.logToChat(level, msgStr);
}
@@ -18,7 +18,7 @@ import com.seibel.lod.core.wrapperInterfaces.config.ILodConfigWrapperSingleton;
import static com.seibel.lod.core.render.LodRenderer.EVENT_LOGGER;
public class LodQuadBuilder {
static final int MAX_BUFFER_SIZE = (1024 * 1024 * 1);
static final int MAX_BUFFER_SIZE = (1024 * 1024);
static final int QUAD_BYTE_SIZE = (12 * 6);
static final int MAX_QUADS_PER_BUFFER = MAX_BUFFER_SIZE / QUAD_BYTE_SIZE;
//static final int MAX_MERGED_QUAD_SIZE = 64;
@@ -232,7 +232,7 @@ public class LodQuadBuilder {
}
final ArrayList<Quad>[] quads = new ArrayList[6];
final ArrayList<Quad>[] quads = (ArrayList<Quad>[])new ArrayList[6];
public LodQuadBuilder(int initialSize, boolean enableSkylightCulling, int skyLightCullingBelow) {
for (int i=0; i<6; i++) quads[i] = new ArrayList<Quad>();
@@ -26,6 +26,7 @@ import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import com.seibel.lod.core.logging.ConfigBasedLogger;
import org.apache.logging.log4j.LogManager;
import org.lwjgl.glfw.GLFW;
import org.lwjgl.opengl.GL;
import org.lwjgl.opengl.GL11;
@@ -70,7 +71,8 @@ public class GLProxy
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
public static final ConfigBasedLogger GL_LOGGER = new ConfigBasedLogger(() -> CONFIG.client().advanced().debugging().debugSwitch().getLogRendererGLEvent());
public static final ConfigBasedLogger GL_LOGGER = new ConfigBasedLogger(LogManager.getLogger(GLProxy.class),
() -> CONFIG.client().advanced().debugging().debugSwitch().getLogRendererGLEvent());
private static GLProxy instance = null;
@@ -461,7 +463,7 @@ public class GLProxy
*/
public void recordOpenGlCall(Runnable renderCall)
{
workerThread.execute(new Thread(() -> { runnableContainer(renderCall); }));
workerThread.execute(() -> runnableContainer(renderCall));
}
private void runnableContainer(Runnable renderCall)
{
@@ -28,8 +28,10 @@ import com.seibel.lod.core.logging.ConfigBasedLogger;
import com.seibel.lod.core.logging.SpamReducedLogger;
import com.seibel.lod.core.objects.BoolType;
import com.seibel.lod.core.objects.Pos2D;
import com.seibel.lod.core.render.objects.GLState;
import com.seibel.lod.core.util.*;
import com.seibel.lod.core.util.gridList.*;
import org.apache.logging.log4j.LogManager;
import org.lwjgl.opengl.GL32;
import com.seibel.lod.core.builders.lodBuilding.bufferBuilding.LodBufferBuilderFactory;
@@ -60,11 +62,12 @@ import com.seibel.lod.core.wrapperInterfaces.world.IWorldWrapper;
public class LodRenderer
{
private static final ILodConfigWrapperSingleton CONFIG = SingletonHandler.get(ILodConfigWrapperSingleton.class);
public static final ConfigBasedLogger EVENT_LOGGER = new ConfigBasedLogger(() -> CONFIG.client().advanced().debugging().debugSwitch().getLogRendererBufferEvent());
public static final ConfigBasedLogger EVENT_LOGGER = new ConfigBasedLogger(LogManager.getLogger(LodRenderer.class),
() -> CONFIG.client().advanced().debugging().debugSwitch().getLogRendererBufferEvent());
public static final boolean ENABLE_DRAW_LAG_SPIKE_LOGGING = false;
public static final boolean ENABLE_DUMP_GL_STATE = false;
public static final long DRAW_LAG_SPIKE_THRESOLD_NS = TimeUnit.NANOSECONDS.convert(20, TimeUnit.MILLISECONDS);
public static final boolean ENABLE_DUMP_GL_STATE = true;
public static final long DRAW_LAG_SPIKE_THRESHOLD_NS = TimeUnit.NANOSECONDS.convert(20, TimeUnit.MILLISECONDS);
public static class LagSpikeCatcher {
@@ -73,7 +76,7 @@ public class LodRenderer
public void end(String source) {
if (!ENABLE_DRAW_LAG_SPIKE_LOGGING) return;
timer = System.nanoTime() - timer;
if (timer> DRAW_LAG_SPIKE_THRESOLD_NS) { //4 ms
if (timer> DRAW_LAG_SPIKE_THRESHOLD_NS) { //4 ms
EVENT_LOGGER.debug("NOTE: "+source+" took "+Duration.ofNanos(timer)+"!");
}
@@ -135,23 +138,6 @@ public class LodRenderer
}
public static SpamReducedLogger tickLogger = new SpamReducedLogger(1);
public static void dumpGLState(String str) {
if (!ENABLE_DUMP_GL_STATE) return;
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.
@@ -184,17 +170,10 @@ public class LodRenderer
// get MC's shader program
// Save all MC render state
LagSpikeCatcher drawSaveGLState = new LagSpikeCatcher();
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);
dumpGLState("PRE_LOD-DRAW");
GLState currentState = new GLState();
if (ENABLE_DUMP_GL_STATE) {
tickLogger.debug("Saving GL state: {}", currentState);
}
drawSaveGLState.end("drawSaveGLState");
GLProxy glProxy = GLProxy.getInstance();
@@ -376,7 +355,6 @@ public class LodRenderer
oy += dy;
}
}
dumpGLState("Post Lod Draw Before Cleanup");
//if (drawCall==0)
// tickLogger.info("DrawCall Count: {}", drawCount);
@@ -391,29 +369,11 @@ public class LodRenderer
shaderProgram.unbind();
lightmapTexture.free();
GL32.glEnable(GL32.GL_CULL_FACE);
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
if (currentBlend)
GL32.glEnable(GL32.GL_BLEND);
else
GL32.glDisable(GL32.GL_BLEND);
// 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);
// clear the depth buffer so everything is drawn over the LODs
GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT);
GL32.glEnable(GL32.GL_DEPTH_TEST);
currentState.restore();
drawCleanup.end("LodDrawCleanup");
// end of internal LOD profiling
profiler.pop();
tickLogger.incLogTries();
@@ -0,0 +1,114 @@
package com.seibel.lod.core.render;
import com.seibel.lod.core.enums.config.GpuUploadMethod;
import com.seibel.lod.core.enums.config.LoggerMode;
import com.seibel.lod.core.handlers.dependencyInjection.SingletonHandler;
import com.seibel.lod.core.logging.ConfigBasedLogger;
import com.seibel.lod.core.logging.ConfigBasedSpamLogger;
import com.seibel.lod.core.objects.opengl.LodVertexBuffer;
import com.seibel.lod.core.render.objects.GLState;
import com.seibel.lod.core.render.objects.ShaderProgram;
import com.seibel.lod.core.render.objects.VertexAttribute;
import com.seibel.lod.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
import org.apache.logging.log4j.LogManager;
import org.lwjgl.opengl.GL32;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
public class RenderSystemTest {
public RenderSystemTest() {}
public static final ConfigBasedLogger logger = new ConfigBasedLogger(
LogManager.getLogger(RenderSystemTest.class), () -> LoggerMode.LOG_ALL_TO_CHAT);
public static final ConfigBasedSpamLogger spamLogger = new ConfigBasedSpamLogger(
LogManager.getLogger(RenderSystemTest.class), () -> LoggerMode.LOG_ALL_TO_CHAT, 1);
private static final IMinecraftRenderWrapper MC_RENDER = SingletonHandler.get(IMinecraftRenderWrapper.class);
ShaderProgram basicShader;
LodVertexBuffer sameContextBuffer;
LodVertexBuffer sharedContextBuffer;
VertexAttribute va;
boolean init = false;
public void init() {
if (init) return;
logger.info("init");
init = true;
va = VertexAttribute.create();
// Pos
va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec2Pointer(false));
// Color
va.setVertexAttribute(0, 1, VertexAttribute.VertexPointer.addVec4Pointer(false));
va.completeAndCheck(Float.BYTES * 6);
basicShader = new ShaderProgram("shaders/test/vert.vert", "shaders/test/frag.frag", "fragColor");
createBuffer();
}
// Render a square with uv color
private static final float[] vertices = {
// PosX,Y, ColorR,G,B,A
-0.5f, -0.5f, 0.0f, 0.0f, 0.0f, 1.0f,
0.4f, -0.4f, 1.0f, 0.0f, 0.0f, 1.0f,
0.3f, 0.3f, 1.0f, 1.0f, 0.0f, 0.0f,
-0.2f, 0.2f, 0.0f, 1.0f, 1.0f, 1.0f
};
private static LodVertexBuffer createTextingBuffer() {
LodVertexBuffer vbo = new LodVertexBuffer(false);
ByteBuffer buffer = ByteBuffer.allocateDirect(vertices.length * Float.BYTES);
// Fill buffer with the vertices.
buffer = buffer.order(ByteOrder.nativeOrder());
buffer.asFloatBuffer().put(vertices);
buffer.rewind();
vbo.uploadBuffer(buffer, 4, GpuUploadMethod.DATA, vertices.length * Float.BYTES);
return vbo;
}
private void createBuffer() {
GLProxy.getInstance().recordOpenGlCall(() -> sharedContextBuffer = createTextingBuffer());
GLProxy.ensureAllGLJobCompleted();
sameContextBuffer = createTextingBuffer();
}
public void render() {
spamLogger.debug("rendering");
GLState state = new GLState();
init();
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, MC_RENDER.getTargetFrameBuffer());
GL32.glViewport(0,0, MC_RENDER.getTargetFrameBufferViewportWidth(), MC_RENDER.getTargetFrameBufferViewportHeight());
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, GL32.GL_FILL);
GL32.glDisable(GL32.GL_CULL_FACE);
GL32.glDisable(GL32.GL_DEPTH_TEST);
GL32.glDisable(GL32.GL_STENCIL_TEST);
GL32.glDisable(GL32.GL_BLEND);
//GL32.glDisable(GL32.GL_SCISSOR_TEST);
basicShader.bind();
va.bind();
// Switch between the two buffers per second
if (System.currentTimeMillis() % 2000 < 1000) {
va.bindBufferToBindingPoint(sameContextBuffer.id, 0);
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, sameContextBuffer.id);
spamLogger.debug("same context buffer");
} else {
va.bindBufferToBindingPoint(sharedContextBuffer.id, 0);
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, sharedContextBuffer.id);
spamLogger.debug("shared context buffer");
}
// Render the square
GL32.glDrawArrays(GL32.GL_TRIANGLE_FAN, 0, 4);
GL32.glClear(GL32.GL_DEPTH_BUFFER_BIT);
state.restore();
spamLogger.incLogTries();
}
}
@@ -0,0 +1,188 @@
package com.seibel.lod.core.render.objects;
import static org.lwjgl.opengl.GL46.*;
// Turns GL int enums back to readable strings
public class GLEnums {
public static String getString(int glEnum) {
// blend stuff
switch (glEnum) {
case GL_ZERO:
return "GL_ZERO";
case GL_ONE:
return "GL_ONE";
case GL_SRC_COLOR:
return "GL_SRC_COLOR";
case GL_ONE_MINUS_SRC_COLOR:
return "GL_ONE_MINUS_SRC_COLOR";
case GL_DST_COLOR:
return "GL_DST_COLOR";
case GL_ONE_MINUS_DST_COLOR:
return "GL_ONE_MINUS_DST_COLOR";
case GL_SRC_ALPHA:
return "GL_SRC_ALPHA";
case GL_ONE_MINUS_SRC_ALPHA:
return "GL_ONE_MINUS_SRC_ALPHA";
case GL_DST_ALPHA:
return "GL_DST_ALPHA";
case GL_ONE_MINUS_DST_ALPHA:
return "GL_ONE_MINUS_DST_ALPHA";
case GL_CONSTANT_COLOR:
return "GL_CONSTANT_COLOR";
case GL_ONE_MINUS_CONSTANT_COLOR:
return "GL_ONE_MINUS_CONSTANT_COLOR";
case GL_CONSTANT_ALPHA:
return "GL_CONSTANT_ALPHA";
case GL_ONE_MINUS_CONSTANT_ALPHA:
return "GL_ONE_MINUS_CONSTANT_ALPHA";
default:
}
// shader stuff
switch (glEnum) {
case GL_VERTEX_SHADER:
return "GL_VERTEX_SHADER";
case GL_GEOMETRY_SHADER:
return "GL_GEOMETRY_SHADER";
case GL_FRAGMENT_SHADER:
return "GL_FRAGMENT_SHADER";
default:
}
// stencil stuff
switch (glEnum) {
case GL_KEEP:
return "GL_KEEP";
case GL_ZERO:
return "GL_ZERO";
case GL_REPLACE:
return "GL_REPLACE";
case GL_INCR:
return "GL_INCR";
case GL_DECR:
return "GL_DECR";
case GL_INVERT:
return "GL_INVERT";
case GL_INCR_WRAP:
return "GL_INCR_WRAP";
case GL_DECR_WRAP:
return "GL_DECR_WRAP";
default:
}
// depth stuff
switch (glEnum) {
case GL_NEVER:
return "GL_NEVER";
case GL_LESS:
return "GL_LESS";
case GL_EQUAL:
return "GL_EQUAL";
case GL_LEQUAL:
return "GL_LEQUAL";
case GL_GREATER:
return "GL_GREATER";
case GL_NOTEQUAL:
return "GL_NOTEQUAL";
case GL_GEQUAL:
return "GL_GEQUAL";
case GL_ALWAYS:
return "GL_ALWAYS";
default:
}
// Texture binding points
switch (glEnum) {
case GL_TEXTURE0:
return "GL_TEXTURE0";
case GL_TEXTURE1:
return "GL_TEXTURE1";
case GL_TEXTURE2:
return "GL_TEXTURE2";
case GL_TEXTURE3:
return "GL_TEXTURE3";
case GL_TEXTURE4:
return "GL_TEXTURE4";
case GL_TEXTURE5:
return "GL_TEXTURE5";
case GL_TEXTURE6:
return "GL_TEXTURE6";
case GL_TEXTURE7:
return "GL_TEXTURE7";
case GL_TEXTURE8:
return "GL_TEXTURE8";
case GL_TEXTURE9:
return "GL_TEXTURE9";
case GL_TEXTURE10:
return "GL_TEXTURE10";
case GL_TEXTURE11:
return "GL_TEXTURE11";
case GL_TEXTURE12:
return "GL_TEXTURE12";
case GL_TEXTURE13:
return "GL_TEXTURE13";
case GL_TEXTURE14:
return "GL_TEXTURE14";
case GL_TEXTURE15:
return "GL_TEXTURE15";
case GL_TEXTURE16:
return "GL_TEXTURE16";
case GL_TEXTURE17:
return "GL_TEXTURE17";
case GL_TEXTURE18:
return "GL_TEXTURE18";
case GL_TEXTURE19:
return "GL_TEXTURE19";
case GL_TEXTURE20:
return "GL_TEXTURE20";
case GL_TEXTURE21:
return "GL_TEXTURE21";
case GL_TEXTURE22:
return "GL_TEXTURE22";
case GL_TEXTURE23:
return "GL_TEXTURE23";
case GL_TEXTURE24:
return "GL_TEXTURE24";
case GL_TEXTURE25:
return "GL_TEXTURE25";
case GL_TEXTURE26:
return "GL_TEXTURE26";
case GL_TEXTURE27:
return "GL_TEXTURE27";
case GL_TEXTURE28:
return "GL_TEXTURE28";
case GL_TEXTURE29:
return "GL_TEXTURE29";
case GL_TEXTURE30:
return "GL_TEXTURE30";
case GL_TEXTURE31:
return "GL_TEXTURE31";
default:
}
// Polygon modes
switch (glEnum) {
case GL_POINT:
return "GL_POINT";
case GL_LINE:
return "GL_LINE";
case GL_FILL:
return "GL_FILL";
default:
}
// Culling modes
switch (glEnum) {
case GL_FRONT:
return "GL_FRONT";
case GL_BACK:
return "GL_BACK";
case GL_FRONT_AND_BACK:
return "GL_FRONT_AND_BACK";
default:
}
return "GL_UNKNOWN(" + glEnum + ")";
}
}
@@ -0,0 +1,98 @@
package com.seibel.lod.core.render.objects;
import org.lwjgl.opengl.GL32;
public class GLState {
public int prog;
public int vao;
public int vbo;
public int fbo;
public int text;
public boolean blend;
public int blendSrc;
public int blendDst;
public boolean depth;
public int depthFunc;
public boolean stencil;
public int stencilFunc;
public int stencilRef;
public int stencilMask;
public int[] view;
public boolean cull;
public int cullMode;
public int polyMode;
public void saveState() {
prog = GL32.glGetInteger(GL32.GL_CURRENT_PROGRAM);
vao = GL32.glGetInteger(GL32.GL_VERTEX_ARRAY_BINDING);
vbo = GL32.glGetInteger(GL32.GL_ARRAY_BUFFER_BINDING);
fbo = GL32.glGetInteger(GL32.GL_FRAMEBUFFER_BINDING);
text = GL32.glGetInteger(GL32.GL_TEXTURE_BINDING_2D);
blend = GL32.glIsEnabled(GL32.GL_BLEND);
blendSrc = GL32.glGetInteger(GL32.GL_BLEND_SRC);
blendDst = GL32.glGetInteger(GL32.GL_BLEND_DST);
depth = GL32.glIsEnabled(GL32.GL_DEPTH_TEST);
depthFunc = GL32.glGetInteger(GL32.GL_DEPTH_FUNC);
stencil = GL32.glIsEnabled(GL32.GL_STENCIL_TEST);
stencilFunc = GL32.glGetInteger(GL32.GL_STENCIL_FUNC);
stencilRef = GL32.glGetInteger(GL32.GL_STENCIL_REF);
stencilMask = GL32.glGetInteger(GL32.GL_STENCIL_VALUE_MASK);
view = new int[4];
GL32.glGetIntegerv(GL32.GL_VIEWPORT, view);
cull = GL32.glIsEnabled(GL32.GL_CULL_FACE);
cullMode = GL32.glGetInteger(GL32.GL_CULL_FACE_MODE);
polyMode = GL32.glGetInteger(GL32.GL_POLYGON_MODE);
}
@Override
public String toString() {
return "GLState{" + "prog=" + prog + ", vao=" + vao + ", vbo=" + vbo + ", fbo=" + fbo + ", text=" + GLEnums.getString(text) +
", blend=" + blend + ", blendMode=" + GLEnums.getString(blendSrc) + "," + GLEnums.getString(blendDst) +
", depth=" + depth +
", depthFunc=" + GLEnums.getString(depthFunc) + ", stencil=" + stencil + ", stencilFunc=" +
GLEnums.getString(stencilFunc) + ", stencilRef=" + stencilRef + ", stencilMask=" + stencilMask +
", view={x:" + view[0] + ", y:" + view[1] +
", w:" + view[2] + ", h:" + view[3] + "}" + ", cull=" + cull + ", cullMode="
+ GLEnums.getString(cullMode) + ", polyMode=" + GLEnums.getString(polyMode) + '}';
}
public void restore() {
GL32.glBindFramebuffer(GL32.GL_FRAMEBUFFER, fbo);
if (blend) {
GL32.glEnable(GL32.GL_BLEND);
} else {
GL32.glDisable(GL32.GL_BLEND);
}
GL32.glBindTexture(GL32.GL_TEXTURE_2D, text);
GL32.glBindVertexArray(vao);
GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, vbo);
GL32.glBlendFunc(blendSrc, blendDst);
if (depth) {
GL32.glEnable(GL32.GL_DEPTH_TEST);
} else {
GL32.glDisable(GL32.GL_DEPTH_TEST);
}
GL32.glDepthFunc(depthFunc);
if (stencil) {
GL32.glEnable(GL32.GL_STENCIL_TEST);
} else {
GL32.glDisable(GL32.GL_STENCIL_TEST);
}
GL32.glStencilFunc(stencilFunc, stencilRef, stencilMask);
GL32.glViewport(view[0], view[1], view[2], view[3]);
GL32.glUseProgram(prog);
if (cull) {
GL32.glEnable(GL32.GL_CULL_FACE);
} else {
GL32.glDisable(GL32.GL_CULL_FACE);
}
GL32.glCullFace(cullMode);
GL32.glPolygonMode(GL32.GL_FRONT_AND_BACK, polyMode);
}
public GLState() {
saveState();
}
}
@@ -19,6 +19,7 @@
package com.seibel.lod.core.render.objects;
import com.seibel.lod.core.render.GLProxy;
import org.lwjgl.opengl.GL32;
import com.seibel.lod.core.util.LodUtil;
@@ -50,7 +51,7 @@ public abstract class VertexAttribute {
return new VertexPointer(3, GL32.GL_FLOAT, normalized, 12);
}
public static VertexPointer addVec4Pointer(boolean normalized) {
return new VertexPointer(1, GL32.GL_FLOAT, normalized, 16);
return new VertexPointer(4, GL32.GL_FLOAT, normalized, 16);
}
public static VertexPointer addUnsignedBytePointer(boolean normalized) {
return new VertexPointer(1, GL32.GL_UNSIGNED_BYTE, normalized, 4); // Always aligned to 4 bytes
@@ -85,6 +86,14 @@ public abstract class VertexAttribute {
GL32.glBindVertexArray(id);
}
public static VertexAttribute create() {
if (GLProxy.getInstance().VertexAttributeBufferBindingSupported) {
return new VertexAttributePostGL43();
} else {
return new VertexAttributePreGL43();
}
}
// This will bind VertexAttribute
public void bind() {
GL32.glBindVertexArray(id);
@@ -793,16 +793,16 @@ public interface ILodConfigWrapperSingleton extends IBindable
interface IDebugging
{
String DESC = "These settings can be used to look for bugs, or see how certain aspects of the mod work.";
boolean DRAW_LODS_DEFAULT = true;
String DRAW_LODS_DESC = ""
+ " If true, the mod is enabled and fake chunks will be drawn. \n"
+ " If false, the mod will still generate fake chunks, \n"
+ " but they won't be rendered. \n"
RendererType RENDERER_TYPE_DEFAULT = RendererType.DEFAULT;
String RENDERER_TYPE_DESC = ""
+ " What renderer is active? \n"
+ "\n"
+ " Disabling rendering will reduce GPU usage \n";
boolean getDrawLods();
void setDrawLods(boolean newDrawLods);
+ " " + RendererType.DEFAULT + ": Default lod renderer \n"
+ " " + RendererType.DEBUG + ": Debug testing renderer \n"
+ " " + RendererType.DISABLED + ": Disable rendering \n";
RendererType getRendererType();
void setRendererType(RendererType newRendererType);
DebugMode DEBUG_MODE_DEFAULT = DebugMode.OFF;
String DEBUG_MODE_DESC = ""
+10 -20
View File
@@ -236,10 +236,10 @@
"How frequently should vertex buffers (geometry) be rebuilt and sent to the GPU?",
"DistantHorizons.config.client.advanced.debugging":
"Debug",
"DistantHorizons.config.client.advanced.debugging.drawLods":
"Draw LOD's",
"DistantHorizons.config.client.advanced.debugging.drawLods.@tooltip":
"§6True:§r fake chunks will be rendered.\n§6False:§r fake chunks will not be rendered, however they will still be generated and saved to file.",
"DistantHorizons.config.client.advanced.debugging.rendererType":
"Renderer type",
"DistantHorizons.config.client.advanced.debugging.rendererType.@tooltip":
"TODO",
"DistantHorizons.config.client.advanced.debugging.debugMode":
"Debug mode",
"DistantHorizons.config.client.advanced.debugging.debugMode.@tooltip":
@@ -402,6 +402,12 @@
"No collision",
"DistantHorizons.config.enum.BlocksToAvoid.BOTH":
"Both",
"DistantHorizons.config.enum.RendererType.DEFAULT":
"Default",
"DistantHorizons.config.enum.RendererType.DEBUG":
"Debug",
"DistantHorizons.config.enum.RendererType.DISABLED":
"Disabled",
"DistantHorizons.config.enum.DebugMode.OFF":
"Off",
"DistantHorizons.config.enum.DebugMode.SHOW_WIREFRAME":
@@ -414,22 +420,6 @@
"Show generation mode",
"DistantHorizons.config.enum.DebugMode.SHOW_GENMODE_WIREFRAME":
"Show generation mode with wireframe",
/*
DISABLED(Level.OFF, Level.OFF),
LOG_ALL_TO_FILE(Level.ALL, Level.OFF),
LOG_ERROR_TO_CHAT(Level.ALL, Level.ERROR),
LOG_WARNING_TO_CHAT(Level.ALL, Level.WARN),
LOG_INFO_TO_CHAT(Level.ALL, Level.INFO),
LOG_DEBUG_TO_CHAT(Level.ALL, Level.DEBUG),
LOG_ALL_TO_CHAT(Level.ALL, Level.ALL),
LOG_ERROR_TO_CHAT_AND_FILE(Level.ERROR, Level.ERROR),
LOG_WARNING_TO_CHAT_AND_FILE(Level.WARN, Level.WARN),
LOG_INFO_TO_CHAT_AND_FILE(Level.INFO, Level.INFO),
LOG_DEBUG_TO_CHAT_AND_FILE(Level.DEBUG, Level.DEBUG),
LOG_WARNING_TO_CHAT_AND_INFO_TO_FILE(Level.INFO, Level.WARN),
LOG_ERROR_TO_CHAT_AND_INFO_TO_FILE(Level.INFO, Level.ERROR),
*/
"DistantHorizons.config.enum.LoggerMode.DISABLED":
"Disabled",
"DistantHorizons.config.enum.LoggerMode.LOG_ALL_TO_FILE":
@@ -0,0 +1,9 @@
#version 150 core
in vec4 fColor;
out vec4 fragColor;
void main()
{
fragColor = fColor;
}
+11
View File
@@ -0,0 +1,11 @@
#version 150 core
in vec2 vPosition;
in vec4 color;
out vec4 fColor;
void main()
{
gl_Position = vec4(vPosition, 0.0, 1.0);
fColor = color;
}