diff --git a/dependencies.gradle b/dependencies.gradle
index 04923996a..9ca52ac84 100644
--- a/dependencies.gradle
+++ b/dependencies.gradle
@@ -136,6 +136,9 @@ dependencies {
// Better Crashes
compileOnly("com.github.GTNewHorizons:BetterCrashes:1.4.1-GTNH:dev")
+ // Distant Horizons
+ compileOnly("maven.modrinth:DistantHorizonsApi:5.1.0")
+
afterEvaluate {
dependencies {
testImplementation(platform('org.junit:junit-bom:5.14.1'))
diff --git a/src/main/java/com/gtnewhorizons/angelica/iris/IrisGLSMBridge.java b/src/main/java/com/gtnewhorizons/angelica/iris/IrisGLSMBridge.java
index beca86b2d..f017a790b 100644
--- a/src/main/java/com/gtnewhorizons/angelica/iris/IrisGLSMBridge.java
+++ b/src/main/java/com/gtnewhorizons/angelica/iris/IrisGLSMBridge.java
@@ -14,6 +14,7 @@ import net.coderbot.iris.pipeline.DeferredWorldRenderingPipeline;
import net.coderbot.iris.pipeline.WorldRenderingPipeline;
import net.coderbot.iris.samplers.IrisSamplers;
import net.coderbot.iris.texture.pbr.PBRTextureManager;
+import net.coderbot.iris.vertices.ImmediateState;
public class IrisGLSMBridge {
@@ -114,7 +115,7 @@ public class IrisGLSMBridge {
if (!drp.shouldOverrideShaders()) return;
if (drp.getActivePassProgramId() == -1) return;
- if (DepthColorStorage.isOwnedProgram(event.newProgram)) {
+ if (!ImmediateState.isRenderingLevel || DepthColorStorage.isOwnedProgram(event.newProgram)) {
DepthColorStorage.unlockDepthColor();
} else {
drp.onModProgramOverride();
diff --git a/src/main/java/net/coderbot/iris/Iris.java b/src/main/java/net/coderbot/iris/Iris.java
index 2131738c5..a5405a803 100644
--- a/src/main/java/net/coderbot/iris/Iris.java
+++ b/src/main/java/net/coderbot/iris/Iris.java
@@ -7,6 +7,7 @@ import com.gtnewhorizons.angelica.AngelicaMod;
import com.gtnewhorizons.angelica.Tags;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import cpw.mods.fml.client.registry.ClientRegistry;
+import cpw.mods.fml.common.Loader;
import cpw.mods.fml.common.eventhandler.SubscribeEvent;
import cpw.mods.fml.common.gameevent.InputEvent;
import it.unimi.dsi.fastutil.ints.Int2IntMap;
@@ -17,6 +18,7 @@ import net.coderbot.iris.block_rendering.BlockRenderingSettings;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import net.coderbot.iris.celeritas.IrisCeleritasShaderProvider;
import com.gtnewhorizons.angelica.rendering.celeritas.api.IrisShaderProviderHolder;
+import net.coderbot.iris.compat.dh.DHCompat;
import net.coderbot.iris.config.IrisConfig;
import net.coderbot.iris.gl.shader.StandardMacros;
import net.coderbot.iris.gui.screen.ShaderPackScreen;
@@ -113,11 +115,31 @@ public class Iris {
// Used in favor of queueDefaultShaderPackOptionValues() for resetting as the
// behavior is more concrete and therefore is more likely to repair a user's issues
private static boolean resetShaderPackOptions = false;
+ private static boolean loadShaderPackWhenPossible = false;
private static String IRIS_VERSION;
@Getter
private static boolean fallback;
+ public static boolean loadedIncompatiblePack() {
+ return DHCompat.lastPackIncompatible();
+ }
+
+ public static void loadShaderpackWhenPossible() {
+ loadShaderPackWhenPossible = true;
+ }
+
+ public static void tryLoadShaderpackWhenPossible() {
+ if (loadShaderPackWhenPossible) {
+ loadShaderPackWhenPossible = false;
+ try {
+ reload();
+ } catch (IOException e) {
+ logger.error("Error during deferred shader reload", e);
+ }
+ }
+ }
+
/**
* Lazy executor for parallelizing shader transformations during shader pack loading.
* Creates threads on demand and shuts down after a period of inactivity.
@@ -350,6 +372,7 @@ public class Iris {
*
This is called right before options are loaded, so we can add key bindings here.
*/
public void onEarlyInitialize() {
+ DHCompat.run();
try {
if (!Files.exists(getShaderpacksDirectory())) {
Files.createDirectories(getShaderpacksDirectory());
@@ -395,8 +418,19 @@ public class Iris {
PBRTextureManager.INSTANCE.init();
- // Only load the shader pack when we can access OpenGL
- loadShaderpack();
+ boolean isDHLoaded;
+ try {
+ Class.forName("com.seibel.distanthorizons.DistantHorizonsTweaker");
+ isDHLoaded = true;
+ }
+ catch (Exception e) {
+ isDHLoaded = false;
+ }
+
+ // When DH is present, defer shaderpack loading until its init callback has run.
+ if (!isDHLoaded) {
+ loadShaderpack();
+ }
}
/**
@@ -721,6 +755,12 @@ public class Iris {
BlockRenderingSettings.INSTANCE.reloadRendererIfRequired();
}
+
+ if (loadedIncompatiblePack() && Minecraft.getMinecraft().thePlayer != null) {
+ Iris.logger.warn("Incompatible pack for DH!");
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.BOLD.toString() + EnumChatFormatting.RED + "This pack doesn't have DH support."));
+ Minecraft.getMinecraft().thePlayer.addChatMessage(new ChatComponentText(EnumChatFormatting.RED + "Distant Horizons (DH) chunks won't show up. This isn't a bug, get another shader."));
+ }
}
/**
diff --git a/src/main/java/net/coderbot/iris/compat/dh/DHCompat.java b/src/main/java/net/coderbot/iris/compat/dh/DHCompat.java
index 64f820012..f215514e2 100644
--- a/src/main/java/net/coderbot/iris/compat/dh/DHCompat.java
+++ b/src/main/java/net/coderbot/iris/compat/dh/DHCompat.java
@@ -1,14 +1,129 @@
package net.coderbot.iris.compat.dh;
-/**
- * Stub implementation of Distant Horizons compatibility.
- */
-public class DHCompat {
- public int getDepthTex() {
- return 0;
- }
+import com.gtnewhorizons.angelica.rendering.RenderingState;
+import net.coderbot.iris.Iris;
+import net.coderbot.iris.pipeline.DeferredWorldRenderingPipeline;
+import net.minecraft.client.Minecraft;
+import org.joml.Matrix4f;
+import org.joml.Matrix4fc;
- public int getDepthTexNoTranslucent() {
- return 0;
- }
+import java.lang.invoke.MethodHandle;
+import java.lang.invoke.MethodHandles;
+import java.lang.invoke.MethodType;
+import java.lang.reflect.InvocationTargetException;
+
+public class DHCompat {
+ private static boolean dhPresent;
+ private static boolean lastIncompatible;
+ private DHCompatInternal compatInternalInstance;
+ private final static Matrix4f tempProj = new Matrix4f();
+
+ public DHCompat(DeferredWorldRenderingPipeline pipeline, boolean renderDHShadow) {
+ if (pipeline == null) {
+ return;
+ }
+ try {
+ if (dhPresent) {
+ compatInternalInstance = new DHCompatInternal(pipeline, renderDHShadow);
+ lastIncompatible = compatInternalInstance.incompatiblePack();
+ }
+ } catch (Throwable e) {
+ lastIncompatible = false;
+ if (e instanceof InvocationTargetException ite) {
+ throw new RuntimeException("Unknown error loading Distant Horizons compatibility.", ite.getCause());
+ } else {
+ throw new RuntimeException("Unknown error loading Distant Horizons compatibility.", e);
+ }
+ }
+
+ }
+
+ public static Matrix4fc getProjection() {
+ Matrix4f projection = RenderingState.INSTANCE.getProjectionMatrix();
+ if (!dhPresent) {
+ return projection;
+ }
+
+ return tempProj.setPerspective(projection.perspectiveFov(), projection.m11() / projection.m00(), DHCompat.getNearPlane(), DHCompat.getFarPlane());
+ }
+
+ public static void run() {
+ try {
+ Class.forName("com.seibel.distanthorizons.DistantHorizonsTweaker");
+ dhPresent = true;
+ }
+ catch (Exception e) {
+ dhPresent = false;
+ }
+ try {
+ if (dhPresent) {
+ LodRendererEvents.setupEventHandlers();
+ }
+ } catch (Throwable e) {
+ dhPresent = false;
+ if (e instanceof ExceptionInInitializerError eiie) {
+ throw new RuntimeException("Failure loading DH compat.", eiie.getCause());
+ } else {
+ throw new RuntimeException("DH found, but one or more API methods are missing. Iris requires DH [2.0.4] or DH API version [1.1.0] or newer. Please make sure you are on the latest version of DH and Iris.", e);
+ }
+ }
+ }
+
+ public static boolean lastPackIncompatible() {
+ return dhPresent && hasRenderingEnabled() && lastIncompatible;
+ }
+
+ public static float getFarPlane() {
+ if (!dhPresent) return 0.01f;
+ return DHCompatInternal.getFarPlane();
+ }
+
+ public static float getNearPlane() {
+ if (!dhPresent) return 0.01f;
+ return DHCompatInternal.getNearPlane();
+ }
+
+ public static int getRenderDistance() {
+ if (!dhPresent) return Minecraft.getMinecraft().gameSettings.renderDistanceChunks * 16;
+
+ return DHCompatInternal.getRenderDistance();
+ }
+
+ public static boolean checkFrame() {
+ if (!dhPresent) {
+ return false;
+ }
+
+ return DHCompatInternal.checkFrame();
+ }
+
+ public static boolean hasRenderingEnabled() {
+ if (!dhPresent) {
+ return false;
+ }
+
+ return checkFrame();
+ }
+
+ public void clearPipeline() {
+ if (compatInternalInstance == null) return;
+
+ compatInternalInstance.clear();
+ }
+
+ public int getDepthTex() {
+ if (compatInternalInstance == null) return -1;
+
+ return compatInternalInstance.getStoredDepthTex();
+ }
+
+ public int getDepthTexNoTranslucent() {
+ if (compatInternalInstance == null) return -1;
+
+ return compatInternalInstance.getDepthTexNoTranslucent();
+ }
+
+ public DHCompatInternal getInstance() {
+ return compatInternalInstance;
+ }
}
diff --git a/src/main/java/net/coderbot/iris/compat/dh/DHCompatInternal.java b/src/main/java/net/coderbot/iris/compat/dh/DHCompatInternal.java
new file mode 100644
index 000000000..116ba4c09
--- /dev/null
+++ b/src/main/java/net/coderbot/iris/compat/dh/DHCompatInternal.java
@@ -0,0 +1,291 @@
+package net.coderbot.iris.compat.dh;
+
+import com.gtnewhorizons.angelica.glsm.GLStateManager;
+import com.seibel.distanthorizons.api.DhApi;
+import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiFramebuffer;
+import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram;
+import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
+import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector;
+import net.coderbot.iris.Iris;
+import net.coderbot.iris.gl.framebuffer.GlFramebuffer;
+import net.coderbot.iris.gl.texture.DepthBufferFormat;
+import net.coderbot.iris.gl.texture.DepthCopyStrategy;
+import net.coderbot.iris.pipeline.DeferredWorldRenderingPipeline;
+import net.coderbot.iris.rendertarget.DepthTexture;
+import net.coderbot.iris.rendertarget.IRenderTargetExt;
+import net.coderbot.iris.shaderpack.CloudSetting;
+import net.coderbot.iris.shaderpack.ProgramSource;
+import net.coderbot.iris.uniforms.CapturedRenderingState;
+import net.irisshaders.iris.api.v0.IrisApi;
+import net.minecraft.client.Minecraft;
+import org.lwjgl.opengl.GL11;
+
+import java.io.IOException;
+
+public class DHCompatInternal {
+ public static final DHCompatInternal SHADERLESS = new DHCompatInternal(null, false);
+ static boolean dhEnabled;
+ private static int guiScale = -1;
+ private final DeferredWorldRenderingPipeline pipeline;
+ public boolean shouldOverrideShadow;
+ public boolean shouldOverride;
+ private GlFramebuffer dhGenericFramebuffer;
+ private IrisLodRenderProgram solidProgram;
+ private IrisGenericRenderProgram genericShader;
+ private IrisLodRenderProgram translucentProgram;
+ private IrisLodRenderProgram shadowProgram;
+ private GlFramebuffer dhTerrainFramebuffer;
+ private DhFrameBufferWrapper dhTerrainFramebufferWrapper;
+ private GlFramebuffer dhWaterFramebuffer;
+ private GlFramebuffer dhShadowFramebuffer;
+ private DhFrameBufferWrapper dhShadowFramebufferWrapper;
+ private DepthTexture depthTexNoTranslucent;
+ private boolean translucentDepthDirty;
+ private int storedDepthTex = -1;
+ private boolean incompatible = false;
+ private int cachedVersion;
+
+ public DHCompatInternal(DeferredWorldRenderingPipeline pipeline, boolean dhShadowEnabled) {
+ this.pipeline = pipeline;
+
+ if (pipeline == null || !DhApi.Delayed.configs.graphics().renderingEnabled().getValue()) {
+ return;
+ }
+
+ if (pipeline.getDHTerrainShader().isEmpty() && pipeline.getDHWaterShader().isEmpty()) {
+ Iris.logger.warn("No DH shader found in this pack.");
+ incompatible = true;
+ return;
+ }
+
+ cachedVersion = ((IRenderTargetExt) Minecraft.getMinecraft().getFramebuffer()).iris$getDepthBufferVersion();
+
+ createDepthTex(Minecraft.getMinecraft().getFramebuffer().framebufferWidth, Minecraft.getMinecraft().getFramebuffer().framebufferHeight);
+ translucentDepthDirty = true;
+
+ ProgramSource terrain = pipeline.getDHTerrainShader().get();
+ solidProgram = IrisLodRenderProgram.createProgram(terrain.getName(), false, false, terrain, pipeline.getCustomUniforms(), pipeline);
+
+ ProgramSource generic = pipeline.getDHGenericShader().get();
+ genericShader = IrisGenericRenderProgram.createProgram(generic.getName() + "_g", false, false, generic, pipeline.getCustomUniforms(), pipeline);
+ dhGenericFramebuffer = pipeline.createDHFramebuffer(generic, false);
+
+ if (pipeline.getDHWaterShader().isPresent()) {
+ ProgramSource water = pipeline.getDHWaterShader().get();
+ translucentProgram = IrisLodRenderProgram.createProgram(water.getName(), false, true, water, pipeline.getCustomUniforms(), pipeline);
+ dhWaterFramebuffer = pipeline.createDHFramebuffer(water, true);
+ }
+
+ if (pipeline.getDHShadowShader().isPresent() && dhShadowEnabled) {
+ ProgramSource shadow = pipeline.getDHShadowShader().get();
+ shadowProgram = IrisLodRenderProgram.createProgram(shadow.getName(), true, false, shadow, pipeline.getCustomUniforms(), pipeline);
+ if (pipeline.hasShadowRenderTargets()) {
+ dhShadowFramebuffer = pipeline.createDHFramebufferShadow(shadow);
+ dhShadowFramebufferWrapper = new DhFrameBufferWrapper(dhShadowFramebuffer);
+ }
+ shouldOverrideShadow = true;
+ } else {
+ shouldOverrideShadow = false;
+ }
+
+ dhTerrainFramebuffer = pipeline.createDHFramebuffer(terrain, false);
+ dhTerrainFramebufferWrapper = new DhFrameBufferWrapper(dhTerrainFramebuffer);
+
+ if (translucentProgram == null) {
+ translucentProgram = solidProgram;
+ }
+
+ shouldOverride = true;
+ }
+
+ public static int getDhBlockRenderDistance() {
+ if (DhApi.Delayed.configs == null || !dhEnabled) {
+ // Called before DH has finished setup
+ return Minecraft.getMinecraft().gameSettings.renderDistanceChunks * 16;
+ }
+
+ return DhApi.Delayed.configs.graphics().chunkRenderDistance().getValue() * 16;
+ }
+
+ public static int getRenderDistance() {
+ return getDhBlockRenderDistance();
+ }
+
+ public static float getFarPlane() {
+ if (DhApi.Delayed.configs == null) {
+ // Called before DH has finished setup
+ return 0;
+ }
+
+ int lodChunkDist = DhApi.Delayed.configs.graphics().chunkRenderDistance().getValue();
+ int lodBlockDist = lodChunkDist * 16;
+ // sqrt 2 to prevent the corners from being cut off
+ return (float) ((lodBlockDist + 512) * Math.sqrt(2));
+ }
+
+ public static float getNearPlane() {
+ if (DhApi.Delayed.renderProxy == null) {
+ // Called before DH has finished setup
+ return 0;
+ }
+
+ return DhApi.Delayed.renderProxy.getNearClipPlaneDistanceInBlocks(CapturedRenderingState.INSTANCE.getTickDelta());
+ }
+
+ public static boolean checkFrame() {
+ if (guiScale == -1) {
+ guiScale = Minecraft.getMinecraft().gameSettings.guiScale;
+ }
+
+ if (DhApi.Delayed.configs == null) return dhEnabled;
+
+ if ((dhEnabled != DhApi.Delayed.configs.graphics().renderingEnabled().getValue() || guiScale != Minecraft.getMinecraft().gameSettings.guiScale)
+ && IrisApi.getInstance().isShaderPackInUse()) {
+ guiScale = Minecraft.getMinecraft().gameSettings.guiScale;
+ dhEnabled = DhApi.Delayed.configs.graphics().renderingEnabled().getValue();
+ try {
+ Iris.reload();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ return dhEnabled;
+ }
+
+ public boolean incompatiblePack() {
+ return incompatible;
+ }
+
+ public void reconnectDHTextures(int depthTex) {
+ if (((IRenderTargetExt) Minecraft.getMinecraft().getFramebuffer()).iris$getDepthBufferVersion() != cachedVersion) {
+ cachedVersion = ((IRenderTargetExt) Minecraft.getMinecraft().getFramebuffer()).iris$getDepthBufferVersion();
+ createDepthTex(Minecraft.getMinecraft().getFramebuffer().framebufferWidth, Minecraft.getMinecraft().getFramebuffer().framebufferHeight);
+ }
+ if (storedDepthTex != depthTex && dhTerrainFramebuffer != null) {
+ storedDepthTex = depthTex;
+ dhTerrainFramebuffer.addDepthAttachmentBypass(depthTex);
+ if (dhWaterFramebuffer != null) {
+ dhWaterFramebuffer.addDepthAttachmentBypass(depthTex);
+ }
+ if (dhGenericFramebuffer != null) {
+ dhGenericFramebuffer.addDepthAttachmentBypass(depthTex);
+ }
+ }
+ }
+
+ public void createDepthTex(int width, int height) {
+ if (depthTexNoTranslucent != null) {
+ depthTexNoTranslucent.destroy();
+ depthTexNoTranslucent = null;
+ }
+
+ translucentDepthDirty = true;
+
+ depthTexNoTranslucent = new DepthTexture(width, height, DepthBufferFormat.DEPTH32F);
+ }
+
+ public void clear() {
+ if (solidProgram != null) {
+ solidProgram.free();
+ solidProgram = null;
+ }
+ if (translucentProgram != null) {
+ translucentProgram.free();
+ translucentProgram = null;
+ }
+ if (shadowProgram != null) {
+ shadowProgram.free();
+ shadowProgram = null;
+ }
+ shouldOverrideShadow = false;
+ shouldOverride = false;
+ dhTerrainFramebuffer = null;
+ dhWaterFramebuffer = null;
+ dhShadowFramebuffer = null;
+ storedDepthTex = -1;
+ translucentDepthDirty = true;
+
+ OverrideInjector.INSTANCE.unbind(IDhApiFramebuffer.class, dhTerrainFramebufferWrapper);
+ OverrideInjector.INSTANCE.unbind(IDhApiGenericObjectShaderProgram.class, genericShader);
+ OverrideInjector.INSTANCE.unbind(IDhApiFramebuffer.class, dhShadowFramebufferWrapper);
+ dhTerrainFramebufferWrapper = null;
+ dhShadowFramebufferWrapper = null;
+ }
+
+ public void setModelPos(DhApiVec3f modelPos) {
+ solidProgram.bind();
+ solidProgram.setModelPos(modelPos);
+ translucentProgram.bind();
+ translucentProgram.setModelPos(modelPos);
+ solidProgram.bind();
+ }
+
+ public IrisLodRenderProgram getSolidShader() {
+ return solidProgram;
+ }
+
+ public GlFramebuffer getSolidFB() {
+ return dhTerrainFramebuffer;
+ }
+
+ public DhFrameBufferWrapper getSolidFBWrapper() {
+ return dhTerrainFramebufferWrapper;
+ }
+
+ public IrisLodRenderProgram getShadowShader() {
+ return shadowProgram;
+ }
+
+ public GlFramebuffer getShadowFB() {
+ return dhShadowFramebuffer;
+ }
+
+ public DhFrameBufferWrapper getShadowFBWrapper() {
+ return dhShadowFramebufferWrapper;
+ }
+
+ public IrisLodRenderProgram getTranslucentShader() {
+ if (translucentProgram == null) {
+ return solidProgram;
+ }
+ return translucentProgram;
+ }
+
+ public int getStoredDepthTex() {
+ return storedDepthTex;
+ }
+
+ public void copyTranslucents(int width, int height) {
+ if (translucentDepthDirty) {
+ translucentDepthDirty = false;
+ GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, depthTexNoTranslucent.getTextureId());
+ dhTerrainFramebuffer.bindAsReadBuffer();
+ GLStateManager.glCopyTexImage2D(GL11.GL_TEXTURE_2D, 0, DepthBufferFormat.DEPTH32F.getGlInternalFormat(), 0, 0, width, height, 0);
+ } else {
+ DepthCopyStrategy.fastest(false).copy(dhTerrainFramebuffer, storedDepthTex, null, depthTexNoTranslucent.getTextureId(), width, height);
+ }
+ }
+
+ public GlFramebuffer getTranslucentFB() {
+ return dhWaterFramebuffer;
+ }
+
+ public GlFramebuffer getGenericFB() {
+ return dhGenericFramebuffer;
+ }
+
+ public int getDepthTexNoTranslucent() {
+ if (depthTexNoTranslucent == null) return 0;
+
+ return depthTexNoTranslucent.getTextureId();
+ }
+
+ public IDhApiGenericObjectShaderProgram getGenericShader() {
+ return genericShader;
+ }
+
+ public boolean avoidRenderingClouds() {
+ return pipeline != null && (pipeline.getDHCloudSetting() == CloudSetting.OFF || (pipeline.getDHCloudSetting() == CloudSetting.DEFAULT && pipeline.getCloudSetting() == CloudSetting.OFF));
+ }
+}
diff --git a/src/main/java/net/coderbot/iris/compat/dh/DhFrameBufferWrapper.java b/src/main/java/net/coderbot/iris/compat/dh/DhFrameBufferWrapper.java
new file mode 100644
index 000000000..1d4a68cb4
--- /dev/null
+++ b/src/main/java/net/coderbot/iris/compat/dh/DhFrameBufferWrapper.java
@@ -0,0 +1,55 @@
+package net.coderbot.iris.compat.dh;
+
+import com.gtnewhorizons.angelica.glsm.GLStateManager;
+import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiFramebuffer;
+import net.coderbot.iris.gl.framebuffer.GlFramebuffer;
+import org.lwjgl.opengl.GL30;
+
+public class DhFrameBufferWrapper implements IDhApiFramebuffer {
+ private final GlFramebuffer framebuffer;
+
+
+ public DhFrameBufferWrapper(GlFramebuffer framebuffer) {
+ this.framebuffer = framebuffer;
+ }
+
+
+ @Override
+ public boolean overrideThisFrame() {
+ return true;
+ }
+
+ @Override
+ public void bind() {
+ this.framebuffer.bind();
+ }
+
+ @Override
+ public void addDepthAttachment(int i, boolean b) {
+ // ignore
+ }
+
+ @Override
+ public int getId() {
+ return this.framebuffer.getId();
+ }
+
+ @Override
+ public int getStatus() {
+ this.bind();
+ int status = GLStateManager.glCheckFramebufferStatus(GL30.GL_FRAMEBUFFER);
+ return status;
+ }
+
+ @Override
+ public void addColorAttachment(int i, int i1) {
+ // ignore
+ }
+
+ @Override
+ public void destroy() {
+ // ignore
+ //this.framebuffer.destroy();
+ }
+
+}
diff --git a/src/main/java/net/coderbot/iris/compat/dh/IrisGenericRenderProgram.java b/src/main/java/net/coderbot/iris/compat/dh/IrisGenericRenderProgram.java
new file mode 100644
index 000000000..626fae2be
--- /dev/null
+++ b/src/main/java/net/coderbot/iris/compat/dh/IrisGenericRenderProgram.java
@@ -0,0 +1,351 @@
+package net.coderbot.iris.compat.dh;
+
+import com.google.common.primitives.Ints;
+import com.gtnewhorizons.angelica.glsm.GLStateManager;
+import com.gtnewhorizons.angelica.mixins.interfaces.EntityRendererAccessor;
+import com.mitchej123.lwjgl.MemoryStack;
+import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram;
+import com.seibel.distanthorizons.api.interfaces.render.IDhApiRenderableBoxGroup;
+import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
+import com.seibel.distanthorizons.api.objects.math.DhApiMat4f;
+import com.seibel.distanthorizons.api.objects.math.DhApiVec3d;
+import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBox;
+import com.seibel.distanthorizons.api.objects.render.DhApiRenderableBoxGroupShading;
+import net.coderbot.iris.gl.blending.BlendModeOverride;
+import net.coderbot.iris.gl.blending.BufferBlendOverride;
+import net.coderbot.iris.gl.program.ProgramImages;
+import net.coderbot.iris.gl.program.ProgramSamplers;
+import net.coderbot.iris.gl.program.ProgramUniforms;
+import net.coderbot.iris.gl.shader.GlShader;
+import net.coderbot.iris.gl.shader.ShaderType;
+import net.coderbot.iris.gl.state.FogMode;
+import net.coderbot.iris.pipeline.DeferredWorldRenderingPipeline;
+import net.coderbot.iris.pipeline.PatchedShaderPrinter;
+import net.coderbot.iris.pipeline.transform.PatchShaderType;
+import net.coderbot.iris.pipeline.transform.TransformPatcher;
+import net.coderbot.iris.samplers.IrisSamplers;
+import net.coderbot.iris.shaderpack.ProgramSource;
+import net.coderbot.iris.uniforms.CommonUniforms;
+import net.coderbot.iris.uniforms.builtin.BuiltinReplacementUniforms;
+import net.coderbot.iris.uniforms.custom.CustomUniforms;
+import net.irisshaders.iris.api.v0.IrisApi;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.texture.DynamicTexture;
+import org.joml.Matrix3f;
+import org.joml.Matrix4f;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL13;
+import org.lwjgl.opengl.GL15;
+import org.lwjgl.opengl.GL20;
+import org.lwjgl.opengl.GL30;
+
+import java.nio.FloatBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class IrisGenericRenderProgram implements IDhApiGenericObjectShaderProgram {
+ // Uniforms
+ public final int modelViewUniform;
+ public final int modelViewInverseUniform;
+ public final int projectionUniform;
+ public final int projectionInverseUniform;
+ public final int normalMatrix3fUniform;
+ // Fog/Clip Uniforms
+ private final int id;
+ private final ProgramUniforms uniforms;
+ private final CustomUniforms customUniforms;
+ private final ProgramSamplers samplers;
+ private final ProgramImages images;
+ private final BlendModeOverride blend;
+ private final BufferBlendOverride[] bufferBlendOverrides;
+ private final Matrix4f tempModel = new Matrix4f();
+ private final Matrix4f tempProj = new Matrix4f();
+ private final Matrix4f tempMat4 = new Matrix4f();
+ private final Matrix3f tempMat3 = new Matrix3f();
+
+ private final int instancedShaderOffsetChunkUniform;
+ private final int instancedShaderOffsetSubChunkUniform;
+ private final int instancedShaderCameraChunkPosUniform;
+ private final int instancedShaderCameraSubChunkPosUniform;
+ private final int instancedShaderProjectionModelViewMatrixUniform;
+ private final int va;
+ private final int uBlockLight;
+ private final int uSkyLight;
+
+ // This will bind AbstractVertexAttribute
+ private IrisGenericRenderProgram(String name, boolean isShadowPass, boolean translucent, BlendModeOverride override, BufferBlendOverride[] bufferBlendOverrides, String vertex, String tessControl, String tessEval, String geometry, String fragment, CustomUniforms customUniforms, DeferredWorldRenderingPipeline pipeline) {
+ id = GLStateManager.glCreateProgram();
+
+ GLStateManager.glBindAttribLocation(this.id, 0, "vPosition");
+
+ this.bufferBlendOverrides = bufferBlendOverrides;
+
+ GlShader vert = new GlShader(ShaderType.VERTEX, name + ".vsh", vertex);
+ GLStateManager.glAttachShader(id, vert.getHandle());
+
+ GlShader tessCont = null;
+ if (tessControl != null) {
+ tessCont = new GlShader(ShaderType.TESSELATION_CONTROL, name + ".tcs", tessControl);
+ GLStateManager.glAttachShader(id, tessCont.getHandle());
+ }
+
+ GlShader tessE = null;
+ if (tessEval != null) {
+ tessE = new GlShader(ShaderType.TESSELATION_EVAL, name + ".tes", tessEval);
+ GLStateManager.glAttachShader(id, tessE.getHandle());
+ }
+
+ GlShader geom = null;
+ if (geometry != null) {
+ geom = new GlShader(ShaderType.GEOMETRY, name + ".gsh", geometry);
+ GLStateManager.glAttachShader(id, geom.getHandle());
+ }
+
+ GlShader frag = new GlShader(ShaderType.FRAGMENT, name + ".fsh", fragment);
+ GLStateManager.glAttachShader(id, frag.getHandle());
+
+ GLStateManager.glLinkProgram(this.id);
+ int status = GLStateManager.glGetProgrami(this.id, GL20.GL_LINK_STATUS);
+ if (status != 1) {
+ String message = "Shader link error in Iris DH program! Details: " + GLStateManager.glGetProgramInfoLog(this.id, 9999);
+ this.free();
+ throw new RuntimeException(message);
+ } else {
+ GLStateManager.glUseProgram(this.id);
+ }
+
+ vert.destroy();
+ frag.destroy();
+
+ if (tessCont != null) tessCont.destroy();
+ if (tessE != null) tessE.destroy();
+ if (geom != null) geom.destroy();
+
+ blend = override;
+ ProgramUniforms.Builder uniformBuilder = ProgramUniforms.builder(name, id);
+ ProgramSamplers.Builder samplerBuilder = ProgramSamplers.builder(id, IrisSamplers.WORLD_RESERVED_TEXTURE_UNITS);
+ CommonUniforms.addDynamicUniforms(uniformBuilder, FogMode.PER_VERTEX);
+ customUniforms.assignTo(uniformBuilder);
+ BuiltinReplacementUniforms.addBuiltinReplacementUniforms(uniformBuilder);
+ ProgramImages.Builder builder = ProgramImages.builder(id);
+ pipeline.addGbufferOrShadowSamplers(samplerBuilder, builder,
+ isShadowPass ? pipeline::getFlippedBeforeShadow : () -> translucent ? pipeline.getFlippedAfterTranslucent() : pipeline.getFlippedAfterPrepare(),
+ isShadowPass, true, true, false);
+ customUniforms.mapholderToPass(uniformBuilder, this);
+ this.uniforms = uniformBuilder.buildUniforms();
+ this.customUniforms = customUniforms;
+ samplers = samplerBuilder.build();
+ images = builder.build();
+
+ this.va = GLStateManager.glGenVertexArrays();
+ GLStateManager.glBindVertexArray(va);
+ GLStateManager.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 0, 0);
+ GLStateManager.glEnableVertexAttribArray(0);
+
+ projectionUniform = tryGetUniformLocation2("iris_ProjectionMatrix");
+ projectionInverseUniform = tryGetUniformLocation2("iris_ProjectionMatrixInverse");
+ modelViewUniform = tryGetUniformLocation2("iris_ModelViewMatrix");
+ modelViewInverseUniform = tryGetUniformLocation2("iris_ModelViewMatrixInverse");
+ normalMatrix3fUniform = tryGetUniformLocation2("iris_NormalMatrix");
+
+ this.instancedShaderOffsetChunkUniform = this.tryGetUniformLocation2("uOffsetChunk");
+ this.instancedShaderOffsetSubChunkUniform = this.tryGetUniformLocation2("uOffsetSubChunk");
+ this.instancedShaderCameraChunkPosUniform = this.tryGetUniformLocation2("uCameraPosChunk");
+ this.instancedShaderCameraSubChunkPosUniform = this.tryGetUniformLocation2("uCameraPosSubChunk");
+ this.instancedShaderProjectionModelViewMatrixUniform = this.tryGetUniformLocation2("uProjectionMvm");
+ this.uBlockLight = this.tryGetUniformLocation2("uBlockLight");
+ this.uSkyLight = this.tryGetUniformLocation2("uSkyLight");
+ }
+
+ public static IrisGenericRenderProgram createProgram(String name, boolean isShadowPass, boolean translucent, ProgramSource source, CustomUniforms uniforms, DeferredWorldRenderingPipeline pipeline) {
+ Map transformed = TransformPatcher.patchDHGeneric(
+ name,
+ source.getVertexSource().orElseThrow(RuntimeException::new),
+ source.getTessControlSource().orElse(null),
+ source.getTessEvalSource().orElse(null),
+ source.getGeometrySource().orElse(null),
+ source.getFragmentSource().orElseThrow(RuntimeException::new),
+ pipeline.getTextureMap());
+ String vertex = transformed.get(PatchShaderType.VERTEX);
+ String tessControl = transformed.get(PatchShaderType.TESS_CONTROL);
+ String tessEval = transformed.get(PatchShaderType.TESS_EVAL);
+ String geometry = transformed.get(PatchShaderType.GEOMETRY);
+ String fragment = transformed.get(PatchShaderType.FRAGMENT);
+ PatchedShaderPrinter.debugPatchedShaders(source.getName() + "_g", vertex, geometry, tessControl, tessEval, fragment);
+
+ List bufferOverrides = new ArrayList<>();
+
+ source.getDirectives().getBufferBlendOverrides().forEach(information -> {
+ int index = Ints.indexOf(source.getDirectives().getDrawBuffers(), information.getIndex());
+ if (index > -1) {
+ bufferOverrides.add(new BufferBlendOverride(index, information.getBlendMode()));
+ }
+ });
+
+ return new IrisGenericRenderProgram(name, isShadowPass, translucent, source.getDirectives().getBlendModeOverride().orElse(null), bufferOverrides.toArray(BufferBlendOverride[]::new), vertex, tessControl, tessEval, geometry, fragment, uniforms, pipeline);
+ }
+
+ // Noise Uniforms
+
+ private static int getChunkPosFromDouble(double value) {
+ return (int) Math.floor(value / 16);
+ }
+
+ private static float getSubChunkPosFromDouble(double value) {
+ double chunkPos = Math.floor(value / 16);
+ return (float) (value - chunkPos * 16);
+ }
+
+ public int tryGetUniformLocation2(CharSequence name) {
+ return GLStateManager.glGetUniformLocation(this.id, name);
+ }
+
+ public void setUniform(int index, Matrix4f matrix) {
+ if (index == -1 || matrix == null) return;
+
+ try (MemoryStack stack = MemoryStack.stackPush()) {
+ FloatBuffer buffer = stack.callocFloat(16);
+ matrix.get(buffer);
+ buffer.rewind();
+
+ GLStateManager.glUniformMatrix4(index, false, buffer);
+ }
+ }
+
+ public void setUniform(int index, Matrix3f matrix) {
+ if (index == -1) return;
+
+ try (MemoryStack stack = MemoryStack.stackPush()) {
+ FloatBuffer buffer = stack.callocFloat(9);
+ matrix.get(buffer);
+ buffer.rewind();
+
+ GLStateManager.glUniformMatrix3(index, false, buffer);
+ }
+ }
+
+ // Override ShaderProgram.bind()
+ public void bind(DhApiRenderParam renderParam) {
+ GLStateManager.glBindVertexArray(va);
+ GLStateManager.glUseProgram(id);
+ if (blend != null) blend.apply();
+
+ for (BufferBlendOverride override : bufferBlendOverrides) {
+ override.apply();
+ }
+
+ toJOML(tempModel, renderParam.dhModelViewMatrix);
+ toJOML(tempProj, renderParam.dhProjectionMatrix);
+
+ setUniform(modelViewUniform, tempModel);
+ setUniform(projectionUniform, tempProj);
+ this.setUniform(this.instancedShaderProjectionModelViewMatrixUniform, tempMat4.set(tempProj).mul(tempModel));
+ tempModel.invert();
+ tempProj.invert();
+ setUniform(modelViewInverseUniform, tempModel);
+ setUniform(projectionInverseUniform, tempProj);
+ setUniform(normalMatrix3fUniform, tempModel.transpose3x3(tempMat3));
+ GLStateManager.glActiveTexture(GL13.GL_TEXTURE0 + IrisSamplers.LIGHTMAP_TEXTURE_UNIT);
+ DynamicTexture lightmapTexture = ((EntityRendererAccessor) Minecraft.getMinecraft().entityRenderer).getLightmapTexture();
+ GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, lightmapTexture.getGlTextureId());
+
+ samplers.update();
+ uniforms.update();
+
+ customUniforms.push(this);
+
+ images.update();
+ }
+
+ public void unbind() {
+ GLStateManager.glBindVertexArray(0);
+ GLStateManager.glUseProgram(0);
+ ProgramUniforms.clearActiveUniforms();
+ ProgramSamplers.clearActiveSamplers();
+ BlendModeOverride.restore();
+ }
+
+ @Override
+ public void bindVertexBuffer(int i) {
+ GLStateManager.glBindBuffer(GL15.GL_ARRAY_BUFFER, i);
+ GLStateManager.glVertexAttribPointer(0, 3, GL11.GL_FLOAT, false, 12, 0);
+ }
+
+ @Override
+ public boolean overrideThisFrame() {
+ return IrisApi.getInstance().isShaderPackInUse();
+ }
+
+ @Override
+ public int getId() {
+ return id;
+ }
+
+ public void free() {
+ GLStateManager.glDeleteProgram(id);
+ }
+
+ public void fillIndirectUniformData(DhApiRenderParam dhApiRenderParam, DhApiRenderableBoxGroupShading dhApiRenderableBoxGroupShading, IDhApiRenderableBoxGroup boxGroup, DhApiVec3d camPos) {
+ bind(dhApiRenderParam);
+ GLStateManager.enableDepthTest();
+ GLStateManager.glDepthFunc(GL11.GL_LEQUAL);
+ this.setUniform(this.instancedShaderOffsetChunkUniform,
+ getChunkPosFromDouble(boxGroup.getOriginBlockPos().x),
+ getChunkPosFromDouble(boxGroup.getOriginBlockPos().y),
+ getChunkPosFromDouble(boxGroup.getOriginBlockPos().z)
+ );
+ this.setUniform(this.instancedShaderOffsetSubChunkUniform,
+ getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().x),
+ getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().y),
+ getSubChunkPosFromDouble(boxGroup.getOriginBlockPos().z)
+ );
+
+ this.setUniform(this.instancedShaderCameraChunkPosUniform,
+ getChunkPosFromDouble(camPos.x),
+ getChunkPosFromDouble(camPos.y),
+ getChunkPosFromDouble(camPos.z)
+ );
+ this.setUniform(this.instancedShaderCameraSubChunkPosUniform,
+ getSubChunkPosFromDouble(camPos.x),
+ getSubChunkPosFromDouble(camPos.y),
+ getSubChunkPosFromDouble(camPos.z)
+ );
+ this.setUniform(this.uBlockLight,
+ boxGroup.getBlockLight());
+ this.setUniform(this.uSkyLight,
+ boxGroup.getSkyLight());
+
+ }
+
+ @Override
+ public void fillSharedDirectUniformData(DhApiRenderParam dhApiRenderParam, DhApiRenderableBoxGroupShading dhApiRenderableBoxGroupShading, IDhApiRenderableBoxGroup iDhApiRenderableBoxGroup, DhApiVec3d dhApiVec3d) {
+ throw new IllegalStateException("Only indirect is supported with Iris.");
+ }
+
+ @Override
+ public void fillDirectUniformData(DhApiRenderParam dhApiRenderParam, IDhApiRenderableBoxGroup iDhApiRenderableBoxGroup, DhApiRenderableBox dhApiRenderableBox, DhApiVec3d dhApiVec3d) {
+ throw new IllegalStateException("Only indirect is supported with Iris.");
+ }
+
+ private void toJOML(Matrix4f target, DhApiMat4f mat4f) {
+ target.setTransposed(mat4f.getValuesAsArray());
+ }
+
+ private void setUniform(int index, int value) {
+ GLStateManager.glUniform1i(index, value);
+ }
+
+ private void setUniform(int index, float value) {
+ GLStateManager.glUniform1f(index, value);
+ }
+
+ private void setUniform(int index, float x, float y, float z) {
+ GLStateManager.glUniform3f(index, x, y, z);
+ }
+
+ private void setUniform(int index, int x, int y, int z) {
+ GLStateManager.glUniform3i(index, x, y, z);
+ }
+
+}
diff --git a/src/main/java/net/coderbot/iris/compat/dh/IrisLodRenderProgram.java b/src/main/java/net/coderbot/iris/compat/dh/IrisLodRenderProgram.java
new file mode 100644
index 000000000..659b198cb
--- /dev/null
+++ b/src/main/java/net/coderbot/iris/compat/dh/IrisLodRenderProgram.java
@@ -0,0 +1,266 @@
+package net.coderbot.iris.compat.dh;
+
+import com.google.common.primitives.Ints;
+import com.gtnewhorizons.angelica.glsm.GLStateManager;
+import com.gtnewhorizons.angelica.mixins.interfaces.EntityRendererAccessor;
+import com.mitchej123.lwjgl.MemoryStack;
+import com.seibel.distanthorizons.api.DhApi;
+import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
+import net.coderbot.iris.gl.blending.BlendModeOverride;
+import net.coderbot.iris.gl.blending.BufferBlendOverride;
+import net.coderbot.iris.gl.program.ProgramImages;
+import net.coderbot.iris.gl.program.ProgramSamplers;
+import net.coderbot.iris.gl.program.ProgramUniforms;
+import net.coderbot.iris.gl.shader.GlShader;
+import net.coderbot.iris.gl.shader.ShaderType;
+import net.coderbot.iris.gl.state.FogMode;
+import net.coderbot.iris.gl.texture.TextureType;
+import net.coderbot.iris.pipeline.DeferredWorldRenderingPipeline;
+import net.coderbot.iris.pipeline.PatchedShaderPrinter;
+import net.coderbot.iris.pipeline.transform.PatchShaderType;
+import net.coderbot.iris.pipeline.transform.TransformPatcher;
+import net.coderbot.iris.samplers.IrisSamplers;
+import net.coderbot.iris.shaderpack.ProgramSource;
+import net.coderbot.iris.uniforms.CommonUniforms;
+import net.coderbot.iris.uniforms.builtin.BuiltinReplacementUniforms;
+import net.coderbot.iris.uniforms.custom.CustomUniforms;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.renderer.texture.DynamicTexture;
+import org.joml.Matrix3f;
+import org.joml.Matrix4f;
+import org.joml.Matrix4fc;
+import org.lwjgl.opengl.GL11;
+import org.lwjgl.opengl.GL13;
+import org.lwjgl.opengl.GL20;
+import org.lwjgl.opengl.GL32;
+
+import java.nio.FloatBuffer;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Map;
+
+public class IrisLodRenderProgram {
+ // Uniforms
+ public final int modelOffsetUniform;
+ public final int worldYOffsetUniform;
+ public final int mircoOffsetUniform;
+ public final int modelViewUniform;
+ public final int modelViewInverseUniform;
+ public final int projectionUniform;
+ public final int projectionInverseUniform;
+ public final int normalMatrix3fUniform;
+ // Fog/Clip Uniforms
+ public final int clipDistanceUniform;
+ private final int id;
+ private final ProgramUniforms uniforms;
+ private final CustomUniforms customUniforms;
+ private final ProgramSamplers samplers;
+ private final ProgramImages images;
+ private final BlendModeOverride blend;
+ private final BufferBlendOverride[] bufferBlendOverrides;
+ private final Matrix4f tempMat4a = new Matrix4f();
+ private final Matrix4f tempMat4b = new Matrix4f();
+ private final Matrix3f tempMat3 = new Matrix3f();
+
+ // This will bind AbstractVertexAttribute
+ private IrisLodRenderProgram(String name, boolean isShadowPass, boolean translucent, BlendModeOverride override, BufferBlendOverride[] bufferBlendOverrides, String vertex, String tessControl, String tessEval, String geometry, String fragment, CustomUniforms customUniforms, DeferredWorldRenderingPipeline pipeline) {
+ id = GLStateManager.glCreateProgram();
+
+ GLStateManager.glBindAttribLocation(this.id, 0, "vPosition");
+ GLStateManager.glBindAttribLocation(this.id, 1, "iris_color");
+ GLStateManager.glBindAttribLocation(this.id, 2, "irisExtra");
+
+ this.bufferBlendOverrides = bufferBlendOverrides;
+
+ GlShader vert = new GlShader(ShaderType.VERTEX, name + ".vsh", vertex);
+ GLStateManager.glAttachShader(id, vert.getHandle());
+
+ GlShader tessCont = null;
+ if (tessControl != null) {
+ tessCont = new GlShader(ShaderType.TESSELATION_CONTROL, name + ".tcs", tessControl);
+ GLStateManager.glAttachShader(id, tessCont.getHandle());
+ }
+
+ GlShader tessE = null;
+ if (tessEval != null) {
+ tessE = new GlShader(ShaderType.TESSELATION_EVAL, name + ".tes", tessEval);
+ GLStateManager.glAttachShader(id, tessE.getHandle());
+ }
+
+ GlShader geom = null;
+ if (geometry != null) {
+ geom = new GlShader(ShaderType.GEOMETRY, name + ".gsh", geometry);
+ GLStateManager.glAttachShader(id, geom.getHandle());
+ }
+
+ GlShader frag = new GlShader(ShaderType.FRAGMENT, name + ".fsh", fragment);
+ GLStateManager.glAttachShader(id, frag.getHandle());
+
+ GLStateManager.glLinkProgram(this.id);
+ int status = GLStateManager.glGetProgrami(this.id, GL20.GL_LINK_STATUS);
+ if (status != 1) {
+ String message = "Shader link error in Iris DH program! Details: " + GLStateManager.glGetProgramInfoLog(this.id, 9999);
+ this.free();
+ throw new RuntimeException(message);
+ } else {
+ GLStateManager.glUseProgram(this.id);
+ }
+
+ vert.destroy();
+ frag.destroy();
+
+ if (tessCont != null) tessCont.destroy();
+ if (tessE != null) tessE.destroy();
+ if (geom != null) geom.destroy();
+
+ blend = override;
+ ProgramUniforms.Builder uniformBuilder = ProgramUniforms.builder(name, id);
+ ProgramSamplers.Builder samplerBuilder = ProgramSamplers.builder(id, IrisSamplers.WORLD_RESERVED_TEXTURE_UNITS);
+ CommonUniforms.addDynamicUniforms(uniformBuilder, FogMode.PER_VERTEX);
+ customUniforms.assignTo(uniformBuilder);
+ BuiltinReplacementUniforms.addBuiltinReplacementUniforms(uniformBuilder);
+ ProgramImages.Builder builder = ProgramImages.builder(id);
+ pipeline.addGbufferOrShadowSamplers(samplerBuilder, builder,
+ isShadowPass ? pipeline::getFlippedBeforeShadow : () -> translucent ? pipeline.getFlippedAfterTranslucent() : pipeline.getFlippedAfterPrepare(),
+ isShadowPass, true, true, false);
+ customUniforms.mapholderToPass(uniformBuilder, this);
+ this.uniforms = uniformBuilder.buildUniforms();
+ this.customUniforms = customUniforms;
+ samplers = samplerBuilder.build();
+ images = builder.build();
+
+ modelOffsetUniform = tryGetUniformLocation2("modelOffset");
+ worldYOffsetUniform = tryGetUniformLocation2("worldYOffset");
+ mircoOffsetUniform = tryGetUniformLocation2("mircoOffset");
+ projectionUniform = tryGetUniformLocation2("iris_ProjectionMatrix");
+ projectionInverseUniform = tryGetUniformLocation2("iris_ProjectionMatrixInverse");
+ modelViewUniform = tryGetUniformLocation2("iris_ModelViewMatrix");
+ modelViewInverseUniform = tryGetUniformLocation2("iris_ModelViewMatrixInverse");
+ normalMatrix3fUniform = tryGetUniformLocation2("iris_NormalMatrix");
+
+ // Fog/Clip Uniforms
+ clipDistanceUniform = tryGetUniformLocation2("clipDistance");
+ }
+
+ public static IrisLodRenderProgram createProgram(String name, boolean isShadowPass, boolean translucent, ProgramSource source, CustomUniforms uniforms, DeferredWorldRenderingPipeline pipeline) {
+ Map transformed = TransformPatcher.patchDHTerrain(
+ name,
+ source.getVertexSource().orElseThrow(RuntimeException::new),
+ source.getTessControlSource().orElse(null),
+ source.getTessEvalSource().orElse(null),
+ source.getGeometrySource().orElse(null),
+ source.getFragmentSource().orElseThrow(RuntimeException::new),
+ pipeline.getTextureMap());
+ String vertex = transformed.get(PatchShaderType.VERTEX);
+ String tessControl = transformed.get(PatchShaderType.TESS_CONTROL);
+ String tessEval = transformed.get(PatchShaderType.TESS_EVAL);
+ String geometry = transformed.get(PatchShaderType.GEOMETRY);
+ String fragment = transformed.get(PatchShaderType.FRAGMENT);
+ PatchedShaderPrinter.debugPatchedShaders(source.getName(), vertex, geometry, tessControl, tessEval, fragment);
+
+ List bufferOverrides = new ArrayList<>();
+
+ source.getDirectives().getBufferBlendOverrides().forEach(information -> {
+ int index = Ints.indexOf(source.getDirectives().getDrawBuffers(), information.getIndex());
+ if (index > -1) {
+ bufferOverrides.add(new BufferBlendOverride(index, information.getBlendMode()));
+ }
+ });
+
+ return new IrisLodRenderProgram(name, isShadowPass, translucent, source.getDirectives().getBlendModeOverride().orElse(null), bufferOverrides.toArray(BufferBlendOverride[]::new), vertex, tessControl, tessEval, geometry, fragment, uniforms, pipeline);
+ }
+
+ // Noise Uniforms
+
+ public int tryGetUniformLocation2(CharSequence name) {
+ return GLStateManager.glGetUniformLocation(this.id, name);
+ }
+
+ public void setUniform(int index, Matrix4fc matrix) {
+ if (index == -1 || matrix == null) return;
+
+ try (MemoryStack stack = MemoryStack.stackPush()) {
+ FloatBuffer buffer = stack.callocFloat(16);
+ matrix.get(buffer);
+ buffer.rewind();
+
+ GLStateManager.glUniformMatrix4(index, false, buffer);
+ }
+ }
+
+ public void setUniform(int index, Matrix3f matrix) {
+ if (index == -1) return;
+
+ try (MemoryStack stack = MemoryStack.stackPush()) {
+ FloatBuffer buffer = stack.callocFloat(9);
+ matrix.get(buffer);
+ buffer.rewind();
+
+ GLStateManager.glUniformMatrix3(index, false, buffer);
+ }
+ }
+
+ // Override ShaderProgram.bind()
+ public void bind() {
+ GLStateManager.glUseProgram(id);
+ if (blend != null) blend.apply();
+
+ for (BufferBlendOverride override : bufferBlendOverrides) {
+ override.apply();
+ }
+ }
+
+ public void unbind() {
+ GLStateManager.glUseProgram(0);
+ ProgramUniforms.clearActiveUniforms();
+ ProgramSamplers.clearActiveSamplers();
+ BlendModeOverride.restore();
+ }
+
+ public void free() {
+ GLStateManager.glDeleteProgram(id);
+ }
+
+ public void fillUniformData(Matrix4fc projection, Matrix4fc modelView, int worldYOffset, float partialTicks) {
+ GLStateManager.glUseProgram(id);
+
+ GLStateManager.glActiveTexture(GL13.GL_TEXTURE0 + IrisSamplers.LIGHTMAP_TEXTURE_UNIT);
+ DynamicTexture lightmapTexture = ((EntityRendererAccessor) Minecraft.getMinecraft().entityRenderer).getLightmapTexture();
+ GLStateManager.glBindTexture(GL11.GL_TEXTURE_2D, lightmapTexture.getGlTextureId());
+ setUniform(modelViewUniform, modelView);
+ setUniform(modelViewInverseUniform, modelView.invert(tempMat4a));
+ setUniform(projectionUniform, projection);
+ setUniform(projectionInverseUniform, projection.invert(tempMat4b));
+ setUniform(normalMatrix3fUniform, tempMat4a.set(modelView).invert().transpose3x3(tempMat3));
+
+ setUniform(mircoOffsetUniform, 0.01f); // 0.01 block offset
+
+ // setUniform(skyLightUniform, skyLight);
+
+ if (worldYOffsetUniform != -1) setUniform(worldYOffsetUniform, (float) worldYOffset);
+
+ // Fog/Clip Uniforms
+ float dhNearClipDistance = DhApi.Delayed.renderProxy.getNearClipPlaneDistanceInBlocks(partialTicks);
+ setUniform(clipDistanceUniform, dhNearClipDistance);
+
+ samplers.update();
+ uniforms.update();
+
+ customUniforms.push(this);
+
+ images.update();
+ }
+
+ private void setUniform(int index, float value) {
+ GLStateManager.glUniform1f(index, value);
+ }
+
+ public void setModelPos(DhApiVec3f modelPos) {
+ setUniform(modelOffsetUniform, modelPos);
+ }
+
+ private void setUniform(int index, DhApiVec3f pos) {
+ GLStateManager.glUniform3f(index, pos.x, pos.y, pos.z);
+ }
+
+}
diff --git a/src/main/java/net/coderbot/iris/compat/dh/LodRendererEvents.java b/src/main/java/net/coderbot/iris/compat/dh/LodRendererEvents.java
new file mode 100644
index 000000000..76651e487
--- /dev/null
+++ b/src/main/java/net/coderbot/iris/compat/dh/LodRendererEvents.java
@@ -0,0 +1,383 @@
+package net.coderbot.iris.compat.dh;
+
+import com.gtnewhorizons.angelica.glsm.GLStateManager;
+import com.gtnewhorizons.angelica.rendering.RenderingState;
+import com.seibel.distanthorizons.api.DhApi;
+import com.seibel.distanthorizons.api.enums.rendering.EDhApiFogDrawMode;
+import com.seibel.distanthorizons.api.enums.rendering.EDhApiRenderPass;
+import com.seibel.distanthorizons.api.interfaces.override.IDhApiOverrideable;
+import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiFramebuffer;
+import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiGenericObjectShaderProgram;
+import com.seibel.distanthorizons.api.interfaces.override.rendering.IDhApiShadowCullingFrustum;
+import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiAfterDhInitEvent;
+import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeApplyShaderRenderEvent;
+import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeBufferRenderEvent;
+import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeDeferredRenderEvent;
+import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeGenericObjectRenderEvent;
+import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeGenericRenderSetupEvent;
+import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeRenderCleanupEvent;
+import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeRenderEvent;
+import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeRenderPassEvent;
+import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeRenderSetupEvent;
+import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeTextureClearEvent;
+import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiColorDepthTextureCreatedEvent;
+import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiCancelableEventParam;
+import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiEventParam;
+import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam;
+import com.seibel.distanthorizons.api.objects.math.DhApiVec3f;
+import com.seibel.distanthorizons.coreapi.DependencyInjection.OverrideInjector;
+import net.coderbot.iris.Iris;
+import net.coderbot.iris.pipeline.ShadowRenderer;
+import net.coderbot.iris.pipeline.WorldRenderingPipeline;
+import net.coderbot.iris.shadows.ShadowRenderingState;
+import net.coderbot.iris.uniforms.CapturedRenderingState;
+import net.irisshaders.iris.api.v0.IrisApi;
+import org.joml.Matrix4f;
+import org.lwjgl.opengl.GL11;
+
+public class LodRendererEvents {
+ // TODO: Query actual world min height for Cubic Chunks compatibility
+ private static final int WORLD_MIN_Y = 0;
+
+ private static boolean eventHandlersBound = false;
+
+ private static boolean atTranslucent = false;
+ private static int textureWidth;
+ private static int textureHeight;
+ private static final Matrix4f tempMat4 = new Matrix4f();
+
+
+ // constructor //
+
+ public static void setupEventHandlers() {
+ if (!eventHandlersBound) {
+ eventHandlersBound = true;
+ Iris.logger.info("Queuing DH event binding...");
+
+ DhApiAfterDhInitEvent beforeCleanupEvent = new DhApiAfterDhInitEvent() {
+ @Override
+ public void afterDistantHorizonsInit(DhApiEventParam event) {
+ Iris.logger.info("DH Ready, binding Iris event handlers...");
+
+ Iris.loadShaderpackWhenPossible();
+
+ setupSetDeferredBeforeRenderingEvent();
+ setupReconnectDepthTextureEvent();
+ setupGenericEvent();
+ setupCreateDepthTextureEvent();
+ setupTransparentRendererEventCancling();
+ setupBeforeBufferClearEvent();
+ setupBeforeRenderCleanupEvent();
+ beforeBufferRenderEvent();
+ setupBeforeRenderFrameBufferBinding();
+ setupBeforeRenderPassEvent();
+ setupBeforeApplyShaderEvent();
+ DHCompatInternal.dhEnabled = DhApi.Delayed.configs.graphics().renderingEnabled().getValue();
+ Iris.logger.info("DH Iris events bound.");
+ }
+ };
+ DhApi.events.bind(DhApiAfterDhInitEvent.class, beforeCleanupEvent);
+ }
+ }
+
+
+ // setup event handlers //
+
+
+ private static void setupSetDeferredBeforeRenderingEvent() {
+ DhApiBeforeRenderEvent beforeRenderEvent = new DhApiBeforeRenderEvent() {
+ // this event is called before DH starts any rendering prep
+ // canceling it will prevent DH from rendering for that frame
+ @Override
+ public void beforeRender(DhApiCancelableEventParam event) {
+
+ DhApi.Delayed.renderProxy.setDeferTransparentRendering(IrisApi.getInstance().isShaderPackInUse() && getInstance().shouldOverride);
+ DhApi.Delayed.configs.graphics().fog().drawMode().setValue(getInstance().shouldOverride ? EDhApiFogDrawMode.FOG_DISABLED : EDhApiFogDrawMode.FOG_ENABLED);
+ }
+ };
+
+ DhApi.events.bind(DhApiBeforeRenderEvent.class, beforeRenderEvent);
+ }
+
+ private static void setupReconnectDepthTextureEvent() {
+ DhApiBeforeTextureClearEvent beforeRenderEvent = new DhApiBeforeTextureClearEvent() {
+ @Override
+ public void beforeClear(DhApiCancelableEventParam event) {
+ var getResult = DhApi.Delayed.renderProxy.getDhDepthTextureId();
+ if (getResult.success) {
+ int depthTextureId = getResult.payload;
+ getInstance().reconnectDHTextures(depthTextureId);
+ }
+ }
+ };
+
+ DhApi.events.bind(DhApiBeforeTextureClearEvent.class, beforeRenderEvent);
+ }
+
+ private static void setupGenericEvent() {
+ DhApiBeforeGenericRenderSetupEvent beforeRenderEvent = new DhApiBeforeGenericRenderSetupEvent() {
+ @Override
+ public void beforeSetup(DhApiEventParam dhApiEventParam) {
+ if (getInstance().getGenericFB() != null) {
+ getInstance().getGenericFB().bind();
+ }
+ }
+ };
+
+ DhApiBeforeGenericObjectRenderEvent beforeDrawEvent = new DhApiBeforeGenericObjectRenderEvent() {
+ @Override
+ public void beforeRender(DhApiCancelableEventParam dhApiCancelableEventParam) {
+ if (dhApiCancelableEventParam.value.resourceLocationPath.equalsIgnoreCase("Clouds")) {
+ if (getInstance().avoidRenderingClouds()) {
+ dhApiCancelableEventParam.cancelEvent();
+ }
+ }
+ }
+ };
+
+ DhApi.events.bind(DhApiBeforeGenericRenderSetupEvent.class, beforeRenderEvent);
+ DhApi.events.bind(DhApiBeforeGenericObjectRenderEvent.class, beforeDrawEvent);
+ }
+
+ private static DHCompatInternal getInstance() {
+ return Iris.getPipelineManager().getPipeline().map(WorldRenderingPipeline::getDHCompat).map(DHCompat::getInstance).orElse(DHCompatInternal.SHADERLESS);
+ }
+
+ private static void setupCreateDepthTextureEvent() {
+ DhApiColorDepthTextureCreatedEvent beforeRenderEvent = new DhApiColorDepthTextureCreatedEvent() {
+ @Override
+ public void onResize(DhApiEventParam input) {
+ textureWidth = input.value.newWidth;
+ textureHeight = input.value.newHeight;
+ }
+ };
+
+ DhApi.events.bind(DhApiColorDepthTextureCreatedEvent.class, beforeRenderEvent);
+ }
+
+ private static void setupTransparentRendererEventCancling() {
+ DhApiBeforeRenderEvent beforeRenderEvent = new DhApiBeforeRenderEvent() {
+ @Override
+ public void beforeRender(DhApiCancelableEventParam event) {
+ if (ShadowRenderingState.areShadowsCurrentlyBeingRendered() && (!getInstance().shouldOverrideShadow)) {
+ event.cancelEvent();
+ }
+ }
+ };
+ DhApiBeforeDeferredRenderEvent beforeRenderEvent2 = new DhApiBeforeDeferredRenderEvent() {
+ @Override
+ public void beforeRender(DhApiCancelableEventParam event) {
+ if (ShadowRenderingState.areShadowsCurrentlyBeingRendered() && (!getInstance().shouldOverrideShadow)) {
+ event.cancelEvent();
+ }
+ }
+ };
+
+ DhApi.events.bind(DhApiBeforeRenderEvent.class, beforeRenderEvent);
+ DhApi.events.bind(DhApiBeforeDeferredRenderEvent.class, beforeRenderEvent2);
+ }
+
+ private static void setupBeforeRenderCleanupEvent() {
+ DhApiBeforeRenderCleanupEvent beforeCleanupEvent = new DhApiBeforeRenderCleanupEvent() {
+ @Override
+ public void beforeCleanup(DhApiEventParam event) {
+ if (getInstance().shouldOverride) {
+ if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) {
+ getInstance().getShadowShader().unbind();
+ } else {
+ getInstance().getSolidShader().unbind();
+ if (atTranslucent) {
+ GLStateManager.enableCull();
+ }
+ }
+ }
+ }
+ };
+
+ DhApi.events.bind(DhApiBeforeRenderCleanupEvent.class, beforeCleanupEvent);
+ }
+
+ private static void setupBeforeBufferClearEvent() {
+ DhApiBeforeTextureClearEvent beforeCleanupEvent = new DhApiBeforeTextureClearEvent() {
+ @Override
+ public void beforeClear(DhApiCancelableEventParam event) {
+ if (event.value.renderPass == EDhApiRenderPass.OPAQUE) {
+ if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) {
+ event.cancelEvent();
+ } else if (getInstance().shouldOverride) {
+ GLStateManager.glClear(GL11.GL_DEPTH_BUFFER_BIT);
+ event.cancelEvent();
+ }
+ }
+ }
+ };
+
+ DhApi.events.bind(DhApiBeforeTextureClearEvent.class, beforeCleanupEvent);
+ }
+
+ private static void beforeBufferRenderEvent() {
+ DhApiBeforeBufferRenderEvent beforeCleanupEvent = new DhApiBeforeBufferRenderEvent() {
+ @Override
+ public void beforeRender(DhApiEventParam input) {
+ DHCompatInternal instance = getInstance();
+ if (instance.shouldOverride) {
+ DhApiVec3f modelPos = input.value.modelPos;
+ if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) {
+ instance.getShadowShader().bind();
+ instance.getShadowShader().setModelPos(modelPos);
+ } else if (atTranslucent) {
+ instance.getTranslucentShader().bind();
+ instance.getTranslucentShader().setModelPos(modelPos);
+ } else {
+ instance.getSolidShader().bind();
+ instance.getSolidShader().setModelPos(modelPos);
+ }
+ }
+ }
+ };
+
+ DhApi.events.bind(DhApiBeforeBufferRenderEvent.class, beforeCleanupEvent);
+ }
+
+ private static void setupBeforeRenderFrameBufferBinding() {
+ DhApiBeforeRenderSetupEvent beforeRenderPassEvent = new DhApiBeforeRenderSetupEvent() {
+ @Override
+ public void beforeSetup(DhApiEventParam event) {
+ DHCompatInternal instance = getInstance();
+
+ OverrideInjector.INSTANCE.unbind(IDhApiShadowCullingFrustum.class, (IDhApiOverrideable) ShadowRenderer.FRUSTUM);
+ OverrideInjector.INSTANCE.unbind(IDhApiFramebuffer.class, instance.getShadowFBWrapper());
+ OverrideInjector.INSTANCE.unbind(IDhApiFramebuffer.class, instance.getSolidFBWrapper());
+ OverrideInjector.INSTANCE.unbind(IDhApiGenericObjectShaderProgram.class, instance.getGenericShader());
+
+ if (instance.shouldOverride) {
+ if (instance.getGenericShader() != null) {
+ OverrideInjector.INSTANCE.bind(IDhApiGenericObjectShaderProgram.class, instance.getGenericShader());
+ }
+ if (ShadowRenderingState.areShadowsCurrentlyBeingRendered() && instance.shouldOverrideShadow) {
+ OverrideInjector.INSTANCE.bind(IDhApiFramebuffer.class, instance.getShadowFBWrapper());
+ OverrideInjector.INSTANCE.bind(IDhApiShadowCullingFrustum.class, (IDhApiOverrideable) ShadowRenderer.FRUSTUM);
+ } else {
+ OverrideInjector.INSTANCE.bind(IDhApiFramebuffer.class, instance.getSolidFBWrapper());
+ }
+ }
+ }
+ };
+ DhApi.events.bind(DhApiBeforeRenderSetupEvent.class, beforeRenderPassEvent);
+
+ }
+
+ private static void setupBeforeRenderPassEvent() {
+ DhApiBeforeRenderPassEvent beforeCleanupEvent = new DhApiBeforeRenderPassEvent() {
+ @Override
+ public void beforeRender(DhApiEventParam event) {
+ DHCompatInternal instance = getInstance();
+
+ // config overrides
+ if (instance.shouldOverride) {
+ DhApi.Delayed.configs.graphics().ambientOcclusion().enabled().setValue(false);
+ DhApi.Delayed.configs.graphics().fog().drawMode().setValue(EDhApiFogDrawMode.FOG_DISABLED);
+
+ if (event.value.renderPass == EDhApiRenderPass.OPAQUE_AND_TRANSPARENT) {
+ Iris.logger.error("Unexpected; somehow the Opaque + Translucent pass ran with shaders on.");
+ }
+ } else {
+ DhApi.Delayed.configs.graphics().ambientOcclusion().enabled().clearValue();
+ DhApi.Delayed.configs.graphics().fog().drawMode().clearValue();
+ }
+
+
+ // cleanup
+ if (event.value.renderPass == EDhApiRenderPass.OPAQUE) {
+ if (instance.shouldOverride) {
+ if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) {
+ instance.getShadowShader().bind();
+ } else {
+ instance.getSolidShader().bind();
+ }
+ atTranslucent = false;
+ }
+ }
+
+
+ // opaque
+ if (event.value.renderPass == EDhApiRenderPass.OPAQUE) {
+ float partialTicks = event.value.partialTicks;
+
+ if (instance.shouldOverride) {
+ if (ShadowRenderingState.areShadowsCurrentlyBeingRendered()) {
+ instance.getShadowShader().fillUniformData(
+ ShadowRenderer.PROJECTION, ShadowRenderer.MODELVIEW,
+ WORLD_MIN_Y,
+ partialTicks);
+ } else {
+ Matrix4f projection = RenderingState.INSTANCE.getProjectionMatrix();;
+
+ instance.getSolidShader().fillUniformData(
+ tempMat4.setPerspective(projection.perspectiveFov(), projection.m11() / projection.m00(), event.value.nearClipPlane, event.value.farClipPlane),
+ RenderingState.INSTANCE.getModelViewMatrix(),
+ WORLD_MIN_Y,
+ partialTicks);
+ }
+ }
+ }
+
+
+ // transparent
+ if (event.value.renderPass == EDhApiRenderPass.TRANSPARENT) {
+ float partialTicks = event.value.partialTicks;
+ int depthTextureId = DhApi.Delayed.renderProxy.getDhDepthTextureId().payload;
+
+ if (instance.shouldOverrideShadow && ShadowRenderingState.areShadowsCurrentlyBeingRendered()) {
+ instance.getShadowShader().bind();
+ instance.getShadowFB().bind();
+ atTranslucent = true;
+
+ return;
+ }
+
+ if (instance.shouldOverride && instance.getTranslucentFB() != null) {
+ instance.copyTranslucents(textureWidth, textureHeight);
+ instance.getTranslucentShader().bind();
+ Matrix4f projection = RenderingState.INSTANCE.getProjectionMatrix();
+ GLStateManager.disableCull();
+
+ instance.getTranslucentShader().fillUniformData(
+ new Matrix4f().setPerspective(projection.perspectiveFov(), projection.m11() / projection.m00(), event.value.nearClipPlane, event.value.farClipPlane),
+ RenderingState.INSTANCE.getModelViewMatrix(),
+ WORLD_MIN_Y,
+ partialTicks);
+
+ instance.getTranslucentFB().bind();
+ }
+
+ atTranslucent = true;
+ }
+
+ }
+ };
+
+ DhApi.events.bind(DhApiBeforeRenderPassEvent.class, beforeCleanupEvent);
+ }
+
+ private static void setupBeforeApplyShaderEvent() {
+ DhApiBeforeApplyShaderRenderEvent beforeApplyShaderEvent = new DhApiBeforeApplyShaderRenderEvent() {
+ @Override
+ public void beforeRender(DhApiCancelableEventParam event) {
+ if (IrisApi.getInstance().isShaderPackInUse()) {
+ DHCompatInternal instance = getInstance();
+
+ OverrideInjector.INSTANCE.unbind(IDhApiShadowCullingFrustum.class, (IDhApiOverrideable) ShadowRenderer.FRUSTUM);
+ OverrideInjector.INSTANCE.unbind(IDhApiFramebuffer.class, instance.getShadowFBWrapper());
+ OverrideInjector.INSTANCE.unbind(IDhApiFramebuffer.class, instance.getSolidFBWrapper());
+
+ event.cancelEvent();
+ }
+ }
+ };
+
+ DhApi.events.bind(DhApiBeforeApplyShaderRenderEvent.class, beforeApplyShaderEvent);
+ }
+
+
+}
diff --git a/src/main/java/net/coderbot/iris/config/IrisConfig.java b/src/main/java/net/coderbot/iris/config/IrisConfig.java
index 86b2c8b26..47a1de440 100644
--- a/src/main/java/net/coderbot/iris/config/IrisConfig.java
+++ b/src/main/java/net/coderbot/iris/config/IrisConfig.java
@@ -33,12 +33,18 @@ public class IrisConfig {
*/
private boolean disableUpdateMessage;
+ /**
+ * If debug features should be enabled. Gives much more detailed OpenGL error outputs at the cost of performance.
+ */
+ private boolean enableDebugOptions;
+
private final Path propertiesPath;
public IrisConfig(Path propertiesPath) {
shaderPackName = null;
enableShaders = true;
disableUpdateMessage = false;
+ enableDebugOptions = false;
this.propertiesPath = propertiesPath;
}
@@ -103,6 +109,10 @@ public class IrisConfig {
this.enableShaders = enabled;
}
+ public boolean areDebugOptionsEnabled() {
+ return enableDebugOptions;
+ }
+
/**
* loads the config file and then populates the string, int, and boolean entries with the parsed entries
*
@@ -121,6 +131,7 @@ public class IrisConfig {
}
shaderPackName = properties.getProperty("shaderPack");
enableShaders = !"false".equals(properties.getProperty("enableShaders"));
+ enableDebugOptions = "true".equals(properties.getProperty("enableDebugOptions"));
disableUpdateMessage = "true".equals(properties.getProperty("disableUpdateMessage"));
// TODO: GUI
try {
@@ -147,6 +158,7 @@ public class IrisConfig {
final Properties properties = new Properties();
properties.setProperty("shaderPack", getShaderPackName().orElse(""));
properties.setProperty("enableShaders", enableShaders ? "true" : "false");
+ properties.setProperty("enableDebugOptions", enableDebugOptions ? "true" : "false");
properties.setProperty("disableUpdateMessage", disableUpdateMessage ? "true" : "false");
properties.setProperty("maxShadowRenderDistance", String.valueOf(IrisVideoSettings.shadowDistance));
// NB: This uses ISO-8859-1 with unicode escapes as the encoding
diff --git a/src/main/java/net/coderbot/iris/gl/framebuffer/GlFramebuffer.java b/src/main/java/net/coderbot/iris/gl/framebuffer/GlFramebuffer.java
index 706a6ff46..c4f272e69 100644
--- a/src/main/java/net/coderbot/iris/gl/framebuffer/GlFramebuffer.java
+++ b/src/main/java/net/coderbot/iris/gl/framebuffer/GlFramebuffer.java
@@ -45,6 +45,12 @@ public class GlFramebuffer extends GlResource {
this.hasDepthAttachment = true;
}
+ public void addDepthAttachmentBypass(int texture) {
+ final int fb = getGlId();
+ RenderSystem.framebufferTexture2D(fb, GL30.GL_FRAMEBUFFER, GL30.GL_DEPTH_ATTACHMENT, GL11.GL_TEXTURE_2D, texture, 0);
+ this.hasDepthAttachment = true;
+ }
+
public void addColorAttachment(int index, int texture) {
final int fb = getGlId();
diff --git a/src/main/java/net/coderbot/iris/gl/shader/StandardMacros.java b/src/main/java/net/coderbot/iris/gl/shader/StandardMacros.java
index 23c69dc54..caaa98d17 100644
--- a/src/main/java/net/coderbot/iris/gl/shader/StandardMacros.java
+++ b/src/main/java/net/coderbot/iris/gl/shader/StandardMacros.java
@@ -4,6 +4,7 @@ import com.google.common.collect.ImmutableList;
import com.gtnewhorizons.angelica.Tags;
import com.gtnewhorizons.angelica.config.AngelicaConfig;
import cpw.mods.fml.common.Loader;
+import net.coderbot.iris.compat.dh.DHCompat;
import net.coderbot.iris.parsing.BiomeCategories;
import net.coderbot.iris.pipeline.HandRenderer;
import net.coderbot.iris.pipeline.WorldRenderingPhase;
@@ -77,10 +78,32 @@ public class StandardMacros {
define(standardDefines, "MC_SPECULAR_MAP");
define(standardDefines, "MC_RENDER_QUALITY", "1.0");
define(standardDefines, "MC_SHADOW_QUALITY", "1.0");
- define(standardDefines, "IS_ANGELICA");
- if (AngelicaConfig.defineIsIris) {
- define(standardDefines, "IS_IRIS");
- }
+ define(standardDefines, "IS_ANGELICA");
+ if (AngelicaConfig.defineIsIris) {
+ define(standardDefines, "IS_IRIS");
+ }
+
+ if (DHCompat.hasRenderingEnabled()) {
+ define(standardDefines, "DISTANT_HORIZONS");
+ }
+
+ define(standardDefines, "DH_BLOCK_UNKNOWN", String.valueOf(0));
+ define(standardDefines, "DH_BLOCK_LEAVES", String.valueOf(1));
+ define(standardDefines, "DH_BLOCK_STONE", String.valueOf(2));
+ define(standardDefines, "DH_BLOCK_WOOD", String.valueOf(3));
+ define(standardDefines, "DH_BLOCK_METAL", String.valueOf(4));
+ define(standardDefines, "DH_BLOCK_DIRT", String.valueOf(5));
+ define(standardDefines, "DH_BLOCK_LAVA", String.valueOf(6));
+ define(standardDefines, "DH_BLOCK_DEEPSLATE", String.valueOf(7));
+ define(standardDefines, "DH_BLOCK_SNOW", String.valueOf(8));
+ define(standardDefines, "DH_BLOCK_SAND", String.valueOf(9));
+ define(standardDefines, "DH_BLOCK_TERRACOTTA", String.valueOf(10));
+ define(standardDefines, "DH_BLOCK_NETHER_STONE", String.valueOf(11));
+ define(standardDefines, "DH_BLOCK_WATER", String.valueOf(12));
+ define(standardDefines, "DH_BLOCK_GRASS", String.valueOf(13));
+ define(standardDefines, "DH_BLOCK_AIR", String.valueOf(14));
+ define(standardDefines, "DH_BLOCK_ILLUMINATED", String.valueOf(15));
+
define(standardDefines, "ANGELICA_VERSION", makeAngelicaVersion());
define(standardDefines, "MC_HAND_DEPTH", Float.toString(HandRenderer.DEPTH));
diff --git a/src/main/java/net/coderbot/iris/gl/uniform/DynamicLocationalUniformHolder.java b/src/main/java/net/coderbot/iris/gl/uniform/DynamicLocationalUniformHolder.java
index e96058edc..6de2d5e05 100644
--- a/src/main/java/net/coderbot/iris/gl/uniform/DynamicLocationalUniformHolder.java
+++ b/src/main/java/net/coderbot/iris/gl/uniform/DynamicLocationalUniformHolder.java
@@ -3,6 +3,7 @@ package net.coderbot.iris.gl.uniform;
import net.coderbot.iris.gl.state.ValueUpdateNotifier;
import org.joml.Vector2i;
import org.joml.Vector3i;
+import org.joml.Vector3ic;
import org.joml.Vector4f;
import org.joml.Vector4i;
@@ -43,7 +44,7 @@ public interface DynamicLocationalUniformHolder extends LocationalUniformHolder,
return this;
}
- default DynamicUniformHolder uniform3i(String name, Supplier value, ValueUpdateNotifier notifier) {
+ default DynamicUniformHolder uniform3i(String name, Supplier value, ValueUpdateNotifier notifier) {
location(name, UniformType.VEC3I).ifPresent(id -> addDynamicUniform(new Vector3IntegerJomlUniform(id, value, notifier), notifier));
return this;
diff --git a/src/main/java/net/coderbot/iris/gl/uniform/DynamicUniformHolder.java b/src/main/java/net/coderbot/iris/gl/uniform/DynamicUniformHolder.java
index c130bd9d0..c02c952cd 100644
--- a/src/main/java/net/coderbot/iris/gl/uniform/DynamicUniformHolder.java
+++ b/src/main/java/net/coderbot/iris/gl/uniform/DynamicUniformHolder.java
@@ -3,6 +3,7 @@ package net.coderbot.iris.gl.uniform;
import net.coderbot.iris.gl.state.ValueUpdateNotifier;
import org.joml.Vector2i;
import org.joml.Vector3i;
+import org.joml.Vector3ic;
import org.joml.Vector4f;
import org.joml.Vector4i;
@@ -16,7 +17,7 @@ public interface DynamicUniformHolder extends UniformHolder {
DynamicUniformHolder uniform1f(String name, DoubleSupplier value, ValueUpdateNotifier notifier);
DynamicUniformHolder uniform1i(String name, IntSupplier value, ValueUpdateNotifier notifier);
DynamicUniformHolder uniform2i(String name, Supplier value, ValueUpdateNotifier notifier);
- DynamicUniformHolder uniform3i(String name, Supplier value, ValueUpdateNotifier notifier);
+ DynamicUniformHolder uniform3i(String name, Supplier value, ValueUpdateNotifier notifier);
DynamicUniformHolder uniform4f(String name, Supplier value, ValueUpdateNotifier notifier);
DynamicUniformHolder uniform4fArray(String name, Supplier value, ValueUpdateNotifier notifier);
DynamicUniformHolder uniform4i(String name, Supplier value, ValueUpdateNotifier notifier);
diff --git a/src/main/java/net/coderbot/iris/gl/uniform/LocationalUniformHolder.java b/src/main/java/net/coderbot/iris/gl/uniform/LocationalUniformHolder.java
index bf2046c52..ae5997b70 100644
--- a/src/main/java/net/coderbot/iris/gl/uniform/LocationalUniformHolder.java
+++ b/src/main/java/net/coderbot/iris/gl/uniform/LocationalUniformHolder.java
@@ -2,11 +2,14 @@ package net.coderbot.iris.gl.uniform;
import net.minecraft.util.Vec3;
import org.joml.Matrix4f;
+import org.joml.Matrix4fc;
import org.joml.Vector2f;
import org.joml.Vector2i;
import org.joml.Vector3d;
import org.joml.Vector3f;
+import org.joml.Vector3fc;
import org.joml.Vector3i;
+import org.joml.Vector3ic;
import org.joml.Vector4f;
import java.util.OptionalInt;
@@ -70,14 +73,14 @@ public interface LocationalUniformHolder extends UniformHolder {
}
@Override
- default LocationalUniformHolder uniform3f(UniformUpdateFrequency updateFrequency, String name, Supplier value) {
+ default LocationalUniformHolder uniform3f(UniformUpdateFrequency updateFrequency, String name, Supplier value) {
location(name, UniformType.VEC3).ifPresent(id -> addUniform(updateFrequency, new Vector3Uniform(id, value)));
return this;
}
@Override
- default LocationalUniformHolder uniform3i(UniformUpdateFrequency updateFrequency, String name, Supplier value) {
+ default LocationalUniformHolder uniform3i(UniformUpdateFrequency updateFrequency, String name, Supplier value) {
location(name, UniformType.VEC3I).ifPresent(id -> addUniform(updateFrequency, new Vector3IntegerJomlUniform(id, value)));
return this;
@@ -119,7 +122,7 @@ public interface LocationalUniformHolder extends UniformHolder {
}
@Override
- default LocationalUniformHolder uniformMatrix(UniformUpdateFrequency updateFrequency, String name, Supplier value) {
+ default LocationalUniformHolder uniformMatrix(UniformUpdateFrequency updateFrequency, String name, Supplier value) {
location(name, UniformType.MAT4).ifPresent(id -> addUniform(updateFrequency, new MatrixUniform(id, value)));
return this;
diff --git a/src/main/java/net/coderbot/iris/gl/uniform/MatrixUniform.java b/src/main/java/net/coderbot/iris/gl/uniform/MatrixUniform.java
index 237843f68..541a5db5c 100644
--- a/src/main/java/net/coderbot/iris/gl/uniform/MatrixUniform.java
+++ b/src/main/java/net/coderbot/iris/gl/uniform/MatrixUniform.java
@@ -2,6 +2,7 @@ package net.coderbot.iris.gl.uniform;
import com.gtnewhorizons.angelica.glsm.RenderSystem;
import org.joml.Matrix4f;
+import org.joml.Matrix4fc;
import org.lwjgl.BufferUtils;
import java.nio.FloatBuffer;
@@ -10,9 +11,9 @@ import java.util.function.Supplier;
public class MatrixUniform extends Uniform {
private final FloatBuffer buffer = BufferUtils.createFloatBuffer(16);
private Matrix4f cachedValue;
- private final Supplier value;
+ private final Supplier value;
- MatrixUniform(int location, Supplier value) {
+ MatrixUniform(int location, Supplier value) {
super(location);
this.cachedValue = null;
@@ -21,7 +22,7 @@ public class MatrixUniform extends Uniform {
@Override
public void update() {
- final Matrix4f newValue = value.get();
+ final Matrix4fc newValue = value.get();
if( newValue == null ){
throw new RuntimeException("MatrixUniform value is null");
}
diff --git a/src/main/java/net/coderbot/iris/gl/uniform/UniformHolder.java b/src/main/java/net/coderbot/iris/gl/uniform/UniformHolder.java
index de6891d69..9fa8101f7 100644
--- a/src/main/java/net/coderbot/iris/gl/uniform/UniformHolder.java
+++ b/src/main/java/net/coderbot/iris/gl/uniform/UniformHolder.java
@@ -1,12 +1,13 @@
package net.coderbot.iris.gl.uniform;
import net.minecraft.util.Vec3;
-import org.joml.Matrix4f;
+import org.joml.Matrix4fc;
import org.joml.Vector2f;
import org.joml.Vector2i;
import org.joml.Vector3d;
-import org.joml.Vector3f;
+import org.joml.Vector3fc;
import org.joml.Vector3i;
+import org.joml.Vector3ic;
import org.joml.Vector4f;
import java.util.function.BooleanSupplier;
@@ -29,9 +30,9 @@ public interface UniformHolder {
UniformHolder uniform2i(UniformUpdateFrequency updateFrequency, String name, Supplier value);
- UniformHolder uniform3f(UniformUpdateFrequency updateFrequency, String name, Supplier value);
+ UniformHolder uniform3f(UniformUpdateFrequency updateFrequency, String name, Supplier value);
- UniformHolder uniform3i(UniformUpdateFrequency updateFrequency, String name, Supplier value);
+ UniformHolder uniform3i(UniformUpdateFrequency updateFrequency, String name, Supplier value);
UniformHolder uniformVanilla3f(UniformUpdateFrequency updateFrequency, String name, Supplier value);
@@ -43,7 +44,7 @@ public interface UniformHolder {
UniformHolder uniform4fArray(UniformUpdateFrequency updateFrequency, String name, Supplier value);
- UniformHolder uniformMatrix(UniformUpdateFrequency updateFrequency, String name, Supplier value);
+ UniformHolder uniformMatrix(UniformUpdateFrequency updateFrequency, String name, Supplier value);
UniformHolder uniformMatrixFromArray(UniformUpdateFrequency updateFrequency, String name, Supplier value);
diff --git a/src/main/java/net/coderbot/iris/gl/uniform/Vector3IntegerJomlUniform.java b/src/main/java/net/coderbot/iris/gl/uniform/Vector3IntegerJomlUniform.java
index 2ab719d83..30437adfb 100644
--- a/src/main/java/net/coderbot/iris/gl/uniform/Vector3IntegerJomlUniform.java
+++ b/src/main/java/net/coderbot/iris/gl/uniform/Vector3IntegerJomlUniform.java
@@ -3,21 +3,22 @@ package net.coderbot.iris.gl.uniform;
import com.gtnewhorizons.angelica.glsm.RenderSystem;
import net.coderbot.iris.gl.state.ValueUpdateNotifier;
import org.joml.Vector3i;
+import org.joml.Vector3ic;
import java.util.function.Supplier;
public class Vector3IntegerJomlUniform extends Uniform {
- private Vector3i cachedValue;
- private final Supplier value;
+ private final Vector3i cachedValue;
+ private final Supplier value;
- Vector3IntegerJomlUniform(int location, Supplier value) {
+ Vector3IntegerJomlUniform(int location, Supplier value) {
this(location, value, null);
}
- Vector3IntegerJomlUniform(int location, Supplier value, ValueUpdateNotifier notifier) {
+ Vector3IntegerJomlUniform(int location, Supplier value, ValueUpdateNotifier notifier) {
super(location, notifier);
- this.cachedValue = null;
+ this.cachedValue = new Vector3i();
this.value = value;
}
@@ -31,11 +32,11 @@ public class Vector3IntegerJomlUniform extends Uniform {
}
private void updateValue() {
- Vector3i newValue = value.get();
+ Vector3ic newValue = value.get();
- if (cachedValue == null || !newValue.equals(cachedValue)) {
- cachedValue = newValue;
- RenderSystem.uniform3i(this.location, newValue.x, newValue.y, newValue.z);
+ if (!newValue.equals(cachedValue)) {
+ cachedValue.set(newValue.x(), newValue.y(), newValue.z());
+ RenderSystem.uniform3i(this.location, cachedValue.x(), cachedValue.y(), cachedValue.z());
}
}
}
diff --git a/src/main/java/net/coderbot/iris/gl/uniform/Vector3Uniform.java b/src/main/java/net/coderbot/iris/gl/uniform/Vector3Uniform.java
index 48ceadea7..790348bd8 100644
--- a/src/main/java/net/coderbot/iris/gl/uniform/Vector3Uniform.java
+++ b/src/main/java/net/coderbot/iris/gl/uniform/Vector3Uniform.java
@@ -3,15 +3,16 @@ package net.coderbot.iris.gl.uniform;
import com.gtnewhorizons.angelica.glsm.RenderSystem;
import org.joml.Vector3d;
import org.joml.Vector3f;
+import org.joml.Vector3fc;
import org.joml.Vector4f;
import java.util.function.Supplier;
public class Vector3Uniform extends Uniform {
private final Vector3f cachedValue;
- private final Supplier value;
+ private final Supplier value;
- Vector3Uniform(int location, Supplier value) {
+ Vector3Uniform(int location, Supplier value) {
super(location);
this.cachedValue = new Vector3f();
@@ -44,7 +45,7 @@ public class Vector3Uniform extends Uniform {
@Override
public void update() {
- Vector3f newValue = value.get();
+ Vector3fc newValue = value.get();
if (!newValue.equals(cachedValue)) {
cachedValue.set(newValue.x(), newValue.y(), newValue.z());
diff --git a/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java b/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java
index 9ad878a5d..8c9107f09 100644
--- a/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java
+++ b/src/main/java/net/coderbot/iris/pipeline/DeferredWorldRenderingPipeline.java
@@ -29,12 +29,14 @@ import net.coderbot.iris.gl.buffer.ShaderStorageBufferHolder;
import net.coderbot.iris.gl.buffer.ShaderStorageInfo;
import net.coderbot.iris.gl.framebuffer.GlFramebuffer;
import net.coderbot.iris.gl.image.GlImage;
+import net.coderbot.iris.gl.image.ImageHolder;
import net.coderbot.iris.gl.image.ImageInformation;
import net.coderbot.iris.gl.program.ComputeProgram;
import net.coderbot.iris.gl.program.Program;
import net.coderbot.iris.gl.program.ProgramBuilder;
import net.coderbot.iris.gl.program.ProgramImages;
import net.coderbot.iris.gl.program.ProgramSamplers;
+import net.coderbot.iris.gl.sampler.SamplerHolder;
import net.coderbot.iris.gl.state.FogMode;
import net.coderbot.iris.gl.texture.DepthBufferFormat;
import net.coderbot.iris.gl.texture.TextureType;
@@ -177,6 +179,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
private final boolean oldLighting;
private final boolean allowConcurrentCompute;
private final OptionalInt forcedShadowRenderDistanceChunks;
+ private final CloudSetting dhCloudSetting;
private Pass current = null;
@@ -192,6 +195,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
private int currentSpecularTexture;
private PackDirectives packDirectives;
private final Set activeFeatures;
+ private final ProgramFallbackResolver resolver;
public DeferredWorldRenderingPipeline(ProgramSet programs) {
Objects.requireNonNull(programs);
@@ -206,7 +210,7 @@ public class DeferredWorldRenderingPipeline implements WorldRenderingPipeline, R
.map(DeferredWorldRenderingPipeline::submitCompositeTransform)
.orElse(null);
- final ProgramFallbackResolver resolver = new ProgramFallbackResolver(programs);
+ resolver = new ProgramFallbackResolver(programs);
final Map, CompletableFuture