From 3d13ba7645e4e28e41b7b0f3c4ca9918ef6737c5 Mon Sep 17 00:00:00 2001 From: Acuadragon100 <8165958-acuadragon100@users.noreply.gitlab.com> Date: Thu, 23 Apr 2026 12:07:31 +0200 Subject: [PATCH] Disable fade rendering when immersive portals and sodium are active at once. --- .../core/api/internal/ClientApi.java | 22 +++- .../IImmersivePortalsAccessor.java | 29 +++++ .../modAccessor/ImmersivePortalsAccessor.java | 104 ++++++++++++++++++ 3 files changed, 151 insertions(+), 4 deletions(-) create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IImmersivePortalsAccessor.java create mode 100644 core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/ImmersivePortalsAccessor.java diff --git a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java index 891263526..9e0d1fd36 100644 --- a/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java +++ b/core/src/main/java/com/seibel/distanthorizons/core/api/internal/ClientApi.java @@ -24,6 +24,7 @@ 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.core.api.internal.rendering.DhRenderState; +import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector; import com.seibel.distanthorizons.core.enums.MinecraftTextFormat; import com.seibel.distanthorizons.core.file.structure.ClientOnlySaveStructure; import com.seibel.distanthorizons.core.logging.DhLoggerBuilder; @@ -40,6 +41,8 @@ import com.seibel.distanthorizons.core.util.objects.Pair; import com.seibel.distanthorizons.core.util.objects.RollingAverage; import com.seibel.distanthorizons.core.util.threading.ThreadPoolUtil; import com.seibel.distanthorizons.core.wrapperInterfaces.minecraft.IMinecraftRenderWrapper; +import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.IImmersivePortalsAccessor; +import com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor.ISodiumAccessor; import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhMetaRenderer; import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhVanillaFadeRenderer; import com.seibel.distanthorizons.core.wrapperInterfaces.render.renderPass.IDhTestTriangleRenderer; @@ -669,6 +672,19 @@ public class ClientApi //================// //region + private static boolean shouldRenderFade() { + // don't fade when Iris shaders are active, otherwise the rendering can get weird + if (DhApiRenderProxy.INSTANCE.getDeferTransparentRendering()) return false; + + // When immersive portals and sodium are combined the fade renders on top of the portal, so turn it off when a portal is on-screen. + IImmersivePortalsAccessor immersivePortals = ModAccessorInjector.INSTANCE.get(IImmersivePortalsAccessor.class); + ISodiumAccessor sodium = ModAccessorInjector.INSTANCE.get(ISodiumAccessor.class); + if (sodium != null && immersivePortals != null && immersivePortals.hasPortalOnScreen()) { + return false; + } + return true; + } + /** * The first fade pass. * Called after MC finishes rendering the opaque passes. @@ -690,8 +706,7 @@ public class ClientApi // or if LOD-only mode is enabled (fading is used to remove the MC render pass) || Config.Client.Advanced.Debugging.lodOnlyMode.get() ) - // don't fade when Iris shaders are active, otherwise the rendering can get weird - && !DhApiRenderProxy.INSTANCE.getDeferTransparentRendering()) + && shouldRenderFade()) { RenderParams renderParams = new RenderParams(EDhApiRenderPass.OPAQUE, RENDER_STATE); fadeRenderer.render(renderParams); @@ -720,8 +735,7 @@ public class ClientApi // or if LOD-only mode is enabled (fading is used to remove the MC render pass) || Config.Client.Advanced.Debugging.lodOnlyMode.get() ) - // don't fade when Iris shaders are active, otherwise the rendering can get weird - && !DhApiRenderProxy.INSTANCE.getDeferTransparentRendering(); + && shouldRenderFade(); if (renderFade) { RenderParams renderParams = new RenderParams(EDhApiRenderPass.TRANSPARENT, RENDER_STATE); diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IImmersivePortalsAccessor.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IImmersivePortalsAccessor.java new file mode 100644 index 000000000..b9420a157 --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/IImmersivePortalsAccessor.java @@ -0,0 +1,29 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor; + +public interface IImmersivePortalsAccessor extends IModAccessor +{ + + boolean isRenderingPortal(); + + boolean hasPortalOnScreen(); + +} diff --git a/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/ImmersivePortalsAccessor.java b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/ImmersivePortalsAccessor.java new file mode 100644 index 000000000..86fea687a --- /dev/null +++ b/core/src/main/java/com/seibel/distanthorizons/core/wrapperInterfaces/modAccessor/ImmersivePortalsAccessor.java @@ -0,0 +1,104 @@ +/* + * This file is part of the Distant Horizons mod + * licensed under the GNU LGPL v3 License. + * + * Copyright (C) 2020 James Seibel + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, version 3. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program. If not, see . + */ + +package com.seibel.distanthorizons.core.wrapperInterfaces.modAccessor; + +import com.seibel.distanthorizons.api.DhApi; +import com.seibel.distanthorizons.api.methods.events.abstractEvents.DhApiBeforeRenderEvent; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiCancelableEventParam; +import com.seibel.distanthorizons.api.methods.events.sharedParameterObjects.DhApiRenderParam; +import com.seibel.distanthorizons.core.dependencyInjection.ModAccessorInjector; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + +public class ImmersivePortalsAccessor implements IImmersivePortalsAccessor +{ + + private static MethodHandle isRendering; + + private static long lastPortalTime = -1; + private static boolean portalVisible = false; + + public ImmersivePortalsAccessor() { + DhApi.events.bind(DhApiBeforeRenderEvent.class, BeforeRender.INSTANCE); + } + + @Override + public boolean isRenderingPortal() + { + try { + if (isRendering == null) { + isRendering = MethodHandles.lookup().findStatic( + #if MC_VER > MC_1_16_5 + Class.forName("qouteall.imm_ptl.core.render.context_management.PortalRendering"), + #else + Class.forName("com.qouteall.immersive_portals.render.context_management.PortalRendering"), + #endif + "isRendering", MethodType.methodType(Boolean.TYPE) + ); + } + boolean result = (boolean) isRendering.invoke(); + if (result) { + portalVisible = true; + lastPortalTime = System.currentTimeMillis(); + } else if (portalVisible) { + if (System.currentTimeMillis() - lastPortalTime > 1000) { + portalVisible = false; + } + } + return result; + } + catch (Throwable e) + { + throw new RuntimeException(e); + } + } + + @Override + public boolean hasPortalOnScreen() { + return portalVisible; + } + + @Override + public String getModName() + { + return "ImmersivePortalsMod"; + } + + + public static class BeforeRender extends DhApiBeforeRenderEvent + { + + public static BeforeRender INSTANCE = new BeforeRender(); + + private BeforeRender() {} + + @Override + public void beforeRender(DhApiCancelableEventParam event) + { + if (ModAccessorInjector.INSTANCE.get(IImmersivePortalsAccessor.class).isRenderingPortal()) { + event.cancelEvent(); + } + } + + } + +}