1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
|
package moe.nea.firmament.util.render
import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.VertexFormat
import io.github.notenoughupdates.moulconfig.platform.next
import java.util.OptionalInt
import org.joml.Matrix3x2f
import util.render.CustomRenderLayers
import net.minecraft.client.gui.DrawContext
import net.minecraft.client.render.BufferBuilder
import net.minecraft.client.render.RenderLayer
import net.minecraft.client.util.BufferAllocator
import net.minecraft.util.Identifier
import moe.nea.firmament.util.MC
import moe.nea.firmament.util.collections.nonNegligibleSubSectionsAlignedWith
import moe.nea.firmament.util.math.Projections
object RenderCircleProgress {
fun renderCircularSlice(
drawContext: DrawContext,
layer: RenderLayer.MultiPhase,
u1: Float,
u2: Float,
v1: Float,
v2: Float,
angleRadians: ClosedFloatingPointRange<Float>,
color: Int = -1,
innerCutoutRadius: Float = 0F
) {
val sections = angleRadians.nonNegligibleSubSectionsAlignedWith((τ / 8f).toFloat())
.zipWithNext().toList()
BufferAllocator(layer.vertexFormat.vertexSize * sections.size * 3).use { allocator ->
val bufferBuilder = BufferBuilder(allocator, VertexFormat.DrawMode.TRIANGLES, layer.vertexFormat)
val matrix: Matrix3x2f = drawContext.matrices
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
.vertex(matrix, secondPoint.x, secondPoint.y, 0F)
.texture(lerp(u1, u2, ilerp(secondPoint.x)), lerp(v1, v2, ilerp(secondPoint.y)))
.color(color)
.next()
bufferBuilder
.vertex(matrix, firstPoint.x, firstPoint.y, 0F)
.texture(lerp(u1, u2, ilerp(firstPoint.x)), lerp(v1, v2, ilerp(firstPoint.y)))
.color(color)
.next()
bufferBuilder
.vertex(matrix, 0F, 0F, 0F)
.texture(lerp(u1, u2, ilerp(0F)), lerp(v1, v2, ilerp(0F)))
.color(color)
.next()
}
bufferBuilder.end().use { buffer ->
// TODO: write a better utility to pass uniforms :sob: ill even take a mixin at this point
if (innerCutoutRadius <= 0) {
layer.draw(buffer)
return
}
val vertexBuffer = layer.vertexFormat.uploadImmediateVertexBuffer(buffer.buffer)
val indexBufferConstructor = RenderSystem.getSequentialBuffer(VertexFormat.DrawMode.TRIANGLES)
val indexBuffer = indexBufferConstructor.getIndexBuffer(buffer.drawParameters.indexCount)
RenderSystem.getDevice().createCommandEncoder().createRenderPass(
{ "Firmament Circle Renderer" },
MC.instance.framebuffer.colorAttachmentView,
OptionalInt.empty(),
).use { renderPass ->
renderPass.setPipeline(layer.pipeline)
// renderPass.setUniform("InnerCutoutRadius", innerCutoutRadius)
renderPass.setIndexBuffer(indexBuffer, indexBufferConstructor.indexType)
renderPass.setVertexBuffer(0, vertexBuffer)
renderPass.drawIndexed(0, 0, buffer.drawParameters.indexCount, 1)
}
}
}
}
fun renderCircle(
drawContext: DrawContext,
texture: Identifier,
progress: Float,
u1: Float,
u2: Float,
v1: Float,
v2: Float,
) {
renderCircularSlice(
drawContext,
CustomRenderLayers.GUI_TEXTURED_NO_DEPTH_TRIS.apply(texture),
u1, u2, v1, v2,
(-τ / 4).toFloat()..(progress * τ - τ / 4).toFloat()
)
}
}
|