mirror of
https://gitlab.bixilon.de/bixilon/minosoft.git
synced 2025-09-13 01:16:46 -04:00
make opengl texture array implementation lighter
Most of the functionality is actually not opengl specific, so abstract it
This commit is contained in:
parent
31225196ee
commit
35a9a08880
@ -34,7 +34,7 @@ class BakedFaceTest {
|
|||||||
|
|
||||||
private fun texture(): Texture {
|
private fun texture(): Texture {
|
||||||
val manager = BakedModelTestUtil.createTextureManager(texture)
|
val manager = BakedModelTestUtil.createTextureManager(texture)
|
||||||
return manager.staticTextures.createTexture(texture.toResourceLocation())
|
return manager.staticTextures.create(texture.toResourceLocation())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun singleMesh(): ChunkMesh {
|
private fun singleMesh(): ChunkMesh {
|
||||||
|
@ -13,17 +13,22 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering.system.dummy.texture
|
package de.bixilon.minosoft.gui.rendering.system.dummy.texture
|
||||||
|
|
||||||
|
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||||
import de.bixilon.kutil.latch.AbstractLatch
|
import de.bixilon.kutil.latch.AbstractLatch
|
||||||
|
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.shader.NativeShader
|
import de.bixilon.minosoft.gui.rendering.system.base.shader.NativeShader
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureStates
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureStates
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.array.StaticTextureArray
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.array.StaticTextureArray
|
||||||
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.Texture
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
class DummyStaticTextureArray(context: RenderContext) : StaticTextureArray(context, false, 0) {
|
class DummyStaticTextureArray(context: RenderContext) : StaticTextureArray(context, false, 0) {
|
||||||
|
|
||||||
override fun load(latch: AbstractLatch) {
|
override fun load(animationIndex: AtomicInteger, textures: Collection<Texture>) {
|
||||||
for (texture in this.named.values) {
|
for (texture in textures) {
|
||||||
(texture as DummyTexture).state = TextureStates.LOADED
|
if (texture !is DummyTexture) continue
|
||||||
|
texture.state = TextureStates.LOADED
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -31,6 +36,12 @@ class DummyStaticTextureArray(context: RenderContext) : StaticTextureArray(conte
|
|||||||
animator.init()
|
animator.init()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
override fun create(resourceLocation: ResourceLocation, mipmaps: Boolean, properties: Boolean, factory: (mipmaps: Int) -> Texture): Texture {
|
||||||
|
return super.create(resourceLocation, mipmaps, properties) { DummyTexture() }
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun findResolution(size: Vec2i) = size
|
||||||
|
|
||||||
override fun activate() = Unit
|
override fun activate() = Unit
|
||||||
override fun use(shader: NativeShader, name: String) = Unit
|
override fun use(shader: NativeShader, name: String) = Unit
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.TextureRend
|
|||||||
import de.bixilon.minosoft.gui.rendering.textures.properties.ImageProperties
|
import de.bixilon.minosoft.gui.rendering.textures.properties.ImageProperties
|
||||||
|
|
||||||
class DummyTexture : Texture {
|
class DummyTexture : Texture {
|
||||||
override var array = TextureArrayProperties(Vec2(), 1, Vec2())
|
override var array = TextureArrayProperties(Vec2(), 1, 1.0f)
|
||||||
override var state: TextureStates = TextureStates.DECLARED
|
override var state: TextureStates = TextureStates.DECLARED
|
||||||
override var size: Vec2i = Vec2i(1, 1)
|
override var size: Vec2i = Vec2i(1, 1)
|
||||||
override val transparency: TextureTransparencies get() = TextureTransparencies.OPAQUE
|
override val transparency: TextureTransparencies get() = TextureTransparencies.OPAQUE
|
||||||
|
@ -59,7 +59,7 @@ class WorldBorderRenderer(
|
|||||||
shader.native.defines["MAX_DISTANCE"] = MAX_DISTANCE
|
shader.native.defines["MAX_DISTANCE"] = MAX_DISTANCE
|
||||||
shader.load()
|
shader.load()
|
||||||
|
|
||||||
texture = context.textures.staticTextures.createTexture(TEXTURE)
|
texture = context.textures.staticTextures.create(TEXTURE)
|
||||||
context.camera.offset::offset.observe(this) { reload = true }
|
context.camera.offset::offset.observe(this) { reload = true }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -44,7 +44,7 @@ class DoubleChestRenderer(
|
|||||||
|
|
||||||
private fun register(loader: ModelLoader, name: ResourceLocation, texture: ResourceLocation) {
|
private fun register(loader: ModelLoader, name: ResourceLocation, texture: ResourceLocation) {
|
||||||
val static = loader.context.textures.staticTextures
|
val static = loader.context.textures.staticTextures
|
||||||
val override = mapOf(TEXTURE to static.createTexture(texture))
|
val override = mapOf(TEXTURE to static.create(texture))
|
||||||
loader.skeletal.register(name, MODEL, override)
|
loader.skeletal.register(name, MODEL, override)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -52,8 +52,8 @@ class DoubleChestRenderer(
|
|||||||
if (textures.size != 2) throw IllegalStateException("Textures must be left and right!")
|
if (textures.size != 2) throw IllegalStateException("Textures must be left and right!")
|
||||||
val static = loader.context.textures.staticTextures
|
val static = loader.context.textures.staticTextures
|
||||||
val override = mapOf(
|
val override = mapOf(
|
||||||
TEXTURE_5[0] to static.createTexture(textures[0]),
|
TEXTURE_5[0] to static.create(textures[0]),
|
||||||
TEXTURE_5[1] to static.createTexture(textures[1]),
|
TEXTURE_5[1] to static.create(textures[1]),
|
||||||
)
|
)
|
||||||
loader.skeletal.register(name, MODEL_5, override)
|
loader.skeletal.register(name, MODEL_5, override)
|
||||||
}
|
}
|
||||||
|
@ -41,7 +41,7 @@ class SingleChestRenderer(
|
|||||||
private val named = minecraft("chest")
|
private val named = minecraft("chest")
|
||||||
|
|
||||||
fun register(loader: ModelLoader, name: ResourceLocation, texture: ResourceLocation) {
|
fun register(loader: ModelLoader, name: ResourceLocation, texture: ResourceLocation) {
|
||||||
val texture = loader.context.textures.staticTextures.createTexture(texture)
|
val texture = loader.context.textures.staticTextures.create(texture)
|
||||||
val model = if (loader.packFormat < 5) MODEL else MODEL_5
|
val model = if (loader.packFormat < 5) MODEL else MODEL_5
|
||||||
loader.skeletal.register(name, model, mapOf(named to texture))
|
loader.skeletal.register(name, model, mapOf(named to texture))
|
||||||
}
|
}
|
||||||
|
@ -95,7 +95,7 @@ class ShulkerBoxRenderer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun load(name: ResourceLocation, texture: ResourceLocation, loader: ModelLoader) {
|
private fun load(name: ResourceLocation, texture: ResourceLocation, loader: ModelLoader) {
|
||||||
val texture = loader.context.textures.staticTextures.createTexture(texture)
|
val texture = loader.context.textures.staticTextures.create(texture)
|
||||||
loader.skeletal.register(name, TEMPLATE, override = mapOf(this.named to texture))
|
loader.skeletal.register(name, TEMPLATE, override = mapOf(this.named to texture))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,8 @@ class BitmapCodeRenderer(
|
|||||||
) : AscentedCodePointRenderer {
|
) : AscentedCodePointRenderer {
|
||||||
|
|
||||||
fun updateArray() {
|
fun updateArray() {
|
||||||
uvStart *= texture.array.uvEnd
|
val end = texture.array.uvEnd ?: return
|
||||||
uvEnd *= texture.array.uvEnd
|
uvStart *= end
|
||||||
|
uvEnd *= end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -78,7 +78,7 @@ class BitmapFontType(
|
|||||||
|
|
||||||
private fun load(file: ResourceLocation, height: Int, ascent: Int, chars: List<String>, context: RenderContext): BitmapFontType? {
|
private fun load(file: ResourceLocation, height: Int, ascent: Int, chars: List<String>, context: RenderContext): BitmapFontType? {
|
||||||
if (chars.isEmpty() || height <= 0) return null
|
if (chars.isEmpty() || height <= 0) return null
|
||||||
val texture = context.textures.staticTextures.createTexture(file, mipmaps = false, properties = false)
|
val texture = context.textures.staticTextures.create(file, mipmaps = false, properties = false)
|
||||||
texture.load(context) // force load it, we need to calculate the width of every char
|
texture.load(context) // force load it, we need to calculate the width of every char
|
||||||
|
|
||||||
return load(texture, texture.size.y / chars.size, ascent, chars.codePoints())
|
return load(texture, texture.size.y / chars.size, ascent, chars.codePoints())
|
||||||
|
@ -19,14 +19,15 @@ import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.Texture
|
|||||||
|
|
||||||
class UnicodeCodeRenderer(
|
class UnicodeCodeRenderer(
|
||||||
override val texture: Texture,
|
override val texture: Texture,
|
||||||
override var uvStart: Vec2,
|
override val uvStart: Vec2,
|
||||||
override var uvEnd: Vec2,
|
override val uvEnd: Vec2,
|
||||||
override val width: Float,
|
override val width: Float,
|
||||||
) : RasterizedCodePointRenderer {
|
) : RasterizedCodePointRenderer {
|
||||||
|
|
||||||
|
|
||||||
fun updateArray() {
|
fun updateArray() {
|
||||||
uvStart = uvStart * texture.array.uvEnd
|
val end = texture.array.uvEnd ?: return
|
||||||
uvEnd = uvEnd * texture.array.uvEnd
|
uvStart *= end
|
||||||
|
uvEnd *= end
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -87,7 +87,7 @@ class LegacyUnicodeFontType(
|
|||||||
sizes.skip(PAGE_SIZE.toLong())
|
sizes.skip(PAGE_SIZE.toLong())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
val texture = textures.createTexture(textureFile, mipmaps = false, properties = false)
|
val texture = textures.create(textureFile, mipmaps = false, properties = false)
|
||||||
|
|
||||||
loadPage(pageId, texture, chars, sizes)
|
loadPage(pageId, texture, chars, sizes)
|
||||||
}
|
}
|
||||||
|
@ -13,11 +13,11 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering.font.types.unicode.unihex
|
package de.bixilon.minosoft.gui.rendering.font.types.unicode.unihex
|
||||||
|
|
||||||
|
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||||
import de.bixilon.minosoft.gui.rendering.font.renderer.code.CodePointRenderer
|
import de.bixilon.minosoft.gui.rendering.font.renderer.code.CodePointRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.font.types.empty.EmptyCodeRenderer
|
import de.bixilon.minosoft.gui.rendering.font.types.empty.EmptyCodeRenderer
|
||||||
import de.bixilon.minosoft.gui.rendering.font.types.unicode.unihex.UnifontTexture.Companion.isPixelSet
|
import de.bixilon.minosoft.gui.rendering.font.types.unicode.unihex.UnifontTexture.Companion.isPixelSet
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.array.StaticTextureArray
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.array.StaticTextureArray
|
||||||
import de.bixilon.minosoft.gui.rendering.system.opengl.texture.OpenGLTextureArray.Companion.TEXTURE_RESOLUTION_ID_MAP
|
|
||||||
|
|
||||||
class UnifontRasterizer(
|
class UnifontRasterizer(
|
||||||
private val array: StaticTextureArray,
|
private val array: StaticTextureArray,
|
||||||
@ -54,15 +54,8 @@ class UnifontRasterizer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun calculateRows(width: Int): Int {
|
private fun calculateRows(width: Int): Int {
|
||||||
var previous = TEXTURE_RESOLUTION_ID_MAP.last()
|
val size = array.findResolution(Vec2i(width, HEIGHT))
|
||||||
for (index in TEXTURE_RESOLUTION_ID_MAP.size - 1 downTo 0) {
|
return size.y / HEIGHT
|
||||||
val resolution = TEXTURE_RESOLUTION_ID_MAP[index]
|
|
||||||
val size = resolution * resolution / HEIGHT
|
|
||||||
if (width >= size) return previous / HEIGHT
|
|
||||||
previous = resolution
|
|
||||||
}
|
|
||||||
|
|
||||||
return 1
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun createTexture(): UnifontTexture {
|
private fun createTexture(): UnifontTexture {
|
||||||
|
@ -31,7 +31,7 @@ class FireOverlay(
|
|||||||
private val config = context.connection.profiles.rendering.overlay.fire
|
private val config = context.connection.profiles.rendering.overlay.fire
|
||||||
private val player = context.connection.player
|
private val player = context.connection.player
|
||||||
private val shader = context.shaders.genericTexture2dShader
|
private val shader = context.shaders.genericTexture2dShader
|
||||||
private var texture: Texture = context.textures.staticTextures.createTexture("block/fire_1".toResourceLocation().texture())
|
private var texture: Texture = context.textures.staticTextures.create("block/fire_1".toResourceLocation().texture())
|
||||||
private val lava = context.connection.registries.fluid[LavaFluid]
|
private val lava = context.connection.registries.fluid[LavaFluid]
|
||||||
override val render: Boolean
|
override val render: Boolean
|
||||||
get() {
|
get() {
|
||||||
|
@ -23,7 +23,7 @@ import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
|||||||
|
|
||||||
class PowderSnowOverlay(context: RenderContext) : SimpleOverlay(context) {
|
class PowderSnowOverlay(context: RenderContext) : SimpleOverlay(context) {
|
||||||
private val config = context.connection.profiles.rendering.overlay
|
private val config = context.connection.profiles.rendering.overlay
|
||||||
override val texture: Texture = context.textures.staticTextures.createTexture(OVERLAY_TEXTURE)
|
override val texture: Texture = context.textures.staticTextures.create(OVERLAY_TEXTURE)
|
||||||
private val strength = FloatAverage(1L * 1000000000L, 0.0f)
|
private val strength = FloatAverage(1L * 1000000000L, 0.0f)
|
||||||
override var render: Boolean = false
|
override var render: Boolean = false
|
||||||
get() = config.powderSnow && field
|
get() = config.powderSnow && field
|
||||||
|
@ -23,7 +23,7 @@ import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
|||||||
|
|
||||||
class PumpkinOverlay(context: RenderContext) : FirstPersonOverlay(context) {
|
class PumpkinOverlay(context: RenderContext) : FirstPersonOverlay(context) {
|
||||||
private val config = context.connection.profiles.rendering.overlay
|
private val config = context.connection.profiles.rendering.overlay
|
||||||
override val texture: Texture = context.textures.staticTextures.createTexture(OVERLAY_TEXTURE)
|
override val texture: Texture = context.textures.staticTextures.create(OVERLAY_TEXTURE)
|
||||||
override val render: Boolean
|
override val render: Boolean
|
||||||
get() {
|
get() {
|
||||||
if (!config.pumpkin) {
|
if (!config.pumpkin) {
|
||||||
|
@ -24,7 +24,7 @@ import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
|||||||
|
|
||||||
class WaterOverlay(context: RenderContext) : SimpleOverlay(context) {
|
class WaterOverlay(context: RenderContext) : SimpleOverlay(context) {
|
||||||
private val player = context.connection.player
|
private val player = context.connection.player
|
||||||
override val texture: Texture = context.textures.staticTextures.createTexture("minecraft:misc/underwater".toResourceLocation().texture())
|
override val texture: Texture = context.textures.staticTextures.create("minecraft:misc/underwater".toResourceLocation().texture())
|
||||||
override val render: Boolean
|
override val render: Boolean
|
||||||
get() = player.gamemode != Gamemodes.SPECTATOR && player.physics.submersion.eye is WaterFluid
|
get() = player.gamemode != Gamemodes.SPECTATOR && player.physics.submersion.eye is WaterFluid
|
||||||
|
|
||||||
|
@ -22,7 +22,7 @@ import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
|||||||
|
|
||||||
class WorldBorderOverlay(context: RenderContext) : SimpleOverlay(context) {
|
class WorldBorderOverlay(context: RenderContext) : SimpleOverlay(context) {
|
||||||
private val config = context.connection.profiles.rendering.overlay
|
private val config = context.connection.profiles.rendering.overlay
|
||||||
override val texture: Texture = context.textures.staticTextures.createTexture(OVERLAY_TEXTURE)
|
override val texture: Texture = context.textures.staticTextures.create(OVERLAY_TEXTURE)
|
||||||
override val render: Boolean
|
override val render: Boolean
|
||||||
get() = config.worldBorder && context.connection.world.border.isOutside(context.connection.player.physics.position)
|
get() = config.worldBorder && context.connection.world.border.isOutside(context.connection.player.physics.position)
|
||||||
|
|
||||||
|
@ -33,8 +33,8 @@ import java.util.*
|
|||||||
class WeatherOverlay(private val context: RenderContext) : Overlay {
|
class WeatherOverlay(private val context: RenderContext) : Overlay {
|
||||||
private val world = context.connection.world
|
private val world = context.connection.world
|
||||||
private val config = context.connection.profiles.rendering.overlay.weather
|
private val config = context.connection.profiles.rendering.overlay.weather
|
||||||
private val rain = context.textures.staticTextures.createTexture(RAIN)
|
private val rain = context.textures.staticTextures.create(RAIN)
|
||||||
private val snow = context.textures.staticTextures.createTexture(SNOW)
|
private val snow = context.textures.staticTextures.create(SNOW)
|
||||||
private val precipitation get() = context.connection.player.physics.positionInfo.biome?.precipitation
|
private val precipitation get() = context.connection.player.physics.positionInfo.biome?.precipitation
|
||||||
override val render: Boolean
|
override val render: Boolean
|
||||||
get() = world.dimension.effects.weather && world.weather.raining && when (precipitation) { // ToDo: Check if exposed to the sky
|
get() = world.dimension.effects.weather && world.weather.raining && when (precipitation) { // ToDo: Check if exposed to the sky
|
||||||
@ -70,7 +70,7 @@ class WeatherOverlay(private val context: RenderContext) : Overlay {
|
|||||||
val offsetMultiplicator = random.nextFloat(0.8f, 1.2f)
|
val offsetMultiplicator = random.nextFloat(0.8f, 1.2f)
|
||||||
val alpha = random.nextFloat(0.8f, 1.0f)
|
val alpha = random.nextFloat(0.8f, 1.0f)
|
||||||
mesh.addZQuad(
|
mesh.addZQuad(
|
||||||
Vec2(offset, 0), OVERLAY_Z, Vec2(offset + step, windowSize.y), Vec2(0.0f), texture.array.uvEnd
|
Vec2(offset, 0), OVERLAY_Z, Vec2(offset + step, windowSize.y), Vec2(0.0f), texture.array.uvEnd ?: Vec2(1.0f)
|
||||||
) { position, uv ->
|
) { position, uv ->
|
||||||
val transformed = Vec2()
|
val transformed = Vec2()
|
||||||
transformed.x = position.x / (windowSize.x / 2) - 1.0f
|
transformed.x = position.x / (windowSize.x / 2) - 1.0f
|
||||||
|
@ -44,14 +44,14 @@ data class BlockModel(
|
|||||||
|
|
||||||
fun createTexture(name: String, textures: TextureManager): Texture? {
|
fun createTexture(name: String, textures: TextureManager): Texture? {
|
||||||
if (!name.startsWith("#")) {
|
if (!name.startsWith("#")) {
|
||||||
return textures.staticTextures.createTexture(name.toResourceLocation())
|
return textures.staticTextures.create(name.toResourceLocation())
|
||||||
}
|
}
|
||||||
val texture = this.textures?.get(name.substring(1))
|
val texture = this.textures?.get(name.substring(1))
|
||||||
if (texture == null || texture !is ResourceLocation) {
|
if (texture == null || texture !is ResourceLocation) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
return textures.staticTextures.createTexture(texture)
|
return textures.staticTextures.create(texture)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun getOrNullTexture(name: String, textures: TextureManager): Texture? {
|
fun getOrNullTexture(name: String, textures: TextureManager): Texture? {
|
||||||
|
@ -27,8 +27,8 @@ class LavaFluidModel : FluidModel {
|
|||||||
override val transparency = TextureTransparencies.OPAQUE// TODO: from texture
|
override val transparency = TextureTransparencies.OPAQUE// TODO: from texture
|
||||||
|
|
||||||
override fun load(context: RenderContext) {
|
override fun load(context: RenderContext) {
|
||||||
still = context.textures.staticTextures.createTexture(context.models.block.fixTexturePath(STILL).texture())
|
still = context.textures.staticTextures.create(context.models.block.fixTexturePath(STILL).texture())
|
||||||
flowing = context.textures.staticTextures.createTexture(context.models.block.fixTexturePath(FLOWING).texture())
|
flowing = context.textures.staticTextures.create(context.models.block.fixTexturePath(FLOWING).texture())
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -31,8 +31,8 @@ class WaterFluidModel : FluidModel {
|
|||||||
override val transparency = TextureTransparencies.TRANSLUCENT// TODO: from texture
|
override val transparency = TextureTransparencies.TRANSLUCENT// TODO: from texture
|
||||||
|
|
||||||
override fun load(context: RenderContext) {
|
override fun load(context: RenderContext) {
|
||||||
still = context.textures.staticTextures.createTexture(context.models.block.fixTexturePath(STILL).texture())
|
still = context.textures.staticTextures.create(context.models.block.fixTexturePath(STILL).texture())
|
||||||
flowing = context.textures.staticTextures.createTexture(context.models.block.fixTexturePath(FLOWING).texture())
|
flowing = context.textures.staticTextures.create(context.models.block.fixTexturePath(FLOWING).texture())
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -32,7 +32,7 @@ class ItemModel(
|
|||||||
if (this.textures == null) return null
|
if (this.textures == null) return null
|
||||||
val texture = this.textures["layer0", "particle"]?.toResourceLocation()?.texture() ?: return null
|
val texture = this.textures["layer0", "particle"]?.toResourceLocation()?.texture() ?: return null
|
||||||
|
|
||||||
return ItemModelPrototype(textures.staticTextures.createTexture(texture))
|
return ItemModelPrototype(textures.staticTextures.create(texture))
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
|
@ -119,7 +119,7 @@ class ParticleRenderer(
|
|||||||
translucentMesh.load()
|
translucentMesh.load()
|
||||||
for (particle in connection.registries.particleType) {
|
for (particle in connection.registries.particleType) {
|
||||||
for (resourceLocation in particle.textures) {
|
for (resourceLocation in particle.textures) {
|
||||||
context.textures.staticTextures.createTexture(resourceLocation)
|
context.textures.staticTextures.create(resourceLocation)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,7 +42,7 @@ data class SkeletalModel(
|
|||||||
if (name in skip) continue
|
if (name in skip) continue
|
||||||
val file = name.texture()
|
val file = name.texture()
|
||||||
if (file in skip) continue
|
if (file in skip) continue
|
||||||
val texture = context.textures.staticTextures.createTexture(file)
|
val texture = context.textures.staticTextures.create(file)
|
||||||
this.loadedTextures[name] = SkeletalTextureInstance(properties, texture)
|
this.loadedTextures[name] = SkeletalTextureInstance(properties, texture)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,7 @@ class SkyboxRenderer(
|
|||||||
override fun init() {
|
override fun init() {
|
||||||
for (properties in DefaultDimensionEffects) {
|
for (properties in DefaultDimensionEffects) {
|
||||||
val texture = properties.fixedTexture ?: continue
|
val texture = properties.fixedTexture ?: continue
|
||||||
textureCache[texture] = sky.context.textures.staticTextures.createTexture(texture)
|
textureCache[texture] = sky.context.textures.staticTextures.create(texture)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,13 +29,14 @@ import java.util.*
|
|||||||
class MoonRenderer(
|
class MoonRenderer(
|
||||||
sky: SkyRenderer,
|
sky: SkyRenderer,
|
||||||
) : PlanetRenderer(sky) {
|
) : PlanetRenderer(sky) {
|
||||||
override val texture = sky.context.textures.staticTextures.createTexture(MOON_PHASES)
|
override val texture = sky.context.textures.staticTextures.create(MOON_PHASES)
|
||||||
private var phase = MoonPhases.FULL_MOON
|
private var phase = MoonPhases.FULL_MOON
|
||||||
|
|
||||||
private fun updateUV(phases: MoonPhases) {
|
private fun updateUV(phases: MoonPhases) {
|
||||||
val coordinates = PHASE_UV[phases.ordinal]
|
val coordinates = PHASE_UV[phases.ordinal]
|
||||||
uvStart = Vec2(1.0f / 4 * coordinates.x, 1.0f / 2 * coordinates.y) * texture.array.uvEnd
|
val end = texture.array.uvEnd ?: Vec2i(1.0f)
|
||||||
uvEnd = Vec2(1.0f / 4 * (coordinates.x + 1), 1.0f / 2 * (coordinates.y + 1)) * texture.array.uvEnd
|
uvStart = Vec2(1.0f / 4 * coordinates.x, 1.0f / 2 * coordinates.y) * end
|
||||||
|
uvEnd = Vec2(1.0f / 4 * (coordinates.x + 1), 1.0f / 2 * (coordinates.y + 1)) * end
|
||||||
meshInvalid = true
|
meshInvalid = true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ import kotlin.math.pow
|
|||||||
class SunRenderer(
|
class SunRenderer(
|
||||||
sky: SkyRenderer,
|
sky: SkyRenderer,
|
||||||
) : PlanetRenderer(sky) {
|
) : PlanetRenderer(sky) {
|
||||||
override val texture = sky.context.textures.staticTextures.createTexture(SUN)
|
override val texture = sky.context.textures.staticTextures.create(SUN)
|
||||||
|
|
||||||
public override fun calculateAngle(): Float {
|
public override fun calculateAngle(): Float {
|
||||||
val time = sky.context.connection.world.time
|
val time = sky.context.connection.world.time
|
||||||
|
@ -42,8 +42,8 @@ abstract class TextureManager {
|
|||||||
if (this::debugTexture.isInitialized) {
|
if (this::debugTexture.isInitialized) {
|
||||||
throw IllegalStateException("Already initialized!")
|
throw IllegalStateException("Already initialized!")
|
||||||
}
|
}
|
||||||
debugTexture = staticTextures.createTexture(RenderConstants.DEBUG_TEXTURE_RESOURCE_LOCATION)
|
debugTexture = staticTextures.create(RenderConstants.DEBUG_TEXTURE_RESOURCE_LOCATION)
|
||||||
whiteTexture = CodeTexturePart(texture = staticTextures.createTexture(minosoft("white").texture(), mipmaps = false), uvStart = Vec2(0.0f, 0.0f), uvEnd = Vec2(0.001f, 0.001f), size = Vec2i(16, 16))
|
whiteTexture = CodeTexturePart(texture = staticTextures.create(minosoft("white").texture(), mipmaps = false), uvStart = Vec2(0.0f, 0.0f), uvEnd = Vec2(0.001f, 0.001f), size = Vec2i(16, 16))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun initializeSkins(connection: PlayConnection) {
|
fun initializeSkins(connection: PlayConnection) {
|
||||||
|
@ -13,10 +13,14 @@
|
|||||||
|
|
||||||
package de.bixilon.minosoft.gui.rendering.system.base.texture.array
|
package de.bixilon.minosoft.gui.rendering.system.base.texture.array
|
||||||
|
|
||||||
|
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||||
import de.bixilon.kutil.concurrent.lock.simple.SimpleLock
|
import de.bixilon.kutil.concurrent.lock.simple.SimpleLock
|
||||||
import de.bixilon.kutil.concurrent.pool.DefaultThreadPool
|
import de.bixilon.kutil.concurrent.pool.DefaultThreadPool
|
||||||
|
import de.bixilon.kutil.concurrent.pool.ThreadPool
|
||||||
import de.bixilon.kutil.concurrent.pool.runnable.ForcePooledRunnable
|
import de.bixilon.kutil.concurrent.pool.runnable.ForcePooledRunnable
|
||||||
|
import de.bixilon.kutil.concurrent.pool.runnable.SimplePoolRunnable
|
||||||
import de.bixilon.kutil.latch.AbstractLatch
|
import de.bixilon.kutil.latch.AbstractLatch
|
||||||
|
import de.bixilon.kutil.latch.AbstractLatch.Companion.child
|
||||||
import de.bixilon.minosoft.assets.util.InputStreamUtil.readAsString
|
import de.bixilon.minosoft.assets.util.InputStreamUtil.readAsString
|
||||||
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||||
@ -28,6 +32,7 @@ import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.file.PNGTex
|
|||||||
import de.bixilon.minosoft.gui.rendering.textures.properties.ImageProperties
|
import de.bixilon.minosoft.gui.rendering.textures.properties.ImageProperties
|
||||||
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
import de.bixilon.minosoft.util.KUtil.toResourceLocation
|
||||||
import de.bixilon.minosoft.util.json.Jackson
|
import de.bixilon.minosoft.util.json.Jackson
|
||||||
|
import java.util.concurrent.atomic.AtomicInteger
|
||||||
|
|
||||||
abstract class StaticTextureArray(
|
abstract class StaticTextureArray(
|
||||||
val context: RenderContext,
|
val context: RenderContext,
|
||||||
@ -50,10 +55,9 @@ abstract class StaticTextureArray(
|
|||||||
return texture
|
return texture
|
||||||
}
|
}
|
||||||
|
|
||||||
operator fun plusAssign(texture: Texture) = pushTexture(texture)
|
operator fun plusAssign(texture: Texture) = push(texture)
|
||||||
|
|
||||||
|
fun push(texture: Texture) {
|
||||||
fun pushTexture(texture: Texture) {
|
|
||||||
lock.lock()
|
lock.lock()
|
||||||
other += texture
|
other += texture
|
||||||
lock.unlock()
|
lock.unlock()
|
||||||
@ -62,7 +66,7 @@ abstract class StaticTextureArray(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun createTexture(resourceLocation: ResourceLocation, mipmaps: Boolean = true, properties: Boolean = true, factory: (mipmaps: Int) -> Texture = { PNGTexture(resourceLocation, mipmaps = it) }): Texture {
|
open fun create(resourceLocation: ResourceLocation, mipmaps: Boolean = true, properties: Boolean = true, factory: (mipmaps: Int) -> Texture = { PNGTexture(resourceLocation, mipmaps = it) }): Texture {
|
||||||
lock.lock()
|
lock.lock()
|
||||||
named[resourceLocation]?.let { lock.unlock(); return it }
|
named[resourceLocation]?.let { lock.unlock(); return it }
|
||||||
|
|
||||||
@ -92,6 +96,30 @@ abstract class StaticTextureArray(
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
|
abstract fun findResolution(size: Vec2i): Vec2i
|
||||||
|
|
||||||
abstract fun load(latch: AbstractLatch)
|
|
||||||
|
private fun load(latch: AbstractLatch, textures: Collection<Texture>) {
|
||||||
|
for (texture in textures) {
|
||||||
|
if (texture.state != TextureStates.DECLARED) continue
|
||||||
|
|
||||||
|
latch.inc()
|
||||||
|
DefaultThreadPool += SimplePoolRunnable(ThreadPool.HIGH) { texture.load(context); latch.dec() }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected abstract fun load(animationIndex: AtomicInteger, textures: Collection<Texture>)
|
||||||
|
|
||||||
|
fun load(latch: AbstractLatch) {
|
||||||
|
val latch = latch.child(0)
|
||||||
|
load(latch, named.values)
|
||||||
|
load(latch, other)
|
||||||
|
latch.await()
|
||||||
|
|
||||||
|
val animationIndex = AtomicInteger()
|
||||||
|
load(animationIndex, named.values)
|
||||||
|
load(animationIndex, other)
|
||||||
|
|
||||||
|
state = TextureArrayStates.LOADED
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -16,7 +16,7 @@ package de.bixilon.minosoft.gui.rendering.system.base.texture.array
|
|||||||
import de.bixilon.kotlinglm.vec2.Vec2
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
|
|
||||||
data class TextureArrayProperties(
|
data class TextureArrayProperties(
|
||||||
val uvEnd: Vec2,
|
val uvEnd: Vec2?,
|
||||||
val size: Int,
|
val size: Int,
|
||||||
val pixel: Vec2,
|
val pixel: Float,
|
||||||
)
|
)
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/*
|
/*
|
||||||
* Minosoft
|
* Minosoft
|
||||||
* Copyright (C) 2021 Moritz Zwerger
|
* 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 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.
|
||||||
*
|
*
|
||||||
@ -15,8 +15,8 @@ package de.bixilon.minosoft.gui.rendering.system.base.texture.array
|
|||||||
|
|
||||||
enum class TextureArrayStates {
|
enum class TextureArrayStates {
|
||||||
DECLARED,
|
DECLARED,
|
||||||
PRE_LOADED,
|
|
||||||
LOADED,
|
LOADED,
|
||||||
|
UPLOADED,
|
||||||
UNLOADED,
|
UNLOADED,
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
@ -25,6 +25,7 @@ import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.memory.Memo
|
|||||||
import de.bixilon.minosoft.gui.rendering.textures.properties.ImageProperties
|
import de.bixilon.minosoft.gui.rendering.textures.properties.ImageProperties
|
||||||
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
|
import de.bixilon.minosoft.gui.rendering.util.vec.vec2.Vec2iUtil.EMPTY
|
||||||
|
|
||||||
|
@Deprecated("Slow, because of synchronized loading of mcmeta")
|
||||||
class SpriteTexture(private val original: Texture) : Texture {
|
class SpriteTexture(private val original: Texture) : Texture {
|
||||||
override var array: TextureArrayProperties by original::array
|
override var array: TextureArrayProperties by original::array
|
||||||
override var properties: ImageProperties by original::properties
|
override var properties: ImageProperties by original::properties
|
||||||
|
@ -14,15 +14,11 @@
|
|||||||
package de.bixilon.minosoft.gui.rendering.system.opengl.texture
|
package de.bixilon.minosoft.gui.rendering.system.opengl.texture
|
||||||
|
|
||||||
import de.bixilon.kotlinglm.vec2.Vec2
|
import de.bixilon.kotlinglm.vec2.Vec2
|
||||||
|
import de.bixilon.kotlinglm.vec2.Vec2i
|
||||||
import de.bixilon.kutil.cast.CastUtil.unsafeCast
|
import de.bixilon.kutil.cast.CastUtil.unsafeCast
|
||||||
import de.bixilon.kutil.concurrent.pool.DefaultThreadPool
|
|
||||||
import de.bixilon.kutil.concurrent.pool.ThreadPool
|
|
||||||
import de.bixilon.kutil.concurrent.pool.runnable.SimplePoolRunnable
|
|
||||||
import de.bixilon.kutil.latch.AbstractLatch
|
import de.bixilon.kutil.latch.AbstractLatch
|
||||||
import de.bixilon.kutil.latch.SimpleLatch
|
|
||||||
import de.bixilon.minosoft.gui.rendering.RenderContext
|
import de.bixilon.minosoft.gui.rendering.RenderContext
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.shader.NativeShader
|
import de.bixilon.minosoft.gui.rendering.system.base.shader.NativeShader
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureStates
|
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.array.StaticTextureArray
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.array.StaticTextureArray
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.array.TextureArrayProperties
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.array.TextureArrayProperties
|
||||||
import de.bixilon.minosoft.gui.rendering.system.base.texture.array.TextureArrayStates
|
import de.bixilon.minosoft.gui.rendering.system.base.texture.array.TextureArrayStates
|
||||||
@ -46,92 +42,17 @@ class OpenGLTextureArray(
|
|||||||
async: Boolean,
|
async: Boolean,
|
||||||
mipmaps: Int,
|
mipmaps: Int,
|
||||||
) : StaticTextureArray(context, async, mipmaps) {
|
) : StaticTextureArray(context, async, mipmaps) {
|
||||||
private var textureIds = IntArray(TEXTURE_RESOLUTION_ID_MAP.size) { -1 }
|
private var handles = IntArray(RESOLUTIONS.size) { -1 }
|
||||||
|
|
||||||
private val texturesByResolution = Array<MutableList<Texture>>(TEXTURE_RESOLUTION_ID_MAP.size) { mutableListOf() }
|
private val resolution = Array<MutableList<Texture>>(RESOLUTIONS.size) { mutableListOf() }
|
||||||
private val lastTextureId = IntArray(TEXTURE_RESOLUTION_ID_MAP.size)
|
private val lastTextureId = IntArray(RESOLUTIONS.size)
|
||||||
|
|
||||||
init {
|
init {
|
||||||
context.system.unsafeCast<OpenGLRenderSystem>().textureBindingIndex += TEXTURE_RESOLUTION_ID_MAP.size
|
context.system.unsafeCast<OpenGLRenderSystem>().textureBindingIndex += RESOLUTIONS.size
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
private fun preLoad(latch: AbstractLatch, textures: Collection<Texture>) {
|
private fun upload(resolution: Int, textures: List<Texture>): Int {
|
||||||
for (texture in textures) {
|
|
||||||
if (texture.state != TextureStates.DECLARED) {
|
|
||||||
latch.dec()
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
DefaultThreadPool += SimplePoolRunnable(ThreadPool.HIGH) { texture.load(context); latch.dec() }
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun preLoad(animationIndex: AtomicInteger, textures: Collection<Texture>) {
|
|
||||||
for (texture in textures) {
|
|
||||||
check(texture.size.x <= TEXTURE_MAX_RESOLUTION) { "Texture's width exceeds $TEXTURE_MAX_RESOLUTION (${texture.size.x})" }
|
|
||||||
check(texture.size.y <= TEXTURE_MAX_RESOLUTION) { "Texture's height exceeds $TEXTURE_MAX_RESOLUTION (${texture.size.y})" }
|
|
||||||
|
|
||||||
|
|
||||||
var arrayId = -1
|
|
||||||
var arrayResolution = -1
|
|
||||||
|
|
||||||
for (i in TEXTURE_RESOLUTION_ID_MAP.indices) {
|
|
||||||
arrayResolution = TEXTURE_RESOLUTION_ID_MAP[i]
|
|
||||||
if (texture.size.x <= arrayResolution && texture.size.y <= arrayResolution) {
|
|
||||||
arrayId = i
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
val uvEnd: Vec2? = if (texture.size.x == arrayResolution && texture.size.y == arrayResolution) {
|
|
||||||
null
|
|
||||||
} else {
|
|
||||||
Vec2(texture.size) / arrayResolution
|
|
||||||
}
|
|
||||||
val singlePixelSize = Vec2(1.0f) / arrayResolution
|
|
||||||
val array = TextureArrayProperties(uvEnd ?: Vec2(1.0f, 1.0f), arrayResolution, singlePixelSize)
|
|
||||||
|
|
||||||
if (texture is SpriteTexture) {
|
|
||||||
val animationIndex = animationIndex.getAndIncrement()
|
|
||||||
val animation = TextureAnimation(texture)
|
|
||||||
animator.animations += animation
|
|
||||||
texture.renderData = OpenGLTextureData(-1, -1, uvEnd, animationIndex)
|
|
||||||
for (split in texture.splitTextures) {
|
|
||||||
split.renderData = OpenGLTextureData(arrayId, lastTextureId[arrayId]++, uvEnd, animationIndex)
|
|
||||||
split.array = array
|
|
||||||
texturesByResolution[arrayId] += split
|
|
||||||
}
|
|
||||||
for (frame in texture.properties.animation!!.frames) {
|
|
||||||
frame.texture = texture.splitTextures[frame.index]
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
texturesByResolution[arrayId] += texture
|
|
||||||
texture.renderData = OpenGLTextureData(arrayId, lastTextureId[arrayId]++, uvEnd, -1)
|
|
||||||
texture.array = array
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Synchronized
|
|
||||||
override fun load(latch: AbstractLatch) {
|
|
||||||
if (state == TextureArrayStates.LOADED || state == TextureArrayStates.PRE_LOADED) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
val preLoadLatch = SimpleLatch(named.size + other.size)
|
|
||||||
preLoad(preLoadLatch, named.values)
|
|
||||||
preLoad(preLoadLatch, other)
|
|
||||||
preLoadLatch.await()
|
|
||||||
|
|
||||||
val animationIndex = AtomicInteger()
|
|
||||||
preLoad(animationIndex, named.values)
|
|
||||||
preLoad(animationIndex, other)
|
|
||||||
|
|
||||||
state = TextureArrayStates.PRE_LOADED
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
private fun loadSingleArray(resolution: Int, textures: List<Texture>): Int {
|
|
||||||
val textureId = OpenGLTextureUtil.createTextureArray(mipmaps)
|
val textureId = OpenGLTextureUtil.createTextureArray(mipmaps)
|
||||||
|
|
||||||
for (level in 0..mipmaps) {
|
for (level in 0..mipmaps) {
|
||||||
@ -154,22 +75,20 @@ class OpenGLTextureArray(
|
|||||||
|
|
||||||
|
|
||||||
override fun upload(latch: AbstractLatch?) {
|
override fun upload(latch: AbstractLatch?) {
|
||||||
var totalLayers = 0
|
var total = 0
|
||||||
for ((index, textures) in texturesByResolution.withIndex()) {
|
for ((index, textures) in resolution.withIndex()) {
|
||||||
if (textures.isEmpty()) {
|
if (textures.isEmpty()) continue
|
||||||
continue
|
handles[index] = upload(RESOLUTIONS[index], textures)
|
||||||
}
|
total += textures.size
|
||||||
textureIds[index] = loadSingleArray(TEXTURE_RESOLUTION_ID_MAP[index], textures)
|
|
||||||
totalLayers += textures.size
|
|
||||||
}
|
}
|
||||||
Log.log(LogMessageType.RENDERING, LogLevels.VERBOSE) { "Loaded ${named.size} textures containing ${animator.animations.size} animated ones, split into $totalLayers layers!" }
|
Log.log(LogMessageType.RENDERING, LogLevels.VERBOSE) { "Loaded ${named.size} textures containing ${animator.animations.size} animated ones, split into $total layers!" }
|
||||||
|
|
||||||
animator.init()
|
animator.init()
|
||||||
state = TextureArrayStates.LOADED
|
state = TextureArrayStates.UPLOADED
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun activate() {
|
override fun activate() {
|
||||||
for ((index, textureId) in textureIds.withIndex()) {
|
for ((index, textureId) in handles.withIndex()) {
|
||||||
if (textureId == -1) {
|
if (textureId == -1) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -182,7 +101,7 @@ class OpenGLTextureArray(
|
|||||||
shader.use()
|
shader.use()
|
||||||
activate()
|
activate()
|
||||||
|
|
||||||
for ((index, textureId) in textureIds.withIndex()) {
|
for ((index, textureId) in handles.withIndex()) {
|
||||||
if (textureId == -1) {
|
if (textureId == -1) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -192,8 +111,71 @@ class OpenGLTextureArray(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
override fun findResolution(size: Vec2i): Vec2i {
|
||||||
const val TEXTURE_MAX_RESOLUTION = 2048
|
if (size.x >= MAX_RESOLUTION || size.y >= MAX_RESOLUTION) return Vec2i(MAX_RESOLUTION)
|
||||||
val TEXTURE_RESOLUTION_ID_MAP = intArrayOf(16, 32, 64, 128, 256, 512, 1024, TEXTURE_MAX_RESOLUTION) // A 12x12 texture will be saved in texture id 0 (in 0 are only 16x16 textures). Animated textures get split
|
val array = findArray(size)
|
||||||
|
if (array < 0) return Vec2i(0, 0)
|
||||||
|
return Vec2i(RESOLUTIONS[array])
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun findArray(size: Vec2i): Int {
|
||||||
|
for ((index, resolution) in RESOLUTIONS.withIndex()) {
|
||||||
|
if (size.x > resolution || size.y > resolution) continue
|
||||||
|
return index
|
||||||
|
}
|
||||||
|
|
||||||
|
return -1
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun load(animationIndex: AtomicInteger, arrayId: Int, texture: Texture) {
|
||||||
|
val resolution = RESOLUTIONS[arrayId]
|
||||||
|
val pixel = PIXEL[arrayId]
|
||||||
|
val size = texture.size
|
||||||
|
|
||||||
|
val uvEnd = if (size.x == resolution && size.y == resolution) null else Vec2(size) / resolution
|
||||||
|
val array = TextureArrayProperties(uvEnd, resolution, pixel)
|
||||||
|
|
||||||
|
if (texture !is SpriteTexture) {
|
||||||
|
this.resolution[arrayId] += texture
|
||||||
|
texture.renderData = OpenGLTextureData(arrayId, lastTextureId[arrayId]++, uvEnd, -1)
|
||||||
|
texture.array = array
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
val animationIndex = animationIndex.getAndIncrement()
|
||||||
|
val animation = TextureAnimation(texture)
|
||||||
|
animator.animations += animation
|
||||||
|
|
||||||
|
texture.renderData = OpenGLTextureData(-1, -1, uvEnd, animationIndex)
|
||||||
|
for (split in texture.splitTextures) {
|
||||||
|
split.renderData = OpenGLTextureData(arrayId, lastTextureId[arrayId]++, uvEnd, animationIndex)
|
||||||
|
split.array = array
|
||||||
|
this.resolution[arrayId] += split
|
||||||
|
}
|
||||||
|
for (frame in texture.properties.animation!!.frames) {
|
||||||
|
frame.texture = texture.splitTextures[frame.index]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun load(animationIndex: AtomicInteger, textures: Collection<Texture>) {
|
||||||
|
for (texture in textures) {
|
||||||
|
if (texture.size.x > MAX_RESOLUTION || texture.size.y > MAX_RESOLUTION) {
|
||||||
|
Log.log(LogMessageType.LOADING, LogLevels.WARN) { "Texture $texture exceeds max resolution ($MAX_RESOLUTION): ${texture.size}" }
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
val arrayId = findArray(texture.size)
|
||||||
|
if (arrayId == -1) {
|
||||||
|
Log.log(LogMessageType.LOADING, LogLevels.WARN) { "Can not find texture array for $arrayId" }
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
load(animationIndex, arrayId, texture)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private companion object {
|
||||||
|
const val MAX_RESOLUTION = 2048
|
||||||
|
val RESOLUTIONS = intArrayOf(16, 32, 64, 128, 256, 512, 1024, MAX_RESOLUTION) // A 12x12 texture will be saved in texture id 0 (in 0 are only 16x16 textures). Animated textures get split
|
||||||
|
val PIXEL = FloatArray(RESOLUTIONS.size) { 1.0f / RESOLUTIONS[it] }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user