Немножечко низкоуровневых оптимизаций рендера
This commit is contained in:
parent
2a7a62e6ed
commit
1f50315ed5
@ -200,54 +200,39 @@ class GLStateTracker(val locator: ISBFileLocator) {
|
|||||||
var VBO: VertexBufferObject? = null
|
var VBO: VertexBufferObject? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
ensureSameThread()
|
ensureSameThread()
|
||||||
if (field === value) return
|
|
||||||
isMe(value?.state)
|
|
||||||
field = value
|
|
||||||
|
|
||||||
if (value == null) {
|
if (field !== value) {
|
||||||
glBindBuffer(GL_ARRAY_BUFFER, 0)
|
isMe(value?.state)
|
||||||
checkForGLError()
|
require(value?.isArray != false) { "Provided buffer object is not of Array type" }
|
||||||
return
|
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
|
var EBO: VertexBufferObject? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
ensureSameThread()
|
ensureSameThread()
|
||||||
if (field === value) return
|
|
||||||
isMe(value?.state)
|
|
||||||
field = value
|
|
||||||
|
|
||||||
if (value == null) {
|
if (field !== value) {
|
||||||
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0)
|
isMe(value?.state)
|
||||||
checkForGLError()
|
require(value?.isElementArray != false) { "Provided buffer object is not of Array type" }
|
||||||
return
|
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
|
var VAO: VertexArrayObject? = null
|
||||||
set(value) {
|
set(value) {
|
||||||
ensureSameThread()
|
ensureSameThread()
|
||||||
if (field === value) return
|
|
||||||
isMe(value?.state)
|
|
||||||
field = value
|
|
||||||
|
|
||||||
if (value == null) {
|
if (field !== value) {
|
||||||
glBindVertexArray(0)
|
isMe(value?.state)
|
||||||
checkForGLError()
|
glBindVertexArray(value?.pointer ?: 0)
|
||||||
return
|
checkForGLError("Setting Vertex Array Object")
|
||||||
|
field = value
|
||||||
}
|
}
|
||||||
|
|
||||||
glBindVertexArray(value.pointer)
|
|
||||||
checkForGLError()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var readFramebuffer: GLFrameBuffer? = null
|
var readFramebuffer: GLFrameBuffer? = null
|
||||||
@ -301,17 +286,28 @@ class GLStateTracker(val locator: ISBFileLocator) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var program: GLShaderProgram? = null
|
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
|
var activeTexture = 0
|
||||||
set(value) {
|
set(value) {
|
||||||
ensureSameThread()
|
ensureSameThread()
|
||||||
if (field == value) return
|
|
||||||
require(value >= 0) { "Invalid texture block $value" }
|
if (field != value) {
|
||||||
require(value < 80) { "Too big texture block index $value, OpenGL 4.6 guarantee only 80!" }
|
require(value >= 0) { "Invalid texture block $value" }
|
||||||
field = value
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var texture2D: GLTexture2D? by TexturesTracker(80)
|
var texture2D: GLTexture2D? by TexturesTracker(80)
|
||||||
@ -439,18 +435,6 @@ class GLStateTracker(val locator: ISBFileLocator) {
|
|||||||
return obj
|
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 shaderVertexTexture: TexturedProgram
|
||||||
val shaderVertexTextureColor: TexturedColoredProgram
|
val shaderVertexTextureColor: TexturedColoredProgram
|
||||||
|
|
||||||
|
@ -57,7 +57,10 @@ open class GLShaderProgram(val state: GLStateTracker, shaders: Iterable<GLStateT
|
|||||||
glGetError()
|
glGetError()
|
||||||
}
|
}
|
||||||
|
|
||||||
fun use() = state.use(this)
|
fun use(): GLShaderProgram {
|
||||||
|
state.program = this
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
private val locations = Object2ObjectArrayMap<String, Uniform<*>>()
|
private val locations = Object2ObjectArrayMap<String, Uniform<*>>()
|
||||||
private val uniformsExist = Object2BooleanArrayMap<String>()
|
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) {
|
inner class F2Uniform(name: String) : Uniform<IStruct2f>(name) {
|
||||||
|
private var v0 = 0f
|
||||||
|
private var v1 = 0f
|
||||||
|
|
||||||
override var value: IStruct2f = Vector2f.ZERO
|
override var value: IStruct2f = Vector2f.ZERO
|
||||||
set(value) {
|
set(value) {
|
||||||
state.ensureSameThread()
|
state.ensureSameThread()
|
||||||
|
|
||||||
if (field != value) {
|
val (v0, v1) = value
|
||||||
glProgramUniform2f(pointer, location, value.component1(), value.component2())
|
|
||||||
|
if (this.v0 != v0 || this.v1 != v1) {
|
||||||
|
glProgramUniform2f(pointer, location, v0, v1)
|
||||||
checkForGLError()
|
checkForGLError()
|
||||||
|
|
||||||
field = if (value is Vector2f) value else Vector2f(value)
|
field = if (value is Vector2f) value else Vector2f(value)
|
||||||
|
this.v0 = v0
|
||||||
|
this.v1 = v1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class F3Uniform(name: String) : Uniform<IStruct3f>(name) {
|
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
|
override var value: IStruct3f = Vector3f.ZERO
|
||||||
set(value) {
|
set(value) {
|
||||||
state.ensureSameThread()
|
state.ensureSameThread()
|
||||||
|
|
||||||
if (field != value) {
|
val (v0, v1, v2) = value
|
||||||
glProgramUniform3f(pointer, location, value.component1(), value.component2(), value.component3())
|
|
||||||
|
if (this.v0 != v0 || this.v1 != v1 || this.v2 != v2) {
|
||||||
|
glProgramUniform3f(pointer, location, v0, v1, v2)
|
||||||
checkForGLError()
|
checkForGLError()
|
||||||
|
|
||||||
field = if (value is Vector3f) value else Vector3f(value)
|
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 buff3x3: FloatBuffer = 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 buff4x4: FloatBuffer = ByteBuffer.allocateDirect(4 * 4 * 4).also { it.order(ByteOrder.nativeOrder()) }.asFloatBuffer()
|
||||||
|
|
||||||
inner class F3x3Uniform(name: String) : Uniform<IMatrix3f<*>>(name) {
|
inner class F3x3Uniform(name: String) : Uniform<IMatrix3f<*>>(name) {
|
||||||
override var value: IMatrix3f<*> = Matrix3f.ZERO
|
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) {
|
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
|
override var value: IMatrix4f<*> = Matrix4f.ZERO
|
||||||
set(value) {
|
set(value) {
|
||||||
state.ensureSameThread()
|
state.ensureSameThread()
|
||||||
|
|
||||||
if (field != value) {
|
buff4x4.position(0)
|
||||||
buff4x4.position(0)
|
value.write(buff4x4)
|
||||||
value.write(buff4x4)
|
buff4x4.position(0)
|
||||||
buff4x4.position(0)
|
_value.position(0)
|
||||||
|
|
||||||
|
if (buff4x4 != _value) {
|
||||||
glProgramUniformMatrix4fv(pointer, location, false, buff4x4)
|
glProgramUniformMatrix4fv(pointer, location, false, buff4x4)
|
||||||
checkForGLError()
|
checkForGLError()
|
||||||
|
buff4x4.position(0)
|
||||||
|
_value.put(buff4x4)
|
||||||
field = value.toMatrix4f()
|
field = value.toMatrix4f()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
inner class F4Uniform(name: String) : Uniform<IStruct4f>(name) {
|
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
|
override var value: IStruct4f = Vector4f.ZERO
|
||||||
set(value) {
|
set(value) {
|
||||||
state.ensureSameThread()
|
state.ensureSameThread()
|
||||||
|
|
||||||
if (field != value) {
|
val (v0, v1, v2, v3) = value
|
||||||
glProgramUniform4f(pointer, location, value.component1(), value.component2(), value.component3(), value.component4())
|
|
||||||
|
if (this.v0 != v0 || this.v1 != v1 || this.v2 != v2 || this.v3 != v3) {
|
||||||
|
glProgramUniform4f(pointer, location, v0, v1, v2, v3)
|
||||||
checkForGLError()
|
checkForGLError()
|
||||||
|
|
||||||
field = if (value is Vector4f) value else Vector4f(value)
|
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.Int2ObjectAVLTreeMap
|
||||||
import it.unimi.dsi.fastutil.ints.Int2ObjectFunction
|
import it.unimi.dsi.fastutil.ints.Int2ObjectFunction
|
||||||
|
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap
|
||||||
import ru.dbotthepony.kvector.matrix.Matrix4fStack
|
import ru.dbotthepony.kvector.matrix.Matrix4fStack
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -9,6 +10,7 @@ import ru.dbotthepony.kvector.matrix.Matrix4fStack
|
|||||||
*/
|
*/
|
||||||
class LayeredRenderer {
|
class LayeredRenderer {
|
||||||
private val layers = Int2ObjectAVLTreeMap<ArrayList<(Matrix4fStack) -> Unit>>()
|
private val layers = Int2ObjectAVLTreeMap<ArrayList<(Matrix4fStack) -> Unit>>()
|
||||||
|
private val layersHash = Int2ObjectOpenHashMap<ArrayList<(Matrix4fStack) -> Unit>>()
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Сортировка [layer] происходит от дальнего (БОЛЬШЕ!) к ближнему (МЕНЬШЕ!)
|
* Сортировка [layer] происходит от дальнего (БОЛЬШЕ!) к ближнему (МЕНЬШЕ!)
|
||||||
@ -17,7 +19,15 @@ class LayeredRenderer {
|
|||||||
* `8 -> 6 -> 4 -> 1 -> -4 -> -7`
|
* `8 -> 6 -> 4 -> 1 -> -4 -> -7`
|
||||||
*/
|
*/
|
||||||
fun add(layer: Int, renderer: (Matrix4fStack) -> Unit) {
|
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) {
|
fun render(stack: Matrix4fStack) {
|
||||||
|
Loading…
Reference in New Issue
Block a user