commonMain.ru.casperix.opengl.renderer.impl.MaterialBinder.kt Maven / Gradle / Ivy
package ru.casperix.opengl.renderer.impl
import ru.casperix.opengl.core.*
import ru.casperix.opengl.renderer.exp.TileMapMaterial
import ru.casperix.opengl.renderer.TextureConfig
import ru.casperix.opengl.renderer.TextureProvider
import ru.casperix.opengl.renderer.shader.ShaderController
import ru.casperix.opengl.renderer.shader.ShaderUniform
import ru.casperix.opengl.renderer.texture.GLTexture
import ru.casperix.renderer.material.Material
import ru.casperix.renderer.material.SimpleMaterial
@ExperimentalUnsignedTypes
class MaterialBinder(config: TextureConfig) {
private val textureBinder = TextureProvider()
private var textureLayers = Array(80) { null }
data class TextureLayer(val texture: GLTexture, val shader: ShaderUniform)
fun setupMaterialAttributes(controller: ShaderController, material: Material) {
(material as? SimpleMaterial)?.apply {
color?.let {
controller.uMaterialColor?.set(it.toColor4f())
}
albedoMap?.let {
setTexture(controller.uAlbedoTexture, 0, textureBinder.getTexture(it))
}
normalMap?.let {
setTexture(controller.uNormalTexture, 1, textureBinder.getTexture(it))
}
specularMap?.let {
setTexture(controller.uSpecularTexture, 2, textureBinder.getTexture(it))
}
}
(material as? TileMapMaterial)?.apply {
textureArray.let {
setTexture(controller.uTextureArray, 0, textureBinder.getTexture(it))
}
tileMap.let {
setTexture(controller.uTileMapTexture, 1, textureBinder.getTexture(it))
}
controller.uTexScale?.set(texScale)
controller.uTileSmoothMode?.set(smooth.ordinal)
}
}
private fun setTexture(textureLocation: ShaderUniform?, textureChannel: Int, texture: GLTexture) {
if (textureLocation == null) {
return
}
if (textureChannel < 0 || textureChannel >= 80) {
throw Error("Texture layer must be positive and smaller than 80")
}
val layer = TextureLayer(texture, textureLocation)
if (textureLayers[textureChannel] == layer) return
textureLayers[textureChannel] = layer
textureLocation.set(textureChannel, texture)
}
fun unbind() {
textureLayers.forEachIndexed { channel, textureLayer ->
if (textureLayer != null) {
glActiveTexture(GL_TEXTURE0 + channel)
glBindTexture(GL_TEXTURE_2D, 0)
glBindTexture(GL_TEXTURE_2D_ARRAY, 0)
glBindTexture(GL_TEXTURE_CUBE_MAP, 0)
textureLayers[channel] = null
}
}
}
}