Skip to content

Commit

Permalink
Fusion bloom fix & other bloom effect API modifications (GregTechCEu#…
Browse files Browse the repository at this point in the history
  • Loading branch information
Tictim authored May 7, 2024
1 parent 46d2dc0 commit d006d60
Show file tree
Hide file tree
Showing 6 changed files with 177 additions and 31 deletions.
7 changes: 7 additions & 0 deletions src/main/java/gregtech/client/event/ClientEventHandler.java
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
import gregtech.client.renderer.handler.BlockPosHighlightRenderer;
import gregtech.client.renderer.handler.MultiblockPreviewRenderer;
import gregtech.client.renderer.handler.TerminalARRenderer;
import gregtech.client.utils.BloomEffectUtil;
import gregtech.client.utils.DepthTextureUtil;
import gregtech.client.utils.TooltipHelper;
import gregtech.common.ConfigHolder;
Expand All @@ -24,6 +25,7 @@
import net.minecraft.util.EnumHand;
import net.minecraft.util.ResourceLocation;
import net.minecraftforge.client.event.*;
import net.minecraftforge.event.world.WorldEvent;
import net.minecraftforge.fml.client.event.ConfigChangedEvent;
import net.minecraftforge.fml.common.Mod;
import net.minecraftforge.fml.common.eventhandler.EventPriority;
Expand Down Expand Up @@ -157,4 +159,9 @@ private static void renderHUDMetaItem(@NotNull ItemStack stack) {
}
}
}

@SubscribeEvent
public static void onWorldUnload(WorldEvent.Unload event) {
BloomEffectUtil.invalidateWorldTickets(event.getWorld());
}
}
10 changes: 9 additions & 1 deletion src/main/java/gregtech/client/particle/GTOverheatParticle.java
Original file line number Diff line number Diff line change
Expand Up @@ -251,7 +251,15 @@ public void renderBloomEffect(@NotNull BufferBuilder buffer, @NotNull EffectRend

@Override
public boolean shouldRenderBloomEffect(@NotNull EffectRenderContext context) {
return !this.insulated;
if (this.insulated) return false;
for (Cuboid6 cuboid : pipeBoxes) {
if (!context.camera().isBoxInFrustum(
cuboid.min.x + posX, cuboid.min.y + posY, cuboid.min.z + posZ,
cuboid.max.x + posX, cuboid.max.y + posY, cuboid.max.z + posZ)) {
return false;
}
}
return true;
}

private static final IRenderSetup SETUP = new IRenderSetup() {
Expand Down
158 changes: 136 additions & 22 deletions src/main/java/gregtech/client/utils/BloomEffectUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
import net.minecraft.entity.Entity;
import net.minecraft.launchwrapper.Launch;
import net.minecraft.util.BlockRenderLayer;
import net.minecraft.world.World;
import net.minecraftforge.common.util.EnumHelper;
import net.minecraftforge.fml.relauncher.Side;
import net.minecraftforge.fml.relauncher.SideOnly;
Expand All @@ -38,15 +39,19 @@
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.locks.ReentrantLock;
import java.util.function.Consumer;
import java.util.function.Predicate;
import java.util.function.Supplier;

@SideOnly(Side.CLIENT)
public class BloomEffectUtil {

private static final Map<BloomRenderKey, List<BloomRenderTicket>> BLOOM_RENDERS = new Object2ObjectOpenHashMap<>();
private static final List<BloomRenderTicket> SCHEDULED_BLOOM_RENDERS = new ArrayList<>();

private static final ReentrantLock BLOOM_RENDER_LOCK = new ReentrantLock();

/**
* @deprecated use {@link #getBloomLayer()}
*/
Expand Down Expand Up @@ -147,12 +152,12 @@ public static Framebuffer getBloomFBO() {
/**
* <p>
* Register a custom bloom render callback for subsequent world render. The render call persists until the
* {@code metaTileEntity} is invalidated, or the ticket is manually freed by calling
* {@link BloomRenderTicket#invalidate()}.
* {@code metaTileEntity} is invalidated, or the world associated with {@code metaTileEntity} or the ticket is
* manually freed by calling {@link BloomRenderTicket#invalidate()}.
* </p>
* <p>
* This method does not register bloom render ticket when Optifine is present, and {@code null} will be returned
* instead of a ticket instance.
* This method does not register bloom render ticket when Optifine is present, and an invalid ticket will be
* returned instead.
* </p>
*
* @param setup Render setup, if exists
Expand All @@ -162,13 +167,28 @@ public static Framebuffer getBloomFBO() {
* @return Ticket for the registered bloom render callback
* @throws NullPointerException if {@code bloomType == null || render == null || metaTileEntity == null}
*/
@Nullable
@NotNull
public static BloomRenderTicket registerBloomRender(@Nullable IRenderSetup setup,
@NotNull BloomType bloomType,
@NotNull IBloomEffect render,
@NotNull MetaTileEntity metaTileEntity) {
Objects.requireNonNull(metaTileEntity, "metaTileEntity == null");
return registerBloomRender(setup, bloomType, render, t -> metaTileEntity.isValid());
return registerBloomRender(setup, bloomType,
new IBloomEffect() {

@Override
public void renderBloomEffect(@NotNull BufferBuilder buffer, @NotNull EffectRenderContext context) {
render.renderBloomEffect(buffer, context);
}

@Override
public boolean shouldRenderBloomEffect(@NotNull EffectRenderContext context) {
return metaTileEntity.getWorld() == context.renderViewEntity().world &&
render.shouldRenderBloomEffect(context);
}
},
t -> metaTileEntity.isValid(),
metaTileEntity::getWorld);
}

/**
Expand All @@ -178,8 +198,8 @@ public static BloomRenderTicket registerBloomRender(@Nullable IRenderSetup setup
* {@link BloomRenderTicket#invalidate()}.
* </p>
* <p>
* This method does not register bloom render ticket when Optifine is present, and {@code null} will be returned
* instead of a ticket instance.
* This method does not register bloom render ticket when Optifine is present, and an invalid ticket will be
* returned instead.
* </p>
*
* @param setup Render setup, if exists
Expand All @@ -189,7 +209,7 @@ public static BloomRenderTicket registerBloomRender(@Nullable IRenderSetup setup
* @return Ticket for the registered bloom render callback
* @throws NullPointerException if {@code bloomType == null || render == null || metaTileEntity == null}
*/
@Nullable
@NotNull
public static BloomRenderTicket registerBloomRender(@Nullable IRenderSetup setup,
@NotNull BloomType bloomType,
@NotNull IBloomEffect render,
Expand All @@ -204,8 +224,8 @@ public static BloomRenderTicket registerBloomRender(@Nullable IRenderSetup setup
* manually freed by calling {@link BloomRenderTicket#invalidate()}, or invalidated by validity checker.
* </p>
* <p>
* This method does not register bloom render ticket when Optifine is present, and {@code null} will be returned
* instead of a ticket instance.
* This method does not register bloom render ticket when Optifine is present, and an invalid ticket will be
* returned instead.
* </p>
*
* @param setup Render setup, if exists
Expand All @@ -215,18 +235,85 @@ public static BloomRenderTicket registerBloomRender(@Nullable IRenderSetup setup
* Checked on both pre/post render each frame.
* @return Ticket for the registered bloom render callback
* @throws NullPointerException if {@code bloomType == null || render == null}
* @see #registerBloomRender(IRenderSetup, BloomType, IBloomEffect, MetaTileEntity)
* @see #registerBloomRender(IRenderSetup, BloomType, IBloomEffect, GTParticle)
* @see #registerBloomRender(IRenderSetup, BloomType, IBloomEffect, Predicate, Supplier)
*/
@Nullable
@NotNull
public static BloomRenderTicket registerBloomRender(@Nullable IRenderSetup setup,
@NotNull BloomType bloomType,
@NotNull IBloomEffect render,
@Nullable Predicate<BloomRenderTicket> validityChecker) {
if (Mods.Optifine.isModLoaded()) return null;
BloomRenderTicket ticket = new BloomRenderTicket(setup, bloomType, render, validityChecker);
SCHEDULED_BLOOM_RENDERS.add(ticket);
return registerBloomRender(setup, bloomType, render, validityChecker, null);
}

/**
* <p>
* Register a custom bloom render callback for subsequent world render. The render call persists until it is
* manually freed by calling {@link BloomRenderTicket#invalidate()}, or invalidated by validity checker.
* </p>
* <p>
* This method does not register bloom render ticket when Optifine is present, and an invalid ticket will be
* returned instead.
* </p>
*
* @param setup Render setup, if exists
* @param bloomType Type of the bloom
* @param render Rendering callback
* @param validityChecker Optional validity checker; returning {@code false} causes the ticket to be invalidated.
* Checked on both pre/post render each frame.
* @param worldContext Optional world bound to the ticket. If the world returned is not null, the bloom ticket
* will be automatically invalidated on world unload. If world context returns {@code null},
* it will not be affected by aforementioned automatic invalidation.
* @return Ticket for the registered bloom render callback
* @throws NullPointerException if {@code bloomType == null || render == null}
* @see #registerBloomRender(IRenderSetup, BloomType, IBloomEffect, MetaTileEntity)
* @see #registerBloomRender(IRenderSetup, BloomType, IBloomEffect, GTParticle)
*/
@NotNull
public static BloomRenderTicket registerBloomRender(@Nullable IRenderSetup setup,
@NotNull BloomType bloomType,
@NotNull IBloomEffect render,
@Nullable Predicate<BloomRenderTicket> validityChecker,
@Nullable Supplier<World> worldContext) {
if (Mods.Optifine.isModLoaded()) return BloomRenderTicket.INVALID;
BloomRenderTicket ticket = new BloomRenderTicket(setup, bloomType, render, validityChecker, worldContext);
BLOOM_RENDER_LOCK.lock();
try {
SCHEDULED_BLOOM_RENDERS.add(ticket);
} finally {
BLOOM_RENDER_LOCK.unlock();
}
return ticket;
}

/**
* Invalidate tickets associated with given world.
*
* @param world World
*/
public static void invalidateWorldTickets(@NotNull World world) {
Objects.requireNonNull(world, "world == null");
BLOOM_RENDER_LOCK.lock();
try {
for (BloomRenderTicket ticket : SCHEDULED_BLOOM_RENDERS) {
if (ticket.isValid() && ticket.worldContext != null && ticket.worldContext.get() == world) {
ticket.invalidate();
}
}

for (Map.Entry<BloomRenderKey, List<BloomRenderTicket>> e : BLOOM_RENDERS.entrySet()) {
for (BloomRenderTicket ticket : e.getValue()) {
if (ticket.isValid() && ticket.worldContext != null && ticket.worldContext.get() == world) {
ticket.invalidate();
}
}
}
} finally {
BLOOM_RENDER_LOCK.unlock();
}
}

/**
* @deprecated use ticket-based bloom render hooks
*/
Expand Down Expand Up @@ -281,14 +368,26 @@ public static int renderBloomBlockLayer(RenderGlobal renderGlobal,
BlockRenderLayer blockRenderLayer, // 70% sure it's translucent uh yeah
double partialTicks,
int pass,
Entity entity) {
Minecraft mc = Minecraft.getMinecraft();
mc.profiler.endStartSection("BTLayer");
@NotNull Entity entity) {
Minecraft.getMinecraft().profiler.endStartSection("BTLayer");

if (Mods.Optifine.isModLoaded()) {
return renderGlobal.renderBlockLayer(blockRenderLayer, partialTicks, pass, entity);
}

BLOOM_RENDER_LOCK.lock();
try {
return renderBloomInternal(renderGlobal, blockRenderLayer, partialTicks, pass, entity);
} finally {
BLOOM_RENDER_LOCK.unlock();
}
}

private static int renderBloomInternal(RenderGlobal renderGlobal,
BlockRenderLayer blockRenderLayer,
double partialTicks,
int pass,
@NotNull Entity entity) {
preDraw();

EffectRenderContext context = EffectRenderContext.getInstance().update(entity, (float) partialTicks);
Expand All @@ -309,7 +408,7 @@ public static int renderBloomBlockLayer(RenderGlobal renderGlobal,
return renderGlobal.renderBlockLayer(blockRenderLayer, partialTicks, pass, entity);
}

Framebuffer fbo = mc.getFramebuffer();
Framebuffer fbo = Minecraft.getMinecraft().getFramebuffer();

if (bloomFBO == null ||
bloomFBO.framebufferWidth != fbo.framebufferWidth ||
Expand Down Expand Up @@ -360,12 +459,12 @@ public static int renderBloomBlockLayer(RenderGlobal renderGlobal,
// reset transparent layer render state and render
OpenGlHelper.glBindFramebuffer(OpenGlHelper.GL_FRAMEBUFFER, fbo.framebufferObject);
GlStateManager.enableBlend();
mc.getTextureManager().bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
Minecraft.getMinecraft().getTextureManager().bindTexture(TextureMap.LOCATION_BLOCKS_TEXTURE);
GlStateManager.shadeModel(GL11.GL_SMOOTH);

int result = renderGlobal.renderBlockLayer(blockRenderLayer, partialTicks, pass, entity);

mc.profiler.endStartSection("bloom");
Minecraft.getMinecraft().profiler.endStartSection("bloom");

// blend bloom + transparent
fbo.bindFramebufferTexture();
Expand Down Expand Up @@ -492,29 +591,44 @@ private record BloomRenderKey(@Nullable IRenderSetup renderSetup, @NotNull Bloom

public static final class BloomRenderTicket {

public static final BloomRenderTicket INVALID = new BloomRenderTicket();

@Nullable
private final IRenderSetup renderSetup;
private final BloomType bloomType;
private final IBloomEffect render;
@Nullable
private final Predicate<BloomRenderTicket> validityChecker;
@Nullable
private final Supplier<World> worldContext;

private boolean invalidated;

BloomRenderTicket() {
this(null, BloomType.DISABLED, (b, c) -> {}, null, null);
this.invalidated = true;
}

BloomRenderTicket(@Nullable IRenderSetup renderSetup, @NotNull BloomType bloomType,
@NotNull IBloomEffect render, @Nullable Predicate<BloomRenderTicket> validityChecker) {
@NotNull IBloomEffect render, @Nullable Predicate<BloomRenderTicket> validityChecker,
@Nullable Supplier<World> worldContext) {
this.renderSetup = renderSetup;
this.bloomType = Objects.requireNonNull(bloomType, "bloomType == null");
this.render = Objects.requireNonNull(render, "render == null");
this.validityChecker = validityChecker;
this.worldContext = worldContext;
}

@Nullable
@Deprecated
@ApiStatus.ScheduledForRemoval(inVersion = "2.9")
public IRenderSetup getRenderSetup() {
return this.renderSetup;
}

@NotNull
@Deprecated
@ApiStatus.ScheduledForRemoval(inVersion = "2.9")
public BloomType getBloomType() {
return this.bloomType;
}
Expand Down
16 changes: 16 additions & 0 deletions src/main/java/gregtech/client/utils/EffectRenderContext.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package gregtech.client.utils;

import net.minecraft.client.renderer.ActiveRenderInfo;
import net.minecraft.client.renderer.culling.ClippingHelperImpl;
import net.minecraft.client.renderer.culling.Frustum;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.Vec3d;

Expand All @@ -20,6 +22,9 @@ public static EffectRenderContext getInstance() {
return instance;
}

private final ClippingHelperImpl clippingHelper = new ClippingHelperImpl();
private final Frustum camera = new Frustum(this.clippingHelper);

@Nullable
private Entity renderViewEntity;
private float partialTicks;
Expand Down Expand Up @@ -53,6 +58,9 @@ public EffectRenderContext update(@NotNull Entity renderViewEntity, float partia
this.rotationXY = ActiveRenderInfo.getRotationXY();
this.rotationXZ = ActiveRenderInfo.getRotationXZ();

this.clippingHelper.init();
this.camera.setPosition(this.cameraX, this.cameraY, this.cameraZ);

return this;
}

Expand Down Expand Up @@ -134,4 +142,12 @@ public float rotationXY() {
public float rotationXZ() {
return rotationXZ;
}

/**
* @return camera
*/
@NotNull
public Frustum camera() {
return camera;
}
}
Loading

0 comments on commit d006d60

Please sign in to comment.