package net.minecraft.client.renderer.debug; import com.mojang.blaze3d.vertex.PoseStack; import com.mojang.blaze3d.vertex.VertexConsumer; import net.fabricmc.api.EnvType; import net.fabricmc.api.Environment; import net.minecraft.client.Minecraft; import net.minecraft.client.renderer.LevelRenderer; import net.minecraft.client.renderer.MultiBufferSource; import net.minecraft.client.renderer.RenderType; import net.minecraft.client.renderer.SectionOcclusionGraph; import net.minecraft.client.renderer.chunk.SectionRenderDispatcher; import net.minecraft.client.renderer.culling.Frustum; import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.util.Mth; import org.joml.Matrix4f; import org.joml.Vector4f; @Environment(EnvType.CLIENT) public class ChunkCullingDebugRenderer implements DebugRenderer.SimpleDebugRenderer { public static final Direction[] DIRECTIONS = Direction.values(); private final Minecraft minecraft; public ChunkCullingDebugRenderer(Minecraft minecraft) { this.minecraft = minecraft; } @Override public void render(PoseStack poseStack, MultiBufferSource bufferSource, double camX, double camY, double camZ) { LevelRenderer levelRenderer = this.minecraft.levelRenderer; if (this.minecraft.sectionPath || this.minecraft.sectionVisibility) { SectionOcclusionGraph sectionOcclusionGraph = levelRenderer.getSectionOcclusionGraph(); for (SectionRenderDispatcher.RenderSection renderSection : levelRenderer.getVisibleSections()) { SectionOcclusionGraph.Node node = sectionOcclusionGraph.getNode(renderSection); if (node != null) { BlockPos blockPos = renderSection.getRenderOrigin(); poseStack.pushPose(); poseStack.translate(blockPos.getX() - camX, blockPos.getY() - camY, blockPos.getZ() - camZ); Matrix4f matrix4f = poseStack.last().pose(); if (this.minecraft.sectionPath) { VertexConsumer vertexConsumer = bufferSource.getBuffer(RenderType.lines()); int i = node.step == 0 ? 0 : Mth.hsvToRgb(node.step / 50.0F, 0.9F, 0.9F); int j = i >> 16 & 0xFF; int k = i >> 8 & 0xFF; int l = i & 0xFF; for (int m = 0; m < DIRECTIONS.length; m++) { if (node.hasSourceDirection(m)) { Direction direction = DIRECTIONS[m]; vertexConsumer.addVertex(matrix4f, 8.0F, 8.0F, 8.0F).setColor(j, k, l, 255).setNormal(direction.getStepX(), direction.getStepY(), direction.getStepZ()); vertexConsumer.addVertex( matrix4f, (float)(8 - 16 * direction.getStepX()), (float)(8 - 16 * direction.getStepY()), (float)(8 - 16 * direction.getStepZ()) ) .setColor(j, k, l, 255) .setNormal(direction.getStepX(), direction.getStepY(), direction.getStepZ()); } } } if (this.minecraft.sectionVisibility && renderSection.getCompiled().hasRenderableLayers()) { VertexConsumer vertexConsumer = bufferSource.getBuffer(RenderType.lines()); int i = 0; for (Direction direction2 : DIRECTIONS) { for (Direction direction3 : DIRECTIONS) { boolean bl = renderSection.getCompiled().facesCanSeeEachother(direction2, direction3); if (!bl) { i++; vertexConsumer.addVertex( matrix4f, (float)(8 + 8 * direction2.getStepX()), (float)(8 + 8 * direction2.getStepY()), (float)(8 + 8 * direction2.getStepZ()) ) .setColor(255, 0, 0, 255) .setNormal(direction2.getStepX(), direction2.getStepY(), direction2.getStepZ()); vertexConsumer.addVertex( matrix4f, (float)(8 + 8 * direction3.getStepX()), (float)(8 + 8 * direction3.getStepY()), (float)(8 + 8 * direction3.getStepZ()) ) .setColor(255, 0, 0, 255) .setNormal(direction3.getStepX(), direction3.getStepY(), direction3.getStepZ()); } } } if (i > 0) { VertexConsumer vertexConsumer2 = bufferSource.getBuffer(RenderType.debugQuads()); float f = 0.5F; float g = 0.2F; vertexConsumer2.addVertex(matrix4f, 0.5F, 15.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 15.5F, 15.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 15.5F, 15.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 0.5F, 15.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 0.5F, 0.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 15.5F, 0.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 15.5F, 0.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 0.5F, 0.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 0.5F, 15.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 0.5F, 15.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 0.5F, 0.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 0.5F, 0.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 15.5F, 0.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 15.5F, 0.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 15.5F, 15.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 15.5F, 15.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 0.5F, 0.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 15.5F, 0.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 15.5F, 15.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 0.5F, 15.5F, 0.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 0.5F, 15.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 15.5F, 15.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 15.5F, 0.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); vertexConsumer2.addVertex(matrix4f, 0.5F, 0.5F, 15.5F).setColor(0.9F, 0.9F, 0.0F, 0.2F); } } poseStack.popPose(); } } } Frustum frustum = levelRenderer.getCapturedFrustum(); if (frustum != null) { poseStack.pushPose(); poseStack.translate((float)(frustum.getCamX() - camX), (float)(frustum.getCamY() - camY), (float)(frustum.getCamZ() - camZ)); Matrix4f matrix4f2 = poseStack.last().pose(); Vector4f[] vector4fs = frustum.getFrustumPoints(); VertexConsumer vertexConsumer3 = bufferSource.getBuffer(RenderType.debugQuads()); this.addFrustumQuad(vertexConsumer3, matrix4f2, vector4fs, 0, 1, 2, 3, 0, 1, 1); this.addFrustumQuad(vertexConsumer3, matrix4f2, vector4fs, 4, 5, 6, 7, 1, 0, 0); this.addFrustumQuad(vertexConsumer3, matrix4f2, vector4fs, 0, 1, 5, 4, 1, 1, 0); this.addFrustumQuad(vertexConsumer3, matrix4f2, vector4fs, 2, 3, 7, 6, 0, 0, 1); this.addFrustumQuad(vertexConsumer3, matrix4f2, vector4fs, 0, 4, 7, 3, 0, 1, 0); this.addFrustumQuad(vertexConsumer3, matrix4f2, vector4fs, 1, 5, 6, 2, 1, 0, 1); VertexConsumer vertexConsumer4 = bufferSource.getBuffer(RenderType.lines()); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[0]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[1]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[1]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[2]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[2]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[3]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[3]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[0]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[4]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[5]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[5]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[6]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[6]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[7]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[7]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[4]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[0]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[4]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[1]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[5]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[2]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[6]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[3]); this.addFrustumVertex(vertexConsumer4, matrix4f2, vector4fs[7]); poseStack.popPose(); } } private void addFrustumVertex(VertexConsumer buffer, Matrix4f pose, Vector4f position) { buffer.addVertex(pose, position.x(), position.y(), position.z()).setColor(-16777216).setNormal(0.0F, 0.0F, -1.0F); } private void addFrustumQuad( VertexConsumer buffer, Matrix4f pose, Vector4f[] frustumPoints, int point1, int point2, int point3, int point4, int red, int green, int blue ) { float f = 0.25F; buffer.addVertex(pose, frustumPoints[point1].x(), frustumPoints[point1].y(), frustumPoints[point1].z()) .setColor((float)red, (float)green, (float)blue, 0.25F); buffer.addVertex(pose, frustumPoints[point2].x(), frustumPoints[point2].y(), frustumPoints[point2].z()) .setColor((float)red, (float)green, (float)blue, 0.25F); buffer.addVertex(pose, frustumPoints[point3].x(), frustumPoints[point3].y(), frustumPoints[point3].z()) .setColor((float)red, (float)green, (float)blue, 0.25F); buffer.addVertex(pose, frustumPoints[point4].x(), frustumPoints[point4].y(), frustumPoints[point4].z()) .setColor((float)red, (float)green, (float)blue, 0.25F); } }