diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt index 4cdb748a..285d9dae 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/Main.kt @@ -17,9 +17,8 @@ import ru.dbotthepony.kstarbound.world.entities.PlayerEntity import ru.dbotthepony.kstarbound.io.json.VersionedJson import ru.dbotthepony.kstarbound.io.readVarInt import ru.dbotthepony.kstarbound.util.AssetPathStack -import ru.dbotthepony.kstarbound.world.`object`.WorldObject +import ru.dbotthepony.kstarbound.world.entities.WorldObject import ru.dbotthepony.kvector.vector.Vector2d -import ru.dbotthepony.kvector.vector.Vector2f import java.io.BufferedInputStream import java.io.ByteArrayInputStream import java.io.DataInputStream diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/StarboundClient.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/StarboundClient.kt index b0b61d53..d425e712 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/StarboundClient.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/StarboundClient.kt @@ -236,7 +236,8 @@ class StarboundClient : Closeable { putDebugLog("Initialized GLFW window") } - val maxTextureBlocks = glGetInteger(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS) + val maxTextureBlocks = glGetInteger(GL_MAX_TEXTURE_IMAGE_UNITS) + val maxUserTextureBlocks = maxTextureBlocks - 1 // available textures blocks for generic use val maxVertexAttribBindPoints = glGetInteger(GL_MAX_VERTEX_ATTRIB_BINDINGS) init { @@ -375,6 +376,17 @@ class StarboundClient : Closeable { checkForGLError() } + val whiteTexture = GLTexture2D("white") + + init { + val buffer = ByteBuffer.allocateDirect(3) + buffer.put(0xFF.toByte()) + buffer.put(0xFF.toByte()) + buffer.put(0xFF.toByte()) + buffer.position(0) + whiteTexture.upload(GL_RGB, 1, 1, GL_RGB, GL_UNSIGNED_BYTE, buffer) + } + fun setViewport(x: Int, y: Int, width: Int, height: Int) { ensureSameThread() diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLTexture.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLTexture.kt index 2e7ae594..433a3176 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLTexture.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/GLTexture.kt @@ -32,7 +32,7 @@ private class GLTexturePropertyTracker(private val flag: Int, private var value: @Suppress("SameParameterValue") class GLTexture2D(val name: String = "") : GLObject() { override val client = StarboundClient.current() - override val pointer = glGenTextures() + override val pointer = glCreateTextures(GL_TEXTURE_2D) init { checkForGLError() diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/Programs.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/Programs.kt index d22b73b3..bea1c0f0 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/Programs.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/shader/Programs.kt @@ -1,9 +1,13 @@ package ru.dbotthepony.kstarbound.client.gl.shader +import com.google.common.collect.ImmutableList +import org.lwjgl.opengl.GL20.GL_FRAGMENT_SHADER +import org.lwjgl.opengl.GL20.GL_VERTEX_SHADER import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.gl.vertex.GeometryType import ru.dbotthepony.kstarbound.client.gl.vertex.StreamVertexBuilder import ru.dbotthepony.kstarbound.client.gl.vertex.VertexAttributes +import ru.dbotthepony.kstarbound.client.render.FONT_VERTEX_FORMAT import ru.dbotthepony.kvector.api.IStruct4f import ru.dbotthepony.kvector.arrays.Matrix3f import ru.dbotthepony.kvector.vector.RGBAColor @@ -18,14 +22,40 @@ private fun shaders1(name: String): List { return listOf(client.internalVertex("shaders/vertex/$name.vsh"), client.internalFragment("shaders/fragment/$name.fsh")) } -class FontProgram : GLShaderProgram(shaders1("font"), VertexAttributes.POSITION_UV), GLShaderProgram.Regular { - override var viewMatrix: Matrix3f by F3x3Uniform("viewMatrix", true) - override var worldMatrix: Matrix3f by F3x3Uniform("worldMatrix", true) - override var modelMatrix: Matrix3f by F3x3Uniform("modelMatrix", true) - override var colorMultiplier: IStruct4f by F4Uniform("colorMultiplier", true) - var texture by IUniform("texture0") +private fun fontShaders(): List { + val client = StarboundClient.current() + var read = StarboundClient.readInternal("shaders/fragment/font.fsh") - val builder = StreamVertexBuilder(attributes, GeometryType.QUADS) + val textures = ArrayList() + val cases = ArrayList() + val cases2 = ArrayList() + + for (i in 0 until client.maxUserTextureBlocks) { + cases.add("\tvec4 colorResult$i = colorMultiplier * texture(texture$i, uvOut).r;") + } + + for (i in 0 until client.maxUserTextureBlocks) { + textures.add("layout (binding=$i) uniform sampler2D texture$i;") + cases2.add("if (textureIndexOut < ${i + 0.1f}) { colorResult = colorResult$i; }") + } + + cases2.add(" { colorResult = colorMultiplier; }") + + read = read.replace("uniform sampler2D texture0;", textures.joinToString("\n")).replace("\tcolorResult = colorMultiplier * texture(texture0, uvOut).r;", cases.joinToString("\n") + cases2.joinToString("\n\telse ")) + + val fragment = GLShader(read, GL_FRAGMENT_SHADER) + val vertex = GLShader(StarboundClient.readInternal("shaders/vertex/font.vsh"), GL_VERTEX_SHADER) + + return listOf(fragment, vertex) +} + +class FontProgram : GLShaderProgram(shaders1("font"), FONT_VERTEX_FORMAT), GLShaderProgram.Regular { + override var viewMatrix: Matrix3f by F3x3Uniform("viewMatrix") + override var worldMatrix: Matrix3f by F3x3Uniform("worldMatrix") + override var modelMatrix: Matrix3f by F3x3Uniform("modelMatrix", true) + override var colorMultiplier: IStruct4f by F4Uniform("colorMultiplier") + + var texture by IUniform("texture0") init { viewMatrix = Matrix3f.identity() diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/vertex/VertexAttributeType.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/vertex/VertexAttributeType.kt index 52a41b39..6019b5f1 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/vertex/VertexAttributeType.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/vertex/VertexAttributeType.kt @@ -3,7 +3,8 @@ package ru.dbotthepony.kstarbound.client.gl.vertex import ru.dbotthepony.kstarbound.client.gl.GLType enum class VertexAttributeType(val type: GLType) { - POSITION(GLType.VEC2F), + POSITION(GLType.VEC3F), + TEXTURE_INDEX(GLType.FLOAT), COLOR(GLType.VEC4F), UV(GLType.VEC2F), HUE_SHIFT(GLType.FLOAT) diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/vertex/VertexBuilder.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/vertex/VertexBuilder.kt index a0792034..af5d0d78 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/vertex/VertexBuilder.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/gl/vertex/VertexBuilder.kt @@ -7,6 +7,7 @@ import org.lwjgl.opengl.GL45.GL_UNSIGNED_BYTE import ru.dbotthepony.kstarbound.client.gl.BufferObject import ru.dbotthepony.kvector.api.IStruct2f import ru.dbotthepony.kvector.api.IStruct4f +import ru.dbotthepony.kvector.arrays.Matrix3f import java.nio.ByteBuffer import java.nio.ByteOrder @@ -191,6 +192,7 @@ class VertexBuilder( vertexCount = 0 indexCount = 0 elementCount = 0 + elementVertices = 0 vertexMemory.position(0) indexMemory.position(0) ensureCapacity() @@ -235,11 +237,15 @@ class VertexBuilder( elementCount++ elementVertices = 0 + val indexWriter = indexWriter + val indexMemory = indexMemory + val elementIndexOffset = elementIndexOffset + for (index in mode.indices.indices) { indexWriter.write(indexMemory, mode.indices.getInt(index) + elementIndexOffset) } - elementIndexOffset += mode.elements + this.elementIndexOffset += mode.elements indexCount += mode.indices.size ensureCapacity() @@ -261,6 +267,12 @@ class VertexBuilder( return this } + fun vertex(transform: Matrix3f, x: Float, y: Float): VertexBuilder { + vertex() + position(transform, x, y) + return this + } + private fun pushFloat(attr: VertexAttributes.Attribute, x: Float): VertexBuilder { vertexMemory.position(vertexCount * attributes.vertexStride + attr.relativeOffset) vertexMemory.putFloat(x) @@ -269,6 +281,14 @@ class VertexBuilder( return this } + private fun pushInt(attr: VertexAttributes.Attribute, x: Int): VertexBuilder { + vertexMemory.position(vertexCount * attributes.vertexStride + attr.relativeOffset) + vertexMemory.putInt(x) + vertexAttributes = vertexAttributes or attr.flag + + return this + } + private fun pushFloat2(attr: VertexAttributes.Attribute, x: Float, y: Float): VertexBuilder { vertexMemory.position(vertexCount * attributes.vertexStride + attr.relativeOffset) vertexMemory.putFloat(x) @@ -278,6 +298,16 @@ class VertexBuilder( return this } + private fun pushFloat3(attr: VertexAttributes.Attribute, x: Float, y: Float, z: Float): VertexBuilder { + vertexMemory.position(vertexCount * attributes.vertexStride + attr.relativeOffset) + vertexMemory.putFloat(x) + vertexMemory.putFloat(y) + vertexMemory.putFloat(z) + vertexAttributes = vertexAttributes or attr.flag + + return this + } + private fun pushFloat4(attr: VertexAttributes.Attribute, x: Float, y: Float, z: Float, w: Float): VertexBuilder { vertexMemory.position(vertexCount * attributes.vertexStride + attr.relativeOffset) vertexMemory.putFloat(x) @@ -289,25 +319,45 @@ class VertexBuilder( return this } + private val position = attributes[VertexAttributeType.POSITION] + private val uv = attributes[VertexAttributeType.UV] + private val color = attributes[VertexAttributeType.COLOR] + private val hueShift = attributes[VertexAttributeType.HUE_SHIFT] + private val textureIndex = attributes[VertexAttributeType.TEXTURE_INDEX] + fun position(x: Float, y: Float): VertexBuilder { - return pushFloat2(requireNotNull(attributes[VertexAttributeType.POSITION]) { "Vertex format does not have position attribute" }, x, y) + return pushFloat3(requireNotNull(position) { "Vertex format does not have position attribute" }, x, y, 1f) } fun position(value: IStruct2f) = position(value.component1(), value.component2()) + fun position(transform: Matrix3f, x: Float, y: Float): VertexBuilder { + return pushFloat3( + requireNotNull(position) { "Vertex format does not have position attribute" }, + x * transform.c00 + y * transform.c10 + transform.c20, + x * transform.c01 + y * transform.c11 + transform.c21, + x * transform.c02 + y * transform.c12 + transform.c22) + } + + fun position(transform: Matrix3f, value: IStruct2f) = position(transform, value.component1(), value.component2()) + fun uv(x: Float, y: Float): VertexBuilder { - return pushFloat2(requireNotNull(attributes[VertexAttributeType.UV]) { "Vertex format does not have texture UV attribute" }, x, y) + return pushFloat2(requireNotNull(uv) { "Vertex format does not have texture UV attribute" }, x, y) } fun uv(value: IStruct2f) = position(value.component1(), value.component2()) fun color(x: Float, y: Float, z: Float, w: Float): VertexBuilder { - return pushFloat4(requireNotNull(attributes[VertexAttributeType.COLOR]) { "Vertex format does not have color attribute" }, x, y, z, w) + return pushFloat4(requireNotNull(color) { "Vertex format does not have color attribute" }, x, y, z, w) } fun color(value: IStruct4f) = color(value.component1(), value.component2(), value.component3(), value.component4()) fun hueShift(x: Float): VertexBuilder { - return pushFloat(requireNotNull(attributes[VertexAttributeType.HUE_SHIFT]) { "Vertex format does not have texture UV attribute" }, x) + return pushFloat(requireNotNull(hueShift) { "Vertex format does not have texture UV attribute" }, x) + } + + fun textureIndex(x: Int): VertexBuilder { + return pushFloat(requireNotNull(textureIndex) { "Vertex format does not have texture index attribute" }, x.toFloat()) } } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/Font.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/Font.kt index 8209dd77..9c98a301 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/Font.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/render/Font.kt @@ -1,17 +1,30 @@ package ru.dbotthepony.kstarbound.client.render import it.unimi.dsi.fastutil.chars.Char2ObjectArrayMap +import it.unimi.dsi.fastutil.objects.Object2IntOpenHashMap import it.unimi.dsi.fastutil.objects.Object2ObjectFunction +import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap +import it.unimi.dsi.fastutil.objects.ObjectOpenHashSet import org.lwjgl.opengl.GL45.* +import org.lwjgl.system.MemoryUtil import ru.dbotthepony.kstarbound.client.StarboundClient import ru.dbotthepony.kstarbound.client.freetype.LoadFlag import ru.dbotthepony.kstarbound.client.gl.* import ru.dbotthepony.kstarbound.client.freetype.struct.FT_Pixel_Mode import ru.dbotthepony.kstarbound.client.gl.vertex.VertexAttributes import ru.dbotthepony.kstarbound.client.gl.vertex.GeometryType +import ru.dbotthepony.kstarbound.client.gl.vertex.VertexAttributeType import ru.dbotthepony.kstarbound.client.gl.vertex.VertexBuilder +import ru.dbotthepony.kstarbound.defs.image.IUVCoordinates +import ru.dbotthepony.kstarbound.math.roundTowardsNegativeInfinity +import ru.dbotthepony.kstarbound.math.roundTowardsPositiveInfinity import ru.dbotthepony.kvector.arrays.Matrix3f +import ru.dbotthepony.kvector.util2d.AABB +import ru.dbotthepony.kvector.util2d.AABBi import ru.dbotthepony.kvector.vector.RGBAColor +import ru.dbotthepony.kvector.vector.Vector2d +import ru.dbotthepony.kvector.vector.Vector2i +import ru.dbotthepony.kvector.vector.Vector4f private fun breakLines(text: String): List { var nextLineBreak = text.indexOf('\n', 0) @@ -55,12 +68,14 @@ enum class TextAlignY { TOP, CENTER, BOTTOM } +val FONT_VERTEX_FORMAT = VertexAttributes.of(VertexAttributeType.POSITION, VertexAttributeType.UV) + class Font( val font: String = "hobo.ttf", val size: Int = 48 ) { - val state = StarboundClient.current() - val face = state.freeType.Face(font, 0L) + val client = StarboundClient.current() + val face = client.freeType.Face(font, 0L) init { face.setSize(0, size) @@ -78,6 +93,37 @@ class Font( private val descender = face.nativeMemory.descender.toFloat() / ((size / 48f) * 32f) val lineHeight = ascender - descender + val bbox = AABBi( + Vector2i(roundTowardsNegativeInfinity(face.nativeMemory.bbox.xMin.toInt() / (12.0 * 48.0 / size)), roundTowardsNegativeInfinity(face.nativeMemory.bbox.yMin.toInt() / (12.0 * 48.0 / size))), + Vector2i(roundTowardsPositiveInfinity(face.nativeMemory.bbox.xMax.toInt() / (12.0 * 48.0 / size)), roundTowardsPositiveInfinity(face.nativeMemory.bbox.yMax.toInt() / (12.0 * 48.0 / size))), + ) + + private val atlas = GLTexture2D() + private val atlasWidth: Int = glGetInternalformati(GL_TEXTURE_2D, GL_RED, GL_MAX_WIDTH).coerceAtMost(4096) + private val atlasHeight: Int = glGetInternalformati(GL_TEXTURE_2D, GL_RED, GL_MAX_HEIGHT).coerceAtMost(4096) + private var nextAtlasX = 0 + private var nextAtlasY = 0 + + init { + glTextureStorage2D(atlas.pointer, 1, GL_R8, atlasWidth, atlasHeight) + checkForGLError() + + atlas.textureMinFilter = GL_LINEAR + atlas.textureMagFilter = GL_LINEAR + atlas.textureWrapS = GL_CLAMP_TO_EDGE + atlas.textureWrapT = GL_CLAMP_TO_EDGE + } + + private val builder = VertexBuilder(FONT_VERTEX_FORMAT, GeometryType.QUADS) + private val vao = VertexArrayObject() + private val vbo = BufferObject.VBO() + private val ebo = BufferObject.EBO() + + init { + vao.elementBuffer = ebo + vao.bindAttributes(vbo, FONT_VERTEX_FORMAT) + } + fun render( text: List, @@ -111,11 +157,7 @@ class Font( if (scale != 1f) model.scale(x = scale, y = scale) - state.programs.font.use() - state.programs.font.colorMultiplier = color - state.programs.font.worldMatrix = state.stack.last() - state.activeTexture = 0 - state.programs.font.texture = 0 + builder.begin() val space = getGlyph(' ') @@ -170,7 +212,19 @@ class Font( model.translate(x = -lineWidth - movedX, y = lineHeight) } - state.vao = null + client.programs.font.use() + client.programs.font.colorMultiplier = color + client.programs.font.worldMatrix = client.stack.last() + + builder.upload(vbo, ebo, GL_STREAM_DRAW) + + client.activeTexture = 0 + atlas.bind() + + client.vao = vao + glDrawElements(GL_TRIANGLES, builder.indexCount, builder.indexType, 0L) + checkForGLError() + client.vao = null return TextSize(totalX * scale, totalY * scale) } @@ -207,10 +261,10 @@ class Font( if (chr == '\t') { if (lineGlyphs % 4 == 0) { lineWidth += space.advanceX * 4 - state.stack.last().translate(x = space.advanceX * 4) + client.stack.last().translate(x = space.advanceX * 4) } else { lineWidth += space.advanceX * (lineGlyphs % 4) - state.stack.last().translate(x = space.advanceX * (lineGlyphs % 4)) + client.stack.last().translate(x = space.advanceX * (lineGlyphs % 4)) } lineGlyphs += lineGlyphs % 4 @@ -243,8 +297,6 @@ class Font( } private inner class Glyph(val char: Char) { - private val texture: GLTexture2D? - val isEmpty: Boolean val width: Float @@ -255,13 +307,13 @@ class Font( val advanceX: Float val advanceY: Float - private val vao: VertexArrayObject? - - private val indexCount: Int - - private val elementIndexType: Int + val uv: Vector4f init { + if (nextAtlasY + bbox.height > atlasHeight) { + throw IllegalStateException("Font atlas is full") + } + face.loadChar(char, LoadFlag.RENDER) val glyph = face.nativeMemory.glyph ?: throw IllegalStateException("Unable to load glyph data for $char (code ${char.code})") val bitmap = glyph.bitmap @@ -282,43 +334,26 @@ class Font( // интересно, а что будет когда буфер будет "вычищен" из памяти? Чо, будет double free? val buff = bitmap.byteBuffer!! - texture = state.newTexture("$font:$char") - glPixelStorei(GL_UNPACK_ALIGNMENT, 1) - texture.upload(GL_RED, bitmap.width, bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, buff) - texture.generateMips() - texture.textureMinFilter = GL_LINEAR - texture.textureMagFilter = GL_LINEAR - texture.textureWrapS = GL_CLAMP_TO_EDGE - texture.textureWrapT = GL_CLAMP_TO_EDGE + try { + uv = Vector4f(nextAtlasX / atlasWidth.toFloat(), nextAtlasY / atlasHeight.toFloat(), (nextAtlasX + bitmap.width) / atlasWidth.toFloat(), (nextAtlasY + bitmap.rows) / atlasHeight.toFloat()) - glPixelStorei(GL_UNPACK_ALIGNMENT, 4) + glTextureSubImage2D(atlas.pointer, 0, nextAtlasX, nextAtlasY, bitmap.width, bitmap.rows, GL_RED, GL_UNSIGNED_BYTE, buff) + checkForGLError("Uploading glyph texture data") - vao = state.newVAO() - val ebo = state.newEBO() - val vbo = state.newVBO() + nextAtlasX += bbox.width - vao.elementBuffer = ebo - vao.bindAttributes(vbo, VertexAttributes.POSITION_UV) - - val builder = VertexBuilder(VertexAttributes.POSITION_UV, GeometryType.QUADS) - - builder.vertex(0f, 0f).uv(0f, 0f) - builder.vertex(width, 0f).uv(1f, 0f) - builder.vertex(width, height).uv(1f, 1f) - builder.vertex(0f, height).uv(0f, 1f) - - builder.upload(vbo, ebo, GL_STATIC_DRAW) - indexCount = builder.indexCount - elementIndexType = builder.indexType + if (nextAtlasX + bbox.width > atlasWidth) { + nextAtlasX = 0 + nextAtlasY += bbox.height + } + } finally { + glPixelStorei(GL_UNPACK_ALIGNMENT, 4) + } } else { isEmpty = true - indexCount = 0 - elementIndexType = 0 - - vao = null - texture = null + uv = Vector4f.ZERO } } @@ -328,14 +363,12 @@ class Font( return } - vao!!.bind() - model.translate(bearingX, -bearingY) - texture!!.bind() - state.programs.font.modelMatrix = model - glDrawElements(GL_TRIANGLES, indexCount, elementIndexType, 0L) - checkForGLError() + builder.vertex(model, 0f, 0f).uv(uv.x, uv.y) + builder.vertex(model, width, 0f).uv(uv.z, uv.y) + builder.vertex(model, width, height).uv(uv.z, uv.w) + builder.vertex(model, 0f, height).uv(uv.x, uv.w) model.translate(advanceX - bearingX, bearingY) } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/client/world/ClientWorld.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/client/world/ClientWorld.kt index e89d2d92..1074fa74 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/client/world/ClientWorld.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/client/world/ClientWorld.kt @@ -270,12 +270,12 @@ class ClientWorld( if (obj.pos.x in client.viewportCellX .. client.viewportCellX + client.viewportCellWidth && obj.pos.y in client.viewportCellY .. client.viewportCellY + client.viewportCellHeight) { //layers.add(RenderLayer.Object.index) { layers.add(obj.orientation?.renderLayer ?: continue) { - client.quadWireframe { + /*client.quadWireframe { it.vertex(obj.pos.x.toFloat(), obj.pos.y.toFloat()) it.vertex(obj.pos.x.toFloat() + 1f, obj.pos.y.toFloat()) it.vertex(obj.pos.x.toFloat() + 1f, obj.pos.y.toFloat() + 1f) it.vertex(obj.pos.x.toFloat(), obj.pos.y.toFloat() + 1f) - } + }*/ obj.drawables.forEach { val (x, y) = obj.imagePosition diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/Drawable.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/Drawable.kt index 0c6e10df..0da155b4 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/defs/Drawable.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/defs/Drawable.kt @@ -84,7 +84,7 @@ sealed class Drawable(val position: Vector2f, val color: RGBAColor, val fullbrig val texture = client.loadTexture(path.imagePath.value!!) val program = if (fullbright) client.programs.positionTexture else client.programs.positionTextureLightmap - program.modelMatrix = transform.map({ it }, { + val mat = transform.map({ it }, { val mat = Matrix3f.identity() it.scale.map({ mat.scale(it / PIXELS_IN_STARBOUND_UNITf, it / PIXELS_IN_STARBOUND_UNITf) }, { mat.scale(it / PIXELS_IN_STARBOUND_UNITf) }) @@ -105,6 +105,9 @@ sealed class Drawable(val position: Vector2f, val color: RGBAColor, val fullbrig mat }) + //program.modelMatrix = mat + program.modelMatrix = Matrix3f.identity() + program.worldMatrix = client.stack.last() program.use() program.texture0 = 0 @@ -112,10 +115,10 @@ sealed class Drawable(val position: Vector2f, val color: RGBAColor, val fullbrig texture.bind() program.builder.builder.begin(GeometryType.QUADS) - program.builder.builder.vertex(x, y).uv(sprite.u0, sprite.v0) - program.builder.builder.vertex(x + sprite.width, y).uv(sprite.u1, sprite.v0) - program.builder.builder.vertex(x + sprite.width, y + sprite.height).uv(sprite.u1, sprite.v1) - program.builder.builder.vertex(x, y + sprite.height).uv(sprite.u0, sprite.v1) + program.builder.builder.vertex(mat, x, y).uv(sprite.u0, sprite.v0) + program.builder.builder.vertex(mat, x + sprite.width, y).uv(sprite.u1, sprite.v0) + program.builder.builder.vertex(mat, x + sprite.width, y + sprite.height).uv(sprite.u1, sprite.v1) + program.builder.builder.vertex(mat, x, y + sprite.height).uv(sprite.u0, sprite.v1) program.builder.upload() program.builder.draw() } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt index 7cf86ab9..b4cec3ea 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/World.kt @@ -18,7 +18,7 @@ import ru.dbotthepony.kstarbound.world.api.ICellAccess import ru.dbotthepony.kstarbound.world.api.IChunkCell import ru.dbotthepony.kstarbound.world.api.TileView import ru.dbotthepony.kstarbound.world.entities.Entity -import ru.dbotthepony.kstarbound.world.`object`.WorldObject +import ru.dbotthepony.kstarbound.world.entities.WorldObject import ru.dbotthepony.kvector.api.IStruct2d import ru.dbotthepony.kvector.api.IStruct2i import ru.dbotthepony.kvector.arrays.Object2DArray diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/Entity.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/Entity.kt index 8b76f9d8..c657a947 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/Entity.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/Entity.kt @@ -4,12 +4,7 @@ import ru.dbotthepony.kstarbound.world.Chunk import ru.dbotthepony.kstarbound.world.World import ru.dbotthepony.kvector.vector.Vector2d -abstract class Entity( - /** - * The world this entity in, never changes. - */ - val world: World<*, *> -) { +abstract class Entity(val world: World<*, *>) { /** * The chunk this entity currently in, it is automatically updated on each change of [position] */ @@ -17,13 +12,9 @@ abstract class Entity( set(value) { if (!isSpawned) { throw IllegalStateException("Trying to set chunk this entity belong to before spawning in world") - } - - if (isRemoved) { + } else if (isRemoved) { throw IllegalStateException("This entity was removed") - } - - if (value == field) { + } else if (value == field) { return } diff --git a/src/main/kotlin/ru/dbotthepony/kstarbound/world/object/WorldObject.kt b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/WorldObject.kt similarity index 99% rename from src/main/kotlin/ru/dbotthepony/kstarbound/world/object/WorldObject.kt rename to src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/WorldObject.kt index dd6ae11d..f123d012 100644 --- a/src/main/kotlin/ru/dbotthepony/kstarbound/world/object/WorldObject.kt +++ b/src/main/kotlin/ru/dbotthepony/kstarbound/world/entities/WorldObject.kt @@ -1,4 +1,4 @@ -package ru.dbotthepony.kstarbound.world.`object` +package ru.dbotthepony.kstarbound.world.entities import com.google.common.collect.ImmutableMap import com.google.gson.JsonObject diff --git a/src/main/resources/shaders/fragment/font.fsh b/src/main/resources/shaders/fragment/font.fsh index 7dfffba9..df9c3547 100644 --- a/src/main/resources/shaders/fragment/font.fsh +++ b/src/main/resources/shaders/fragment/font.fsh @@ -1,7 +1,7 @@ -#version 330 +#version 450 -uniform sampler2D texture0; +layout (binding = 0) uniform sampler2D texture0; uniform vec4 colorMultiplier; out vec4 colorResult; diff --git a/src/main/resources/shaders/vertex/configurable.vsh b/src/main/resources/shaders/vertex/configurable.vsh index c31008c8..2acc7d93 100644 --- a/src/main/resources/shaders/vertex/configurable.vsh +++ b/src/main/resources/shaders/vertex/configurable.vsh @@ -1,5 +1,5 @@ -layout (location = 0) in vec2 pos; +layout (location = 0) in vec3 pos; #ifdef TEXTURE layout (location = TEXTURE) in vec2 uvIn; @@ -21,7 +21,7 @@ uniform mat3 worldMatrix; // matrix stack uniform mat3 modelMatrix; // local transformations void main() { - vec3 result = viewMatrix * worldMatrix * modelMatrix * vec3(pos, 1.0); + vec3 result = viewMatrix * worldMatrix * modelMatrix * pos; gl_Position = vec4(result.x, result.y, 0.0, result.z); #ifdef HUE_SHIFT diff --git a/src/main/resources/shaders/vertex/font.vsh b/src/main/resources/shaders/vertex/font.vsh index e2aafaaf..34c9a0c8 100644 --- a/src/main/resources/shaders/vertex/font.vsh +++ b/src/main/resources/shaders/vertex/font.vsh @@ -1,17 +1,16 @@ -#version 330 +#version 450 -layout (location = 0) in vec2 pos; +layout (location = 0) in vec3 pos; layout (location = 1) in vec2 uvData; uniform mat3 viewMatrix; // projection (viewport) uniform mat3 worldMatrix; // world position -uniform mat3 modelMatrix; // mesh/local transformations out vec2 uvOut; void main() { - vec3 result = viewMatrix * worldMatrix * modelMatrix * vec3(pos, 1.0); + vec3 result = viewMatrix * worldMatrix * pos; gl_Position = vec4(result.x, result.y, 0.0, result.z); uvOut = uvData;