From cb6d4a14716ffd5278643bf09ec828a8fe2379ac Mon Sep 17 00:00:00 2001 From: NULL511 Date: Wed, 7 Feb 2024 09:44:33 -0500 Subject: [PATCH 01/17] separate camera and shadow frustum culling --- .../core/render/RenderBufferHandler.java | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java index ac06920ff..141e3295b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java @@ -68,6 +68,7 @@ public class RenderBufferHandler implements AutoCloseable public F3Screen.MultiDynamicMessage f3Message; + private final IDhApiCullingFrustum cameraFrustum; private int visibleBufferCount; private int culledBufferCount; private int shadowVisibleBufferCount; @@ -82,14 +83,8 @@ public class RenderBufferHandler implements AutoCloseable public RenderBufferHandler(LodQuadTree lodQuadTree) { this.lodQuadTree = lodQuadTree; - this.culledBufferCount = 0; - - IDhApiCullingFrustum coreFrustum = DhApi.overrides.get(IDhApiCullingFrustum.class, IOverrideInjector.CORE_PRIORITY); - if (coreFrustum == null) - { - DhApi.overrides.bind(IDhApiCullingFrustum.class, new DhFrustumBounds()); - } + this.cameraFrustum = new DhFrustumBounds(); this.f3Message = new F3Screen.MultiDynamicMessage( () -> @@ -238,8 +233,13 @@ public class RenderBufferHandler implements AutoCloseable // update the frustum if necessary boolean enableFrustumCulling = !Config.Client.Advanced.Graphics.AdvancedGraphics.disableFrustumCulling.get(); - IDhApiCullingFrustum frustum = DhApi.overrides.get(IDhApiCullingFrustum.class, IOverrideInjector.CORE_PRIORITY); - if (enableFrustumCulling) + boolean isShadowPass = (IRIS_ACCESSOR != null && IRIS_ACCESSOR.isRenderingShadowPass()); + + IDhApiCullingFrustum frustum = isShadowPass + ? DhApi.overrides.get(IDhApiCullingFrustum.class, IOverrideInjector.CORE_PRIORITY) + : cameraFrustum; + + if (enableFrustumCulling && frustum != null) { int worldMinY = clientLevelWrapper.getMinHeight(); int worldHeight = clientLevelWrapper.getHeight(); @@ -253,7 +253,6 @@ public class RenderBufferHandler implements AutoCloseable // Update the section list // //=========================// - boolean isShadowPass = (IRIS_ACCESSOR != null && IRIS_ACCESSOR.isRenderingShadowPass()); if (isShadowPass) { this.shadowCulledBufferCount = 0; From bddf9c85e81bcbdeebd7e67518a020c291c79597 Mon Sep 17 00:00:00 2001 From: NULL511 Date: Wed, 7 Feb 2024 10:01:25 -0500 Subject: [PATCH 02/17] lava ID fix --- .../seibel/distanthorizons/core/render/RenderBufferHandler.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java index 141e3295b..4cd37831a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java @@ -277,7 +277,7 @@ public class RenderBufferHandler implements AutoCloseable try { - if (enableFrustumCulling) + if (enableFrustumCulling && frustum != null) { DhLodPos lodBounds = renderSection.pos.getSectionBBoxPos(); int blockMinX = lodBounds.getMinX().toBlockWidth(); From 3f5622debf48b6f018ffe6323a0fb93abf1daa8f Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 10 Feb 2024 12:10:10 -0600 Subject: [PATCH 03/17] Add "database has been closed" to DbConnectionClosedException --- .../distanthorizons/core/sql/DbConnectionClosedException.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/sql/DbConnectionClosedException.java b/core/src/main/java/com/seibel/distanthorizons/core/sql/DbConnectionClosedException.java index 75a8b769d..b4e8cffb0 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/sql/DbConnectionClosedException.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/sql/DbConnectionClosedException.java @@ -20,7 +20,7 @@ public class DbConnectionClosedException extends SQLException { // TODO long term we should prevent using repos that are closed, but for now this is the easier solution String message = e.getMessage().toLowerCase(); - return message.contains("connection closed") || message.contains("pointer is closed"); + return message.contains("connection closed") || message.contains("pointer is closed") || message.contains("database has been closed"); } } From a9ccc6fa3489a881087759b28859dffef010c6a3 Mon Sep 17 00:00:00 2001 From: NULL511 Date: Sat, 10 Feb 2024 18:06:34 -0500 Subject: [PATCH 04/17] alter frustum culling api usage --- .../core/render/RenderBufferHandler.java | 43 ++++++++++++++----- .../core/render/renderer/LodRenderer.java | 9 +--- 2 files changed, 33 insertions(+), 19 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java index 4cd37831a..d0c80d1b6 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java @@ -24,6 +24,7 @@ import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiCullin import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector; +import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.f3.F3Screen; @@ -35,12 +36,15 @@ import com.seibel.distanthorizons.core.render.renderer.LodRenderer; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.util.objects.SortedArraySet; import com.seibel.distanthorizons.core.util.objects.quadTree.QuadNode; +import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IIrisAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverrideInjector; import com.seibel.distanthorizons.coreapi.util.math.Mat4f; +import com.seibel.distanthorizons.coreapi.util.math.Vec3d; import com.seibel.distanthorizons.coreapi.util.math.Vec3f; import org.apache.logging.log4j.Logger; +import org.joml.Matrix4f; import org.joml.Matrix4fc; import java.util.Comparator; @@ -56,6 +60,8 @@ public class RenderBufferHandler implements AutoCloseable { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); + private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); + private static final IIrisAccessor IRIS_ACCESSOR = ModAccessorInjector.INSTANCE.get(IIrisAccessor.class); /** contains all relevant data */ @@ -126,7 +132,7 @@ public class RenderBufferHandler implements AutoCloseable * TODO: This might get locked by update() causing move() call. Is there a way to avoid this? * Maybe dupe the base list and use atomic swap on render? Or is this not worth it? */ - public void buildRenderListAndUpdateSections(IClientLevelWrapper clientLevelWrapper, Matrix4fc matWorldViewProjection, Vec3f lookForwardVector) + public void buildRenderListAndUpdateSections(IClientLevelWrapper clientLevelWrapper, DhApiRenderParam renderEventParam, Vec3f lookForwardVector) { EDhDirection[] axisDirections = new EDhDirection[3]; @@ -234,17 +240,32 @@ public class RenderBufferHandler implements AutoCloseable // update the frustum if necessary boolean enableFrustumCulling = !Config.Client.Advanced.Graphics.AdvancedGraphics.disableFrustumCulling.get(); boolean isShadowPass = (IRIS_ACCESSOR != null && IRIS_ACCESSOR.isRenderingShadowPass()); - - IDhApiCullingFrustum frustum = isShadowPass - ? DhApi.overrides.get(IDhApiCullingFrustum.class, IOverrideInjector.CORE_PRIORITY) - : cameraFrustum; - if (enableFrustumCulling && frustum != null) + IDhApiCullingFrustum frustum = this.cameraFrustum; + + if (enableFrustumCulling) { - int worldMinY = clientLevelWrapper.getMinHeight(); - int worldHeight = clientLevelWrapper.getHeight(); - - frustum.update(worldMinY, worldMinY + worldHeight, new Mat4f(matWorldViewProjection)); + if (isShadowPass) { + frustum = DhApi.overrides.get(IDhApiCullingFrustum.class, IOverrideInjector.CORE_PRIORITY); + if (frustum == null) enableFrustumCulling = false; + } + else + { + int worldMinY = clientLevelWrapper.getMinHeight(); + int worldHeight = clientLevelWrapper.getHeight(); + + Vec3d cameraPos = MC_RENDER.getCameraExactPosition(); + + Matrix4fc matWorldView = new Matrix4f() + .setTransposed(renderEventParam.mcModelViewMatrix.getValuesAsArray()) + .translate(-(float) cameraPos.x, -(float) cameraPos.y, -(float) cameraPos.z); + + Matrix4fc matWorldViewProjection = new Matrix4f() + .setTransposed(renderEventParam.dhProjectionMatrix.getValuesAsArray()) + .mul(matWorldView); + + frustum.update(worldMinY, worldMinY + worldHeight, new Mat4f(matWorldViewProjection)); + } } @@ -277,7 +298,7 @@ public class RenderBufferHandler implements AutoCloseable try { - if (enableFrustumCulling && frustum != null) + if (enableFrustumCulling) { DhLodPos lodBounds = renderSection.pos.getSectionBBoxPos(); int blockMinX = lodBounds.getMinX().toBlockWidth(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java index dac8d049b..6f2148976 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/LodRenderer.java @@ -351,14 +351,7 @@ public class LodRenderer if (renderingFirstPass) { - Matrix4f matWorldView = new Matrix4f() - .setTransposed(MC_RENDER.getWorldViewMatrix().getValuesAsArray()); - - Matrix4fc matWorldViewProjection = new Matrix4f() - .setTransposed(renderEventParam.dhProjectionMatrix.getValuesAsArray()) - .mul(matWorldView); - - this.bufferHandler.buildRenderListAndUpdateSections(clientLevelWrapper, matWorldViewProjection, MC_RENDER.getLookAtVector()); + this.bufferHandler.buildRenderListAndUpdateSections(clientLevelWrapper, renderEventParam, MC_RENDER.getLookAtVector()); transparencyEnabled = Config.Client.Advanced.Graphics.Quality.transparency.get().transparencyEnabled; fakeOceanFloor = Config.Client.Advanced.Graphics.Quality.transparency.get().fakeTransparencyEnabled; From 65e053db0deafd5ec362f8ec9180e145f10e445f Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 10 Feb 2024 17:30:42 -0600 Subject: [PATCH 05/17] Add ColumnRenderBufferBuilder debug config options --- .../distanthorizons/core/config/Config.java | 21 +++++++ .../DebugColumnConfigEventHandler.java | 56 +++++++++++++++++++ .../ColumnRenderBufferBuilder.java | 26 +++++---- .../assets/distanthorizons/lang/en_us.json | 9 +++ 4 files changed, 101 insertions(+), 11 deletions(-) create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/DebugColumnConfigEventHandler.java diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index a24224c74..5eca235fe 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -30,6 +30,7 @@ import com.seibel.distanthorizons.core.config.types.*; import com.seibel.distanthorizons.core.config.types.enums.*; import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; +import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftSharedWrapper; import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.util.StringUtil; @@ -1160,6 +1161,26 @@ public class Config .addListener(UnsafeValuesConfigListener.INSTANCE) .build(); + public static ConfigEntry columnBuilderDebugEnable = new ConfigEntry.Builder() + .set(false) + .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) + .addListener(DebugColumnConfigEventHandler.INSTANCE) + .build(); + public static ConfigEntry columnBuilderDebugDetailLevel = new ConfigEntry.Builder() + .set((int) DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL) + .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) + .addListener(DebugColumnConfigEventHandler.INSTANCE) + .build(); + public static ConfigEntry columnBuilderDebugXPos = new ConfigEntry.Builder() + .set(0) + .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) + .addListener(DebugColumnConfigEventHandler.INSTANCE) + .build(); + public static ConfigEntry columnBuilderDebugZPos = new ConfigEntry.Builder() + .set(0) + .setAppearance(EConfigEntryAppearance.ONLY_IN_GUI) + .addListener(DebugColumnConfigEventHandler.INSTANCE) + .build(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/DebugColumnConfigEventHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/DebugColumnConfigEventHandler.java new file mode 100644 index 000000000..9e014f45f --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/eventHandlers/DebugColumnConfigEventHandler.java @@ -0,0 +1,56 @@ +/* + * 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.core.config.eventHandlers; + +import com.seibel.distanthorizons.api.DhApi; +import com.seibel.distanthorizons.api.enums.config.EHorizontalQuality; +import com.seibel.distanthorizons.api.enums.config.EMaxHorizontalResolution; +import com.seibel.distanthorizons.api.enums.config.EVerticalQuality; +import com.seibel.distanthorizons.api.enums.config.quickOptions.EQualityPreset; +import com.seibel.distanthorizons.api.enums.rendering.ETransparency; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderProxy; +import com.seibel.distanthorizons.core.config.Config; +import com.seibel.distanthorizons.core.config.ConfigEntryWithPresetOptions; +import com.seibel.distanthorizons.core.config.eventHandlers.presets.AbstractPresetConfigEventHandler; +import com.seibel.distanthorizons.core.config.listeners.ConfigChangeListener; +import com.seibel.distanthorizons.core.config.listeners.IConfigListener; +import com.seibel.distanthorizons.coreapi.interfaces.config.IConfigEntry; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; + +public class DebugColumnConfigEventHandler implements IConfigListener +{ + public static DebugColumnConfigEventHandler INSTANCE = new DebugColumnConfigEventHandler(); + + @Override + public void onConfigValueSet() + { + IDhApiRenderProxy renderProxy = DhApi.Delayed.renderProxy; + if (renderProxy != null) + { + renderProxy.clearRenderDataCache(); + } + } + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java index ebb7052a4..6b75be291 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/render/bufferBuilding/ColumnRenderBufferBuilder.java @@ -180,18 +180,22 @@ public class ColumnRenderBufferBuilder // Variable initialization EDebugRendering debugMode = Config.Client.Advanced.Debugging.debugRendering.get(); - // TODO make a config for this - // can be uncommented to limit which section positions are build and thus, rendered + // can be used to limit which section positions are build and thus, rendered // useful when debugging a specific section -// if (renderSource.sectionPos.getDetailLevel() == 6 -// && renderSource.sectionPos.getZ() == 0 && renderSource.sectionPos.getX() == 0) -// { -// int test = 0; -// } -// else -// { -// return; -// } + boolean enableColumnBufferLimit = Config.Client.Advanced.Debugging.columnBuilderDebugEnable.get(); + if (enableColumnBufferLimit) + { + if (renderSource.sectionPos.getDetailLevel() == Config.Client.Advanced.Debugging.columnBuilderDebugDetailLevel.get() + && renderSource.sectionPos.getX() == Config.Client.Advanced.Debugging.columnBuilderDebugXPos.get() + && renderSource.sectionPos.getZ() == Config.Client.Advanced.Debugging.columnBuilderDebugZPos.get()) + { + int test = 0; + } + else + { + return; + } + } byte detailLevel = renderSource.getDataDetailLevel(); for (int x = 0; x < ColumnRenderSource.SECTION_SIZE; x++) diff --git a/core/src/main/resources/assets/distanthorizons/lang/en_us.json b/core/src/main/resources/assets/distanthorizons/lang/en_us.json index 3adec012b..73b1ab284 100644 --- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json +++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json @@ -433,6 +433,15 @@ "distanthorizons.config.client.advanced.debugging.allowUnsafeValues.@tooltip": "If enabled, very limited config input validation will be performed. \n\nWarning: enabling this can cause instability or crashing, use at your own risk. \nNote: this option isn't saved between sessions.", + "distanthorizons.config.client.advanced.debugging.columnBuilderDebugEnable": + "Enable Column Builder Limiting", + "distanthorizons.config.client.advanced.debugging.columnBuilderDebugDetailLevel": + "Column Builder Limit - Detail Level", + "distanthorizons.config.client.advanced.debugging.columnBuilderDebugXPos": + "Column Builder Limit - X Pos", + "distanthorizons.config.client.advanced.debugging.columnBuilderDebugZPos": + "Column Builder Limit - Z Pos", + "distanthorizons.config.client.advanced.buffers": "Buffers", From 61c83e4c10c8f9c62356268d97d5c96d852c22c5 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 10 Feb 2024 18:06:24 -0600 Subject: [PATCH 06/17] GeneratedFullDataFileHandler refactor --- .../GeneratedFullDataFileHandler.java | 90 +++++++------------ 1 file changed, 34 insertions(+), 56 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java index 4b18ed3b1..16af4f26e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java @@ -20,10 +20,12 @@ package com.seibel.distanthorizons.core.file.fullDatafile; import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor; +import com.seibel.distanthorizons.core.dataObjects.fullData.sources.CompleteFullDataSource; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IFullDataSource; +import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IIncompleteFullDataSource; import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; -import com.seibel.distanthorizons.core.generation.MissingWorldGenPositionFinder; import com.seibel.distanthorizons.core.generation.IWorldGenerationQueue; +import com.seibel.distanthorizons.core.generation.MissingWorldGenPositionFinder; import com.seibel.distanthorizons.core.generation.tasks.IWorldGenTaskTracker; import com.seibel.distanthorizons.core.generation.tasks.WorldGenResult; import com.seibel.distanthorizons.core.level.DhLevel; @@ -31,9 +33,10 @@ import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.LodUtil; +import com.seibel.distanthorizons.core.util.TimerUtil; +import com.seibel.distanthorizons.core.util.objects.Reference; import org.apache.logging.log4j.Logger; -import java.lang.ref.WeakReference; import java.util.*; import java.util.concurrent.*; import java.util.concurrent.atomic.AtomicReference; @@ -48,8 +51,8 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler private final ArrayList onWorldGenTaskCompleteListeners = new ArrayList<>(); - /** Used to prevent data sources from being garbage collected before their world gen finishes. */ - private final ConcurrentHashMap generatingDataSourceByPos = new ConcurrentHashMap<>(); + /** Used to prevent world gen tasks from being queued multiple times. */ + private final Set generatingDataPos = Collections.newSetFromMap(new ConcurrentHashMap<>()); @@ -66,16 +69,20 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler //===========// @Override - public IFullDataSource get(DhSectionPos pos) + public IFullDataSource get(DhSectionPos pos) { return this.get(pos, true); } + public IFullDataSource get(DhSectionPos pos, boolean runWorldGenCheck) { IFullDataSource dataSource = super.get(pos); - // add world gen tasks for missing columns in the data source - // if this position hasn't already been queued for generation - IWorldGenerationQueue worldGenQueue = this.worldGenQueueRef.get(); - if (worldGenQueue != null && !this.generatingDataSourceByPos.containsKey(pos)) + if (runWorldGenCheck) { - this.queueWorldGenForMissingColumnsInDataSource(worldGenQueue, pos, dataSource); + // add world gen tasks for missing columns in the data source + // if this position hasn't already been queued for generation + IWorldGenerationQueue worldGenQueue = this.worldGenQueueRef.get(); + if (worldGenQueue != null && !this.generatingDataPos.contains(pos)) + { + this.queueWorldGenForMissingColumnsInDataSource(worldGenQueue, pos, dataSource); + } } return dataSource; @@ -101,17 +108,17 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler public void clearGenerationQueue() { this.worldGenQueueRef.set(null); - this.generatingDataSourceByPos.clear(); // clear the incomplete data sources + this.generatingDataPos.clear(); // clear the incomplete data sources } /** Can be used to remove positions that are outside the player's render distance. */ public void removeGenRequestIf(Function removeIf) { - this.generatingDataSourceByPos.forEach((pos, dataSource) -> + this.generatingDataPos.forEach((pos) -> { if (removeIf.apply(pos)) { - this.generatingDataSourceByPos.remove(pos); + this.generatingDataPos.remove(pos); } }); } @@ -131,35 +138,33 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler // events // //========// - private void onWorldGenTaskComplete(WorldGenResult genTaskResult, Throwable exception, GenTask genTask, DhSectionPos pos) + private void onWorldGenTaskComplete(WorldGenResult genTaskResult, Throwable exception) { if (exception != null) { // don't log shutdown exceptions if (!(exception instanceof CancellationException || exception.getCause() instanceof CancellationException)) { - LOGGER.error("Uncaught Gen Task Exception at " + pos + ":", exception); + LOGGER.error("Uncaught Gen Task Exception at [" + genTaskResult.pos + "], error: ["+ exception.getMessage() + "].", exception); } } else if (genTaskResult.success) { - this.fireOnGenPosSuccessListeners(pos); + this.fireOnGenPosSuccessListeners(genTaskResult.pos); return; } else { // generation didn't complete - LOGGER.debug("Gen Task Failed at " + pos); + LOGGER.debug("Gen Task Failed at " + genTaskResult.pos); } // if the generation task was split up into smaller positions, add the on-complete event to them for (CompletableFuture siblingFuture : genTaskResult.childFutures) { - siblingFuture.whenComplete((siblingGenTaskResult, siblingEx) -> this.onWorldGenTaskComplete(siblingGenTaskResult, siblingEx, genTask, pos)); + siblingFuture.whenComplete((siblingGenTaskResult, siblingEx) -> this.onWorldGenTaskComplete(siblingGenTaskResult, siblingEx)); } - - genTask.releaseStrongReference(); } private void fireOnGenPosSuccessListeners(DhSectionPos pos) @@ -188,20 +193,16 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler for (DhSectionPos genPos : genPosList) { // try not to re-queue already generating tasks - if (this.generatingDataSourceByPos.containsKey(genPos)) + if (this.generatingDataPos.contains(genPos)) { continue; } // queue each new gen task - GenTask genTask = new GenTask(dataSource.getSectionPos(), new WeakReference<>(dataSource)); + GenTask genTask = new GenTask(dataSource.getSectionPos()); CompletableFuture worldGenFuture = worldGenQueue.submitGenTask(genPos, dataSource.getDataDetailLevel(), genTask); - worldGenFuture.whenComplete((genTaskResult, ex) -> - { - this.onWorldGenTaskComplete(genTaskResult, ex, genTask, genPos); - this.onWorldGenTaskComplete(genTaskResult, ex, genTask, pos); - }); + worldGenFuture.whenComplete((genTaskResult, ex) -> this.onWorldGenTaskComplete(genTaskResult, ex)); taskFutureList.add(worldGenFuture); } @@ -210,11 +211,11 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler // mark the data source as generating if necessary if (taskFutureList.size() != 0) { - this.generatingDataSourceByPos.put(pos, dataSource); + this.generatingDataPos.add(pos); CompletableFuture.allOf(taskFutureList.toArray(new CompletableFuture[0])) .whenComplete((voidObj, ex) -> { - this.generatingDataSourceByPos.remove(pos); + this.generatingDataPos.remove(pos); }); } } @@ -225,52 +226,29 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler // helper classes // //================// + // TODO may not be needed private class GenTask implements IWorldGenTaskTracker { private final DhSectionPos pos; - // weak reference (probably) used to prevent overloading the GC when lots of gen tasks are created? // TODO do we still need a weak reference here? - private final WeakReference targetFullDataSourceRef; - // the target data source is where the generated chunk data will be put when completed - private IFullDataSource loadedTargetFullDataSource = null; - - - - public GenTask(DhSectionPos pos, WeakReference targetFullDataSourceRef) + public GenTask(DhSectionPos pos) { this.pos = pos; - this.targetFullDataSourceRef = targetFullDataSourceRef; } @Override - public boolean isMemoryAddressValid() { return this.targetFullDataSourceRef.get() != null; } + public boolean isMemoryAddressValid() { return true; } @Override public Consumer getChunkDataConsumer() { - if (this.loadedTargetFullDataSource == null) - { - this.loadedTargetFullDataSource = this.targetFullDataSourceRef.get(); - } - if (this.loadedTargetFullDataSource == null) - { - return null; - } - - return (chunkSizedFullDataSource) -> { - if (chunkSizedFullDataSource.getSectionPos().overlapsExactly(this.loadedTargetFullDataSource.getSectionPos())) - { - ((DhLevel) GeneratedFullDataFileHandler.this.level).updateDataSourcesWithChunkData(chunkSizedFullDataSource); - } + ((DhLevel) GeneratedFullDataFileHandler.this.level).updateDataSourcesWithChunkData(chunkSizedFullDataSource); }; } - - public void releaseStrongReference() { this.loadedTargetFullDataSource = null; } - } /** used by external event listeners */ From 89ea4c517200993d6e2a9883826d5fe328e921fe Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 10 Feb 2024 18:06:37 -0600 Subject: [PATCH 07/17] potentially fix world gen getting stuck --- .../core/file/fullDatafile/GeneratedFullDataFileHandler.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java index 16af4f26e..5336800bf 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java @@ -198,6 +198,11 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler continue; } + if (this.repo.existsWithPrimaryKey(genPos.serialize())) + { + continue; + } + // queue each new gen task GenTask genTask = new GenTask(dataSource.getSectionPos()); From 9ccbc792b4c3591b06deee89574d5c5751173c71 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 10 Feb 2024 18:08:08 -0600 Subject: [PATCH 08/17] Minor file handler refactor --- .../core/file/AbstractDataSourceHandler.java | 33 ++++++------------- .../fullDatafile/FullDataFileHandler.java | 8 ++++- .../core/pos/DhSectionPos.java | 30 +++++++++++++++++ 3 files changed, 47 insertions(+), 24 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/AbstractDataSourceHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/AbstractDataSourceHandler.java index b87b809c5..8f2ec3440 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/AbstractDataSourceHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/AbstractDataSourceHandler.java @@ -17,6 +17,7 @@ import java.io.ByteArrayOutputStream; import java.io.File; import java.io.IOException; import java.nio.channels.ClosedChannelException; +import java.util.ArrayList; import java.util.Enumeration; import java.util.Timer; import java.util.TimerTask; @@ -187,8 +188,6 @@ public abstract class AbstractDataSourceHandler updateDataSourcesWithChunkDataAsync(ChunkSizedFullDataAccessor chunkDataView) { - DhSectionPos pos = chunkDataView.getSectionPos().convertNewToDetailLevel(DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); - ThreadPoolExecutor executor = ThreadPools.getFileHandlerExecutor(); if (executor == null || executor.isTerminated()) { @@ -199,7 +198,15 @@ public abstract class AbstractDataSourceHandler this.updateDataSourcesRecursively(pos, chunkDataView), executor); + return CompletableFuture.runAsync(() -> + { + DhSectionPos bottomPos = chunkDataView.getSectionPos().convertNewToDetailLevel(DhSectionPos.SECTION_MINIMUM_DETAIL_LEVEL); + + bottomPos.forEachPosUpToDetailLevel( + this.topSectionDetailLevelRef.byteValue(), + (pos) -> this.updateDataSourceAtPos(pos, chunkDataView) ); + + }, executor); } catch (RejectedExecutionException ignore) { @@ -207,26 +214,6 @@ public abstract class AbstractDataSourceHandler this.topSectionDetailLevelRef.get()) - { - return; - } - - - DhSectionPos chunkSectionPos = chunkDataView.getSectionPos(); - LodUtil.assertTrue(chunkSectionPos.overlapsExactly(pos), "Update failed, chunk [" + chunkSectionPos + "] does not overlap section [" + pos + "]."); - - // update this pos - this.updateDataSourceAtPos(pos, chunkDataView); - - // recursively update the parent pos - DhSectionPos parentPos = pos.getParentPos(); - this.updateDataSourcesRecursively(parentPos, chunkDataView); - } protected void updateDataSourceAtPos(DhSectionPos pos, ChunkSizedFullDataAccessor chunkData) { // a lock is necessary to prevent two threads from writing to the same position at once, diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataFileHandler.java index 503214ef0..8f89ab2a5 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataFileHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/FullDataFileHandler.java @@ -89,7 +89,11 @@ public class FullDataFileHandler extends AbstractDataSourceHandler
@@ -314,6 +315,21 @@ public class DhSectionPos } } + /** Applies the given consumer to all children of the position at the given section detail level. */ + public void forEachChildDownToDetailLevel(byte minSectionDetailLevel, Function callback) + { + boolean stop = callback.apply(this); + if (stop || minSectionDetailLevel == this.detailLevel) + { + return; + } + + for (int i = 0; i < 4; i++) + { + this.getChildByIndex(i).forEachChildDownToDetailLevel(minSectionDetailLevel, callback); + } + } + /** Applies the given consumer to all children of the position at the given section detail level. */ public void forEachChildAtLevel(byte sectionDetailLevel, Consumer callback) { @@ -329,6 +345,20 @@ public class DhSectionPos } } + /** Applies the given consumer to all children of the position at the given section detail level. */ + public void forEachPosUpToDetailLevel(byte maxSectionDetailLevel, Consumer callback) + { + callback.accept(this); + if (maxSectionDetailLevel == this.detailLevel) + { + return; + } + + this.getParentPos().forEachPosUpToDetailLevel(maxSectionDetailLevel, callback); + } + + + //===============// From b4269afc9fba5cfeb1a619ae4a9de8c90f019fde Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 10 Feb 2024 21:37:59 -0600 Subject: [PATCH 09/17] Add IDhApiShadowCullingFrustum and a config for shadow culling --- .../config/client/IDhApiGraphicsConfig.java | 39 +++++++---- .../rendering/IDhApiShadowCullingFrustum.java | 40 +++++++++++ .../config/client/DhApiGraphicsConfig.java | 12 ++-- .../distanthorizons/core/config/Config.java | 35 ++++++---- .../core/render/RenderBufferHandler.java | 70 ++++++++++++------- .../assets/distanthorizons/lang/en_us.json | 14 ++-- 6 files changed, 150 insertions(+), 60 deletions(-) create mode 100644 api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShadowCullingFrustum.java diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java index 4e5fd3acc..eae828efc 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/config/client/IDhApiGraphicsConfig.java @@ -112,19 +112,6 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup // advanced graphic settings // //===========================// - /** - * Sets whether LODs outside the view frustum culling will - * be culled.

- * - * Disabling this will prevent LODs not rendering on the corner - * of the users vision and may fix issues if LODs appear to - * start/stop rendering incorrectly based on the camera direction, - * but will also reduce FPS. - * - * @since API 1.1.0 - */ - IDhApiConfigValue disableFrustumCulling(); - /** * Sets the distance used by the near clip plane to reduce * overdraw.
@@ -187,4 +174,30 @@ public interface IDhApiGraphicsConfig extends IDhApiConfigGroup */ IDhApiConfigValue lodShading(); + /** + * Sets whether LODs outside the view frustum culling will + * be culled.

+ * + * Disabling this will prevent LODs not rendering on the corner + * of the users vision and may fix issues if LODs appear to + * start/stop rendering incorrectly based on the camera direction, + * but will also reduce FPS. + * + * @since API 1.1.0 + * @see IDhApiGraphicsConfig#disableShadowFrustumCulling() + */ + IDhApiConfigValue disableFrustumCulling(); + + /** + * Identical to the other frustum culling option, except that it is + * only used when a shader mod is present using the DH API + * and the shadow pass is being rendered.

+ * + * Disable this if shadows render incorrectly. + * + * @since API 1.1.0 + * @see IDhApiGraphicsConfig#disableFrustumCulling() + */ + IDhApiConfigValue disableShadowFrustumCulling(); + } diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShadowCullingFrustum.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShadowCullingFrustum.java new file mode 100644 index 000000000..9fdd6cef3 --- /dev/null +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShadowCullingFrustum.java @@ -0,0 +1,40 @@ +/* + * 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.interfaces.override.rendering; + +import com.seibel.distanthorizons.api.enums.EDhApiDetailLevel; +import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; +import com.seibel.distanthorizons.coreapi.util.math.Mat4f; + +/** + * The culling frustum used during Distant Horizons' shadow pass + * if another mod has enabled Distant Horizons' shadow + * pass via the API. + * + * @see IDhApiCullingFrustum + * + * @author James Seibel + * @version 2024-2-10 + * @since API 1.1.0 + */ +public interface IDhApiShadowCullingFrustum extends IDhApiCullingFrustum +{ + // should be identical to the parent culling frustum +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java index aded64723..63b810521 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/external/methods/config/client/DhApiGraphicsConfig.java @@ -105,10 +105,6 @@ public class DhApiGraphicsConfig implements IDhApiGraphicsConfig // advanced graphic settings // //===========================// - @Override - public IDhApiConfigValue disableFrustumCulling() - { return new DhApiConfigValue(Config.Client.Advanced.Graphics.AdvancedGraphics.disableFrustumCulling); } - @Deprecated @Override public IDhApiConfigValue overdrawPrevention() @@ -150,6 +146,14 @@ public class DhApiGraphicsConfig implements IDhApiGraphicsConfig public IDhApiConfigValue lodShading() { return new DhApiConfigValue(Config.Client.Advanced.Graphics.AdvancedGraphics.lodShading); } + @Override + public IDhApiConfigValue disableFrustumCulling() + { return new DhApiConfigValue(Config.Client.Advanced.Graphics.AdvancedGraphics.disableFrustumCulling); } + + @Override + public IDhApiConfigValue disableShadowFrustumCulling() + { return new DhApiConfigValue(Config.Client.Advanced.Graphics.AdvancedGraphics.disableShadowPassFrustumCulling); } + } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java index 5eca235fe..f81eb8ce9 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/config/Config.java @@ -534,18 +534,6 @@ public class Config public static class AdvancedGraphics { - public static ConfigEntry disableFrustumCulling = new ConfigEntry.Builder() - .set(false) - .comment("" - + "If false LODs outside the player's camera \n" - + "aren't drawn, increasing GPU performance. \n" - + "\n" - + "If true all LODs are drawn, even those behind \n" - + "the player's camera, decreasing GPU performance. \n" - + "\n" - + "Disable this if you see LODs disappearing at the corners of your vision.") - .build(); - /** * @deprecated Use overdrawPrevention instead, will be removed when DH updates to MC 1.21
* After removal a float value will be used to control overdraw instead.
@@ -666,6 +654,29 @@ public class Config .setPerformance(EConfigEntryPerformance.NONE) .build(); + public static ConfigEntry disableFrustumCulling = new ConfigEntry.Builder() + .set(false) + .comment("" + + "If false LODs outside the player's camera \n" + + "aren't drawn, increasing GPU performance. \n" + + "\n" + + "If true all LODs are drawn, even those behind \n" + + "the player's camera, decreasing GPU performance. \n" + + "\n" + + "Disable this if you see LODs disappearing at the corners of your vision.") + .build(); + + public static ConfigEntry disableShadowPassFrustumCulling = new ConfigEntry.Builder() + .set(false) + .comment("" + + "Identical to the other frustum culling option\n" + + "only used when a shader mod is present using the DH API\n" + + "and the shadow pass is being rendered.\n" + + "\n" + + "Disable this if shadows render incorrectly.") + .build(); + + } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java index d0c80d1b6..8e47270f0 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java @@ -20,7 +20,9 @@ package com.seibel.distanthorizons.core.render; import com.seibel.distanthorizons.api.DhApi; +import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiCullingFrustum; +import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; import com.seibel.distanthorizons.core.config.Config; import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector; @@ -74,7 +76,6 @@ public class RenderBufferHandler implements AutoCloseable public F3Screen.MultiDynamicMessage f3Message; - private final IDhApiCullingFrustum cameraFrustum; private int visibleBufferCount; private int culledBufferCount; private int shadowVisibleBufferCount; @@ -90,7 +91,11 @@ public class RenderBufferHandler implements AutoCloseable { this.lodQuadTree = lodQuadTree; - this.cameraFrustum = new DhFrustumBounds(); + IDhApiCullingFrustum coreFrustum = DhApi.overrides.get(IDhApiCullingFrustum.class, IOverrideInjector.CORE_PRIORITY); + if (coreFrustum == null) + { + DhApi.overrides.bind(IDhApiCullingFrustum.class, new DhFrustumBounds()); + } this.f3Message = new F3Screen.MultiDynamicMessage( () -> @@ -237,35 +242,48 @@ public class RenderBufferHandler implements AutoCloseable - // update the frustum if necessary - boolean enableFrustumCulling = !Config.Client.Advanced.Graphics.AdvancedGraphics.disableFrustumCulling.get(); + //====================================// + // get and update the culling frustum // + //====================================// + + // get the culling frustum + boolean enableFrustumCulling; + IDhApiCullingFrustum frustum; boolean isShadowPass = (IRIS_ACCESSOR != null && IRIS_ACCESSOR.isRenderingShadowPass()); + if (isShadowPass) + { + enableFrustumCulling = !Config.Client.Advanced.Graphics.AdvancedGraphics.disableShadowPassFrustumCulling.get(); + frustum = DhApi.overrides.get(IDhApiShadowCullingFrustum.class); + } + else + { + enableFrustumCulling = !Config.Client.Advanced.Graphics.AdvancedGraphics.disableFrustumCulling.get(); + frustum = DhApi.overrides.get(IDhApiCullingFrustum.class); + } + // use the core frustum if no override is present + if (frustum == null) + { + frustum = DhApi.overrides.get(IDhApiCullingFrustum.class, IOverrideInjector.CORE_PRIORITY); + } - IDhApiCullingFrustum frustum = this.cameraFrustum; + // update the frustum if necessary if (enableFrustumCulling) { - if (isShadowPass) { - frustum = DhApi.overrides.get(IDhApiCullingFrustum.class, IOverrideInjector.CORE_PRIORITY); - if (frustum == null) enableFrustumCulling = false; - } - else - { - int worldMinY = clientLevelWrapper.getMinHeight(); - int worldHeight = clientLevelWrapper.getHeight(); - - Vec3d cameraPos = MC_RENDER.getCameraExactPosition(); - - Matrix4fc matWorldView = new Matrix4f() - .setTransposed(renderEventParam.mcModelViewMatrix.getValuesAsArray()) - .translate(-(float) cameraPos.x, -(float) cameraPos.y, -(float) cameraPos.z); - - Matrix4fc matWorldViewProjection = new Matrix4f() - .setTransposed(renderEventParam.dhProjectionMatrix.getValuesAsArray()) - .mul(matWorldView); - - frustum.update(worldMinY, worldMinY + worldHeight, new Mat4f(matWorldViewProjection)); - } + int worldMinY = clientLevelWrapper.getMinHeight(); + int worldHeight = clientLevelWrapper.getHeight(); + + Vec3d cameraPos = MC_RENDER.getCameraExactPosition(); + + Matrix4fc matWorldView = new Matrix4f() + .setTransposed(renderEventParam.mcModelViewMatrix.getValuesAsArray()) + .translate(-(float) cameraPos.x, -(float) cameraPos.y, -(float) cameraPos.z); + + Matrix4fc matWorldViewProjection = new Matrix4f() + .setTransposed(renderEventParam.dhProjectionMatrix.getValuesAsArray()) + .mul(matWorldView); + + frustum.update(worldMinY, worldMinY + worldHeight, new Mat4f(matWorldViewProjection)); } diff --git a/core/src/main/resources/assets/distanthorizons/lang/en_us.json b/core/src/main/resources/assets/distanthorizons/lang/en_us.json index 73b1ab284..b6a02475e 100644 --- a/core/src/main/resources/assets/distanthorizons/lang/en_us.json +++ b/core/src/main/resources/assets/distanthorizons/lang/en_us.json @@ -265,10 +265,6 @@ "distanthorizons.config.client.advanced.graphics.advancedGraphics": "Advanced Graphics Options", - "distanthorizons.config.client.advanced.graphics.advancedGraphics.disableFrustumCulling": - "Disable Frustum Culling", - "distanthorizons.config.client.advanced.graphics.advancedGraphics.disableFrustumCulling.@tooltip": - "If false LODs outside the player's camera \naren't drawn, increasing GPU performance. \n\nIf true all LODs are drawn, even those behind \nthe player's camera, decreasing GPU performance. \n\nDisable this if you see LODs disappearing at the corners of your vision.", "distanthorizons.config.client.advanced.graphics.advancedGraphics.overdrawPrevention": "Overdraw Prevention", "distanthorizons.config.client.advanced.graphics.advancedGraphics.overdrawPrevention.@tooltip": @@ -305,7 +301,15 @@ "LOD Shading", "distanthorizons.config.client.advanced.graphics.advancedGraphics.lodShading.@tooltip": "Defines how LODs should be shaded. \nCan be used to improve shader compatibility.", - + "distanthorizons.config.client.advanced.graphics.advancedGraphics.disableFrustumCulling": + "Disable Frustum Culling", + "distanthorizons.config.client.advanced.graphics.advancedGraphics.disableFrustumCulling.@tooltip": + "If false LODs outside the player's camera \naren't drawn, increasing GPU performance. \n\nIf true all LODs are drawn, even those behind \nthe player's camera, decreasing GPU performance. \n\nDisable this if you see LODs disappearing at the corners of your vision.", + "distanthorizons.config.client.advanced.graphics.advancedGraphics.disableShadowPassFrustumCulling": + "Disable Shadow Pass Frustum Culling", + "distanthorizons.config.client.advanced.graphics.advancedGraphics.disableShadowPassFrustumCulling.@tooltip": + "Identical to the other frustum culling option except that it is \nonly used when a shader mod is present using the DH API \nand the shadow pass is being rendered. \n\nDisable this if shadows render incorrectly.", + "distanthorizons.config.client.advanced.worldGenerator": "World Generator", From 97e7f0563640465c089625990e687fd9de8d6fb4 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 10 Feb 2024 21:58:20 -0600 Subject: [PATCH 10/17] Fix using the wrong near clip plane --- .../java/com/seibel/distanthorizons/core/util/RenderUtil.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java index d3cbd2097..2f5af7933 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java @@ -147,7 +147,7 @@ public class RenderUtil { // in James' testing a near clip plane distance of 2 blocks is enough to allow the fragment // culling to take effect instead of seeing the near clip plane. - float nearClipDist = 2f; //MC_RENDER.getRenderDistance() * LodUtil.CHUNK_WIDTH / 4.0f; //getNearClipPlaneDistanceInBlocks(partialTicks); + float nearClipDist = RenderUtil.getNearClipPlaneDistanceInBlocks(partialTicks); if (Config.Client.Advanced.Debugging.lodOnlyMode.get()) { nearClipDist = 0.1f; From c718733104e77e3e5284193e891d17dd140909ce Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 10 Feb 2024 22:02:15 -0600 Subject: [PATCH 11/17] Fix the API seeing the wrong far clip plane --- .../core/render/renderer/shaders/SSAOApplyShader.java | 4 ++-- .../com/seibel/distanthorizons/core/util/RenderUtil.java | 7 ++++--- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOApplyShader.java b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOApplyShader.java index 220441779..eb871c92b 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOApplyShader.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/renderer/shaders/SSAOApplyShader.java @@ -96,8 +96,8 @@ public class SSAOApplyShader extends AbstractShaderRenderer if (this.gFarUniform >= 0) { - float far = (float) ((RenderUtil.getFarClipPlaneDistanceInBlocks() + LodUtil.REGION_WIDTH) * Math.sqrt(2)); - GL32.glUniform1f(this.gFarUniform, far); + float farClipPlane = RenderUtil.getFarClipPlaneDistanceInBlocks(); + GL32.glUniform1f(this.gFarUniform, farClipPlane); } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java index 2f5af7933..4f4352643 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderUtil.java @@ -153,8 +153,7 @@ public class RenderUtil nearClipDist = 0.1f; } - int farPlaneDistanceInBlocks = RenderUtil.getFarClipPlaneDistanceInBlocks(); - float farClipDist = (float) ((farPlaneDistanceInBlocks + LodUtil.REGION_WIDTH) * Math.sqrt(2)); + float farClipDist = (float) RenderUtil.getFarClipPlaneDistanceInBlocks(); // Create a copy of the current matrix, so it won't be modified. Mat4f lodProj = mcProjMat.copy(); @@ -228,7 +227,9 @@ public class RenderUtil public static int getFarClipPlaneDistanceInBlocks() { int lodChunkDist = Config.Client.Advanced.Graphics.Quality.lodChunkRenderDistanceRadius.get(); - return lodChunkDist * LodUtil.CHUNK_WIDTH; + int lodBlockDist = lodChunkDist * LodUtil.CHUNK_WIDTH; + // sqrt 2 to prevent the corners from being cut off + return (int)((lodBlockDist + LodUtil.REGION_WIDTH) * Math.sqrt(2)); } /** @return false if LODs shouldn't be rendered for any reason */ From 5d4268e9026be42d0ed7db74fe55ed93107241bb Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 10 Feb 2024 22:05:46 -0600 Subject: [PATCH 12/17] Minor IDhLevel refactor and rename DhLevel -> AbstractDhLevel --- .../GeneratedFullDataFileHandler.java | 7 +------ .../{DhLevel.java => AbstractDhLevel.java} | 19 ++++++++++++------- .../core/level/DhClientLevel.java | 3 +-- .../core/level/DhClientServerLevel.java | 3 +-- .../core/level/DhServerLevel.java | 2 +- .../distanthorizons/core/level/IDhLevel.java | 2 ++ .../core/util/RenderDataPointUtil.java | 6 +++--- 7 files changed, 21 insertions(+), 21 deletions(-) rename core/src/main/java/com/seibel/distanthorizons/core/level/{DhLevel.java => AbstractDhLevel.java} (88%) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java index 5336800bf..d9bc2923a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/file/fullDatafile/GeneratedFullDataFileHandler.java @@ -20,21 +20,16 @@ package com.seibel.distanthorizons.core.file.fullDatafile; import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor; -import com.seibel.distanthorizons.core.dataObjects.fullData.sources.CompleteFullDataSource; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IFullDataSource; -import com.seibel.distanthorizons.core.dataObjects.fullData.sources.interfaces.IIncompleteFullDataSource; import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.generation.IWorldGenerationQueue; import com.seibel.distanthorizons.core.generation.MissingWorldGenPositionFinder; import com.seibel.distanthorizons.core.generation.tasks.IWorldGenTaskTracker; import com.seibel.distanthorizons.core.generation.tasks.WorldGenResult; -import com.seibel.distanthorizons.core.level.DhLevel; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.util.LodUtil; -import com.seibel.distanthorizons.core.util.TimerUtil; -import com.seibel.distanthorizons.core.util.objects.Reference; import org.apache.logging.log4j.Logger; import java.util.*; @@ -251,7 +246,7 @@ public class GeneratedFullDataFileHandler extends FullDataFileHandler { return (chunkSizedFullDataSource) -> { - ((DhLevel) GeneratedFullDataFileHandler.this.level).updateDataSourcesWithChunkData(chunkSizedFullDataSource); + GeneratedFullDataFileHandler.this.level.updateDataSourcesWithChunkData(chunkSizedFullDataSource); }; } } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java similarity index 88% rename from core/src/main/java/com/seibel/distanthorizons/core/level/DhLevel.java rename to core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index fe47c50dd..72e3324c7 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -27,18 +27,23 @@ import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; import java.util.concurrent.CompletableFuture; -public abstract class DhLevel implements IDhLevel +public abstract class AbstractDhLevel implements IDhLevel { - public final ChunkToLodBuilder chunkToLodBuilder; - protected DhLevel() { this.chunkToLodBuilder = new ChunkToLodBuilder(); } - - public abstract void updateDataSourcesWithChunkData(ChunkSizedFullDataAccessor data); - @Override - public int getMinY() { return 0; } + //=============// + // constructor // + //=============// + + protected AbstractDhLevel() { this.chunkToLodBuilder = new ChunkToLodBuilder(); } + + + + //=================// + // default methods // + //=================// @Override public void updateChunkAsync(IChunkWrapper chunk) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java index a7b235a90..1c69e5c83 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientLevel.java @@ -31,14 +31,13 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IProfilerWrap import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; import java.io.File; /** The level used when connected to a server */ -public class DhClientLevel extends DhLevel implements IDhClientLevel +public class DhClientLevel extends AbstractDhLevel implements IDhClientLevel { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java index d7da78f41..be70e9f95 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhClientServerLevel.java @@ -38,14 +38,13 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IBiomeWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; -import com.seibel.distanthorizons.coreapi.util.math.Mat4f; import org.apache.logging.log4j.Logger; import java.awt.*; import java.util.Iterator; /** The level used on a singleplayer world */ -public class DhClientServerLevel extends DhLevel implements IDhClientLevel, IDhServerLevel +public class DhClientServerLevel extends AbstractDhLevel implements IDhClientLevel, IDhServerLevel { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java index f88052daf..9b12a3627 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/DhServerLevel.java @@ -30,7 +30,7 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.ILevelWrapper; import com.seibel.distanthorizons.core.wrapperInterfaces.world.IServerLevelWrapper; import org.apache.logging.log4j.Logger; -public class DhServerLevel extends DhLevel implements IDhServerLevel +public class DhServerLevel extends AbstractDhLevel implements IDhServerLevel { private static final Logger LOGGER = DhLoggerBuilder.getLogger(); public final ServerLevelModule serverside; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java index 1ae9d402b..f614dad86 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/IDhLevel.java @@ -19,6 +19,7 @@ package com.seibel.distanthorizons.core.level; +import com.seibel.distanthorizons.core.dataObjects.fullData.accessor.ChunkSizedFullDataAccessor; import com.seibel.distanthorizons.core.file.fullDatafile.IFullDataSourceProvider; import com.seibel.distanthorizons.core.file.structure.AbstractSaveStructure; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; @@ -44,5 +45,6 @@ public interface IDhLevel extends AutoCloseable boolean hasSkyLight(); + void updateDataSourcesWithChunkData(ChunkSizedFullDataAccessor data); } diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java index 4d00bf0e7..1a110fc2a 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointUtil.java @@ -19,7 +19,7 @@ package com.seibel.distanthorizons.core.util; -import com.seibel.distanthorizons.core.level.DhLevel; +import com.seibel.distanthorizons.core.level.AbstractDhLevel; import com.seibel.distanthorizons.core.logging.SpamReducedLogger; import com.seibel.distanthorizons.core.dataObjects.render.columnViews.ColumnArrayView; import com.seibel.distanthorizons.core.dataObjects.render.columnViews.IColumnDataView; @@ -174,9 +174,9 @@ public class RenderDataPointUtil return dataPoint & ~(HEIGHT_SHIFTED_MASK | DEPTH_SHIFTED_MASK) | height | depth; } - /** AKA the ending/top/highest Y value above {@link DhLevel#getMinY()} */ + /** AKA the ending/top/highest Y value above {@link AbstractDhLevel#getMinY()} */ public static short getYMax(long dataPoint) { return (short) ((dataPoint >>> HEIGHT_SHIFT) & HEIGHT_MASK); } - /** AKA the starting/bottom/lowest Y value above {@link DhLevel#getMinY()} */ + /** AKA the starting/bottom/lowest Y value above {@link AbstractDhLevel#getMinY()} */ public static short getYMin(long dataPoint) { return (short) ((dataPoint >>> DEPTH_SHIFT) & DEPTH_MASK); } public static short getAlpha(long dataPoint) { return (short) ((((dataPoint >>> ALPHA_SHIFT) & ALPHA_MASK) << ALPHA_DOWNSIZE_SHIFT) | 0b1111); } From cc134092ed8d92ed73fefcc92c1d6e1fcffd1c0e Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 11 Feb 2024 14:56:12 -0600 Subject: [PATCH 13/17] Default to no culling for the shadow pass --- .../rendering/IDhApiShadowCullingFrustum.java | 5 ++- .../core/{pos => render}/DhFrustumBounds.java | 2 +- .../core/render/NeverCullFrustum.java | 40 +++++++++++++++++++ .../core/render/RenderBufferHandler.java | 19 ++++----- 4 files changed, 55 insertions(+), 11 deletions(-) rename core/src/main/java/com/seibel/distanthorizons/core/{pos => render}/DhFrustumBounds.java (97%) create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/render/NeverCullFrustum.java diff --git a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShadowCullingFrustum.java b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShadowCullingFrustum.java index 9fdd6cef3..5759587a0 100644 --- a/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShadowCullingFrustum.java +++ b/api/src/main/java/com/seibel/distanthorizons/api/interfaces/override/rendering/IDhApiShadowCullingFrustum.java @@ -26,7 +26,10 @@ import com.seibel.distanthorizons.coreapi.util.math.Mat4f; /** * The culling frustum used during Distant Horizons' shadow pass * if another mod has enabled Distant Horizons' shadow - * pass via the API. + * pass via the API.

+ * + * If no {@link IDhApiShadowCullingFrustum} is bound then culling + * will not be done in the shadow pass. * * @see IDhApiCullingFrustum * diff --git a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhFrustumBounds.java b/core/src/main/java/com/seibel/distanthorizons/core/render/DhFrustumBounds.java similarity index 97% rename from core/src/main/java/com/seibel/distanthorizons/core/pos/DhFrustumBounds.java rename to core/src/main/java/com/seibel/distanthorizons/core/render/DhFrustumBounds.java index 62d3aac75..cf18751b8 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/pos/DhFrustumBounds.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/DhFrustumBounds.java @@ -1,4 +1,4 @@ -package com.seibel.distanthorizons.core.pos; +package com.seibel.distanthorizons.core.render; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiCullingFrustum; import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverrideInjector; diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/NeverCullFrustum.java b/core/src/main/java/com/seibel/distanthorizons/core/render/NeverCullFrustum.java new file mode 100644 index 000000000..971b03b50 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/NeverCullFrustum.java @@ -0,0 +1,40 @@ +package com.seibel.distanthorizons.core.render; + +import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiCullingFrustum; +import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverrideInjector; +import com.seibel.distanthorizons.coreapi.util.math.Mat4f; + +/** + * Dummy {@link IDhApiCullingFrustum} that allows everything through.
+ * Useful when a frustum is required, but culling shouldn't be done. + */ +public class NeverCullFrustum implements IDhApiCullingFrustum +{ + //=============// + // constructor // + //=============// + + public NeverCullFrustum() { } + + + + //=========// + // methods // + //=========// + + @Override + public void update(int worldMinBlockY, int worldMaxBlockY, Mat4f dhWorldViewProjection) { /* update isn't needed */ } + + @Override + public boolean intersects(int lodBlockPosMinX, int lodBlockPosMinZ, int lodBlockWidth, int lodDetailLevel) { return true; } + + + + //=====================// + // overridable methods // + //=====================// + + @Override + public int getPriority() { return IOverrideInjector.CORE_PRIORITY; } + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java index 8e47270f0..8fb1da7a4 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/RenderBufferHandler.java @@ -20,7 +20,6 @@ package com.seibel.distanthorizons.core.render; import com.seibel.distanthorizons.api.DhApi; -import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiCullingFrustum; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum; import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; @@ -30,7 +29,6 @@ import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector; import com.seibel.distanthorizons.core.enums.EDhDirection; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.f3.F3Screen; -import com.seibel.distanthorizons.core.pos.DhFrustumBounds; import com.seibel.distanthorizons.core.pos.DhLodPos; import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.pos.Pos2D; @@ -91,12 +89,20 @@ public class RenderBufferHandler implements AutoCloseable { this.lodQuadTree = lodQuadTree; - IDhApiCullingFrustum coreFrustum = DhApi.overrides.get(IDhApiCullingFrustum.class, IOverrideInjector.CORE_PRIORITY); - if (coreFrustum == null) + IDhApiCullingFrustum coreCameraFrustum = DhApi.overrides.get(IDhApiCullingFrustum.class, IOverrideInjector.CORE_PRIORITY); + if (coreCameraFrustum == null) { DhApi.overrides.bind(IDhApiCullingFrustum.class, new DhFrustumBounds()); } + // by default the shadow pass shouldn't have any frustum culling + IDhApiShadowCullingFrustum coreShadowFrustum = DhApi.overrides.get(IDhApiShadowCullingFrustum.class, IOverrideInjector.CORE_PRIORITY); + if (coreShadowFrustum == null) + { + DhApi.overrides.bind(IDhApiShadowCullingFrustum.class, new NeverCullFrustum()); + } + + this.f3Message = new F3Screen.MultiDynamicMessage( () -> { @@ -260,11 +266,6 @@ public class RenderBufferHandler implements AutoCloseable enableFrustumCulling = !Config.Client.Advanced.Graphics.AdvancedGraphics.disableFrustumCulling.get(); frustum = DhApi.overrides.get(IDhApiCullingFrustum.class); } - // use the core frustum if no override is present - if (frustum == null) - { - frustum = DhApi.overrides.get(IDhApiCullingFrustum.class, IOverrideInjector.CORE_PRIORITY); - } // update the frustum if necessary From b8f90ddc551302b5b9202375e1cc4b14e4e49cfc Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 11 Feb 2024 16:39:03 -0600 Subject: [PATCH 14/17] Add SharedApi.isChunkAtBlockPosAlreadyUpdating() --- .../core/api/internal/SharedApi.java | 23 ++++++++++++------- 1 file changed, 15 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java index d73975f33..b0499375d 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/SharedApi.java @@ -26,10 +26,10 @@ import com.seibel.distanthorizons.core.generation.DhLightingEngine; import com.seibel.distanthorizons.core.level.IDhLevel; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; import com.seibel.distanthorizons.core.logging.f3.F3Screen; +import com.seibel.distanthorizons.core.pos.DhBlockPos2D; import com.seibel.distanthorizons.core.pos.DhChunkPos; import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; import com.seibel.distanthorizons.core.util.LodUtil; -import com.seibel.distanthorizons.core.util.ThreadUtil; import com.seibel.distanthorizons.core.util.TimerUtil; import com.seibel.distanthorizons.core.util.objects.Pair; import com.seibel.distanthorizons.core.util.threading.ThreadPools; @@ -55,7 +55,7 @@ public class SharedApi private static final Logger LOGGER = DhLoggerBuilder.getLogger(); private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class); - private static final Set UPDATING_CHUNK_SET = ConcurrentHashMap.newKeySet(); + private static final Set UPDATING_CHUNK_POS_SET = ConcurrentHashMap.newKeySet(); /** how many chunks can be queued for updating per thread, used to prevent updates from infinitely pilling up if the user flys around extremely fast */ private static final int MAX_UPDATING_CHUNK_COUNT_PER_THREAD = 500; private static final int MIN_MS_BETWEEN_OVERLOADED_LOG_MESSAGE = 5_000; @@ -80,7 +80,7 @@ public class SharedApi this.f3Message = new F3Screen.DynamicMessage(() -> { int maxUpdateCount = MAX_UPDATING_CHUNK_COUNT_PER_THREAD * Config.Client.Advanced.MultiThreading.numberOfLodBuilderThreads.get(); - return LodUtil.formatLog("Queued chunk updates: " + UPDATING_CHUNK_SET.size() + " / " + maxUpdateCount); + return LodUtil.formatLog("Queued chunk updates: " + UPDATING_CHUNK_POS_SET.size() + " / " + maxUpdateCount); }); } @@ -139,6 +139,13 @@ public class SharedApi // chunk update // //==============// + /** + * Used to prevent getting a full chunk from MC if it isn't necessary.
+ * This is important since asking MC for a chunk is slow and may block the render thread. + */ + public static boolean isChunkAtBlockPosAlreadyUpdating(int blockPosX, int blockPosZ) { return UPDATING_CHUNK_POS_SET.contains(new DhChunkPos(new DhBlockPos2D(blockPosX, blockPosZ))); } + + /** handles both block place and break events */ public void chunkBlockChangedEvent(IChunkWrapper chunk, ILevelWrapper level) { this.applyChunkUpdate(chunk, level, true); } @@ -202,7 +209,7 @@ public class SharedApi // task limiting check // //=====================// - int currentQueueCount = UPDATING_CHUNK_SET.size(); + int currentQueueCount = UPDATING_CHUNK_POS_SET.size(); int maxQueueCount = MAX_UPDATING_CHUNK_COUNT_PER_THREAD * Config.Client.Advanced.MultiThreading.numberOfLodBuilderThreads.get(); if (currentQueueCount >= maxQueueCount) { @@ -220,12 +227,12 @@ public class SharedApi } // prevent duplicate update requests - if (UPDATING_CHUNK_SET.contains(chunkWrapper.getChunkPos())) + if (UPDATING_CHUNK_POS_SET.contains(chunkWrapper.getChunkPos())) { // this chunk is already being updated return; } - UPDATING_CHUNK_SET.add(chunkWrapper.getChunkPos()); + UPDATING_CHUNK_POS_SET.add(chunkWrapper.getChunkPos()); @@ -339,13 +346,13 @@ public class SharedApi CHUNK_UPDATE_TIMER.schedule(new TimerTask() { @Override - public void run() { UPDATING_CHUNK_SET.remove(chunkWrapper.getChunkPos()); } + public void run() { UPDATING_CHUNK_POS_SET.remove(chunkWrapper.getChunkPos()); } }, updateTimeoutInSec * 1000L); } else { // instantly allow this chunk to be updated again - UPDATING_CHUNK_SET.remove(chunkWrapper.getChunkPos()); + UPDATING_CHUNK_POS_SET.remove(chunkWrapper.getChunkPos()); } } }); From 7df442878dc533a4b85623c9bb5dd416e401b2b9 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 11 Feb 2024 18:29:47 -0600 Subject: [PATCH 15/17] Fix NeverCullFrustum casting error --- .../seibel/distanthorizons/core/render/NeverCullFrustum.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/NeverCullFrustum.java b/core/src/main/java/com/seibel/distanthorizons/core/render/NeverCullFrustum.java index 971b03b50..7e10b0b44 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/NeverCullFrustum.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/NeverCullFrustum.java @@ -1,6 +1,7 @@ package com.seibel.distanthorizons.core.render; import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiCullingFrustum; +import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum; import com.seibel.distanthorizons.coreapi.interfaces.dependencyInjection.IOverrideInjector; import com.seibel.distanthorizons.coreapi.util.math.Mat4f; @@ -8,7 +9,7 @@ import com.seibel.distanthorizons.coreapi.util.math.Mat4f; * Dummy {@link IDhApiCullingFrustum} that allows everything through.
* Useful when a frustum is required, but culling shouldn't be done. */ -public class NeverCullFrustum implements IDhApiCullingFrustum +public class NeverCullFrustum implements IDhApiCullingFrustum, IDhApiShadowCullingFrustum { //=============// // constructor // From 5c30d077ddf6cf21e5ba2b47c18a2c98d3d15738 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 11 Feb 2024 20:16:23 -0600 Subject: [PATCH 16/17] Add comments about corrupted data in full data transformer --- .../FullDataToRenderDataTransformer.java | 21 ++++++++++++++++++- 1 file changed, 20 insertions(+), 1 deletion(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java index 6e0c81d27..a3b3d54d1 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/dataObjects/transformers/FullDataToRenderDataTransformer.java @@ -243,6 +243,21 @@ public class FullDataToRenderDataTransformer int id = FullDataPointUtil.getId(fullData); int light = FullDataPointUtil.getLight(fullData); + // TODO how should corrupted data be handled? + // TODO why is the full data corrupted in the first place? FullDataPointUtil hasn't been changed in a long time, could one of the full data point objects be corrupted? + // TODO if either of these happen the ID might also be invalid + //if (bottomY + blockHeight > 300) + //{ + // // this data point is too tall, it's probably a monolith + // int k = 0; + // throw new RuntimeException(); + //} + //if (light > 16 || light < 0) + //{ + // // light is out of range + // throw new RuntimeException(); + //} + IBiomeWrapper biome; IBlockStateWrapper block; try @@ -257,7 +272,11 @@ public class FullDataToRenderDataTransformer { brokenPos.add(fullDataMapping.getPos()); String dimName = level.getLevelWrapper().getDimensionType().getDimensionName(); - LOGGER.warn("Unable to get data point with id ["+id+"] (Max possible ID: ["+fullDataMapping.getMaxValidId()+"]) for pos ["+fullDataMapping.getPos()+"] in dimension ["+dimName+"]. Error: ["+e.getMessage()+"]. Further errors for this position won't be logged."); + LOGGER.warn("Unable to get data point with id ["+id+"] " + + "(Max possible ID: ["+fullDataMapping.getMaxValidId()+"]) " + + "for pos ["+fullDataMapping.getPos()+"] in dimension ["+dimName+"]. " + + "Error: ["+e.getMessage()+"]. " + + "Further errors for this position won't be logged."); } // skip rendering broken data From d7c96bbba4895009f851c0affe1ab6ed6d8395be Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sun, 11 Feb 2024 21:31:24 -0600 Subject: [PATCH 17/17] Fix ocean floors showing at very low detail levels --- .../core/util/RenderDataPointReducingList.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointReducingList.java b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointReducingList.java index 344c58dd8..773707bad 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointReducingList.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/util/RenderDataPointReducingList.java @@ -832,8 +832,8 @@ public class RenderDataPointReducingList return RenderDataPointUtil.createVoidDataPoint(); } - long highest; - int lowest; + long highestDataPoint; + long lowestDataPoint; int index = 0; //first loop: find the first visible segment. foundVisible: @@ -843,8 +843,8 @@ public class RenderDataPointReducingList long dataPoint = view.get(index); if (isDataVisible(dataPoint)) { - highest = dataPoint; - lowest = RenderDataPointUtil.getYMin(dataPoint); + highestDataPoint = dataPoint; + lowestDataPoint = dataPoint; break foundVisible; } } @@ -858,13 +858,15 @@ public class RenderDataPointReducingList long dataPoint = view.get(index); if (isDataVisible(dataPoint)) { - int y = RenderDataPointUtil.getYMin(dataPoint); - if (y > highest) highest = dataPoint; - else if (y < lowest) lowest = y; + int yMax = RenderDataPointUtil.getYMax(dataPoint); + int yMin = RenderDataPointUtil.getYMin(dataPoint); + + if (yMax > RenderDataPointUtil.getYMax(highestDataPoint)) highestDataPoint = dataPoint; + else if (yMin < RenderDataPointUtil.getYMin(lowestDataPoint)) lowestDataPoint = dataPoint; } } - return (highest & ~RenderDataPointUtil.DEPTH_SHIFTED_MASK) | ((lowest & RenderDataPointUtil.DEPTH_MASK) << RenderDataPointUtil.DEPTH_SHIFT); + return (highestDataPoint & ~RenderDataPointUtil.DEPTH_SHIFTED_MASK) | (RenderDataPointUtil.getYMin(lowestDataPoint) << RenderDataPointUtil.DEPTH_SHIFT); }