commonMain.ru.casperix.opengl.renderer.ShaderProvider.kt Maven / Gradle / Ivy
package ru.casperix.opengl.renderer
import ru.casperix.opengl.renderer.exp.TileMapMaterial
import ru.casperix.opengl.renderer.generated.Resources
import ru.casperix.opengl.core.misc.ShaderFactory
import ru.casperix.opengl.renderer.impl.ShaderAttributes
import ru.casperix.opengl.renderer.shader.ShaderBuffer
import ru.casperix.opengl.renderer.shader.ShaderController
import ru.casperix.renderer.material.Material
import ru.casperix.renderer.material.SimpleMaterial
import ru.casperix.renderer.vector.vertex.ColorFormat
import ru.casperix.renderer.vector.vertex.VertexAttributes
@ExperimentalUnsignedTypes
class ShaderProvider(val config: OpenGlRendererConfig) {
private val shaderMap = mutableMapOf()
private val simpleShader = ShaderReference(Resources.shader2d_vert, Resources.shader2d_frag)
class ShaderReference(val vertexShaderSource: String, val fragmentShaderSource: String)
data class ShaderKey(val attributes: VertexAttributes, val material: Material)
fun getOrCreate(
vertexAttributes: VertexAttributes,
material: Material
): ShaderController {
return shaderMap.getOrPut(ShaderKey(vertexAttributes, material)) {
val attributes = if (material is SimpleMaterial) {
ShaderAttributes(
hasMaterialColor = material.color != null,
hasMaterialAlbedoMap = material.albedoMap != null,
hasMaterialNormal = material.normalMap != null,
hasMaterialNormalMap = material.normalMap != null,
hasVertexColor3 = vertexAttributes.color == ColorFormat.BGR || vertexAttributes.color == ColorFormat.RGB,
hasVertexColor4 = vertexAttributes.color == ColorFormat.BGRA || vertexAttributes.color == ColorFormat.RGBA,
)
} else if (material is TileMapMaterial) {
ShaderAttributes(
hasMaterialTileMap = true,
hasMaterialTileGird = material.gird,
hasMaterialNormal = true,
hasMaterialTextureArray = true,
)
} else {
ShaderAttributes()
}
createSimpleShader(attributes)
}
}
private fun createSimpleShader(shaderAttributes: ShaderAttributes): ShaderController = shaderAttributes.run {
val shaderDefines = mutableSetOf()
if (config.discardAlpha) {
shaderDefines += "CONFIG_DISCARD_ALPHA"
}
if (config.gammaCorrection) {
shaderDefines += "CONFIG_GAMMA_CORRECTION"
}
if (hasMaterialColor) {
shaderDefines += "MATERIAL_COLOR"
}
if (hasMaterialAlbedoMap) {
shaderDefines += "MATERIAL_ALBEDO_MAP"
}
if (hasMaterialTileMap) {
shaderDefines += "MATERIAL_TILE_MAP"
}
if (hasMaterialTileGird) {
shaderDefines += "MATERIAL_TILE_GIRD"
}
if (hasMaterialTextureArray) {
shaderDefines += "MATERIAL_TEXTURE_ARRAY"
}
if (hasMaterialNormal) {
shaderDefines += "MATERIAL_NORMAL"
}
if (hasMaterialNormalMap) {
shaderDefines += "MATERIAL_NORMAL_MAP"
}
if (hasMaterialSpecularMap) {
shaderDefines += "MATERIAL_SPECULAR_MAP"
}
if (hasMaterialAlbedoMap || hasMaterialNormalMap || hasMaterialSpecularMap || hasMaterialTextureArray) {
shaderDefines += "VERTEX_TEXTURE_COORD"
}
if (hasVertexColor) {
shaderDefines += "VERTEX_COLOR"
}
if (hasVertexColor3) {
shaderDefines += "VERTEX_COLOR3"
}
if (hasVertexColor4) {
shaderDefines += "VERTEX_COLOR4"
}
val vertexShader = ShaderFactory.setup(simpleShader.vertexShaderSource, shaderDefines)
val fragmentShader = ShaderFactory.setup(simpleShader.fragmentShaderSource, shaderDefines)
val buffer = ShaderBuffer(vertexShader, fragmentShader, null)
return ShaderController(buffer, this)
}
}