Skip to content
This repository has been archived by the owner on Apr 22, 2021. It is now read-only.

[enhancement] Font Rendering Optimization #1880

Merged
merged 8 commits into from
Jan 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/main/java/me/zeroeightsix/kami/gui/hudgui/LabelHud.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ abstract class LabelHud(
override fun renderHud(vertexHelper: VertexHelper) {
super.renderHud(vertexHelper)
displayText.draw(
Vec2d((width * dockingH.multiplier).toDouble(), (height * dockingV.multiplier).toDouble()),
Vec2d(width * dockingH.multiplier - 1.0 * dockingH.offset, (height * dockingV.multiplier).toDouble()),
horizontalAlign = dockingH,
verticalAlign = dockingV
)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ open class Slider(
(renderHeight * ClickGUI.getScaleFactor()).roundToInt()
)
}*/
FontRenderAdapter.drawString(name, 2f, 1.0f, color = GuiColors.text)
FontRenderAdapter.drawString(name, 1.5f, 1.0f, color = GuiColors.text)
//GlStateUtils.popScissor()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@ import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import me.zeroeightsix.kami.KamiMod
import me.zeroeightsix.kami.manager.Manager
import me.zeroeightsix.kami.util.Wrapper
import me.zeroeightsix.kami.util.graphics.TextureUtils
import me.zeroeightsix.kami.util.graphics.texture.MipmapTexture
import me.zeroeightsix.kami.util.threads.defaultScope
import net.minecraft.util.ResourceLocation
import org.lwjgl.opengl.GL11.GL_RGBA
import org.lwjgl.opengl.GL11.*
import org.lwjgl.opengl.GL12.GL_CLAMP_TO_EDGE
import org.lwjgl.opengl.GL14.GL_TEXTURE_LOD_BIAS
import java.io.File
import java.io.FileInputStream
import java.io.IOException
Expand All @@ -31,7 +31,7 @@ object KamiMojiManager : Manager {
private const val zipUrl = "https://github.com/2b2t-Utilities/emojis/archive/master.zip"

private val parser = JsonParser()
private val emojiMap = HashMap<String, ResourceLocation>()
private val emojiMap = HashMap<String, MipmapTexture>()
private val fileMap = HashMap<String, File>()

private val job = defaultScope.launch(Dispatchers.IO) {
Expand All @@ -48,7 +48,7 @@ object KamiMojiManager : Manager {
}

directory.listFiles()?.forEach {
if (it.isFile && it.extension == "png" ) {
if (it.isFile && it.extension == "png") {
fileMap[it.nameWithoutExtension] = it
}
}
Expand Down Expand Up @@ -104,7 +104,7 @@ object KamiMojiManager : Manager {
zip.close()
}

fun getEmoji(name: String?): ResourceLocation? {
fun getEmoji(name: String?): MipmapTexture? {
if (name == null) return null

// Returns null if still loading
Expand All @@ -128,10 +128,17 @@ object KamiMojiManager : Manager {

try {
val image = ImageIO.read(file)
val dynamicTexture = TextureUtils.genTextureWithMipmaps(image, 3, GL_RGBA)
val resourceLocation = Wrapper.minecraft.textureManager.getDynamicTextureLocation(name, dynamicTexture)
val texture = MipmapTexture(image, GL_RGBA, 3)

emojiMap[name] = resourceLocation
texture.bindTexture()
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.0f)
texture.unbindTexture()

emojiMap[name] = texture
} catch (e: IOException) {
KamiMod.LOG.warn("Failed to load emoji", e)
}
Expand Down
53 changes: 23 additions & 30 deletions src/main/java/me/zeroeightsix/kami/module/modules/chat/KamiMoji.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,13 @@ package me.zeroeightsix.kami.module.modules.chat
import me.zeroeightsix.kami.manager.managers.KamiMojiManager
import me.zeroeightsix.kami.module.Category
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.util.graphics.GlStateUtils.resetTexParam
import me.zeroeightsix.kami.util.graphics.GlStateUtils
import me.zeroeightsix.kami.util.graphics.texture.MipmapTexture
import net.minecraft.client.renderer.GlStateManager
import net.minecraft.client.renderer.Tessellator
import net.minecraft.client.renderer.vertex.DefaultVertexFormats
import net.minecraft.util.ResourceLocation
import org.kamiblue.commons.extension.ceilToInt
import org.lwjgl.opengl.GL11.*
import org.lwjgl.opengl.GL12.GL_CLAMP_TO_EDGE
import org.lwjgl.opengl.GL14.GL_TEXTURE_LOD_BIAS

internal object KamiMoji : Module(
name = "KamiMoji",
Expand All @@ -21,22 +19,30 @@ internal object KamiMoji : Module(
@JvmStatic
fun renderText(inputText: String, fontHeight: Int, shadow: Boolean, posX: Float, posY: Float, alpha: Float): String {
var text = inputText
val blend = glGetBoolean(GL_BLEND)

GlStateManager.color(1.0f, 1.0f, 1.0f, alpha)
GlStateUtils.blend(true)
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE)

for (possible in text.split(":")) {
if (KamiMojiManager.isEmoji(possible)) {
val emojiText = ":$possible:"
if (!shadow) {
val index = text.indexOf(emojiText)
if (index == -1) continue
val texture = KamiMojiManager.getEmoji(possible) ?: continue
val emojiText = ":$possible:"

val x = mc.fontRenderer.getStringWidth(text.substring(0, index)) + fontHeight / 4
drawEmoji(KamiMojiManager.getEmoji(possible), (posX + x).toDouble(), posY.toDouble(), fontHeight.toFloat(), alpha)
}
if (!shadow) {
val index = text.indexOf(emojiText)
if (index == -1) continue

text = text.replaceFirst(emojiText, getReplacement(fontHeight))
val x = mc.fontRenderer.getStringWidth(text.substring(0, index)) + fontHeight / 4
drawEmoji(texture, (posX + x).toDouble(), posY.toDouble(), fontHeight.toFloat(), alpha)
}

text = text.replaceFirst(emojiText, getReplacement(fontHeight))
}

GlStateUtils.blend(blend)
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)

return text
}

Expand Down Expand Up @@ -64,30 +70,17 @@ internal object KamiMoji : Module(
}

/* This is created because vanilla one doesn't take double position input */
private fun drawEmoji(emojiTexture: ResourceLocation?, x: Double, y: Double, size: Float, alpha: Float) {
if (emojiTexture == null) return
private fun drawEmoji(texture: MipmapTexture, x: Double, y: Double, size: Float, alpha: Float) {
val tessellator = Tessellator.getInstance()
val bufBuilder = tessellator.buffer

mc.textureManager.bindTexture(emojiTexture)
texture.bindTexture()

GlStateManager.color(1.0f, 1.0f, 1.0f, alpha)
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE)

glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR)
glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_LOD_BIAS, 0.0f)

bufBuilder.begin(7, DefaultVertexFormats.POSITION_TEX)
bufBuilder.begin(GL_TRIANGLE_STRIP, DefaultVertexFormats.POSITION_TEX)
bufBuilder.pos(x, y + size, 0.0).tex(0.0, 1.0).endVertex()
bufBuilder.pos(x + size, y + size, 0.0).tex(1.0, 1.0).endVertex()
bufBuilder.pos(x + size, y, 0.0).tex(1.0, 0.0).endVertex()
bufBuilder.pos(x, y, 0.0).tex(0.0, 0.0).endVertex()
bufBuilder.pos(x + size, y, 0.0).tex(1.0, 0.0).endVertex()
tessellator.draw()

resetTexParam()
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,13 @@ package me.zeroeightsix.kami.module.modules.client

import me.zeroeightsix.kami.module.Category
import me.zeroeightsix.kami.module.Module
import me.zeroeightsix.kami.util.AsyncCachedValue
import me.zeroeightsix.kami.util.TimeUnit
import me.zeroeightsix.kami.util.graphics.font.KamiFontRenderer
import me.zeroeightsix.kami.util.threads.onMainThread
import java.awt.GraphicsEnvironment
import java.util.*
import kotlin.collections.HashMap

internal object CustomFont : Module(
name = "CustomFont",
Expand All @@ -12,27 +17,42 @@ internal object CustomFont : Module(
category = Category.CLIENT,
enabledByDefault = true
) {
private const val DEFAULT_FONT_NAME = "Source Sans Pro"
private const val DEFAULT_FONT_NAME = "Lato"

val fontName = setting("FontName", DEFAULT_FONT_NAME, consumer = { prev, value ->
getMatchingFontName(value) ?: prev
getMatchingFontName(value) ?: getMatchingFontName(prev) ?: DEFAULT_FONT_NAME
})
private val sizeSetting = setting("Size", 1.0f, 0.5f..2.0f, 0.05f)
private val gapSetting = setting("Gap", 0.0f, -10f..10f, 0.5f)
private val lineSpaceSetting = setting("LineSpace", 0.0f, -10f..10f, 0.5f)
private val baselineOffsetSetting = setting("BaselineOffset", 0.0f, -10.0f..10.0f, 0.25f)
private val lodBiasSetting = setting("LodBias", 2.0f, 0.0f..5.0f, 0.05f)
private val lineSpaceSetting = setting("LineSpace", 0.0f, -10f..10f, 0.05f)
private val baselineOffsetSetting = setting("BaselineOffset", 0.0f, -10.0f..10.0f, 0.05f)
private val lodBiasSetting = setting("LodBias", 0.0f, -10.0f..10.0f, 0.05f)

val isDefaultFont get() = fontName.value.equals(DEFAULT_FONT_NAME, true)
val size get() = sizeSetting.value * 0.15f
val gap get() = gapSetting.value * 0.5f - 0.8f
val lineSpace get() = size * (lineSpaceSetting.value * 0.05f + 0.8f)
val lodBias get() = lodBiasSetting.value * 0.5f - 1.25f
val baselineOffset get() = baselineOffsetSetting.value - 4.0f
val lineSpace get() = size * (lineSpaceSetting.value * 0.05f + 0.77f)
val lodBias get() = lodBiasSetting.value * 0.25f - 0.5f
val baselineOffset get() = baselineOffsetSetting.value * 2.0f - 4.5f

/** Available fonts on the system */
val availableFonts : Map<String, String> by AsyncCachedValue(5L, TimeUnit.SECONDS) {
HashMap<String, String>().apply {
val environment = GraphicsEnvironment.getLocalGraphicsEnvironment()

environment.availableFontFamilyNames.forEach {
this[it.toLowerCase(Locale.ROOT)] = it
}

environment.allFonts.forEach {
this[it.name.toLowerCase(Locale.ROOT)] = it.family
}
}
}

private fun getMatchingFontName(name: String): String? {
return if (name.equals(DEFAULT_FONT_NAME, true)) DEFAULT_FONT_NAME
else KamiFontRenderer.availableFonts.firstOrNull { it.equals(name, true) }
else availableFonts[name.toLowerCase(Locale.ROOT)]
}

init {
Expand Down
13 changes: 0 additions & 13 deletions src/main/java/me/zeroeightsix/kami/util/graphics/GlStateUtils.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import me.zeroeightsix.kami.util.Wrapper
import net.minecraft.client.gui.ScaledResolution
import net.minecraft.client.renderer.GlStateManager
import org.lwjgl.opengl.GL11.*
import org.lwjgl.opengl.GL12.*

object GlStateUtils {
private val mc = Wrapper.minecraft
Expand Down Expand Up @@ -108,18 +107,6 @@ object GlStateUtils {
colorLock = state
}

@JvmStatic
fun resetTexParam() {
GlStateManager.bindTexture(0)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST_MIPMAP_LINEAR)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 1000)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LOD, 1000)
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_LOD, -1000)
}

fun rescaleActual() {
rescale(Wrapper.minecraft.displayWidth.toDouble(), Wrapper.minecraft.displayHeight.toDouble())
}
Expand Down
55 changes: 0 additions & 55 deletions src/main/java/me/zeroeightsix/kami/util/graphics/TextureUtils.kt

This file was deleted.

21 changes: 21 additions & 0 deletions src/main/java/me/zeroeightsix/kami/util/graphics/font/CharInfo.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package me.zeroeightsix.kami.util.graphics.font

class CharInfo(
/** Character's width */
val width: Double,

/** Character's height */
val height: Double,

/** Upper left u */
val u1: Double,

/** Upper left v */
val v1: Double,

/** Lower right u */
val u2: Double,

/** Lower right v */
val v2: Double
)
Loading