Draw glass behind translucent panels on 1.21.11
A copy of the game behind the screen is blurred once a frame and drawn through each panel's rounded rectangle texture by a glass pipeline. Older versions keep blurring the whole background. Co-Authored-By: Claude Opus 5.5 <[email protected]>
This commit is contained in:
+1
-1
Submodule common updated: 5c0912f0cf...4d9c629eaf
@@ -49,12 +49,13 @@ public class GameRendererMixin {
|
||||
|
||||
//? if >=1.21.6 {
|
||||
// From 1.21.6 the menu blur's strength is the vanilla setting, read here every frame. While a
|
||||
// Saturn screen is open, it's Saturn's background blur instead, faded in with the screen.
|
||||
// Saturn screen is open, it's Saturn's background blur instead, faded in with the screen. Glass
|
||||
// uses the same blur, so this holds even when the screen doesn't blur its whole background.
|
||||
@Redirect(method = "render", at = @At(value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/option/GameOptions;getMenuBackgroundBlurrinessValue()I"))
|
||||
private int useSaturnBlur(GameOptions options) {
|
||||
if (MinecraftClient.getInstance().currentScreen instanceof SaturnScreenFabric saturnScreen) {
|
||||
return saturnScreen.screen.getBackgroundBlur();
|
||||
return saturnScreen.screen.getBlurRadius();
|
||||
}
|
||||
|
||||
return options.getMenuBackgroundBlurrinessValue();
|
||||
|
||||
@@ -76,6 +76,14 @@ public class SaturnProviderImpl implements SaturnProvider {
|
||||
return (IdentifierRef) (Object) playerSkin.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean supportsGlass() {
|
||||
//? if >=1.21.11 {
|
||||
return true;
|
||||
//?} else
|
||||
//return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getModVersion() {
|
||||
return FabricLoader.getInstance().getModContainer(SaturnClient.MOD_ID)
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
package org.saturnclient.impl.ui;
|
||||
|
||||
//? if >=1.21.11 {
|
||||
import com.mojang.blaze3d.pipeline.RenderPipeline;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.textures.FilterMode;
|
||||
import com.mojang.blaze3d.textures.GpuTextureView;
|
||||
|
||||
import org.saturnclient.saturnclient.SaturnClient;
|
||||
|
||||
import net.minecraft.client.gl.Framebuffer;
|
||||
import net.minecraft.client.gl.GpuSampler;
|
||||
import net.minecraft.client.gl.PostEffectProcessor;
|
||||
import net.minecraft.client.gl.RenderPipelines;
|
||||
import net.minecraft.client.gl.SimpleFramebuffer;
|
||||
import net.minecraft.client.render.DefaultFramebufferSet;
|
||||
import net.minecraft.client.texture.TextureSetup;
|
||||
import net.minecraft.client.util.Pool;
|
||||
import net.minecraft.util.Identifier;
|
||||
|
||||
// Glass: a copy of the game behind the screen, blurred with vanilla's blur (as strong as Saturn's
|
||||
// background blur), drawn through each panel's rounded rectangle texture (shaders/core/glass.fsh).
|
||||
// The copy is made while the screen builds its GUI, before the GUI is drawn, so it holds the world
|
||||
// or panorama alone.
|
||||
// TODO: glass before 1.21.11 (#23). Those versions blur the whole background instead.
|
||||
public final class GlassRenderer {
|
||||
public static final RenderPipeline PIPELINE = RenderPipeline.builder(RenderPipelines.POSITION_TEX_COLOR_SNIPPET)
|
||||
.withLocation(Identifier.of("saturnclient", "pipeline/glass"))
|
||||
.withFragmentShader(Identifier.of("saturnclient", "core/glass"))
|
||||
.withSampler("Sampler1")
|
||||
.build();
|
||||
|
||||
private static final Identifier BLUR = Identifier.ofVanilla("blur");
|
||||
// For the blur's intermediate target, freed once unused for a few frames
|
||||
private static final Pool POOL = new Pool(3);
|
||||
|
||||
private static SimpleFramebuffer backdrop;
|
||||
|
||||
private GlassRenderer() {
|
||||
}
|
||||
|
||||
// Copies the main framebuffer and blurs the copy. Call once a frame, before drawing glass.
|
||||
public static void captureBackdrop() {
|
||||
Framebuffer main = SaturnClient.client.getFramebuffer();
|
||||
int width = main.textureWidth;
|
||||
int height = main.textureHeight;
|
||||
|
||||
if (backdrop == null) {
|
||||
backdrop = new SimpleFramebuffer("Saturn glass", width, height, false);
|
||||
} else if (backdrop.textureWidth != width || backdrop.textureHeight != height) {
|
||||
backdrop.resize(width, height);
|
||||
}
|
||||
|
||||
RenderSystem.getDevice().createCommandEncoder().copyTextureToTexture(
|
||||
main.getColorAttachment(), backdrop.getColorAttachment(), 0, 0, 0, 0, 0, width, height);
|
||||
|
||||
PostEffectProcessor blur = SaturnClient.client.getShaderLoader().loadPostEffect(BLUR,
|
||||
DefaultFramebufferSet.MAIN_ONLY);
|
||||
if (blur != null) {
|
||||
blur.render(backdrop, POOL);
|
||||
}
|
||||
POOL.decrementLifespan();
|
||||
}
|
||||
|
||||
// The mask, then the blurred copy, as the glass pipeline samples them
|
||||
public static TextureSetup textures(GpuTextureView mask, GpuSampler maskSampler) {
|
||||
return TextureSetup.of(mask, maskSampler, backdrop.getColorAttachmentView(),
|
||||
RenderSystem.getSamplerCache().get(FilterMode.LINEAR));
|
||||
}
|
||||
}
|
||||
//?}
|
||||
@@ -61,6 +61,10 @@ public class RenderScopeImpl implements RenderScope {
|
||||
|
||||
private ScissorStack scissorStack;
|
||||
private int opacity = 0xFF << 24;
|
||||
//? if >=1.21.11 {
|
||||
// Whether the glass backdrop was made for this scope's frame
|
||||
private boolean backdropCaptured = false;
|
||||
//?}
|
||||
|
||||
public RenderScopeImpl(DrawContext context) {
|
||||
this(context.getMatrices(), ((DrawContextAccessor) (Object) context).getState());
|
||||
@@ -230,6 +234,28 @@ public class RenderScopeImpl implements RenderScope {
|
||||
this.scissorStack.peekLast()));
|
||||
}
|
||||
|
||||
//? if >=1.21.11 {
|
||||
@Override
|
||||
public void drawGlass(IdentifierRef mask, int x, int y, int width, int height) {
|
||||
int color = getColor(0xFFFFFFFF);
|
||||
if (mask == null || color >>> 24 == 0)
|
||||
return;
|
||||
|
||||
if (!backdropCaptured) {
|
||||
GlassRenderer.captureBackdrop();
|
||||
backdropCaptured = true;
|
||||
}
|
||||
|
||||
AbstractTexture maskTexture = SaturnClient.client.getTextureManager().getTexture((Identifier) (Object) mask);
|
||||
this.state.addSimpleElement(new TexturedQuadGuiElementRenderState(
|
||||
GlassRenderer.PIPELINE,
|
||||
GlassRenderer.textures(maskTexture.getGlTextureView(), maskTexture.getSampler()),
|
||||
new Matrix3x2f(this.matrices.stack),
|
||||
x, y, x + width, y + height, 0, 1, 0, 1, color,
|
||||
this.scissorStack.peekLast()));
|
||||
}
|
||||
//?}
|
||||
|
||||
// Scissor management
|
||||
@Override
|
||||
public void enableScissor(int x1, int y1, int x2, int y2) {
|
||||
|
||||
@@ -0,0 +1,31 @@
|
||||
#version 330
|
||||
|
||||
// Saturn's glass: the blurred game behind the screen, cut to a panel's shape.
|
||||
|
||||
layout(std140) uniform DynamicTransforms {
|
||||
mat4 ModelViewMat;
|
||||
vec4 ColorModulator;
|
||||
vec3 ModelOffset;
|
||||
mat4 TextureMat;
|
||||
};
|
||||
|
||||
// The panel's rounded rectangle, the same texture its background is drawn with
|
||||
uniform sampler2D Sampler0;
|
||||
// The game behind the screen, blurred, the size of the framebuffer
|
||||
uniform sampler2D Sampler1;
|
||||
|
||||
in vec2 texCoord0;
|
||||
in vec4 vertexColor;
|
||||
|
||||
out vec4 fragColor;
|
||||
|
||||
void main() {
|
||||
float mask = texture(Sampler0, texCoord0).a * vertexColor.a;
|
||||
if (mask == 0.0) {
|
||||
discard;
|
||||
}
|
||||
|
||||
// The blurred copy lines up with the framebuffer being drawn to.
|
||||
vec2 screenUv = gl_FragCoord.xy / vec2(textureSize(Sampler1, 0));
|
||||
fragColor = vec4(texture(Sampler1, screenUv).rgb, mask) * ColorModulator;
|
||||
}
|
||||
Reference in New Issue
Block a user