aboutsummaryrefslogtreecommitdiff
path: root/src/main/kotlin/util/render
diff options
context:
space:
mode:
Diffstat (limited to 'src/main/kotlin/util/render')
-rw-r--r--src/main/kotlin/util/render/FacingThePlayerContext.kt101
-rw-r--r--src/main/kotlin/util/render/LerpUtils.kt33
-rw-r--r--src/main/kotlin/util/render/RenderCircleProgress.kt95
-rw-r--r--src/main/kotlin/util/render/RenderContextDSL.kt6
-rw-r--r--src/main/kotlin/util/render/RenderInWorldContext.kt294
-rw-r--r--src/main/kotlin/util/render/TranslatedScissors.kt22
6 files changed, 551 insertions, 0 deletions
diff --git a/src/main/kotlin/util/render/FacingThePlayerContext.kt b/src/main/kotlin/util/render/FacingThePlayerContext.kt
new file mode 100644
index 0000000..eb37e35
--- /dev/null
+++ b/src/main/kotlin/util/render/FacingThePlayerContext.kt
@@ -0,0 +1,101 @@
+
+package moe.nea.firmament.util.render
+
+import com.mojang.blaze3d.systems.RenderSystem
+import io.github.notenoughupdates.moulconfig.platform.next
+import org.joml.Matrix4f
+import net.minecraft.client.font.TextRenderer
+import net.minecraft.client.render.BufferRenderer
+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.VertexFormat
+import net.minecraft.client.render.VertexFormats
+import net.minecraft.text.Text
+import net.minecraft.util.Identifier
+import net.minecraft.util.math.BlockPos
+import moe.nea.firmament.util.FirmFormatters
+import moe.nea.firmament.util.MC
+import moe.nea.firmament.util.assertTrueOr
+
+@RenderContextDSL
+class FacingThePlayerContext(val worldContext: RenderInWorldContext) {
+ val matrixStack by worldContext::matrixStack
+ fun waypoint(position: BlockPos, label: Text) {
+ text(
+ label,
+ Text.literal("§e${FirmFormatters.formatDistance(MC.player?.pos?.distanceTo(position.toCenterPos()) ?: 42069.0)}")
+ )
+ }
+
+ fun text(
+ vararg texts: Text,
+ verticalAlign: RenderInWorldContext.VerticalAlign = RenderInWorldContext.VerticalAlign.CENTER,
+ background: Int = 0x70808080,
+ ) {
+ assertTrueOr(texts.isNotEmpty()) { return@text }
+ for ((index, text) in texts.withIndex()) {
+ worldContext.matrixStack.push()
+ val width = MC.font.getWidth(text)
+ worldContext.matrixStack.translate(-width / 2F, verticalAlign.align(index, texts.size), 0F)
+ val vertexConsumer: VertexConsumer =
+ worldContext.vertexConsumers.getBuffer(RenderLayer.getTextBackgroundSeeThrough())
+ val matrix4f = worldContext.matrixStack.peek().positionMatrix
+ vertexConsumer.vertex(matrix4f, -1.0f, -1.0f, 0.0f).color(background)
+ .light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
+ vertexConsumer.vertex(matrix4f, -1.0f, MC.font.fontHeight.toFloat(), 0.0f).color(background)
+ .light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
+ vertexConsumer.vertex(matrix4f, width.toFloat(), MC.font.fontHeight.toFloat(), 0.0f)
+ .color(background)
+ .light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
+ vertexConsumer.vertex(matrix4f, width.toFloat(), -1.0f, 0.0f).color(background)
+ .light(LightmapTextureManager.MAX_BLOCK_LIGHT_COORDINATE).next()
+ worldContext.matrixStack.translate(0F, 0F, 0.01F)
+
+ MC.font.draw(
+ text,
+ 0F,
+ 0F,
+ -1,
+ false,
+ worldContext.matrixStack.peek().positionMatrix,
+ worldContext.vertexConsumers,
+ TextRenderer.TextLayerType.SEE_THROUGH,
+ 0,
+ LightmapTextureManager.MAX_LIGHT_COORDINATE
+ )
+ worldContext.matrixStack.pop()
+ }
+ }
+
+
+ fun texture(
+ texture: Identifier, width: Int, height: Int,
+ u1: Float, v1: Float,
+ u2: Float, v2: Float,
+ ) {
+ RenderSystem.setShaderTexture(0, texture)
+ RenderSystem.setShader(GameRenderer::getPositionTexColorProgram)
+ val hw = width / 2F
+ val hh = height / 2F
+ val matrix4f: Matrix4f = worldContext.matrixStack.peek().positionMatrix
+ val buf = Tessellator.getInstance()
+ .begin(VertexFormat.DrawMode.QUADS, VertexFormats.POSITION_TEXTURE_COLOR)
+ buf.vertex(matrix4f, -hw, -hh, 0F)
+ .color(-1)
+ .texture(u1, v1).next()
+ buf.vertex(matrix4f, -hw, +hh, 0F)
+ .color(-1)
+ .texture(u1, v2).next()
+ buf.vertex(matrix4f, +hw, +hh, 0F)
+ .color(-1)
+ .texture(u2, v2).next()
+ buf.vertex(matrix4f, +hw, -hh, 0F)
+ .color(-1)
+ .texture(u2, v1).next()
+ BufferRenderer.drawWithGlobalProgram(buf.end())
+ }
+
+}
diff --git a/src/main/kotlin/util/render/LerpUtils.kt b/src/main/kotlin/util/render/LerpUtils.kt
new file mode 100644
index 0000000..f2c2f25
--- /dev/null
+++ b/src/main/kotlin/util/render/LerpUtils.kt
@@ -0,0 +1,33 @@
+
+package moe.nea.firmament.util.render
+
+import me.shedaniel.math.Color
+
+val pi = Math.PI
+val tau = Math.PI * 2
+fun lerpAngle(a: Float, b: Float, progress: Float): Float {
+ // TODO: there is at least 10 mods to many in here lol
+ val shortestAngle = ((((b.mod(tau) - a.mod(tau)).mod(tau)) + tau + pi).mod(tau)) - pi
+ return ((a + (shortestAngle) * progress).mod(tau)).toFloat()
+}
+
+fun lerp(a: Float, b: Float, progress: Float): Float {
+ return a + (b - a) * progress
+}
+fun lerp(a: Int, b: Int, progress: Float): Int {
+ return (a + (b - a) * progress).toInt()
+}
+
+fun ilerp(a: Float, b: Float, value: Float): Float {
+ return (value - a) / (b - a)
+}
+
+fun lerp(a: Color, b: Color, progress: Float): Color {
+ return Color.ofRGBA(
+ lerp(a.red, b.red, progress),
+ lerp(a.green, b.green, progress),
+ lerp(a.blue, b.blue, progress),
+ lerp(a.alpha, b.alpha, progress),
+ )
+}
+
diff --git a/src/main/kotlin/util/render/RenderCircleProgress.kt b/src/main/kotlin/util/render/RenderCircleProgress.kt
new file mode 100644
index 0000000..a2f42b5
--- /dev/null
+++ b/src/main/kotlin/util/render/RenderCircleProgress.kt
@@ -0,0 +1,95 @@
+
+package moe.nea.firmament.util.render
+
+import com.mojang.blaze3d.systems.RenderSystem
+import io.github.notenoughupdates.moulconfig.platform.next
+import org.joml.Matrix4f
+import org.joml.Vector2f
+import kotlin.math.atan2
+import kotlin.math.tan
+import net.minecraft.client.gui.DrawContext
+import net.minecraft.client.render.BufferRenderer
+import net.minecraft.client.render.GameRenderer
+import net.minecraft.client.render.Tessellator
+import net.minecraft.client.render.VertexFormat.DrawMode
+import net.minecraft.client.render.VertexFormats
+import net.minecraft.util.Identifier
+
+object RenderCircleProgress {
+
+ fun renderCircle(
+ drawContext: DrawContext,
+ texture: Identifier,
+ progress: Float,
+ u1: Float,
+ u2: Float,
+ v1: Float,
+ v2: Float,
+ ) {
+ RenderSystem.setShaderTexture(0, texture)
+ RenderSystem.setShader(GameRenderer::getPositionTexColorProgram)
+ RenderSystem.enableBlend()
+ val matrix: Matrix4f = drawContext.matrices.peek().positionMatrix
+ val bufferBuilder = Tessellator.getInstance().begin(DrawMode.TRIANGLES, VertexFormats.POSITION_TEXTURE_COLOR)
+
+ val corners = listOf(
+ Vector2f(0F, -1F),
+ Vector2f(1F, -1F),
+ Vector2f(1F, 0F),
+ Vector2f(1F, 1F),
+ Vector2f(0F, 1F),
+ Vector2f(-1F, 1F),
+ Vector2f(-1F, 0F),
+ Vector2f(-1F, -1F),
+ )
+
+ for (i in (0 until 8)) {
+ if (progress < i / 8F) {
+ break
+ }
+ val second = corners[(i + 1) % 8]
+ val first = corners[i]
+ if (progress <= (i + 1) / 8F) {
+ val internalProgress = 1 - (progress - i / 8F) * 8F
+ val angle = lerpAngle(
+ atan2(second.y, second.x),
+ atan2(first.y, first.x),
+ internalProgress
+ )
+ if (angle < tau / 8 || angle >= tau * 7 / 8) {
+ second.set(1F, tan(angle))
+ } else if (angle < tau * 3 / 8) {
+ second.set(1 / tan(angle), 1F)
+ } else if (angle < tau * 5 / 8) {
+ second.set(-1F, -tan(angle))
+ } else {
+ second.set(-1 / tan(angle), -1F)
+ }
+ }
+
+ fun ilerp(f: Float): Float =
+ ilerp(-1f, 1f, f)
+
+ bufferBuilder
+ .vertex(matrix, second.x, second.y, 0F)
+ .texture(lerp(u1, u2, ilerp(second.x)), lerp(v1, v2, ilerp(second.y)))
+ .color(-1)
+ .next()
+ bufferBuilder
+ .vertex(matrix, first.x, first.y, 0F)
+ .texture(lerp(u1, u2, ilerp(first.x)), lerp(v1, v2, ilerp(first.y)))
+ .color(-1)
+ .next()
+ bufferBuilder
+ .vertex(matrix, 0F, 0F, 0F)
+ .texture(lerp(u1, u2, ilerp(0F)), lerp(v1, v2, ilerp(0F)))
+ .color(-1)
+ .next()
+ }
+ BufferRenderer.drawWithGlobalProgram(bufferBuilder.end())
+ RenderSystem.disableBlend()
+ }
+
+
+
+}
diff --git a/src/main/kotlin/util/render/RenderContextDSL.kt b/src/main/kotlin/util/render/RenderContextDSL.kt
new file mode 100644
index 0000000..9bb4431
--- /dev/null
+++ b/src/main/kotlin/util/render/RenderContextDSL.kt
@@ -0,0 +1,6 @@
+
+package moe.nea.firmament.util.render
+
+@DslMarker
+annotation class RenderContextDSL {
+}
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()
+ }
+ }
+}
+
+
diff --git a/src/main/kotlin/util/render/TranslatedScissors.kt b/src/main/kotlin/util/render/TranslatedScissors.kt
new file mode 100644
index 0000000..c1e6544
--- /dev/null
+++ b/src/main/kotlin/util/render/TranslatedScissors.kt
@@ -0,0 +1,22 @@
+
+package moe.nea.firmament.util.render
+
+import org.joml.Vector4f
+import net.minecraft.client.gui.DrawContext
+
+fun DrawContext.enableScissorWithTranslation(x1: Float, y1: Float, x2: Float, y2: Float) {
+ val pMat = matrices.peek().positionMatrix
+ val target = Vector4f()
+
+ target.set(x1, y1, 0f, 1f)
+ target.mul(pMat)
+ val scissorX1 = target.x
+ val scissorY1 = target.y
+
+ target.set(x2, y2, 0f, 1f)
+ target.mul(pMat)
+ val scissorX2 = target.x
+ val scissorY2 = target.y
+
+ enableScissor(scissorX1.toInt(), scissorY1.toInt(), scissorX2.toInt(), scissorY2.toInt())
+}