From a8bda0f2575450a34b12bc9de03ac26b3e0518c0 Mon Sep 17 00:00:00 2001 From: Moritz Zwerger Date: Wed, 4 Oct 2023 00:49:40 +0200 Subject: [PATCH] new atlas texture management --- .../rendering/gui/test/GuiRenderTestUtil.kt | 2 +- .../world/WorldRendererPipelineTest.kt | 15 +++- .../types/unicode/unihex/UnifontRasterizer.kt | 2 +- .../gui/rendering/gui/atlas/AtlasLoader.kt | 34 ++++++--- .../rendering/gui/atlas/RawAtlasElement.kt | 14 +++- .../AtlasTexture.kt} | 11 ++- .../gui/atlas/textures/AtlasTextureManager.kt | 70 +++++++++++++++++++ .../atlas/{ => textures}/CodeTexturePart.kt | 2 +- .../system/base/texture/TextureManager.kt | 2 +- .../base/texture/array/StaticTextureArray.kt | 3 +- 10 files changed, 134 insertions(+), 21 deletions(-) rename src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/{AtlasTextureManager.kt => textures/AtlasTexture.kt} (74%) create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/textures/AtlasTextureManager.kt rename src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/{ => textures}/CodeTexturePart.kt (95%) diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/gui/test/GuiRenderTestUtil.kt b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/gui/test/GuiRenderTestUtil.kt index db0cbbead..4056d28d2 100644 --- a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/gui/test/GuiRenderTestUtil.kt +++ b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/gui/test/GuiRenderTestUtil.kt @@ -21,7 +21,7 @@ import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.font.manager.FontManager import de.bixilon.minosoft.gui.rendering.font.types.dummy.DummyFontType import de.bixilon.minosoft.gui.rendering.gui.GUIRenderer -import de.bixilon.minosoft.gui.rendering.gui.atlas.CodeTexturePart +import de.bixilon.minosoft.gui.rendering.gui.atlas.textures.CodeTexturePart import de.bixilon.minosoft.gui.rendering.gui.elements.Element import de.bixilon.minosoft.gui.rendering.system.dummy.DummyRenderSystem import de.bixilon.minosoft.gui.rendering.system.dummy.texture.DummyTexture diff --git a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/renderer/renderer/pipeline/world/WorldRendererPipelineTest.kt b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/renderer/renderer/pipeline/world/WorldRendererPipelineTest.kt index 7c1a8d176..afe3561bb 100644 --- a/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/renderer/renderer/pipeline/world/WorldRendererPipelineTest.kt +++ b/src/integration-test/kotlin/de/bixilon/minosoft/gui/rendering/renderer/renderer/pipeline/world/WorldRendererPipelineTest.kt @@ -1,3 +1,16 @@ +/* + * Minosoft + * Copyright (C) 2020-2023 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + package de.bixilon.minosoft.gui.rendering.renderer.renderer.pipeline.world import de.bixilon.kotlinglm.vec2.Vec2i @@ -11,7 +24,7 @@ import de.bixilon.minosoft.gui.rendering.font.manager.FontManager import de.bixilon.minosoft.gui.rendering.font.types.dummy.DummyFontType import de.bixilon.minosoft.gui.rendering.framebuffer.FramebufferManager import de.bixilon.minosoft.gui.rendering.framebuffer.world.WorldFramebuffer -import de.bixilon.minosoft.gui.rendering.gui.atlas.CodeTexturePart +import de.bixilon.minosoft.gui.rendering.gui.atlas.textures.CodeTexturePart import de.bixilon.minosoft.gui.rendering.renderer.renderer.RendererManager import de.bixilon.minosoft.gui.rendering.renderer.renderer.pipeline.RendererPipeline import de.bixilon.minosoft.gui.rendering.renderer.renderer.world.LayerSettings diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/font/types/unicode/unihex/UnifontRasterizer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/font/types/unicode/unihex/UnifontRasterizer.kt index 9f5a7bdf5..93252f999 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/font/types/unicode/unihex/UnifontRasterizer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/font/types/unicode/unihex/UnifontRasterizer.kt @@ -67,7 +67,7 @@ class UnifontRasterizer( private fun createTexture(): UnifontTexture { val texture = UnifontTexture(calculateRows(width)) - array.pushTexture(texture) + array += texture this.textures += texture return texture diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/AtlasLoader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/AtlasLoader.kt index c9a09e2ab..c29c09e29 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/AtlasLoader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/AtlasLoader.kt @@ -15,45 +15,59 @@ package de.bixilon.minosoft.gui.rendering.gui.atlas import de.bixilon.kutil.cast.CastUtil.unsafeCast import de.bixilon.kutil.json.JsonObject +import de.bixilon.kutil.json.MutableJsonObject import de.bixilon.minosoft.assets.util.InputStreamUtil.readJsonObject import de.bixilon.minosoft.data.registries.identified.ResourceLocation import de.bixilon.minosoft.data.registries.identified.ResourceLocationUtil.extend import de.bixilon.minosoft.gui.rendering.RenderContext +import de.bixilon.minosoft.gui.rendering.gui.atlas.textures.AtlasTextureManager import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture import de.bixilon.minosoft.util.KUtil.toResourceLocation +import java.util.* class AtlasLoader(val context: RenderContext) { private val raw: MutableMap> = HashMap() - fun load(id: String, packFormat: Int, data: JsonObject): RawAtlasElement? { + fun loadElement(data: JsonObject): RawAtlasElement? { val textureName = data["texture"]?.toResourceLocation()?.texture() ?: throw IllegalArgumentException("Missing texture!") val assets = context.connection.assetsManager.getAssetsManager(textureName) ?: return null - // TODO: check packFormat match return RawAtlasElement.deserialize(textureName, assets, data) } - fun load(id: String, data: JsonObject): RawAtlasElement? { - // TODO: sort all by versionId (descending) and load first best matching - // try to load first best - TODO() + fun loadElement(data: JsonObject, packFormat: Int): RawAtlasElement? { + val sorted = TreeMap { a, b -> (b - a) } + + for ((key, value) in data) { + sorted[key.toInt()] = value.unsafeCast() + } + + for ((format, data) in sorted) { + if (format > packFormat) continue + return loadElement(data) + } + return null } fun load(name: ResourceLocation, data: JsonObject) { val elements: MutableMap = hashMapOf() for ((id, element) in data) { - elements[id] = load(id, element.unsafeCast()) ?: continue + elements[id] = loadElement(element.unsafeCast(), 0) ?: continue } raw[name] = elements } fun load(name: ResourceLocation) { - val file = name.atlas() - val data = context.connection.assetsManager[file].readJsonObject() + val all = context.connection.assetsManager.getAll(name.atlas()) + val data: MutableJsonObject = mutableMapOf() + + for (file in all) { + data += file.readJsonObject() + } load(name, data) } @@ -71,6 +85,8 @@ class AtlasLoader(val context: RenderContext) { map[atlasName] = Atlas(data) } + textures.load() + return map } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/RawAtlasElement.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/RawAtlasElement.kt index ec771ec11..56599f6cf 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/RawAtlasElement.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/RawAtlasElement.kt @@ -19,6 +19,8 @@ import de.bixilon.kutil.json.JsonObject import de.bixilon.kutil.primitive.IntUtil.toInt import de.bixilon.minosoft.assets.AssetsManager import de.bixilon.minosoft.data.registries.identified.ResourceLocation +import de.bixilon.minosoft.gui.rendering.gui.atlas.textures.AtlasTextureManager +import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.readTexture import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.toVec2i import it.unimi.dsi.fastutil.ints.Int2ObjectMap import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap @@ -30,11 +32,17 @@ class RawAtlasElement( val end: Vec2i = resolution, val slots: Int2ObjectMap?, val areas: Map?, - val assets: AssetsManager?, + val assets: AssetsManager, // used for caching ) { fun load(textures: AtlasTextureManager): AtlasElement { - TODO() + val textureData = assets[texture].readTexture() + + val (texture, uvStart, uvEnd) = textures.add(textureData, start, end, resolution) + val size = (end + 1) - start + + + return AtlasElement(texture, uvStart, uvEnd, size, slots, areas) } companion object { @@ -62,7 +70,7 @@ class RawAtlasElement( return areas } - fun deserialize(texture: ResourceLocation, assets: AssetsManager?, data: JsonObject): RawAtlasElement { + fun deserialize(texture: ResourceLocation, assets: AssetsManager, data: JsonObject): RawAtlasElement { val resolution = data["resolution"]?.toVec2i() ?: RESOLUTION val start = data["start"]?.toVec2i() ?: START val end = data["end"]?.toVec2i() ?: resolution diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/AtlasTextureManager.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/textures/AtlasTexture.kt similarity index 74% rename from src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/AtlasTextureManager.kt rename to src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/textures/AtlasTexture.kt index d8c2f652a..3472c9364 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/AtlasTextureManager.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/textures/AtlasTexture.kt @@ -11,8 +11,13 @@ * This software is not affiliated with Mojang AB, the original developer of Minecraft. */ -package de.bixilon.minosoft.gui.rendering.gui.atlas +package de.bixilon.minosoft.gui.rendering.gui.atlas.textures -import de.bixilon.minosoft.gui.rendering.RenderContext +import de.bixilon.kotlinglm.vec2.Vec2 +import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.Texture -class AtlasTextureManager(private val context: RenderContext) +data class AtlasTexture( + val texture: Texture, + val uvStart: Vec2, + val uvEnd: Vec2, +) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/textures/AtlasTextureManager.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/textures/AtlasTextureManager.kt new file mode 100644 index 000000000..b95a444e9 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/textures/AtlasTextureManager.kt @@ -0,0 +1,70 @@ +/* + * Minosoft + * Copyright (C) 2020-2023 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.gui.atlas.textures + +import de.bixilon.kotlinglm.vec2.Vec2 +import de.bixilon.kotlinglm.vec2.Vec2i +import de.bixilon.minosoft.gui.rendering.RenderContext +import de.bixilon.minosoft.gui.rendering.system.base.texture.data.TextureData +import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.memory.MemoryTexture +import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.memory.TextureGenerator +import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY +import java.nio.ByteBuffer + +class AtlasTextureManager(private val context: RenderContext) { + private val targets: MutableList = mutableListOf() + + fun add(textureData: TextureData, start: Vec2i, end: Vec2i, resolution: Vec2i): AtlasTexture { + val scale = textureData.size / resolution + + val realStart = start * scale + val realEnd = end * scale + val size = (realEnd + 1) - realStart + + val target = request(size) + + return target.put(textureData.buffer, textureData.size, realStart, realEnd) + } + + private fun request(size: Vec2i): Target { + // TODO: optimize that + val target = Target(Vec2i.EMPTY, TextureGenerator.allocate(size), size) + this.targets += target + + return target + } + + + fun load() { + for (target in targets) { + context.textures.staticTextures += target.texture + } + targets.clear() + } + + private data class Target( + val offset: Vec2i, + val buffer: ByteBuffer, + val size: Vec2i, + ) { + val texture = MemoryTexture(size, mipmaps = false, buffer = buffer) + + fun put(source: ByteBuffer, size: Vec2i, start: Vec2i, end: Vec2i): AtlasTexture { + // TODO + + return AtlasTexture(texture, Vec2(0, 0), Vec2(1, 1)) + } + } + +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/CodeTexturePart.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/textures/CodeTexturePart.kt similarity index 95% rename from src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/CodeTexturePart.kt rename to src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/textures/CodeTexturePart.kt index 19bba34c4..966ea183b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/CodeTexturePart.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/gui/atlas/textures/CodeTexturePart.kt @@ -11,7 +11,7 @@ * This software is not affiliated with Mojang AB, the original developer of Minecraft. */ -package de.bixilon.minosoft.gui.rendering.gui.atlas +package de.bixilon.minosoft.gui.rendering.gui.atlas.textures import de.bixilon.kotlinglm.vec2.Vec2 import de.bixilon.kotlinglm.vec2.Vec2i diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/TextureManager.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/TextureManager.kt index 7fc215e7d..284d160c9 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/TextureManager.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/TextureManager.kt @@ -17,7 +17,7 @@ import de.bixilon.kotlinglm.vec2.Vec2 import de.bixilon.kotlinglm.vec2.Vec2i import de.bixilon.minosoft.data.registries.identified.Namespaces.minosoft import de.bixilon.minosoft.gui.rendering.RenderConstants -import de.bixilon.minosoft.gui.rendering.gui.atlas.CodeTexturePart +import de.bixilon.minosoft.gui.rendering.gui.atlas.textures.CodeTexturePart import de.bixilon.minosoft.gui.rendering.system.base.shader.NativeShader import de.bixilon.minosoft.gui.rendering.system.base.shader.ShaderUniforms import de.bixilon.minosoft.gui.rendering.system.base.texture.array.StaticTextureArray diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/array/StaticTextureArray.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/array/StaticTextureArray.kt index a073469e9..f1fc4e492 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/array/StaticTextureArray.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/texture/array/StaticTextureArray.kt @@ -23,7 +23,8 @@ interface StaticTextureArray : TextureArray { val animator: SpriteAnimator val state: TextureArrayStates - fun get(resourceLocation: ResourceLocation): Texture? + operator fun get(resourceLocation: ResourceLocation): Texture? + operator fun plusAssign(texture: Texture) = pushTexture(texture) fun pushTexture(texture: Texture) fun createTexture(resourceLocation: ResourceLocation, mipmaps: Boolean = true, properties: Boolean = true, default: (mipmaps: Boolean) -> Texture = { PNGTexture(resourceLocation, mipmaps = it) }): Texture