diff --git a/src/main/java/com/fusionflux/portalcubed/client/render/portal/FramebufferRenderer.java b/src/main/java/com/fusionflux/portalcubed/client/render/portal/FramebufferRenderer.java new file mode 100644 index 00000000..679b2b7e --- /dev/null +++ b/src/main/java/com/fusionflux/portalcubed/client/render/portal/FramebufferRenderer.java @@ -0,0 +1,71 @@ +package com.fusionflux.portalcubed.client.render.portal; + +import com.fusionflux.portalcubed.entity.ExperimentalPortal; +import com.fusionflux.portalcubed.mixin.client.MinecraftAccessor; +import com.mojang.blaze3d.pipeline.RenderTarget; +import com.mojang.blaze3d.pipeline.TextureTarget; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.vertex.PoseStack; +import net.minecraft.client.Minecraft; + +import java.util.ArrayDeque; +import java.util.Queue; + +import static com.mojang.blaze3d.platform.GlConst.GL_COLOR_BUFFER_BIT; +import static com.mojang.blaze3d.platform.GlConst.GL_DEPTH_BUFFER_BIT; + +public class FramebufferRenderer extends PortalRenderer { + // Nice setup, fastutil (IntArrayFIFOQueue isn't a priority queue) + private static final Queue FREE_TARGETS = new ArrayDeque<>(); + + private int portalLayer = 0; + + private static RenderTarget getRenderTarget(int width, int height) { + final RenderTarget target = FREE_TARGETS.poll(); + if (target == null) { + return new TextureTarget(width, height, true, Minecraft.ON_OSX); + } + if (target.width != width || target.height != height) { + target.resize(width, height, Minecraft.ON_OSX); + } + return target; + } + + private static void freeRenderTarget(RenderTarget target) { + if (!FREE_TARGETS.offer(target)) { + target.destroyBuffers(); + } + } + + @Override + public boolean enabled(ExperimentalPortal portal) { + return portalLayer < MAX_PORTAL_LAYER && portal.getActive(); + } + + @Override + public void preRender(ExperimentalPortal portal, float tickDelta, PoseStack poseStack) { + } + + @Override + public void postRender(ExperimentalPortal portal, float tickDelta, PoseStack poseStack) { + final Minecraft minecraft = Minecraft.getInstance(); + final RenderTarget oldTarget = minecraft.getMainRenderTarget(); + final RenderTarget newTarget = getRenderTarget(oldTarget.width, oldTarget.height); + + ((MinecraftAccessor)minecraft).setMainRenderTarget(newTarget); + newTarget.bindWrite(true); + + GlStateManager._clearColor(1, 0, 1, 1); + GlStateManager._clearDepth(1); + GlStateManager._clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT, Minecraft.ON_OSX); + + portalLayer++; + renderWorld(portal, tickDelta, poseStack); + portalLayer--; + + ((MinecraftAccessor)minecraft).setMainRenderTarget(oldTarget); + oldTarget.bindWrite(true); + + freeRenderTarget(newTarget); + } +} diff --git a/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRenderers.java b/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRenderers.java index e92d8e5b..2d297e3e 100644 --- a/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRenderers.java +++ b/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRenderers.java @@ -5,7 +5,7 @@ public enum PortalRenderers { DISABLED(DisabledRenderer::new), STENCIL(StencilRenderer::new), - FRAMEBUFFER(DisabledRenderer::new); + FRAMEBUFFER(FramebufferRenderer::new); public final Supplier creator; diff --git a/src/main/java/com/fusionflux/portalcubed/mixin/client/MinecraftAccessor.java b/src/main/java/com/fusionflux/portalcubed/mixin/client/MinecraftAccessor.java new file mode 100644 index 00000000..5fd66458 --- /dev/null +++ b/src/main/java/com/fusionflux/portalcubed/mixin/client/MinecraftAccessor.java @@ -0,0 +1,14 @@ +package com.fusionflux.portalcubed.mixin.client; + +import com.mojang.blaze3d.pipeline.RenderTarget; +import net.minecraft.client.Minecraft; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.gen.Accessor; + +@Mixin(Minecraft.class) +public interface MinecraftAccessor { + @Mutable + @Accessor("mainRenderTarget") + void setMainRenderTarget(RenderTarget target); +} diff --git a/src/main/resources/assets/portalcubed/lang/en_us.json b/src/main/resources/assets/portalcubed/lang/en_us.json index eb15be09..a5171f50 100644 --- a/src/main/resources/assets/portalcubed/lang/en_us.json +++ b/src/main/resources/assets/portalcubed/lang/en_us.json @@ -327,10 +327,10 @@ "portalcubed.midnightconfig.enum.TitleScreenMode.P1": "Portal 1", "portalcubed.midnightconfig.enum.TitleScreenMode.P2": "Portal 2", "portalcubed.midnightconfig.staticPortalItemDrops": "Static Portal Item Drops", - "portalcubed.midnightconfig.renderer": "Portal Renderer", + "portalcubed.midnightconfig.renderer": "Portal Renderer (in development)", "portalcubed.midnightconfig.enum.PortalRenderers.DISABLED": "Disabled", - "portalcubed.midnightconfig.enum.PortalRenderers.STENCIL": "Stencil \u00a7c(BROKEN)\u00a7r", - "portalcubed.midnightconfig.enum.PortalRenderers.FRAMEBUFFER": "Framebuffer \u00a7c(NOT IMPLEMENTED)\u00a7r", + "portalcubed.midnightconfig.enum.PortalRenderers.STENCIL": "Stencil", + "portalcubed.midnightconfig.enum.PortalRenderers.FRAMEBUFFER": "Framebuffer", "death.attack.portalcubed.acid": "%s was dissolved in toxic goo", "death.attack.portalcubed.fizzle": "%s got fizzled", diff --git a/src/main/resources/portalcubed.mixins.json b/src/main/resources/portalcubed.mixins.json index 709f40e3..123698d3 100644 --- a/src/main/resources/portalcubed.mixins.json +++ b/src/main/resources/portalcubed.mixins.json @@ -34,6 +34,7 @@ "client.KeyboardInputMixin", "client.KeyMappingAccessor", "client.LocalPlayerMixin", + "client.MinecraftAccessor", "client.MinecraftMixin", "client.ModelBakeryMixin", "client.MouseHandlerMixin",