Atlas skin element rendertypes, buffer upload things

This commit is contained in:
DBotThePony 2022-10-07 12:59:51 +07:00
parent 13d2506661
commit b8923ba31d
Signed by: DBot
GPG Key ID: DCC23B5715498507
4 changed files with 178 additions and 9 deletions

View File

@ -14,8 +14,10 @@ import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter import com.google.gson.stream.JsonWriter
import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.systems.RenderSystem
import com.mojang.blaze3d.vertex.PoseStack import com.mojang.blaze3d.vertex.PoseStack
import com.mojang.blaze3d.vertex.VertexConsumer
import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import ru.dbotthepony.mc.otm.core.RGBAColor
import ru.dbotthepony.mc.otm.core.linearInterpolation import ru.dbotthepony.mc.otm.core.linearInterpolation
import java.lang.reflect.Type import java.lang.reflect.Type
@ -201,6 +203,93 @@ sealed class AbstractSkinElement {
winding: UVWindingOrder = this.winding winding: UVWindingOrder = this.winding
) = renderRawPartial(stack, x.toFloat(), y.toFloat(), width.toFloat(), height.toFloat(), 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 toJson(): JsonElement
abstract fun toNetwork(buff: FriendlyByteBuf) abstract fun toNetwork(buff: FriendlyByteBuf)

View File

@ -10,10 +10,19 @@ import com.google.gson.TypeAdapter
import com.google.gson.internal.bind.TypeAdapters import com.google.gson.internal.bind.TypeAdapters
import com.google.gson.stream.JsonReader import com.google.gson.stream.JsonReader
import com.google.gson.stream.JsonWriter 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.client.renderer.texture.TextureAtlasSprite
import net.minecraft.network.FriendlyByteBuf import net.minecraft.network.FriendlyByteBuf
import net.minecraft.resources.ResourceLocation import net.minecraft.resources.ResourceLocation
import org.lwjgl.opengl.GL11.GL_ALWAYS
import ru.dbotthepony.mc.otm.isClient import ru.dbotthepony.mc.otm.isClient
import ru.dbotthepony.mc.otm.isClientThread
import java.lang.reflect.Type import java.lang.reflect.Type
import java.util.stream.Stream import java.util.stream.Stream
@ -30,7 +39,7 @@ class AtlasSkinElement private constructor(
check(isClient) { "Invalid realm" } check(isClient) { "Invalid realm" }
val _textureAtlasSprite = _textureAtlasSprite 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) val get = WidgetAtlasHolder.INSTANCE.getSprite(location)
this._textureAtlasSprite = get this._textureAtlasSprite = get
changeset = WidgetAtlasHolder.INSTANCE.changeset changeset = WidgetAtlasHolder.INSTANCE.changeset
@ -54,7 +63,7 @@ class AtlasSkinElement private constructor(
override val v0 get() = textureAtlasSprite.v0 override val v0 get() = textureAtlasSprite.v0
override val u1 get() = textureAtlasSprite.u1 override val u1 get() = textureAtlasSprite.u1
override val v1 get() = textureAtlasSprite.v1 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 { override fun equals(other: Any?): Boolean {
if (other is AtlasSkinElement) if (other is AtlasSkinElement)
@ -143,5 +152,50 @@ class AtlasSkinElement private constructor(
): AtlasSkinElement { ): AtlasSkinElement {
return fromJson(json) 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
}
} }
} }

View File

@ -12,6 +12,7 @@ import ru.dbotthepony.mc.otm.OverdriveThatMatters
import ru.dbotthepony.mc.otm.client.LOGGED_IN import ru.dbotthepony.mc.otm.client.LOGGED_IN
import ru.dbotthepony.mc.otm.client.minecraft import ru.dbotthepony.mc.otm.client.minecraft
import ru.dbotthepony.mc.otm.client.onceClient import ru.dbotthepony.mc.otm.client.onceClient
import ru.dbotthepony.mc.otm.isClientThread
import ru.dbotthepony.mc.otm.registry.WriteOnce import ru.dbotthepony.mc.otm.registry.WriteOnce
import java.util.stream.Stream import java.util.stream.Stream
import kotlin.properties.Delegates import kotlin.properties.Delegates
@ -45,7 +46,7 @@ class WidgetAtlasHolder private constructor(manager: TextureManager) : TextureAt
throw IllegalStateException("Trying to get sprite too early") throw IllegalStateException("Trying to get sprite too early")
} }
if (demandsRebuild) { if (demandsRebuild && isClientThread()) {
apply(prepare(resourceManager, profileManager), resourceManager, profileManager) apply(prepare(resourceManager, profileManager), resourceManager, profileManager)
} }

View File

@ -2,6 +2,7 @@ package ru.dbotthepony.mc.otm.core
import com.mojang.blaze3d.systems.RenderSystem import com.mojang.blaze3d.systems.RenderSystem
import net.minecraft.ChatFormatting import net.minecraft.ChatFormatting
import kotlin.math.roundToInt
data class RGBAColor(val red: Float, val green: Float, val blue: Float, val alpha: Float = 1f) { 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) 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 { fun toInt(): Int {
val r = (this.red * 255).toInt() val r = (this.red * 255).roundToInt()
val g = (this.green * 255).toInt() val g = (this.green * 255).roundToInt()
val b = (this.blue * 255).toInt() val b = (this.blue * 255).roundToInt()
return (r shl 16) or (g shl 8) or b 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 { fun toIntInv(): Int {
val r = (this.red * 255).toInt() val r = (this.red * 255).roundToInt()
val g = (this.green * 255).toInt() val g = (this.green * 255).roundToInt()
val b = (this.blue * 255).toInt() val b = (this.blue * 255).roundToInt()
return (b shl 16) or (g shl 8) or r return (b shl 16) or (g shl 8) or r
} }