diff options
author | Aaron <51387595+AzureAaron@users.noreply.github.com> | 2023-11-13 21:33:01 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-11-13 21:33:01 -0500 |
commit | 41cc6598899c0ec3b906c75f6be6805be315e100 (patch) | |
tree | 09272777eeccc55c9f28e3c64b4d0aea61b92bf3 /src/main | |
parent | 7fd8afe2f92f2407fca51328cf8f4a2c75c716f9 (diff) | |
parent | 736db8f1b0076ebe639bf0c1590e86d05191f01f (diff) | |
download | Skyblocker-41cc6598899c0ec3b906c75f6be6805be315e100.tar.gz Skyblocker-41cc6598899c0ec3b906c75f6be6805be315e100.tar.bz2 Skyblocker-41cc6598899c0ec3b906c75f6be6805be315e100.zip |
Merge pull request #415 from AzureAaron/batched-rendering
Batched Rendering + Future Sodium Compat
Diffstat (limited to 'src/main')
4 files changed, 102 insertions, 35 deletions
diff --git a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java index 65404c6c..ad3b6318 100644 --- a/src/main/java/de/hysky/skyblocker/SkyblockerMod.java +++ b/src/main/java/de/hysky/skyblocker/SkyblockerMod.java @@ -27,6 +27,7 @@ import de.hysky.skyblocker.utils.NEURepoManager; import de.hysky.skyblocker.utils.Utils; import de.hysky.skyblocker.utils.chat.ChatMessageListener; import de.hysky.skyblocker.utils.discord.DiscordRPCManager; +import de.hysky.skyblocker.utils.render.RenderHelper; import de.hysky.skyblocker.utils.render.culling.OcclusionCulling; import de.hysky.skyblocker.utils.render.gui.ContainerSolverManager; import de.hysky.skyblocker.utils.render.title.TitleContainer; @@ -115,6 +116,7 @@ public class SkyblockerMod implements ClientModInitializer { SecretsTracker.init(); ApiUtils.init(); Debug.init(); + RenderHelper.init(); containerSolverManager.init(); statusBarTracker.init(); Scheduler.INSTANCE.scheduleCyclic(Utils::update, 20); diff --git a/src/main/java/de/hysky/skyblocker/skyblock/special/SpecialEffects.java b/src/main/java/de/hysky/skyblocker/skyblock/special/SpecialEffects.java index fba447ea..bc4f98c2 100644 --- a/src/main/java/de/hysky/skyblocker/skyblock/special/SpecialEffects.java +++ b/src/main/java/de/hysky/skyblocker/skyblock/special/SpecialEffects.java @@ -1,8 +1,8 @@ package de.hysky.skyblocker.skyblock.special; -import com.mojang.blaze3d.systems.RenderSystem; import de.hysky.skyblocker.config.SkyblockerConfigManager; import de.hysky.skyblocker.utils.Utils; +import de.hysky.skyblocker.utils.render.RenderHelper; import net.fabricmc.fabric.api.client.message.v1.ClientReceiveMessageEvents; import net.minecraft.client.MinecraftClient; import net.minecraft.enchantment.Enchantments; @@ -58,15 +58,10 @@ public class SpecialEffects { ItemStack stack = getStackFromName(matcher.group("item")); if (!stack.isEmpty()) { - if (RenderSystem.isOnRenderThread()) { + RenderHelper.runOnRenderThread(() -> { client.particleManager.addEmitter(client.player, ParticleTypes.PORTAL, 30); client.gameRenderer.showFloatingItem(stack); - } else { - RenderSystem.recordRenderCall(() -> { - client.particleManager.addEmitter(client.player, ParticleTypes.PORTAL, 30); - client.gameRenderer.showFloatingItem(stack); - }); - } + }); } } } diff --git a/src/main/java/de/hysky/skyblocker/utils/render/RenderHelper.java b/src/main/java/de/hysky/skyblocker/utils/render/RenderHelper.java index e4cfea1b..3d8213fe 100644 --- a/src/main/java/de/hysky/skyblocker/utils/render/RenderHelper.java +++ b/src/main/java/de/hysky/skyblocker/utils/render/RenderHelper.java @@ -1,11 +1,16 @@ package de.hysky.skyblocker.utils.render; import com.mojang.blaze3d.systems.RenderSystem; +import com.mojang.logging.LogUtils; + +import de.hysky.skyblocker.SkyblockerMod; import de.hysky.skyblocker.mixin.accessor.BeaconBlockEntityRendererInvoker; import de.hysky.skyblocker.utils.render.culling.OcclusionCulling; import de.hysky.skyblocker.utils.render.title.Title; import de.hysky.skyblocker.utils.render.title.TitleContainer; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; +import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderEvents; +import net.fabricmc.fabric.api.event.Event; import net.minecraft.client.MinecraftClient; import net.minecraft.client.font.TextRenderer; import net.minecraft.client.render.*; @@ -14,18 +19,33 @@ import net.minecraft.client.util.math.MatrixStack; import net.minecraft.sound.SoundEvents; import net.minecraft.text.OrderedText; import net.minecraft.text.Text; +import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Box; import net.minecraft.util.math.Vec3d; + +import java.lang.invoke.MethodHandle; +import java.lang.invoke.MethodHandles; +import java.lang.invoke.MethodType; + import org.joml.Matrix3f; import org.joml.Matrix4f; import org.lwjgl.opengl.GL11; +import org.slf4j.Logger; public class RenderHelper { + private static final Logger LOGGER = LogUtils.getLogger(); + private static final Identifier TRANSLUCENT_DRAW = new Identifier(SkyblockerMod.NAMESPACE, "translucent_draw"); + private static final MethodHandle SCHEDULE_DEFERRED_RENDER_TASK = getDeferredRenderTaskHandle(); private static final Vec3d ONE = new Vec3d(1, 1, 1); private static final int MAX_OVERWORLD_BUILD_HEIGHT = 319; private static final MinecraftClient client = MinecraftClient.getInstance(); + public static void init() { + WorldRenderEvents.AFTER_TRANSLUCENT.addPhaseOrdering(Event.DEFAULT_PHASE, TRANSLUCENT_DRAW); + WorldRenderEvents.AFTER_TRANSLUCENT.register(TRANSLUCENT_DRAW, RenderHelper::drawTranslucents); + } + public static void renderFilledThroughWallsWithBeaconBeam(WorldRenderContext context, BlockPos pos, float[] colorComponents, float alpha) { renderFilledThroughWalls(context, pos, colorComponents, alpha); renderBeaconBeam(context, pos, colorComponents); @@ -46,33 +66,16 @@ public class RenderHelper { private static void renderFilled(WorldRenderContext context, Vec3d pos, Vec3d dimensions, float[] colorComponents, float alpha, boolean throughWalls) { MatrixStack matrices = context.matrixStack(); Vec3d camera = context.camera().getPos(); - Tessellator tessellator = RenderSystem.renderThreadTesselator(); - BufferBuilder buffer = tessellator.getBuffer(); matrices.push(); matrices.translate(-camera.x, -camera.y, -camera.z); - RenderSystem.setShader(GameRenderer::getPositionColorProgram); - RenderSystem.setShaderColor(1f, 1f, 1f, 1f); - RenderSystem.polygonOffset(-1f, -10f); - RenderSystem.enablePolygonOffset(); - RenderSystem.enableBlend(); - RenderSystem.defaultBlendFunc(); - RenderSystem.enableDepthTest(); - RenderSystem.depthFunc(throughWalls ? GL11.GL_ALWAYS : GL11.GL_LEQUAL); - RenderSystem.disableCull(); + VertexConsumerProvider consumers = context.consumers(); + VertexConsumer buffer = consumers.getBuffer(throughWalls ? SkyblockerRenderLayers.FILLED_THROUGH_WALLS : SkyblockerRenderLayers.FILLED); - buffer.begin(DrawMode.TRIANGLE_STRIP, VertexFormats.POSITION_COLOR); WorldRenderer.renderFilledBox(matrices, buffer, pos.x, pos.y, pos.z, pos.x + dimensions.x, pos.y + dimensions.y, pos.z + dimensions.z, colorComponents[0], colorComponents[1], colorComponents[2], alpha); - tessellator.draw(); matrices.pop(); - RenderSystem.polygonOffset(0f, 0f); - RenderSystem.disablePolygonOffset(); - RenderSystem.disableBlend(); - RenderSystem.disableDepthTest(); - RenderSystem.depthFunc(GL11.GL_LEQUAL); - RenderSystem.enableCull(); } private static void renderBeaconBeam(WorldRenderContext context, BlockPos pos, float[] colorComponents) { @@ -83,13 +86,8 @@ public class RenderHelper { matrices.push(); matrices.translate(pos.getX() - camera.getX(), pos.getY() - camera.getY(), pos.getZ() - camera.getZ()); - Tessellator tessellator = RenderSystem.renderThreadTesselator(); - BufferBuilder buffer = tessellator.getBuffer(); - VertexConsumerProvider.Immediate consumer = VertexConsumerProvider.immediate(buffer); - - BeaconBlockEntityRendererInvoker.renderBeam(matrices, consumer, context.tickDelta(), context.world().getTime(), 0, MAX_OVERWORLD_BUILD_HEIGHT, colorComponents); + BeaconBlockEntityRendererInvoker.renderBeam(matrices, context.consumers(), context.tickDelta(), context.world().getTime(), 0, MAX_OVERWORLD_BUILD_HEIGHT, colorComponents); - consumer.draw(); matrices.pop(); } } @@ -259,6 +257,28 @@ public class RenderHelper { } /** + * This is called after all {@link WorldRenderEvents#AFTER_TRANSLUCENT} listeners have been called so that we can draw all remaining render layers. + */ + private static void drawTranslucents(WorldRenderContext context) { + //Draw all render layers that haven't been drawn yet - drawing a specific layer does nothing and idk why + ((VertexConsumerProvider.Immediate) context.consumers()).draw(); + } + + public static void runOnRenderThread(Runnable runnable) { + if (RenderSystem.isOnRenderThread()) { + runnable.run(); + } else if (SCHEDULE_DEFERRED_RENDER_TASK != null) { //Sodium + try { + SCHEDULE_DEFERRED_RENDER_TASK.invokeExact(runnable); + } catch (Throwable t) { + LOGGER.error("[Skyblocker] Failed to schedule a render task!", t); + } + } else { //Vanilla + RenderSystem.recordRenderCall(runnable::run); + } + } + + /** * Adds the title to {@link TitleContainer} and {@link #playNotificationSound() plays the notification sound} if the title is not in the {@link TitleContainer} already. * No checking needs to be done on whether the title is in the {@link TitleContainer} already by the caller. * @@ -284,12 +304,26 @@ public class RenderHelper { } private static void playNotificationSound() { - if (MinecraftClient.getInstance().player != null) { - MinecraftClient.getInstance().player.playSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 100f, 0.1f); + if (client.player != null) { + client.player.playSound(SoundEvents.ENTITY_EXPERIENCE_ORB_PICKUP, 100f, 0.1f); } } public static boolean pointIsInArea(double x, double y, double x1, double y1, double x2, double y2) { return x >= x1 && x <= x2 && y >= y1 && y <= y2; } + + // TODO Get rid of reflection once the new Sodium is released + private static MethodHandle getDeferredRenderTaskHandle() { + try { + Class<?> deferredTaskClass = Class.forName("me.jellysquid.mods.sodium.client.render.util.DeferredRenderTask"); + + MethodHandles.Lookup lookup = MethodHandles.publicLookup(); + MethodType mt = MethodType.methodType(void.class, Runnable.class); + + return lookup.findStatic(deferredTaskClass, "schedule", mt); + } catch (Throwable ignored) {} + + return null; + } } diff --git a/src/main/java/de/hysky/skyblocker/utils/render/SkyblockerRenderLayers.java b/src/main/java/de/hysky/skyblocker/utils/render/SkyblockerRenderLayers.java new file mode 100644 index 00000000..ee113cc4 --- /dev/null +++ b/src/main/java/de/hysky/skyblocker/utils/render/SkyblockerRenderLayers.java @@ -0,0 +1,36 @@ +package de.hysky.skyblocker.utils.render; + +import com.mojang.blaze3d.systems.RenderSystem; + +import net.minecraft.client.render.RenderLayer; +import net.minecraft.client.render.RenderLayer.MultiPhase; +import net.minecraft.client.render.RenderLayer.MultiPhaseParameters; +import net.minecraft.client.render.RenderPhase; +import net.minecraft.client.render.RenderPhase.Cull; +import net.minecraft.client.render.RenderPhase.DepthTest; +import net.minecraft.client.render.RenderPhase.Transparency; +import net.minecraft.client.render.VertexFormat.DrawMode; +import net.minecraft.client.render.VertexFormats; + +public class SkyblockerRenderLayers { + private static final Transparency DEFAULT_TRANSPARENCY = new Transparency("default_transparency", () -> { + RenderSystem.enableBlend(); + RenderSystem.defaultBlendFunc(); + }, RenderSystem::disableBlend); + + public static final MultiPhase FILLED = RenderLayer.of("filled", VertexFormats.POSITION_COLOR, DrawMode.TRIANGLE_STRIP, RenderLayer.CUTOUT_BUFFER_SIZE, false, true, MultiPhaseParameters.builder() + .program(RenderPhase.COLOR_PROGRAM) + .cull(Cull.DISABLE_CULLING) + .layering(RenderPhase.POLYGON_OFFSET_LAYERING) + .transparency(DEFAULT_TRANSPARENCY) + .depthTest(DepthTest.LEQUAL_DEPTH_TEST) + .build(false)); + + public static final MultiPhase FILLED_THROUGH_WALLS = RenderLayer.of("filled_through_walls", VertexFormats.POSITION_COLOR, DrawMode.TRIANGLE_STRIP, RenderLayer.CUTOUT_BUFFER_SIZE, false, true, MultiPhaseParameters.builder() + .program(RenderPhase.COLOR_PROGRAM) + .cull(Cull.DISABLE_CULLING) + .layering(RenderPhase.POLYGON_OFFSET_LAYERING) + .transparency(DEFAULT_TRANSPARENCY) + .depthTest(DepthTest.ALWAYS_DEPTH_TEST) + .build(false)); +} |