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 39f10bdc..50cf2ad6 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLStateTracker.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLStateTracker.kt @@ -8,7 +8,7 @@ import ru.dbotthepony.kstarbound.client.freetype.FreeType import ru.dbotthepony.kstarbound.client.freetype.InvalidArgumentException import ru.dbotthepony.kstarbound.client.gl.program.GLPrograms import ru.dbotthepony.kstarbound.client.gl.shader.GLShader -import ru.dbotthepony.kstarbound.client.gl.program.GLShaderProgram +import ru.dbotthepony.kstarbound.client.gl.shader.GLShaderProgram import ru.dbotthepony.kstarbound.client.gl.shader.GLTransformableColorableProgram import ru.dbotthepony.kstarbound.client.gl.shader.GLTransformableProgram import ru.dbotthepony.kstarbound.client.gl.vertex.GLAttributeList @@ -533,11 +533,8 @@ class GLStateTracker(val locator: ISBFileLocator) { fun use(obj: GLShaderProgram): GLShaderProgram { ensureSameThread() - if (obj == program) { + if (obj === program) return obj - } - - check(obj.linked) { "Program is not linked!" } program = obj glUseProgram(obj.pointer) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/GLInternalProgram.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/GLInternalProgram.kt index 5b90353d..8a986a5e 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/GLInternalProgram.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/GLInternalProgram.kt @@ -2,6 +2,7 @@ package ru.dbotthepony.kstarbound.client.gl.program import ru.dbotthepony.kstarbound.client.gl.GLStateTracker import ru.dbotthepony.kstarbound.client.gl.shader.GLShader +import ru.dbotthepony.kstarbound.client.gl.shader.GLShaderProgram private fun loadShaders( vertex: Collection, diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/Programs.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/Programs.kt index 1bf2cbea..4c9e1bcd 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/Programs.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/Programs.kt @@ -4,6 +4,7 @@ import ru.dbotthepony.kstarbound.client.gl.BlendFunc import ru.dbotthepony.kstarbound.client.gl.GLStateTracker import ru.dbotthepony.kstarbound.client.gl.GLType import ru.dbotthepony.kstarbound.client.gl.shader.GLShader +import ru.dbotthepony.kstarbound.client.gl.shader.GLShaderProgram import ru.dbotthepony.kstarbound.client.gl.shader.GLTransformableColorableProgram import ru.dbotthepony.kstarbound.client.gl.vertex.GLAttributeList import ru.dbotthepony.kstarbound.client.gl.vertex.StreamVertexBuilder @@ -36,19 +37,11 @@ private class SimpleProgram(private val name: String, priva vertex.unlink() fragment.unlink() - if (!newValue.linked) { - newValue.link() - } - return newValue } } class GLLiquidProgram(state: GLStateTracker) : GLInternalProgram(state, "liquid") { - init { - link() - } - val baselineColor = this["baselineColor"]!! val transform = this["transform"]!! @@ -62,10 +55,6 @@ class GLLiquidProgram(state: GLStateTracker) : GLInternalProgram(state, "liquid" } class GLLightProgram(state: GLStateTracker) : GLInternalProgram(state, "light") { - init { - link() - } - val baselineColor = this["baselineColor"]!! val transform = this["transform"]!! @@ -79,10 +68,6 @@ class GLLightProgram(state: GLStateTracker) : GLInternalProgram(state, "light") } class GLHardLightGeometryProgram(state: GLStateTracker) : GLInternalProgram(state, listOf("hard_light_geometry"), listOf("hard_light_geometry"), listOf("hard_light_geometry")) { - init { - link() - } - val transform = this["transform"]!! val localToWorldTransform = this["localToWorldTransform"]!! val lightPosition = this["lightPosition"]!! @@ -94,10 +79,6 @@ class GLHardLightGeometryProgram(state: GLStateTracker) : GLInternalProgram(stat } class GLSoftLightGeometryProgram(state: GLStateTracker) : GLInternalProgram(state, listOf("soft_light_geometry2"), listOf("soft_light_geometry2")) { - init { - link() - } - val transform = this["transform"]!! val lightPenetration = this["lightPenetration"]!! val localToWorldTransform = this["localToWorldTransform"]!! @@ -113,10 +94,6 @@ class GLSoftLightGeometryProgram(state: GLStateTracker) : GLInternalProgram(stat } class GLColorQuadProgram(state: GLStateTracker) : GLInternalProgram(state, "screen_quad") { - init { - link() - } - val color = this["color"]!! private val builder by lazy { @@ -163,10 +140,6 @@ class GLColorQuadProgram(state: GLStateTracker) : GLInternalProgram(state, "scre } class GLTextureQuadProgram(state: GLStateTracker) : GLInternalProgram(state, "screen_quad_tex") { - init { - link() - } - val texture = this["texture0"]!! private val builder by lazy { @@ -191,10 +164,6 @@ class GLTextureQuadProgram(state: GLStateTracker) : GLInternalProgram(state, "sc } class GLTextureBlurredQuadProgram(state: GLStateTracker) : GLInternalProgram(state, "screen_quad_tex_blur") { - init { - link() - } - val texture = this["texture0"]!! private val builder by lazy { @@ -229,10 +198,6 @@ class GLFlatProgram(state: GLStateTracker, vararg shaders: GLShader) : GLTransfo } class GLFlatColorProgram(state: GLStateTracker) : GLInternalProgram(state, "flat_color") { - init { - link() - } - val transform = this["transform"]!! val builder by lazy { diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/GLShaderProgram.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLShaderProgram.kt similarity index 73% rename from src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/GLShaderProgram.kt rename to src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLShaderProgram.kt index 3ee2fdf6..b3419ea3 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/program/GLShaderProgram.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLShaderProgram.kt @@ -1,9 +1,10 @@ -package ru.dbotthepony.kstarbound.client.gl.program +package ru.dbotthepony.kstarbound.client.gl.shader import it.unimi.dsi.fastutil.objects.Object2ObjectFunction import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap import org.lwjgl.opengl.GL46.* import ru.dbotthepony.kstarbound.client.gl.GLStateTracker +import ru.dbotthepony.kstarbound.client.gl.checkForGLError import ru.dbotthepony.kstarbound.client.gl.shader.GLShader import ru.dbotthepony.kstarbound.client.gl.shader.GLUniformLocation import ru.dbotthepony.kstarbound.client.gl.shader.ShaderLinkException @@ -11,19 +12,37 @@ import ru.dbotthepony.kvector.api.IFloatMatrix import ru.dbotthepony.kvector.api.IStruct3f import ru.dbotthepony.kvector.api.IStruct4f import java.util.* +import java.util.stream.Stream import kotlin.collections.HashSet -open class GLShaderProgram(val state: GLStateTracker, vararg shaders: GLShader) { +open class GLShaderProgram(val state: GLStateTracker, shaders: Stream) { + constructor(state: GLStateTracker, shaders: Collection) : this(state, shaders.stream()) + constructor(state: GLStateTracker, vararg shaders: GLShader) : this(state, Arrays.stream(shaders)) + init { state.ensureSameThread() } val pointer = glCreateProgram() - var linked = false - private set - private val attached = HashSet() - val access = object : Collection by attached {} + init { + checkForGLError() + + for (shader in shaders) { + glAttachShader(pointer, shader.pointer) + } + + glLinkProgram(pointer) + + val success = intArrayOf(0) + glGetProgramiv(pointer, GL_LINK_STATUS, success) + + if (success[0] == 0) { + throw ShaderLinkException(glGetProgramInfoLog(pointer)) + } + + glGetError() + } private val locationCache = Object2ObjectOpenHashMap>() @@ -37,7 +56,6 @@ open class GLShaderProgram(val state: GLStateTracker, vararg shaders: GLShader) */ operator fun get(name: String): GLUniformLocation? { state.ensureSameThread() - check(linked) { "Shader program is not linked!" } return locationCache.computeIfAbsent(name, Object2ObjectFunction { val location = glGetUniformLocation(pointer, name) @@ -54,42 +72,5 @@ open class GLShaderProgram(val state: GLStateTracker, vararg shaders: GLShader) operator fun set(name: String, value: Int) = this[name]?.set(value) operator fun set(name: String, value: IFloatMatrix<*>) = this[name]?.set(value) - fun attach(shader: GLShader) { - state.ensureSameThread() - check(!linked) { "Program is already linked!" } - - if (!attached.add(shader)) { - throw IllegalStateException("Already attached! $shader") - } - require(!shader.unlinked) { "$shader is already unlinked, and thus can not be used" } - - glAttachShader(pointer, shader.pointer) - } - - fun link() { - check(!linked) { "Program is already linked!" } - state.ensureSameThread() - glLinkProgram(pointer) - - val success = intArrayOf(0) - glGetProgramiv(pointer, GL_LINK_STATUS, success) - - if (success[0] == 0) { - throw ShaderLinkException(glGetProgramInfoLog(pointer)) - } - - glGetError() - - linked = true - } - fun use() = state.use(this) - - fun unlinkChildren() { - attached.forEach(GLShader::unlink) - } - - init { - shaders.forEach(this::attach) - } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLTransformableProgram.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLTransformableProgram.kt index e8892fb3..58638b5a 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLTransformableProgram.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLTransformableProgram.kt @@ -1,17 +1,12 @@ package ru.dbotthepony.kstarbound.client.gl.shader import ru.dbotthepony.kstarbound.client.gl.GLStateTracker -import ru.dbotthepony.kstarbound.client.gl.program.GLShaderProgram import ru.dbotthepony.kvector.matrix.nfloat.Matrix4f open class GLTransformableProgram(state: GLStateTracker, vararg shaders: GLShader) : GLShaderProgram(state, *shaders) { - init { - link() - } - val transform = this["_transform"]!! init { transform.set(Matrix4f.IDENTITY) } -} \ No newline at end of file +} diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLUniformLocation.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLUniformLocation.kt index 47a8643a..0d650aac 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLUniformLocation.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/GLUniformLocation.kt @@ -2,7 +2,6 @@ package ru.dbotthepony.kstarbound.client.gl.shader import org.lwjgl.opengl.GL41.* import ru.dbotthepony.kstarbound.client.gl.checkForGLError -import ru.dbotthepony.kstarbound.client.gl.program.GLShaderProgram import ru.dbotthepony.kvector.api.IFloatMatrix import ru.dbotthepony.kvector.api.IStruct2f import ru.dbotthepony.kvector.api.IStruct3f diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/ConfiguredShaderProgram.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/ConfiguredShaderProgram.kt index 7e766b2e..837cd4d3 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/ConfiguredShaderProgram.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/ConfiguredShaderProgram.kt @@ -1,7 +1,7 @@ package ru.dbotthepony.kstarbound.client.render import org.lwjgl.opengl.GL46.* -import ru.dbotthepony.kstarbound.client.gl.program.GLShaderProgram +import ru.dbotthepony.kstarbound.client.gl.shader.GLShaderProgram import ru.dbotthepony.kstarbound.client.gl.VertexArrayObject import ru.dbotthepony.kstarbound.client.gl.checkForGLError import ru.dbotthepony.kstarbound.client.gl.vertex.VertexBuilder