OpenGL object tracking cleanup

This commit is contained in:
DBotThePony 2023-09-20 14:51:33 +07:00
parent 1e8cc5898d
commit 85e81a0b0b
Signed by: DBot
GPG Key ID: DCC23B5715498507
12 changed files with 164 additions and 222 deletions

View File

@ -8,6 +8,7 @@ import org.lwjgl.glfw.Callbacks
import org.lwjgl.glfw.GLFW import org.lwjgl.glfw.GLFW
import org.lwjgl.glfw.GLFWErrorCallback import org.lwjgl.glfw.GLFWErrorCallback
import org.lwjgl.opengl.GL import org.lwjgl.opengl.GL
import org.lwjgl.opengl.GL11
import org.lwjgl.opengl.GL46.* import org.lwjgl.opengl.GL46.*
import org.lwjgl.opengl.GLCapabilities import org.lwjgl.opengl.GLCapabilities
import org.lwjgl.system.MemoryStack import org.lwjgl.system.MemoryStack
@ -21,15 +22,14 @@ import ru.dbotthepony.kstarbound.client.gl.BlendFunc
import ru.dbotthepony.kstarbound.client.gl.GLFrameBuffer import ru.dbotthepony.kstarbound.client.gl.GLFrameBuffer
import ru.dbotthepony.kstarbound.client.gl.GLTexture2D import ru.dbotthepony.kstarbound.client.gl.GLTexture2D
import ru.dbotthepony.kstarbound.client.gl.ScissorRect import ru.dbotthepony.kstarbound.client.gl.ScissorRect
import ru.dbotthepony.kstarbound.client.gl.VBOType
import ru.dbotthepony.kstarbound.client.gl.VertexArrayObject import ru.dbotthepony.kstarbound.client.gl.VertexArrayObject
import ru.dbotthepony.kstarbound.client.gl.VertexBufferObject import ru.dbotthepony.kstarbound.client.gl.BufferObject
import ru.dbotthepony.kstarbound.client.gl.checkForGLError import ru.dbotthepony.kstarbound.client.gl.checkForGLError
import ru.dbotthepony.kstarbound.client.gl.properties.GLStateFuncTracker import ru.dbotthepony.kstarbound.client.gl.properties.GLStateFuncTracker
import ru.dbotthepony.kstarbound.client.gl.properties.GLStateGenericTracker import ru.dbotthepony.kstarbound.client.gl.properties.GLGenericTracker
import ru.dbotthepony.kstarbound.client.gl.properties.GLObjectTracker
import ru.dbotthepony.kstarbound.client.gl.properties.GLStateIntTracker import ru.dbotthepony.kstarbound.client.gl.properties.GLStateIntTracker
import ru.dbotthepony.kstarbound.client.gl.properties.GLStateSwitchTracker import ru.dbotthepony.kstarbound.client.gl.properties.GLStateSwitchTracker
import ru.dbotthepony.kstarbound.client.gl.properties.TexturesTracker
import ru.dbotthepony.kstarbound.client.gl.shader.GLPrograms import ru.dbotthepony.kstarbound.client.gl.shader.GLPrograms
import ru.dbotthepony.kstarbound.client.gl.shader.GLShader import ru.dbotthepony.kstarbound.client.gl.shader.GLShader
import ru.dbotthepony.kstarbound.client.gl.shader.GLShaderProgram import ru.dbotthepony.kstarbound.client.gl.shader.GLShaderProgram
@ -237,8 +237,6 @@ class StarboundClient : Closeable {
putDebugLog("Initialized GLFW window") putDebugLog("Initialized GLFW window")
} }
val programs = GLPrograms()
val flat2DLines by lazy { StreamVertexBuilder(GLAttributeList.VEC2F, GeometryType.LINES) } val flat2DLines by lazy { StreamVertexBuilder(GLAttributeList.VEC2F, GeometryType.LINES) }
val flat2DTriangles by lazy { StreamVertexBuilder(GLAttributeList.VEC2F, GeometryType.TRIANGLES) } val flat2DTriangles by lazy { StreamVertexBuilder(GLAttributeList.VEC2F, GeometryType.TRIANGLES) }
val flat2DTexturedQuads by lazy { StreamVertexBuilder(GLAttributeList.VERTEX_TEXTURE, GeometryType.QUADS) } val flat2DTexturedQuads by lazy { StreamVertexBuilder(GLAttributeList.VERTEX_TEXTURE, GeometryType.QUADS) }
@ -308,7 +306,7 @@ class StarboundClient : Closeable {
var textureUnpackAlignment by GLStateIntTracker(::glPixelStorei, GL_UNPACK_ALIGNMENT, 4) var textureUnpackAlignment by GLStateIntTracker(::glPixelStorei, GL_UNPACK_ALIGNMENT, 4)
var scissorRect by GLStateGenericTracker(ScissorRect(0, 0, 0, 0)) { var scissorRect by GLGenericTracker(ScissorRect(0, 0, 0, 0)) {
// require(it.x >= 0) { "Invalid X ${it.x}"} // require(it.x >= 0) { "Invalid X ${it.x}"}
// require(it.y >= 0) { "Invalid Y ${it.y}"} // require(it.y >= 0) { "Invalid Y ${it.y}"}
@ -320,130 +318,42 @@ class StarboundClient : Closeable {
var depthTest by GLStateSwitchTracker(GL_DEPTH_TEST) var depthTest by GLStateSwitchTracker(GL_DEPTH_TEST)
var VBO: VertexBufferObject? = null var vbo by GLObjectTracker<BufferObject.VBO>(::glBindBuffer, GL_ARRAY_BUFFER)
set(value) { var ebo by GLObjectTracker<BufferObject.EBO>(::glBindBuffer, GL_ELEMENT_ARRAY_BUFFER)
ensureSameThread() var vao by GLObjectTracker<VertexArrayObject>(::glBindVertexArray)
var framebuffer by GLObjectTracker<GLFrameBuffer>(::glBindFramebuffer, GL_FRAMEBUFFER)
var program by GLObjectTracker<GLShaderProgram>(::glUseProgram)
if (field !== value) { val maxTextureBlocks = glGetInteger(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS)
isMe(value?.client) private val textures = Array(maxTextureBlocks) { GLObjectTracker<GLTexture2D>(GL11::glBindTexture, GL_TEXTURE_2D) }
require(value?.isArray != false) { "Provided buffer object is not of Array type" }
glBindBuffer(GL_ARRAY_BUFFER, value?.pointer ?: 0)
checkForGLError("Setting Vertex Buffer Object")
field = value
}
}
var EBO: VertexBufferObject? = null
set(value) {
ensureSameThread()
if (field !== value) {
isMe(value?.client)
require(value?.isElementArray != false) { "Provided buffer object is not of Array type" }
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, value?.pointer ?: 0)
checkForGLError("Setting Element Buffer Object")
field = value
}
}
var VAO: VertexArrayObject? = null
set(value) {
ensureSameThread()
if (field !== value) {
isMe(value?.client)
glBindVertexArray(value?.pointer ?: 0)
checkForGLError("Setting Vertex Array Object")
field = value
}
}
var readFramebuffer: GLFrameBuffer? = null
set(value) {
ensureSameThread()
if (field === value) return
isMe(value?.client)
field = value
if (value == null) {
glBindFramebuffer(GL_READ_FRAMEBUFFER, 0)
checkForGLError()
return
}
glBindFramebuffer(GL_READ_FRAMEBUFFER, value.pointer)
checkForGLError()
}
var writeFramebuffer: GLFrameBuffer? = null
set(value) {
ensureSameThread()
if (field === value) return
isMe(value?.client)
field = value
if (value == null) {
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0)
checkForGLError()
return
}
glBindFramebuffer(GL_DRAW_FRAMEBUFFER, value.pointer)
checkForGLError()
}
var framebuffer: GLFrameBuffer?
get() {
val readFramebuffer = readFramebuffer
val writeFramebuffer = writeFramebuffer
if (readFramebuffer == writeFramebuffer) {
return writeFramebuffer
}
return null
}
set(value) {
readFramebuffer = value
writeFramebuffer = value
}
var program: GLShaderProgram? = null
set(value) {
ensureSameThread()
if (value !== field) {
isMe(value?.client)
glUseProgram(value?.pointer ?: 0)
checkForGLError("Setting shader program")
field = value
}
}
var activeTexture = 0 var activeTexture = 0
set(value) { set(value) {
ensureSameThread() ensureSameThread()
if (field != value) { if (field != value) {
require(value >= 0) { "Invalid texture block $value" } require(value in 0 until maxTextureBlocks) { "Texture block out of bounds: $value (max texture blocks is $maxTextureBlocks)" }
require(value < 80) { "Too big texture block index $value, OpenGL 4.6 guarantee only 80!" }
glActiveTexture(GL_TEXTURE0 + value) glActiveTexture(GL_TEXTURE0 + value)
checkForGLError() checkForGLError()
field = value field = value
} }
} }
var texture2D: GLTexture2D? by TexturesTracker(80) var texture2D: GLTexture2D?
get() = textures[activeTexture].get()
set(value) { textures[activeTexture].accept(value) }
var clearColor by GLStateGenericTracker<IStruct4f>(RGBAColor.WHITE) { var clearColor by GLGenericTracker<IStruct4f>(RGBAColor.WHITE) {
val (r, g, b, a) = it val (r, g, b, a) = it
glClearColor(r, g, b, a) glClearColor(r, g, b, a)
} }
var blendFunc by GLStateGenericTracker(BlendFunc()) { var blendFunc by GLGenericTracker(BlendFunc()) {
glBlendFuncSeparate(it.sourceColor.enum, it.destinationColor.enum, it.sourceAlpha.enum, it.destinationAlpha.enum) glBlendFuncSeparate(it.sourceColor.enum, it.destinationColor.enum, it.sourceAlpha.enum, it.destinationAlpha.enum)
} }
val programs = GLPrograms()
init { init {
glActiveTexture(GL_TEXTURE0) glActiveTexture(GL_TEXTURE0)
checkForGLError() checkForGLError()
@ -538,40 +448,8 @@ class StarboundClient : Closeable {
} }
} }
fun bind(obj: VertexBufferObject): VertexBufferObject { fun newVBO() = BufferObject.VBO()
if (obj.type == VBOType.ARRAY) fun newEBO() = BufferObject.EBO()
VBO = obj
else
EBO = obj
return obj
}
fun unbind(obj: VertexBufferObject): VertexBufferObject {
if (obj.type == VBOType.ARRAY)
if (obj == VBO)
VBO = null
else
if (obj == EBO)
EBO = null
return obj
}
fun bind(obj: VertexArrayObject): VertexArrayObject {
VAO = obj
return obj
}
fun unbind(obj: VertexArrayObject): VertexArrayObject {
if (obj == VAO)
VAO = null
return obj
}
fun newVBO() = VertexBufferObject.vbo()
fun newEBO() = VertexBufferObject.ebo()
fun newVAO() = VertexArrayObject() fun newVAO() = VertexArrayObject()
inline fun quadWireframe(color: RGBAColor = RGBAColor.WHITE, lambda: (VertexBuilder) -> Unit) { inline fun quadWireframe(color: RGBAColor = RGBAColor.WHITE, lambda: (VertexBuilder) -> Unit) {

View File

@ -5,41 +5,23 @@ import org.lwjgl.system.MemoryUtil
import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.StarboundClient
import java.nio.ByteBuffer import java.nio.ByteBuffer
enum class VBOType(val glType: Int) { sealed class BufferObject(val glType: Int) : GLObject() {
ARRAY(GL_ARRAY_BUFFER), final override val client = StarboundClient.current()
ELEMENT_ARRAY(GL_ELEMENT_ARRAY_BUFFER), final override val pointer = glGenBuffers()
}
class VertexBufferObject private constructor(val type: VBOType) {
val client = StarboundClient.current()
val pointer = glGenBuffers()
init { init {
checkForGLError("Creating Vertex Buffer Object") checkForGLError("Creating Vertex Buffer Object")
client.registerCleanable(this, ::glDeleteBuffers, pointer) client.registerCleanable(this, ::glDeleteBuffers, pointer)
} }
val isArray get() = type == VBOType.ARRAY fun bufferData(data: ByteBuffer, usage: Int): BufferObject {
val isElementArray get() = type == VBOType.ELEMENT_ARRAY
fun bind(): VertexBufferObject {
client.bind(this)
return this
}
fun unbind(): VertexBufferObject {
client.unbind(this)
return this
}
fun bufferData(data: ByteBuffer, usage: Int): VertexBufferObject {
client.ensureSameThread() client.ensureSameThread()
glNamedBufferData(pointer, data, usage) glNamedBufferData(pointer, data, usage)
checkForGLError() checkForGLError()
return this return this
} }
fun bufferData(data: ByteBuffer, usage: Int, length: Long): VertexBufferObject { fun bufferData(data: ByteBuffer, usage: Int, length: Long): BufferObject {
client.ensureSameThread() client.ensureSameThread()
if (length > data.remaining().toLong()) { if (length > data.remaining().toLong()) {
@ -52,36 +34,51 @@ class VertexBufferObject private constructor(val type: VBOType) {
return this return this
} }
fun bufferData(data: IntArray, usage: Int): VertexBufferObject { fun bufferData(data: IntArray, usage: Int): BufferObject {
client.ensureSameThread() client.ensureSameThread()
glNamedBufferData(pointer, data, usage) glNamedBufferData(pointer, data, usage)
checkForGLError() checkForGLError()
return this return this
} }
fun bufferData(data: FloatArray, usage: Int): VertexBufferObject { fun bufferData(data: FloatArray, usage: Int): BufferObject {
client.ensureSameThread() client.ensureSameThread()
glNamedBufferData(pointer, data, usage) glNamedBufferData(pointer, data, usage)
checkForGLError() checkForGLError()
return this return this
} }
fun bufferData(data: DoubleArray, usage: Int): VertexBufferObject { fun bufferData(data: DoubleArray, usage: Int): BufferObject {
client.ensureSameThread() client.ensureSameThread()
glNamedBufferData(pointer, data, usage) glNamedBufferData(pointer, data, usage)
checkForGLError() checkForGLError()
return this return this
} }
fun bufferData(data: LongArray, usage: Int): VertexBufferObject { fun bufferData(data: LongArray, usage: Int): BufferObject {
client.ensureSameThread() client.ensureSameThread()
glNamedBufferData(pointer, data, usage) glNamedBufferData(pointer, data, usage)
checkForGLError() checkForGLError()
return this return this
} }
companion object { class VBO : BufferObject(GL_ARRAY_BUFFER) {
fun vbo() = VertexBufferObject(VBOType.ARRAY) override fun bind() {
fun ebo() = VertexBufferObject(VBOType.ELEMENT_ARRAY) client.vbo = this
}
override fun unbind() {
if (client.vbo == this) client.vbo = null
}
}
class EBO : BufferObject(GL_ELEMENT_ARRAY_BUFFER) {
override fun bind() {
client.ebo = this
}
override fun unbind() {
if (client.ebo == this) client.ebo = null
}
} }
} }

View File

@ -11,9 +11,9 @@ import org.lwjgl.opengl.GL45.glCheckNamedFramebufferStatus
import org.lwjgl.opengl.GL46 import org.lwjgl.opengl.GL46
import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.StarboundClient
class GLFrameBuffer { class GLFrameBuffer : GLObject() {
val client = StarboundClient.current() override val client = StarboundClient.current()
val pointer = GL46.glGenFramebuffers() override val pointer = GL46.glGenFramebuffers()
init { init {
checkForGLError("Creating framebuffer") checkForGLError("Creating framebuffer")
@ -50,25 +50,12 @@ class GLFrameBuffer {
attachTexture(width, height, format) attachTexture(width, height, format)
} }
fun bind() { override fun bind() {
client.framebuffer = this client.framebuffer = this
} }
fun bindWrite() { override fun unbind() {
client.writeFramebuffer = this if (client.framebuffer == this)
} client.framebuffer = null
fun bindRead() {
client.readFramebuffer = this
}
fun unbind() {
if (client.writeFramebuffer == this) {
client.writeFramebuffer = null
}
if (client.readFramebuffer == this) {
client.readFramebuffer = null
}
} }
} }

View File

@ -0,0 +1,11 @@
package ru.dbotthepony.kstarbound.client.gl
import ru.dbotthepony.kstarbound.client.StarboundClient
abstract class GLObject {
abstract val pointer: Int
abstract val client: StarboundClient
abstract fun bind()
abstract fun unbind()
}

View File

@ -30,9 +30,9 @@ private class GLTexturePropertyTracker(private val flag: Int, private var value:
} }
@Suppress("SameParameterValue") @Suppress("SameParameterValue")
class GLTexture2D(val name: String = "<unknown>") { class GLTexture2D(val name: String = "<unknown>") : GLObject() {
val client = StarboundClient.current() override val client = StarboundClient.current()
val pointer = glGenTextures() override val pointer = glGenTextures()
init { init {
checkForGLError() checkForGLError()
@ -71,9 +71,13 @@ class GLTexture2D(val name: String = "<unknown>") {
var textureWrapS by GLTexturePropertyTracker(GL_TEXTURE_WRAP_S, GL_REPEAT) var textureWrapS by GLTexturePropertyTracker(GL_TEXTURE_WRAP_S, GL_REPEAT)
var textureWrapT by GLTexturePropertyTracker(GL_TEXTURE_WRAP_T, GL_REPEAT) var textureWrapT by GLTexturePropertyTracker(GL_TEXTURE_WRAP_T, GL_REPEAT)
fun bind(): GLTexture2D { override fun bind() {
client.texture2D = this client.texture2D = this
return this }
override fun unbind() {
if (client.texture2D === this)
client.texture2D = null
} }
fun generateMips(): GLTexture2D { fun generateMips(): GLTexture2D {

View File

@ -3,21 +3,22 @@ package ru.dbotthepony.kstarbound.client.gl
import org.lwjgl.opengl.GL46.* import org.lwjgl.opengl.GL46.*
import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.StarboundClient
class VertexArrayObject { class VertexArrayObject : GLObject() {
val client = StarboundClient.current() override val client = StarboundClient.current()
val pointer = glGenVertexArrays() override val pointer = glGenVertexArrays()
init { init {
checkForGLError() checkForGLError()
client.registerCleanable(this, ::glDeleteVertexArrays, pointer) client.registerCleanable(this, ::glDeleteVertexArrays, pointer)
} }
fun bind(): VertexArrayObject { override fun bind() {
return client.bind(this) client.vao = this
} }
fun unbind(): VertexArrayObject { override fun unbind() {
return client.unbind(this) if (client.vao == this)
client.vao = null
} }
fun attribute(position: Int, size: Int, type: Int, normalize: Boolean, stride: Int, offset: Long = 0L): VertexArrayObject { fun attribute(position: Int, size: Int, type: Int, normalize: Boolean, stride: Int, offset: Long = 0L): VertexArrayObject {

View File

@ -5,7 +5,7 @@ import ru.dbotthepony.kstarbound.client.gl.checkForGLError
import kotlin.properties.ReadWriteProperty import kotlin.properties.ReadWriteProperty
import kotlin.reflect.KProperty import kotlin.reflect.KProperty
class GLStateGenericTracker<T>(private var value: T, private val callback: (T) -> Unit) : ReadWriteProperty<StarboundClient, T> { class GLGenericTracker<T>(private var value: T, private val callback: (T) -> Unit) : ReadWriteProperty<StarboundClient, T> {
override fun getValue(thisRef: StarboundClient, property: KProperty<*>): T { override fun getValue(thisRef: StarboundClient, property: KProperty<*>): T {
return value return value
} }

View File

@ -0,0 +1,58 @@
package ru.dbotthepony.kstarbound.client.gl.properties
import ru.dbotthepony.kstarbound.client.StarboundClient
import ru.dbotthepony.kstarbound.client.gl.GLObject
import ru.dbotthepony.kstarbound.client.gl.checkForGLError
import java.util.function.Consumer
import java.util.function.IntConsumer
import java.util.function.Supplier
import kotlin.reflect.KProperty
class GLObjectTracker<T : GLObject>(
private val glFunc: IntConsumer,
private val nullValue: Int = 0,
private val message: String? = null
) : Supplier<T?>, Consumer<T?> {
constructor(glFunc: BiConsumer, type: Int, nullValue: Int = 0, message: String? = null) : this(IntConsumer { glFunc.invoke(type, it) }, nullValue)
constructor(glFunc: BiConsumer, type: Int, message: String? = null) : this(IntConsumer { glFunc.invoke(type, it) }, 0, message)
constructor(glFunc: IntConsumer, message: String?) : this(glFunc, 0, message)
fun interface BiConsumer {
fun invoke(a: Int, b: Int)
}
private val client = StarboundClient.current()
private var value: T? = null
private var actualPointer = nullValue
set(value) {
if (value != field) {
glFunc.accept(value)
checkForGLError()
field = value
}
}
operator fun getValue(thisRef: Any?, property: KProperty<*>): T? {
return value
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: T?) {
accept(value)
}
override fun get(): T? {
return value
}
override fun accept(value: T?) {
client.ensureSameThread()
if (this.value !== value) {
if (value != null && value.client != client)
throw IllegalArgumentException("$value does not belong to $client (it belongs to ${value.client})")
actualPointer = value?.pointer ?: nullValue
this.value = value
}
}
}

View File

@ -6,6 +6,7 @@ import it.unimi.dsi.fastutil.objects.Object2ObjectArrayMap
import it.unimi.dsi.fastutil.objects.Object2ObjectFunction import it.unimi.dsi.fastutil.objects.Object2ObjectFunction
import org.lwjgl.opengl.GL46.* import org.lwjgl.opengl.GL46.*
import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.StarboundClient
import ru.dbotthepony.kstarbound.client.gl.GLObject
import ru.dbotthepony.kstarbound.client.gl.checkForGLError import ru.dbotthepony.kstarbound.client.gl.checkForGLError
import ru.dbotthepony.kstarbound.client.gl.vertex.GLAttributeList import ru.dbotthepony.kstarbound.client.gl.vertex.GLAttributeList
import ru.dbotthepony.kvector.api.IStruct2f import ru.dbotthepony.kvector.api.IStruct2f
@ -26,10 +27,9 @@ import kotlin.reflect.KProperty
open class GLShaderProgram( open class GLShaderProgram(
shaders: Iterable<GLShader>, shaders: Iterable<GLShader>,
val attributes: GLAttributeList val attributes: GLAttributeList
) { ) : GLObject() {
val client = StarboundClient.current() final override val client = StarboundClient.current()
final override val pointer = glCreateProgram()
val pointer = glCreateProgram()
init { init {
checkForGLError("Creating shader program") checkForGLError("Creating shader program")
@ -57,6 +57,15 @@ open class GLShaderProgram(
return this return this
} }
final override fun bind() {
client.program = this
}
final override fun unbind() {
if (client.program === this)
client.program = null
}
private val locations = Object2ObjectArrayMap<String, Uniform<*>>() private val locations = Object2ObjectArrayMap<String, Uniform<*>>()
private val uniformsExist = Object2BooleanArrayMap<String>() private val uniformsExist = Object2BooleanArrayMap<String>()

View File

@ -3,7 +3,7 @@ package ru.dbotthepony.kstarbound.client.gl.vertex
import org.lwjgl.opengl.GL46 import org.lwjgl.opengl.GL46
import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.StarboundClient
import ru.dbotthepony.kstarbound.client.gl.VertexArrayObject import ru.dbotthepony.kstarbound.client.gl.VertexArrayObject
import ru.dbotthepony.kstarbound.client.gl.VertexBufferObject import ru.dbotthepony.kstarbound.client.gl.BufferObject
import ru.dbotthepony.kstarbound.client.gl.checkForGLError import ru.dbotthepony.kstarbound.client.gl.checkForGLError
/** /**
@ -17,8 +17,8 @@ class StreamVertexBuilder(
val state = StarboundClient.current() val state = StarboundClient.current()
val builder = VertexBuilder(attributes, type, initialCapacity) val builder = VertexBuilder(attributes, type, initialCapacity)
private val vao = VertexArrayObject() private val vao = VertexArrayObject()
private val vbo = VertexBufferObject.vbo() private val vbo = BufferObject.VBO()
private val ebo = VertexBufferObject.ebo() private val ebo = BufferObject.EBO()
init { init {
vao.bind() vao.bind()

View File

@ -5,7 +5,7 @@ import org.lwjgl.opengl.GL46.GL_UNSIGNED_INT
import org.lwjgl.opengl.GL46.GL_UNSIGNED_SHORT import org.lwjgl.opengl.GL46.GL_UNSIGNED_SHORT
import org.lwjgl.opengl.GL46.GL_UNSIGNED_BYTE import org.lwjgl.opengl.GL46.GL_UNSIGNED_BYTE
import ru.dbotthepony.kstarbound.client.gl.GLType import ru.dbotthepony.kstarbound.client.gl.GLType
import ru.dbotthepony.kstarbound.client.gl.VertexBufferObject import ru.dbotthepony.kstarbound.client.gl.BufferObject
import ru.dbotthepony.kvector.util2d.AABB import ru.dbotthepony.kvector.util2d.AABB
import java.nio.ByteBuffer import java.nio.ByteBuffer
import java.nio.ByteOrder import java.nio.ByteOrder
@ -220,10 +220,7 @@ class VertexBuilder(
return this return this
} }
fun upload(vbo: VertexBufferObject, ebo: VertexBufferObject, drawType: Int = GL46.GL_DYNAMIC_DRAW) { fun upload(vbo: BufferObject.VBO, ebo: BufferObject.EBO, drawType: Int = GL46.GL_DYNAMIC_DRAW) {
require(vbo.isArray) { "$vbo is not an array" }
require(ebo.isElementArray) { "$ebo is not an element array" }
end() end()
check(elementVertices == 0) { "Not fully built vertex element ($mode requires ${mode?.elements} vertex points to be present, yet last strip has only $elementVertices elements)" } check(elementVertices == 0) { "Not fully built vertex element ($mode requires ${mode?.elements} vertex points to be present, yet last strip has only $elementVertices elements)" }

View File

@ -170,7 +170,7 @@ class Font(
stack.last().translateWithMultiplication(x = -lineWidth - movedX, y = lineHeight) stack.last().translateWithMultiplication(x = -lineWidth - movedX, y = lineHeight)
} }
state.VAO = null state.vao = null
stack.pop() stack.pop()
return TextSize(totalX * scale, totalY * scale) return TextSize(totalX * scale, totalY * scale)
@ -258,8 +258,8 @@ class Font(
val advanceX: Float val advanceX: Float
val advanceY: Float val advanceY: Float
private val vbo: VertexBufferObject? // все три указателя должны хранится во избежание утечки private val vbo: BufferObject.VBO? // все три указателя должны хранится во избежание утечки
private val ebo: VertexBufferObject? // все три указателя должны хранится во избежание утечки private val ebo: BufferObject.EBO? // все три указателя должны хранится во избежание утечки
private val vao: VertexArrayObject? // все три указателя должны хранится во избежание утечки private val vao: VertexArrayObject? // все три указателя должны хранится во избежание утечки
private val indexCount: Int private val indexCount: Int