Немножечко низкоуровневых оптимизаций рендера
This commit is contained in:
parent
2a7a62e6ed
commit
1f50315ed5
src/main/kotlin/ru/dbotthepony/kstarbound/client
@ -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
|
||||
|
||||
|
@ -57,7 +57,10 @@ open class GLShaderProgram(val state: GLStateTracker, shaders: Iterable<GLStateT
|
||||
glGetError()
|
||||
}
|
||||
|
||||
fun use() = state.use(this)
|
||||
fun use(): GLShaderProgram {
|
||||
state.program = this
|
||||
return this
|
||||
}
|
||||
|
||||
private val locations = Object2ObjectArrayMap<String, Uniform<*>>()
|
||||
private val uniformsExist = Object2BooleanArrayMap<String>()
|
||||
@ -129,35 +132,51 @@ open class GLShaderProgram(val state: GLStateTracker, shaders: Iterable<GLStateT
|
||||
}
|
||||
|
||||
inner class F2Uniform(name: String) : Uniform<IStruct2f>(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<IStruct3f>(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<IMatrix3f<*>>(name) {
|
||||
override var value: IMatrix3f<*> = Matrix3f.ZERO
|
||||
@ -177,32 +196,48 @@ open class GLShaderProgram(val state: GLStateTracker, shaders: Iterable<GLStateT
|
||||
}
|
||||
|
||||
inner class F4x4Uniform(name: String) : Uniform<IMatrix4f<*>>(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<IStruct4f>(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
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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<ArrayList<(Matrix4fStack) -> Unit>>()
|
||||
private val layersHash = Int2ObjectOpenHashMap<ArrayList<(Matrix4fStack) -> 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) {
|
||||
|
Loading…
Reference in New Issue
Block a user