From 71f1dce9564cb0de2c647f86a8eb06d621b6da91 Mon Sep 17 00:00:00 2001 From: James Seibel Date: Sat, 6 Sep 2025 10:54:08 -0500 Subject: [PATCH] Add unexplored fog --- .../core/level/AbstractDhLevel.java | 43 ++++++++- .../distanthorizons/core/level/IDhLevel.java | 6 ++ .../core/render/LodRenderSection.java | 88 +++++++++++++------ 3 files changed, 107 insertions(+), 30 deletions(-) diff --git a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java index eddab3590..96ea06a5e 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/level/AbstractDhLevel.java @@ -19,7 +19,9 @@ package com.seibel.distanthorizons.core.level; +import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiChunkModifiedEvent; +import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.file.fullDatafile.DelayedFullDataSourceSaveCache; import com.seibel.distanthorizons.core.generation.DhLightingEngine; @@ -29,6 +31,7 @@ import com.seibel.distanthorizons.core.pos.DhSectionPos; import com.seibel.distanthorizons.core.pos.blockPos.DhBlockPos; import com.seibel.distanthorizons.core.render.renderer.generic.CloudRenderHandler; import com.seibel.distanthorizons.core.render.renderer.generic.GenericObjectRenderer; +import com.seibel.distanthorizons.core.render.renderer.generic.GenericRenderObjectFactory; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.sql.dto.ChunkHashDTO; import com.seibel.distanthorizons.core.sql.repo.AbstractDhRepo; @@ -38,6 +41,7 @@ import com.seibel.distanthorizons.core.util.KeyedLockContainer; import com.seibel.distanthorizons.core.util.LodUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.chunk.IChunkWrapper; import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector; +import com.seibel.distanthorizons.coreapi.ModInfo; import org.apache.logging.log4j.Logger; import org.jetbrains.annotations.Nullable; @@ -73,13 +77,15 @@ public abstract class AbstractDhLevel implements IDhLevel @Nullable protected CloudRenderHandler cloudRenderHandler; + private IDhApiRenderableBoxGroup unexploredFogRenderableBoxGroup; + //=============// // constructor // //=============// - protected AbstractDhLevel() { } + protected AbstractDhLevel() { } /** * Creating the repos requires access to the level file, which isn't @@ -361,6 +367,32 @@ public abstract class AbstractDhLevel implements IDhLevel + //================// + // unexplored fog // + //================// + + public IDhApiRenderableBoxGroup getUnexploredFogRenderableBoxGroup() + { + if (this.unexploredFogRenderableBoxGroup == null) + { + this.unexploredFogRenderableBoxGroup = GenericRenderObjectFactory.INSTANCE.createAbsolutePositionedGroup(ModInfo.NAME+":UnexploredFog", new ArrayList<>(512)); + this.unexploredFogRenderableBoxGroup.setBlockLight(LodUtil.MIN_MC_LIGHT); + this.unexploredFogRenderableBoxGroup.setSkyLight(LodUtil.MAX_MC_LIGHT); + this.unexploredFogRenderableBoxGroup.setSsaoEnabled(true); + this.unexploredFogRenderableBoxGroup.setShading(DhApiRenderableBoxGroupShading.getDefaultShaded()); + + GenericObjectRenderer genericRenderer = this.getGenericRenderer(); + if (genericRenderer != null) + { + genericRenderer.add(this.unexploredFogRenderableBoxGroup); + } + } + + return this.unexploredFogRenderableBoxGroup; + } + + + //================// // base overrides // //================// @@ -377,6 +409,15 @@ public abstract class AbstractDhLevel implements IDhLevel this.beaconBeamRepo.close(); } + + GenericObjectRenderer genericRenderer = this.getGenericRenderer(); + if (genericRenderer != null + && this.unexploredFogRenderableBoxGroup != null) + { + genericRenderer.remove(this.unexploredFogRenderableBoxGroup.getId()); + } + + this.delayedFullDataSourceSaveCache.close(); } 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 5857c836e..b6c1f683e 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.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.core.dataObjects.fullData.sources.FullDataSourceV2; import com.seibel.distanthorizons.core.file.fullDatafile.FullDataSourceProviderV2; import com.seibel.distanthorizons.core.file.fullDatafile.GeneratedFullDataSourceProvider; @@ -61,9 +62,14 @@ public interface IDhLevel extends AutoCloseable, GeneratedFullDataSourceProvider void updateBeaconBeamsForChunkPos(DhChunkPos chunkPos, List activeBeamList); void updateBeaconBeamsForSectionPos(long sectionPos, List activeBeamList); + /** @return null on server-only levels */ @Nullable BeaconBeamRepo getBeaconBeamRepo(); + /** @return null on server-only levels */ + @Nullable + IDhApiRenderableBoxGroup getUnexploredFogRenderableBoxGroup(); + FullDataSourceProviderV2 getFullDataProvider(); ISaveStructure getSaveStructure(); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java index 750295574..6203cf64c 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/render/LodRenderSection.java @@ -21,7 +21,6 @@ package com.seibel.distanthorizons.core.render; import com.google.common.base.Suppliers; import com.google.common.cache.Cache; -import com.seibel.distanthorizons.api.DhApi; import com.seibel.distanthorizons.api.enums.rendering.EDhApiBlockMaterial; import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup; import com.seibel.distanthorizons.api.objects.math.DhApiVec3d; @@ -45,14 +44,12 @@ import com.seibel.distanthorizons.core.render.renderer.IDebugRenderable; import com.seibel.distanthorizons.core.dataObjects.render.bufferBuilding.ColumnRenderBuffer; import com.seibel.distanthorizons.core.render.renderer.DebugRenderer; import com.seibel.distanthorizons.core.render.renderer.generic.BeaconRenderHandler; -import com.seibel.distanthorizons.core.render.renderer.generic.RenderableBoxGroup; import com.seibel.distanthorizons.core.sql.dto.BeaconBeamDTO; import com.seibel.distanthorizons.core.sql.repo.BeaconBeamRepo; import com.seibel.distanthorizons.core.util.KeyedLockContainer; import com.seibel.distanthorizons.core.util.threading.PriorityTaskPicker; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper; -import com.seibel.distanthorizons.coreapi.ModInfo; import com.seibel.distanthorizons.coreapi.util.MathUtil; import it.unimi.dsi.fastutil.longs.LongArrayList; import org.apache.logging.log4j.Logger; @@ -88,7 +85,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable private final Cache cachedRenderSourceByPos; private final AtomicInteger uploadTaskCountRef; - private final IDhApiRenderableBoxGroup fogRenderableBoxGroup; + private final DhApiRenderableBox unexploredFogRenderableBox; /** * contains the list of beacons currently being rendered in this section @@ -162,35 +159,40 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable this.fullDataSourceProvider = fullDataSourceProvider; this.uploadTaskCountRef = uploadTaskCountRef; + this.beaconRenderHandler = this.quadTree.beaconRenderHandler; + this.beaconBeamRepo = this.level.getBeaconBeamRepo(); + this.unexploredFogRenderableBox = this.createUnexploredFogRenderableBox(); + + DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus); + } + private DhApiRenderableBox createUnexploredFogRenderableBox() + { // width float fogWidthInBlocks = (float) DhSectionPos.getBlockWidth(this.pos); - // random height + // pseudo random height (should be consistent for a given position) int fogHeightRange = (int) ((this.level.getMaxY() - this.level.getMinY()) * 0.25); int halfFogHeightRange = fogHeightRange / 2; float randomHeightModifier = (float) (DhSectionPos.hashCode(this.pos) % fogHeightRange) - halfFogHeightRange; - // random color + // pseudo random color (should be consistent for a given position) int randomColorModifier = (DhSectionPos.hashCode(this.pos) % 30) - 15; int randomGrayColorValue = 90 + randomColorModifier; randomGrayColorValue = MathUtil.clamp(1, randomGrayColorValue, 256); // clamp to prevent accidental out-of-range colors - - ArrayList boxList = new ArrayList<>(); - boxList.add(new DhApiRenderableBox( - new DhApiVec3d(0,0,0), - new DhApiVec3d(fogWidthInBlocks, this.level.getMaxY() + randomHeightModifier, fogWidthInBlocks), - new Color(randomGrayColorValue, randomGrayColorValue, randomGrayColorValue), EDhApiBlockMaterial.UNKNOWN)); - this.fogRenderableBoxGroup = new RenderableBoxGroup( - ModInfo.NAME + ":UnexploredFog", - new DhApiVec3d(DhSectionPos.getMinCornerBlockX(this.pos), level.getMinY(), DhSectionPos.getMinCornerBlockZ(this.pos)), - boxList, true); - this.beaconRenderHandler = this.quadTree.beaconRenderHandler; - this.beaconBeamRepo = this.level.getBeaconBeamRepo(); + return new DhApiRenderableBox( + // min pos + new DhApiVec3d(DhSectionPos.getMinCornerBlockX(this.pos), + 0, + DhSectionPos.getMinCornerBlockZ(this.pos)), + // max pos + new DhApiVec3d(DhSectionPos.getMinCornerBlockX(this.pos) + fogWidthInBlocks, + this.level.getMaxY() + randomHeightModifier, + DhSectionPos.getMinCornerBlockZ(this.pos) + fogWidthInBlocks), + new Color(randomGrayColorValue, randomGrayColorValue, randomGrayColorValue), EDhApiBlockMaterial.UNKNOWN); - DebugRenderer.register(this, Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus); } @@ -244,6 +246,14 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable this.getAndBuildRenderDataRunnable = () -> { + // reset the fog + this.stopRenderingUnexploredFog(); + if (!this.getFullDataSourceExists()) + { + // no render data is present, fill the area with "fog" + this.startRenderingUnexploredFog(); + } + this.getAndRefreshRenderingBeacons(); this.getAndUploadRenderDataToGpuAsync() .thenRun(() -> @@ -459,19 +469,12 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable public void setRenderingEnabled(boolean enabled) { this.renderingEnabled = enabled;} /** @see LodRenderSection#setRenderingEnabled */ - public void onRenderingEnabled() - { - this.startRenderingBeacons(); - if (!this.getFullDataSourceExists()) - { - this.level.getGenericRenderer().add(this.fogRenderableBoxGroup); - } - } + public void onRenderingEnabled() { this.startRenderingBeacons(); } /** @see LodRenderSection#setRenderingEnabled */ public void onRenderingDisabled() { this.stopRenderingBeacons(); - this.level.getGenericRenderer().remove(this.fogRenderableBoxGroup.getId()); + this.stopRenderingUnexploredFog(); if (Config.Client.Advanced.Debugging.DebugWireframe.showRenderSectionStatus.get()) { @@ -666,6 +669,33 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable + //================// + // unexplored fog // + //================// + + private void startRenderingUnexploredFog() + { + IDhApiRenderableBoxGroup boxGroup = this.level.getUnexploredFogRenderableBoxGroup(); + if (boxGroup != null) // box group will be null for server levels, that shouldn't be a problem here, but just in case + { + boxGroup.add(this.unexploredFogRenderableBox); + boxGroup.triggerBoxChange(); + } + } + + private void stopRenderingUnexploredFog() + { + IDhApiRenderableBoxGroup boxGroup = this.level.getUnexploredFogRenderableBoxGroup(); + if (boxGroup != null) // box group will be null for server levels, that shouldn't be a problem here, but just in case + { + if (boxGroup.remove(this.unexploredFogRenderableBox)) + { + boxGroup.triggerBoxChange(); + } + } + } + + //==============// // base methods // @@ -717,7 +747,7 @@ public class LodRenderSection implements IDebugRenderable, AutoCloseable this.stopRenderingBeacons(); - this.level.getGenericRenderer().remove(this.fogRenderableBoxGroup.getId()); + this.stopRenderingUnexploredFog(); if (this.renderBuffer != null) {