diff --git a/src/main/java/com/seibel/lod/config/LodConfig.java b/src/main/java/com/seibel/lod/config/LodConfig.java index 2a91d95e1..caffa670d 100644 --- a/src/main/java/com/seibel/lod/config/LodConfig.java +++ b/src/main/java/com/seibel/lod/config/LodConfig.java @@ -38,7 +38,9 @@ import com.seibel.lod.enums.HorizontalQuality; import com.seibel.lod.enums.HorizontalResolution; import com.seibel.lod.enums.HorizontalScale; import com.seibel.lod.enums.LodTemplate; +import com.seibel.lod.enums.VanillaOverdraw; import com.seibel.lod.enums.VerticalQuality; +import com.seibel.lod.util.LodUtil; import net.minecraftforge.common.ForgeConfigSpec; import net.minecraftforge.eventbus.api.SubscribeEvent; @@ -49,7 +51,7 @@ import net.minecraftforge.fml.config.ModConfig; * This handles any configuration the user has access to. * * @author James Seibel - * @version 10-9-2021 + * @version 10-10-2021 */ @Mod.EventBusSubscriber public class LodConfig @@ -99,6 +101,7 @@ public class LodConfig public final ForgeConfigSpec.BooleanValue drawLods; + public final ForgeConfigSpec.EnumValue vanillaOverdraw; Graphics(ForgeConfigSpec.Builder builder) { @@ -183,6 +186,16 @@ public class LodConfig + " distances higher than 128 \n") .define("alwaysDrawAtMaxQuality", false); + vanillaOverdraw = builder + .comment("\n\n" + + " How often should LODs be drawn on top of regular chunks? \n" + + " HALF and ALWAYS will prevent holes in the world, but may look odd on transparent blocks. \n" + + VanillaOverdraw.NEVER + ": LODs won't render on top of vanilla chunks. \n" + + VanillaOverdraw.HALF + ": LODs will render on top of distant vanilla chunks to hide holes in the world. \n" + + " " + " For vanilla render distances less than or equal to " + LodUtil.MINIMUM_RENDER_DISTANCE_FOR_PARTIAL_OVERDRAW + " " + VanillaOverdraw.HALF + " defaults works the same as " + VanillaOverdraw.ALWAYS + ". \n" + + VanillaOverdraw.ALWAYS + ": LODs will render on all vanilla chunks preventing holes in the world. \n") + .defineEnum("vanillaOverdraw", VanillaOverdraw.HALF); + builder.pop(); } } @@ -207,7 +220,6 @@ public class LodConfig + " overhangs, caves, floating islands, ect. \n" + " Higher options will use more memory and lower performance. \n" + " " + VerticalQuality.LOW + ": uses at max 2 columns per position. \n" - + " " + VerticalQuality.MEDIUM + ": uses at max 4 columns per position. \n" + " " + VerticalQuality.HIGH + ": uses at max 8 columns per position. \n") .defineEnum("Vertical Quality", VerticalQuality.MEDIUM); diff --git a/src/main/java/com/seibel/lod/enums/VanillaOverdraw.java b/src/main/java/com/seibel/lod/enums/VanillaOverdraw.java new file mode 100644 index 000000000..4167e0cf6 --- /dev/null +++ b/src/main/java/com/seibel/lod/enums/VanillaOverdraw.java @@ -0,0 +1,23 @@ +package com.seibel.lod.enums; + +/** + * None, Half, Always + * + *

+ * This represents how far the LODs should overlap with + * the vanilla Minecraft terrain. + * + * @author James Seibel + * @version 10-10-2021 + */ +public enum VanillaOverdraw +{ + /** Never draw LODs where a minecraft chunk could be. */ + NEVER, + + /** Draw LODs over the farther minecraft chunks. */ + HALF, + + /** Draw LODs over all minecraft chunks. */ + ALWAYS, +} \ No newline at end of file diff --git a/src/main/java/com/seibel/lod/proxy/ClientProxy.java b/src/main/java/com/seibel/lod/proxy/ClientProxy.java index b68e817e9..98832575d 100644 --- a/src/main/java/com/seibel/lod/proxy/ClientProxy.java +++ b/src/main/java/com/seibel/lod/proxy/ClientProxy.java @@ -18,6 +18,10 @@ package com.seibel.lod.proxy; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.lwjgl.glfw.GLFW; + import com.mojang.blaze3d.matrix.MatrixStack; import com.seibel.lod.builders.bufferBuilding.LodBufferBuilder; import com.seibel.lod.builders.lodBuilding.LodBuilder; @@ -25,6 +29,7 @@ import com.seibel.lod.builders.worldGeneration.LodNodeGenWorker; import com.seibel.lod.builders.worldGeneration.LodWorldGenerator; import com.seibel.lod.config.LodConfig; import com.seibel.lod.enums.DistanceGenerationMode; +import com.seibel.lod.enums.VanillaOverdraw; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.LodWorld; import com.seibel.lod.objects.RegionPos; @@ -34,6 +39,7 @@ import com.seibel.lod.util.DetailDistanceUtil; import com.seibel.lod.util.LodUtil; import com.seibel.lod.util.ThreadMapUtil; import com.seibel.lod.wrappers.MinecraftWrapper; + import net.minecraft.profiler.IProfiler; import net.minecraft.util.text.StringTextComponent; import net.minecraftforge.client.event.InputEvent; @@ -42,9 +48,6 @@ import net.minecraftforge.event.world.BlockEvent; import net.minecraftforge.event.world.ChunkEvent; import net.minecraftforge.event.world.WorldEvent; import net.minecraftforge.eventbus.api.SubscribeEvent; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.lwjgl.glfw.GLFW; /** * This handles all events sent to the client, @@ -178,8 +181,7 @@ public class ClientProxy // LodConfig.CLIENT.graphics.fogDistance.set(FogDistance.FAR); // LodConfig.CLIENT.graphics.fogDrawOverride.set(FogDrawOverride.ALWAYS_DRAW_FOG_FANCY); // LodConfig.CLIENT.graphics.shadingMode.set(ShadingMode.DARKEN_SIDES); -// LodConfig.CLIENT.graphics.brightnessMultiplier.set(1.0); -// LodConfig.CLIENT.graphics.saturationMultiplier.set(1.0); + LodConfig.CLIENT.graphics.vanillaOverdraw.set(VanillaOverdraw.HALF); // LodConfig.CLIENT.worldGenerator.distanceGenerationMode.set(DistanceGenerationMode.SURFACE); // LodConfig.CLIENT.graphics.lodChunkRenderDistance.set(64); diff --git a/src/main/java/com/seibel/lod/util/LodUtil.java b/src/main/java/com/seibel/lod/util/LodUtil.java index d993804f8..6c9c468ef 100644 --- a/src/main/java/com/seibel/lod/util/LodUtil.java +++ b/src/main/java/com/seibel/lod/util/LodUtil.java @@ -23,6 +23,8 @@ import java.io.File; import java.util.HashSet; import com.seibel.lod.builders.bufferBuilding.lodTemplates.Box; +import com.seibel.lod.config.LodConfig; +import com.seibel.lod.enums.VanillaOverdraw; import com.seibel.lod.objects.LodDimension; import com.seibel.lod.objects.RegionPos; import com.seibel.lod.wrappers.MinecraftWrapper; @@ -54,6 +56,12 @@ public class LodUtil { private static final MinecraftWrapper mc = MinecraftWrapper.INSTANCE; + /** + * vanilla render distances less than or equal to this will not allow partial + * overdraw. The VanillaOverdraw with either be ALWAYS or NEVER. + */ + public static final int MINIMUM_RENDER_DISTANCE_FOR_PARTIAL_OVERDRAW = 5; + /** The maximum number of LODs that can be rendered vertically */ public static final int MAX_NUMBER_OF_VERTICAL_LODS = 32; @@ -359,21 +367,66 @@ public class LodUtil int chunkRenderDist = mc.getRenderDistance(); ChunkPos centerChunk = new ChunkPos(playerPos); - // skip chunks that are already going to be rendered by Minecraft + + int skipRadius; + VanillaOverdraw overdraw = LodConfig.CLIENT.graphics.vanillaOverdraw.get(); + switch (overdraw) + { + case ALWAYS: + // don't skip any positions + return new HashSet(); + + case HALF: + // for small render distances just skip everything + // since the distance isn't far enough + // where partial skipping doesn't make sense + if (chunkRenderDist <= MINIMUM_RENDER_DISTANCE_FOR_PARTIAL_OVERDRAW) + { + // don't skip any positions + return new HashSet(); + } + else + { + // only skip positions that are greater than + // half the render distance + skipRadius = (int) Math.ceil(chunkRenderDist / 2.0); + } + break; + + default: + case NEVER: + // skip chunks in render distance that are rendered + // by vanilla minecraft + skipRadius = 0; + break; + } + + + // get the chunks that are going to be rendered by Minecraft HashSet posToSkip = getRenderedChunks(); - // go through each chunk within the normal view distance + + // apply special cases to those positions for (int x = centerChunk.x - chunkRenderDist; x < centerChunk.x + chunkRenderDist; x++) { for (int z = centerChunk.z - chunkRenderDist; z < centerChunk.z + chunkRenderDist; z++) { + // if the skipRadius is being used... + if (skipRadius != 0 && + ((x <= centerChunk.x - skipRadius || x >= centerChunk.x + skipRadius) + || (z <= centerChunk.z - skipRadius || z >= centerChunk.z + skipRadius))) + { + // ...remove everything outside the skipRadius + posToSkip.remove(new ChunkPos(x, z)); + continue; + } + + if (!lodDim.doesDataExist(LodUtil.CHUNK_DETAIL_LEVEL, x, z)) continue; long data = lodDim.getSingleData(LodUtil.CHUNK_DETAIL_LEVEL, x, z); - short lodAverageHeight = DataPointUtil.getHeight(data); - if (playerPos.getY() <= lodAverageHeight) { // don't draw LODs that are taller than the player