commonMain.ru.casperix.opengl.renderer.texture.GLTexture2DArray.kt Maven / Gradle / Ivy
package ru.casperix.opengl.renderer.texture
import io.github.oshai.kotlinlogging.KotlinLogging
import ru.casperix.opengl.core.*
import ru.casperix.opengl.renderer.texture.GLTexture.Companion.asGLMagFilter
import ru.casperix.opengl.renderer.texture.GLTexture.Companion.asGLMinFilter
import ru.casperix.opengl.renderer.texture.GLTexture.Companion.asGLWrap
import ru.casperix.renderer.material.Texture2DArray
import ru.casperix.renderer.pixel_map.PixelMap
class GLTexture2DArray(val texture: Texture2DArray) : GLTexture {
val logger = KotlinLogging.logger { }
val handle = GLTextureHandlerProvider.next()
// constructor(colorProvider: ColorCube) : this(colorProvider.minX, colorProvider.maxX, colorProvider.minY, colorProvider.maxY, colorProvider.minZ, colorProvider.maxZ)
class PixelMap3D(val bytes: UByteArray, val width: Int, val height: Int, val depth: Int)
init {
glBindTexture(GL_TEXTURE_2D_ARRAY, handle)
texture.config.apply {
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_S, asGLWrap(uWrap))
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_T, asGLWrap(vWrap))
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_WRAP_R, asGLWrap(wWrap))
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MIN_FILTER, asGLMinFilter(minFilter, useMipMap))
glTexParameteri(GL_TEXTURE_2D_ARRAY, GL_TEXTURE_MAG_FILTER, asGLMagFilter(magFilter, useMipMap))
}
texture.apply {
val bytes = toMap3D(maps)
loadData(bytes, maps.size)
}
if (texture.config.useMipMap) {
glGenerateMipmap(GL_TEXTURE_2D_ARRAY)
}
glBindTexture(GL_TEXTURE_2D_ARRAY, 0)
logger.debug { "Texture created: ${toShortString()}" }
}
override fun dispose() {
glDeleteTexture(handle)
logger.debug { "Texture disposed: ${toShortString()}" }
}
private fun toShortString(): String {
return "id: $handle; size: ${texture.maps.first().width}x${texture.maps.first().height}x${texture.maps.size}"
}
private fun toMap3D(maps: List): PixelMap3D {
if (maps.isEmpty()) return PixelMap3D(UByteArray(0), 0, 0, 0)
val first = maps.first()
val size = first.byteArray.data.size
val output = UByteArray(size * maps.size)
maps.forEachIndexed { index, next ->
if (next.pixelCodec != first.pixelCodec) {
throw Exception("Expected all codec is: ${first.pixelCodec}. But actual codec is ${next.pixelCodec}")
}
if (next.byteArray.data.size != size) {
throw Exception("Expected all size is: $size. But actual size is ${next.byteArray.data.size} for '${next.name}'")
}
next.byteArray.data.copyInto(output, index * size)
}
return PixelMap3D(output, first.width, first.height, maps.size)
}
private fun loadData(map: PixelMap3D, layerAmount: Int) {
glTexImage3D(
GL_TEXTURE_2D_ARRAY,
0,
GL_RGBA,
map.width,
map.height,
layerAmount,
0,
GL_RGBA,
GL_UNSIGNED_BYTE,
map.bytes.toByteArray()
)
}
override fun bind(channel: Int) {
glActiveTexture(GL_TEXTURE0 + channel)
glBindTexture(GL_TEXTURE_2D_ARRAY, handle)
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy