Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Restore ability to enable stenciling #1830

Merged
merged 35 commits into from
Jan 18, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
ea3aeb4
Separate ClientModLoader begin/finish into two methods, implement Mai…
FiniteReality Nov 27, 2024
5135ec1
Flow stencil information through post chains
FiniteReality Nov 30, 2024
613cb46
Fix copy-paste fail in RenderTarget
FiniteReality Dec 8, 2024
f938bfe
Use an enum for the buffer type instead of two bools
FiniteReality Dec 8, 2024
b5cd630
Fix import whoopsie
FiniteReality Dec 8, 2024
922fad6
Fix stenciling on the main target
FiniteReality Dec 9, 2024
721d79d
Remove no-op method for enabling depth, pass desired width/height
FiniteReality Dec 9, 2024
ff68a10
Minimise patch by removing unnecessary indentation
FiniteReality Dec 9, 2024
117c7af
Respond to XFact's feedback
FiniteReality Dec 30, 2024
f278e8d
Remove stencil-only patches in MainTarget
FiniteReality Jan 9, 2025
552d636
Stencil requires depth
Technici4n Jan 9, 2025
2278de1
Remove unnecessary AttachmentState patch
Technici4n Jan 9, 2025
fa4ebe7
Keep simplifying
Technici4n Jan 9, 2025
f3df3e4
Keep simplifying?
Technici4n Jan 9, 2025
46e68fe
Missed old patch to delete
Technici4n Jan 9, 2025
02a1ea2
getDescriptor simplification
Technici4n Jan 9, 2025
f62e417
Simplified event
shartte Jan 9, 2025
3f5ddc1
Simplify allocation (+ missed genPatches)
Technici4n Jan 9, 2025
1f62c68
Fix patches that I didn't cherry pick
Technici4n Jan 14, 2025
3a9cf29
Remove bad patch (my bad)
Technici4n Jan 14, 2025
d4e0484
Experiment with going back to a global stencil parameter, still confi…
Technici4n Jan 14, 2025
7946bfc
Split off mod construction and registry+config loading. Not sure it i…
Technici4n Jan 14, 2025
42746f0
Use global stencil state
Technici4n Jan 14, 2025
b70c8f7
Add super basic test and make things work
Technici4n Jan 14, 2025
d2ed447
Document stencil test, and prefer RenderSystem or GL30 to GL33
Technici4n Jan 15, 2025
5f4bd67
Align MainTarget and RenderTarget patches
Technici4n Jan 15, 2025
d5c0198
Revert "Split off mod construction and registry+config loading. Not s…
Technici4n Jan 15, 2025
2ea4992
Remove now-unneeded ATs
Technici4n Jan 15, 2025
2bbe875
Add config option to choose between 24+8 and 32+8 formats
Technici4n Jan 15, 2025
9de54d2
Remove rendertarget != null check
Technici4n Jan 15, 2025
7f4952d
add small clarification
Technici4n Jan 15, 2025
76b0d06
Fix test breaking screen rendering and semi-disable by default
Technici4n Jan 15, 2025
2a2b00a
Immaculate
Technici4n Jan 16, 2025
057ecba
Address review comments
Technici4n Jan 16, 2025
e8f3e14
Do not use stencil for PostChain internal buffers since it is not usa…
Technici4n Jan 16, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
42 changes: 42 additions & 0 deletions patches/com/mojang/blaze3d/pipeline/MainTarget.java.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
--- a/com/mojang/blaze3d/pipeline/MainTarget.java
+++ b/com/mojang/blaze3d/pipeline/MainTarget.java
@@ -16,7 +_,10 @@
static final MainTarget.Dimension DEFAULT_DIMENSIONS = new MainTarget.Dimension(854, 480);

public MainTarget(int p_166137_, int p_166138_) {
- super(true);
+ this(p_166137_, p_166138_, false);
+ }
+ public MainTarget(int p_166137_, int p_166138_, boolean enableStencil) {
+ super(true, enableStencil);
this.createFrameBuffer(p_166137_, p_166138_);
}

@@ -37,6 +_,14 @@
GlStateManager._texParameter(3553, 10242, 33071);
GlStateManager._texParameter(3553, 10243, 33071);
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.depthBufferId,
+ 0);
+ }
GlStateManager._bindTexture(0);
this.viewWidth = maintarget$dimension.width;
this.viewHeight = maintarget$dimension.height;
@@ -82,7 +_,11 @@
RenderSystem.assertOnRenderThreadOrInit();
GlStateManager._getError();
GlStateManager._bindTexture(this.depthBufferId);
- GlStateManager._texImage2D(3553, 0, 6402, p_166145_.width, p_166145_.height, 0, 6402, 5126, null);
+ if (!this.useStencil) {
+ GlStateManager._texImage2D(3553, 0, 6402, p_166145_.width, p_166145_.height, 0, 6402, 5126, null);
+ } else {
+ net.neoforged.neoforge.client.ClientHooks.texImageDepthStencil(p_166145_.width, p_166145_.height);
+ }
return GlStateManager._getError() != 1285;
}

66 changes: 66 additions & 0 deletions patches/com/mojang/blaze3d/pipeline/RenderTarget.java.patch
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
--- a/com/mojang/blaze3d/pipeline/RenderTarget.java
+++ b/com/mojang/blaze3d/pipeline/RenderTarget.java
@@ -25,6 +_,7 @@
public int viewWidth;
public int viewHeight;
public final boolean useDepth;
+ public final boolean useStencil;
public int frameBufferId;
protected int colorTextureId;
protected int depthBufferId;
@@ -32,7 +_,15 @@
public int filterMode;

public RenderTarget(boolean p_166199_) {
- this.useDepth = p_166199_;
+ this(p_166199_, false);
+ }
+
+ public RenderTarget(boolean useDepth, boolean useStencil) {
+ if (useStencil && !useDepth) {
+ throw new IllegalArgumentException("Stencil can only be enabled if depth is enabled.");
+ }
+ this.useDepth = useDepth;
+ this.useStencil = useStencil;
this.frameBufferId = -1;
this.colorTextureId = -1;
this.depthBufferId = -1;
@@ -96,7 +_,11 @@
GlStateManager._texParameter(3553, 34892, 0);
GlStateManager._texParameter(3553, 10242, 33071);
GlStateManager._texParameter(3553, 10243, 33071);
- GlStateManager._texImage2D(3553, 0, 6402, this.width, this.height, 0, 6402, 5126, null);
+ if (!this.useStencil) {
+ GlStateManager._texImage2D(3553, 0, 6402, this.width, this.height, 0, 6402, 5126, null);
+ } else {
+ net.neoforged.neoforge.client.ClientHooks.texImageDepthStencil(this.width, this.height);
+ }
}

this.setFilterMode(9728, true);
@@ -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.depthBufferId,
+ 0);
+ }

this.checkStatus();
this.clear();
@@ -217,6 +_,10 @@
if (this.useDepth) {
GlStateManager._clearDepth(1.0);
i |= 256;
+ }
+ if (this.useStencil) {
+ GlStateManager._clearStencil(0);
+ i |= org.lwjgl.opengl.GL32.GL_STENCIL_BUFFER_BIT;
}

GlStateManager._clear(i);
14 changes: 14 additions & 0 deletions patches/com/mojang/blaze3d/pipeline/TextureTarget.java.patch
Original file line number Diff line number Diff line change
@@ -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_);
}
Original file line number Diff line number Diff line change
@@ -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<RenderTarget> {
+public record RenderTargetDescriptor(int width, int height, boolean useDepth, boolean useStencil) implements ResourceDescriptor<RenderTarget> {
+ 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_) {
8 changes: 5 additions & 3 deletions patches/net/minecraft/client/Minecraft.java.patch
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}

Expand All @@ -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.instantiateMainTarget(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();
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,14 @@
--- a/net/minecraft/client/renderer/LevelRenderer.java
+++ b/net/minecraft/client/renderer/LevelRenderer.java
@@ -459,7 +_,7 @@
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);
+ RenderTargetDescriptor rendertargetdescriptor = new RenderTargetDescriptor(i, j, true, this.minecraft.getMainRenderTarget().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);
}
Expand Down
30 changes: 30 additions & 0 deletions src/main/java/net/neoforged/neoforge/client/ClientHooks.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
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.GlStateManager;
import com.mojang.blaze3d.platform.NativeImage;
import com.mojang.blaze3d.platform.Window;
import com.mojang.blaze3d.resource.RenderTargetDescriptor;
Expand Down Expand Up @@ -144,6 +146,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;
Expand Down Expand Up @@ -182,6 +185,7 @@
import net.neoforged.neoforge.client.model.data.ModelData;
import net.neoforged.neoforge.client.renderstate.RegisterRenderStateModifiersEvent;
import net.neoforged.neoforge.common.NeoForge;
import net.neoforged.neoforge.common.NeoForgeConfig;
import net.neoforged.neoforge.common.NeoForgeMod;
import net.neoforged.neoforge.forge.snapshots.ForgeSnapshotsModClient;
import net.neoforged.neoforge.gametest.GameTestHooks;
Expand All @@ -195,6 +199,7 @@
import org.joml.Matrix4f;
import org.joml.Vector3f;
import org.joml.Vector4f;
import org.lwjgl.opengl.GL32;

/**
* Class for various client-side-only hooks.
Expand Down Expand Up @@ -1099,4 +1104,29 @@ public static Map<ResourceLocation, ResourceLocation> 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 instantiateMainTarget(int width, int height) {
var e = ModLoader.postEventWithReturn(new ConfigureMainRenderTargetEvent());
return new MainTarget(width, height, e.isStencilEnabled());
}

/**
* Called by our stencil hooks to specify the depth+stencil texture.
*/
@ApiStatus.Internal
public static void texImageDepthStencil(int width, int height) {
var reducedPrecision = NeoForgeConfig.CLIENT.reducedDepthStencilFormat.getAsBoolean();
GlStateManager._texImage2D(
GL32.GL_TEXTURE_2D,
0,
reducedPrecision ? GL32.GL_DEPTH24_STENCIL8 : GL32.GL_DEPTH32F_STENCIL8,
width, height,
0,
GL32.GL_DEPTH_STENCIL,
// Since data is null, the format here does not matter as long as it matches internalFormat.
// So the usage, for depth, of unsigned int in one case and float in the other case, is not a problem.
reducedPrecision ? GL32.GL_UNSIGNED_INT_24_8 : GL32.GL_FLOAT_32_UNSIGNED_INT_24_8_REV,
null);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
/*
* 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;

/**
* Fired when configuring the {@linkplain MainTarget main render target} during startup.
* <p>
* This event is not {@linkplain ICancellableEvent cancellable}.
* <p>
* 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 boolean enableStencil;

/**
* Returns whether enabling the stencil buffer on the main render target was requested.
*
* @return <code>true</code>, if the stencil buffer is enabled, or <code>false</code> otherwise.
*/
public boolean isStencilEnabled() {
return this.enableStencil;
}

/**
* Enables the stencil buffer for the main render target.
*/
public void enableStencil() {
this.enableStencil = true;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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");
Expand All @@ -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));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,8 @@ public static class Client {

public final BooleanValue logUntranslatedConfigurationWarnings;

public final BooleanValue reducedDepthStencilFormat;

Client(ModConfigSpec.Builder builder) {
experimentalForgeLightPipelineEnabled = builder
.comment("EXPERIMENTAL: Enable the NeoForge block rendering pipeline - fixes the lighting of custom models.")
Expand All @@ -114,6 +116,11 @@ public static class Client {
.comment("A config option mainly for developers. Logs out configuration values that do not have translations when running a client in a development environment.")
.translation("neoforge.configgui.logUntranslatedConfigurationWarnings")
.define("logUntranslatedConfigurationWarnings", true);

reducedDepthStencilFormat = builder
.comment("Configures how many bits are used for the depth buffer when stenciling has been enabled by a mod. Set to true for 24+8 bits and to false for 32+8 bits. Setting to true will slightly reduce VRAM usage, but risks introducing visual artifacts.")
.translation("neoforge.configgui.reducedDepthStencilFormat")
.define("reducedDepthStencilFormat", false);
}
}

Expand Down
2 changes: 2 additions & 0 deletions src/main/resources/assets/neoforge/lang/en_us.json
Original file line number Diff line number Diff line change
Expand Up @@ -206,6 +206,8 @@
"neoforge.configgui.logUntranslatedItemTagWarnings.tooltip": "A config option mainly for developers. Logs out modded item tags that do not have translations when running on integrated server. Format desired is tag.item.<namespace>.<path> for the translation key. Defaults to SILENCED.",
"neoforge.configgui.permissionHandler": "Permission Handler",
"neoforge.configgui.permissionHandler.tooltip": "The permission handler used by the server. Defaults to neoforge:default_handler if no such handler with that name is registered.",
"neoforge.configgui.reducedDepthStencilFormat": "Reduced Depth+Stencil Format",
"neoforge.configgui.reducedDepthStencilFormat.tooltip": "Configures how many bits are used for the depth buffer when stenciling has been enabled by a mod. Set to true for 24+8 bits and to false for 32+8 bits. Setting to true will slightly reduce VRAM usage, but risks introducing visual artifacts.",
"neoforge.configgui.removeErroringBlockEntities": "Remove Erroring Block Entities",
"neoforge.configgui.removeErroringBlockEntities.tooltip": "Set this to true to remove any BlockEntity that throws an error in its update method instead of closing the server and reporting a crash log.",
"neoforge.configgui.removeErroringBlockEntities.tooltip.warning": "BE WARNED THIS COULD SCREW UP EVERYTHING.\nUSE SPARINGLY.\nWE ARE NOT RESPONSIBLE FOR DAMAGES.",
Expand Down
Loading
Loading