From 4b27f39a04578977b27576126e7ca4c8bcaaa9d4 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Wed, 10 Jul 2024 07:37:11 -0500 Subject: [PATCH] Fix generic rendering at extreme distances --- .../IDhApiCustomRenderObjectFactory.java | 3 +- .../render/IDhApiRenderableBoxGroup.java | 6 +- .../api/objects/math/DhApiVec3d.java | 94 +++++++++++++++ .../objects/render/DhApiRenderableBox.java | 11 +- .../render/glObject/shader/ShaderProgram.java | 6 +- .../renderer/generic/BeaconRenderHandler.java | 5 +- .../renderer/generic/CloudRenderHandler.java | 10 +- .../generic/GenericObjectRenderer.java | 107 ++++++++++-------- .../generic/GenericRenderObjectFactory.java | 8 +- .../renderer/generic/RenderableBoxGroup.java | 59 ++++++---- .../distanthorizons/core/util/LodUtil.java | 9 ++ .../shaders/genericObject/direct/vert.vert | 2 + .../shaders/genericObject/instanced/vert.vert | 41 +++---- 13 files changed, 252 insertions(+), 109 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3d.java diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java index 7e78e0c60..5b9b7ae66 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiCustomRenderObjectFactory.java @@ -1,5 +1,6 @@ package com.seibel.distanthorizons.api.interfaces.render; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; @@ -20,7 +21,7 @@ import java.util.List; public interface IDhApiCustomRenderObjectFactory { IDhApiRenderableBoxGroup createForSingleBox(DhApiRenderableBox cube); - IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3f originBlockPos, List cubeList); + IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3d originBlockPos, List cubeList); IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List cubeList); } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java index 061f75455..5eda2969f 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/render/IDhApiRenderableBoxGroup.java @@ -2,7 +2,9 @@ package com.seibel.distanthorizons.api.interfaces.render; import com.seibel.distanthorizons.api.enums.config.EDhApiLodShading; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3i; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; @@ -35,9 +37,9 @@ public interface IDhApiRenderableBoxGroup extends List boolean isSsaoEnabled(); /** Sets where this group will render in the level. */ - void setOriginBlockPos(DhApiVec3f pos); + void setOriginBlockPos(DhApiVec3d pos); /** @return the block position in the level that all {@see DhApiRenderableBox} will render relative to. */ - DhApiVec3f getOriginBlockPos(); + DhApiVec3d getOriginBlockPos(); /** * Called right before this group is rendered.
diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3d.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3d.java new file mode 100644 index 000000000..9e1344262 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/math/DhApiVec3d.java @@ -0,0 +1,94 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020-2023 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.api.objects.math; + +/** + * Often used to store block positions or any other + * position in 3D space. + * + * @author James Seibel + * @version 2024-7-9 + * @since API 3.0.0 + */ +public class DhApiVec3d +{ + public double x; + public double y; + public double z; + + + + /** creates a Vec3 at (0,0,0) */ + public DhApiVec3d() + { + this.x = 0; + this.y = 0; + this.z = 0; + } + + public DhApiVec3d(double x, double y, double z) + { + this.x = x; + this.y = y; + this.z = z; + } + + @Override + public boolean equals(Object obj) + { + if (this == obj) + { + return true; + } + else if (obj != null && this.getClass() == obj.getClass()) + { + DhApiVec3d Vec3d = (DhApiVec3d) obj; + if (Double.compare(Vec3d.x, this.x) != 0) + { + return false; + } + else if (Double.compare(Vec3d.y, this.y) != 0) + { + return false; + } + else + { + return Double.compare(Vec3d.z, this.z) == 0; + } + } + else + { + return false; + } + } + + @Override + public int hashCode() + { + long i = Double.doubleToLongBits(this.x); + i = 31 * i + Double.doubleToLongBits(this.y); + i = 31 * i + Double.doubleToLongBits(this.z); + return Long.hashCode(i); + } + + @Override + public String toString() { return "[" + this.x + ", " + this.y + ", " + this.z + "]"; } + +} diff --git a/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java b/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java index 23e1296d4..a69684e95 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/objects/render/DhApiRenderableBox.java @@ -2,6 +2,7 @@ package com.seibel.distanthorizons.api.objects.render; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import java.awt.*; @@ -16,9 +17,9 @@ import java.awt.*; public class DhApiRenderableBox { /** the position closest to (-inf,-inf) */ - public DhApiVec3f minPos; + public DhApiVec3d minPos; /** the position closest to (+inf,+inf) */ - public DhApiVec3f maxPos; + public DhApiVec3d maxPos; public Color color; @@ -28,16 +29,16 @@ public class DhApiRenderableBox // constructors // //==============// - public DhApiRenderableBox(DhApiVec3f minPos, float width, Color color) + public DhApiRenderableBox(DhApiVec3d minPos, float width, Color color) { - this(minPos, new DhApiVec3f( + this(minPos, new DhApiVec3d( minPos.x + width, minPos.y + width, minPos.z + width ), color); } - public DhApiRenderableBox(DhApiVec3f minPos, DhApiVec3f maxPos, Color color) + public DhApiRenderableBox(DhApiVec3d minPos, DhApiVec3d maxPos, Color color) { this.minPos = minPos; this.maxPos = maxPos; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java index b7e932e2d..fc821a461 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/glObject/shader/ShaderProgram.java @@ -26,6 +26,7 @@ import java.util.Arrays; import java.util.List; import java.util.function.Supplier; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3i; import org.lwjgl.opengl.GL32; import org.lwjgl.system.MemoryStack; @@ -195,11 +196,10 @@ public class ShaderProgram { GL32.glUniform3f(location, value.x, value.y, value.z); } - /** Requires ShaderProgram binded. */ - public void setUniform(int location, Vec3d value) + public void setUniform(int location, DhApiVec3i value) { - GL32.glUniform3f(location, (float) value.x, (float) value.y, (float) value.z); + GL32.glUniform3i(location, value.x, value.y, value.z); } /** Requires ShaderProgram binded. */ diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java index 0e0243040..dd4140b02 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/BeaconRenderHandler.java @@ -20,6 +20,7 @@ package com.seibel.distanthorizons.core.render.renderer.generic; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; @@ -182,8 +183,8 @@ public class BeaconRenderHandler if (beaconRefCount.getAndIncrement() == 0) { DhApiRenderableBox beaconBox = new DhApiRenderableBox( - new DhApiVec3f(beacon.pos.x, beacon.pos.y+1, beacon.pos.z), - new DhApiVec3f(beacon.pos.x+1, BEAM_TOP_Y, beacon.pos.z+1), + new DhApiVec3d(beacon.pos.x, beacon.pos.y+1, beacon.pos.z), + new DhApiVec3d(beacon.pos.x+1, BEAM_TOP_Y, beacon.pos.z+1), beacon.color ); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java index f7325bfc6..6fa285cfb 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/CloudRenderHandler.java @@ -20,6 +20,7 @@ package com.seibel.distanthorizons.core.render.renderer.generic; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; @@ -203,8 +204,8 @@ public class CloudRenderHandler } DhApiRenderableBox box = new DhApiRenderableBox( - new DhApiVec3f(minXBlockPos, 0, minZBlockPos), - new DhApiVec3f(maxXBlockPos, CLOUD_BOX_THICKNESS, maxZBlockPos), + new DhApiVec3d(minXBlockPos, 0, minZBlockPos), + new DhApiVec3d(maxXBlockPos, CLOUD_BOX_THICKNESS, maxZBlockPos), color ); boxList.add(box); @@ -231,7 +232,7 @@ public class CloudRenderHandler for (int z = -1; z <= 1; z++) { IDhApiRenderableBoxGroup boxGroup = GenericRenderObjectFactory.INSTANCE.createRelativePositionedGroup( - new DhApiVec3f(0, 0, 0), // the offset will be set during rendering + new DhApiVec3d(0, 0, 0), // the offset will be set during rendering boxList); boxGroup.setBlockLight(LodUtil.MIN_MC_LIGHT); boxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); @@ -265,6 +266,7 @@ public class CloudRenderHandler this.disabledWarningLogged = true; LOGGER.warn("Instanced rendering unavailable, cloud rendering disabled."); } + boxGroup.setActive(false); return; } @@ -311,7 +313,7 @@ public class CloudRenderHandler //==============// boxGroup.setOriginBlockPos( - new DhApiVec3f( + new DhApiVec3d( clouds.xOffset + (clouds.instanceOffsetX * clouds.widthInBlocks) + xOffset + clouds.halfWidthInBlocks, this.level.getLevelWrapper().getMaxHeight() + 200, clouds.zOffset + (clouds.instanceOffsetZ * clouds.widthInBlocks) + zOffset + clouds.halfWidthInBlocks diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java index 3472f9602..19b2273dd 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericObjectRenderer.java @@ -24,7 +24,8 @@ import com.seibel.distanthorizons.api.enums.config.EDhApiLoggerMode; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; -import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3i; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; @@ -93,8 +94,10 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister private int directShaderTransformUniform; private int directShaderColorUniform; - private int instancedShaderOffsetUniform; - private int instancedShaderCameraPosUniform; + private int instancedShaderOffsetChunkUniform; + private int instancedShaderOffsetSubChunkUniform; + private int instancedShaderCameraChunkPosUniform; + private int instancedShaderCameraSubChunkPosUniform; private int instancedShaderProjectionModelViewMatrixUniform; private int lightMapUniform; @@ -213,8 +216,10 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister this.directShaderTransformUniform = this.shader.tryGetUniformLocation("uTransform"); this.directShaderColorUniform = this.shader.tryGetUniformLocation("uColor"); - this.instancedShaderOffsetUniform = this.shader.tryGetUniformLocation("uOffset"); - this.instancedShaderCameraPosUniform = this.shader.tryGetUniformLocation("uCameraPos"); + this.instancedShaderOffsetChunkUniform = this.shader.tryGetUniformLocation("uOffsetChunk"); + this.instancedShaderOffsetSubChunkUniform = this.shader.tryGetUniformLocation("uOffsetSubChunk"); + this.instancedShaderCameraChunkPosUniform = this.shader.tryGetUniformLocation("uCameraPosChunk"); + this.instancedShaderCameraSubChunkPosUniform = this.shader.tryGetUniformLocation("uCameraPosSubChunk"); this.instancedShaderProjectionModelViewMatrixUniform = this.shader.tryGetUniformLocation("uProjectionMvm"); this.lightMapUniform = this.shader.getUniformLocation("uLightMap"); @@ -266,7 +271,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // single giant box IDhApiRenderableBoxGroup singleGiantBoxGroup = factory.createForSingleBox( new DhApiRenderableBox( - new DhApiVec3f(0f,0f,0f), new DhApiVec3f(16f,190f,16f), + new DhApiVec3d(0,0,0), new DhApiVec3d(16,190,16), new Color(Color.CYAN.getRed(), Color.CYAN.getGreen(), Color.CYAN.getBlue(), 125)) ); singleGiantBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); @@ -277,7 +282,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // single slender box IDhApiRenderableBoxGroup singleTallBoxGroup = factory.createForSingleBox( new DhApiRenderableBox( - new DhApiVec3f(16f,0f,31f), new DhApiVec3f(17f,2000f,32f), + new DhApiVec3d(16,0,31), new DhApiVec3d(17,2000,32), new Color(Color.GREEN.getRed(), Color.GREEN.getGreen(), Color.GREEN.getBlue(), 125)) ); singleTallBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); @@ -290,7 +295,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister for (int i = 0; i < 18; i++) { absBoxList.add(new DhApiRenderableBox( - new DhApiVec3f(0f+i,150f+i,24f), new DhApiVec3f(1f+i,151f+i,25f), + new DhApiVec3d(i,150+i,24), new DhApiVec3d(1+i,151+i,25), new Color(Color.ORANGE.getRed(), Color.ORANGE.getGreen(), Color.ORANGE.getBlue()))); } IDhApiRenderableBoxGroup absolutePosBoxGroup = factory.createAbsolutePositionedGroup(absBoxList); @@ -302,15 +307,15 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister for (int i = 0; i < 8; i+=2) { relBoxList.add(new DhApiRenderableBox( - new DhApiVec3f(0f,0f+i,0f), new DhApiVec3f(1f,1f+i,1f), + new DhApiVec3d(0,i,0), new DhApiVec3d(1,1+i,1), new Color(Color.MAGENTA.getRed(), Color.MAGENTA.getGreen(), Color.MAGENTA.getBlue()))); } IDhApiRenderableBoxGroup relativePosBoxGroup = factory.createRelativePositionedGroup( - new DhApiVec3f(24f, 140f, 24f), + new DhApiVec3d(24, 140, 24), relBoxList); relativePosBoxGroup.setPreRenderFunc((event) -> { - DhApiVec3f pos = relativePosBoxGroup.getOriginBlockPos(); + DhApiVec3d pos = relativePosBoxGroup.getOriginBlockPos(); pos.x += event.partialTicks / 2; pos.x %= 32; relativePosBoxGroup.setOriginBlockPos(pos); @@ -325,16 +330,16 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister for (int z = 0; z < 50*2; z+=2) { massRelBoxList.add(new DhApiRenderableBox( - new DhApiVec3f(0f-x, 0f, 0f-z), new DhApiVec3f(1f-x, 1f, 1f-z), + new DhApiVec3d(-x, 0, -z), new DhApiVec3d(1-x, 1, 1-z), new Color(Color.RED.getRed(), Color.RED.getGreen(), Color.RED.getBlue()))); } } IDhApiRenderableBoxGroup massRelativePosBoxGroup = factory.createRelativePositionedGroup( - new DhApiVec3f(-25f, 140f, 0f), + new DhApiVec3d(-25, 140, 0), massRelBoxList); massRelativePosBoxGroup.setPreRenderFunc((event) -> { - DhApiVec3f blockPos = massRelativePosBoxGroup.getOriginBlockPos(); + DhApiVec3d blockPos = massRelativePosBoxGroup.getOriginBlockPos(); blockPos.y += event.partialTicks / 4; if (blockPos.y > 150f) { @@ -415,8 +420,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister Mat4f projectionMvmMatrix = new Mat4f(renderEventParam.dhProjectionMatrix); projectionMvmMatrix.multiply(renderEventParam.dhModelViewMatrix); - Vec3d camPosDouble = MC_RENDER.getCameraExactPosition(); - Vec3f camPos = new Vec3f((float) camPosDouble.x, (float) camPosDouble.y, (float) camPosDouble.z); + Vec3d camPos = MC_RENDER.getCameraExactPosition(); @@ -467,24 +471,36 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // instanced rendering // //=====================// - private void renderBoxGroupInstanced(RenderableBoxGroup boxGroup, Vec3f camPos, Mat4f projectionMvmMatrix) + private void renderBoxGroupInstanced(RenderableBoxGroup boxGroup, Vec3d camPos, Mat4f projectionMvmMatrix) { // update instance data // boxGroup.updateVertexAttributeData(); - this.shader.setUniform(this.instancedShaderOffsetUniform, + this.shader.setUniform(this.instancedShaderOffsetChunkUniform, + new DhApiVec3i( + LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().x), + LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().y), + LodUtil.getChunkPosFromDouble(boxGroup.getOriginBlockPos().z) + )); + this.shader.setUniform(this.instancedShaderOffsetSubChunkUniform, new Vec3f( - boxGroup.getOriginBlockPos().x, - boxGroup.getOriginBlockPos().y, - boxGroup.getOriginBlockPos().z + LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().x), + LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().y), + LodUtil.getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().z) )); - this.shader.setUniform(this.instancedShaderCameraPosUniform, + this.shader.setUniform(this.instancedShaderCameraChunkPosUniform, + new DhApiVec3i( + LodUtil.getChunkPosFromDouble(camPos.x), + LodUtil.getChunkPosFromDouble(camPos.y), + LodUtil.getChunkPosFromDouble(camPos.z) + )); + this.shader.setUniform(this.instancedShaderCameraSubChunkPosUniform, new Vec3f( - camPos.x, - camPos.y, - camPos.z + LodUtil.getSubChunkPosFromDouble(camPos.x), + LodUtil.getSubChunkPosFromDouble(camPos.y), + LodUtil.getSubChunkPosFromDouble(camPos.z) )); this.shader.setUniform(this.instancedShaderProjectionModelViewMatrixUniform, @@ -516,15 +532,20 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister GL32.glVertexAttribPointer(1, 4, GL32.GL_FLOAT, false, 4 * Float.BYTES, 0); this.vertexAttribDivisor(1, 1); - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceTranslationVbo); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceScaleVbo); GL32.glEnableVertexAttribArray(2); this.vertexAttribDivisor(2, 1); GL32.glVertexAttribPointer(2, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0); - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceScaleVbo); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceChunkPosVbo); GL32.glEnableVertexAttribArray(3); this.vertexAttribDivisor(3, 1); - GL32.glVertexAttribPointer(3, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0); + GL32.glVertexAttribIPointer(3, 3, GL32.GL_INT, 3 * Integer.BYTES, 0); + + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, boxGroup.instanceSubChunkPosVbo); + GL32.glEnableVertexAttribArray(4); + this.vertexAttribDivisor(4, 1); + GL32.glVertexAttribPointer(4, 3, GL32.GL_FLOAT, false, 3 * Float.BYTES, 0); // Draw instanced @@ -568,7 +589,7 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister // direct rendering // //==================// - private void renderBoxGroupDirect(RenderableBoxGroup boxGroup, Mat4f transformMatrix, Vec3f camPos) + private void renderBoxGroupDirect(RenderableBoxGroup boxGroup, Mat4f transformMatrix, Vec3d camPos) { this.shader.setUniform(this.lightMapUniform, 0); // TODO this should probably be passed in this.shader.setUniform(this.skyLightUniform, boxGroup.skyLight); @@ -594,32 +615,22 @@ public class GenericObjectRenderer implements IDhApiCustomRenderRegister } private void renderBox( RenderableBoxGroup boxGroup, DhApiRenderableBox box, - Mat4f transformationMatrix, Vec3f camPos) + Mat4f transformationMatrix, Vec3d camPos) { - float originOffsetX = 0; - float originOffsetY = 0; - float originOffsetZ = 0; - if (boxGroup.positionBoxesRelativeToGroupOrigin) - { - originOffsetX = boxGroup.getOriginBlockPos().x; - originOffsetY = boxGroup.getOriginBlockPos().y; - originOffsetZ = boxGroup.getOriginBlockPos().z; - } - Mat4f boxTransform = Mat4f.createTranslateMatrix( - box.minPos.x + originOffsetX - camPos.x, - box.minPos.y + originOffsetY - camPos.y, - box.minPos.z + originOffsetZ - camPos.z); + (float) (box.minPos.x + boxGroup.getOriginBlockPos().x - camPos.x), + (float) (box.minPos.y + boxGroup.getOriginBlockPos().y - camPos.y), + (float) (box.minPos.z + boxGroup.getOriginBlockPos().z - camPos.z)); boxTransform.multiply(Mat4f.createScaleMatrix( - box.maxPos.x - box.minPos.x, - box.maxPos.y - box.minPos.y, - box.maxPos.z - box.minPos.z)); + (float) (box.maxPos.x - box.minPos.x), + (float) (box.maxPos.y - box.minPos.y), + (float) (box.maxPos.z - box.minPos.z))); Mat4f transformMatrix = transformationMatrix.copy(); transformMatrix.multiply(boxTransform); this.shader.setUniform(this.directShaderTransformUniform, transformMatrix); - + this.shader.setUniform(this.directShaderColorUniform, box.color); - + GL32.glDrawElements(GL32.GL_TRIANGLES, BOX_INDICES.length, GL32.GL_UNSIGNED_INT, 0); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericRenderObjectFactory.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericRenderObjectFactory.java index a9234a2c6..263b00ece 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericRenderObjectFactory.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/GenericRenderObjectFactory.java @@ -22,9 +22,11 @@ package com.seibel.distanthorizons.core.render.renderer.generic; import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderObjectFactory; import com.seibel.distanthorizons.api.interfaces.render.IDhApiCustomRenderRegister; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.util.math.Vec3d; import com.seibel.distanthorizons.core.util.math.Vec3f; import org.apache.logging.log4j.Logger; @@ -66,11 +68,11 @@ public class GenericRenderObjectFactory implements IDhApiCustomRenderObjectFacto } @Override - public IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3f originBlockPos, List boxList) - { return new RenderableBoxGroup(new Vec3f(originBlockPos), boxList, true); } + public IDhApiRenderableBoxGroup createRelativePositionedGroup(DhApiVec3d originBlockPos, List boxList) + { return new RenderableBoxGroup(new DhApiVec3d(originBlockPos.x, originBlockPos.y, originBlockPos.z), boxList, true); } @Override public IDhApiRenderableBoxGroup createAbsolutePositionedGroup(List boxList) - { return new RenderableBoxGroup(new Vec3f(0, 0, 0), boxList, false); } + { return new RenderableBoxGroup(new DhApiVec3d(0, 0, 0), boxList, false); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java index 7fc2c74cf..96fff73fa 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/generic/RenderableBoxGroup.java @@ -2,12 +2,11 @@ package com.seibel.distanthorizons.core.render.renderer.generic; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; -import com.seibel.distanthorizons.api.objects.math.DhApiVec3f; +import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox; import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; import com.seibel.distanthorizons.core.render.glObject.GLProxy; import com.seibel.distanthorizons.core.util.LodUtil; -import com.seibel.distanthorizons.core.util.math.Vec3f; import org.jetbrains.annotations.Nullable; import org.lwjgl.opengl.GL32; @@ -36,7 +35,7 @@ public class RenderableBoxGroup private final ArrayList boxList; - private final Vec3f originBlockPos; + private final DhApiVec3d originBlockPos; public boolean active = true; @@ -52,9 +51,11 @@ public class RenderableBoxGroup public Consumer afterRenderFunc; // instance data - public int instanceTranslationVbo = 0; - public int instanceScaleVbo = 0; public int instanceColorVbo = 0; + public int instanceScaleVbo = 0; + public int instanceChunkPosVbo = 0; + public int instanceSubChunkPosVbo = 0; + public int uploadedBoxCount = -1; @@ -65,7 +66,7 @@ public class RenderableBoxGroup public long getId() { return this.id; } @Override - public void setOriginBlockPos(DhApiVec3f pos) + public void setOriginBlockPos(DhApiVec3d pos) { this.originBlockPos.x = pos.x; this.originBlockPos.y = pos.y; @@ -73,7 +74,7 @@ public class RenderableBoxGroup } @Override - public DhApiVec3f getOriginBlockPos() { return new DhApiVec3f(this.originBlockPos.x, this.originBlockPos.y, this.originBlockPos.z); } + public DhApiVec3d getOriginBlockPos() { return new DhApiVec3d(this.originBlockPos.x, this.originBlockPos.y, this.originBlockPos.z); } @Override @@ -106,7 +107,7 @@ public class RenderableBoxGroup // constructor // //=============// - public RenderableBoxGroup(Vec3f originBlockPos, List boxList, boolean positionBoxesRelativeToGroupOrigin) + public RenderableBoxGroup(DhApiVec3d originBlockPos, List boxList, boolean positionBoxesRelativeToGroupOrigin) { this.id = NEXT_ID_ATOMIC_INT.getAndIncrement(); this.boxList = new ArrayList<>(boxList); @@ -201,9 +202,10 @@ public class RenderableBoxGroup } this.vertexDataDirty = false; - if (this.instanceTranslationVbo == 0) + if (this.instanceChunkPosVbo == 0) { - this.instanceTranslationVbo = GL32.glGenBuffers(); + this.instanceChunkPosVbo = GL32.glGenBuffers(); + this.instanceSubChunkPosVbo = GL32.glGenBuffers(); this.instanceScaleVbo = GL32.glGenBuffers(); this.instanceColorVbo = GL32.glGenBuffers(); } @@ -214,7 +216,8 @@ public class RenderableBoxGroup // transformation / scaling // - float[] translationData = new float[boxCount * 3]; + int[] chunkPosData = new int[boxCount * 3]; + float[] subChunkPosData = new float[boxCount * 3]; float[] scalingData = new float[boxCount * 3]; for (int i = 0; i < boxCount; i++) { @@ -222,13 +225,17 @@ public class RenderableBoxGroup int dataIndex = i * 3; - translationData[dataIndex] = box.minPos.x; - translationData[dataIndex + 1] = box.minPos.y; - translationData[dataIndex + 2] = box.minPos.z; + chunkPosData[dataIndex] = LodUtil.getChunkPosFromDouble(box.minPos.x); + chunkPosData[dataIndex + 1] = LodUtil.getChunkPosFromDouble(box.minPos.y); + chunkPosData[dataIndex + 2] = LodUtil.getChunkPosFromDouble(box.minPos.z); - scalingData[dataIndex] = box.maxPos.x - box.minPos.x; - scalingData[dataIndex + 1] = box.maxPos.y - box.minPos.y; - scalingData[dataIndex + 2] = box.maxPos.z - box.minPos.z; + subChunkPosData[dataIndex] = LodUtil.getSubChunkPosFromDouble(box.minPos.x); + subChunkPosData[dataIndex + 1] = LodUtil.getSubChunkPosFromDouble(box.minPos.y); + subChunkPosData[dataIndex + 2] = LodUtil.getSubChunkPosFromDouble(box.minPos.z); + + scalingData[dataIndex] = (float) (box.maxPos.x - box.minPos.x); + scalingData[dataIndex + 1] = (float) (box.maxPos.y - box.minPos.y); + scalingData[dataIndex + 2] = (float) (box.maxPos.z - box.minPos.z); } @@ -249,8 +256,10 @@ public class RenderableBoxGroup // Upload transformation matrices - GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceTranslationVbo); - GL32.glBufferData(GL32.GL_ARRAY_BUFFER, translationData ,GL32.GL_DYNAMIC_DRAW); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceChunkPosVbo); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, chunkPosData ,GL32.GL_DYNAMIC_DRAW); + GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceSubChunkPosVbo); + GL32.glBufferData(GL32.GL_ARRAY_BUFFER, subChunkPosData ,GL32.GL_DYNAMIC_DRAW); GL32.glBindBuffer(GL32.GL_ARRAY_BUFFER, this.instanceScaleVbo); GL32.glBufferData(GL32.GL_ARRAY_BUFFER, scalingData, GL32.GL_DYNAMIC_DRAW); @@ -273,10 +282,16 @@ public class RenderableBoxGroup { GLProxy.getInstance().queueRunningOnRenderThread(() -> { - if (this.instanceTranslationVbo != 0) + if (this.instanceChunkPosVbo != 0) { - GL32.glDeleteBuffers(this.instanceTranslationVbo); - this.instanceTranslationVbo = 0; + GL32.glDeleteBuffers(this.instanceChunkPosVbo); + this.instanceChunkPosVbo = 0; + } + + if (this.instanceSubChunkPosVbo != 0) + { + GL32.glDeleteBuffers(this.instanceSubChunkPosVbo); + this.instanceSubChunkPosVbo = 0; } if (this.instanceScaleVbo != 0) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java index 08ec41d1e..ad9de0b90 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/LodUtil.java @@ -253,6 +253,15 @@ public class LodUtil renderDist * 2 + 1); } + /** Returns the chunk int position for the given double position */ + public static int getChunkPosFromDouble(double value) { return (int) Math.floor(value / CHUNK_WIDTH); } + /** Returns the float position inside the chunk for the given double position */ + public static float getSubChunkPosFromDouble(double value) + { + double chunkPos = Math.floor(value / CHUNK_WIDTH); + return (float) (value - chunkPos * CHUNK_WIDTH); + } + // True if the requested threshold pass, or false otherwise // For details, see: diff --git a/core/src/main/resources/shaders/genericObject/direct/vert.vert b/core/src/main/resources/shaders/genericObject/direct/vert.vert index ec528ae44..55cf5cad7 100644 --- a/core/src/main/resources/shaders/genericObject/direct/vert.vert +++ b/core/src/main/resources/shaders/genericObject/direct/vert.vert @@ -5,6 +5,7 @@ uniform vec4 uColor; uniform int uSkyLight; uniform int uBlockLight; uniform sampler2D uLightMap; + uniform float uNorthShading; uniform float uSouthShading; uniform float uEastShading; @@ -12,6 +13,7 @@ uniform float uWestShading; uniform float uTopShading; uniform float uBottomShading; + in vec3 vPosition; out vec4 fColor; diff --git a/core/src/main/resources/shaders/genericObject/instanced/vert.vert b/core/src/main/resources/shaders/genericObject/instanced/vert.vert index eee0d4142..25231ac39 100644 --- a/core/src/main/resources/shaders/genericObject/instanced/vert.vert +++ b/core/src/main/resources/shaders/genericObject/instanced/vert.vert @@ -1,15 +1,20 @@ #version 330 core layout (location = 1) in vec4 aColor; -layout (location = 2) in vec3 aTranslate; -layout (location = 3) in vec3 aScale; +layout (location = 2) in vec3 aScale; +layout (location = 3) in ivec3 aTranslateChunk; +layout (location = 4) in vec3 aTranslateSubChunk; + +uniform ivec3 uOffsetChunk; +uniform vec3 uOffsetSubChunk; +uniform ivec3 uCameraPosChunk; +uniform vec3 uCameraPosSubChunk; -uniform vec3 uOffset; -uniform vec3 uCameraPos; uniform mat4 uProjectionMvm; uniform int uSkyLight; uniform int uBlockLight; uniform sampler2D uLightMap; + uniform float uNorthShading; uniform float uSouthShading; uniform float uEastShading; @@ -17,6 +22,7 @@ uniform float uWestShading; uniform float uTopShading; uniform float uBottomShading; + in vec3 vPosition; out vec4 fColor; @@ -24,22 +30,19 @@ out vec4 fColor; void main() { // aTranslate - moves the vertex to the boxGroup's relative position - // uOffset - moves the vertex to the boxGroup's position + // uOffset - moves the vertex to the boxGroup's world position // uCameraPos - moves the vertex into camera space - float transX = aTranslate.x + uOffset.x - uCameraPos.x; - float transY = aTranslate.y + uOffset.y - uCameraPos.y; - float transZ = aTranslate.z + uOffset.z - uCameraPos.z; - - float scaleX = aScale.x; - float scaleY = aScale.y; - float scaleZ = aScale.z; + vec3 trans = (aTranslateChunk + uOffsetChunk - uCameraPosChunk) * 16.0f; + // separate float and int values are to fix percission loss at extreme distances from the origin (IE 10,000,000+) + // luckily large translate values minus large cameraPos generally equal values that cleanly fit in a float + trans += (aTranslateSubChunk + uOffsetSubChunk - uCameraPosSubChunk); // combination translation and scaling matrix mat4 transform = mat4( - scaleX, 0.0, 0.0, 0.0, - 0.0, scaleY, 0.0, 0.0, - 0.0, 0.0, scaleZ, 0.0, - transX, transY, transZ, 1.0 + aScale.x, 0.0, 0.0, 0.0, + 0.0, aScale.y, 0.0, 0.0, + 0.0, 0.0, aScale.z, 0.0, + trans.x, trans.y, trans.z, 1.0 ); gl_Position = uProjectionMvm * transform * vec4(vPosition, 1.0); @@ -47,10 +50,10 @@ void main() float blockLight = (float(uBlockLight)+0.5) / 16.0; float skyLight = (float(uSkyLight)+0.5) / 16.0; vec4 lightColor = vec4(texture(uLightMap, vec2(blockLight, skyLight)).xyz, 1.0); - - + + fColor = lightColor * aColor; - + // apply directional shading if (gl_VertexID >= 0 && gl_VertexID < 4) { fColor.rgb *= uNorthShading; } else if (gl_VertexID >= 4 && gl_VertexID < 8) { fColor.rgb *= uSouthShading; }