From 4444fcca44d9a53c8162d69e0e9f19fd214c2f54 Mon Sep 17 00:00:00 2001 From: nea Date: Tue, 4 Jul 2023 04:22:13 +0200 Subject: Add text rendering debugging --- .../nea/firmament/events/WorldRenderLastEvent.kt | 8 +++ .../kotlin/moe/nea/firmament/util/assertions.kt | 20 ++++++ .../firmament/util/render/RenderInWorldContext.kt | 81 ++++++++++++++++++++-- 3 files changed, 103 insertions(+), 6 deletions(-) create mode 100644 src/main/kotlin/moe/nea/firmament/util/assertions.kt (limited to 'src/main/kotlin/moe/nea/firmament') diff --git a/src/main/kotlin/moe/nea/firmament/events/WorldRenderLastEvent.kt b/src/main/kotlin/moe/nea/firmament/events/WorldRenderLastEvent.kt index 4778b91..c5da84f 100644 --- a/src/main/kotlin/moe/nea/firmament/events/WorldRenderLastEvent.kt +++ b/src/main/kotlin/moe/nea/firmament/events/WorldRenderLastEvent.kt @@ -22,7 +22,10 @@ import org.joml.Matrix4f import net.minecraft.client.render.Camera import net.minecraft.client.render.GameRenderer import net.minecraft.client.render.LightmapTextureManager +import net.minecraft.client.render.VertexConsumerProvider import net.minecraft.client.util.math.MatrixStack +import net.minecraft.util.math.Position +import net.minecraft.util.math.Vec3d /** * This event is called after all world rendering is done, but before any GUI rendering (including hand) has been done. @@ -35,6 +38,11 @@ data class WorldRenderLastEvent( val gameRenderer: GameRenderer, val lightmapTextureManager: LightmapTextureManager, val positionMatrix: Matrix4f, + val vertexConsumers: VertexConsumerProvider.Immediate, ) : FirmamentEvent() { companion object : FirmamentEventBus() + data class TextRenderCall(val string: String, val position: Position) + + val toRender = mutableListOf(TextRenderCall("Test String", Vec3d(0.0, 0.0, 0.0))) + } diff --git a/src/main/kotlin/moe/nea/firmament/util/assertions.kt b/src/main/kotlin/moe/nea/firmament/util/assertions.kt new file mode 100644 index 0000000..0fe569a --- /dev/null +++ b/src/main/kotlin/moe/nea/firmament/util/assertions.kt @@ -0,0 +1,20 @@ +package moe.nea.firmament.util + +/** + * Less aggressive version of `require(obj != null)`, which fails in devenv but continues at runtime. + */ +inline fun assertNotNullOr(obj: T?, block: () -> T): T { + assert(obj != null) + return obj ?: block() +} + + +/** + * Less aggressive version of `require(condition)`, which fails in devenv but continues at runtime. + */ +inline fun assertTrueOr(condition: Boolean, block: () -> Unit) { + assert(condition) + if (!condition) block() +} + + diff --git a/src/main/kotlin/moe/nea/firmament/util/render/RenderInWorldContext.kt b/src/main/kotlin/moe/nea/firmament/util/render/RenderInWorldContext.kt index 9c38145..1603b6b 100644 --- a/src/main/kotlin/moe/nea/firmament/util/render/RenderInWorldContext.kt +++ b/src/main/kotlin/moe/nea/firmament/util/render/RenderInWorldContext.kt @@ -22,22 +22,32 @@ import com.mojang.blaze3d.systems.RenderSystem import java.lang.Math.pow import org.joml.Matrix4f import org.joml.Vector3f +import net.minecraft.client.font.TextRenderer import net.minecraft.client.gl.VertexBuffer import net.minecraft.client.render.BufferBuilder import net.minecraft.client.render.Camera import net.minecraft.client.render.GameRenderer +import net.minecraft.client.render.LightmapTextureManager +import net.minecraft.client.render.RenderLayer import net.minecraft.client.render.Tessellator +import net.minecraft.client.render.VertexConsumer +import net.minecraft.client.render.VertexConsumerProvider import net.minecraft.client.render.VertexFormat import net.minecraft.client.render.VertexFormats import net.minecraft.client.util.math.MatrixStack import net.minecraft.client.util.math.MatrixStack.Entry +import net.minecraft.text.Text import net.minecraft.util.math.BlockPos import net.minecraft.util.math.Vec3d +import moe.nea.firmament.events.WorldRenderLastEvent +import moe.nea.firmament.util.MC +import moe.nea.firmament.util.assertTrueOr class RenderInWorldContext private constructor( private val tesselator: Tessellator, private val matrixStack: MatrixStack, - private val camera: Camera + private val camera: Camera, + private val vertexConsumers: VertexConsumerProvider.Immediate, ) { private val buffer = tesselator.buffer @@ -54,6 +64,59 @@ class RenderInWorldContext private constructor( matrixStack.pop() } + enum class VerticalAlign { + TOP, BOTTOM, CENTER; + + fun align(index: Int, count: Int): Float { + return when (this) { + CENTER -> (index - count / 2F) * (1 + MC.font.fontHeight.toFloat()) + BOTTOM -> (index - count) * (1 + MC.font.fontHeight.toFloat()) + TOP -> (index) * (1 + MC.font.fontHeight.toFloat()) + } + } + } + + fun text(position: Vec3d, vararg texts: Text, verticalAlign: VerticalAlign = VerticalAlign.CENTER) { + assertTrueOr(texts.isNotEmpty()) { return@text } + matrixStack.push() + matrixStack.translate(position.x, position.y, position.z) + matrixStack.multiply(camera.rotation) + matrixStack.scale(-0.025F, -0.025F, -1F) + for ((index, text) in texts.withIndex()) { + matrixStack.push() + val width = MC.font.getWidth(text) + matrixStack.translate(-width / 2F, verticalAlign.align(index, texts.size), 0F) + val vertexConsumer: VertexConsumer = vertexConsumers.getBuffer(RenderLayer.getTextBackgroundSeeThrough()) + val matrix4f = matrixStack.peek().positionMatrix + vertexConsumer.vertex(matrix4f, -1.0f, -1.0f, 0.0f).color(0x70808080) + .light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next() + vertexConsumer.vertex(matrix4f, -1.0f, MC.font.fontHeight.toFloat(), 0.0f).color(0x70808080) + .light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next() + vertexConsumer.vertex(matrix4f, width.toFloat(), MC.font.fontHeight.toFloat(), 0.0f) + .color(0x70808080) + .light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next() + vertexConsumer.vertex(matrix4f, width.toFloat(), -1.0f, 0.0f).color(0x70808080) + .light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next() + matrixStack.translate(0F, 0F, 0.01F) + + MC.font.draw( + text, + 0F, + 0F, + -1, + false, + matrixStack.peek().positionMatrix, + vertexConsumers, + TextRenderer.TextLayerType.SEE_THROUGH, + 0, + LightmapTextureManager.MAX_LIGHT_COORDINATE + ) + matrixStack.pop() + } + matrixStack.pop() + vertexConsumers.drawCurrentLayer() + } + fun tinyBlock(vec3d: Vec3d, size: Float) { RenderSystem.setShader(GameRenderer::getPositionColorProgram) matrixStack.push() @@ -157,20 +220,26 @@ class RenderInWorldContext private constructor( buf.unfixColor() } - fun renderInWorld(matrices: MatrixStack, camera: Camera, block: RenderInWorldContext. () -> Unit) { + + fun renderInWorld(event: WorldRenderLastEvent, block: RenderInWorldContext. () -> Unit) { RenderSystem.disableDepthTest() RenderSystem.enableBlend() RenderSystem.defaultBlendFunc() RenderSystem.disableCull() - matrices.push() - matrices.translate(-camera.pos.x, -camera.pos.y, -camera.pos.z) + event.matrices.push() + event.matrices.translate(-event.camera.pos.x, -event.camera.pos.y, -event.camera.pos.z) - val ctx = RenderInWorldContext(RenderSystem.renderThreadTesselator(), matrices, camera) + val ctx = RenderInWorldContext( + RenderSystem.renderThreadTesselator(), + event.matrices, + event.camera, + event.vertexConsumers + ) block(ctx) - matrices.pop() + event.matrices.pop() RenderSystem.setShaderColor(1F, 1F, 1F, 1F) VertexBuffer.unbind() -- cgit