package ru.dbotthepony.kstarbound.client.render import org.lwjgl.opengl.GL46.* import ru.dbotthepony.kstarbound.client.gl.program.GLShaderProgram import ru.dbotthepony.kstarbound.client.gl.VertexArrayObject import ru.dbotthepony.kstarbound.client.gl.checkForGLError import ru.dbotthepony.kstarbound.client.gl.vertex.AbstractVertexBuilder import ru.dbotthepony.kvector.api.IFloatMatrix import ru.dbotthepony.kvector.matrix.Matrix4fStack /** * Служит для быстрой настройки состояния для будущей отрисовки * * Установка текстурных блоков, программы, самих текстур и загрузка юниформ должна осуществляться тут * * Класс обязан быть наследован для осмысленных результатов * * Ожидается, что состояние будет выставлено ПОЛНОСТЬЮ, т.е. НИКАКОЙ предыдущий код НЕ МОЖЕТ повлиять на результат выполнения * шейдерной программы, которая связанна с этим объектом (за исключением не вызова [setTransform] внешним кодом) */ open class ConfiguredShaderProgram( val program: GLShaderProgram, ) { private val transformLocation = program["_transform"] open fun setTransform(value: IFloatMatrix<*>) { transformLocation?.set(value) } /** * Вызывается перед началом отрисовки */ open fun setup() { program.use() } } /** * Запечённый статичный меш, позволяет быстро отрисовать меш со всеми параметрами * с заданной матрицей трансформации */ class ConfiguredStaticMesh( val programState: ConfiguredShaderProgram, val indexCount: Int, val vao: VertexArrayObject, val elementIndexType: Int, ) : AutoCloseable { private var onClose = {} constructor(programState: ConfiguredShaderProgram, builder: AbstractVertexBuilder<*>) : this( programState, builder.indexCount, programState.program.state.newVAO(), builder.elementIndexType, ) { val vbo = programState.program.state.newVBO() val ebo = programState.program.state.newEBO() onClose = { vbo.close() ebo.close() } vao.bind() vbo.bind() ebo.bind() builder.upload(vbo, ebo, GL_STATIC_DRAW) builder.attributes.apply(vao, true) vao.unbind() vbo.unbind() ebo.unbind() } fun render(transform: IFloatMatrix<*>? = null) { check(isValid) { "$this is no longer valid" } programState.setup() if (transform != null) { programState.setTransform(transform) } vao.bind() glDrawElements(GL_TRIANGLES, indexCount, elementIndexType, 0L) checkForGLError() } fun renderStacked(transform: Matrix4fStack) = render(transform.last) var isValid = true private set override fun close() { vao.close() onClose.invoke() isValid = false } }