diff --git a/patches/com/mojang/blaze3d/framegraph/FrameGraphBuilder.java.patch b/patches/com/mojang/blaze3d/framegraph/FrameGraphBuilder.java.patch new file mode 100644 index 00000000000..84d9e314b44 --- /dev/null +++ b/patches/com/mojang/blaze3d/framegraph/FrameGraphBuilder.java.patch @@ -0,0 +1,49 @@ +--- a/com/mojang/blaze3d/framegraph/FrameGraphBuilder.java ++++ b/com/mojang/blaze3d/framegraph/FrameGraphBuilder.java +@@ -173,6 +_,11 @@ + public T get() { + return this.resource; + } ++ ++ @Override ++ public ResourceDescriptor getDescriptor() { ++ return null; ++ } + } + + @OnlyIn(Dist.CLIENT) +@@ -211,6 +_,10 @@ + public String toString() { + return this.createdBy != null ? this.holder + "#" + this.version + " (from " + this.createdBy + ")" : this.holder + "#" + this.version; + } ++ ++ public ResourceDescriptor getDescriptor() { ++ return this.holder.getDescriptor(); ++ } + } + + @OnlyIn(Dist.CLIENT) +@@ -265,6 +_,11 @@ + this.physicalResource = null; + } + } ++ ++ @Override ++ public ResourceDescriptor getDescriptor() { ++ return descriptor; ++ } + } + + @OnlyIn(Dist.CLIENT) +@@ -363,6 +_,11 @@ + @Override + public String toString() { + return this.name; ++ } ++ ++ @Nullable ++ public ResourceDescriptor getDescriptor() { ++ return null; + } + } + } diff --git a/patches/com/mojang/blaze3d/pipeline/MainTarget.java.patch b/patches/com/mojang/blaze3d/pipeline/MainTarget.java.patch new file mode 100644 index 00000000000..d3bcf3cd2fd --- /dev/null +++ b/patches/com/mojang/blaze3d/pipeline/MainTarget.java.patch @@ -0,0 +1,87 @@ +--- a/com/mojang/blaze3d/pipeline/MainTarget.java ++++ b/com/mojang/blaze3d/pipeline/MainTarget.java +@@ -16,8 +_,12 @@ + static final MainTarget.Dimension DEFAULT_DIMENSIONS = new MainTarget.Dimension(854, 480); + + public MainTarget(int p_166137_, int p_166138_) { +- super(true); +- this.createFrameBuffer(p_166137_, p_166138_); ++ this(p_166137_, p_166138_, true, false); ++ } ++ ++ public MainTarget(int width, int height, boolean useDepth, boolean useStencil) { ++ super(useDepth, useStencil); ++ this.createFrameBuffer(width, height); + } + + private void createFrameBuffer(int p_166142_, int p_166143_) { +@@ -37,6 +_,10 @@ + GlStateManager._texParameter(3553, 10242, 33071); + GlStateManager._texParameter(3553, 10243, 33071); + GlStateManager._glFramebufferTexture2D(36160, 36096, 3553, this.depthBufferId, 0); ++ if (this.useStencil) { ++ GlStateManager._bindTexture(this.stencilBufferId); ++ GlStateManager._glFramebufferTexture2D(36160, org.lwjgl.opengl.GL32.GL_STENCIL_ATTACHMENT, 3553, this.stencilBufferId, 0); ++ } + GlStateManager._bindTexture(0); + this.viewWidth = maintarget$dimension.width; + this.viewHeight = maintarget$dimension.height; +@@ -50,7 +_,14 @@ + RenderSystem.assertOnRenderThreadOrInit(); + this.colorTextureId = TextureUtil.generateTextureId(); + this.depthBufferId = TextureUtil.generateTextureId(); ++ if (this.useStencil) { ++ this.stencilBufferId = this.depthBufferId; ++ } + MainTarget.AttachmentState maintarget$attachmentstate = MainTarget.AttachmentState.NONE; ++ MainTarget.AttachmentState targetState = MainTarget.AttachmentState.COLOR_DEPTH; ++ if (this.useStencil) { ++ targetState = targetState.with(MainTarget.AttachmentState.STENCIL); ++ } + + for (MainTarget.Dimension maintarget$dimension : MainTarget.Dimension.listWithFallback(p_166147_, p_166148_)) { + maintarget$attachmentstate = MainTarget.AttachmentState.NONE; +@@ -58,11 +_,15 @@ + maintarget$attachmentstate = maintarget$attachmentstate.with(MainTarget.AttachmentState.COLOR); + } + +- if (this.allocateDepthAttachment(maintarget$dimension)) { ++ if (this.useStencil && this.allocateDepthStencilAttachment(maintarget$dimension)) { ++ maintarget$attachmentstate = maintarget$attachmentstate.with(MainTarget.AttachmentState.DEPTH_STENCIL); ++ } ++ ++ else if (this.allocateDepthAttachment(maintarget$dimension)) { + maintarget$attachmentstate = maintarget$attachmentstate.with(MainTarget.AttachmentState.DEPTH); + } + +- if (maintarget$attachmentstate == MainTarget.AttachmentState.COLOR_DEPTH) { ++ if (maintarget$attachmentstate == targetState) { + return maintarget$dimension; + } + } +@@ -86,12 +_,24 @@ + return GlStateManager._getError() != 1285; + } + ++ private boolean allocateDepthStencilAttachment(MainTarget.Dimension p_166145_) { ++ RenderSystem.assertOnRenderThreadOrInit(); ++ GlStateManager._getError(); ++ GlStateManager._bindTexture(this.depthBufferId); ++ GlStateManager._texImage2D(3553, 0, 6402, p_166145_.width, p_166145_.height, 0, org.lwjgl.opengl.GL32.GL_DEPTH_STENCIL, org.lwjgl.opengl.GL32.GL_UNSIGNED_INT_24_8, null); ++ return GlStateManager._getError() != 1285; ++ } ++ + @OnlyIn(Dist.CLIENT) + static enum AttachmentState { + NONE, + COLOR, + DEPTH, +- COLOR_DEPTH; ++ COLOR_DEPTH, ++ STENCIL, ++ COLOR_STENCIL, ++ DEPTH_STENCIL, ++ COLOR_DEPTH_STENCIL; + + private static final MainTarget.AttachmentState[] VALUES = values(); + diff --git a/patches/com/mojang/blaze3d/pipeline/RenderTarget.java.patch b/patches/com/mojang/blaze3d/pipeline/RenderTarget.java.patch new file mode 100644 index 00000000000..dcb0a44d751 --- /dev/null +++ b/patches/com/mojang/blaze3d/pipeline/RenderTarget.java.patch @@ -0,0 +1,137 @@ +--- a/com/mojang/blaze3d/pipeline/RenderTarget.java ++++ b/com/mojang/blaze3d/pipeline/RenderTarget.java +@@ -25,17 +_,34 @@ + public int viewWidth; + public int viewHeight; + public final boolean useDepth; ++ public final boolean useStencil; + public int frameBufferId; + protected int colorTextureId; + protected int depthBufferId; ++ protected int stencilBufferId; + private final float[] clearChannels = Util.make(() -> new float[]{1.0F, 1.0F, 1.0F, 0.0F}); + public int filterMode; + ++ // If this is true, we can use stencil texture formats rather than combined depth-stencil textures. ++ private final boolean stencilTextureSupported; ++ + public RenderTarget(boolean p_166199_) { +- this.useDepth = p_166199_; ++ this(p_166199_, false); ++ } ++ ++ public RenderTarget(boolean useDepth, boolean useStencil) { ++ this.useDepth = useDepth; ++ this.useStencil = useStencil; + this.frameBufferId = -1; + this.colorTextureId = -1; + this.depthBufferId = -1; ++ ++ if (!useDepth && useStencil) { ++ var capabilities = org.lwjgl.opengl.GL.getCapabilities(); ++ stencilTextureSupported = capabilities.GL_ARB_texture_stencil8 || capabilities.OpenGL44; ++ } else { ++ stencilTextureSupported = false; ++ } + } + + public void resize(int p_83942_, int p_83943_) { +@@ -53,6 +_,11 @@ + RenderSystem.assertOnRenderThreadOrInit(); + this.unbindRead(); + this.unbindWrite(); ++ if (this.stencilBufferId > -1 && this.stencilBufferId != this.depthBufferId) { ++ TextureUtil.releaseTextureId(this.stencilBufferId); ++ this.stencilBufferId = -1; ++ } ++ + if (this.depthBufferId > -1) { + TextureUtil.releaseTextureId(this.depthBufferId); + this.depthBufferId = -1; +@@ -96,9 +_,50 @@ + GlStateManager._texParameter(3553, 34892, 0); + GlStateManager._texParameter(3553, 10242, 33071); + GlStateManager._texParameter(3553, 10243, 33071); ++ if (!this.useStencil) // If stenciling is enabled, we will fill this later + GlStateManager._texImage2D(3553, 0, 6402, this.width, this.height, 0, 6402, 5126, null); + } + ++ if (this.useStencil) { ++ if (this.useDepth) { ++ // If depth and stencil buffers are both enabled, we must combine them ++ this.stencilBufferId = this.depthBufferId; ++ } else { ++ // Otherwise, we can generate a new texture in its place. ++ this.stencilBufferId = TextureUtil.generateTextureId(); ++ GlStateManager._bindTexture(this.stencilBufferId); ++ GlStateManager._texParameter(3553, 10241, 9728); ++ GlStateManager._texParameter(3553, 10240, 9728); ++ GlStateManager._texParameter(3553, 34892, 0); ++ GlStateManager._texParameter(3553, 10242, 33071); ++ GlStateManager._texParameter(3553, 10243, 33071); ++ } ++ ++ if (this.useDepth || !stencilTextureSupported) { ++ // Use a combined format for both depth and stencil. ++ GlStateManager._texImage2D( ++ org.lwjgl.opengl.GL32.GL_TEXTURE_2D, ++ 0, ++ org.lwjgl.opengl.GL32.GL_DEPTH24_STENCIL8, ++ this.width, this.height, ++ 0, ++ org.lwjgl.opengl.GL32.GL_DEPTH_STENCIL, ++ org.lwjgl.opengl.GL32.GL_UNSIGNED_INT_24_8, ++ null); ++ } else { ++ // Otherwise, we can use a separate format. ++ GlStateManager._texImage2D( ++ org.lwjgl.opengl.GL32.GL_TEXTURE_2D, ++ 0, ++ org.lwjgl.opengl.GL32.GL_STENCIL_INDEX8, ++ this.width, this.height, ++ 0, ++ org.lwjgl.opengl.GL32.GL_STENCIL_INDEX, ++ org.lwjgl.opengl.GL32.GL_BYTE, ++ null); ++ } ++ } ++ + this.setFilterMode(9728, true); + GlStateManager._bindTexture(this.colorTextureId); + GlStateManager._texParameter(3553, 10242, 33071); +@@ -109,6 +_,14 @@ + if (this.useDepth) { + GlStateManager._glFramebufferTexture2D(36160, 36096, 3553, this.depthBufferId, 0); + } ++ if (this.useStencil) { ++ GlStateManager._glFramebufferTexture2D( ++ org.lwjgl.opengl.GL32.GL_FRAMEBUFFER, ++ org.lwjgl.opengl.GL32.GL_STENCIL_ATTACHMENT, ++ org.lwjgl.opengl.GL32.GL_TEXTURE_2D, ++ this.stencilBufferId, ++ 0); ++ } + + this.checkStatus(); + this.clear(); +@@ -218,6 +_,10 @@ + GlStateManager._clearDepth(1.0); + i |= 256; + } ++ if (this.useStencil) { ++ GlStateManager._clearStencil(0); ++ i |= org.lwjgl.opengl.GL32.GL_STENCIL_BUFFER_BIT; ++ } + + GlStateManager._clear(i); + this.unbindWrite(); +@@ -229,5 +_,9 @@ + + public int getDepthTextureId() { + return this.depthBufferId; ++ } ++ ++ public int getStencilTextureId() { ++ return this.stencilBufferId; + } + } diff --git a/patches/com/mojang/blaze3d/pipeline/TextureTarget.java.patch b/patches/com/mojang/blaze3d/pipeline/TextureTarget.java.patch new file mode 100644 index 00000000000..e0661d83e49 --- /dev/null +++ b/patches/com/mojang/blaze3d/pipeline/TextureTarget.java.patch @@ -0,0 +1,14 @@ +--- a/com/mojang/blaze3d/pipeline/TextureTarget.java ++++ b/com/mojang/blaze3d/pipeline/TextureTarget.java +@@ -7,7 +_,10 @@ + @OnlyIn(Dist.CLIENT) + public class TextureTarget extends RenderTarget { + public TextureTarget(int p_166213_, int p_166214_, boolean p_166215_) { +- super(p_166215_); ++ this(p_166213_, p_166214_, p_166215_, false); ++ } ++ public TextureTarget(int p_166213_, int p_166214_, boolean p_166215_, boolean useStencil) { ++ super(p_166215_, useStencil); + RenderSystem.assertOnRenderThreadOrInit(); + this.resize(p_166213_, p_166214_); + } diff --git a/patches/com/mojang/blaze3d/resource/RenderTargetDescriptor.java.patch b/patches/com/mojang/blaze3d/resource/RenderTargetDescriptor.java.patch new file mode 100644 index 00000000000..060e486b3c7 --- /dev/null +++ b/patches/com/mojang/blaze3d/resource/RenderTargetDescriptor.java.patch @@ -0,0 +1,18 @@ +--- a/com/mojang/blaze3d/resource/RenderTargetDescriptor.java ++++ b/com/mojang/blaze3d/resource/RenderTargetDescriptor.java +@@ -6,9 +_,13 @@ + import net.neoforged.api.distmarker.OnlyIn; + + @OnlyIn(Dist.CLIENT) +-public record RenderTargetDescriptor(int width, int height, boolean useDepth) implements ResourceDescriptor { ++public record RenderTargetDescriptor(int width, int height, boolean useDepth, boolean useStencil) implements ResourceDescriptor { ++ public RenderTargetDescriptor(int width, int height, boolean useDepth) { ++ this(width, height, useDepth, false); ++ } ++ + public RenderTarget allocate() { +- return new TextureTarget(this.width, this.height, this.useDepth); ++ return new TextureTarget(this.width, this.height, this.useDepth, this.useStencil); + } + + public void free(RenderTarget p_363223_) { diff --git a/patches/net/minecraft/client/Minecraft.java.patch b/patches/net/minecraft/client/Minecraft.java.patch index 04429bcce30..c59651003d2 100644 --- a/patches/net/minecraft/client/Minecraft.java.patch +++ b/patches/net/minecraft/client/Minecraft.java.patch @@ -8,7 +8,7 @@ this.demo = p_91084_.game.demo; this.allowsMultiplayer = !p_91084_.game.disableMultiplayer; this.allowsChat = !p_91084_.game.disableChat; -@@ -483,15 +_,17 @@ +@@ -483,15 +_,18 @@ LOGGER.error("Couldn't set icon", (Throwable)ioexception); } @@ -18,11 +18,13 @@ this.keyboardHandler = new KeyboardHandler(this); - this.keyboardHandler.setup(this.window.getWindow()); RenderSystem.initRenderer(this.options.glDebugVerbosity, false); - this.mainRenderTarget = new MainTarget(this.window.getWidth(), this.window.getHeight()); +- this.mainRenderTarget = new MainTarget(this.window.getWidth(), this.window.getHeight()); ++ net.neoforged.neoforge.client.loading.ClientModLoader.begin(this); ++ this.mainRenderTarget = net.neoforged.neoforge.client.ClientHooks.createMainRenderTarget(this.window.getWidth(), this.window.getHeight()); this.mainRenderTarget.setClearColor(0.0F, 0.0F, 0.0F, 0.0F); this.mainRenderTarget.clear(); this.resourceManager = new ReloadableResourceManager(PackType.CLIENT_RESOURCES); -+ net.neoforged.neoforge.client.loading.ClientModLoader.begin(this, this.resourcePackRepository, this.resourceManager); ++ net.neoforged.neoforge.client.loading.ClientModLoader.finish(this.resourcePackRepository, this.resourceManager); + //Move client bootstrap to after mod loading so that events can be fired for it. + ClientBootstrap.bootstrap(); this.resourcePackRepository.reload(); @@ -177,7 +179,7 @@ this.deltaTracker.updatePauseState(this.pause); this.deltaTracker.updateFrozenState(!this.isLevelRunningNormally()); long l = Util.getNanos(); -@@ -1351,10 +_,12 @@ +@@ -1351,10 +_,13 @@ this.window.setGuiScale((double)i); if (this.screen != null) { this.screen.resize(this, this.window.getGuiScaledWidth(), this.window.getGuiScaledHeight()); @@ -185,6 +187,7 @@ } RenderTarget rendertarget = this.getMainRenderTarget(); ++ if (rendertarget != null) rendertarget.resize(this.window.getWidth(), this.window.getHeight()); + if (this.gameRenderer != null) this.gameRenderer.resize(this.window.getWidth(), this.window.getHeight()); diff --git a/patches/net/minecraft/client/renderer/LevelRenderer.java.patch b/patches/net/minecraft/client/renderer/LevelRenderer.java.patch index 9173efdbf43..094b3d9dfee 100644 --- a/patches/net/minecraft/client/renderer/LevelRenderer.java.patch +++ b/patches/net/minecraft/client/renderer/LevelRenderer.java.patch @@ -1,5 +1,15 @@ --- a/net/minecraft/client/renderer/LevelRenderer.java +++ b/net/minecraft/client/renderer/LevelRenderer.java +@@ -459,7 +_,8 @@ + this.targets.main = framegraphbuilder.importExternal("main", this.minecraft.getMainRenderTarget()); + int i = this.minecraft.getMainRenderTarget().width; + int j = this.minecraft.getMainRenderTarget().height; +- RenderTargetDescriptor rendertargetdescriptor = new RenderTargetDescriptor(i, j, true); ++ boolean useStencil = this.minecraft.getMainRenderTarget().useStencil; ++ RenderTargetDescriptor rendertargetdescriptor = new RenderTargetDescriptor(i, j, true, useStencil); + PostChain postchain = this.getTransparencyChain(); + if (postchain != null) { + this.targets.translucent = framegraphbuilder.createInternal("translucent", rendertargetdescriptor); @@ -473,6 +_,9 @@ this.targets.entityOutline = framegraphbuilder.importExternal("entity_outline", this.entityOutlineTarget); } diff --git a/patches/net/minecraft/client/renderer/PostChain.java.patch b/patches/net/minecraft/client/renderer/PostChain.java.patch new file mode 100644 index 00000000000..0cabd6b5ec2 --- /dev/null +++ b/patches/net/minecraft/client/renderer/PostChain.java.patch @@ -0,0 +1,49 @@ +--- a/net/minecraft/client/renderer/PostChain.java ++++ b/net/minecraft/client/renderer/PostChain.java +@@ -79,8 +_,8 @@ + abstracttexture.setFilter(flag, false); + postpass.addInput(new PostPass.TextureInput(s3, abstracttexture, i, j)); + continue; +- case PostChainConfig.TargetInput(String s1, ResourceLocation resourcelocation1, boolean flag1, boolean flag2): +- postpass.addInput(new PostPass.TargetInput(s1, resourcelocation1, flag1, flag2)); ++ case PostChainConfig.TargetInput(String s1, ResourceLocation resourcelocation1, boolean flag1, boolean flag2, boolean useStencilBuffer): ++ postpass.addInput(new PostPass.TargetInput(s1, resourcelocation1, net.minecraft.client.renderer.PostPass.TargetInput.BufferType.from(flag1, useStencilBuffer), flag2)); + continue; + default: + throw new MatchException(null, null); +@@ -95,17 +_,33 @@ + Matrix4f matrix4f = new Matrix4f().setOrtho(0.0F, (float)p_361423_, 0.0F, (float)p_362735_, 0.1F, 1000.0F); + Map> map = new HashMap<>(this.internalTargets.size() + this.externalTargets.size()); + ++ // Enable the depth and stencil buffers based on whether any external targets use them. ++ // This is necessary so any created buffers get the correct parameters for blitting. ++ boolean useDepth = false; ++ boolean useStencil = false; + for (ResourceLocation resourcelocation : this.externalTargets) { + map.put(resourcelocation, p_361871_.getOrThrow(resourcelocation)); ++ ++ var handle = p_361871_.get(resourcelocation); ++ ++ if (handle instanceof FrameGraphBuilder.Handle frameHandle ++ && frameHandle.getDescriptor() instanceof RenderTargetDescriptor renderDescriptor) { ++ useDepth |= renderDescriptor.useDepth(); ++ useStencil |= renderDescriptor.useStencil(); ++ } else { ++ var target = handle.get(); ++ useDepth |= target.useDepth; ++ useStencil |= target.useStencil; ++ } + } + + for (Entry entry : this.internalTargets.entrySet()) { + ResourceLocation resourcelocation1 = entry.getKey(); + RenderTargetDescriptor rendertargetdescriptor = switch (entry.getValue()) { + case PostChainConfig.FixedSizedTarget(int i, int j) -> { +- yield new RenderTargetDescriptor(i, j, true); ++ yield new RenderTargetDescriptor(i, j, useDepth, useStencil); + } +- case PostChainConfig.FullScreenTarget postchainconfig$fullscreentarget -> new RenderTargetDescriptor(p_361423_, p_362735_, true); ++ case PostChainConfig.FullScreenTarget postchainconfig$fullscreentarget -> new RenderTargetDescriptor(p_361423_, p_362735_, useDepth, useStencil); + default -> throw new MatchException(null, null); + }; + map.put(resourcelocation1, p_362523_.createInternal(resourcelocation1.toString(), rendertargetdescriptor)); diff --git a/patches/net/minecraft/client/renderer/PostChainConfig.java.patch b/patches/net/minecraft/client/renderer/PostChainConfig.java.patch new file mode 100644 index 00000000000..131ae122196 --- /dev/null +++ b/patches/net/minecraft/client/renderer/PostChainConfig.java.patch @@ -0,0 +1,15 @@ +--- a/net/minecraft/client/renderer/PostChainConfig.java ++++ b/net/minecraft/client/renderer/PostChainConfig.java +@@ -108,7 +_,11 @@ + } + + @OnlyIn(Dist.CLIENT) +- public static record TargetInput(String samplerName, ResourceLocation targetId, boolean useDepthBuffer, boolean bilinear) implements PostChainConfig.Input { ++ public static record TargetInput(String samplerName, ResourceLocation targetId, boolean useDepthBuffer, boolean bilinear, boolean useStencilBuffer) implements PostChainConfig.Input { ++ public TargetInput(String samplerName, ResourceLocation targetId, boolean useDepthBuffer, boolean bilinear) { ++ this(samplerName, targetId, useDepthBuffer, bilinear, false); ++ } ++ + public static final Codec CODEC = RecordCodecBuilder.create( + p_363892_ -> p_363892_.group( + Codec.STRING.fieldOf("sampler_name").forGetter(PostChainConfig.TargetInput::samplerName), diff --git a/patches/net/minecraft/client/renderer/PostPass.java.patch b/patches/net/minecraft/client/renderer/PostPass.java.patch new file mode 100644 index 00000000000..efa98f666ba --- /dev/null +++ b/patches/net/minecraft/client/renderer/PostPass.java.patch @@ -0,0 +1,73 @@ +--- a/net/minecraft/client/renderer/PostPass.java ++++ b/net/minecraft/client/renderer/PostPass.java +@@ -122,7 +_,54 @@ + } + + @OnlyIn(Dist.CLIENT) +- public static record TargetInput(String samplerName, ResourceLocation targetId, boolean depthBuffer, boolean bilinear) implements PostPass.Input { ++ public static record TargetInput(String samplerName, ResourceLocation targetId, BufferType bufferType, boolean bilinear) implements PostPass.Input { ++ public enum BufferType { ++ NONE(false, false), ++ DEPTH_ONLY(true, false), ++ STENCIL_ONLY(false, true), ++ DEPTH_STENCIL(true, true); ++ ++ private final boolean depth; ++ private final boolean stencil; ++ ++ BufferType(boolean depth, boolean stencil) { ++ this.depth = depth; ++ this.stencil = stencil; ++ } ++ ++ public boolean hasDepth() { ++ return this.depth; ++ } ++ ++ public boolean hasStencil() { ++ return this.stencil; ++ } ++ ++ public static BufferType from(boolean useDepth, boolean useStencil) { ++ if (useDepth && useStencil) { ++ return DEPTH_STENCIL; ++ } else if (useDepth) { ++ return DEPTH_ONLY; ++ } else if (useStencil) { ++ return STENCIL_ONLY; ++ } else { ++ return NONE; ++ } ++ } ++ } ++ ++ public TargetInput(String samplerName, ResourceLocation targetId, boolean depthBuffer, boolean bilinear) { ++ this(samplerName, targetId, depthBuffer ? BufferType.DEPTH_ONLY : BufferType.NONE, bilinear); ++ } ++ ++ public boolean depthBuffer() { ++ return bufferType.hasDepth(); ++ } ++ ++ public boolean stencilBuffer() { ++ return bufferType.hasStencil(); ++ } ++ + private ResourceHandle getHandle(Map> p_364534_) { + ResourceHandle resourcehandle = p_364534_.get(this.targetId); + if (resourcehandle == null) { +@@ -142,7 +_,13 @@ + ResourceHandle resourcehandle = this.getHandle(p_361239_); + RenderTarget rendertarget = resourcehandle.get(); + rendertarget.setFilterMode(this.bilinear ? 9729 : 9728); +- p_366564_.bindSampler(this.samplerName + "Sampler", this.depthBuffer ? rendertarget.getDepthTextureId() : rendertarget.getColorTextureId()); ++ if (this.depthBuffer()) ++ p_366564_.bindSampler(this.samplerName + "Sampler", rendertarget.getDepthTextureId()); ++ // If stencil is specified ++ else if (this.stencilBuffer()) ++ p_366564_.bindSampler(this.samplerName + "Sampler", rendertarget.getStencilTextureId()); ++ else ++ p_366564_.bindSampler(this.samplerName + "Sampler", rendertarget.getColorTextureId()); + p_366564_.safeGetUniform(this.samplerName + "Size").set((float)rendertarget.width, (float)rendertarget.height); + } + diff --git a/src/main/java/net/neoforged/neoforge/client/ClientHooks.java b/src/main/java/net/neoforged/neoforge/client/ClientHooks.java index 7e497ecaf27..df2e9ab4ad8 100644 --- a/src/main/java/net/neoforged/neoforge/client/ClientHooks.java +++ b/src/main/java/net/neoforged/neoforge/client/ClientHooks.java @@ -9,6 +9,7 @@ import com.google.common.collect.HashBiMap; import com.google.common.collect.ImmutableMap; import com.mojang.blaze3d.framegraph.FrameGraphBuilder; +import com.mojang.blaze3d.pipeline.MainTarget; import com.mojang.blaze3d.platform.NativeImage; import com.mojang.blaze3d.platform.Window; import com.mojang.blaze3d.resource.RenderTargetDescriptor; @@ -144,6 +145,7 @@ import net.neoforged.neoforge.client.event.ClientPlayerNetworkEvent; import net.neoforged.neoforge.client.event.ClientTickEvent; import net.neoforged.neoforge.client.event.ComputeFovModifierEvent; +import net.neoforged.neoforge.client.event.ConfigureMainRenderTargetEvent; import net.neoforged.neoforge.client.event.CustomizeGuiOverlayEvent; import net.neoforged.neoforge.client.event.EntityRenderersEvent; import net.neoforged.neoforge.client.event.FrameGraphSetupEvent; @@ -1099,4 +1101,10 @@ public static Map gatherMaterialAtlases(Map< public static FrameGraphSetupEvent fireFrameGraphSetup(FrameGraphBuilder builder, LevelTargetBundle targets, RenderTargetDescriptor renderTargetDescriptor, Frustum frustum, Camera camera, Matrix4f modelViewMatrix, Matrix4f projectionMatrix, DeltaTracker deltaTracker, ProfilerFiller profiler) { return NeoForge.EVENT_BUS.post(new FrameGraphSetupEvent(builder, targets, renderTargetDescriptor, frustum, camera, modelViewMatrix, projectionMatrix, deltaTracker, profiler)); } + + @ApiStatus.Internal + public static MainTarget createMainRenderTarget(int width, int height) { + var e = ModLoader.postEventWithReturn(new ConfigureMainRenderTargetEvent(width, height)); + return new MainTarget(width, height, e.useDepth(), e.useStencil()); + } } diff --git a/src/main/java/net/neoforged/neoforge/client/event/ConfigureMainRenderTargetEvent.java b/src/main/java/net/neoforged/neoforge/client/event/ConfigureMainRenderTargetEvent.java new file mode 100644 index 00000000000..1e4803f466e --- /dev/null +++ b/src/main/java/net/neoforged/neoforge/client/event/ConfigureMainRenderTargetEvent.java @@ -0,0 +1,83 @@ +/* + * Copyright (c) NeoForged and contributors + * SPDX-License-Identifier: LGPL-2.1-only + */ + +package net.neoforged.neoforge.client.event; + +import com.mojang.blaze3d.pipeline.MainTarget; +import net.neoforged.bus.api.Event; +import net.neoforged.bus.api.ICancellableEvent; +import net.neoforged.fml.LogicalSide; +import net.neoforged.fml.event.IModBusEvent; +import org.jetbrains.annotations.ApiStatus; + +/** + * Fired when configuring the {@linkplain MainTarget main render target} during startup. + *

+ * This event is not {@linkplain ICancellableEvent cancellable}. + *

+ * This event is fired on the mod-specific event bus, only on the {@linkplain LogicalSide#CLIENT logical client}. + */ +public class ConfigureMainRenderTargetEvent extends Event implements IModBusEvent { + private final boolean useDepth; + private boolean useStencil; + + private final int width; + private final int height; + + @ApiStatus.Internal + public ConfigureMainRenderTargetEvent(int width, int height) { + this.useDepth = true; + this.useStencil = false; + + this.width = width; + this.height = height; + } + + /** + * Returns whether the depth buffer was enabled. + * + * @return true, if the depth buffer is enabled, or false otherwise. + */ + public boolean useDepth() { + return this.useDepth; + } + + /** + * Returns whether the stencil buffer was requested. + * + * @return true, if the stencil buffer is enabled, or false otherwise. + */ + public boolean useStencil() { + return this.useStencil; + } + + /** + * Returns the preferred width of the framebuffer. + * + * @return The width, in pixels, to attempt to use for the framebuffer. + */ + public int width() { + return this.width; + } + + /** + * Returns the preferred height of the framebuffer. + * + * @return The height, in pixels, to attempt to use for the framebuffer. + */ + public int height() { + return this.height; + } + + /** + * Enable the stencil buffer for the main render target. + * + * @return this, for method chaining. + */ + public ConfigureMainRenderTargetEvent enableStencil() { + this.useStencil = true; + return this; + } +} diff --git a/src/main/java/net/neoforged/neoforge/client/loading/ClientModLoader.java b/src/main/java/net/neoforged/neoforge/client/loading/ClientModLoader.java index d8c4a35e616..4ee4d48b270 100644 --- a/src/main/java/net/neoforged/neoforge/client/loading/ClientModLoader.java +++ b/src/main/java/net/neoforged/neoforge/client/loading/ClientModLoader.java @@ -47,7 +47,7 @@ public class ClientModLoader extends CommonModLoader { @Nullable private static ModLoadingException error; - public static void begin(final Minecraft minecraft, final PackRepository defaultResourcePacks, final ReloadableResourceManager mcResourceManager) { + public static void begin(final Minecraft minecraft) { // force log4j to shutdown logging in a shutdown hook. This is because we disable default shutdown hook so the server properly logs it's shutdown Runtime.getRuntime().addShutdownHook(new Thread(LogManager::shutdown)); ImmediateWindowHandler.updateProgress("Loading mods"); @@ -60,6 +60,9 @@ public static void begin(final Minecraft minecraft, final PackRepository default } catch (ModLoadingException e) { error = e; } + } + + public static void finish(final PackRepository defaultResourcePacks, final ReloadableResourceManager mcResourceManager) { if (error == null) { ResourcePackLoader.populatePackRepository(defaultResourcePacks, PackType.CLIENT_RESOURCES, false); DataPackConfig.DEFAULT.addModPacks(ResourcePackLoader.getPackNames(PackType.SERVER_DATA)); diff --git a/src/main/resources/META-INF/accesstransformer.cfg b/src/main/resources/META-INF/accesstransformer.cfg index fc21dedc592..1f4ce258fa3 100644 --- a/src/main/resources/META-INF/accesstransformer.cfg +++ b/src/main/resources/META-INF/accesstransformer.cfg @@ -1,4 +1,8 @@ # Note: This file is for manually added ATs. When AT entries can be programmatically generated based on fixed rules you may define those rules in the build.gradle file +public com.mojang.blaze3d.framegraph.FrameGraphBuilder$Handle +public com.mojang.blaze3d.framegraph.FrameGraphBuilder$Handle holder +public com.mojang.blaze3d.framegraph.FrameGraphBuilder$VirtualResource +public com.mojang.blaze3d.framegraph.FrameGraphBuilder$Pass public net.minecraft.advancements.CriteriaTriggers register(Ljava/lang/String;Lnet/minecraft/advancements/CriterionTrigger;)Lnet/minecraft/advancements/CriterionTrigger; # register default net.minecraft.client.KeyMapping isDown # isDown public-f net.minecraft.client.Options keyMappings # keyMappings