Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2a4bfef7a6 | |||
| 7be65a2258 |
@@ -23,7 +23,6 @@ import com.seibel.distanthorizons.api.DhApi;
|
||||
import com.seibel.distanthorizons.api.enums.config.EDhApiMcRenderingFadeMode;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass;
|
||||
import com.seibel.distanthorizons.api.methods.events.abstractEvents.*;
|
||||
import com.seibel.distanthorizons.api.objects.DhApiResult;
|
||||
import com.seibel.distanthorizons.core.api.internal.rendering.DhRenderState;
|
||||
import com.seibel.distanthorizons.core.enums.MinecraftTextFormat;
|
||||
import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure;
|
||||
@@ -33,8 +32,8 @@ import com.seibel.distanthorizons.core.pos.DhChunkPos;
|
||||
import com.seibel.distanthorizons.core.render.DhApiRenderProxy;
|
||||
import com.seibel.distanthorizons.core.render.renderer.*;
|
||||
import com.seibel.distanthorizons.core.util.TimerUtil;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.util.objects.Pair;
|
||||
import com.seibel.distanthorizons.core.util.threading.PriorityTaskPicker;
|
||||
import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.coreapi.DependencyInjection.ApiEventInjector;
|
||||
@@ -42,6 +41,7 @@ import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.network.messages.AbstractNetworkMessage;
|
||||
import com.seibel.distanthorizons.core.network.session.NetworkSession;
|
||||
import com.seibel.distanthorizons.coreapi.ModInfo;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiDebugRendering;
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRendererMode;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.level.IServerKeyedClientLevel;
|
||||
@@ -55,23 +55,13 @@ import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapp
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector4f;
|
||||
import org.lwjgl.glfw.GLFW;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.GL46;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* This holds the methods that should be called
|
||||
@@ -561,11 +551,8 @@ public class ClientApi
|
||||
* The first fade pass.
|
||||
* Called after MC finishes rendering the opaque passes.
|
||||
*/
|
||||
public void renderFadeOpaque() // TODO this is actually the transparent pass
|
||||
public void renderFadeOpaque()
|
||||
{
|
||||
DepthCalculator.INSTANCE.getMcTransparentDepthTexture();
|
||||
DepthCalculator.INSTANCE.tryCalculateAsync();
|
||||
|
||||
// only fade when DH is rendering
|
||||
if (Config.Client.Advanced.Debugging.rendererMode.get() == EDhApiRendererMode.DEFAULT
|
||||
&&
|
||||
@@ -586,10 +573,8 @@ public class ClientApi
|
||||
* Called after MC finishes rendering both opaque
|
||||
* and transparent passes.
|
||||
*/
|
||||
public void renderFadeTransparent() // TODO this is actually the opaque pass
|
||||
public void renderFadeTransparent()
|
||||
{
|
||||
DepthCalculator.INSTANCE.getMcOpaqueDepthTexture();
|
||||
|
||||
// only fade when DH is rendering
|
||||
if (Config.Client.Advanced.Debugging.rendererMode.get() == EDhApiRendererMode.DEFAULT)
|
||||
{
|
||||
@@ -618,30 +603,27 @@ public class ClientApi
|
||||
/** Trigger once on key press, with CLIENT PLAYER. */
|
||||
public void keyPressedEvent(int glfwKey)
|
||||
{
|
||||
//if (!Config.Client.Advanced.Debugging.enableDebugKeybindings.get())
|
||||
//{
|
||||
// // keybindings are disabled
|
||||
// return;
|
||||
//}
|
||||
if (!Config.Client.Advanced.Debugging.enableDebugKeybindings.get())
|
||||
{
|
||||
// keybindings are disabled
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
if (glfwKey == GLFW.GLFW_KEY_F8)
|
||||
{
|
||||
DepthCalculator.INSTANCE.pause = true;
|
||||
//Config.Client.Advanced.Debugging.debugRendering.set(EDhApiDebugRendering.next(Config.Client.Advanced.Debugging.debugRendering.get()));
|
||||
//MC_CLIENT.sendChatMessage("F8: Set debug mode to " + Config.Client.Advanced.Debugging.debugRendering.get());
|
||||
Config.Client.Advanced.Debugging.debugRendering.set(EDhApiDebugRendering.next(Config.Client.Advanced.Debugging.debugRendering.get()));
|
||||
MC_CLIENT.sendChatMessage("F8: Set debug mode to " + Config.Client.Advanced.Debugging.debugRendering.get());
|
||||
}
|
||||
else if (glfwKey == GLFW.GLFW_KEY_F6)
|
||||
{
|
||||
DepthCalculator.INSTANCE.pause = true;
|
||||
//Config.Client.Advanced.Debugging.rendererMode.set(EDhApiRendererMode.next(Config.Client.Advanced.Debugging.rendererMode.get()));
|
||||
//MC_CLIENT.sendChatMessage("F6: Set rendering to " + Config.Client.Advanced.Debugging.rendererMode.get());
|
||||
Config.Client.Advanced.Debugging.rendererMode.set(EDhApiRendererMode.next(Config.Client.Advanced.Debugging.rendererMode.get()));
|
||||
MC_CLIENT.sendChatMessage("F6: Set rendering to " + Config.Client.Advanced.Debugging.rendererMode.get());
|
||||
}
|
||||
else if (glfwKey == GLFW.GLFW_KEY_P)
|
||||
{
|
||||
DepthCalculator.INSTANCE.pause = true;
|
||||
//prefLoggerEnabled = !prefLoggerEnabled;
|
||||
//MC_CLIENT.sendChatMessage("P: Debug Pref Logger is " + (prefLoggerEnabled ? "enabled" : "disabled"));
|
||||
prefLoggerEnabled = !prefLoggerEnabled;
|
||||
MC_CLIENT.sendChatMessage("P: Debug Pref Logger is " + (prefLoggerEnabled ? "enabled" : "disabled"));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -101,6 +101,7 @@ public class Config
|
||||
.build();
|
||||
|
||||
public static ConfigUiLinkedEntry quickEnableWorldGenerator = new ConfigUiLinkedEntry(Common.WorldGenerator.enableDistantGeneration);
|
||||
public static ConfigUiLinkedEntry quickEnableServerGeneration = new ConfigUiLinkedEntry(Server.enableServerGeneration);
|
||||
|
||||
public static ConfigUiLinkedEntry quickShowWorldGenProgress = new ConfigUiLinkedEntry(Common.WorldGenerator.showGenerationProgress);
|
||||
|
||||
@@ -118,20 +119,6 @@ public class Config
|
||||
|
||||
|
||||
|
||||
public static ConfigEntry<Boolean> dynamicFadeUseOpaqueMcDepth = new ConfigEntry.Builder<Boolean>()
|
||||
.set(true)
|
||||
.comment(""
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<String> dynamicFadeExportPath = new ConfigEntry.Builder<String>()
|
||||
.set("C:/Users/James_Seibel/Desktop/")
|
||||
.comment(""
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
|
||||
|
||||
public static class Advanced
|
||||
{
|
||||
// common config links need to have their destination
|
||||
@@ -1748,6 +1735,15 @@ public class Config
|
||||
|
||||
|
||||
// Generation
|
||||
public static ConfigEntry<Boolean> enableServerGeneration = new ConfigEntry.Builder<Boolean>()
|
||||
.set(true)
|
||||
.comment(""
|
||||
+ "When enabled, Distant Horizons will attempt to download missing LODs from the server.\n"
|
||||
+ "\n"
|
||||
+ "Note: the server must have Distant Generation enabled for it to work."
|
||||
+ "")
|
||||
.build();
|
||||
|
||||
public static ConfigEntry<Integer> generationRequestRateLimit = new ConfigEntry.Builder<Integer>()
|
||||
.setChatCommandName("generation.requestRateLimit")
|
||||
.setMinDefaultMax(1, 20, 100)
|
||||
|
||||
+52
-17
@@ -11,6 +11,7 @@ import java.io.Closeable;
|
||||
import java.util.*;
|
||||
import java.util.function.BinaryOperator;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.Supplier;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class SessionConfig implements INetworkObject
|
||||
@@ -31,7 +32,23 @@ public class SessionConfig implements INetworkObject
|
||||
{
|
||||
// Note: config values are transmitted in the insertion order
|
||||
|
||||
registerConfigEntry(Config.Common.WorldGenerator.enableDistantGeneration, Boolean::logicalAnd);
|
||||
registerConfigEntry(Config.Common.WorldGenerator.enableDistantGeneration.getChatCommandName(), new Entry(
|
||||
Config.Server.enableServerGeneration::get,
|
||||
runnable -> new Closeable()
|
||||
{
|
||||
private final ConfigChangeListener<Boolean> distantGenerationChanges = new ConfigChangeListener<>(Config.Common.WorldGenerator.enableDistantGeneration, ignored -> runnable.run());
|
||||
private final ConfigChangeListener<Boolean> serverGenerationChanges = new ConfigChangeListener<>(Config.Server.enableServerGeneration, ignored -> runnable.run());
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
this.serverGenerationChanges.close();
|
||||
this.distantGenerationChanges.close();
|
||||
}
|
||||
},
|
||||
(Boolean client, Boolean server) -> client && Config.Common.WorldGenerator.enableDistantGeneration.get()
|
||||
));
|
||||
|
||||
registerConfigEntry(Config.Server.maxGenerationRequestDistance, Math::min);
|
||||
registerConfigEntry(Config.Common.WorldGenerator.generationCenterChunkX, (x, y) -> y);
|
||||
registerConfigEntry(Config.Common.WorldGenerator.generationCenterChunkZ, (x, y) -> y);
|
||||
@@ -90,14 +107,24 @@ public class SessionConfig implements INetworkObject
|
||||
|
||||
private static <T> void registerConfigEntry(ConfigEntry<T> configEntry, BinaryOperator<T> valueConstrainer)
|
||||
{
|
||||
CONFIG_ENTRIES.compute(Objects.requireNonNull(configEntry.getChatCommandName()), (key, existingEntry) -> {
|
||||
if (existingEntry != null)
|
||||
{
|
||||
throw new IllegalArgumentException("Attempted to register config entry with duplicate chatCommandName: " + key);
|
||||
}
|
||||
|
||||
return new Entry(configEntry, valueConstrainer);
|
||||
});
|
||||
registerConfigEntry(
|
||||
Objects.requireNonNull(configEntry.getChatCommandName()),
|
||||
new Entry(
|
||||
configEntry::get,
|
||||
runnable -> new ConfigChangeListener<>(configEntry, ignored -> runnable.run()),
|
||||
valueConstrainer
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
private static void registerConfigEntry(String key, Entry entry)
|
||||
{
|
||||
if (CONFIG_ENTRIES.containsKey(key))
|
||||
{
|
||||
throw new IllegalArgumentException("Attempted to register config entry with duplicate key: " + key);
|
||||
}
|
||||
|
||||
CONFIG_ENTRIES.put(key, entry);
|
||||
}
|
||||
|
||||
|
||||
@@ -115,7 +142,7 @@ public class SessionConfig implements INetworkObject
|
||||
T value = (T) this.values.get(name);
|
||||
if (value == null)
|
||||
{
|
||||
value = (T) entry.supplier.get();
|
||||
value = (T) entry.valueSupplier.get();
|
||||
}
|
||||
|
||||
return (this.constrainingConfig != null
|
||||
@@ -210,13 +237,15 @@ public class SessionConfig implements INetworkObject
|
||||
|
||||
private static class Entry
|
||||
{
|
||||
public final ConfigEntry<Object> supplier;
|
||||
public final Supplier<Object> valueSupplier;
|
||||
public final Function<Runnable, Closeable> changeListenerFactory;
|
||||
public final BinaryOperator<Object> valueConstrainer;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> Entry(ConfigEntry<T> supplier, BinaryOperator<T> valueConstrainer)
|
||||
private <T> Entry(Supplier<Object> valueSupplier, Function<Runnable, Closeable> changeListenerFactory, BinaryOperator<T> valueConstrainer)
|
||||
{
|
||||
this.supplier = (ConfigEntry<Object>) supplier;
|
||||
this.valueSupplier = valueSupplier;
|
||||
this.changeListenerFactory = changeListenerFactory;
|
||||
this.valueConstrainer = (BinaryOperator<Object>) valueConstrainer;
|
||||
}
|
||||
|
||||
@@ -225,23 +254,29 @@ public class SessionConfig implements INetworkObject
|
||||
/** fires if any config value was changed */
|
||||
public static class AnyChangeListener implements Closeable
|
||||
{
|
||||
private final ArrayList<ConfigChangeListener<?>> changeListeners;
|
||||
private final ArrayList<Closeable> changeListeners;
|
||||
|
||||
public AnyChangeListener(Runnable runnable)
|
||||
{
|
||||
this.changeListeners = new ArrayList<>(CONFIG_ENTRIES.size());
|
||||
for (Entry entry : CONFIG_ENTRIES.values())
|
||||
{
|
||||
this.changeListeners.add(new ConfigChangeListener<>(entry.supplier, ignored -> runnable.run()));
|
||||
this.changeListeners.add(entry.changeListenerFactory.apply(runnable));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close()
|
||||
{
|
||||
for (ConfigChangeListener<?> changeListener : this.changeListeners)
|
||||
for (Closeable changeListener : this.changeListeners)
|
||||
{
|
||||
changeListener.close();
|
||||
try
|
||||
{
|
||||
changeListener.close();
|
||||
}
|
||||
catch (Exception ignored)
|
||||
{
|
||||
}
|
||||
}
|
||||
this.changeListeners.clear();
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.seibel.distanthorizons.core.enums.EDhDirection;
|
||||
import com.seibel.distanthorizons.core.file.fullDatafile.V2.FullDataSourceProviderV2;
|
||||
import com.seibel.distanthorizons.core.generation.tasks.DataSourceRetrievalResult;
|
||||
import com.seibel.distanthorizons.core.generation.tasks.ERetrievalResultState;
|
||||
import com.seibel.distanthorizons.core.level.DhClientServerLevel;
|
||||
import com.seibel.distanthorizons.core.level.IDhClientLevel;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
@@ -144,6 +145,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
||||
this.beaconRenderHandler = (genericObjectRenderer != null) ? new BeaconRenderHandler(genericObjectRenderer) : null;
|
||||
|
||||
Config.Common.WorldGenerator.enableDistantGeneration.addListener(this);
|
||||
Config.Server.enableServerGeneration.addListener(this);
|
||||
|
||||
}
|
||||
|
||||
@@ -662,7 +664,9 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
||||
@Override
|
||||
public void onConfigValueSet()
|
||||
{
|
||||
boolean generatorEnabled = Config.Common.WorldGenerator.enableDistantGeneration.get();
|
||||
boolean generatorEnabled = this.level instanceof DhClientServerLevel
|
||||
? Config.Common.WorldGenerator.enableDistantGeneration.get()
|
||||
: Config.Server.enableServerGeneration.get();
|
||||
if (generatorEnabled)
|
||||
{
|
||||
// world gen tasks will need to be re-queued
|
||||
@@ -920,6 +924,7 @@ public class LodQuadTree extends QuadTree<LodRenderSection> implements IDebugRen
|
||||
|
||||
DebugRenderer.unregister(this, Config.Client.Advanced.Debugging.DebugWireframe.showQuadTreeRenderStatus);
|
||||
Config.Common.WorldGenerator.enableDistantGeneration.removeListener(this);
|
||||
Config.Server.enableServerGeneration.removeListener(this);
|
||||
|
||||
|
||||
ThreadPoolExecutor mainCleanupExecutor = ThreadPoolUtil.getCleanupExecutor();
|
||||
|
||||
-444
@@ -1,444 +0,0 @@
|
||||
package com.seibel.distanthorizons.core.render.renderer;
|
||||
|
||||
import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass;
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.logging.DhLogger;
|
||||
import com.seibel.distanthorizons.core.logging.DhLoggerBuilder;
|
||||
import com.seibel.distanthorizons.core.util.math.Mat4f;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftGLWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import org.joml.Matrix4f;
|
||||
import org.joml.Vector4f;
|
||||
import org.lwjgl.opengl.GL32;
|
||||
import org.lwjgl.opengl.GL46;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.*;
|
||||
import java.awt.image.BufferedImage;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.NumberFormat;
|
||||
import java.util.Arrays;
|
||||
import java.util.function.Function;
|
||||
|
||||
public class DepthCalculator
|
||||
{
|
||||
|
||||
public static DepthCalculator INSTANCE = new DepthCalculator();
|
||||
private static final DhLogger LOGGER = new DhLoggerBuilder().build();
|
||||
|
||||
private static final IMinecraftClientWrapper MC_CLIENT = SingletonInjector.INSTANCE.get(IMinecraftClientWrapper.class);
|
||||
private static final IMinecraftRenderWrapper MC_RENDER = SingletonInjector.INSTANCE.get(IMinecraftRenderWrapper.class);
|
||||
private static final IMinecraftGLWrapper GLMC = SingletonInjector.INSTANCE.get(IMinecraftGLWrapper.class);
|
||||
|
||||
|
||||
private float[] mcOpaqueDepthTextureValues = new float[1];
|
||||
private float[] mcTransparentDepthTextureValues = new float[1];
|
||||
private float[] dhDepthTextureValues = new float[1];
|
||||
private float[] outDepthTextureValues = new float[1];
|
||||
private float lastClosestDhDepth = 1.0f;
|
||||
|
||||
public float actualMcBlockDistance = 8 * 16; // needs to be non-zero to start DH rendering
|
||||
@Deprecated // Replace with thread pool and an AtomicBool for running state
|
||||
public Thread thread = null;
|
||||
public boolean pause = false;
|
||||
|
||||
private boolean gotDhDepthThisFrame = false;
|
||||
private boolean gotMcDepthThisFrame = false;
|
||||
|
||||
|
||||
//=============//
|
||||
// constructor //
|
||||
//=============//
|
||||
|
||||
private DepthCalculator() { }
|
||||
|
||||
|
||||
//======//
|
||||
// test //
|
||||
//======//
|
||||
|
||||
public void getMcOpaqueDepthTexture() { this.gotMcDepthThisFrame = this.trySetDepthTexture(MC_RENDER.getDepthTextureId(), this.mcOpaqueDepthTextureValues); }
|
||||
public void getMcTransparentDepthTexture() { this.gotMcDepthThisFrame = this.trySetDepthTexture(MC_RENDER.getDepthTextureId(), this.mcTransparentDepthTextureValues); }
|
||||
public void trySetDhDepthTexture() { this.gotDhDepthThisFrame = this.trySetDepthTexture(LodRenderer.INSTANCE.getActiveDepthTextureId(), this.dhDepthTextureValues); }
|
||||
private boolean trySetDepthTexture(int id, float[] outputRef)
|
||||
{
|
||||
// don't change the texture if a process is already running
|
||||
if (this.thread != null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
this.resizeTexturesIfNeeded();
|
||||
if (id == -1)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// FIXME this is slow and causes frame stuttering
|
||||
GL46.glGetTextureImage(id, 0, GL32.GL_DEPTH_COMPONENT, GL32.GL_FLOAT, outputRef);
|
||||
return true;
|
||||
}
|
||||
private void resizeTexturesIfNeeded()
|
||||
{
|
||||
int width = MC_RENDER.getTargetFramebufferViewportWidth();
|
||||
int height = MC_RENDER.getTargetFramebufferViewportHeight();
|
||||
int elementCount = width * height;
|
||||
if (this.dhDepthTextureValues.length != elementCount)
|
||||
{
|
||||
this.mcOpaqueDepthTextureValues = new float[width * height];
|
||||
this.mcTransparentDepthTextureValues = new float[width * height];
|
||||
|
||||
this.dhDepthTextureValues = new float[width * height];
|
||||
this.outDepthTextureValues = new float[width * height];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
public void tryCalculateAsync()
|
||||
{
|
||||
if (this.thread != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
//if (!this.gotDhDepthThisFrame
|
||||
// || !this.gotMcDepthThisFrame)
|
||||
//{
|
||||
// return;
|
||||
//}
|
||||
|
||||
if (this.pause)
|
||||
{
|
||||
int k = 0;
|
||||
}
|
||||
|
||||
|
||||
this.thread = new Thread(() ->
|
||||
{
|
||||
try
|
||||
{
|
||||
this.calculateDepth();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
LOGGER.error("async test: " + e.getMessage(), e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
this.thread = null;
|
||||
this.pause = false;
|
||||
}
|
||||
});
|
||||
this.thread.start();
|
||||
}
|
||||
public void calculateDepth()
|
||||
{
|
||||
int width = MC_RENDER.getTargetFramebufferViewportWidth();
|
||||
int height = MC_RENDER.getTargetFramebufferViewportHeight();
|
||||
int elementCount = width * height;
|
||||
|
||||
|
||||
// used to calculate the DH render matrices
|
||||
RenderParams renderParams =
|
||||
new RenderParams(
|
||||
EDhApiRenderPass.OPAQUE,
|
||||
ClientApi.RENDER_STATE.frameTime,
|
||||
ClientApi.RENDER_STATE.mcProjectionMatrix, ClientApi.RENDER_STATE.mcModelViewMatrix,
|
||||
ClientApi.RENDER_STATE.clientLevelWrapper
|
||||
);
|
||||
|
||||
Mat4f dhInvProj = new Mat4f(renderParams.dhProjectionMatrix);
|
||||
dhInvProj.invert();
|
||||
Matrix4f dhInvProjJoml = dhInvProj.createJomlMatrix();
|
||||
|
||||
Mat4f dhInvMvm = new Mat4f(renderParams.dhModelViewMatrix);
|
||||
dhInvMvm.invert();
|
||||
Matrix4f dhInvMvmJoml = dhInvMvm.createJomlMatrix(); // TODO can we use JOML for MC 1.16?
|
||||
|
||||
|
||||
float[] sampledDistances = new float[9];
|
||||
|
||||
// find the closest depth value MC hasn't drawn to
|
||||
float closestDhDepth = 1.0f; float closestDhDistance = Float.MAX_VALUE;
|
||||
int closeUIndex = 0; int closeVIndex = 0;
|
||||
for (int u = 0; u < width; u++) // x
|
||||
{
|
||||
for (int v = 0; v < height; v++) // y
|
||||
{
|
||||
int invertedV = height - 1 - v;
|
||||
int i = (invertedV * width) + u;
|
||||
|
||||
|
||||
this.outDepthTextureValues[i] = 0.0f;
|
||||
|
||||
float mcDepth = Config.Client.dynamicFadeUseOpaqueMcDepth.get()
|
||||
? this.mcOpaqueDepthTextureValues[i]
|
||||
: this.mcTransparentDepthTextureValues[i];
|
||||
if (mcDepth < 1.0f) // ignore positions MC has drawn to
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
float dhDepth = this.dhDepthTextureValues[i];
|
||||
if (dhDepth == 1.0f) // ignore positions DH has NOT drawn to
|
||||
{
|
||||
continue;
|
||||
}
|
||||
this.outDepthTextureValues[i] = dhDepth;
|
||||
|
||||
|
||||
// calculate this point's distance from the camera
|
||||
float ndcU = u / (float)width;
|
||||
float ndcV = invertedV / (float)height;
|
||||
float dist = convertDepthToBlockDistance(ndcU, ndcV, dhInvProjJoml, dhInvMvmJoml, dhDepth);
|
||||
|
||||
//// sample the 9 surrounding pixels to account for off-by-one errors between the MC and DH depth textures
|
||||
//int sampleIndex = 0;
|
||||
//for (int relU = -1; relU < 1; relU++)
|
||||
//{
|
||||
// for (int relV = -1; relV < 1; relV++)
|
||||
// {
|
||||
// invertedV = height - 1 - v + relV;
|
||||
// i = (invertedV * width) + u + relU;
|
||||
// dhDepth = this.dhDepthTextureValues[i];
|
||||
//
|
||||
// if (v + relV < 0 || v + relV > height
|
||||
// || u + relU < 0 || u + relU > width)
|
||||
// {
|
||||
// sampledDistances[sampleIndex] = 0.0f;
|
||||
// sampleIndex++;
|
||||
// }
|
||||
//
|
||||
// // calculate this point's distance from the camera
|
||||
// float ndcU = u / (float)width;
|
||||
// float ndcV = invertedV / (float)height;
|
||||
// float dist = convertDepthToBlockDistance(ndcU, ndcV, dhInvProjJoml, dhInvMvmJoml, dhDepth);
|
||||
//
|
||||
// sampledDistances[sampleIndex] = dist;
|
||||
// sampleIndex++;
|
||||
// }
|
||||
//}
|
||||
//
|
||||
//
|
||||
//Arrays.sort(sampledDistances);
|
||||
//// return the median element
|
||||
//float dist = sampledDistances[sampledDistances.length / 2];
|
||||
//if (dist == 0.0f)
|
||||
//{
|
||||
// // the median was 0, return the smallest non-zero element
|
||||
// for (sampleIndex = 0; sampleIndex < sampledDistances.length; sampleIndex++)
|
||||
// {
|
||||
// if (sampledDistances[sampleIndex] != 0.0f)
|
||||
// {
|
||||
// dist = sampledDistances[sampleIndex];
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
//}
|
||||
|
||||
if (dist < closestDhDistance)
|
||||
{
|
||||
closestDhDepth = dhDepth;
|
||||
closestDhDistance = dist;
|
||||
|
||||
closeUIndex = u;
|
||||
closeVIndex = invertedV;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if (this.lastClosestDhDepth != closestDhDepth)
|
||||
{
|
||||
NumberFormat numForm = NumberFormat.getNumberInstance();
|
||||
ClientApi.INSTANCE.showChatMessageNextFrame(
|
||||
"closest: ["+numForm.format(closestDhDepth)+"]-b["+numForm.format(closestDhDistance)+"]c["+numForm.format(closestDhDistance/16)+"] ("+(closeUIndex)+","+(closeVIndex)+")" +
|
||||
"");
|
||||
|
||||
this.actualMcBlockDistance = closestDhDistance;
|
||||
}
|
||||
this.lastClosestDhDepth = closestDhDepth;
|
||||
|
||||
|
||||
if (this.pause)
|
||||
{
|
||||
// find the range of depth values used by both textures for clearer exporting
|
||||
float closestMcDepth = 1.0f; float furthestMcDepth = 0.0f;
|
||||
float minDhDepth = 1.0f; float maxDhDepth = 0.0f;
|
||||
for (int i = 0; i < elementCount; i++)
|
||||
{
|
||||
float mcDepth = this.mcOpaqueDepthTextureValues[i];
|
||||
if (mcDepth != 0.0f && mcDepth != 1.0f)
|
||||
{
|
||||
if (mcDepth < closestMcDepth)
|
||||
{
|
||||
closestMcDepth = mcDepth;
|
||||
}
|
||||
|
||||
if (mcDepth > furthestMcDepth)
|
||||
{
|
||||
furthestMcDepth = mcDepth;
|
||||
}
|
||||
}
|
||||
|
||||
float dhDepth = this.dhDepthTextureValues[i];
|
||||
if (dhDepth != 0.0f && dhDepth != 1.0f)
|
||||
{
|
||||
if (dhDepth < minDhDepth)
|
||||
{
|
||||
minDhDepth = dhDepth;
|
||||
}
|
||||
|
||||
if (dhDepth > maxDhDepth)
|
||||
{
|
||||
maxDhDepth = dhDepth;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
String exportPath = Config.Client.dynamicFadeExportPath.get();
|
||||
|
||||
ClientApi.INSTANCE.showChatMessageNextFrame("exporting debug textures to: ["+exportPath+"]...");
|
||||
|
||||
// mc opaque
|
||||
createImg(
|
||||
this.mcOpaqueDepthTextureValues,
|
||||
closeUIndex, closeVIndex,
|
||||
(Float depth) -> { return null; },
|
||||
width, height, closestMcDepth, furthestMcDepth,
|
||||
exportPath+"mc-opaque_depth.png");
|
||||
|
||||
// mc transparent
|
||||
createImg(
|
||||
this.mcTransparentDepthTextureValues,
|
||||
closeUIndex, closeVIndex,
|
||||
(Float depth) -> { return null; },
|
||||
width, height, closestMcDepth, furthestMcDepth,
|
||||
exportPath+"mc-tran_depth.png");
|
||||
|
||||
// dh
|
||||
Function<Float, Color> customColorFunc = (Float depth) ->
|
||||
{
|
||||
if (depth == this.lastClosestDhDepth)
|
||||
{
|
||||
return Color.RED;
|
||||
}
|
||||
//else if (depth <= (lastClosestDhDepth + 0.01f))
|
||||
//{
|
||||
// return Color.ORANGE;
|
||||
//}
|
||||
|
||||
return null;
|
||||
};
|
||||
createImg(
|
||||
this.dhDepthTextureValues,
|
||||
closeUIndex, closeVIndex,
|
||||
customColorFunc,
|
||||
width, height, minDhDepth, maxDhDepth,
|
||||
exportPath+"dh_depth.png");
|
||||
|
||||
// temp
|
||||
|
||||
createImg(
|
||||
this.outDepthTextureValues,
|
||||
closeUIndex, closeVIndex,
|
||||
(Float depth) -> { return null; },
|
||||
width, height, minDhDepth, maxDhDepth,
|
||||
exportPath+"temp_depth.png");
|
||||
|
||||
int breakPoint = 0;
|
||||
}
|
||||
}
|
||||
/** NDC (Normalized Device Coordinates) must be between 0.0 and 1.0 (inclusive) */
|
||||
private static float convertDepthToBlockDistance(float ndcU, float ndcV, Matrix4f invProj, Matrix4f invMvm, float depth)
|
||||
{
|
||||
// This assumes depth is scaled to [0, 1]
|
||||
// Transform depth to clip space Z value
|
||||
float z = depth * 2.0f - 1.0f;
|
||||
|
||||
// Create a vector in clip space
|
||||
Vector4f clipSpacePosition = new Vector4f(ndcU, ndcV, z, 1.0f);
|
||||
|
||||
// Transform to world space
|
||||
Vector4f worldSpacePosition = clipSpacePosition.mul(invProj);
|
||||
worldSpacePosition.div(worldSpacePosition.w); // Perform perspective divide
|
||||
|
||||
// Finally apply the inverse model-view matrix to get world space coordinates
|
||||
worldSpacePosition = worldSpacePosition.mul(invMvm);
|
||||
|
||||
// calculate distance from the camera
|
||||
float distance = worldSpacePosition.distance(0, 0, 0, 0);
|
||||
return distance;
|
||||
}
|
||||
private static void createImg(
|
||||
float[] tex,
|
||||
int nearestU, int nearestV,
|
||||
Function<Float, Color> customColorFunc,
|
||||
int width, int height,
|
||||
float minDepth, float maxDepth,
|
||||
String filePath)
|
||||
{
|
||||
// Create a BufferedImage
|
||||
BufferedImage image = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
|
||||
|
||||
for (int u = 0; u < width; u++)
|
||||
{
|
||||
for (int v = 0; v < height; v++)
|
||||
{
|
||||
int invertedY = height - 1 - v;
|
||||
|
||||
// Normalize the depth value to a grayscale pixel
|
||||
float depthValue = tex[(invertedY * width) + u];
|
||||
Color color = customColorFunc.apply(depthValue);
|
||||
if (color == null)
|
||||
{
|
||||
float normalizedDepth = (depthValue - minDepth) / (maxDepth - minDepth); // Normalize to 0.0 to 1.0
|
||||
normalizedDepth = Math.max(0.0f, Math.min(1.0f, normalizedDepth)); // Clamp to valid range
|
||||
|
||||
int gray = (int) (normalizedDepth * 255); // Map to 0-255
|
||||
gray = Math.max(0, Math.min(255, gray)); // Clamp to valid range
|
||||
color = new Color(gray, gray, gray);
|
||||
}
|
||||
|
||||
if (depthValue == 1.0f)
|
||||
{
|
||||
color = new Color(0,0,0,0);
|
||||
}
|
||||
|
||||
if (u == nearestU)
|
||||
{
|
||||
color = Color.MAGENTA;
|
||||
}
|
||||
else if (invertedY == nearestV)
|
||||
{
|
||||
color = Color.ORANGE;
|
||||
}
|
||||
|
||||
image.setRGB(u, v, color.getRGB());
|
||||
}
|
||||
}
|
||||
|
||||
// Write the image to a file
|
||||
try
|
||||
{
|
||||
ImageIO.write(image, "png", new File(filePath));
|
||||
}
|
||||
catch (IOException e)
|
||||
{
|
||||
LOGGER.error("Unable to write texture to file, error: ["+e.getMessage()+"].", e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
+7
-7
@@ -204,17 +204,17 @@ public class DhTerrainShaderProgram extends ShaderProgram implements IDhApiShade
|
||||
this.setUniform(this.uIsWhiteWorld, Config.Client.Advanced.Debugging.enableWhiteWorld.get());
|
||||
|
||||
// Clip Uniform
|
||||
float dhNearClipDistance = 0.1f;//RenderUtil.getNearClipPlaneInBlocksForFading(renderParameters.partialTicks);
|
||||
//if (!Config.Client.Advanced.Debugging.lodOnlyMode.get())
|
||||
//{
|
||||
// // this added value prevents the near clip plane and discard circle from touching, which looks bad
|
||||
// dhNearClipDistance += 16f;
|
||||
//}
|
||||
float dhNearClipDistance = RenderUtil.getNearClipPlaneInBlocksForFading(renderParameters.partialTicks);
|
||||
if (!Config.Client.Advanced.Debugging.lodOnlyMode.get())
|
||||
{
|
||||
// this added value prevents the near clip plane and discard circle from touching, which looks bad
|
||||
dhNearClipDistance += 16f;
|
||||
}
|
||||
// if the player is very high up and the near clip plane has been modified, disable the distance clipping
|
||||
// we're high enough that nothing will render on top of the player and this can cause issues otherwise
|
||||
if (RenderUtil.getHeightBasedNearClipOverride() != -1)
|
||||
{
|
||||
dhNearClipDistance = 1.0f; // TODO does this actually disable anything?
|
||||
dhNearClipDistance = 1.0f;
|
||||
}
|
||||
this.setUniform(this.uClipDistance, dhNearClipDistance);
|
||||
}
|
||||
|
||||
@@ -222,8 +222,6 @@ public class LodRenderer
|
||||
profiler.popPush("LOD Opaque");
|
||||
this.renderLodPass(lodShaderProgram, renderBufferHandler, renderParams, /*opaquePass*/ true);
|
||||
|
||||
DepthCalculator.INSTANCE.trySetDhDepthTexture();
|
||||
|
||||
// custom objects with SSAO
|
||||
if (Config.Client.Advanced.Graphics.GenericRendering.enableGenericRendering.get())
|
||||
{
|
||||
|
||||
+1
-2
@@ -19,7 +19,6 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.render.renderer.shaders;
|
||||
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.glObject.shader.ShaderProgram;
|
||||
@@ -115,7 +114,7 @@ public class VanillaFadeShader extends AbstractShaderRenderer
|
||||
|
||||
float dhNearClipDistance = RenderUtil.getNearClipPlaneInBlocksForFading(partialTicks);
|
||||
// this added value prevents the near clip plane and discard circle from touching, which looks bad
|
||||
//dhNearClipDistance += 16f;
|
||||
dhNearClipDistance += 16f;
|
||||
|
||||
// measured in blocks
|
||||
// these multipliers in James' tests should provide a fairly smooth transition
|
||||
|
||||
@@ -19,10 +19,8 @@
|
||||
|
||||
package com.seibel.distanthorizons.core.util;
|
||||
|
||||
import com.seibel.distanthorizons.core.api.internal.ClientApi;
|
||||
import com.seibel.distanthorizons.core.config.Config;
|
||||
import com.seibel.distanthorizons.core.dependencyInjection.SingletonInjector;
|
||||
import com.seibel.distanthorizons.core.render.renderer.DepthCalculator;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftClientWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper;
|
||||
import com.seibel.distanthorizons.core.wrapperInterfaces.world.IClientLevelWrapper;
|
||||
@@ -129,16 +127,13 @@ public class RenderUtil
|
||||
}
|
||||
public static float getNearClipPlaneInBlocksForFading(float partialTicks)
|
||||
{
|
||||
//float overdraw = getAutoOverdrawPrevention();
|
||||
//return getNearClipPlaneDistanceInBlocks(partialTicks, overdraw);
|
||||
|
||||
return DepthCalculator.INSTANCE.actualMcBlockDistance;
|
||||
float overdraw = getAutoOverdrawPrevention();
|
||||
return getNearClipPlaneDistanceInBlocks(partialTicks, overdraw);
|
||||
}
|
||||
private static float getNearClipPlaneDistanceInBlocks(float partialTicks, float overdrawPreventionPercent)
|
||||
{
|
||||
int chunkRenderDistance = MC_RENDER.getRenderDistance();
|
||||
//float chunkRenderDistance = ClientApi.actualMcBlockDistance / 16.0f;
|
||||
float vanillaBlockRenderedDistance = chunkRenderDistance * LodUtil.CHUNK_WIDTH;
|
||||
int vanillaBlockRenderedDistance = chunkRenderDistance * LodUtil.CHUNK_WIDTH;
|
||||
|
||||
float nearClipPlane;
|
||||
if (Config.Client.Advanced.Debugging.lodOnlyMode.get())
|
||||
|
||||
-2
@@ -63,9 +63,7 @@ public interface IMinecraftRenderWrapper extends IBindable
|
||||
/** @return -1 if no valid framebuffer is available yet */
|
||||
int getTargetFramebuffer(); // Note: Iris is now hooking onto this for DH + Iris compat, try not to change (unless we wanna deal with some annoyances)
|
||||
// Iris commit: https://github.com/IrisShaders/Iris/commit/a76a240527e93780bbcba57c09bef377419d47a7#diff-7b9ded0c79bbcdb130010373387756a28ee8d3640d522c0a5b7acd0abbfc20aeR16
|
||||
/** @return -1 if there was an issue or no texture exists */
|
||||
int getDepthTextureId();
|
||||
/** @return -1 if there was an issue or no texture exists */
|
||||
int getColorTextureId();
|
||||
int getTargetFramebufferViewportWidth();
|
||||
int getTargetFramebufferViewportHeight();
|
||||
|
||||
@@ -84,13 +84,7 @@
|
||||
"Show The Options Button",
|
||||
"distanthorizons.config.client.optionsButton.@tooltip":
|
||||
"Show the config button to the left of the fov button",
|
||||
|
||||
"distanthorizons.config.client.dynamicFadeUseOpaqueMcDepth":
|
||||
"Dynamic Fade Use MC Opaque Depth",
|
||||
"distanthorizons.config.client.dynamicFadeExportPath":
|
||||
"Dynamic Fade Export Path",
|
||||
"distanthorizons.config.client.dynamicFadeExportPath.@tooltip":
|
||||
"Press 'p' to export the depth textures for troubleshooting",
|
||||
|
||||
|
||||
|
||||
"distanthorizons.config.client.advanced":
|
||||
@@ -769,6 +763,11 @@
|
||||
"distanthorizons.config.server.levelKeyPrefix.@tooltip":
|
||||
"Prefix of the level keys sent to the clients.\nIf the mod is running behind a proxy, each backend should use a unique value.\nIf this value is empty, level key will be based on the server's seed hash.",
|
||||
|
||||
"distanthorizons.config.server.enableServerGeneration":
|
||||
"Enable Server Generation",
|
||||
"distanthorizons.config.server.enableServerGeneration.@tooltip":
|
||||
"When enabled, Distant Horizons will attempt to download missing LODs from the server.\n\nNote: the server must have Distant Generation enabled for it to work.",
|
||||
|
||||
"distanthorizons.config.server.generationRequestRateLimit":
|
||||
"Rate Limit for Generation Requests",
|
||||
"distanthorizons.config.server.generationRequestRateLimit.@tooltip":
|
||||
|
||||
Reference in New Issue
Block a user