diff --git a/src/main/java/com/seibel/lod/core/api/ClientApi.java b/src/main/java/com/seibel/lod/core/api/ClientApi.java index 1a41b8e84..ba2a3b117 100644 --- a/src/main/java/com/seibel/lod/core/api/ClientApi.java +++ b/src/main/java/com/seibel/lod/core/api/ClientApi.java @@ -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) { diff --git a/src/main/java/com/seibel/lod/core/builders/lodBuilding/LodBuilder.java b/src/main/java/com/seibel/lod/core/builders/lodBuilding/LodBuilder.java index 61eab6ec7..933871e5e 100644 --- a/src/main/java/com/seibel/lod/core/builders/lodBuilding/LodBuilder.java +++ b/src/main/java/com/seibel/lod/core/builders/lodBuilding/LodBuilder.java @@ -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(); diff --git a/src/main/java/com/seibel/lod/core/enums/rendering/RendererType.java b/src/main/java/com/seibel/lod/core/enums/rendering/RendererType.java new file mode 100644 index 000000000..d50958c65 --- /dev/null +++ b/src/main/java/com/seibel/lod/core/enums/rendering/RendererType.java @@ -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; + }; + } +} diff --git a/src/main/java/com/seibel/lod/core/handlers/LodDimensionFileHandler.java b/src/main/java/com/seibel/lod/core/handlers/LodDimensionFileHandler.java index bc3345a94..e6f4a0400 100644 --- a/src/main/java/com/seibel/lod/core/handlers/LodDimensionFileHandler.java +++ b/src/main/java/com/seibel/lod/core/handlers/LodDimensionFileHandler.java @@ -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; diff --git a/src/main/java/com/seibel/lod/core/handlers/LodDimensionFinder.java b/src/main/java/com/seibel/lod/core/handlers/LodDimensionFinder.java index 47f5983e7..d05f8f2ed 100644 --- a/src/main/java/com/seibel/lod/core/handlers/LodDimensionFinder.java +++ b/src/main/java/com/seibel/lod/core/handlers/LodDimensionFinder.java @@ -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; diff --git a/src/main/java/com/seibel/lod/core/logging/ConfigBasedLogger.java b/src/main/java/com/seibel/lod/core/logging/ConfigBasedLogger.java index fd4d338da..9088dcc8d 100644 --- a/src/main/java/com/seibel/lod/core/logging/ConfigBasedLogger.java +++ b/src/main/java/com/seibel/lod/core/logging/ConfigBasedLogger.java @@ -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 getter; - public ConfigBasedLogger(Supplier configQuery) { + private LoggerMode mode; + private final Supplier getter; + private final Logger logger; + public ConfigBasedLogger(Logger logger, Supplier 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); } } diff --git a/src/main/java/com/seibel/lod/core/logging/ConfigBasedSpamLogger.java b/src/main/java/com/seibel/lod/core/logging/ConfigBasedSpamLogger.java index 19a955f15..d39911f14 100644 --- a/src/main/java/com/seibel/lod/core/logging/ConfigBasedSpamLogger.java +++ b/src/main/java/com/seibel/lod/core/logging/ConfigBasedSpamLogger.java @@ -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 getter; + private LoggerMode mode; + private final Supplier getter; private final int maxLogCount; private final AtomicInteger logTries = new AtomicInteger(0); + private final Logger logger; - public ConfigBasedSpamLogger(Supplier configQuery, int maxLogPerSec) { + public ConfigBasedSpamLogger(Logger logger, Supplier 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); } diff --git a/src/main/java/com/seibel/lod/core/objects/opengl/LodQuadBuilder.java b/src/main/java/com/seibel/lod/core/objects/opengl/LodQuadBuilder.java index 0e99fc282..d5fef7288 100644 --- a/src/main/java/com/seibel/lod/core/objects/opengl/LodQuadBuilder.java +++ b/src/main/java/com/seibel/lod/core/objects/opengl/LodQuadBuilder.java @@ -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[] quads = new ArrayList[6]; + final ArrayList[] quads = (ArrayList[])new ArrayList[6]; public LodQuadBuilder(int initialSize, boolean enableSkylightCulling, int skyLightCullingBelow) { for (int i=0; i<6; i++) quads[i] = new ArrayList(); diff --git a/src/main/java/com/seibel/lod/core/render/GLProxy.java b/src/main/java/com/seibel/lod/core/render/GLProxy.java index 171df4564..3e8422368 100644 --- a/src/main/java/com/seibel/lod/core/render/GLProxy.java +++ b/src/main/java/com/seibel/lod/core/render/GLProxy.java @@ -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) { diff --git a/src/main/java/com/seibel/lod/core/render/LodRenderer.java b/src/main/java/com/seibel/lod/core/render/LodRenderer.java index 4fa39a2a9..5965d1da9 100644 --- a/src/main/java/com/seibel/lod/core/render/LodRenderer.java +++ b/src/main/java/com/seibel/lod/core/render/LodRenderer.java @@ -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(); diff --git a/src/main/java/com/seibel/lod/core/render/RenderSystemTest.java b/src/main/java/com/seibel/lod/core/render/RenderSystemTest.java new file mode 100644 index 000000000..387b4b649 --- /dev/null +++ b/src/main/java/com/seibel/lod/core/render/RenderSystemTest.java @@ -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(); + } + + + +} diff --git a/src/main/java/com/seibel/lod/core/render/objects/GLEnums.java b/src/main/java/com/seibel/lod/core/render/objects/GLEnums.java new file mode 100644 index 000000000..53237fce2 --- /dev/null +++ b/src/main/java/com/seibel/lod/core/render/objects/GLEnums.java @@ -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 + ")"; + } +} \ No newline at end of file diff --git a/src/main/java/com/seibel/lod/core/render/objects/GLState.java b/src/main/java/com/seibel/lod/core/render/objects/GLState.java new file mode 100644 index 000000000..978f9e940 --- /dev/null +++ b/src/main/java/com/seibel/lod/core/render/objects/GLState.java @@ -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(); + } +} diff --git a/src/main/java/com/seibel/lod/core/render/objects/VertexAttribute.java b/src/main/java/com/seibel/lod/core/render/objects/VertexAttribute.java index 31d8cdc02..efb81ba11 100644 --- a/src/main/java/com/seibel/lod/core/render/objects/VertexAttribute.java +++ b/src/main/java/com/seibel/lod/core/render/objects/VertexAttribute.java @@ -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); diff --git a/src/main/java/com/seibel/lod/core/wrapperInterfaces/config/ILodConfigWrapperSingleton.java b/src/main/java/com/seibel/lod/core/wrapperInterfaces/config/ILodConfigWrapperSingleton.java index d837066ff..6d3cd3b78 100644 --- a/src/main/java/com/seibel/lod/core/wrapperInterfaces/config/ILodConfigWrapperSingleton.java +++ b/src/main/java/com/seibel/lod/core/wrapperInterfaces/config/ILodConfigWrapperSingleton.java @@ -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 = "" diff --git a/src/main/resources/assets/lod/lang/en_us.json b/src/main/resources/assets/lod/lang/en_us.json index 8f4206159..3a8869359 100644 --- a/src/main/resources/assets/lod/lang/en_us.json +++ b/src/main/resources/assets/lod/lang/en_us.json @@ -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": diff --git a/src/main/resources/shaders/test/frag.frag b/src/main/resources/shaders/test/frag.frag new file mode 100644 index 000000000..2a8a4d685 --- /dev/null +++ b/src/main/resources/shaders/test/frag.frag @@ -0,0 +1,9 @@ +#version 150 core + +in vec4 fColor; +out vec4 fragColor; + +void main() +{ + fragColor = fColor; +} \ No newline at end of file diff --git a/src/main/resources/shaders/test/vert.vert b/src/main/resources/shaders/test/vert.vert new file mode 100644 index 000000000..12a66443f --- /dev/null +++ b/src/main/resources/shaders/test/vert.vert @@ -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; +} \ No newline at end of file