100 lines
3.0 KiB
Kotlin
100 lines
3.0 KiB
Kotlin
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
|
||
}
|
||
}
|