From b8923ba31db3d06f8f29df20d2918ff5e427b0d4 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Fri, 7 Oct 2022 12:59:51 +0700 Subject: [PATCH] Atlas skin element rendertypes, buffer upload things --- .../otm/client/render/AbstractSkinElement.kt | 89 +++++++++++++++++++ .../mc/otm/client/render/AtlasSkinElement.kt | 58 +++++++++++- .../mc/otm/client/render/WidgetAtlasHolder.kt | 3 +- .../ru/dbotthepony/mc/otm/core/RGBAColor.kt | 37 ++++++-- 4 files changed, 178 insertions(+), 9 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AbstractSkinElement.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AbstractSkinElement.kt index 6b349f0d0..1c01c365f 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AbstractSkinElement.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AbstractSkinElement.kt @@ -14,8 +14,10 @@ import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonWriter import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.vertex.PoseStack +import com.mojang.blaze3d.vertex.VertexConsumer import net.minecraft.network.FriendlyByteBuf import net.minecraft.resources.ResourceLocation +import ru.dbotthepony.mc.otm.core.RGBAColor import ru.dbotthepony.mc.otm.core.linearInterpolation import java.lang.reflect.Type @@ -201,6 +203,93 @@ sealed class AbstractSkinElement { winding: UVWindingOrder = this.winding ) = renderRawPartial(stack, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat(), winding) + protected fun uploadOnto( + pose: PoseStack, + builder: VertexConsumer, + x: Float, + y: Float, + width: Float, + height: Float, + z: Float, + color: RGBAColor?, + u0: Float, + v0: Float, + u1: Float, + v1: Float, + ) { + val intColor = color?.toRGBA() ?: 0 + val matrix = pose.last().pose() + builder.vertex(matrix, x, y + height, z).uv(u0, v1).also { if (color != null) it.color(intColor) }.endVertex() + builder.vertex(matrix, x + width, y + height, z).uv(u1, v1).also { if (color != null) it.color(intColor) }.endVertex() + builder.vertex(matrix, x + width, y, z).uv(u1, v0).also { if (color != null) it.color(intColor) }.endVertex() + builder.vertex(matrix, x, y, z).uv(u0, v0).also { if (color != null) it.color(intColor) }.endVertex() + } + + @JvmOverloads + fun uploadOnto( + pose: PoseStack, + builder: VertexConsumer, + x: Float = 0f, + y: Float = 0f, + width: Float = this.width, + height: Float = this.height, + z: Float = 0f, + color: RGBAColor? = null, + winding: UVWindingOrder = this.winding, + ) { + val (u0, v0, u1, v1) = winding.translate(u0, v0, u1, v1) + uploadOnto(pose, builder, x, y, width, height, z, color, u0, v0, u1, v1) + } + + @JvmOverloads + fun uploadOntoPartial( + pose: PoseStack, + builder: VertexConsumer, + x: Float = 0f, + y: Float = 0f, + width: Float = this.width, + height: Float = this.height, + z: Float = 0f, + color: RGBAColor? = null, + winding: UVWindingOrder = this.winding, + ) { + val u1 = (u0 + linearInterpolation(width / this.width, 0f, u1 - u0)).coerceAtLeast(0f).coerceAtMost(1f) + val v1 = (v0 + linearInterpolation(height / this.height, 0f, v1 - v0)).coerceAtLeast(0f).coerceAtMost(1f) + val (u0_, v0_, u1_, v1_) = winding.translate(u0, v0, u1, v1) + + uploadOnto(pose, builder, x, y, width, height, z, color, u0_, v0_, u1_, v1_) + } + + @JvmOverloads + fun uploadOntoPartialColor( + pose: PoseStack, + builder: VertexConsumer, + x: Float = 0f, + y: Float = 0f, + width: Float = this.width, + height: Float = this.height, + z: Float = 0f, + color: RGBAColor = RGBAColor.WHITE, + winding: UVWindingOrder = this.winding, + ) { + uploadOntoPartial(pose, builder, x, y, width, height, z, color, winding) + } + + @JvmOverloads + fun uploadOntoColor( + pose: PoseStack, + builder: VertexConsumer, + x: Float = 0f, + y: Float = 0f, + width: Float = this.width, + height: Float = this.height, + z: Float = 0f, + color: RGBAColor? = null, + winding: UVWindingOrder = this.winding, + ) { + uploadOnto(pose, builder, x, y, width, height, z, color, winding) + } + abstract fun toJson(): JsonElement abstract fun toNetwork(buff: FriendlyByteBuf) diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AtlasSkinElement.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AtlasSkinElement.kt index 1424a7b12..9f87c4616 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AtlasSkinElement.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/AtlasSkinElement.kt @@ -10,10 +10,19 @@ import com.google.gson.TypeAdapter import com.google.gson.internal.bind.TypeAdapters import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonWriter +import com.mojang.blaze3d.systems.RenderSystem +import com.mojang.blaze3d.vertex.DefaultVertexFormat +import com.mojang.blaze3d.vertex.VertexFormat +import net.minecraft.client.renderer.GameRenderer +import net.minecraft.client.renderer.RenderStateShard +import net.minecraft.client.renderer.RenderStateShard.TextureStateShard +import net.minecraft.client.renderer.RenderType import net.minecraft.client.renderer.texture.TextureAtlasSprite import net.minecraft.network.FriendlyByteBuf import net.minecraft.resources.ResourceLocation +import org.lwjgl.opengl.GL11.GL_ALWAYS import ru.dbotthepony.mc.otm.isClient +import ru.dbotthepony.mc.otm.isClientThread import java.lang.reflect.Type import java.util.stream.Stream @@ -30,7 +39,7 @@ class AtlasSkinElement private constructor( check(isClient) { "Invalid realm" } val _textureAtlasSprite = _textureAtlasSprite - if (_textureAtlasSprite == null || changeset != WidgetAtlasHolder.INSTANCE.changeset || WidgetAtlasHolder.INSTANCE.demandsRebuild) { + if (_textureAtlasSprite == null || changeset != WidgetAtlasHolder.INSTANCE.changeset || (WidgetAtlasHolder.INSTANCE.demandsRebuild && isClientThread())) { val get = WidgetAtlasHolder.INSTANCE.getSprite(location) this._textureAtlasSprite = get changeset = WidgetAtlasHolder.INSTANCE.changeset @@ -54,7 +63,7 @@ class AtlasSkinElement private constructor( override val v0 get() = textureAtlasSprite.v0 override val u1 get() = textureAtlasSprite.u1 override val v1 get() = textureAtlasSprite.v1 - override val texture: ResourceLocation get() = textureAtlasSprite.atlas().location() + override val texture: ResourceLocation get() = WidgetAtlasHolder.LOCATION override fun equals(other: Any?): Boolean { if (other is AtlasSkinElement) @@ -143,5 +152,50 @@ class AtlasSkinElement private constructor( ): AtlasSkinElement { return fromJson(json) } + + val renderTypeGUI by lazy { + val builder = RenderType.CompositeState.builder() + + builder.setTextureState(TextureStateShard(WidgetAtlasHolder.LOCATION, false, false)) + builder.setShaderState(RenderStateShard.ShaderStateShard(GameRenderer::getPositionColorTexShader)) + builder.setDepthTestState(RenderStateShard.DepthTestStateShard("always", GL_ALWAYS)) + builder.setTransparencyState(RenderStateShard.TransparencyStateShard("normal_blend", { + RenderSystem.enableBlend() + RenderSystem.defaultBlendFunc() + }, { + RenderSystem.disableBlend() + })) + + @Suppress("INACCESSIBLE_TYPE") + RenderType.create("gui_element", + DefaultVertexFormat.POSITION_COLOR_TEX, + VertexFormat.Mode.QUADS, + 2048, + false, + false, + builder.createCompositeState(false)) as RenderType + } + + val renderTypeWorld by lazy { + val builder = RenderType.CompositeState.builder() + + builder.setTextureState(TextureStateShard(WidgetAtlasHolder.LOCATION, false, false)) + builder.setShaderState(RenderStateShard.ShaderStateShard(GameRenderer::getPositionColorTexShader)) + builder.setTransparencyState(RenderStateShard.TransparencyStateShard("normal_blend", { + RenderSystem.enableBlend() + RenderSystem.defaultBlendFunc() + }, { + RenderSystem.disableBlend() + })) + + @Suppress("INACCESSIBLE_TYPE") + RenderType.create("gui_element_world", + DefaultVertexFormat.POSITION_COLOR_TEX, + VertexFormat.Mode.QUADS, + 2048, + false, + false, + builder.createCompositeState(false)) as RenderType + } } } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/WidgetAtlasHolder.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/WidgetAtlasHolder.kt index a7a2f0be2..2987d56cc 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/WidgetAtlasHolder.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/client/render/WidgetAtlasHolder.kt @@ -12,6 +12,7 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters import ru.dbotthepony.mc.otm.client.LOGGED_IN import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.onceClient +import ru.dbotthepony.mc.otm.isClientThread import ru.dbotthepony.mc.otm.registry.WriteOnce import java.util.stream.Stream import kotlin.properties.Delegates @@ -45,7 +46,7 @@ class WidgetAtlasHolder private constructor(manager: TextureManager) : TextureAt throw IllegalStateException("Trying to get sprite too early") } - if (demandsRebuild) { + if (demandsRebuild && isClientThread()) { apply(prepare(resourceManager, profileManager), resourceManager, profileManager) } diff --git a/src/main/kotlin/ru/dbotthepony/mc/otm/core/RGBAColor.kt b/src/main/kotlin/ru/dbotthepony/mc/otm/core/RGBAColor.kt index 83d6ffd66..44e049b2a 100644 --- a/src/main/kotlin/ru/dbotthepony/mc/otm/core/RGBAColor.kt +++ b/src/main/kotlin/ru/dbotthepony/mc/otm/core/RGBAColor.kt @@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.core import com.mojang.blaze3d.systems.RenderSystem import net.minecraft.ChatFormatting +import kotlin.math.roundToInt data class RGBAColor(val red: Float, val green: Float, val blue: Float, val alpha: Float = 1f) { constructor(r: Int, g: Int, b: Int) : this((r / 255f), (g / 255f), (b / 255f), 1f) @@ -16,16 +17,40 @@ data class RGBAColor(val red: Float, val green: Float, val blue: Float, val alph ) fun toInt(): Int { - val r = (this.red * 255).toInt() - val g = (this.green * 255).toInt() - val b = (this.blue * 255).toInt() + val r = (this.red * 255).roundToInt() + val g = (this.green * 255).roundToInt() + val b = (this.blue * 255).roundToInt() return (r shl 16) or (g shl 8) or b } + fun toRGBA(): Int { + val r = (this.red * 255).roundToInt() + val g = (this.green * 255).roundToInt() + val b = (this.blue * 255).roundToInt() + val a = (this.alpha * 255).roundToInt() + return (r shl 24) or (g shl 16) or (b shl 8) or a + } + + fun toARGB(): Int { + val r = (this.red * 255).roundToInt() + val g = (this.green * 255).roundToInt() + val b = (this.blue * 255).roundToInt() + val a = (this.alpha * 255).roundToInt() + return (a shl 24) or (r shl 16) or (g shl 8) or b + } + + fun toBGRA(): Int { + val r = (this.red * 255).roundToInt() + val g = (this.green * 255).roundToInt() + val b = (this.blue * 255).roundToInt() + val a = (this.alpha * 255).roundToInt() + return (r shl 24) or (g shl 16) or (r shl 8) or a + } + fun toIntInv(): Int { - val r = (this.red * 255).toInt() - val g = (this.green * 255).toInt() - val b = (this.blue * 255).toInt() + val r = (this.red * 255).roundToInt() + val g = (this.green * 255).roundToInt() + val b = (this.blue * 255).roundToInt() return (b shl 16) or (g shl 8) or r }