diff options
Diffstat (limited to 'src/main/kotlin/util/render/RenderInWorldContext.kt')
-rw-r--r-- | src/main/kotlin/util/render/RenderInWorldContext.kt | 294 |
1 files changed, 294 insertions, 0 deletions
diff --git a/src/main/kotlin/util/render/RenderInWorldContext.kt b/src/main/kotlin/util/render/RenderInWorldContext.kt new file mode 100644 index 0000000..7faa499 --- /dev/null +++ b/src/main/kotlin/util/render/RenderInWorldContext.kt @@ -0,0 +1,294 @@ + + +package moe.nea.firmament.util.render + +import com.mojang.blaze3d.systems.RenderSystem +import io.github.notenoughupdates.moulconfig.platform.next +import java.lang.Math.pow +import org.joml.Matrix4f +import org.joml.Vector3f +import net.minecraft.client.gl.VertexBuffer +import net.minecraft.client.render.BufferBuilder +import net.minecraft.client.render.BufferRenderer +import net.minecraft.client.render.Camera +import net.minecraft.client.render.GameRenderer +import net.minecraft.client.render.RenderLayer +import net.minecraft.client.render.RenderPhase +import net.minecraft.client.render.RenderTickCounter +import net.minecraft.client.render.Tessellator +import net.minecraft.client.render.VertexConsumerProvider +import net.minecraft.client.render.VertexFormat +import net.minecraft.client.render.VertexFormats +import net.minecraft.client.texture.Sprite +import net.minecraft.client.util.math.MatrixStack +import net.minecraft.text.Text +import net.minecraft.util.Identifier +import net.minecraft.util.math.BlockPos +import net.minecraft.util.math.Vec3d +import moe.nea.firmament.events.WorldRenderLastEvent +import moe.nea.firmament.util.FirmFormatters +import moe.nea.firmament.util.MC + +@RenderContextDSL +class RenderInWorldContext private constructor( + private val tesselator: Tessellator, + val matrixStack: MatrixStack, + private val camera: Camera, + private val tickCounter: RenderTickCounter, + val vertexConsumers: VertexConsumerProvider.Immediate, +) { + + object RenderLayers { + val TRANSLUCENT_TRIS = RenderLayer.of("firmament_translucent_tris", + VertexFormats.POSITION_COLOR, + VertexFormat.DrawMode.TRIANGLES, + RenderLayer.DEFAULT_BUFFER_SIZE, + false, true, + RenderLayer.MultiPhaseParameters.builder() + .depthTest(RenderPhase.ALWAYS_DEPTH_TEST) + .transparency(RenderPhase.TRANSLUCENT_TRANSPARENCY) + .program(RenderPhase.COLOR_PROGRAM) + .build(false)) + } + + fun color(color: me.shedaniel.math.Color) { + color(color.red / 255F, color.green / 255f, color.blue / 255f, color.alpha / 255f) + } + + fun color(red: Float, green: Float, blue: Float, alpha: Float) { + RenderSystem.setShaderColor(red, green, blue, alpha) + } + + fun block(blockPos: BlockPos) { + matrixStack.push() + matrixStack.translate(blockPos.x.toFloat(), blockPos.y.toFloat(), blockPos.z.toFloat()) + buildCube(matrixStack.peek().positionMatrix, tesselator) + 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 waypoint(position: BlockPos, vararg label: Text) { + text( + position.toCenterPos(), + *label, + Text.literal("§e${FirmFormatters.formatDistance(MC.player?.pos?.distanceTo(position.toCenterPos()) ?: 42069.0)}"), + background = 0xAA202020.toInt() + ) + } + + fun withFacingThePlayer(position: Vec3d, block: FacingThePlayerContext.() -> Unit) { + matrixStack.push() + matrixStack.translate(position.x, position.y, position.z) + val actualCameraDistance = position.distanceTo(camera.pos) + val distanceToMoveTowardsCamera = if (actualCameraDistance < 10) 0.0 else -(actualCameraDistance - 10.0) + val vec = position.subtract(camera.pos).multiply(distanceToMoveTowardsCamera / actualCameraDistance) + matrixStack.translate(vec.x, vec.y, vec.z) + matrixStack.multiply(camera.rotation) + matrixStack.scale(0.025F, -0.025F, 1F) + + FacingThePlayerContext(this).run(block) + + matrixStack.pop() + vertexConsumers.drawCurrentLayer() + } + + fun sprite(position: Vec3d, sprite: Sprite, width: Int, height: Int) { + texture( + position, sprite.atlasId, width, height, sprite.minU, sprite.minV, sprite.maxU, sprite.maxV + ) + } + + fun texture( + position: Vec3d, texture: Identifier, width: Int, height: Int, + u1: Float, v1: Float, + u2: Float, v2: Float, + ) { + withFacingThePlayer(position) { + texture(texture, width, height, u1, v1, u2, v2) + } + } + + fun text(position: Vec3d, vararg texts: Text, verticalAlign: VerticalAlign = VerticalAlign.CENTER, background: Int = 0x70808080) { + withFacingThePlayer(position) { + text(*texts, verticalAlign = verticalAlign, background = background) + } + } + + fun tinyBlock(vec3d: Vec3d, size: Float) { + RenderSystem.setShader(GameRenderer::getPositionColorProgram) + matrixStack.push() + matrixStack.translate(vec3d.x, vec3d.y, vec3d.z) + matrixStack.scale(size, size, size) + matrixStack.translate(-.5, -.5, -.5) + buildCube(matrixStack.peek().positionMatrix, tesselator) + matrixStack.pop() + } + + fun wireframeCube(blockPos: BlockPos, lineWidth: Float = 10F) { + RenderSystem.setShader(GameRenderer::getRenderTypeLinesProgram) + matrixStack.push() + RenderSystem.lineWidth(lineWidth / pow(camera.pos.squaredDistanceTo(blockPos.toCenterPos()), 0.25).toFloat()) + matrixStack.translate(blockPos.x.toFloat(), blockPos.y.toFloat(), blockPos.z.toFloat()) + buildWireFrameCube(matrixStack.peek(), tesselator) + matrixStack.pop() + } + + fun line(vararg points: Vec3d, lineWidth: Float = 10F) { + line(points.toList(), lineWidth) + } + + fun tracer(toWhere: Vec3d, lineWidth: Float = 3f) { + val cameraForward = Vector3f(0f, 0f, 1f).rotate(camera.rotation) + line(camera.pos.add(Vec3d(cameraForward)), toWhere, lineWidth = lineWidth) + } + + fun line(points: List<Vec3d>, lineWidth: Float = 10F) { + RenderSystem.setShader(GameRenderer::getRenderTypeLinesProgram) + RenderSystem.lineWidth(lineWidth) + val buffer = tesselator.begin(VertexFormat.DrawMode.LINES, VertexFormats.LINES) + + val matrix = matrixStack.peek() + var lastNormal: Vector3f? = null + points.zipWithNext().forEach { (a, b) -> + val normal = Vector3f(b.x.toFloat(), b.y.toFloat(), b.z.toFloat()) + .sub(a.x.toFloat(), a.y.toFloat(), a.z.toFloat()) + .normalize() + val lastNormal0 = lastNormal ?: normal + lastNormal = normal + buffer.vertex(matrix.positionMatrix, a.x.toFloat(), a.y.toFloat(), a.z.toFloat()) + .color(-1) + .normal(matrix, lastNormal0.x, lastNormal0.y, lastNormal0.z) + .next() + buffer.vertex(matrix.positionMatrix, b.x.toFloat(), b.y.toFloat(), b.z.toFloat()) + .color(-1) + .normal(matrix, normal.x, normal.y, normal.z) + .next() + } + + BufferRenderer.drawWithGlobalProgram(buffer.end()) + } + + companion object { + private fun doLine( + matrix: MatrixStack.Entry, + buf: BufferBuilder, + i: Float, + j: Float, + k: Float, + x: Float, + y: Float, + z: Float + ) { + val normal = Vector3f(x, y, z) + .sub(i, j, k) + .normalize() + buf.vertex(matrix.positionMatrix, i, j, k) + .normal(matrix, normal.x, normal.y, normal.z) + .color(-1) + .next() + buf.vertex(matrix.positionMatrix, x, y, z) + .normal(matrix, normal.x, normal.y, normal.z) + .color(-1) + .next() + } + + + private fun buildWireFrameCube(matrix: MatrixStack.Entry, tessellator: Tessellator) { + val buf = tessellator.begin(VertexFormat.DrawMode.LINES, VertexFormats.LINES) + + for (i in 0..1) { + for (j in 0..1) { + val i = i.toFloat() + val j = j.toFloat() + doLine(matrix, buf, 0F, i, j, 1F, i, j) + doLine(matrix, buf, i, 0F, j, i, 1F, j) + doLine(matrix, buf, i, j, 0F, i, j, 1F) + } + } + BufferRenderer.drawWithGlobalProgram(buf.end()) + } + + private fun buildCube(matrix: Matrix4f, tessellator: Tessellator) { + val buf = tessellator.begin(VertexFormat.DrawMode.TRIANGLES, VertexFormats.POSITION_COLOR) + buf.vertex(matrix, 0.0F, 0.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 0.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 1.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 1.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 0.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 1.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 0.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 0.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 0.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 1.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 0.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 0.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 0.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 1.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 1.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 0.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 0.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 0.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 1.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 0.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 0.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 1.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 0.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 1.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 0.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 1.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 0.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 1.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 1.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 1.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 1.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 1.0F, 0.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 1.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 1.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 0.0F, 1.0F, 1.0F).color(-1).next() + buf.vertex(matrix, 1.0F, 0.0F, 1.0F).color(-1).next() + RenderLayers.TRANSLUCENT_TRIS.draw(buf.end()) + } + + + fun renderInWorld(event: WorldRenderLastEvent, block: RenderInWorldContext. () -> Unit) { + RenderSystem.disableDepthTest() + RenderSystem.enableBlend() + RenderSystem.defaultBlendFunc() + RenderSystem.disableCull() + + event.matrices.push() + event.matrices.translate(-event.camera.pos.x, -event.camera.pos.y, -event.camera.pos.z) + + val ctx = RenderInWorldContext( + RenderSystem.renderThreadTesselator(), + event.matrices, + event.camera, + event.tickCounter, + event.vertexConsumers + ) + + block(ctx) + + event.matrices.pop() + + RenderSystem.setShaderColor(1F, 1F, 1F, 1F) + VertexBuffer.unbind() + RenderSystem.enableDepthTest() + RenderSystem.enableCull() + RenderSystem.disableBlend() + } + } +} + + |