diff options
8 files changed, 124 insertions, 13 deletions
diff --git a/build.gradle b/build.gradle index fec3b902..b5eaa09f 100644 --- a/build.gradle +++ b/build.gradle @@ -28,6 +28,7 @@ repositories { name = "meteor-maven" url = "https://maven.meteordev.org/releases" } + maven { url "https://repo.codemc.io/repository/maven-public/" } // For Occlusion Culling library maven {url "https://jitpack.io"} } @@ -63,6 +64,9 @@ dependencies { include modImplementation("com.github.0x3C50:Renderer:${project.renderer_version}") include(modImplementation ("meteordevelopment:discord-ipc:1.1")) + + // Occlusion Culling (https://github.com/LogisticsCraft/OcclusionCulling) + include implementation("com.logisticscraft:occlusionculling:${project.occlusionculling_version}") } base { diff --git a/gradle.properties b/gradle.properties index cbb51b52..ce4f22c0 100644 --- a/gradle.properties +++ b/gradle.properties @@ -20,6 +20,9 @@ rei_version=12.0.625 ## Renderer (https://github.com/0x3C50/Renderer) renderer_version = d687aced4c +## Occlusion Culling (https://github.com/LogisticsCraft/OcclusionCulling) +occlusionculling_version = 0.0.7-SNAPSHOT + # Mod Properties mod_version = 1.10.0 maven_group = me.xmrvizzy diff --git a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java index cc712405..3692db1b 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java +++ b/src/main/java/me/xmrvizzy/skyblocker/SkyblockerMod.java @@ -19,6 +19,7 @@ import me.xmrvizzy.skyblocker.skyblock.rift.TheRift; import me.xmrvizzy.skyblocker.skyblock.tabhud.TabHud; import me.xmrvizzy.skyblocker.skyblock.tabhud.util.PlayerListMgr; import me.xmrvizzy.skyblocker.utils.*; +import me.xmrvizzy.skyblocker.utils.culling.OcclusionCulling; import me.xmrvizzy.skyblocker.utils.title.TitleContainer; import net.fabricmc.api.ClientModInitializer; import net.fabricmc.fabric.api.client.event.lifecycle.v1.ClientTickEvents; @@ -83,6 +84,7 @@ public class SkyblockerMod implements ClientModInitializer { DungeonMap.init(); TheRift.init(); TitleContainer.init(); + OcclusionCulling.init(); containerSolverManager.init(); scheduler.scheduleCyclic(Utils::update, 20); scheduler.scheduleCyclic(DiscordRPCManager::updateDataAndPresence, 100); diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/RenderHelper.java b/src/main/java/me/xmrvizzy/skyblocker/utils/RenderHelper.java index 6fa93735..a1221549 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/utils/RenderHelper.java +++ b/src/main/java/me/xmrvizzy/skyblocker/utils/RenderHelper.java @@ -2,22 +2,29 @@ package me.xmrvizzy.skyblocker.utils; import me.x150.renderer.render.Renderer3d; import me.xmrvizzy.skyblocker.mixin.accessor.BeaconBlockEntityRendererInvoker; +import me.xmrvizzy.skyblocker.utils.culling.OcclusionCulling; import me.xmrvizzy.skyblocker.utils.title.Title; import me.xmrvizzy.skyblocker.utils.title.TitleContainer; import net.fabricmc.fabric.api.client.rendering.v1.WorldRenderContext; import net.minecraft.client.MinecraftClient; -import net.minecraft.client.render.block.entity.BeaconBlockEntityRenderer; +import net.minecraft.client.render.BufferBuilder; +import net.minecraft.client.render.Camera; +import net.minecraft.client.render.Tessellator; +import net.minecraft.client.render.VertexConsumerProvider; +import net.minecraft.client.util.math.MatrixStack; import net.minecraft.sound.SoundEvent; import net.minecraft.text.Text; import net.minecraft.util.Formatting; import net.minecraft.util.Identifier; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; - import java.awt.*; +import com.mojang.blaze3d.systems.RenderSystem; + public class RenderHelper { private static final Vec3d ONE = new Vec3d(1, 1, 1); + private static final int MAX_OVERWORLD_BUILD_HEIGHT = 319; public static void renderFilledThroughWallsWithBeaconBeam(WorldRenderContext context, BlockPos pos, float[] colorComponents, float alpha) { renderFilledThroughWalls(context, pos, colorComponents, alpha); @@ -25,26 +32,40 @@ public class RenderHelper { } public static void renderFilledThroughWalls(WorldRenderContext context, BlockPos pos, float[] colorComponents, float alpha) { - Renderer3d.renderThroughWalls(); - renderFilled(context, pos, colorComponents, alpha); - Renderer3d.stopRenderThroughWalls(); + if (FrustumUtils.isVisible(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1)) { + Renderer3d.renderThroughWalls(); + renderFilled(context, pos, colorComponents, alpha); + Renderer3d.stopRenderThroughWalls(); + } } public static void renderFilledIfVisible(WorldRenderContext context, BlockPos pos, float[] colorComponents, float alpha) { - if (FrustumUtils.isVisible(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1)) { + if (OcclusionCulling.isVisible(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, pos.getY() + 1, pos.getZ() + 1)) { renderFilled(context, pos, colorComponents, alpha); } } - public static void renderFilled(WorldRenderContext context, BlockPos pos, float[] colorComponents, float alpha) { + private static void renderFilled(WorldRenderContext context, BlockPos pos, float[] colorComponents, float alpha) { Renderer3d.renderFilled(context.matrixStack(), new Color(colorComponents[0], colorComponents[1], colorComponents[2], alpha), Vec3d.of(pos), ONE); } - public static void renderBeaconBeam(WorldRenderContext context, BlockPos pos, float[] colorComponents) { - context.matrixStack().push(); - context.matrixStack().translate(pos.getX() - context.camera().getPos().x, pos.getY() - context.camera().getPos().y, pos.getZ() - context.camera().getPos().z); - BeaconBlockEntityRendererInvoker.renderBeam(context.matrixStack(), context.consumers(), context.tickDelta(), context.world().getTime(), 0, BeaconBlockEntityRenderer.MAX_BEAM_HEIGHT, colorComponents); - context.matrixStack().pop(); + private static void renderBeaconBeam(WorldRenderContext context, BlockPos pos, float[] colorComponents) { + if (FrustumUtils.isVisible(pos.getX(), pos.getY(), pos.getZ(), pos.getX() + 1, MAX_OVERWORLD_BUILD_HEIGHT, pos.getZ() + 1)) { + MatrixStack matrices = context.matrixStack(); + Vec3d camera = context.camera().getPos(); + + matrices.push(); + matrices.translate(pos.getX() - camera.x, pos.getY() - camera.y, pos.getZ() - camera.z); + + 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); + + consumer.draw(); + matrices.pop(); + } } public static void displayTitleAndPlaySound(int stayTicks, int fadeOutTicks, String titleKey, Formatting formatting) { diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/RenderUtils.java b/src/main/java/me/xmrvizzy/skyblocker/utils/RenderUtils.java index 73ad468f..61f79ae1 100644 --- a/src/main/java/me/xmrvizzy/skyblocker/utils/RenderUtils.java +++ b/src/main/java/me/xmrvizzy/skyblocker/utils/RenderUtils.java @@ -82,7 +82,7 @@ public class RenderUtils { e.getZ() - MathHelper.lerp(tickDelta, e.lastRenderZ, e.getZ())); } - public static Boolean pointExistsInArea(int x, int y, int x1, int y1, int x2, int y2) { + public static boolean pointExistsInArea(int x, int y, int x1, int y1, int x2, int y2) { return x >= x1 && x <= x2 && y >= y1 && y <= y2; } diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/culling/OcclusionCulling.java b/src/main/java/me/xmrvizzy/skyblocker/utils/culling/OcclusionCulling.java new file mode 100644 index 00000000..e9a25fc3 --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/utils/culling/OcclusionCulling.java @@ -0,0 +1,48 @@ +package me.xmrvizzy.skyblocker.utils.culling; + +import com.logisticscraft.occlusionculling.OcclusionCullingInstance; +import com.logisticscraft.occlusionculling.cache.ArrayOcclusionCache; +import com.logisticscraft.occlusionculling.util.Vec3d; + +import me.xmrvizzy.skyblocker.utils.FrustumUtils; +import net.minecraft.client.MinecraftClient; + +public class OcclusionCulling { + private static final int TRACING_DISTANCE = 128; + private static final MinecraftClient CLIENT = MinecraftClient.getInstance(); + private static OcclusionCullingInstance instance = null; + + // Reused objects to reduce allocation overhead + private static Vec3d cameraPos = new Vec3d(0, 0, 0); + private static Vec3d min = new Vec3d(0, 0, 0); + private static Vec3d max = new Vec3d(0, 0, 0); + + /** + * Initializes the occlusion culling instance + */ + public static void init() { + instance = new OcclusionCullingInstance(TRACING_DISTANCE, new WorldProvider(), new ArrayOcclusionCache(TRACING_DISTANCE), 2); + } + + private static void updateCameraPos() { + var camera = CLIENT.gameRenderer.getCamera().getPos(); + cameraPos.set(camera.x, camera.y, camera.z); + } + + /** + * This first checks checks if the bounding box is within the camera's FOV, if + * it is then it checks for whether it's occluded or not. + * + * @return A boolean representing whether the bounding box is fully visible or + * not. + */ + public static boolean isVisible(double x1, double y1, double z1, double x2, double y2, double z2) { + if (!FrustumUtils.isVisible(x1, y1, z1, x2, y2, z2)) return false; + + updateCameraPos(); + min.set(x1, y1, z1); + max.set(x2, y2, z2); + + return instance.isAABBVisible(min, max, cameraPos); + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/culling/WorldProvider.java b/src/main/java/me/xmrvizzy/skyblocker/utils/culling/WorldProvider.java new file mode 100644 index 00000000..47d92c1f --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/utils/culling/WorldProvider.java @@ -0,0 +1,29 @@ +package me.xmrvizzy.skyblocker.utils.culling; + +import com.logisticscraft.occlusionculling.DataProvider; + +import net.minecraft.client.MinecraftClient; +import net.minecraft.client.world.ClientWorld; +import net.minecraft.util.math.BlockPos; + +public class WorldProvider implements DataProvider { + private final static MinecraftClient CLIENT = MinecraftClient.getInstance(); + private ClientWorld world = null; + + @Override + public boolean prepareChunk(int chunkX, int chunkZ) { + this.world = CLIENT.world; + return this.world != null; + } + + @Override + public boolean isOpaqueFullCube(int x, int y, int z) { + BlockPos pos = new BlockPos(x, y, z); + return this.world.getBlockState(pos).isOpaqueFullCube(this.world, pos); + } + + @Override + public void cleanup() { + this.world = null; + } +} diff --git a/src/main/java/me/xmrvizzy/skyblocker/utils/culling/package-info.java b/src/main/java/me/xmrvizzy/skyblocker/utils/culling/package-info.java new file mode 100644 index 00000000..c25e7f7a --- /dev/null +++ b/src/main/java/me/xmrvizzy/skyblocker/utils/culling/package-info.java @@ -0,0 +1,4 @@ +/** + * Package dedicated to occlusion culling utilities + */ +package me.xmrvizzy.skyblocker.utils.culling;
\ No newline at end of file |