commonMain.ru.casperix.opengl.renderer.DeviceGeometryData.kt Maven / Gradle / Ivy
package ru.casperix.opengl.renderer
import ru.casperix.misc.Disposable
import ru.casperix.opengl.core.*
import ru.casperix.opengl.renderer.impl.VertexAttributeLayout
import ru.casperix.renderer.vector.vertex.ColorFormat
import ru.casperix.renderer.vector.vertex.VertexAttributes
class DeviceGeometryData(val attributes: VertexAttributes) :
Disposable {
private val vertexBufferId = glGenBuffer()
private val indexBufferId = glGenBuffer()
private val vaoId = glGenVertexArray()
val vertexSize = attributes.calculateVertexSize()
var isDisposed = false; private set
private var useIndices = false
var verticesAmount = 0; private set
var indicesAmount = 0; private set
init {
glBindVertexArray(vaoId)
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferId)
var offset = 0
if (attributes.hasPosition2) offset += appendAttribute(VertexAttributeLayout.POSITION2, offset)
if (attributes.hasTextureCoord) offset += appendAttribute(VertexAttributeLayout.TEXTURE_COORD, offset)
if (attributes.hasTangent) offset += appendAttribute(VertexAttributeLayout.TANGENT, offset)
if (attributes.hasPosition3) offset += appendAttribute(VertexAttributeLayout.POSITION3, offset)
if (attributes.color == ColorFormat.BGR || attributes.color == ColorFormat.RGB) offset += appendAttribute(VertexAttributeLayout.COLOR3, offset)
if (attributes.color == ColorFormat.BGRA || attributes.color == ColorFormat.RGBA) offset += appendAttribute(VertexAttributeLayout.COLOR4, offset)
}
private fun appendAttribute(vertexAttribute: VertexAttributeLayout, offset: Int): Int {
val size = vertexAttribute.size
val layoutIndex = vertexAttribute.layout
glEnableVertexAttribArray(layoutIndex)
glVertexAttribPointer(layoutIndex, size, GL_FLOAT, false, vertexSize * 4, offset * 4)
return size
}
override fun dispose() {
glDeleteVertexArrays(intArrayOf(vaoId))
glDeleteBuffers(intArrayOf(vertexBufferId, indexBufferId))
isDisposed = true
}
fun bind() {
glBindVertexArray(vaoId)
glBindBuffer(GL_ARRAY_BUFFER, vertexBufferId)
if (useIndices) {
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, indexBufferId)
}
}
fun reset() {
verticesAmount = 0
indicesAmount = 0
}
fun uploadData(stateController: StateController, vertices: FloatArray, indices: UIntArray?, isStatic: Boolean) {
useIndices = indices != null
stateController.setGeometry(this)
val glUsageFlag = if (isStatic) {
GL_STATIC_DRAW
} else {
GL_DYNAMIC_DRAW
}
glBufferData(GL_ARRAY_BUFFER, vertices, glUsageFlag)
if (indices != null) {
glBufferData(GL_ELEMENT_ARRAY_BUFFER, indices.asIntArray(), glUsageFlag)
indicesAmount = indices.size
} else {
indicesAmount = 0
}
verticesAmount = vertices.size / vertexSize
}
fun draw() {
if (useIndices && indicesAmount > 0) {
glDrawElements(GL_TRIANGLES, indicesAmount, GL_UNSIGNED_INT, 0)
} else if (verticesAmount > 0){
glDrawArrays(GL_TRIANGLES, 0, verticesAmount)
}
}
companion object {
fun unbind() {
glBindVertexArray(0)
glBindBuffer(GL_ARRAY_BUFFER, 0)
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
}
}
}