136 lines
6 KiB
Java
136 lines
6 KiB
Java
package net.minecraft.client.renderer.debug;
|
|
|
|
import com.mojang.blaze3d.vertex.PoseStack;
|
|
import com.mojang.blaze3d.vertex.VertexConsumer;
|
|
import java.time.Duration;
|
|
import java.time.Instant;
|
|
import net.fabricmc.api.EnvType;
|
|
import net.fabricmc.api.Environment;
|
|
import net.minecraft.client.Minecraft;
|
|
import net.minecraft.client.renderer.MultiBufferSource;
|
|
import net.minecraft.client.renderer.RenderType;
|
|
import net.minecraft.client.renderer.ShapeRenderer;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.core.SectionPos;
|
|
import net.minecraft.world.level.LightLayer;
|
|
import net.minecraft.world.level.lighting.LevelLightEngine;
|
|
import net.minecraft.world.level.lighting.LayerLightSectionStorage.SectionType;
|
|
import net.minecraft.world.phys.shapes.BitSetDiscreteVoxelShape;
|
|
import net.minecraft.world.phys.shapes.DiscreteVoxelShape;
|
|
import org.jetbrains.annotations.Nullable;
|
|
import org.joml.Matrix4f;
|
|
import org.joml.Vector4f;
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
public class LightSectionDebugRenderer implements DebugRenderer.SimpleDebugRenderer {
|
|
private static final Duration REFRESH_INTERVAL = Duration.ofMillis(500L);
|
|
private static final int RADIUS = 10;
|
|
private static final Vector4f LIGHT_AND_BLOCKS_COLOR = new Vector4f(1.0F, 1.0F, 0.0F, 0.25F);
|
|
private static final Vector4f LIGHT_ONLY_COLOR = new Vector4f(0.25F, 0.125F, 0.0F, 0.125F);
|
|
private final Minecraft minecraft;
|
|
private final LightLayer lightLayer;
|
|
private Instant lastUpdateTime = Instant.now();
|
|
@Nullable
|
|
private LightSectionDebugRenderer.SectionData data;
|
|
|
|
public LightSectionDebugRenderer(Minecraft minecraft, LightLayer lightLayer) {
|
|
this.minecraft = minecraft;
|
|
this.lightLayer = lightLayer;
|
|
}
|
|
|
|
@Override
|
|
public void render(PoseStack poseStack, MultiBufferSource bufferSource, double camX, double camY, double camZ) {
|
|
Instant instant = Instant.now();
|
|
if (this.data == null || Duration.between(this.lastUpdateTime, instant).compareTo(REFRESH_INTERVAL) > 0) {
|
|
this.lastUpdateTime = instant;
|
|
this.data = new LightSectionDebugRenderer.SectionData(
|
|
this.minecraft.level.getLightEngine(), SectionPos.of(this.minecraft.player.blockPosition()), 10, this.lightLayer
|
|
);
|
|
}
|
|
|
|
renderEdges(poseStack, this.data.lightAndBlocksShape, this.data.minPos, bufferSource, camX, camY, camZ, LIGHT_AND_BLOCKS_COLOR);
|
|
renderEdges(poseStack, this.data.lightShape, this.data.minPos, bufferSource, camX, camY, camZ, LIGHT_ONLY_COLOR);
|
|
VertexConsumer vertexConsumer = bufferSource.getBuffer(RenderType.debugSectionQuads());
|
|
renderFaces(poseStack, this.data.lightAndBlocksShape, this.data.minPos, vertexConsumer, camX, camY, camZ, LIGHT_AND_BLOCKS_COLOR);
|
|
renderFaces(poseStack, this.data.lightShape, this.data.minPos, vertexConsumer, camX, camY, camZ, LIGHT_ONLY_COLOR);
|
|
}
|
|
|
|
private static void renderFaces(
|
|
PoseStack poseStack, DiscreteVoxelShape shape, SectionPos pos, VertexConsumer buffer, double camX, double camY, double camZ, Vector4f color
|
|
) {
|
|
shape.forAllFaces((direction, i, j, k) -> {
|
|
int l = i + pos.getX();
|
|
int m = j + pos.getY();
|
|
int n = k + pos.getZ();
|
|
renderFace(poseStack, buffer, direction, camX, camY, camZ, l, m, n, color);
|
|
});
|
|
}
|
|
|
|
private static void renderEdges(
|
|
PoseStack poseStack, DiscreteVoxelShape shape, SectionPos pos, MultiBufferSource bufferSource, double camX, double camY, double camZ, Vector4f color
|
|
) {
|
|
shape.forAllEdges((i, j, k, l, m, n) -> {
|
|
int o = i + pos.getX();
|
|
int p = j + pos.getY();
|
|
int q = k + pos.getZ();
|
|
int r = l + pos.getX();
|
|
int s = m + pos.getY();
|
|
int t = n + pos.getZ();
|
|
VertexConsumer vertexConsumer = bufferSource.getBuffer(RenderType.debugLineStrip(1.0));
|
|
renderEdge(poseStack, vertexConsumer, camX, camY, camZ, o, p, q, r, s, t, color);
|
|
}, true);
|
|
}
|
|
|
|
private static void renderFace(
|
|
PoseStack poseStack, VertexConsumer buffer, Direction face, double camX, double camY, double camZ, int blockX, int blockY, int blockZ, Vector4f color
|
|
) {
|
|
float f = (float)(SectionPos.sectionToBlockCoord(blockX) - camX);
|
|
float g = (float)(SectionPos.sectionToBlockCoord(blockY) - camY);
|
|
float h = (float)(SectionPos.sectionToBlockCoord(blockZ) - camZ);
|
|
ShapeRenderer.renderFace(poseStack, buffer, face, f, g, h, f + 16.0F, g + 16.0F, h + 16.0F, color.x(), color.y(), color.z(), color.w());
|
|
}
|
|
|
|
private static void renderEdge(
|
|
PoseStack poseStack, VertexConsumer buffer, double camX, double camY, double camZ, int x1, int y1, int z1, int x2, int y2, int z2, Vector4f color
|
|
) {
|
|
float f = (float)(SectionPos.sectionToBlockCoord(x1) - camX);
|
|
float g = (float)(SectionPos.sectionToBlockCoord(y1) - camY);
|
|
float h = (float)(SectionPos.sectionToBlockCoord(z1) - camZ);
|
|
float i = (float)(SectionPos.sectionToBlockCoord(x2) - camX);
|
|
float j = (float)(SectionPos.sectionToBlockCoord(y2) - camY);
|
|
float k = (float)(SectionPos.sectionToBlockCoord(z2) - camZ);
|
|
Matrix4f matrix4f = poseStack.last().pose();
|
|
buffer.addVertex(matrix4f, f, g, h).setColor(color.x(), color.y(), color.z(), 1.0F);
|
|
buffer.addVertex(matrix4f, i, j, k).setColor(color.x(), color.y(), color.z(), 1.0F);
|
|
}
|
|
|
|
@Environment(EnvType.CLIENT)
|
|
static final class SectionData {
|
|
final DiscreteVoxelShape lightAndBlocksShape;
|
|
final DiscreteVoxelShape lightShape;
|
|
final SectionPos minPos;
|
|
|
|
SectionData(LevelLightEngine levelLightEngine, SectionPos pos, int radius, LightLayer lightLayer) {
|
|
int i = radius * 2 + 1;
|
|
this.lightAndBlocksShape = new BitSetDiscreteVoxelShape(i, i, i);
|
|
this.lightShape = new BitSetDiscreteVoxelShape(i, i, i);
|
|
|
|
for (int j = 0; j < i; j++) {
|
|
for (int k = 0; k < i; k++) {
|
|
for (int l = 0; l < i; l++) {
|
|
SectionPos sectionPos = SectionPos.of(pos.x() + l - radius, pos.y() + k - radius, pos.z() + j - radius);
|
|
SectionType sectionType = levelLightEngine.getDebugSectionType(lightLayer, sectionPos);
|
|
if (sectionType == SectionType.LIGHT_AND_DATA) {
|
|
this.lightAndBlocksShape.fill(l, k, j);
|
|
this.lightShape.fill(l, k, j);
|
|
} else if (sectionType == SectionType.LIGHT_ONLY) {
|
|
this.lightShape.fill(l, k, j);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
this.minPos = SectionPos.of(pos.x() - radius, pos.y() - radius, pos.z() - radius);
|
|
}
|
|
}
|
|
}
|