diff --git a/src/main/java/com/fusionflux/portalcubed/PortalCubedConfig.java b/src/main/java/com/fusionflux/portalcubed/PortalCubedConfig.java index 8ec64838..e5c16748 100644 --- a/src/main/java/com/fusionflux/portalcubed/PortalCubedConfig.java +++ b/src/main/java/com/fusionflux/portalcubed/PortalCubedConfig.java @@ -1,6 +1,5 @@ package com.fusionflux.portalcubed; -import com.fusionflux.portalcubed.client.render.portal.PortalRenderers; import eu.midnightdust.lib.config.MidnightConfig; @SuppressWarnings("CanBeFinal") @@ -16,7 +15,7 @@ public class PortalCubedConfig extends MidnightConfig { @Entry @Client public static boolean portalHudMode = false; @Entry(min = 0, max = 100, isSlider = true) @Client public static int gelOverlayOpacity = 100; @Entry @Client public static boolean staticPortalItemDrops = true; - @Entry @Client public static PortalRenderers renderer = PortalRenderers.DISABLED; + @Entry(min = 0, max = 4, isSlider = true) @Client public static int portalRenderingLayers = 1; @Entry @Client public static boolean crossPortalEntityRendering = true; @Entry(min = 0, max = 1000, isSlider = true) @Client public static int portalSmoothTime = 250; } diff --git a/src/main/java/com/fusionflux/portalcubed/accessor/LevelRendererExt.java b/src/main/java/com/fusionflux/portalcubed/accessor/LevelRendererExt.java deleted file mode 100644 index f45976a8..00000000 --- a/src/main/java/com/fusionflux/portalcubed/accessor/LevelRendererExt.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.fusionflux.portalcubed.accessor; - -import net.minecraft.client.renderer.RenderBuffers; -import net.minecraft.client.renderer.culling.Frustum; -import org.quiltmc.loader.api.minecraft.ClientOnly; - -@ClientOnly -public interface LevelRendererExt { - Frustum getCullingFrustum(); - - void setCullingFrustum(Frustum frustum); - - RenderBuffers getRenderBuffers(); - - void setRenderBuffers(RenderBuffers buffers); -} diff --git a/src/main/java/com/fusionflux/portalcubed/accessor/RenderTargetExt.java b/src/main/java/com/fusionflux/portalcubed/accessor/RenderTargetExt.java deleted file mode 100644 index 6abc4c6c..00000000 --- a/src/main/java/com/fusionflux/portalcubed/accessor/RenderTargetExt.java +++ /dev/null @@ -1,7 +0,0 @@ -package com.fusionflux.portalcubed.accessor; - -public interface RenderTargetExt { - boolean isStencilBufferEnabled(); - - void setStencilBufferEnabled(boolean enabled); -} diff --git a/src/main/java/com/fusionflux/portalcubed/client/PortalCubedClient.java b/src/main/java/com/fusionflux/portalcubed/client/PortalCubedClient.java index 6c5334aa..dead4522 100644 --- a/src/main/java/com/fusionflux/portalcubed/client/PortalCubedClient.java +++ b/src/main/java/com/fusionflux/portalcubed/client/PortalCubedClient.java @@ -19,8 +19,7 @@ import com.fusionflux.portalcubed.client.render.entity.animatedtextures.AnimatedEntityTextures; import com.fusionflux.portalcubed.client.render.entity.model.*; import com.fusionflux.portalcubed.client.render.portal.PortalRenderPhase; -import com.fusionflux.portalcubed.client.render.portal.PortalRendererImpl; -import com.fusionflux.portalcubed.client.render.portal.PortalRenderers; +import com.fusionflux.portalcubed.client.render.portal.PortalRendering; import com.fusionflux.portalcubed.entity.Portal; import com.fusionflux.portalcubed.entity.PortalCubedEntities; import com.fusionflux.portalcubed.fluids.PortalCubedFluids; @@ -75,7 +74,6 @@ import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; import org.apache.commons.lang3.mutable.MutableDouble; -import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; import org.joml.Quaternionf; @@ -136,9 +134,6 @@ public class PortalCubedClient implements ClientModInitializer { public static int gelOverlayTimer = -1; public static ResourceLocation gelOverlayTexture = TextureManager.INTENTIONAL_MISSING_TEXTURE; - private static PortalRendererImpl renderer; - private static PortalRenderers rendererType; - public static IPQuaternion cameraInterpStart; public static long cameraInterpStartTime; @@ -320,6 +315,7 @@ Items.LIGHT, new ResourceLocation("level") RenderSystem.depthFunc(GL11.GL_LEQUAL); RenderSystem.enableCull(); }); + PortalRendering.init(); PortalBlocksLoader.initClient(); @@ -804,15 +800,6 @@ public static int globalAdvancementsSize() { return GLOBAL_ADVANCEMENTS.size(); } - @NotNull - public static PortalRendererImpl getRenderer() { - if (rendererType != PortalCubedConfig.renderer) { - rendererType = PortalCubedConfig.renderer; - renderer = rendererType.creator.get(); - } - return renderer; - } - public static Optional interpCamera() { final long time = System.currentTimeMillis(); final long endTime = PortalCubedClient.cameraInterpStartTime + PortalCubedConfig.portalSmoothTime; diff --git a/src/main/java/com/fusionflux/portalcubed/client/render/entity/PortalRenderer.java b/src/main/java/com/fusionflux/portalcubed/client/render/entity/PortalRenderer.java index e1cb1179..db8f1a76 100644 --- a/src/main/java/com/fusionflux/portalcubed/client/render/entity/PortalRenderer.java +++ b/src/main/java/com/fusionflux/portalcubed/client/render/entity/PortalRenderer.java @@ -5,7 +5,6 @@ import com.fusionflux.portalcubed.client.PortalCubedClient; import com.fusionflux.portalcubed.client.render.entity.model.PortalModel; import com.fusionflux.portalcubed.client.render.portal.PortalRenderPhase; -import com.fusionflux.portalcubed.client.render.portal.PortalRendererImpl; import com.fusionflux.portalcubed.entity.Portal; import com.fusionflux.portalcubed.util.GeneralUtil; import com.mojang.blaze3d.vertex.PoseStack; @@ -69,7 +68,7 @@ public void render(@NotNull Portal entity, float yaw, float tickDelta, @NotNull matrices.scale(progress, progress, progress); } - renderPortal(matrices, vertexConsumers, entity, light, r, g, b, tickDelta); + model.renderToBuffer(matrices, vertexConsumers.getBuffer(RenderType.entityTranslucentEmissive(getTextureLocation(entity))), light, OverlayTexture.NO_OVERLAY, r, g, b, 1F); matrices.popPose(); @@ -101,27 +100,6 @@ public void render(@NotNull Portal entity, float yaw, float tickDelta, @NotNull } } - public void renderPortal( - PoseStack poseStack, - MultiBufferSource vertexConsumers, - Portal entity, - int light, - int r, - int g, - int b, - float tickDelta - ) { - final PortalRendererImpl renderer = PortalCubedClient.getRenderer(); - final boolean renderContents = renderPhase == renderer.targetPhase() && renderer.enabled(entity); - if (renderContents) { - renderer.preRender(entity, tickDelta, poseStack, vertexConsumers); - } - model.renderToBuffer(poseStack, vertexConsumers.getBuffer(RenderType.entityTranslucentEmissive(getTextureLocation(entity))), light, OverlayTexture.NO_OVERLAY, r, g, b, 1F); - if (renderContents) { - renderer.postRender(entity, tickDelta, poseStack, vertexConsumers); - } - } - private void renderOtherEntities(Portal entity, PoseStack poseStack, float tickDelta, MultiBufferSource buffer, int packedLight) { if (renderPhase != PortalRenderPhase.ENTITY || !entity.getActive()) return; final UUID otherUuid = entity.getLinkedPortalUUID().orElse(null); diff --git a/src/main/java/com/fusionflux/portalcubed/client/render/portal/DisabledRenderer.java b/src/main/java/com/fusionflux/portalcubed/client/render/portal/DisabledRenderer.java deleted file mode 100644 index b61b0b10..00000000 --- a/src/main/java/com/fusionflux/portalcubed/client/render/portal/DisabledRenderer.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.fusionflux.portalcubed.client.render.portal; - -import com.fusionflux.portalcubed.entity.Portal; -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.renderer.MultiBufferSource; - -public class DisabledRenderer extends PortalRendererImpl { - @Override - public boolean enabled(Portal portal) { - return false; - } - - @Override - public void preRender(Portal portal, float tickDelta, PoseStack poseStack, MultiBufferSource bufferSource) { - } - - @Override - public void postRender(Portal portal, float tickDelta, PoseStack poseStack, MultiBufferSource bufferSource) { - } - - @Override - public PortalRenderPhase targetPhase() { - return PortalRenderPhase.ENTITY; - } -} 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 deleted file mode 100644 index 02d3440c..00000000 --- a/src/main/java/com/fusionflux/portalcubed/client/render/portal/FramebufferRenderer.java +++ /dev/null @@ -1,92 +0,0 @@ -package com.fusionflux.portalcubed.client.render.portal; - -import com.fusionflux.portalcubed.entity.Portal; -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.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; - -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; -import static org.lwjgl.opengl.GL11.*; - -public class FramebufferRenderer extends PortalRendererImpl { - private static final Queue FREE_TARGETS = new ArrayDeque<>(); - - private final PortalRendererImpl stencilRenderer = new StencilRenderer(); - 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(Portal portal) { - return portalLayer < MAX_PORTAL_LAYER && portal.getActive(); - } - - @Override - public void preRender(Portal portal, float tickDelta, PoseStack poseStack, MultiBufferSource bufferSource) { - stencilRenderer.preRender(portal, tickDelta, poseStack, bufferSource); - } - - @Override - public void postRender(Portal portal, float tickDelta, PoseStack poseStack, MultiBufferSource bufferSource) { - ((MultiBufferSource.BufferSource)bufferSource).endBatch(); - RenderSystem.colorMask(true, true, true, true); - RenderSystem.depthMask(true); - RenderSystem.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - RenderSystem.stencilFunc(GL_ALWAYS, 0, 0xff); - glDisable(GL_STENCIL_TEST); - - 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); - portalLayer--; - - ((MinecraftAccessor)minecraft).setMainRenderTarget(oldTarget); - oldTarget.bindWrite(true); - - glEnable(GL_STENCIL_TEST); - RenderSystem.stencilFunc(GL_LEQUAL, portalLayer + 1, 0xff); - newTarget.blitToScreen(oldTarget.width, oldTarget.height, false); - glDisable(GL_STENCIL_TEST); - - freeRenderTarget(newTarget); - } - - @Override - public PortalRenderPhase targetPhase() { - return PortalRenderPhase.FINAL; - } -} diff --git a/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRenderPhase.java b/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRenderPhase.java index 6c666ef0..be2d4f43 100644 --- a/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRenderPhase.java +++ b/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRenderPhase.java @@ -1,5 +1,5 @@ package com.fusionflux.portalcubed.client.render.portal; public enum PortalRenderPhase { - ENTITY, TRACER, FINAL + ENTITY, TRACER } diff --git a/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRenderTarget.java b/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRenderTarget.java new file mode 100644 index 00000000..0a7df439 --- /dev/null +++ b/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRenderTarget.java @@ -0,0 +1,14 @@ +package com.fusionflux.portalcubed.client.render.portal; + +import com.mojang.blaze3d.pipeline.TextureTarget; + +import net.minecraft.client.Minecraft; + +/** + * Stencil code is in {@link com.fusionflux.portalcubed.mixin.client.RenderTargetMixin} +*/ +public final class PortalRenderTarget extends TextureTarget { + PortalRenderTarget(int width, int height) { + super(width, height, true, Minecraft.ON_OSX); + } +} diff --git a/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRendererImpl.java b/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRendererImpl.java deleted file mode 100644 index c9909e77..00000000 --- a/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRendererImpl.java +++ /dev/null @@ -1,120 +0,0 @@ -package com.fusionflux.portalcubed.client.render.portal; - -import com.fusionflux.portalcubed.accessor.GameRendererExt; -import com.fusionflux.portalcubed.accessor.LevelRendererExt; -import com.fusionflux.portalcubed.accessor.MinecraftExt; -import com.fusionflux.portalcubed.client.PortalCubedClient; -import com.fusionflux.portalcubed.client.render.entity.PortalRenderer; -import com.fusionflux.portalcubed.entity.Portal; -import com.mojang.blaze3d.vertex.PoseStack; -import net.fabricmc.fabric.impl.client.rendering.WorldRenderContextImpl; -import net.minecraft.Util; -import net.minecraft.client.Camera; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; -import net.minecraft.client.renderer.RenderBuffers; -import net.minecraft.client.renderer.culling.Frustum; - -import java.util.ArrayDeque; -import java.util.Deque; - -@SuppressWarnings("UnstableApiUsage") -public abstract class PortalRendererImpl { - private static final Deque RENDER_BUFFERS_POOL = new ArrayDeque<>(4); - private static int buffersPoolCount = 0; - - protected static final int MAX_PORTAL_LAYER = 1; // No recursive rendering yet - - public abstract boolean enabled(Portal portal); - - public abstract void preRender(Portal portal, float tickDelta, PoseStack poseStack, MultiBufferSource bufferSource); - - public abstract void postRender(Portal portal, float tickDelta, PoseStack poseStack, MultiBufferSource bufferSource); - - public abstract PortalRenderPhase targetPhase(); - - protected void renderWorld(Portal portal, float tickDelta) { - final Minecraft minecraft = Minecraft.getInstance(); - minecraft.getProfiler().push("pc_portal_render"); - - final WorldRenderContextImpl contextObj = (WorldRenderContextImpl)PortalCubedClient.worldRenderContext; - - final Camera oldCamera = minecraft.gameRenderer.getMainCamera(); - final Frustum oldFrustum = ((LevelRendererExt)minecraft.levelRenderer).getCullingFrustum(); - final RenderBuffers oldRenderBuffers = ((LevelRendererExt)minecraft.levelRenderer).getRenderBuffers(); - final RenderBuffers oldGlobalBuffers = minecraft.renderBuffers(); - final WorldRenderContextImpl oldRenderContext = copyWorldRenderContext(contextObj, new WorldRenderContextImpl()); - - final Camera newCamera = new Camera(); - - final RenderBuffers newRenderBuffers = newRenderBuffers(); - if (newRenderBuffers != null) { - ((LevelRendererExt)minecraft.levelRenderer).setRenderBuffers(newRenderBuffers); - ((MinecraftExt)minecraft).setRenderBuffers(newRenderBuffers); - } - - ((GameRendererExt)minecraft.gameRenderer).setMainCamera(newCamera); - - final PortalRenderPhase phase = PortalRenderer.renderPhase; - PortalRenderer.renderPhase = PortalRenderPhase.ENTITY; - minecraft.gameRenderer.renderLevel(tickDelta, Util.getNanos(), new PoseStack()); - PortalRenderer.renderPhase = phase; - - ((GameRendererExt)minecraft.gameRenderer).setMainCamera(oldCamera); - ((LevelRendererExt)minecraft.levelRenderer).setCullingFrustum(oldFrustum); - ((LevelRendererExt)minecraft.levelRenderer).setRenderBuffers(oldRenderBuffers); - ((MinecraftExt)minecraft).setRenderBuffers(oldGlobalBuffers); - copyWorldRenderContext(oldRenderContext, contextObj); - - if (newRenderBuffers != null) { - freeRenderBuffers(newRenderBuffers); - } - - minecraft.getProfiler().pop(); - } - - private static RenderBuffers newRenderBuffers() { - if (buffersPoolCount >= 2) { - return null; - } - buffersPoolCount--; - if (RENDER_BUFFERS_POOL.isEmpty()) { - return new RenderBuffers(); - } - return RENDER_BUFFERS_POOL.pop(); - } - - private static void freeRenderBuffers(RenderBuffers buffers) { - buffersPoolCount++; - RENDER_BUFFERS_POOL.add(buffers); - } - - private static WorldRenderContextImpl copyWorldRenderContext(WorldRenderContextImpl from, WorldRenderContextImpl to) { - to.prepare( - from.worldRenderer(), - from.matrixStack(), - from.tickDelta(), - from.limitTime(), - from.blockOutlines(), - from.camera(), - from.gameRenderer(), - from.lightmapTextureManager(), - from.projectionMatrix(), - from.consumers(), - from.profiler(), - from.advancedTranslucency(), - from.world() - ); - to.setFrustum(from.frustum()); - to.prepareBlockOutline( - from.entity(), - from.cameraX(), - from.cameraY(), - from.cameraZ(), - from.blockPos(), - from.blockState() - ); - to.renderBlockOutline = from.renderBlockOutline; - return to; - } -} 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 deleted file mode 100644 index 8440a184..00000000 --- a/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRenderers.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.fusionflux.portalcubed.client.render.portal; - -import java.util.function.Supplier; - -@SuppressWarnings("Convert2MethodRef") // Using a lambda makes the classes be loaded more lazily, preventing crashes on the dedicated server -public enum PortalRenderers { - DISABLED(() -> new DisabledRenderer()), - STENCIL(() -> new StencilRenderer()), - FRAMEBUFFER(() -> new FramebufferRenderer()); - - public final Supplier creator; - - PortalRenderers(Supplier creator) { - this.creator = creator; - } -} diff --git a/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRendering.java b/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRendering.java new file mode 100644 index 00000000..c2a88d0e --- /dev/null +++ b/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalRendering.java @@ -0,0 +1,167 @@ +package com.fusionflux.portalcubed.client.render.portal; + +import org.joml.Matrix4f; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL32; + +import com.fusionflux.portalcubed.PortalCubed; +import com.fusionflux.portalcubed.PortalCubedConfig; +import com.fusionflux.portalcubed.entity.Portal; +import com.fusionflux.portalcubed.mixin.client.LevelRendererAccessor; +import com.fusionflux.portalcubed.mixin.client.MinecraftAccessor; +import com.mojang.blaze3d.pipeline.RenderTarget; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferUploader; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexFormat; +import com.mojang.math.Axis; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.fabricmc.fabric.api.client.rendering.v1.CoreShaderRegistrationCallback; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.minecraft.Util; +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.GameRenderer; +import net.minecraft.client.renderer.ShaderInstance; +import net.minecraft.client.renderer.culling.Frustum; +import net.minecraft.world.entity.Entity; + +public final class PortalRendering { + private PortalRendering() { } + + private static ShaderInstance blitShader; + private static RenderTarget PORTAL_TARGET = null; + private static final Matrix4f IDENTITY_MATRIX = new Matrix4f().identity(); + + private static int layer = 0; + + private static RenderTarget createPortalTarget(int width, int height) { + if (PORTAL_TARGET == null) PORTAL_TARGET = new PortalRenderTarget(width, height); + if (PORTAL_TARGET.width != width || PORTAL_TARGET.height != height) PORTAL_TARGET.resize(width, height, Minecraft.ON_OSX); + return PORTAL_TARGET; + } + + public static boolean isRendering() { + return layer != 0; + } + + public static RenderTarget portalTarget() { + return PORTAL_TARGET; + } + + public static void renderScreenTriangle(int r, int g, int b) { + final var shader = GameRenderer.getPositionColorShader(); + shader.MODEL_VIEW_MATRIX.set(IDENTITY_MATRIX); + shader.PROJECTION_MATRIX.set(IDENTITY_MATRIX); + shader.apply(); + + final var tessellator = RenderSystem.renderThreadTesselator(); + final var bufferBuilder = tessellator.getBuilder(); + + bufferBuilder.begin(VertexFormat.Mode.TRIANGLES, DefaultVertexFormat.POSITION_COLOR); + + bufferBuilder.vertex(-1, -1, 0).color(r, g, b, 255).endVertex(); + bufferBuilder.vertex(-1, 3, 0).color(r, g, b, 255).endVertex(); + bufferBuilder.vertex(3, -1, 0).color(r, g, b, 255).endVertex(); + + BufferUploader.draw(bufferBuilder.end()); + shader.clear(); + } + + private static void renderPortal(WorldRenderContext ctx, Portal portal) { + final var mainTarget = Minecraft.getInstance().getMainRenderTarget(); + final var portalTarget = createPortalTarget(mainTarget.width, mainTarget.height); + mainTarget.unbindWrite(); + portalTarget.bindWrite(false); + RenderSystem.clear(GL11.GL_DEPTH_BUFFER_BIT | GL11.GL_COLOR_BUFFER_BIT | GL11.GL_STENCIL_BUFFER_BIT, Minecraft.ON_OSX); + { + GL11.glEnable(GL11.GL_STENCIL_TEST); + GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 0xFF); + GL11.glStencilOp(GL11.GL_KEEP, GL11.GL_KEEP, GL11.GL_REPLACE); + GL11.glStencilMask(0xFF); + RenderSystem.colorMask(false, false, false, false); + RenderSystem.depthMask(false); + + RenderSystem.enableDepthTest(); + RenderSystem.depthFunc(GL11.GL_LEQUAL); + + PortalStencil.render(portal, ctx.matrixStack(), ctx.projectionMatrix(), GameRenderer.getPositionShader()); + + GL11.glStencilFunc(GL11.GL_EQUAL, 1, 0xFF); + GL11.glStencilMask(0x00); + RenderSystem.colorMask(true, true, true, true); + } + RenderSystem.enableCull(); + ((MinecraftAccessor) Minecraft.getInstance()).setMainRenderTarget(portalTarget); + + final var oldFrustum = ((LevelRendererAccessor) ctx.worldRenderer()).portalcubed$getCullingFrustum(); + // TODO: Fix this + ((LevelRendererAccessor) ctx.worldRenderer()).portalcubed$setCullingFrustum(new Frustum(IDENTITY_MATRIX, IDENTITY_MATRIX)); + final var oldRenderChunksInFrustum = ((LevelRendererAccessor) ctx.worldRenderer()).portalcubed$getRenderChunksInFrustum(); + ((LevelRendererAccessor) ctx.worldRenderer()).portalcubed$setCapturedFrustum(null); + + ctx.gameRenderer().setRenderHand(false); + + VirtualPortalCamera.setup(portal, ctx.tickDelta()); + { + final var oldProjectionMatrix = RenderSystem.getProjectionMatrix(); + layer++; + RenderSystem.disableDepthTest(); + ((LevelRendererAccessor) ctx.worldRenderer()).portalcubed$setRenderChunksInFrustum(new ObjectArrayList<>()); + // TODO: Pose stack is leaking????? + ctx.gameRenderer().renderLevel(ctx.tickDelta(), Util.getNanos(), new PoseStack()); + RenderSystem.enableDepthTest(); + layer--; + ctx.gameRenderer().resetProjectionMatrix(oldProjectionMatrix); + } + VirtualPortalCamera.reset(); + + { + GL11.glDisable(GL11.GL_STENCIL_TEST); + GL11.glStencilFunc(GL11.GL_ALWAYS, 1, 0xFF); + GL11.glStencilMask(0xFF); + } + + ((LevelRendererAccessor) ctx.worldRenderer()).portalcubed$setCullingFrustum(oldFrustum); + ((LevelRendererAccessor) ctx.worldRenderer()).portalcubed$setRenderChunksInFrustum(oldRenderChunksInFrustum); + + portalTarget.unbindWrite(); + mainTarget.bindWrite(false); + ((MinecraftAccessor) Minecraft.getInstance()).setMainRenderTarget(mainTarget); + GL11.glDisable(GL32.GL_DEPTH_CLAMP); + RenderSystem.disableCull(); + + blitShader.SCREEN_SIZE.set((float) portalTarget.width, (float) portalTarget.height); + blitShader.setSampler("Sampler0", portalTarget.getColorTextureId()); + PortalStencil.render(portal, ctx.matrixStack(), ctx.projectionMatrix(), blitShader); + } + + public static void init() { + // TODO: DO NOT FORGET TO REMOVE + System.loadLibrary("renderdoc"); + CoreShaderRegistrationCallback.EVENT.register(ctx -> ctx.register(PortalCubed.id("portal_blit"), DefaultVertexFormat.POSITION, shader -> blitShader = shader)); + WorldRenderEvents.END.register(ctx -> { + if (PortalCubedConfig.portalRenderingLayers < 1) return; + if (layer >= PortalCubedConfig.portalRenderingLayers) return; + + final var poseStack = ctx.matrixStack(); + + poseStack.pushPose(); + poseStack.translate(-ctx.camera().getPosition().x, -ctx.camera().getPosition().y, -ctx.camera().getPosition().z); + // TODO: Occlusion Culling? + for (Entity entity : ctx.world().entitiesForRendering()) { + if (entity instanceof Portal portal && portal.getOtherRotation().isPresent() && ctx.frustum().isVisible(portal.getBoundingBoxForCulling())) { + poseStack.pushPose(); + poseStack.translate(portal.getPosition(ctx.tickDelta()).x, portal.getPosition(ctx.tickDelta()).y, portal.getPosition(ctx.tickDelta()).z); + poseStack.mulPose(portal.getRotation().get(ctx.tickDelta())); + poseStack.mulPose(Axis.YP.rotationDegrees(180)); + renderPortal(ctx, portal); + poseStack.popPose(); + } + } + poseStack.popPose(); + }); + } +} diff --git a/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalStencil.java b/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalStencil.java new file mode 100644 index 00000000..035be23b --- /dev/null +++ b/src/main/java/com/fusionflux/portalcubed/client/render/portal/PortalStencil.java @@ -0,0 +1,44 @@ +package com.fusionflux.portalcubed.client.render.portal; + +import org.joml.Matrix4f; +import org.lwjgl.opengl.GL11; +import org.lwjgl.opengl.GL32; + +import com.fusionflux.portalcubed.entity.Portal; +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.BufferUploader; +import com.mojang.blaze3d.vertex.DefaultVertexFormat; +import com.mojang.blaze3d.vertex.PoseStack; +import com.mojang.blaze3d.vertex.VertexFormat; + +import net.minecraft.client.Minecraft; +import net.minecraft.client.renderer.ShaderInstance; + +public final class PortalStencil { + private PortalStencil() { } + + public static void render(Portal portal, PoseStack matrices, Matrix4f projectionMatrix, ShaderInstance shader) { + shader.MODEL_VIEW_MATRIX.set(matrices.last().pose()); + shader.PROJECTION_MATRIX.set(projectionMatrix); + shader.apply(); + + if (portal.getBoundingBox().intersects(Minecraft.getInstance().player.getBoundingBox())) GL11.glEnable(GL32.GL_DEPTH_CLAMP); + + // Build mesh + final var tessellator = RenderSystem.renderThreadTesselator(); + final var bufferBuilder = tessellator.getBuilder(); + + bufferBuilder.begin(VertexFormat.Mode.TRIANGLES, DefaultVertexFormat.POSITION); + + bufferBuilder.vertex(.32, -.82, 0).endVertex(); + bufferBuilder.vertex(.32, .82, 0).endVertex(); + bufferBuilder.vertex(-.32, .82, 0).endVertex(); + + bufferBuilder.vertex(-.32, .82, 0).endVertex(); + bufferBuilder.vertex(-.32, -.82, 0).endVertex(); + bufferBuilder.vertex(.32, -.82, 0).endVertex(); + + BufferUploader.draw(bufferBuilder.end()); + shader.clear(); + } +} diff --git a/src/main/java/com/fusionflux/portalcubed/client/render/portal/StencilRenderer.java b/src/main/java/com/fusionflux/portalcubed/client/render/portal/StencilRenderer.java deleted file mode 100644 index f59ed806..00000000 --- a/src/main/java/com/fusionflux/portalcubed/client/render/portal/StencilRenderer.java +++ /dev/null @@ -1,53 +0,0 @@ -package com.fusionflux.portalcubed.client.render.portal; - -import com.fusionflux.portalcubed.accessor.RenderTargetExt; -import com.fusionflux.portalcubed.entity.Portal; -import com.mojang.blaze3d.systems.RenderSystem; -import com.mojang.blaze3d.vertex.PoseStack; -import net.minecraft.client.Minecraft; -import net.minecraft.client.renderer.MultiBufferSource; - -import static org.lwjgl.opengl.GL11.*; - -public class StencilRenderer extends PortalRendererImpl { - private int portalLayer = 0; - - @Override - public boolean enabled(Portal portal) { - return portalLayer < MAX_PORTAL_LAYER && portal.getActive(); - } - - @Override - public void preRender(Portal portal, float tickDelta, PoseStack poseStack, MultiBufferSource bufferSource) { - ((MultiBufferSource.BufferSource)bufferSource).endBatch(); - // TODO: PortingLib compat - ((RenderTargetExt)Minecraft.getInstance().getMainRenderTarget()).setStencilBufferEnabled(true); - glEnable(GL_STENCIL_TEST); - RenderSystem.clear(GL_STENCIL_BUFFER_BIT, Minecraft.ON_OSX); - RenderSystem.colorMask(false, false, false, false); - RenderSystem.depthMask(false); - RenderSystem.stencilMask(0xff); - RenderSystem.stencilFunc(GL_NEVER, 0, 0xff); - RenderSystem.stencilOp(GL_INCR, GL_KEEP, GL_KEEP); - } - - @Override - public void postRender(Portal portal, float tickDelta, PoseStack poseStack, MultiBufferSource bufferSource) { - ((MultiBufferSource.BufferSource)bufferSource).endBatch(); - RenderSystem.colorMask(true, true, true, true); - RenderSystem.depthMask(true); - RenderSystem.stencilOp(GL_KEEP, GL_KEEP, GL_KEEP); - RenderSystem.stencilFunc(GL_NEVER, 123, 0xff); - - portalLayer++; - renderWorld(portal, tickDelta); - portalLayer--; - - glDisable(GL_STENCIL_TEST); - } - - @Override - public PortalRenderPhase targetPhase() { - return PortalRenderPhase.FINAL; - } -} diff --git a/src/main/java/com/fusionflux/portalcubed/client/render/portal/VirtualPortalCamera.java b/src/main/java/com/fusionflux/portalcubed/client/render/portal/VirtualPortalCamera.java new file mode 100644 index 00000000..ecde7ef5 --- /dev/null +++ b/src/main/java/com/fusionflux/portalcubed/client/render/portal/VirtualPortalCamera.java @@ -0,0 +1,53 @@ +package com.fusionflux.portalcubed.client.render.portal; + +import org.joml.Vector3f; + +import com.fusionflux.portalcubed.entity.Portal; +import com.fusionflux.portalcubed.mixin.client.CameraAccessor; +import com.mojang.math.Axis; + +import net.minecraft.client.Minecraft; +import net.minecraft.world.phys.Vec3; + +public final class VirtualPortalCamera { + private static Vec3 beforeUsagePos; + private static Vector3f beforeUsageRotation; + + private VirtualPortalCamera() { } + + private static Vec3 transformedPos(Portal portal) { + // TODO + return beforeUsagePos; + // return beforeUsagePos + // .subtract(portal.getOriginPos()) + // .add( + // portal.getLinkedPortalUUID().map(uuid -> + // ((Portal) ((ClientLevel) ((Portal) portal).level()).getEntities().get(uuid)).getOriginPos()).orElse(Vec3.ZERO)); + } + + private static Vector3f transformedRotation(Portal portal, float tickDelta) { + // TODO: Confirm this works + var relativeRot = portal.getRotation().get(tickDelta).transformInverse(new Vector3f(beforeUsageRotation)); + relativeRot = Axis.YP.rotationDegrees(180).transform(relativeRot); + var outRotation = portal.getOtherRotation(); + return outRotation.isPresent() ? outRotation.get().transform(relativeRot) : beforeUsageRotation; + } + + public static void setup(Portal portal, float tickDelta) { + final var mainCamera = Minecraft.getInstance().gameRenderer.getMainCamera(); + + beforeUsagePos = mainCamera.getPosition(); + beforeUsageRotation = new Vector3f(mainCamera.getYRot(), mainCamera.getXRot(), 0); + + ((CameraAccessor) mainCamera).portalcubed$setPosition(transformedPos(portal)); + final var transformedRotation = transformedRotation(portal, tickDelta); + ((CameraAccessor) mainCamera).portalcubed$setRotation(transformedRotation.x, transformedRotation.y); + } + + public static void reset() { + final var mainCamera = Minecraft.getInstance().gameRenderer.getMainCamera(); + + ((CameraAccessor) mainCamera).portalcubed$setPosition(beforeUsagePos); + ((CameraAccessor) mainCamera).portalcubed$setRotation(beforeUsageRotation.x, beforeUsageRotation.y); + } +} diff --git a/src/main/java/com/fusionflux/portalcubed/mixin/client/CameraAccessor.java b/src/main/java/com/fusionflux/portalcubed/mixin/client/CameraAccessor.java new file mode 100644 index 00000000..8ca3e622 --- /dev/null +++ b/src/main/java/com/fusionflux/portalcubed/mixin/client/CameraAccessor.java @@ -0,0 +1,16 @@ +package com.fusionflux.portalcubed.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.gen.Invoker; + +import net.minecraft.client.Camera; +import net.minecraft.world.phys.Vec3; + +@Mixin(Camera.class) +public interface CameraAccessor { + @Invoker("setPosition") + void portalcubed$setPosition(Vec3 pos); + + @Invoker("setRotation") + void portalcubed$setRotation(float yRot, float xRot); +} diff --git a/src/main/java/com/fusionflux/portalcubed/mixin/client/GlStateManagerMixin.java b/src/main/java/com/fusionflux/portalcubed/mixin/client/GlStateManagerMixin.java new file mode 100644 index 00000000..ce620050 --- /dev/null +++ b/src/main/java/com/fusionflux/portalcubed/mixin/client/GlStateManagerMixin.java @@ -0,0 +1,36 @@ +package com.fusionflux.portalcubed.mixin.client; + +import org.joml.Vector3i; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; + +import com.fusionflux.portalcubed.client.render.portal.PortalRendering; +import com.mojang.blaze3d.platform.GlStateManager; +import com.mojang.blaze3d.systems.RenderSystem; + +@Mixin(GlStateManager.class) +public abstract class GlStateManagerMixin { + private static Vector3i portalcubed$capturedClearColor = new Vector3i(); + + @Inject(method = "_clearColor", at = @At("HEAD"), cancellable = true, remap = false) + private static void portalcubed$captureClearColor(float r, float g, float b, float a, CallbackInfo ci) { + if (PortalRendering.isRendering()) { + RenderSystem.assertOnRenderThreadOrInit(); + portalcubed$capturedClearColor.set((int) (r * 255), (int) (g * 255), (int) (b * 255)); + ci.cancel(); + } + } + + @Inject(method = "_clear", at = @At("HEAD"), cancellable = true, remap = false) + private static void portalcubed$replaceClearingIfRenderingPortal(int mask, boolean checkError, CallbackInfo ci) { + if (PortalRendering.isRendering()) { + RenderSystem.assertOnRenderThreadOrInit(); + GlStateManager._depthMask(false); + PortalRendering.renderScreenTriangle(portalcubed$capturedClearColor.x, portalcubed$capturedClearColor.y, portalcubed$capturedClearColor.z); + GlStateManager._depthMask(true); + ci.cancel(); + } + } +} diff --git a/src/main/java/com/fusionflux/portalcubed/mixin/client/LevelRendererAccessor.java b/src/main/java/com/fusionflux/portalcubed/mixin/client/LevelRendererAccessor.java new file mode 100644 index 00000000..c5cc020d --- /dev/null +++ b/src/main/java/com/fusionflux/portalcubed/mixin/client/LevelRendererAccessor.java @@ -0,0 +1,26 @@ +package com.fusionflux.portalcubed.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.gen.Accessor; + +import it.unimi.dsi.fastutil.objects.ObjectArrayList; +import net.minecraft.client.renderer.LevelRenderer; +import net.minecraft.client.renderer.culling.Frustum; + +@Mixin(LevelRenderer.class) +public interface LevelRendererAccessor { + @Mutable + @Accessor("renderChunksInFrustum") + void portalcubed$setRenderChunksInFrustum(ObjectArrayList renderChunksInFrustum); + @Accessor("renderChunksInFrustum") + ObjectArrayList portalcubed$getRenderChunksInFrustum(); + + @Accessor("cullingFrustum") + Frustum portalcubed$getCullingFrustum(); + @Accessor("cullingFrustum") + void portalcubed$setCullingFrustum(Frustum frustum); + + @Accessor("capturedFrustum") + void portalcubed$setCapturedFrustum(Frustum frustum); +} diff --git a/src/main/java/com/fusionflux/portalcubed/mixin/client/LevelRendererMixin.java b/src/main/java/com/fusionflux/portalcubed/mixin/client/LevelRendererMixin.java index ea76f899..01044b8f 100644 --- a/src/main/java/com/fusionflux/portalcubed/mixin/client/LevelRendererMixin.java +++ b/src/main/java/com/fusionflux/portalcubed/mixin/client/LevelRendererMixin.java @@ -1,42 +1,37 @@ package com.fusionflux.portalcubed.mixin.client; -import com.fusionflux.portalcubed.accessor.LevelRendererExt; import com.fusionflux.portalcubed.client.PortalCubedClient; -import com.fusionflux.portalcubed.client.render.entity.PortalRenderer; -import com.fusionflux.portalcubed.client.render.portal.PortalRenderPhase; -import com.fusionflux.portalcubed.entity.Portal; +import com.fusionflux.portalcubed.client.render.portal.PortalRendering; import com.llamalad7.mixinextras.injector.wrapoperation.Operation; import com.llamalad7.mixinextras.injector.wrapoperation.WrapOperation; import com.mojang.blaze3d.vertex.PoseStack; -import com.mojang.math.Axis; import net.minecraft.client.Camera; import net.minecraft.client.Minecraft; -import net.minecraft.client.multiplayer.ClientLevel; import net.minecraft.client.renderer.*; import net.minecraft.client.renderer.culling.Frustum; -import net.minecraft.client.renderer.entity.EntityRenderDispatcher; -import net.minecraft.world.entity.Entity; import net.minecraft.world.phys.Vec3; -import org.jetbrains.annotations.Nullable; import org.joml.Matrix4f; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Mutable; import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; +import org.spongepowered.asm.mixin.injection.ModifyVariable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; @Mixin(LevelRenderer.class) -public class LevelRendererMixin implements LevelRendererExt { - @Shadow private Frustum cullingFrustum; - - @Mutable - @Shadow @Final private RenderBuffers renderBuffers; - +public class LevelRendererMixin { @Shadow @Final private Minecraft minecraft; - @Shadow private @Nullable ClientLevel level; + @ModifyVariable(method = "setupRender", at = @At("HEAD"), index = 3, argsOnly = true) + private boolean portalcubed$denyRefreshIfPortalRendering(boolean org) { + return PortalRendering.isRendering() ? true : org; + } + + @Inject(method = "setupRender", at = @At("HEAD"), cancellable = true) + private void portalcubed$cancelSetupRenderIfPortalRendering(Camera camera, Frustum frustum, boolean hasCapturedFrustum, boolean isSpectator, CallbackInfo ci) { + if (PortalRendering.isRendering()) ci.cancel(); + } @Inject(method = "prepareCullFrustum", at = @At("HEAD")) private void modifyCameraRotation(PoseStack poseStack, Vec3 cameraPos, Matrix4f projectionMatrix, CallbackInfo ci) { @@ -46,26 +41,6 @@ private void modifyCameraRotation(PoseStack poseStack, Vec3 cameraPos, Matrix4f } } - @Override - public Frustum getCullingFrustum() { - return cullingFrustum; - } - - @Override - public void setCullingFrustum(Frustum cullingFrustum) { - this.cullingFrustum = cullingFrustum; - } - - @Override - public RenderBuffers getRenderBuffers() { - return renderBuffers; - } - - @Override - public void setRenderBuffers(RenderBuffers renderBuffers) { - this.renderBuffers = renderBuffers; - } - @WrapOperation( method = "renderLevel", at = @At( @@ -76,53 +51,4 @@ public void setRenderBuffers(RenderBuffers renderBuffers) { private boolean overrideDetached(Camera instance, Operation original) { return PortalCubedClient.cameraTransformedThroughPortal != null || original.call(instance); } - - @Inject( - method = "renderLevel", - at = @At("RETURN") - ) - private void renderEndNoFapi( - PoseStack poseStack, - float partialTick, - long finishNanoTime, - boolean renderBlockOutline, - Camera camera, - GameRenderer gameRenderer, - LightTexture lightTexture, - Matrix4f projectionMatrix, - CallbackInfo ci - ) { - assert level != null; - - if (PortalCubedClient.getRenderer().targetPhase() != PortalRenderPhase.FINAL) return; - final MultiBufferSource.BufferSource consumers = renderBuffers.bufferSource(); - final var cameraPos = camera.getPosition(); - poseStack.pushPose(); - poseStack.translate(-cameraPos.x, -cameraPos.y, -cameraPos.z); - final PortalRenderPhase oldRenderPhase = PortalRenderer.renderPhase; - PortalRenderer.renderPhase = PortalRenderPhase.FINAL; - - final EntityRenderDispatcher dispatcher = minecraft.getEntityRenderDispatcher(); - for (final Entity entity : level.entitiesForRendering()) { - if (!(entity instanceof Portal portal) || !portal.getActive()) continue; - final PortalRenderer renderer = (PortalRenderer)dispatcher.getRenderer(portal); - renderer.shouldRender(portal, cullingFrustum, cameraPos.x, cameraPos.y, cameraPos.z); - poseStack.pushPose(); - poseStack.translate(entity.getX(), entity.getY(), entity.getZ()); - poseStack.mulPose(portal.getRotation().get(partialTick)); - poseStack.mulPose(Axis.YP.rotationDegrees(180f)); - renderer.renderPortal( - poseStack, - consumers, - portal, - 0, 1, 1, 1, - partialTick - ); - poseStack.popPose(); - } - - poseStack.popPose(); - consumers.endLastBatch(); - PortalRenderer.renderPhase = oldRenderPhase; - } } diff --git a/src/main/java/com/fusionflux/portalcubed/mixin/client/LightingMixin.java b/src/main/java/com/fusionflux/portalcubed/mixin/client/LightingMixin.java new file mode 100644 index 00000000..0f1cff79 --- /dev/null +++ b/src/main/java/com/fusionflux/portalcubed/mixin/client/LightingMixin.java @@ -0,0 +1,18 @@ +package com.fusionflux.portalcubed.mixin.client; + +import org.joml.Matrix4f; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.ModifyVariable; + +import com.fusionflux.portalcubed.client.render.portal.PortalRendering; +import com.mojang.blaze3d.platform.Lighting; + +@Mixin(Lighting.class) +public abstract class LightingMixin { + @ModifyVariable(method = {"setupLevel", "setupNetherLevel"}, at = @At("HEAD"), index = 0, argsOnly = true) + private static Matrix4f portalcubed$fixLevelLighting(Matrix4f mat) { + if (PortalRendering.isRendering()) mat = new Matrix4f(mat).setTranslation(0, 0, 0); + return mat; + } +} diff --git a/src/main/java/com/fusionflux/portalcubed/mixin/client/RenderSystemAccessor.java b/src/main/java/com/fusionflux/portalcubed/mixin/client/RenderSystemAccessor.java new file mode 100644 index 00000000..7ff063ba --- /dev/null +++ b/src/main/java/com/fusionflux/portalcubed/mixin/client/RenderSystemAccessor.java @@ -0,0 +1,17 @@ +package com.fusionflux.portalcubed.mixin.client; + +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Mutable; +import org.spongepowered.asm.mixin.gen.Accessor; + +import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.blaze3d.vertex.PoseStack; + +@Mixin(RenderSystem.class) +public interface RenderSystemAccessor { + @Mutable + @Accessor + static void setModelViewStack(PoseStack poseStack) { + throw new AssertionError(); + } +} diff --git a/src/main/java/com/fusionflux/portalcubed/mixin/client/RenderTargetMixin.java b/src/main/java/com/fusionflux/portalcubed/mixin/client/RenderTargetMixin.java index 84538245..c9d08494 100644 --- a/src/main/java/com/fusionflux/portalcubed/mixin/client/RenderTargetMixin.java +++ b/src/main/java/com/fusionflux/portalcubed/mixin/client/RenderTargetMixin.java @@ -1,14 +1,14 @@ package com.fusionflux.portalcubed.mixin.client; -import com.fusionflux.portalcubed.accessor.RenderTargetExt; +import com.fusionflux.portalcubed.client.render.portal.PortalRenderTarget; +import com.fusionflux.portalcubed.client.render.portal.PortalRendering; import com.mojang.blaze3d.pipeline.RenderTarget; -import net.minecraft.client.Minecraft; import org.lwjgl.opengl.ARBFramebufferObject; import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; -import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.ModifyArgs; +import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.invoke.arg.Args; import static org.lwjgl.opengl.GL11.GL_DEPTH_COMPONENT; @@ -16,15 +16,7 @@ // Based on https://github.com/iPortalTeam/ImmersivePortalsMod/blob/55c9c1e7e298e09d8d43b0114e64e30271aa43b6/imm_ptl_core/src/main/java/qouteall/imm_ptl/core/mixin/client/render/framebuffer/MixinRenderTarget.java#L3 @Mixin(RenderTarget.class) -public abstract class RenderTargetMixin implements RenderTargetExt { - @Shadow public abstract void resize(int width, int height, boolean getError); - - @Shadow public int width; - @Shadow public int height; - - @Unique - private boolean stencilBufferEnabled; - +public abstract class RenderTargetMixin { @ModifyArgs( method = "createBuffers", at = @At( @@ -34,7 +26,7 @@ public abstract class RenderTargetMixin implements RenderTargetExt { ) ) private void texImage2D(Args args) { - if (stencilBufferEnabled && args.get(2).equals(GL_DEPTH_COMPONENT)) { + if ((Object) this instanceof PortalRenderTarget && args.get(2).equals(GL_DEPTH_COMPONENT)) { args.set(2, GL_DEPTH24_STENCIL8); args.set(6, ARBFramebufferObject.GL_DEPTH_STENCIL); args.set(7, GL_UNSIGNED_INT_24_8); @@ -50,21 +42,13 @@ private void texImage2D(Args args) { ) ) private void framebufferTexture2D(Args args) { - if (stencilBufferEnabled && args.get(1).equals(GL_DEPTH_ATTACHMENT)) { + if ((Object) this instanceof PortalRenderTarget && args.get(1).equals(GL_DEPTH_ATTACHMENT)) { args.set(1, GL_DEPTH_STENCIL_ATTACHMENT); } } - @Override - public boolean isStencilBufferEnabled() { - return stencilBufferEnabled; - } - - @Override - public void setStencilBufferEnabled(boolean enabled) { - if (enabled != stencilBufferEnabled) { - stencilBufferEnabled = enabled; - resize(width, height, Minecraft.ON_OSX); - } + @Inject(method = "bindWrite", at = @At("HEAD"), cancellable = true) + private void portalcubed$cancelBindWriteIfPortalRendering(boolean setViewport, CallbackInfo ci) { + if (PortalRendering.isRendering() && !((Object) this instanceof PortalRenderTarget)) ci.cancel(); } } diff --git a/src/main/java/com/fusionflux/portalcubed/mixin/client/VertexConsumerMixin.java b/src/main/java/com/fusionflux/portalcubed/mixin/client/VertexConsumerMixin.java index d1b46d60..2d9b5717 100644 --- a/src/main/java/com/fusionflux/portalcubed/mixin/client/VertexConsumerMixin.java +++ b/src/main/java/com/fusionflux/portalcubed/mixin/client/VertexConsumerMixin.java @@ -6,8 +6,6 @@ import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.ModifyArg; -import java.util.Objects; - @Mixin(VertexConsumer.class) public interface VertexConsumerMixin { @ModifyArg( diff --git a/src/main/resources/assets/portalcubed/lang/en_us.json b/src/main/resources/assets/portalcubed/lang/en_us.json index 71cae931..fa6fe7e5 100644 --- a/src/main/resources/assets/portalcubed/lang/en_us.json +++ b/src/main/resources/assets/portalcubed/lang/en_us.json @@ -451,7 +451,7 @@ "portalcubed.midnightconfig.portalHudMode": "Use Portal HUD", "portalcubed.midnightconfig.gelOverlayOpacity": "Gel Screen Overlay Opacity", "portalcubed.midnightconfig.staticPortalItemDrops": "Static Portal Item Drops", - "portalcubed.midnightconfig.renderer": "Portal Renderer (in development)", + "portalcubed.midnightconfig.portalRenderingLayers": "Portal Rendering Layers (in development)", "portalcubed.midnightconfig.enum.PortalRenderers.DISABLED": "Disabled", "portalcubed.midnightconfig.enum.PortalRenderers.STENCIL": "Stencil", "portalcubed.midnightconfig.enum.PortalRenderers.FRAMEBUFFER": "Framebuffer", diff --git a/src/main/resources/assets/portalcubed/shaders/core/portal_blit.fsh b/src/main/resources/assets/portalcubed/shaders/core/portal_blit.fsh new file mode 100644 index 00000000..dfdd2b68 --- /dev/null +++ b/src/main/resources/assets/portalcubed/shaders/core/portal_blit.fsh @@ -0,0 +1,11 @@ +#version 150 + +uniform sampler2D Sampler0; + +uniform vec2 ScreenSize; + +out vec4 fragColor; + +void main(){ + fragColor = texture(Sampler0, gl_FragCoord.xy / ScreenSize); +} diff --git a/src/main/resources/assets/portalcubed/shaders/core/portal_blit.json b/src/main/resources/assets/portalcubed/shaders/core/portal_blit.json new file mode 100644 index 00000000..02cbd821 --- /dev/null +++ b/src/main/resources/assets/portalcubed/shaders/core/portal_blit.json @@ -0,0 +1,18 @@ +{ + "blend": { + "func": "add", + "srcrgb": "srcalpha", + "dstrgb": "1-srcalpha" + }, + "vertex": "portalcubed:portal_blit", + "fragment": "portalcubed:portal_blit", + "attributes": [ "Position" ], + "samplers": [ + { "name": "Sampler0" } + ], + "uniforms": [ + { "name": "ModelViewMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ProjMat", "type": "matrix4x4", "count": 16, "values": [ 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 0.0, 1.0 ] }, + { "name": "ScreenSize", "type": "float", "count": 2, "values": [ 1.0, 1.0 ] } + ] +} diff --git a/src/main/resources/assets/portalcubed/shaders/core/portal_blit.vsh b/src/main/resources/assets/portalcubed/shaders/core/portal_blit.vsh new file mode 100644 index 00000000..d4704dbb --- /dev/null +++ b/src/main/resources/assets/portalcubed/shaders/core/portal_blit.vsh @@ -0,0 +1,10 @@ +#version 150 + +in vec3 Position; + +uniform mat4 ModelViewMat; +uniform mat4 ProjMat; + +void main(){ + gl_Position = ProjMat * ModelViewMat * vec4(Position, 1.0); +} diff --git a/src/main/resources/portalcubed.accesswidener b/src/main/resources/portalcubed.accesswidener index 5a81bd20..cc5c3d6d 100644 --- a/src/main/resources/portalcubed.accesswidener +++ b/src/main/resources/portalcubed.accesswidener @@ -1,5 +1,6 @@ accessWidener v1 named accessible class net/minecraft/client/renderer/RenderType$CompositeState -accessible class net/minecraft/client/renderer/RenderStateShard$TextureStateShard -accessible class net/minecraft/client/resources/model/ModelBakery$BakedCacheKey -accessible field net/minecraft/client/resources/model/ModelBakery bakedCache Ljava/util/Map; +accessible class net/minecraft/client/renderer/RenderStateShard$TextureStateShard +accessible class net/minecraft/client/resources/model/ModelBakery$BakedCacheKey +accessible field net/minecraft/client/resources/model/ModelBakery bakedCache Ljava/util/Map; +accessible class net/minecraft/client/renderer/LevelRenderer$RenderChunkInfo diff --git a/src/main/resources/portalcubed.mixins.json b/src/main/resources/portalcubed.mixins.json index 69c07f5e..49ba653a 100644 --- a/src/main/resources/portalcubed.mixins.json +++ b/src/main/resources/portalcubed.mixins.json @@ -32,12 +32,14 @@ "client.BlockModel_DeserializerMixin", "client.BlockModelMixin", "client.CameraMixin", + "client.CameraAccessor", "client.ClientAdvancementMixin", "client.ClientLevelMixin", "client.ClientPacketListenerMixin", "client.DeathScreenAccessor", "client.DeathScreenMixin", "client.FogRendererMixin", + "client.GlStateManagerMixin", "client.GameRendererMixin", "client.GuiMixin", "client.ItemEntityRendererMixin", @@ -45,7 +47,9 @@ "client.KeyboardHandlerMixin", "client.KeyboardInputMixin", "client.KeyMappingAccessor", + "client.LightingMixin", "client.LevelRendererMixin", + "client.LevelRendererAccessor", "client.LocalPlayerMixin", "client.MinecraftAccessor", "client.MinecraftMixin", @@ -57,6 +61,7 @@ "client.ParticleEngineMixin", "client.PlayerRendererMixin", "client.RenderSystemMixin", + "client.RenderSystemAccessor", "client.RenderTargetMixin", "client.ScreenEffectRendererMixin", "client.SimpleBakedModelAccessor",