From 1f50315ed574a1ff7e01e8f2d6102d03c9c49d09 Mon Sep 17 00:00:00 2001 From: DBotThePony Date: Tue, 21 Feb 2023 13:43:49 +0700 Subject: [PATCH] =?UTF-8?q?=D0=9D=D0=B5=D0=BC=D0=BD=D0=BE=D0=B6=D0=B5?= =?UTF-8?q?=D1=87=D0=BA=D0=BE=20=D0=BD=D0=B8=D0=B7=D0=BA=D0=BE=D1=83=D1=80?= =?UTF-8?q?=D0=BE=D0=B2=D0=BD=D0=B5=D0=B2=D1=8B=D1=85=20=D0=BE=D0=BF=D1=82?= =?UTF-8?q?=D0=B8=D0=BC=D0=B8=D0=B7=D0=B0=D1=86=D0=B8=D0=B9=20=D1=80=D0=B5?= =?UTF-8?q?=D0=BD=D0=B4=D0=B5=D1=80=D0=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../kstarbound/client/gl/GLStateTracker.kt | 86 ++++++++----------- .../client/gl/shader/GLShaderProgram.kt | 63 +++++++++++--- .../client/render/LayeredRenderer.kt | 12 ++- 3 files changed, 95 insertions(+), 66 deletions(-) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLStateTracker.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLStateTracker.kt index d9fc1279..f185ebe1 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLStateTracker.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLStateTracker.kt @@ -200,54 +200,39 @@ class GLStateTracker(val locator: ISBFileLocator) { var VBO: VertexBufferObject? = null set(value) { ensureSameThread() - if (field === value) return - isMe(value?.state) - field = value - if (value == null) { - glBindBuffer(GL_ARRAY_BUFFER, 0) - checkForGLError() - return + if (field !== value) { + isMe(value?.state) + 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 } - - if (!value.isArray) throw IllegalArgumentException("Provided buffer object is not of Array type") - glBindBuffer(GL_ARRAY_BUFFER, value.pointer) - checkForGLError() } var EBO: VertexBufferObject? = null set(value) { ensureSameThread() - if (field === value) return - isMe(value?.state) - field = value - if (value == null) { - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0) - checkForGLError() - return + if (field !== value) { + isMe(value?.state) + 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 } - - if (!value.isElementArray) throw IllegalArgumentException("Provided buffer object is not of Array type") - glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, value.pointer) - checkForGLError() } var VAO: VertexArrayObject? = null set(value) { ensureSameThread() - if (field === value) return - isMe(value?.state) - field = value - if (value == null) { - glBindVertexArray(0) - checkForGLError() - return + if (field !== value) { + isMe(value?.state) + glBindVertexArray(value?.pointer ?: 0) + checkForGLError("Setting Vertex Array Object") + field = value } - - glBindVertexArray(value.pointer) - checkForGLError() } var readFramebuffer: GLFrameBuffer? = null @@ -301,17 +286,28 @@ class GLStateTracker(val locator: ISBFileLocator) { } var program: GLShaderProgram? = null - private set + set(value) { + ensureSameThread() + + if (value !== field) { + isMe(value?.state) + glUseProgram(value?.pointer ?: 0) + checkForGLError("Setting shader program") + field = value + } + } var activeTexture = 0 set(value) { ensureSameThread() - if (field == value) return - require(value >= 0) { "Invalid texture block $value" } - require(value < 80) { "Too big texture block index $value, OpenGL 4.6 guarantee only 80!" } - field = value - glActiveTexture(GL_TEXTURE0 + value) - checkForGLError() + + if (field != value) { + require(value >= 0) { "Invalid texture block $value" } + require(value < 80) { "Too big texture block index $value, OpenGL 4.6 guarantee only 80!" } + glActiveTexture(GL_TEXTURE0 + value) + checkForGLError() + field = value + } } var texture2D: GLTexture2D? by TexturesTracker(80) @@ -439,18 +435,6 @@ class GLStateTracker(val locator: ISBFileLocator) { return obj } - fun use(obj: GLShaderProgram): GLShaderProgram { - ensureSameThread() - - if (obj === program) - return obj - - program = obj - glUseProgram(obj.pointer) - checkForGLError() - return obj - } - val shaderVertexTexture: TexturedProgram val shaderVertexTextureColor: TexturedColoredProgram diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLShaderProgram.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLShaderProgram.kt index b67b259e..76ab803f 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLShaderProgram.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLShaderProgram.kt @@ -57,7 +57,10 @@ open class GLShaderProgram(val state: GLStateTracker, shaders: Iterable>() private val uniformsExist = Object2BooleanArrayMap() @@ -129,35 +132,51 @@ open class GLShaderProgram(val state: GLStateTracker, shaders: Iterable(name) { + private var v0 = 0f + private var v1 = 0f + override var value: IStruct2f = Vector2f.ZERO set(value) { state.ensureSameThread() - if (field != value) { - glProgramUniform2f(pointer, location, value.component1(), value.component2()) + val (v0, v1) = value + + if (this.v0 != v0 || this.v1 != v1) { + glProgramUniform2f(pointer, location, v0, v1) checkForGLError() field = if (value is Vector2f) value else Vector2f(value) + this.v0 = v0 + this.v1 = v1 } } } inner class F3Uniform(name: String) : Uniform(name) { + private var v0 = 0f + private var v1 = 0f + private var v2 = 0f + override var value: IStruct3f = Vector3f.ZERO set(value) { state.ensureSameThread() - if (field != value) { - glProgramUniform3f(pointer, location, value.component1(), value.component2(), value.component3()) + val (v0, v1, v2) = value + + if (this.v0 != v0 || this.v1 != v1 || this.v2 != v2) { + glProgramUniform3f(pointer, location, v0, v1, v2) checkForGLError() field = if (value is Vector3f) value else Vector3f(value) + this.v0 = v0 + this.v1 = v1 + this.v2 = v2 } } } - private val buff3x3: FloatBuffer by lazy(LazyThreadSafetyMode.NONE) { ByteBuffer.allocateDirect(4 * 3 * 3).also { it.order(ByteOrder.nativeOrder()) }.asFloatBuffer() } - private val buff4x4: FloatBuffer by lazy(LazyThreadSafetyMode.NONE) { ByteBuffer.allocateDirect(4 * 4 * 4).also { it.order(ByteOrder.nativeOrder()) }.asFloatBuffer() } + private val buff3x3: FloatBuffer = ByteBuffer.allocateDirect(4 * 3 * 3).also { it.order(ByteOrder.nativeOrder()) }.asFloatBuffer() + private val buff4x4: FloatBuffer = ByteBuffer.allocateDirect(4 * 4 * 4).also { it.order(ByteOrder.nativeOrder()) }.asFloatBuffer() inner class F3x3Uniform(name: String) : Uniform>(name) { override var value: IMatrix3f<*> = Matrix3f.ZERO @@ -177,32 +196,48 @@ open class GLShaderProgram(val state: GLStateTracker, shaders: Iterable>(name) { + private val _value = ByteBuffer.allocate(4 * 4 * 4).also { it.order(ByteOrder.nativeOrder()) }.asFloatBuffer() + override var value: IMatrix4f<*> = Matrix4f.ZERO set(value) { state.ensureSameThread() - if (field != value) { - buff4x4.position(0) - value.write(buff4x4) - buff4x4.position(0) + buff4x4.position(0) + value.write(buff4x4) + buff4x4.position(0) + _value.position(0) + + if (buff4x4 != _value) { glProgramUniformMatrix4fv(pointer, location, false, buff4x4) checkForGLError() - + buff4x4.position(0) + _value.put(buff4x4) field = value.toMatrix4f() } } } inner class F4Uniform(name: String) : Uniform(name) { + private var v0 = 0f + private var v1 = 0f + private var v2 = 0f + private var v3 = 0f + override var value: IStruct4f = Vector4f.ZERO set(value) { state.ensureSameThread() - if (field != value) { - glProgramUniform4f(pointer, location, value.component1(), value.component2(), value.component3(), value.component4()) + val (v0, v1, v2, v3) = value + + if (this.v0 != v0 || this.v1 != v1 || this.v2 != v2 || this.v3 != v3) { + glProgramUniform4f(pointer, location, v0, v1, v2, v3) checkForGLError() field = if (value is Vector4f) value else Vector4f(value) + this.v0 = v0 + this.v1 = v1 + this.v2 = v2 + this.v3 = v3 } } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/LayeredRenderer.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/LayeredRenderer.kt index b29fcb49..8286db45 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/LayeredRenderer.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/LayeredRenderer.kt @@ -2,6 +2,7 @@ package ru.dbotthepony.kstarbound.client.render import it.unimi.dsi.fastutil.ints.Int2ObjectAVLTreeMap import it.unimi.dsi.fastutil.ints.Int2ObjectFunction +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap import ru.dbotthepony.kvector.matrix.Matrix4fStack /** @@ -9,6 +10,7 @@ import ru.dbotthepony.kvector.matrix.Matrix4fStack */ class LayeredRenderer { private val layers = Int2ObjectAVLTreeMap Unit>>() + private val layersHash = Int2ObjectOpenHashMap Unit>>() /** * Сортировка [layer] происходит от дальнего (БОЛЬШЕ!) к ближнему (МЕНЬШЕ!) @@ -17,7 +19,15 @@ class LayeredRenderer { * `8 -> 6 -> 4 -> 1 -> -4 -> -7` */ fun add(layer: Int, renderer: (Matrix4fStack) -> Unit) { - layers.computeIfAbsent(-layer, Int2ObjectFunction { ArrayList() }).add(renderer) + var list = layersHash[layer] + + if (list == null) { + list = ArrayList() + layers[-layer] = list + layersHash[layer] = list + } + + list.add(renderer) } fun render(stack: Matrix4fStack) {