diff --git a/src/main/java/org/saturnclient/impl/ui/GlassRenderer.java b/src/main/java/org/saturnclient/impl/ui/GlassRenderer.java index 8e8ccaa..d1264fd 100644 --- a/src/main/java/org/saturnclient/impl/ui/GlassRenderer.java +++ b/src/main/java/org/saturnclient/impl/ui/GlassRenderer.java @@ -17,7 +17,11 @@ package org.saturnclient.impl.ui; //? if >=1.21.6 { import java.io.Reader; import java.util.HashMap; +//? if >=26.1 +//import java.util.LinkedHashSet; import java.util.Map; +//? if >=26.1 +//import java.util.Set; import com.google.gson.JsonElement; import com.google.gson.JsonObject; @@ -85,13 +89,24 @@ public final class GlassRenderer { private GlassRenderer() { } + // From 26.1 the GUI is built before the frame's world is drawn, so the main framebuffer still + // holds the last frame, glass included. The copies wait until the GUI renderer is about to draw + // (GuiRendererMixin), when it holds this frame's world and panorama. + //? if >=26.1 { + /*private static final Set PENDING = new LinkedHashSet<>(); + *///?} + + private static RenderTarget mainTarget() { + //? if >=26.2 { + /*return SaturnClient.client.gameRenderer.mainRenderTarget(); + *///?} else + return SaturnClient.client.getMainRenderTarget(); + } + // Copies the main framebuffer and blurs the copy by blur. Call once a frame for each blur, while // the screen builds its GUI, before drawing glass with it. public static void captureBackdrop(int blur) { - //? if >=26.2 { - /*RenderTarget main = SaturnClient.client.gameRenderer.mainRenderTarget(); - *///?} else - RenderTarget main = SaturnClient.client.getMainRenderTarget(); + RenderTarget main = mainTarget(); int width = main.width; int height = main.height; @@ -108,6 +123,29 @@ public final class GlassRenderer { //? if <1.21.11 //backdrop.getColorTexture().setTextureFilter(FilterMode.LINEAR, false); + //? if >=26.1 { + /*PENDING.add(blur); + } + + // Copies and blurs the backdrops the GUI asked for this frame. GuiRendererMixin calls it once the + // world and the panorama are drawn, before the GUI. + public static void blurPendingBackdrops() { + RenderTarget main = mainTarget(); + for (int blur : PENDING) { + TextureTarget backdrop = BACKDROPS.get(blur); + // The GUI already refers to the backdrop's texture, so after a resize it keeps the last + // frame's until the next one. + if (backdrop != null && backdrop.width == main.width && backdrop.height == main.height) { + blurBackdrop(main, backdrop, blur); + } + } + PENDING.clear(); + } + + private static void blurBackdrop(RenderTarget main, TextureTarget backdrop, int blur) { + int width = main.width; + int height = main.height; + *///?} RenderSystem.getDevice().createCommandEncoder().copyTextureToTexture( main.getColorTexture(), backdrop.getColorTexture(), 0, 0, 0, 0, 0, width, height); @@ -132,6 +170,9 @@ public final class GlassRenderer { private static void release(int kept) { BACKDROPS.entrySet().removeIf(entry -> { boolean unused = entry.getKey() != kept && !isSet(entry.getKey()); + // The GUI already refers to this frame's pending backdrops. + //? if >=26.1 + //unused &= !PENDING.contains(entry.getKey()); if (unused) { entry.getValue().destroyBuffers(); } @@ -139,6 +180,9 @@ public final class GlassRenderer { }); BLURS.entrySet().removeIf(entry -> { boolean unused = entry.getKey() != kept && !isSet(entry.getKey()); + // The GUI already refers to this frame's pending backdrops. + //? if >=26.1 + //unused &= !PENDING.contains(entry.getKey()); if (unused && entry.getValue() != null) { entry.getValue().close(); } diff --git a/src/main/java/org/saturnclient/saturnclient/mixin/GuiRendererMixin.java b/src/main/java/org/saturnclient/saturnclient/mixin/GuiRendererMixin.java index a02eca4..3181893 100644 --- a/src/main/java/org/saturnclient/saturnclient/mixin/GuiRendererMixin.java +++ b/src/main/java/org/saturnclient/saturnclient/mixin/GuiRendererMixin.java @@ -5,16 +5,20 @@ package org.saturnclient.saturnclient.mixin; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import net.minecraft.client.gui.render.GuiRenderer; import net.minecraft.client.renderer.CubeMap; +import org.saturnclient.impl.ui.GlassRenderer; import org.saturnclient.impl.ui.SaturnScreenFabric; import org.saturnclient.impl.ui.Screens; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; *///?} else import net.minecraft.client.Minecraft; import org.spongepowered.asm.mixin.Mixin; /** * From 26.1 GuiRenderer draws the menu panorama from its own cube map, which is vanilla's. While a - * Saturn screen is open, this draws Saturn's panorama instead. Before 26.1 SaturnScreenFabric draws + * Saturn screen is open, this draws Saturn's panorama instead. It also blurs the glass backdrops + * once the panorama is drawn. Before 26.1 SaturnScreenFabric draws * the panorama itself, so this mixin is empty there, and it targets Minecraft because GuiRenderer * doesn't exist before 1.21.6. It stays registered, keeping saturnclient.mixins.json the same for * every version. @@ -27,6 +31,13 @@ public class GuiRendererMixin { boolean saturnScreen = Screens.current() instanceof SaturnScreenFabric; original.call(saturnScreen ? SaturnScreenFabric.PANORAMA_RENDERER : cubeMap, xRot, yRot); } + + // The glass backdrops are copied here, with the frame's world and panorama drawn and the GUI not + // yet: the GUI is built before the frame is drawn (see GlassRenderer). + @Inject(method = "render", at = @At(value = "INVOKE", target = "Lnet/minecraft/client/gui/render/GuiRenderer;prepare()V")) + private void saturn$blurGlassBackdrops(CallbackInfo ci) { + GlassRenderer.blurPendingBackdrops(); + } } *///?} else { @Mixin(Minecraft.class)