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/CustomRenderLayers.kt105
-rw-r--r--src/main/kotlin/util/render/DrawContextExt.kt210
-rw-r--r--src/main/kotlin/util/render/DumpTexture.kt34
-rw-r--r--src/main/kotlin/util/render/FacingThePlayerContext.kt104
-rw-r--r--src/main/kotlin/util/render/FirmamentShaders.kt20
-rw-r--r--src/main/kotlin/util/render/LerpUtils.kt37
-rw-r--r--src/main/kotlin/util/render/MultiSpecialGuiRenderState.kt47
-rw-r--r--src/main/kotlin/util/render/RenderCircleProgress.kt229
-rw-r--r--src/main/kotlin/util/render/RenderInWorldContext.kt352
-rw-r--r--src/main/kotlin/util/render/TintedOverlayTexture.kt21
-rw-r--r--src/main/kotlin/util/render/TranslatedScissors.kt41
11 files changed, 753 insertions, 447 deletions
diff --git a/src/main/kotlin/util/render/CustomRenderLayers.kt b/src/main/kotlin/util/render/CustomRenderLayers.kt
new file mode 100644
index 0000000..4a85c17
--- /dev/null
+++ b/src/main/kotlin/util/render/CustomRenderLayers.kt
@@ -0,0 +1,105 @@
+package util.render
+
+import com.mojang.blaze3d.pipeline.BlendFunction
+import com.mojang.blaze3d.pipeline.RenderPipeline
+import com.mojang.blaze3d.platform.DepthTestFunction
+import com.mojang.blaze3d.vertex.VertexFormat.Mode
+import java.util.function.Function
+import net.minecraft.client.renderer.RenderPipelines
+import com.mojang.blaze3d.shaders.UniformType
+import net.minecraft.client.renderer.RenderType
+import net.minecraft.client.renderer.RenderStateShard
+import com.mojang.blaze3d.vertex.DefaultVertexFormat
+import net.minecraft.resources.ResourceLocation
+import net.minecraft.Util
+import moe.nea.firmament.Firmament
+
+object CustomRenderPipelines {
+ val GUI_TEXTURED_NO_DEPTH_TRIS =
+ RenderPipeline.builder(RenderPipelines.GUI_TEXTURED_SNIPPET)
+ .withVertexFormat(DefaultVertexFormat.POSITION_TEX_COLOR, Mode.TRIANGLES)
+ .withLocation(Firmament.identifier("gui_textured_overlay_tris"))
+ .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST)
+ .withCull(false)
+ .withDepthWrite(false)
+ .build()
+ val OMNIPRESENT_LINES = RenderPipeline
+ .builder(RenderPipelines.LINES_SNIPPET)
+ .withLocation(Firmament.identifier("lines"))
+ .withDepthWrite(false)
+ .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST)
+ .build()
+ val COLORED_OMNIPRESENT_QUADS =
+ RenderPipeline.builder(RenderPipelines.MATRICES_PROJECTION_SNIPPET)// TODO: split this up to support better transparent ordering.
+ .withLocation(Firmament.identifier("colored_omnipresent_quads"))
+ .withVertexShader("core/position_color")
+ .withFragmentShader("core/position_color")
+ .withVertexFormat(DefaultVertexFormat.POSITION_COLOR, Mode.QUADS)
+ .withDepthTestFunction(DepthTestFunction.NO_DEPTH_TEST)
+ .withCull(false)
+ .withDepthWrite(false)
+ .withBlend(BlendFunction.TRANSLUCENT)
+ .build()
+
+ val CIRCLE_FILTER_TRANSLUCENT_GUI_TRIS =
+ RenderPipeline.builder(RenderPipelines.GUI_TEXTURED_SNIPPET)
+ .withVertexFormat(DefaultVertexFormat.POSITION_TEX_COLOR, Mode.TRIANGLES)
+ .withLocation(Firmament.identifier("gui_textured_overlay_tris_circle"))
+ .withUniform("CutoutRadius", UniformType.UNIFORM_BUFFER)
+ .withFragmentShader(Firmament.identifier("circle_discard_color"))
+// .withBlend(BlendFunction.TRANSLUCENT)
+ .build()
+ val PARALLAX_CAPE_SHADER =
+ RenderPipeline.builder(RenderPipelines.ENTITY_SNIPPET)
+ .withLocation(Firmament.identifier("parallax_cape"))
+ .withFragmentShader(Firmament.identifier("cape/parallax"))
+ .withSampler("Sampler0")
+ .withSampler("Sampler1")
+ .withSampler("Sampler3")
+ .withUniform("Animation", UniformType.UNIFORM_BUFFER)
+ .build()
+}
+
+object CustomRenderLayers {
+ inline fun memoizeTextured(crossinline func: (ResourceLocation) -> RenderType.CompositeRenderType) = memoize(func)
+ inline fun <T, R> memoize(crossinline func: (T) -> R): Function<T, R> {
+ return Util.memoize { it: T -> func(it) }
+ }
+
+ val GUI_TEXTURED_NO_DEPTH_TRIS = memoizeTextured { texture ->
+ RenderType.create(
+ "firmament_gui_textured_overlay_tris",
+ RenderType.TRANSIENT_BUFFER_SIZE,
+ CustomRenderPipelines.GUI_TEXTURED_NO_DEPTH_TRIS,
+ RenderType.CompositeState.builder().setTextureState(
+ RenderStateShard.TextureStateShard(texture, false)
+ )
+ .createCompositeState(false)
+ )
+ }
+ val LINES = RenderType.create(
+ "firmament_lines",
+ RenderType.TRANSIENT_BUFFER_SIZE,
+ CustomRenderPipelines.OMNIPRESENT_LINES,
+ RenderType.CompositeState.builder() // TODO: accept linewidth here
+ .createCompositeState(false)
+ )
+ val COLORED_QUADS = RenderType.create(
+ "firmament_quads",
+ RenderType.TRANSIENT_BUFFER_SIZE,
+ false, true,
+ CustomRenderPipelines.COLORED_OMNIPRESENT_QUADS,
+ RenderType.CompositeState.builder()
+ .setLightmapState(RenderStateShard.NO_LIGHTMAP)
+ .createCompositeState(false)
+ )
+
+ val TRANSLUCENT_CIRCLE_GUI =
+ RenderType.create(
+ "firmament_circle_gui",
+ RenderType.TRANSIENT_BUFFER_SIZE,
+ CustomRenderPipelines.CIRCLE_FILTER_TRANSLUCENT_GUI_TRIS,
+ RenderType.CompositeState.builder()
+ .createCompositeState(false)
+ )
+}
diff --git a/src/main/kotlin/util/render/DrawContextExt.kt b/src/main/kotlin/util/render/DrawContextExt.kt
index a143d4d..9ef66f3 100644
--- a/src/main/kotlin/util/render/DrawContextExt.kt
+++ b/src/main/kotlin/util/render/DrawContextExt.kt
@@ -2,63 +2,33 @@ package moe.nea.firmament.util.render
import com.mojang.blaze3d.systems.RenderSystem
import me.shedaniel.math.Color
-import org.joml.Matrix4f
-import net.minecraft.client.gui.DrawContext
-import net.minecraft.client.render.RenderLayer
-import net.minecraft.client.render.RenderLayer.MultiPhaseParameters
-import net.minecraft.client.render.RenderPhase
-import net.minecraft.client.render.VertexFormat
-import net.minecraft.client.render.VertexFormat.DrawMode
-import net.minecraft.client.render.VertexFormats
-import net.minecraft.util.Identifier
-import net.minecraft.util.TriState
-import net.minecraft.util.Util
+import org.joml.Vector3f
+import util.render.CustomRenderLayers
+import kotlin.math.abs
+import net.minecraft.client.renderer.RenderPipelines
+import net.minecraft.client.gui.GuiGraphics
+import net.minecraft.client.gui.navigation.ScreenRectangle
+import net.minecraft.client.renderer.MultiBufferSource
+import com.mojang.blaze3d.vertex.PoseStack
+import net.minecraft.resources.ResourceLocation
import moe.nea.firmament.util.MC
-fun DrawContext.isUntranslatedGuiDrawContext(): Boolean {
- return (matrices.peek().positionMatrix.properties() and Matrix4f.PROPERTY_IDENTITY.toInt()) != 0
-}
-
-object GuiRenderLayers {
- val GUI_TEXTURED_NO_DEPTH = Util.memoize<Identifier, RenderLayer> { texture: Identifier ->
- RenderLayer.of("firmament_gui_textured_no_depth",
- VertexFormats.POSITION_TEXTURE_COLOR,
- DrawMode.QUADS,
- DEFAULT_BUFFER_SIZE,
- MultiPhaseParameters.builder()
- .texture(RenderPhase.Texture(texture, TriState.FALSE, false))
- .program(RenderPhase.POSITION_TEXTURE_COLOR_PROGRAM)
- .transparency(RenderPhase.TRANSLUCENT_TRANSPARENCY)
- .depthTest(RenderPhase.ALWAYS_DEPTH_TEST)
- .build(false))
- }
- val GUI_TEXTURED_TRIS = Util.memoize { texture: Identifier ->
- RenderLayer.of("firmament_gui_textured_overlay_tris",
- VertexFormats.POSITION_TEXTURE_COLOR,
- DrawMode.TRIANGLES,
- DEFAULT_BUFFER_SIZE,
- MultiPhaseParameters.builder()
- .texture(RenderPhase.Texture(texture, TriState.DEFAULT, false))
- .program(RenderPhase.POSITION_TEXTURE_COLOR_PROGRAM)
- .transparency(RenderPhase.TRANSLUCENT_TRANSPARENCY)
- .depthTest(RenderPhase.ALWAYS_DEPTH_TEST)
- .writeMaskState(RenderPhase.COLOR_MASK)
- .build(false))
- }
+fun GuiGraphics.isUntranslatedGuiDrawContext(): Boolean {
+ return pose().m00 == 1F && pose().m11 == 1f && pose().m01 == 0F && pose().m10 == 0F && pose().m20 == 0F && pose().m21 == 0F
}
@Deprecated("Use the other drawGuiTexture")
-fun DrawContext.drawGuiTexture(
- x: Int, y: Int, z: Int, width: Int, height: Int, sprite: Identifier
-) = this.drawGuiTexture(RenderLayer::getGuiTextured, sprite, x, y, width, height)
+fun GuiGraphics.drawGuiTexture(
+ x: Int, y: Int, z: Int, width: Int, height: Int, sprite: ResourceLocation
+) = this.blitSprite(RenderPipelines.GUI_TEXTURED, sprite, x, y, width, height)
-fun DrawContext.drawGuiTexture(
- sprite: Identifier,
+fun GuiGraphics.drawGuiTexture(
+ sprite: ResourceLocation,
x: Int, y: Int, width: Int, height: Int
-) = this.drawGuiTexture(RenderLayer::getGuiTextured, sprite, x, y, width, height)
+) = this.blitSprite(RenderPipelines.GUI_TEXTURED, sprite, x, y, width, height)
-fun DrawContext.drawTexture(
- sprite: Identifier,
+fun GuiGraphics.drawTexture(
+ sprite: ResourceLocation,
x: Int,
y: Int,
u: Float,
@@ -68,34 +38,130 @@ fun DrawContext.drawTexture(
textureWidth: Int,
textureHeight: Int
) {
- this.drawTexture(RenderLayer::getGuiTextured,
- sprite,
- x,
- y,
- u,
- v,
- width,
- height,
- width,
- height,
- textureWidth,
- textureHeight)
+ this.blit(
+ RenderPipelines.GUI_TEXTURED,
+ sprite,
+ x,
+ y,
+ u,
+ v,
+ width,
+ height,
+ width,
+ height,
+ textureWidth,
+ textureHeight
+ )
+}
+
+data class LineRenderState(
+ override val x1: Int,
+ override val x2: Int,
+ override val y1: Int,
+ override val y2: Int,
+ override val scale: Float,
+ override val bounds: ScreenRectangle,
+ val lineWidth: Float,
+ val w: Int,
+ val h: Int,
+ val color: Int,
+ val direction: LineDirection,
+) : MultiSpecialGuiRenderState() {
+ enum class LineDirection {
+ TOP_LEFT_TO_BOTTOM_RIGHT,
+ BOTTOM_LEFT_TO_TOP_RIGHT,
+ }
+
+ override fun createRenderer(vertexConsumers: MultiBufferSource.BufferSource): MultiSpecialGuiRenderer<out MultiSpecialGuiRenderState> {
+ return LineRenderer(vertexConsumers)
+ }
+
+ override val scissorArea = null
}
-fun DrawContext.drawLine(fromX: Int, fromY: Int, toX: Int, toY: Int, color: Color) {
- // TODO: push scissors
- // TODO: use matrix translations and a different render layer
+class LineRenderer(vertexConsumers: MultiBufferSource.BufferSource) :
+ MultiSpecialGuiRenderer<LineRenderState>(vertexConsumers) {
+ override fun getRenderStateClass(): Class<LineRenderState> {
+ return LineRenderState::class.java
+ }
+
+ override fun getTranslateY(height: Int, windowScaleFactor: Int): Float {
+ return height / 2F
+ }
+
+ override fun renderToTexture(
+ state: LineRenderState,
+ matrices: PoseStack
+ ) {
+ val gr = MC.instance.gameRenderer
+ val client = MC.instance
+ gr.globalSettingsUniform
+ .update(
+ state.bounds.width,
+ state.bounds.height,
+ client.options.glintStrength().get(),
+ client.level?.gameTime ?: 0L,
+ client.deltaTracker,
+ client.options.menuBackgroundBlurriness
+ )
+
+ RenderSystem.lineWidth(state.lineWidth)
+ val buf = bufferSource.getBuffer(CustomRenderLayers.LINES)
+ val matrix = matrices.last()
+ val wh = state.w / 2F
+ val hh = state.h / 2F
+ val lowX = -wh
+ val lowY = if (state.direction == LineRenderState.LineDirection.BOTTOM_LEFT_TO_TOP_RIGHT) hh else -hh
+ val highX = wh
+ val highY = -lowY
+ val norm = Vector3f(highX - lowX, highY - lowY, 0F).normalize()
+ buf.addVertex(matrix, lowX, lowY, 0F).setColor(state.color)
+ .setNormal(matrix, norm)
+ buf.addVertex(matrix, highX, highY, 0F).setColor(state.color)
+ .setNormal(matrix, norm)
+ bufferSource.endBatch()
+ gr.globalSettingsUniform
+ .update(
+ client.window.width,
+ client.window.height,
+ client.options.glintStrength().get(),
+ client.level?.gameTime ?: 0L,
+ client.deltaTracker,
+ client.options.menuBackgroundBlurriness
+ )
+
+ }
+
+ override fun getTextureLabel(): String? {
+ return "Firmament Line Renderer"
+ }
+}
+
+
+fun GuiGraphics.drawLine(fromX: Int, fromY: Int, toX: Int, toY: Int, color: Color, lineWidth: Float = 1F) {
if (toY < fromY) {
drawLine(toX, toY, fromX, fromY, color)
return
}
- RenderSystem.lineWidth(MC.window.scaleFactor.toFloat())
- draw { vertexConsumers ->
- val buf = vertexConsumers.getBuffer(RenderInWorldContext.RenderLayers.LINES)
- buf.vertex(fromX.toFloat(), fromY.toFloat(), 0F).color(color.color)
- .normal(toX - fromX.toFloat(), toY - fromY.toFloat(), 0F)
- buf.vertex(toX.toFloat(), toY.toFloat(), 0F).color(color.color)
- .normal(toX - fromX.toFloat(), toY - fromY.toFloat(), 0F)
- }
+ val originalRect = ScreenRectangle(
+ minOf(fromX, toX), minOf(toY, fromY),
+ abs(toX - fromX), abs(toY - fromY)
+ ).transformAxisAligned(pose())
+ val expansionFactor = 3
+ val rect = ScreenRectangle(
+ originalRect.left() - expansionFactor,
+ originalRect.top() - expansionFactor,
+ originalRect.width + expansionFactor * 2,
+ originalRect.height + expansionFactor * 2
+ )
+ // TODO: expand the bounds so that the thickness of the line can be used
+ // TODO: fix this up to work with scissorarea
+ guiRenderState.submitPicturesInPictureState(
+ LineRenderState(
+ rect.left(), rect.right(), rect.top(), rect.bottom(), 1F, rect, lineWidth,
+ originalRect.width, originalRect.height, color.color,
+ if (fromX < toX) LineRenderState.LineDirection.TOP_LEFT_TO_BOTTOM_RIGHT else LineRenderState.LineDirection.BOTTOM_LEFT_TO_TOP_RIGHT
+ )
+ )
}
diff --git a/src/main/kotlin/util/render/DumpTexture.kt b/src/main/kotlin/util/render/DumpTexture.kt
new file mode 100644
index 0000000..2ac6a1c
--- /dev/null
+++ b/src/main/kotlin/util/render/DumpTexture.kt
@@ -0,0 +1,34 @@
+package moe.nea.firmament.util.render
+
+import com.mojang.blaze3d.buffers.GpuBuffer
+import com.mojang.blaze3d.systems.RenderSystem
+import com.mojang.blaze3d.textures.GpuTexture
+import java.io.File
+import com.mojang.blaze3d.platform.NativeImage
+
+fun dumpTexture(gpuTexture: GpuTexture, name: String) {
+ val w = gpuTexture.getWidth(0)
+ val h = gpuTexture.getHeight(0)
+ val buffer = RenderSystem.getDevice()
+ .createBuffer(
+ { "Dump Buffer" },
+ GpuBuffer.USAGE_COPY_DST or GpuBuffer.USAGE_MAP_READ,
+ w * h * gpuTexture.getFormat().pixelSize()
+ )
+ val commandEncoder = RenderSystem.getDevice().createCommandEncoder()
+ commandEncoder.copyTextureToBuffer(
+ gpuTexture, buffer, 0, {
+ val nativeImage = NativeImage(w, h, false)
+ commandEncoder.mapBuffer(buffer, true, false).use { mappedView ->
+ for (i in 0..<w) {
+ for (j in 0..<h) {
+ val color = mappedView.data().getInt((j + i * w) * gpuTexture.format.pixelSize())
+ nativeImage.setPixelABGR(j, h - i - 1, color)
+ }
+ }
+ }
+ buffer.close()
+ nativeImage.writeToFile(File("$name.png"))
+ }, 0
+ )
+}
diff --git a/src/main/kotlin/util/render/FacingThePlayerContext.kt b/src/main/kotlin/util/render/FacingThePlayerContext.kt
index daa8da9..dc45939 100644
--- a/src/main/kotlin/util/render/FacingThePlayerContext.kt
+++ b/src/main/kotlin/util/render/FacingThePlayerContext.kt
@@ -1,21 +1,15 @@
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 util.render.CustomRenderLayers
+import net.minecraft.client.gui.Font
+import net.minecraft.client.renderer.LightTexture
+import net.minecraft.client.renderer.RenderType
+import com.mojang.blaze3d.vertex.VertexConsumer
+import net.minecraft.network.chat.Component
+import net.minecraft.resources.ResourceLocation
+import net.minecraft.core.BlockPos
import moe.nea.firmament.util.FirmFormatters
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.assertTrueOr
@@ -23,76 +17,76 @@ import moe.nea.firmament.util.assertTrueOr
@RenderContextDSL
class FacingThePlayerContext(val worldContext: RenderInWorldContext) {
val matrixStack by worldContext::matrixStack
- fun waypoint(position: BlockPos, label: Text) {
+ fun waypoint(position: BlockPos, label: Component) {
text(
label,
- Text.literal("§e${FirmFormatters.formatDistance(MC.player?.pos?.distanceTo(position.toCenterPos()) ?: 42069.0)}")
+ Component.literal("§e${FirmFormatters.formatDistance(MC.player?.position?.distanceTo(position.center) ?: 42069.0)}")
)
}
fun text(
- vararg texts: Text,
- verticalAlign: RenderInWorldContext.VerticalAlign = RenderInWorldContext.VerticalAlign.CENTER,
- background: Int = 0x70808080,
+ vararg texts: Component,
+ 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.pushPose()
+ val width = MC.font.width(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.vertexConsumers.getBuffer(RenderType.textBackgroundSeeThrough())
+ val matrix4f = worldContext.matrixStack.last().pose()
+ vertexConsumer.addVertex(matrix4f, -1.0f, -1.0f, 0.0f).setColor(background)
+ .setLight(LightTexture.FULL_BLOCK)
+ vertexConsumer.addVertex(matrix4f, -1.0f, MC.font.lineHeight.toFloat(), 0.0f).setColor(background)
+ .setLight(LightTexture.FULL_BLOCK)
+ vertexConsumer.addVertex(matrix4f, width.toFloat(), MC.font.lineHeight.toFloat(), 0.0f)
+ .setColor(background)
+ .setLight(LightTexture.FULL_BLOCK)
+ vertexConsumer.addVertex(matrix4f, width.toFloat(), -1.0f, 0.0f).setColor(background)
+ .setLight(LightTexture.FULL_BLOCK)
worldContext.matrixStack.translate(0F, 0F, 0.01F)
- MC.font.draw(
+ MC.font.drawInBatch(
text,
0F,
0F,
-1,
false,
- worldContext.matrixStack.peek().positionMatrix,
+ worldContext.matrixStack.last().pose(),
worldContext.vertexConsumers,
- TextRenderer.TextLayerType.SEE_THROUGH,
+ Font.DisplayMode.SEE_THROUGH,
0,
- LightmapTextureManager.MAX_LIGHT_COORDINATE
+ LightTexture.FULL_BRIGHT
)
- worldContext.matrixStack.pop()
+ worldContext.matrixStack.popPose()
}
}
fun texture(
- texture: Identifier, width: Int, height: Int,
- u1: Float, v1: Float,
- u2: Float, v2: Float,
+ texture: ResourceLocation, width: Int, height: Int,
+ u1: Float, v1: Float,
+ u2: Float, v2: Float,
) {
- val buf = worldContext.vertexConsumers.getBuffer(RenderLayer.getGuiTexturedOverlay(texture))
+ val buf = worldContext.vertexConsumers.getBuffer(CustomRenderLayers.GUI_TEXTURED_NO_DEPTH_TRIS.apply(texture)) // TODO: this is strictly an incorrect render layer
val hw = width / 2F
val hh = height / 2F
- val matrix4f: Matrix4f = worldContext.matrixStack.peek().positionMatrix
- 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()
- worldContext.vertexConsumers.draw()
+ val matrix4f: Matrix4f = worldContext.matrixStack.last().pose()
+ buf.addVertex(matrix4f, -hw, -hh, 0F)
+ .setColor(-1)
+ .setUv(u1, v1)
+ buf.addVertex(matrix4f, -hw, +hh, 0F)
+ .setColor(-1)
+ .setUv(u1, v2)
+ buf.addVertex(matrix4f, +hw, +hh, 0F)
+ .setColor(-1)
+ .setUv(u2, v2)
+ buf.addVertex(matrix4f, +hw, -hh, 0F)
+ .setColor(-1)
+ .setUv(u2, v1)
+ worldContext.vertexConsumers.endBatch()
}
}
diff --git a/src/main/kotlin/util/render/FirmamentShaders.kt b/src/main/kotlin/util/render/FirmamentShaders.kt
index ba67dbb..53afdf5 100644
--- a/src/main/kotlin/util/render/FirmamentShaders.kt
+++ b/src/main/kotlin/util/render/FirmamentShaders.kt
@@ -1,30 +1,12 @@
package moe.nea.firmament.util.render
-import net.minecraft.client.gl.Defines
-import net.minecraft.client.gl.ShaderProgramKey
-import net.minecraft.client.render.RenderPhase
-import net.minecraft.client.render.VertexFormat
-import net.minecraft.client.render.VertexFormats
-import moe.nea.firmament.Firmament
import moe.nea.firmament.annotations.Subscribe
import moe.nea.firmament.events.DebugInstantiateEvent
-import moe.nea.firmament.util.MC
object FirmamentShaders {
- val shaders = mutableListOf<ShaderProgramKey>()
-
- private fun shader(name: String, format: VertexFormat, defines: Defines): ShaderProgramKey {
- val key = ShaderProgramKey(Firmament.identifier(name), format, defines)
- shaders.add(key)
- return key
- }
-
- val LINES = RenderPhase.ShaderProgram(shader("core/rendertype_lines", VertexFormats.LINES, Defines.EMPTY))
@Subscribe
fun debugLoad(event: DebugInstantiateEvent) {
- shaders.forEach {
- MC.instance.shaderLoader.getOrCreateProgram(it)
- }
+ // TODO: do i still need to work with shaders like this?
}
}
diff --git a/src/main/kotlin/util/render/LerpUtils.kt b/src/main/kotlin/util/render/LerpUtils.kt
index f2c2f25..e7f226c 100644
--- a/src/main/kotlin/util/render/LerpUtils.kt
+++ b/src/main/kotlin/util/render/LerpUtils.kt
@@ -1,33 +1,40 @@
-
package moe.nea.firmament.util.render
import me.shedaniel.math.Color
+import kotlin.math.absoluteValue
-val pi = Math.PI
-val tau = Math.PI * 2
+val π = Math.PI
+val τ = 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()
+ // TODO: there is at least 10 mods to many in here lol
+ if (((b - a).absoluteValue - π).absoluteValue < 0.0001) {
+ return lerp(a, b, progress)
+ }
+ val shortestAngle = ((((b.mod(τ) - a.mod(τ)).mod(τ)) + τ + π).mod(τ)) - π
+ return ((a + (shortestAngle) * progress).mod(τ)).toFloat()
}
+fun wrapAngle(angle: Float): Float = (angle.mod(τ) + τ).mod(τ).toFloat()
+fun wrapAngle(angle: Double): Double = (angle.mod(τ) + τ).mod(τ)
+
fun lerp(a: Float, b: Float, progress: Float): Float {
- return a + (b - a) * progress
+ return a + (b - a) * progress
}
+
fun lerp(a: Int, b: Int, progress: Float): Int {
- return (a + (b - a) * progress).toInt()
+ return (a + (b - a) * progress).toInt()
}
fun ilerp(a: Float, b: Float, value: Float): Float {
- return (value - a) / (b - a)
+ 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),
- )
+ 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/MultiSpecialGuiRenderState.kt b/src/main/kotlin/util/render/MultiSpecialGuiRenderState.kt
new file mode 100644
index 0000000..a58ffdc
--- /dev/null
+++ b/src/main/kotlin/util/render/MultiSpecialGuiRenderState.kt
@@ -0,0 +1,47 @@
+package moe.nea.firmament.util.render
+
+import net.minecraft.client.gui.navigation.ScreenRectangle
+import net.minecraft.client.gui.render.pip.PictureInPictureRenderer
+import net.minecraft.client.gui.render.state.GuiRenderState
+import net.minecraft.client.gui.render.state.pip.PictureInPictureRenderState
+import net.minecraft.client.renderer.MultiBufferSource
+
+abstract class MultiSpecialGuiRenderState : PictureInPictureRenderState {
+ // I wish i had manifolds @Self type here... Maybe i should switch to java after all :(
+ abstract fun createRenderer(vertexConsumers: MultiBufferSource.BufferSource): MultiSpecialGuiRenderer<out MultiSpecialGuiRenderState>
+ abstract val x1: Int
+ abstract val x2: Int
+ abstract val y1: Int
+ abstract val y2: Int
+ abstract val scale: Float
+ abstract val bounds: ScreenRectangle?
+ abstract val scissorArea: ScreenRectangle?
+ override fun x0(): Int = x1
+
+ override fun x1(): Int = x2
+
+ override fun y0(): Int = y1
+
+ override fun y1(): Int = y2
+
+ override fun scale(): Float = scale
+
+ override fun scissorArea(): ScreenRectangle? = scissorArea
+
+ override fun bounds(): ScreenRectangle? = bounds
+
+}
+
+abstract class MultiSpecialGuiRenderer<T : MultiSpecialGuiRenderState>(
+ vertexConsumers: MultiBufferSource.BufferSource
+) : PictureInPictureRenderer<T>(vertexConsumers) {
+ var wasUsedThisFrame = false
+ fun consumeRender(): Boolean {
+ return wasUsedThisFrame.also { wasUsedThisFrame = false }
+ }
+
+ override fun blitTexture(element: T, state: GuiRenderState) {
+ wasUsedThisFrame = true
+ super.blitTexture(element, state)
+ }
+}
diff --git a/src/main/kotlin/util/render/RenderCircleProgress.kt b/src/main/kotlin/util/render/RenderCircleProgress.kt
index 805633c..acd0210 100644
--- a/src/main/kotlin/util/render/RenderCircleProgress.kt
+++ b/src/main/kotlin/util/render/RenderCircleProgress.kt
@@ -1,93 +1,166 @@
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.RenderLayer
-import net.minecraft.client.render.RenderPhase
-import net.minecraft.client.render.Tessellator
-import net.minecraft.client.render.VertexFormat.DrawMode
-import net.minecraft.client.render.VertexFormats
-import net.minecraft.util.Identifier
+import com.mojang.blaze3d.vertex.VertexFormat
+import util.render.CustomRenderLayers
+import net.minecraft.client.gui.GuiGraphics
+import net.minecraft.client.gui.navigation.ScreenRectangle
+import com.mojang.blaze3d.vertex.BufferBuilder
+import net.minecraft.client.renderer.RenderType
+import net.minecraft.client.renderer.MultiBufferSource
+import com.mojang.blaze3d.vertex.ByteBufferBuilder
+import com.mojang.blaze3d.vertex.PoseStack
+import net.minecraft.resources.ResourceLocation
+import moe.nea.firmament.util.MC
+import moe.nea.firmament.util.collections.nonNegligibleSubSectionsAlignedWith
+import moe.nea.firmament.util.math.Projections
+import moe.nea.firmament.util.mc.CustomRenderPassHelper
object RenderCircleProgress {
- fun renderCircle(
- drawContext: DrawContext,
- texture: Identifier,
- progress: Float,
- u1: Float,
- u2: Float,
- v1: Float,
- v2: Float,
- ) {
- RenderSystem.enableBlend()
- drawContext.draw {
- val bufferBuilder = it.getBuffer(GuiRenderLayers.GUI_TEXTURED_TRIS.apply(texture))
- val matrix: Matrix4f = drawContext.matrices.peek().positionMatrix
-
- 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
+ data class State(
+ override val x1: Int,
+ override val x2: Int,
+ override val y1: Int,
+ override val y2: Int,
+ val layer: RenderType.CompositeRenderType,
+ val u1: Float,
+ val u2: Float,
+ val v1: Float,
+ val v2: Float,
+ val angleRadians: ClosedFloatingPointRange<Float>,
+ val color: Int,
+ val innerCutoutRadius: Float,
+ override val scale: Float,
+ override val bounds: ScreenRectangle?,
+ override val scissorArea: ScreenRectangle?,
+ ) : MultiSpecialGuiRenderState() {
+ override fun createRenderer(vertexConsumers: MultiBufferSource.BufferSource): MultiSpecialGuiRenderer<out MultiSpecialGuiRenderState> {
+ return Renderer(vertexConsumers)
+ }
+ }
+
+ class Renderer(vertexConsumers: MultiBufferSource.BufferSource) :
+ MultiSpecialGuiRenderer<State>(vertexConsumers) {
+ override fun renderToTexture(
+ state: State,
+ matrices: PoseStack
+ ) {
+ matrices.pushPose()
+ matrices.translate(0F, -1F, 0F)
+ val sections = state.angleRadians.nonNegligibleSubSectionsAlignedWith((τ / 8f).toFloat())
+ .zipWithNext().toList()
+ val u1 = state.u1
+ val u2 = state.u2
+ val v1 = state.v1
+ val v2 = state.v2
+ val color = state.color
+ val matrix = matrices.last().pose()
+ ByteBufferBuilder(state.layer.format().vertexSize * sections.size * 3).use { allocator ->
+
+ val bufferBuilder = BufferBuilder(allocator, VertexFormat.Mode.TRIANGLES, state.layer.format())
+
+ for ((sectionStart, sectionEnd) in sections) {
+ val firstPoint = Projections.Two.projectAngleOntoUnitBox(sectionStart.toDouble())
+ val secondPoint = Projections.Two.projectAngleOntoUnitBox(sectionEnd.toDouble())
+ fun ilerp(f: Float): Float =
+ ilerp(-1f, 1f, f)
+
+ bufferBuilder
+ .addVertex(matrix, secondPoint.x, secondPoint.y, 0F)
+ .setUv(lerp(u1, u2, ilerp(secondPoint.x)), lerp(v1, v2, ilerp(secondPoint.y)))
+ .setColor(color)
+
+ bufferBuilder
+ .addVertex(matrix, firstPoint.x, firstPoint.y, 0F)
+ .setUv(lerp(u1, u2, ilerp(firstPoint.x)), lerp(v1, v2, ilerp(firstPoint.y)))
+ .setColor(color)
+
+ bufferBuilder
+ .addVertex(matrix, 0F, 0F, 0F)
+ .setUv(lerp(u1, u2, ilerp(0F)), lerp(v1, v2, ilerp(0F)))
+ .setColor(color)
+
}
- 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)
+
+ bufferBuilder.buildOrThrow().use { buffer ->
+ if (state.innerCutoutRadius <= 0) {
+ state.layer.draw(buffer)
+ return
+ }
+ CustomRenderPassHelper(
+ { "RenderCircleProgress" },
+ VertexFormat.Mode.TRIANGLES,
+ state.layer.format(),
+ MC.instance.mainRenderTarget,
+ false,
+ ).use { renderPass ->
+ renderPass.uploadVertices(buffer)
+ renderPass.setAllDefaultUniforms()
+ renderPass.setPipeline(state.layer.renderPipeline)
+ renderPass.setUniform("CutoutRadius", 4) {
+ it.putFloat(state.innerCutoutRadius)
+ }
+ renderPass.draw()
}
}
-
- 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()
}
+ matrices.popPose()
+ }
+
+ override fun getRenderStateClass(): Class<State> {
+ return State::class.java
+ }
+
+ override fun getTextureLabel(): String {
+ return "Firmament Circle"
}
- RenderSystem.disableBlend()
}
+ fun renderCircularSlice(
+ drawContext: GuiGraphics,
+ layer: RenderType.CompositeRenderType,
+ u1: Float,
+ u2: Float,
+ v1: Float,
+ v2: Float,
+ angleRadians: ClosedFloatingPointRange<Float>,
+ color: Int = -1,
+ innerCutoutRadius: Float = 0F
+ ) {
+ val screenRect = ScreenRectangle(-1, -1, 2, 2).transformAxisAligned(drawContext.pose())
+ drawContext.guiRenderState.submitPicturesInPictureState(
+ State(
+ screenRect.left(), screenRect.right(),
+ screenRect.top(), screenRect.bottom(),
+ layer,
+ u1, u2, v1, v2,
+ angleRadians,
+ color,
+ innerCutoutRadius,
+ screenRect.width / 2F,
+ screenRect,
+ null
+ )
+ )
+ }
+ fun renderCircle(
+ drawContext: GuiGraphics,
+ texture: ResourceLocation,
+ progress: Float,
+ u1: Float,
+ u2: Float,
+ v1: Float,
+ v2: Float,
+ color: Int = -1
+ ) {
+ renderCircularSlice(
+ drawContext,
+ CustomRenderLayers.GUI_TEXTURED_NO_DEPTH_TRIS.apply(texture),
+ u1, u2, v1, v2,
+ (-τ / 4).toFloat()..(progress * τ - τ / 4).toFloat(),
+ color = color
+ )
+ }
}
diff --git a/src/main/kotlin/util/render/RenderInWorldContext.kt b/src/main/kotlin/util/render/RenderInWorldContext.kt
index bb58200..f6877c8 100644
--- a/src/main/kotlin/util/render/RenderInWorldContext.kt
+++ b/src/main/kotlin/util/render/RenderInWorldContext.kt
@@ -1,89 +1,80 @@
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.Camera
-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.VertexConsumer
-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 util.render.CustomRenderLayers
+import kotlin.math.pow
+import net.minecraft.client.Camera
+import net.minecraft.client.renderer.RenderType
+import net.minecraft.client.renderer.ItemBlockRenderTypes
+import net.minecraft.client.DeltaTracker
+import net.minecraft.client.renderer.Sheets
+import com.mojang.blaze3d.vertex.VertexConsumer
+import net.minecraft.client.renderer.MultiBufferSource
+import net.minecraft.client.renderer.state.CameraRenderState
+import net.minecraft.client.renderer.texture.TextureAtlasSprite
+import com.mojang.blaze3d.vertex.PoseStack
+import net.minecraft.network.chat.Component
+import net.minecraft.resources.ResourceLocation
+import net.minecraft.core.BlockPos
+import net.minecraft.world.phys.AABB
+import net.minecraft.world.phys.Vec3
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,
+ val matrixStack: PoseStack,
+ private val camera: CameraRenderState,
+ val vertexConsumers: MultiBufferSource.BufferSource,
) {
-
- object RenderLayers {
- val TRANSLUCENT_TRIS = RenderLayer.of("firmament_translucent_tris",
- VertexFormats.POSITION_COLOR,
- VertexFormat.DrawMode.TRIANGLES,
- RenderLayer.CUTOUT_BUFFER_SIZE,
- false, true,
- RenderLayer.MultiPhaseParameters.builder()
- .depthTest(RenderPhase.ALWAYS_DEPTH_TEST)
- .transparency(RenderPhase.TRANSLUCENT_TRANSPARENCY)
- .program(RenderPhase.POSITION_COLOR_PROGRAM)
- .build(false))
- val LINES = RenderLayer.of("firmament_rendertype_lines",
- VertexFormats.LINES,
- VertexFormat.DrawMode.LINES,
- RenderLayer.CUTOUT_BUFFER_SIZE,
- false, false, // do we need translucent? i dont think so
- RenderLayer.MultiPhaseParameters.builder()
- .depthTest(RenderPhase.ALWAYS_DEPTH_TEST)
- .program(FirmamentShaders.LINES)
- .build(false)
- )
- val COLORED_QUADS = RenderLayer.of(
- "firmament_quads",
- VertexFormats.POSITION_COLOR,
- VertexFormat.DrawMode.QUADS,
- RenderLayer.CUTOUT_BUFFER_SIZE,
- false, true,
- RenderLayer.MultiPhaseParameters.builder()
- .depthTest(RenderPhase.ALWAYS_DEPTH_TEST)
- .program(RenderPhase.POSITION_COLOR_PROGRAM)
- .transparency(RenderPhase.TRANSLUCENT_TRANSPARENCY)
- .build(false)
- )
- }
-
- @Deprecated("stateful color management is no longer a thing")
- fun color(color: me.shedaniel.math.Color) {
- color(color.red / 255F, color.green / 255f, color.blue / 255f, color.alpha / 255f)
+ fun block(blockPos: BlockPos, color: Int) {
+ matrixStack.pushPose()
+ matrixStack.translate(blockPos.x.toFloat(), blockPos.y.toFloat(), blockPos.z.toFloat())
+ buildCube(matrixStack.last().pose(), vertexConsumers.getBuffer(CustomRenderLayers.COLORED_QUADS), color)
+ matrixStack.popPose()
}
- @Deprecated("stateful color management is no longer a thing")
- fun color(red: Float, green: Float, blue: Float, alpha: Float) {
- RenderSystem.setShaderColor(red, green, blue, alpha)
+ fun box(aabb: AABB, color: Int) {
+ matrixStack.pushPose()
+ matrixStack.translate(aabb.minX, aabb.minY, aabb.minZ)
+ matrixStack.scale(aabb.xsize.toFloat(), aabb.ysize.toFloat(), aabb.zsize.toFloat())
+ buildCube(matrixStack.last().pose(), vertexConsumers.getBuffer(CustomRenderLayers.COLORED_QUADS), color)
+ matrixStack.popPose()
}
- fun block(blockPos: BlockPos, color: Int) {
- matrixStack.push()
- matrixStack.translate(blockPos.x.toFloat(), blockPos.y.toFloat(), blockPos.z.toFloat())
- buildCube(matrixStack.peek().positionMatrix, vertexConsumers.getBuffer(RenderLayers.COLORED_QUADS), color)
- matrixStack.pop()
+ fun sharedVoxelSurface(blocks: Set<BlockPos>, color: Int) {
+ val m = BlockPos.MutableBlockPos()
+ val l = vertexConsumers.getBuffer(CustomRenderLayers.COLORED_QUADS)
+ blocks.forEach {
+ matrixStack.pushPose()
+ matrixStack.translate(it.x.toFloat(), it.y.toFloat(), it.z.toFloat())
+ val p = matrixStack.last().pose()
+ m.set(it)
+ if (m.setX(it.x + 1) !in blocks) {
+ buildFaceXP(p, l, color)
+ }
+ if (m.setX(it.x - 1) !in blocks) {
+ buildFaceXN(p, l, color)
+ }
+ m.set(it)
+ if (m.setY(it.y + 1) !in blocks) {
+ buildFaceYP(p, l, color)
+ }
+ if (m.setY(it.y - 1) !in blocks) {
+ buildFaceYN(p, l, color)
+ }
+ m.set(it)
+ if (m.setZ(it.z + 1) !in blocks) {
+ buildFaceZP(p, l, color)
+ }
+ if (m.setZ(it.z - 1) !in blocks) {
+ buildFaceZN(p, l, color)
+ }
+ matrixStack.popPose()
+ }
}
enum class VerticalAlign {
@@ -91,46 +82,46 @@ class RenderInWorldContext private constructor(
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())
+ CENTER -> (index - count / 2F) * (1 + MC.font.lineHeight.toFloat())
+ BOTTOM -> (index - count) * (1 + MC.font.lineHeight.toFloat())
+ TOP -> (index) * (1 + MC.font.lineHeight.toFloat())
}
}
}
- fun waypoint(position: BlockPos, vararg label: Text) {
+ fun waypoint(position: BlockPos, vararg label: Component) {
text(
- position.toCenterPos(),
+ position.center,
*label,
- Text.literal("§e${FirmFormatters.formatDistance(MC.player?.pos?.distanceTo(position.toCenterPos()) ?: 42069.0)}"),
+ Component.literal("§e${FirmFormatters.formatDistance(MC.player?.position?.distanceTo(position.center) ?: 42069.0)}"),
background = 0xAA202020.toInt()
)
}
- fun withFacingThePlayer(position: Vec3d, block: FacingThePlayerContext.() -> Unit) {
- matrixStack.push()
+ fun withFacingThePlayer(position: Vec3, block: FacingThePlayerContext.() -> Unit) {
+ matrixStack.pushPose()
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)
+ val vec = position.subtract(camera.pos).scale(distanceToMoveTowardsCamera / actualCameraDistance)
matrixStack.translate(vec.x, vec.y, vec.z)
- matrixStack.multiply(camera.rotation)
+ matrixStack.mulPose(camera.orientation)
matrixStack.scale(0.025F, -0.025F, 1F)
FacingThePlayerContext(this).run(block)
- matrixStack.pop()
- vertexConsumers.drawCurrentLayer()
+ matrixStack.popPose()
+ vertexConsumers.endLastBatch()
}
- fun sprite(position: Vec3d, sprite: Sprite, width: Int, height: Int) {
+ fun sprite(position: Vec3, sprite: TextureAtlasSprite, width: Int, height: Int) {
texture(
- position, sprite.atlasId, width, height, sprite.minU, sprite.minV, sprite.maxU, sprite.maxV
+ position, sprite.atlasLocation(), width, height, sprite.u0, sprite.v0, sprite.u1, sprite.v1
)
}
fun texture(
- position: Vec3d, texture: Identifier, width: Int, height: Int,
+ position: Vec3, texture: ResourceLocation, width: Int, height: Int,
u1: Float, v1: Float,
u2: Float, v2: Float,
) {
@@ -140,8 +131,8 @@ class RenderInWorldContext private constructor(
}
fun text(
- position: Vec3d,
- vararg texts: Text,
+ position: Vec3,
+ vararg texts: Component,
verticalAlign: VerticalAlign = VerticalAlign.CENTER,
background: Int = 0x70808080
) {
@@ -150,42 +141,50 @@ class RenderInWorldContext private constructor(
}
}
- fun tinyBlock(vec3d: Vec3d, size: Float, color: Int) {
- matrixStack.push()
+ fun tinyBlock(vec3d: Vec3, size: Float, color: Int) {
+ matrixStack.pushPose()
matrixStack.translate(vec3d.x, vec3d.y, vec3d.z)
matrixStack.scale(size, size, size)
matrixStack.translate(-.5, -.5, -.5)
- buildCube(matrixStack.peek().positionMatrix, vertexConsumers.getBuffer(RenderLayers.COLORED_QUADS), color)
- matrixStack.pop()
- vertexConsumers.draw()
+ buildCube(matrixStack.last().pose(), vertexConsumers.getBuffer(CustomRenderLayers.COLORED_QUADS), color)
+ matrixStack.popPose()
+ vertexConsumers.endBatch()
}
fun wireframeCube(blockPos: BlockPos, lineWidth: Float = 10F) {
- val buf = vertexConsumers.getBuffer(RenderLayer.LINES)
- matrixStack.push()
+ val buf = vertexConsumers.getBuffer(RenderType.LINES)
+ matrixStack.pushPose()
+ // TODO: add color arg to this
// TODO: this does not render through blocks (or water layers) anymore
- 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(), buf)
- matrixStack.pop()
- vertexConsumers.draw()
+ RenderSystem.lineWidth(lineWidth / camera.pos.distanceToSqr(blockPos.center).pow(0.25).toFloat())
+ val offset = 1 / 512F
+ matrixStack.translate(
+ blockPos.x.toFloat() - offset,
+ blockPos.y.toFloat() - offset,
+ blockPos.z.toFloat() - offset
+ )
+ val scale = 1 + 2 * offset
+ matrixStack.scale(scale, scale, scale)
+
+ buildWireFrameCube(matrixStack.last(), buf)
+ matrixStack.popPose()
+ vertexConsumers.endBatch()
}
- fun line(vararg points: Vec3d, lineWidth: Float = 10F) {
- line(points.toList(), lineWidth)
+ fun line(vararg points: Vec3, color: Int, lineWidth: Float = 10F) {
+ line(points.toList(), color, 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 tracer(toWhere: Vec3, color: Int, lineWidth: Float = 3f) {
+ val cameraForward = Vector3f(0f, 0f, -1f).rotate(camera.orientation)
+ line(camera.pos.add(Vec3(cameraForward)), toWhere, color = color, lineWidth = lineWidth)
}
- fun line(points: List<Vec3d>, lineWidth: Float = 10F) {
+ fun line(points: List<Vec3>, color: Int, lineWidth: Float = 10F) {
RenderSystem.lineWidth(lineWidth)
- // TODO: replace with renderlayers
- val buffer = tesselator.begin(VertexFormat.DrawMode.LINES, VertexFormats.LINES)
+ val buffer = vertexConsumers.getBuffer(CustomRenderLayers.LINES)
- val matrix = matrixStack.peek()
+ val matrix = matrixStack.last()
var lastNormal: Vector3f? = null
points.zipWithNext().forEach { (a, b) ->
val normal = Vector3f(b.x.toFloat(), b.y.toFloat(), b.z.toFloat())
@@ -193,23 +192,22 @@ class RenderInWorldContext private constructor(
.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()
+ buffer.addVertex(matrix.pose(), a.x.toFloat(), a.y.toFloat(), a.z.toFloat())
+ .setColor(color)
+ .setNormal(matrix, lastNormal0.x, lastNormal0.y, lastNormal0.z)
+
+ buffer.addVertex(matrix.pose(), b.x.toFloat(), b.y.toFloat(), b.z.toFloat())
+ .setColor(color)
+ .setNormal(matrix, normal.x, normal.y, normal.z)
+
}
- RenderLayers.LINES.draw(buffer.end())
}
// TODO: put the favourite icons in front of items again
companion object {
private fun doLine(
- matrix: MatrixStack.Entry,
+ matrix: PoseStack.Pose,
buf: VertexConsumer,
i: Float,
j: Float,
@@ -221,18 +219,18 @@ class RenderInWorldContext private constructor(
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()
+ buf.addVertex(matrix.pose(), i, j, k)
+ .setNormal(matrix, normal.x, normal.y, normal.z)
+ .setColor(-1)
+
+ buf.addVertex(matrix.pose(), x, y, z)
+ .setNormal(matrix, normal.x, normal.y, normal.z)
+ .setColor(-1)
+
}
- private fun buildWireFrameCube(matrix: MatrixStack.Entry, buf: VertexConsumer) {
+ private fun buildWireFrameCube(matrix: PoseStack.Pose, buf: VertexConsumer) {
for (i in 0..1) {
for (j in 0..1) {
val i = i.toFloat()
@@ -244,68 +242,72 @@ class RenderInWorldContext private constructor(
}
}
- private fun buildCube(matrix: Matrix4f, buf: VertexConsumer, color: Int) {
- // Y-
- buf.vertex(matrix, 0F, 0F, 0F).color(color)
- buf.vertex(matrix, 0F, 0F, 1F).color(color)
- buf.vertex(matrix, 1F, 0F, 1F).color(color)
- buf.vertex(matrix, 1F, 0F, 0F).color(color)
- // Y+
- buf.vertex(matrix, 0F, 1F, 0F).color(color)
- buf.vertex(matrix, 1F, 1F, 0F).color(color)
- buf.vertex(matrix, 1F, 1F, 1F).color(color)
- buf.vertex(matrix, 0F, 1F, 1F).color(color)
- // X-
- buf.vertex(matrix, 0F, 0F, 0F).color(color)
- buf.vertex(matrix, 0F, 0F, 1F).color(color)
- buf.vertex(matrix, 0F, 1F, 1F).color(color)
- buf.vertex(matrix, 0F, 1F, 0F).color(color)
- // X+
- buf.vertex(matrix, 1F, 0F, 0F).color(color)
- buf.vertex(matrix, 1F, 1F, 0F).color(color)
- buf.vertex(matrix, 1F, 1F, 1F).color(color)
- buf.vertex(matrix, 1F, 0F, 1F).color(color)
- // Z-
- buf.vertex(matrix, 0F, 0F, 0F).color(color)
- buf.vertex(matrix, 1F, 0F, 0F).color(color)
- buf.vertex(matrix, 1F, 1F, 0F).color(color)
- buf.vertex(matrix, 0F, 1F, 0F).color(color)
- // Z+
- buf.vertex(matrix, 0F, 0F, 1F).color(color)
- buf.vertex(matrix, 0F, 1F, 1F).color(color)
- buf.vertex(matrix, 1F, 1F, 1F).color(color)
- buf.vertex(matrix, 1F, 0F, 1F).color(color)
+ private fun buildFaceZP(matrix: Matrix4f, buf: VertexConsumer, rgba: Int) {
+ buf.addVertex(matrix, 0F, 0F, 1F).setColor(rgba)
+ buf.addVertex(matrix, 0F, 1F, 1F).setColor(rgba)
+ buf.addVertex(matrix, 1F, 1F, 1F).setColor(rgba)
+ buf.addVertex(matrix, 1F, 0F, 1F).setColor(rgba)
}
+ private fun buildFaceZN(matrix: Matrix4f, buf: VertexConsumer, rgba: Int) {
+ buf.addVertex(matrix, 0F, 0F, 0F).setColor(rgba)
+ buf.addVertex(matrix, 1F, 0F, 0F).setColor(rgba)
+ buf.addVertex(matrix, 1F, 1F, 0F).setColor(rgba)
+ buf.addVertex(matrix, 0F, 1F, 0F).setColor(rgba)
+ }
+
+ private fun buildFaceXP(matrix: Matrix4f, buf: VertexConsumer, rgba: Int) {
+ buf.addVertex(matrix, 1F, 0F, 0F).setColor(rgba)
+ buf.addVertex(matrix, 1F, 1F, 0F).setColor(rgba)
+ buf.addVertex(matrix, 1F, 1F, 1F).setColor(rgba)
+ buf.addVertex(matrix, 1F, 0F, 1F).setColor(rgba)
+ }
+
+ private fun buildFaceXN(matrix: Matrix4f, buf: VertexConsumer, rgba: Int) {
+ buf.addVertex(matrix, 0F, 0F, 0F).setColor(rgba)
+ buf.addVertex(matrix, 0F, 0F, 1F).setColor(rgba)
+ buf.addVertex(matrix, 0F, 1F, 1F).setColor(rgba)
+ buf.addVertex(matrix, 0F, 1F, 0F).setColor(rgba)
+ }
+
+ private fun buildFaceYN(matrix: Matrix4f, buf: VertexConsumer, rgba: Int) {
+ buf.addVertex(matrix, 0F, 0F, 0F).setColor(rgba)
+ buf.addVertex(matrix, 0F, 0F, 1F).setColor(rgba)
+ buf.addVertex(matrix, 1F, 0F, 1F).setColor(rgba)
+ buf.addVertex(matrix, 1F, 0F, 0F).setColor(rgba)
+ }
+
+ private fun buildFaceYP(matrix: Matrix4f, buf: VertexConsumer, rgba: Int) {
+ buf.addVertex(matrix, 0F, 1F, 0F).setColor(rgba)
+ buf.addVertex(matrix, 1F, 1F, 0F).setColor(rgba)
+ buf.addVertex(matrix, 1F, 1F, 1F).setColor(rgba)
+ buf.addVertex(matrix, 0F, 1F, 1F).setColor(rgba)
+ }
+
+ private fun buildCube(matrix4f: Matrix4f, buf: VertexConsumer, rgba: Int) {
+ buildFaceXP(matrix4f, buf, rgba)
+ buildFaceXN(matrix4f, buf, rgba)
+ buildFaceYP(matrix4f, buf, rgba)
+ buildFaceYN(matrix4f, buf, rgba)
+ buildFaceZP(matrix4f, buf, rgba)
+ buildFaceZN(matrix4f, buf, rgba)
+ }
fun renderInWorld(event: WorldRenderLastEvent, block: RenderInWorldContext. () -> Unit) {
- // TODO: there should be *no more global state*. the only thing we should be doing is render layers. that includes settings like culling, blending, shader color, and depth testing
- // For now i will let these functions remain, but this needs to go before i do a full (non-beta) release
- RenderSystem.disableDepthTest()
- RenderSystem.enableBlend()
- RenderSystem.defaultBlendFunc()
- RenderSystem.disableCull()
-
- event.matrices.push()
+
+ event.matrices.pushPose()
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()
- event.vertexConsumers.draw()
- RenderSystem.setShaderColor(1F, 1F, 1F, 1F)
- VertexBuffer.unbind()
- RenderSystem.enableDepthTest()
- RenderSystem.enableCull()
- RenderSystem.disableBlend()
+ event.matrices.popPose()
+ event.vertexConsumers.endBatch()
}
}
}
diff --git a/src/main/kotlin/util/render/TintedOverlayTexture.kt b/src/main/kotlin/util/render/TintedOverlayTexture.kt
index a02eccc..6513574 100644
--- a/src/main/kotlin/util/render/TintedOverlayTexture.kt
+++ b/src/main/kotlin/util/render/TintedOverlayTexture.kt
@@ -1,10 +1,8 @@
package moe.nea.firmament.util.render
-import com.mojang.blaze3d.platform.GlConst
-import com.mojang.blaze3d.systems.RenderSystem
import me.shedaniel.math.Color
-import net.minecraft.client.render.OverlayTexture
-import net.minecraft.util.math.ColorHelper
+import net.minecraft.client.renderer.texture.OverlayTexture
+import net.minecraft.util.ARGB
import moe.nea.firmament.util.ErrorUtil
class TintedOverlayTexture : OverlayTexture() {
@@ -14,31 +12,24 @@ class TintedOverlayTexture : OverlayTexture() {
private var lastColor: Color? = null
fun setColor(color: Color): TintedOverlayTexture {
- val image = ErrorUtil.notNullOr(texture.image, "Disposed TintedOverlayTexture written to") { return this }
+ val image = ErrorUtil.notNullOr(texture.pixels, "Disposed TintedOverlayTexture written to") { return this }
if (color == lastColor) return this
lastColor = color
for (i in 0..<size) {
for (j in 0..<size) {
if (i < 8) {
- image.setColorArgb(j, i, 0xB2FF0000.toInt())
+ image.setPixel(j, i, 0xB2FF0000.toInt())
} else {
val k = ((1F - j / 15F * 0.75F) * 255F).toInt()
- image.setColorArgb(j, i, ColorHelper.withAlpha(k, color.color))
+ image.setPixel(j, i, ARGB.color(k, color.color))
}
}
}
- RenderSystem.activeTexture(GlConst.GL_TEXTURE1)
- texture.bindTexture()
texture.setFilter(false, false)
texture.setClamp(true)
- image.upload(0,
- 0, 0,
- 0, 0,
- image.width, image.height,
- false)
- RenderSystem.activeTexture(GlConst.GL_TEXTURE0)
+ texture.upload()
return this
}
}
diff --git a/src/main/kotlin/util/render/TranslatedScissors.kt b/src/main/kotlin/util/render/TranslatedScissors.kt
index 8f8bdcf..e337cf0 100644
--- a/src/main/kotlin/util/render/TranslatedScissors.kt
+++ b/src/main/kotlin/util/render/TranslatedScissors.kt
@@ -1,26 +1,31 @@
-
package moe.nea.firmament.util.render
-import org.joml.Matrix4f
-import org.joml.Vector4f
-import net.minecraft.client.gui.DrawContext
+import me.shedaniel.math.Rectangle
+import org.joml.Matrix3x2f
+import org.joml.Vector3f
+import net.minecraft.client.gui.GuiGraphics
+
+fun GuiGraphics.enableScissorWithTranslation(rect: Rectangle) {
+ enableScissor(rect.minX, rect.minY, rect.maxX, rect.maxY)
+}
-fun DrawContext.enableScissorWithTranslation(x1: Float, y1: Float, x2: Float, y2: Float) {
- enableScissor(x1.toInt(), y1.toInt(), x2.toInt(), y2.toInt())
+fun GuiGraphics.enableScissorWithTranslation(x1: Float, y1: Float, x2: Float, y2: Float) {
+ enableScissor(x1.toInt(), y1.toInt(), x2.toInt(), y2.toInt())
}
-fun DrawContext.enableScissorWithoutTranslation(x1: Float, y1: Float, x2: Float, y2: Float) {
- val pMat = matrices.peek().positionMatrix.invert(Matrix4f())
- val target = Vector4f()
- target.set(x1, y1, 0f, 1f)
- target.mul(pMat)
- val scissorX1 = target.x
- val scissorY1 = target.y
+fun GuiGraphics.enableScissorWithoutTranslation(x1: Float, y1: Float, x2: Float, y2: Float) {
+ val pMat = Matrix3x2f(pose()).invert()
+ var target = Vector3f()
+
+ target.set(x1, y1, 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
+ target.set(x2, y2, 1F)
+ target.mul(pMat)
+ val scissorX2 = target.x
+ val scissorY2 = target.y
- enableScissor(scissorX1.toInt(), scissorY1.toInt(), scissorX2.toInt(), scissorY2.toInt())
+ enableScissor(scissorX1.toInt(), scissorY1.toInt(), scissorX2.toInt(), scissorY2.toInt())
}