new atlas texture management

This commit is contained in:
Moritz Zwerger 2023-10-04 00:49:40 +02:00
parent f1f18e2c92
commit a8bda0f257
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
10 changed files with 134 additions and 21 deletions

View File

@ -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

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* 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

View File

@ -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

View File

@ -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<ResourceLocation, Map<String, RawAtlasElement>> = 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<Int, JsonObject> { 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<String, RawAtlasElement> = 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
}

View File

@ -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<AtlasArea>?,
val areas: Map<String, AtlasArea>?,
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

View File

@ -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,
)

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* 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<Target> = 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))
}
}
}

View File

@ -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

View File

@ -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

View File

@ -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