All Downloads are FREE. Search and download functionalities are using the official Maven repository.

commonMain.ru.casperix.opengl.renderer.texture.GLTexture2D.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.Texture2D

class GLTexture2D(val texture: Texture2D) : GLTexture {
    private val logger = KotlinLogging.logger { }
    private val handle = GLTextureHandlerProvider.next()
    private var isDisposed = false
    val isPowerOf2 get() =  isPowerOf2(texture.map.width) && isPowerOf2(texture.map.height)

    init {
        glBindTexture(GL_TEXTURE_2D, handle)

        upload()

        texture.config.apply {
            val actualMipMap = useMipMap && isPowerOf2
            if (useMipMap != actualMipMap) {
                logger.warn { "Mip-map not allowed for rectangle texture ${texture.map.name} (${texture.map.dimension}) " }
            }

            if (actualMipMap) {
                glGenerateMipmap(GL_TEXTURE_2D)
            }

            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, asGLWrap(uWrap))
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, asGLWrap(vWrap))
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, asGLMinFilter(minFilter, actualMipMap))
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, asGLMagFilter(magFilter, actualMipMap))
        }

        logger.debug { "Texture created: ${toShortString()}" }
    }

    override fun dispose() {
        glDeleteTexture(handle)
        isDisposed = true
        logger.debug { "Texture disposed: ${toShortString()}" }
    }

    private fun toShortString(): String {
        return "id: $handle; size: ${texture.map.width}x${texture.map.height}"
    }

    private fun upload() {
        val image = texture.map
        val data = image.byteArray.data
        val bytesPerPixel = image.pixelCodec.bytesPerPixel
        val openGlFormat = when (bytesPerPixel) {
            3 -> GL_RGB8
            4 -> GL_RGBA8
            else -> throw Exception("Unsupported bytesPerPixel: $bytesPerPixel")
        }
        val dataFormat = when (bytesPerPixel) {
            3 -> GL_RGB
            4 -> GL_RGBA
            else -> throw Exception("Unsupported bytesPerPixel: $bytesPerPixel")
        }
        glTexImage2D(
            GL_TEXTURE_2D,
            0,
            openGlFormat,
            image.width,
            image.height,
            0,
            dataFormat,
            GL_UNSIGNED_BYTE,
            data.asByteArray()
        )
    }

    override fun bind(channel: Int) {
        glActiveTexture(GL_TEXTURE0 + channel)
        glBindTexture(GL_TEXTURE_2D, handle)
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy