diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java index 11f53dae5..a4edbfa4d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/DebugRenderer.java @@ -52,7 +52,6 @@ import java.util.concurrent.PriorityBlockingQueue; public class DebugRenderer { public static DebugRenderer INSTANCE = new DebugRenderer(); - public DebugRenderer() { } public static final ConfigBasedLogger logger = new ConfigBasedLogger( LogManager.getLogger(TestRenderer.class), () -> ELoggerMode.LOG_ALL_TO_CHAT); @@ -60,6 +59,26 @@ public class DebugRenderer LogManager.getLogger(TestRenderer.class), () -> ELoggerMode.LOG_ALL_TO_CHAT, 1); private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + + // rendering setup + private ShaderProgram basicShader; + private GLVertexBuffer boxBuffer; + private GLElementBuffer boxOutlineBuffer; + private VertexAttribute va; + private boolean init = false; + + // used when rendering + private Mat4f transformThiFrame; + private Vec3f camPosFloatThisFrame; + + + // render lists + private final LinkedList> renderers = new LinkedList<>(); + + private final PriorityBlockingQueue particles = new PriorityBlockingQueue<>(); + + + // A box from 0,0,0 to 1,1,1 private static final float[] box_vertices = { // Pos x y z @@ -90,6 +109,199 @@ public class DebugRenderer 3, 7, }; + + + //=============// + // constructor // + //=============// + + public DebugRenderer() { } + + + + //==============// + // registration // + //==============// + + public static void unregister(IDebugRenderable renderable) + { + if (INSTANCE != null) + { + INSTANCE.removeRenderer(renderable); + } + } + + public static void makeParticle(BoxParticle particle) + { + if (INSTANCE != null && !Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get()) + { + INSTANCE.particles.add(particle); + } + } + + private void removeRenderer(IDebugRenderable renderable) + { + synchronized (this.renderers) + { + Iterator> iterator = this.renderers.iterator(); + while (iterator.hasNext()) + { + WeakReference renderableRef = iterator.next(); + if (renderableRef.get() == null) + { + iterator.remove(); + continue; + } + if (renderableRef.get() == renderable) + { + iterator.remove(); + return; + } + } + } + } + + public static void clearRenderables() { INSTANCE.renderers.clear(); } + + public void init() + { + if (this.init) + { + return; + } + + this.init = true; + this.va = VertexAttribute.create(); + this.va.bind(); + // Pos + this.va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec3Pointer(false)); + this.va.completeAndCheck(Float.BYTES * 3); + this.basicShader = new ShaderProgram("shaders/debug/vert.vert", "shaders/debug/frag.frag", + "fragColor", new String[]{"vPosition"}); + this.createBuffer(); + } + + private void createBuffer() + { + ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES); + buffer.order(ByteOrder.nativeOrder()); + buffer.asFloatBuffer().put(box_vertices); + buffer.rewind(); + + this.boxBuffer = new GLVertexBuffer(false); + this.boxBuffer.bind(); + this.boxBuffer.uploadBuffer(buffer, 8, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES); + + buffer = ByteBuffer.allocateDirect(box_outline_indices.length * Integer.BYTES); + buffer.order(ByteOrder.nativeOrder()); + buffer.asIntBuffer().put(box_outline_indices); + buffer.rewind(); + + this.boxOutlineBuffer = new GLElementBuffer(false); + this.boxOutlineBuffer.bind(); + this.boxOutlineBuffer.uploadBuffer(buffer, EGpuUploadMethod.DATA, box_outline_indices.length * Integer.BYTES, GL32.GL_STATIC_DRAW); + } + + public void addRenderer(IDebugRenderable r) + { + if (!Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get()) return; + synchronized (this.renderers) + { + this.renderers.add(new WeakReference<>(r)); + } + } + + public static void register(IDebugRenderable r) + { + if (INSTANCE != null) + { + INSTANCE.addRenderer(r); + } + } + + + + //===========// + // rendering // + //===========// + + public void render(Mat4f transform) + { + this.transformThiFrame = transform; + Vec3d camPos = MC_RENDER.getCameraExactPosition(); + camPosFloatThisFrame = new Vec3f((float) camPos.x, (float) camPos.y, (float) camPos.z); + + GLState glState = new GLState(); + this.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_LINE); + //GL32.glLineWidth(2); + GL32.glEnable(GL32.GL_DEPTH_TEST); + GL32.glDisable(GL32.GL_STENCIL_TEST); + GL32.glDisable(GL32.GL_BLEND); + GL32.glDisable(GL32.GL_SCISSOR_TEST); + + this.basicShader.bind(); + this.va.bind(); + this.va.bindBufferToAllBindingPoint(this.boxBuffer.getId()); + + this.boxOutlineBuffer.bind(); + + synchronized (this.renderers) + { + Iterator> it = this.renderers.iterator(); + while (it.hasNext()) + { + // TODO split this up to improve frame times when only some items are needed + WeakReference ref = it.next(); + IDebugRenderable r = ref.get(); + if (r == null) + { + it.remove(); + continue; + } + r.debugRender(this); + } + } + + + BoxParticle head = null; + while ((head = this.particles.poll()) != null && head.isDead(System.nanoTime())) + { + } + if (head != null) + { + this.particles.add(head); + } + + for (BoxParticle particle : this.particles) + { + this.renderBox(particle.getBox()); + } + + + glState.restore(); + } + + public void renderBox(Box box) + { + Mat4f boxTransform = Mat4f.createTranslateMatrix(box.a.x - this.camPosFloatThisFrame.x, box.a.y - this.camPosFloatThisFrame.y, box.a.z - this.camPosFloatThisFrame.z); + boxTransform.multiply(Mat4f.createScaleMatrix(box.b.x - box.a.x, box.b.y - box.a.y, box.b.z - box.a.z)); + Mat4f t = this.transformThiFrame.copy(); + t.multiply(boxTransform); + this.basicShader.setUniform(this.basicShader.getUniformLocation("transform"), t); + this.basicShader.setUniform(this.basicShader.getUniformLocation("uColor"), box.color); + GL32.glDrawElements(GL32.GL_LINES, box_outline_indices.length, GL32.GL_UNSIGNED_INT, 0); + } + + + + //================// + // helper classes // + //================// + public static final class Box { public Vec3f a; @@ -149,14 +361,6 @@ public class DebugRenderer } - ShaderProgram basicShader; - GLVertexBuffer boxBuffer; - GLElementBuffer boxOutlineBuffer; - VertexAttribute va; - boolean init = false; - - private final LinkedList> renderers = new LinkedList<>(); - public static final class BoxParticle implements Comparable { public Box box; @@ -177,26 +381,22 @@ public class DebugRenderer public BoxParticle(Box box, double secondDuration, float yChange) { this(box, System.nanoTime(), (long) (secondDuration * 1000000000), yChange); } - @Override - public int compareTo(@NotNull DebugRenderer.BoxParticle o) + public int compareTo(@NotNull BoxParticle particle) { - return Long.compare(startTime + duration, o.startTime + o.duration); + return Long.compare(this.startTime + this.duration, particle.startTime + particle.duration); } - Box getBox() + public Box getBox() { long now = System.nanoTime(); - float percent = (now - startTime) / (float) duration; + float percent = (now - this.startTime) / (float) this.duration; percent = (float) Math.pow(percent, 4); - float yDiff = yChange * percent; - return new Box(new Vec3f(box.a.x, box.a.y + yDiff, box.a.z), new Vec3f(box.b.x, box.b.y + yDiff, box.b.z), box.color); + float yDiff = this.yChange * percent; + return new Box(new Vec3f(this.box.a.x, this.box.a.y + yDiff, this.box.a.z), new Vec3f(this.box.b.x, this.box.b.y + yDiff, this.box.b.z), this.box.color); } - boolean isDead(long time) - { - return time - startTime > duration; - } + public boolean isDead(long time) { return (time - this.startTime) > this.duration; } } @@ -205,17 +405,16 @@ public class DebugRenderer public Box box; public BoxParticle particaleOnClose; + public BoxWithLife(Box box, long ns, float yChange, Color deathColor) { this.box = box; this.particaleOnClose = new BoxParticle(new Box(box.a, box.b, deathColor), -1, ns, yChange); - DebugRenderer.register(this); + register(this); } - public BoxWithLife(Box box, long ns, float yChange) - { - this(box, ns, yChange, box.color); - } + + public BoxWithLife(Box box, long ns, float yChange) { this(box, ns, yChange, box.color); } public BoxWithLife(Box box, double s, float yChange, Color deathColor) { @@ -223,179 +422,19 @@ public class DebugRenderer this.particaleOnClose = new BoxParticle(new Box(box.a, box.b, deathColor), s, yChange); } - public BoxWithLife(Box box, double s, float yChange) - { - this(box, s, yChange, box.color); - } + public BoxWithLife(Box box, double s, float yChange) { this(box, s, yChange, box.color); } @Override - public void debugRender(DebugRenderer r) - { - r.renderBox(box); - } + public void debugRender(DebugRenderer renderer) { renderer.renderBox(this.box); } @Override public void close() { - makeParticle(new BoxParticle(particaleOnClose.getBox(), System.nanoTime(), particaleOnClose.duration, particaleOnClose.yChange)); - DebugRenderer.unregister(this); + makeParticle(new BoxParticle(this.particaleOnClose.getBox(), System.nanoTime(), this.particaleOnClose.duration, this.particaleOnClose.yChange)); + unregister(this); } } - private final PriorityBlockingQueue particles = new PriorityBlockingQueue<>(); - - public static void unregister(IDebugRenderable r) - { - if (INSTANCE == null) return; - INSTANCE.removeRenderer(r); - } - - public static void makeParticle(BoxParticle particle) - { - if (INSTANCE == null) return; - if (!Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get()) return; - INSTANCE.particles.add(particle); - } - - private void removeRenderer(IDebugRenderable r) - { - synchronized (this.renderers) - { - Iterator> iterator = this.renderers.iterator(); - while (iterator.hasNext()) - { - WeakReference renderableRef = iterator.next(); - if (renderableRef.get() == null) - { - iterator.remove(); - continue; - } - if (renderableRef.get() == r) - { - iterator.remove(); - return; - } - } - } - } - - public static void clearRenderables() { INSTANCE.renderers.clear(); } - - public void init() - { - if (init) return; - init = true; - va = VertexAttribute.create(); - va.bind(); - // Pos\ - va.setVertexAttribute(0, 0, VertexAttribute.VertexPointer.addVec3Pointer(false)); - va.completeAndCheck(Float.BYTES * 3); - basicShader = new ShaderProgram("shaders/debug/vert.vert", "shaders/debug/frag.frag", - "fragColor", new String[]{"vPosition"}); - createBuffer(); - } - - private void createBuffer() - { - ByteBuffer buffer = ByteBuffer.allocateDirect(box_vertices.length * Float.BYTES); - buffer.order(ByteOrder.nativeOrder()); - buffer.asFloatBuffer().put(box_vertices); - buffer.rewind(); - boxBuffer = new GLVertexBuffer(false); - boxBuffer.bind(); - boxBuffer.uploadBuffer(buffer, 8, EGpuUploadMethod.DATA, box_vertices.length * Float.BYTES); - - buffer = ByteBuffer.allocateDirect(box_outline_indices.length * Integer.BYTES); - buffer.order(ByteOrder.nativeOrder()); - buffer.asIntBuffer().put(box_outline_indices); - buffer.rewind(); - boxOutlineBuffer = new GLElementBuffer(false); - boxOutlineBuffer.bind(); - boxOutlineBuffer.uploadBuffer(buffer, EGpuUploadMethod.DATA, box_outline_indices.length * Integer.BYTES, GL32.GL_STATIC_DRAW); - } - - public void addRenderer(IDebugRenderable r) - { - if (!Config.Client.Advanced.Debugging.DebugWireframe.enableRendering.get()) return; - synchronized (renderers) - { - renderers.add(new WeakReference<>(r)); - } - } - - public static void register(IDebugRenderable r) - { - if (INSTANCE == null) return; - INSTANCE.addRenderer(r); - } - - private Mat4f transform_this_frame; - private Vec3f camf; - - public void renderBox(Box box) - { - Mat4f boxTransform = Mat4f.createTranslateMatrix(box.a.x - camf.x, box.a.y - camf.y, box.a.z - camf.z); - boxTransform.multiply(Mat4f.createScaleMatrix(box.b.x - box.a.x, box.b.y - box.a.y, box.b.z - box.a.z)); - Mat4f t = transform_this_frame.copy(); - t.multiply(boxTransform); - basicShader.setUniform(basicShader.getUniformLocation("transform"), t); - basicShader.setUniform(basicShader.getUniformLocation("uColor"), box.color); - GL32.glDrawElements(GL32.GL_LINES, box_outline_indices.length, GL32.GL_UNSIGNED_INT, 0); - } - - public void render(Mat4f transform) - { - transform_this_frame = transform; - Vec3d cam = MC_RENDER.getCameraExactPosition(); - camf = new Vec3f((float) cam.x, (float) cam.y, (float) cam.z); - - 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_LINE); - //GL32.glLineWidth(2); - GL32.glEnable(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(); - va.bindBufferToAllBindingPoint(boxBuffer.getId()); - - boxOutlineBuffer.bind(); - - synchronized (renderers) - { - Iterator> it = renderers.iterator(); - while (it.hasNext()) - { - WeakReference ref = it.next(); - IDebugRenderable r = ref.get(); - if (r == null) - { - it.remove(); - continue; - } - r.debugRender(this); - } - } - - BoxParticle head = null; - while ((head = particles.poll()) != null && head.isDead(System.nanoTime())) - { - } - if (head != null) - { - particles.add(head); - } - particles.forEach(b -> renderBox(b.getBox())); - - state.restore(); - } - }