aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVixid <52578495+VixidDev@users.noreply.github.com>2024-02-19 15:02:49 +0000
committerGitHub <noreply@github.com>2024-02-19 16:02:49 +0100
commit35df2ab2aa2056b61034757fe61554e7075dedd1 (patch)
tree634d4bbd47bb7fc8bc680d884a638d566059300e
parentb065fc1113977529831be5eab587c1612efdde79 (diff)
downloadskyhanni-35df2ab2aa2056b61034757fe61554e7075dedd1.tar.gz
skyhanni-35df2ab2aa2056b61034757fe61554e7075dedd1.tar.bz2
skyhanni-35df2ab2aa2056b61034757fe61554e7075dedd1.zip
Added support for rendering rounded rectangles. #851
-rw-r--r--src/main/java/at/hannibal2/skyhanni/features/misc/RoundedRectangleShader.kt28
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt40
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/shader/Shader.kt50
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderHelper.kt8
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderManager.kt34
-rw-r--r--src/main/java/at/hannibal2/skyhanni/utils/shader/Uniform.kt10
-rw-r--r--src/main/resources/assets/skyhanni/shaders/rounded_rect.fsh34
-rw-r--r--src/main/resources/assets/skyhanni/shaders/rounded_rect.vsh8
8 files changed, 186 insertions, 26 deletions
diff --git a/src/main/java/at/hannibal2/skyhanni/features/misc/RoundedRectangleShader.kt b/src/main/java/at/hannibal2/skyhanni/features/misc/RoundedRectangleShader.kt
new file mode 100644
index 000000000..6b0ce5e63
--- /dev/null
+++ b/src/main/java/at/hannibal2/skyhanni/features/misc/RoundedRectangleShader.kt
@@ -0,0 +1,28 @@
+package at.hannibal2.skyhanni.features.misc
+
+import at.hannibal2.skyhanni.utils.shader.Shader
+import at.hannibal2.skyhanni.utils.shader.Uniform
+import net.minecraft.client.Minecraft
+
+object RoundedRectangleShader : Shader("rounded_rect", "rounded_rect") {
+
+ val INSTANCE: RoundedRectangleShader
+ get() = this
+
+ var scaleFactor: Float = 0f
+ var radius: Float = 0f
+ var smoothness: Float = 0f
+ var halfSize: FloatArray = floatArrayOf(0f, 0f)
+ var centerPos: FloatArray = floatArrayOf(0f, 0f)
+ set(value) {
+ field = floatArrayOf(value[0], Minecraft.getMinecraft().displayHeight - value[1])
+ }
+
+ override fun registerUniforms() {
+ registerUniform(Uniform.UniformType.FLOAT, "scaleFactor") { scaleFactor }
+ registerUniform(Uniform.UniformType.FLOAT, "radius") { radius }
+ registerUniform(Uniform.UniformType.FLOAT, "smoothness") { smoothness }
+ registerUniform(Uniform.UniformType.VEC2, "halfSize") { halfSize }
+ registerUniform(Uniform.UniformType.VEC2, "centerPos") { centerPos }
+ }
+} \ No newline at end of file
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt b/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt
index 7c26c03e2..193beda2a 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/RenderUtils.kt
@@ -6,14 +6,18 @@ import at.hannibal2.skyhanni.data.GuiEditManager.Companion.getAbsX
import at.hannibal2.skyhanni.data.GuiEditManager.Companion.getAbsY
import at.hannibal2.skyhanni.events.GuiRenderItemEvent
import at.hannibal2.skyhanni.events.LorenzRenderWorldEvent
+import at.hannibal2.skyhanni.features.misc.RoundedRectangleShader
import at.hannibal2.skyhanni.test.command.ErrorManager
import at.hannibal2.skyhanni.utils.renderables.Renderable
import at.hannibal2.skyhanni.utils.renderables.RenderableUtils.renderXAligned
+import at.hannibal2.skyhanni.utils.shader.ShaderManager
import io.github.moulberry.moulconfig.internal.TextRenderUtils
import io.github.moulberry.notenoughupdates.util.Utils
+import java.awt.Color
import net.minecraft.client.Minecraft
import net.minecraft.client.gui.FontRenderer
import net.minecraft.client.gui.Gui
+import net.minecraft.client.gui.ScaledResolution
import net.minecraft.client.renderer.GlStateManager
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
@@ -25,7 +29,6 @@ import net.minecraft.util.AxisAlignedBB
import net.minecraft.util.MathHelper
import net.minecraft.util.ResourceLocation
import org.lwjgl.opengl.GL11
-import java.awt.Color
import kotlin.math.cos
import kotlin.math.sin
import kotlin.math.sqrt
@@ -1130,4 +1133,39 @@ object RenderUtils {
GlStateManager.enableLighting()
GlStateManager.enableDepth()
}
+
+ /**
+ * Method to draw a rounded rectangle.
+ *
+ * **NOTE:** If you are using [GlStateManager.translate] or [GlStateManager.scale]
+ * with this method, ensure they are invoked in the correct order if you use both. That is, [GlStateManager.translate]
+ * is called **BEFORE** [GlStateManager.scale], otherwise the rectangle will not be rendered correctly
+ *
+ * @param color color of rect
+ * @param radius the radius of the corners (default 10)
+ * @param smoothness how smooth the corners will appear (default 2). NOTE: This does very
+ * little to the smoothness of the corners in reality due to how the final pixel color is calculated.
+ * It is best kept at its default.
+ */
+ fun drawRoundRect(x: Int, y: Int, width: Int, height: Int, color: Int, radius: Int = 10, smoothness: Int = 1) {
+ val scaledRes = ScaledResolution(Minecraft.getMinecraft())
+ val widthIn = width * scaledRes.scaleFactor
+ val heightIn = height * scaledRes.scaleFactor
+ val xIn = x * scaledRes.scaleFactor
+ val yIn = y * scaledRes.scaleFactor
+
+ RoundedRectangleShader.scaleFactor = scaledRes.scaleFactor.toFloat()
+ RoundedRectangleShader.radius = radius.toFloat()
+ RoundedRectangleShader.smoothness = smoothness.toFloat()
+ RoundedRectangleShader.halfSize = floatArrayOf(widthIn / 2f, heightIn / 2f)
+ RoundedRectangleShader.centerPos = floatArrayOf(xIn + (widthIn / 2f), yIn + (heightIn / 2f))
+
+ GlStateManager.pushMatrix()
+ ShaderManager.enableShader("rounded_rect")
+
+ Gui.drawRect(x, y, x + width, y + height, color)
+
+ ShaderManager.disableShader()
+ GlStateManager.popMatrix()
+ }
}
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/shader/Shader.kt b/src/main/java/at/hannibal2/skyhanni/utils/shader/Shader.kt
index 7fb13ab86..6a95655ca 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/shader/Shader.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/shader/Shader.kt
@@ -1,10 +1,12 @@
package at.hannibal2.skyhanni.utils.shader
+import at.hannibal2.skyhanni.test.command.ErrorManager
import at.hannibal2.skyhanni.utils.LorenzUtils
+import java.util.function.Supplier
import net.minecraft.client.shader.ShaderLinkHelper
import org.apache.commons.lang3.StringUtils
import org.lwjgl.opengl.GL11
-import java.util.function.Supplier
+import org.lwjgl.opengl.OpenGLException
/**
* Superclass for shader objects to compile and attach vertex and fragment shaders to the shader program
@@ -18,23 +20,39 @@ abstract class Shader(vertex: String, fragment: String) {
var shaderProgram: Int = ShaderLinkHelper.getStaticShaderLinkHelper().createProgram()
private val uniforms: MutableList<Uniform<*>> = mutableListOf()
+ var created = false
+
init {
- val vertexShaderID = ShaderManager.loadShader(ShaderType.VERTEX, vertex)
- ShaderManager.attachShader(shaderProgram, vertexShaderID)
- val fragmentShaderID = ShaderManager.loadShader(ShaderType.FRAGMENT, fragment)
- ShaderManager.attachShader(shaderProgram, fragmentShaderID)
-
- ShaderHelper.glLinkProgram(shaderProgram)
-
- val linkStatus = ShaderHelper.glGetProgrami(shaderProgram, ShaderHelper.GL_LINK_STATUS)
- if (linkStatus == GL11.GL_FALSE) {
- LorenzUtils.consoleLog(
- "Error occurred when linking program with Vertex Shader: $vertex and Fragment Shader: $fragment : " +
- StringUtils.trim(ShaderHelper.glGetProgramInfoLog(shaderProgram, 1024))
- )
- }
+ run {
+ val vertexShaderID = ShaderManager.loadShader(ShaderType.VERTEX, vertex).also { if (it == -1) return@run }
+ ShaderManager.attachShader(shaderProgram, vertexShaderID)
+
+ val fragmentShaderID = ShaderManager.loadShader(ShaderType.FRAGMENT, fragment).also { if (it == -1) return@run }
+ ShaderManager.attachShader(shaderProgram, fragmentShaderID)
- this.registerUniforms()
+ ShaderHelper.glLinkProgram(shaderProgram)
+
+ if (ShaderHelper.glGetProgrami(shaderProgram, ShaderHelper.GL_LINK_STATUS) == GL11.GL_FALSE) {
+ val errorMessage = "Failed to link vertex shader $vertex and fragment shader $fragment. Features that " +
+ "utilise this shader will not work correctly, if at all."
+ val errorLog = StringUtils.trim(ShaderHelper.glGetShaderInfoLog(shaderProgram, 1024))
+
+ if (ShaderManager.inWorld()) {
+ ErrorManager.logErrorWithData(
+ OpenGLException("Shader linking error."),
+ errorMessage,
+ "Link Error:\n" to errorLog
+ )
+ } else {
+ LorenzUtils.consoleLog("$errorMessage $errorLog")
+ }
+
+ return@run
+ }
+
+ this.registerUniforms()
+ created = true
+ }
}
abstract fun registerUniforms()
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderHelper.kt b/src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderHelper.kt
index 6f24d0e89..6e36285b1 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderHelper.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderHelper.kt
@@ -137,6 +137,14 @@ class ShaderHelper {
if (USING_ARB_SHADERS) ARBShaderObjects.glUniform1fARB(location, v0) else GL20.glUniform1f(location, v0)
}
+ fun glUniform2f(location: Int, v0: Float, v1: Float) {
+ if (USING_ARB_SHADERS) ARBShaderObjects.glUniform2fARB(location, v0, v1) else GL20.glUniform2f(
+ location,
+ v0,
+ v1
+ )
+ }
+
fun glUniform3f(location: Int, v0: Float, v1: Float, v2: Float) {
if (USING_ARB_SHADERS) ARBShaderObjects.glUniform3fARB(location, v0, v1, v2) else GL20.glUniform3f(
location,
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderManager.kt b/src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderManager.kt
index 6df5c92f8..f9b5541c5 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderManager.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/shader/ShaderManager.kt
@@ -1,12 +1,15 @@
package at.hannibal2.skyhanni.utils.shader
import at.hannibal2.skyhanni.features.chroma.ChromaShader
+import at.hannibal2.skyhanni.features.misc.RoundedRectangleShader
+import at.hannibal2.skyhanni.test.command.ErrorManager
import at.hannibal2.skyhanni.utils.LorenzUtils
+import java.io.BufferedReader
+import java.io.InputStreamReader
import net.minecraft.client.Minecraft
import net.minecraft.util.ResourceLocation
import org.apache.commons.lang3.StringUtils
-import java.io.BufferedReader
-import java.io.InputStreamReader
+import org.lwjgl.opengl.OpenGLException
/**
* Object to handle shaders for SkyHanni
@@ -19,12 +22,14 @@ object ShaderManager {
*/
enum class Shaders(val shader: Shader) {
- CHROMA(ChromaShader.INSTANCE);
+ CHROMA(ChromaShader.INSTANCE),
+ ROUNDED_RECTANGLE(RoundedRectangleShader.INSTANCE);
companion object {
fun getShaderInstance(shaderName: String): Shader? = when (shaderName) {
"chroma" -> CHROMA.shader
+ "rounded_rect" -> ROUNDED_RECTANGLE.shader
else -> {
null
}
@@ -44,6 +49,8 @@ object ShaderManager {
shaders[shaderName] = shader
}
+ if (!shader.created) return
+
activeShader = shader
shader.enable()
shader.updateUniforms()
@@ -75,14 +82,27 @@ object ShaderManager {
ShaderHelper.glCompileShader(shaderID)
if (ShaderHelper.glGetShaderi(shaderID, ShaderHelper.GL_COMPILE_STATUS) == 0) {
- LorenzUtils.consoleLog(
- "Error occurred when compiling shader $fileName${type.extension} : " +
- StringUtils.trim(ShaderHelper.glGetShaderInfoLog(shaderID, 1024))
- )
+ val errorMessage = "Failed to compile shader $fileName${type.extension}. Features that utilise this " +
+ "shader will not work correctly, if at all."
+ val errorLog = StringUtils.trim(ShaderHelper.glGetShaderInfoLog(shaderID, 1024))
+
+ if (inWorld()) {
+ ErrorManager.logErrorWithData(
+ OpenGLException("Shader compilation error."),
+ errorMessage,
+ "GLSL Compilation Error:\n" to errorLog
+ )
+ } else {
+ LorenzUtils.consoleLog("$errorMessage $errorLog")
+ }
+
+ return -1
}
return shaderID
}
+
+ fun inWorld() = (Minecraft.getMinecraft().theWorld != null) && (Minecraft.getMinecraft().thePlayer != null)
}
enum class ShaderType(val extension: String, val shaderType: Int) {
diff --git a/src/main/java/at/hannibal2/skyhanni/utils/shader/Uniform.kt b/src/main/java/at/hannibal2/skyhanni/utils/shader/Uniform.kt
index c9602d423..496d9c46c 100644
--- a/src/main/java/at/hannibal2/skyhanni/utils/shader/Uniform.kt
+++ b/src/main/java/at/hannibal2/skyhanni/utils/shader/Uniform.kt
@@ -21,6 +21,7 @@ class Uniform<T>(
companion object {
val FLOAT: UniformType<Float> = UniformType()
+ val VEC2: UniformType<FloatArray> = UniformType()
val VEC3: UniformType<FloatArray> = UniformType()
val BOOL: UniformType<Boolean> = UniformType()
}
@@ -33,12 +34,17 @@ class Uniform<T>(
val newUniformValue: T = uniformValuesSupplier.get()
if (!Objects.deepEquals(previousUniformValue, newUniformValue)) {
when (uniformType) {
- UniformType.FLOAT -> ShaderHelper.glUniform1f(uniformID, (newUniformValue as Float))
+ UniformType.FLOAT -> {
+ ShaderHelper.glUniform1f(uniformID, (newUniformValue as Float))
+ }
+ UniformType.VEC2 -> {
+ val values = newUniformValue as FloatArray
+ ShaderHelper.glUniform2f(uniformID, values[0], values[1])
+ }
UniformType.VEC3 -> {
val values = newUniformValue as FloatArray
ShaderHelper.glUniform3f(uniformID, values[0], values[1], values[2])
}
-
UniformType.BOOL -> ShaderHelper.glUniform1f(uniformID, if (newUniformValue as Boolean) 1f else 0f)
}
previousUniformValue = newUniformValue
diff --git a/src/main/resources/assets/skyhanni/shaders/rounded_rect.fsh b/src/main/resources/assets/skyhanni/shaders/rounded_rect.fsh
new file mode 100644
index 000000000..9f3c31786
--- /dev/null
+++ b/src/main/resources/assets/skyhanni/shaders/rounded_rect.fsh
@@ -0,0 +1,34 @@
+#version 130
+
+uniform float scaleFactor;
+uniform float radius;
+uniform float smoothness;
+uniform vec2 halfSize;
+uniform vec2 centerPos;
+
+in vec4 color;
+
+// From https://www.shadertoy.com/view/WtdSDs
+float roundedRectSDF(vec2 center, vec2 halfSize, float radius) {
+ return length(max(abs(center) - halfSize + radius, 0.0)) - radius;
+}
+
+void main() {
+ float xScale = gl_ModelViewMatrix[0][0];
+ float yScale = gl_ModelViewMatrix[1][1];
+ float xTranslation = gl_ModelViewMatrix[3][0];
+ float yTranslation = gl_ModelViewMatrix[3][1];
+
+ vec2 newHalfSize = vec2(halfSize.x * xScale, halfSize.y * yScale);
+
+ float newCenterPosY = centerPos.y;
+ if (yScale > 1.0) {
+ newCenterPosY = centerPos.y - (halfSize.y * (yScale - 1));
+ }
+
+ vec2 newCenterPos = vec2((centerPos.x * xScale) + (xTranslation * scaleFactor), newCenterPosY - (yTranslation * scaleFactor));
+
+ float distance = roundedRectSDF(gl_FragCoord.xy - newCenterPos, newHalfSize, radius);
+ float smoothed = 1.0 - smoothstep(0.0, smoothness, distance);
+ gl_FragColor = color * vec4(1.0, 1.0, 1.0, smoothed);
+} \ No newline at end of file
diff --git a/src/main/resources/assets/skyhanni/shaders/rounded_rect.vsh b/src/main/resources/assets/skyhanni/shaders/rounded_rect.vsh
new file mode 100644
index 000000000..beadbf5fb
--- /dev/null
+++ b/src/main/resources/assets/skyhanni/shaders/rounded_rect.vsh
@@ -0,0 +1,8 @@
+#version 130
+
+out vec4 color;
+
+void main() {
+ gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex;
+ color = gl_Color;
+} \ No newline at end of file