OpenGL object tracking cleanup
This commit is contained in:
parent
1e8cc5898d
commit
85e81a0b0b
@ -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) {
|
||||||
|
@ -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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -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
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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()
|
||||||
|
}
|
@ -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 {
|
||||||
|
@ -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 {
|
||||||
|
@ -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
|
||||||
}
|
}
|
@ -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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -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>()
|
||||||
|
|
||||||
|
@ -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()
|
||||||
|
@ -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)" }
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user