diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/font/CharData.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/font/CharData.kt index 076dc96d7..55c1d7e6d 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/font/CharData.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/font/CharData.kt @@ -27,7 +27,6 @@ import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture import de.bixilon.minosoft.gui.rendering.world.mesh.SingleWorldMesh -import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh class CharData( private val renderWindow: RenderWindow, @@ -128,8 +127,8 @@ class CharData( return (width * scale).ceil } - fun render3d(transform: Mat4, mesh: WorldMesh, color: RGBColor, shadow: Boolean, italic: Boolean, bold: Boolean, strikethrough: Boolean, underlined: Boolean, scale: Float, light: Int): Float { - val consumer = MeshConsumer(mesh.opaqueMesh!!, transform, light) + fun render3d(transform: Mat4, mesh: SingleWorldMesh, color: RGBColor, shadow: Boolean, italic: Boolean, bold: Boolean, strikethrough: Boolean, underlined: Boolean, scale: Float, light: Int): Float { + val consumer = MeshConsumer(mesh, transform, light) render(Vec2i(0, 0), color, shadow, italic, bold, strikethrough, underlined, consumer, null, scale) return width.toFloat() } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/font/renderer/BaseComponentRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/font/renderer/BaseComponentRenderer.kt index 186219843..1a0d4e915 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/font/renderer/BaseComponentRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/font/renderer/BaseComponentRenderer.kt @@ -20,7 +20,7 @@ import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.gui.elements.Element import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions -import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh +import de.bixilon.minosoft.gui.rendering.world.mesh.SingleWorldMesh object BaseComponentRenderer : ChatComponentRenderer { @@ -33,7 +33,7 @@ object BaseComponentRenderer : ChatComponentRenderer { return false } - override fun render3dFlat(renderWindow: RenderWindow, matrix: Mat4, scale: Float, mesh: WorldMesh, text: BaseComponent, light: Int) { + override fun render3dFlat(renderWindow: RenderWindow, matrix: Mat4, scale: Float, mesh: SingleWorldMesh, text: BaseComponent, light: Int) { for (part in text.parts) { ChatComponentRenderer.render3dFlat(renderWindow, matrix, scale, mesh, part, light) } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/font/renderer/ChatComponentRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/font/renderer/ChatComponentRenderer.kt index e8095cf50..5b5fcc6b4 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/font/renderer/ChatComponentRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/font/renderer/ChatComponentRenderer.kt @@ -24,6 +24,7 @@ import de.bixilon.minosoft.gui.rendering.gui.elements.Element import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions import de.bixilon.minosoft.gui.rendering.util.mat.mat4.Mat4Util.rotateDegreesAssign +import de.bixilon.minosoft.gui.rendering.world.mesh.SingleWorldMesh import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh interface ChatComponentRenderer { @@ -33,7 +34,7 @@ interface ChatComponentRenderer { */ fun render(initialOffset: Vec2i, offset: Vec2i, size: Vec2i, element: Element, renderWindow: RenderWindow, consumer: GUIVertexConsumer?, options: GUIVertexOptions?, renderInfo: TextRenderInfo, text: T): Boolean - fun render3dFlat(renderWindow: RenderWindow, matrix: Mat4, scale: Float, mesh: WorldMesh, text: T, light: Int) + fun render3dFlat(renderWindow: RenderWindow, matrix: Mat4, scale: Float, mesh: SingleWorldMesh, text: T, light: Int) companion object : ChatComponentRenderer { const val TEXT_BLOCK_RESOLUTION = 128 @@ -46,7 +47,7 @@ interface ChatComponentRenderer { } } - override fun render3dFlat(renderWindow: RenderWindow, matrix: Mat4, scale: Float, mesh: WorldMesh, text: ChatComponent, light: Int) { + override fun render3dFlat(renderWindow: RenderWindow, matrix: Mat4, scale: Float, mesh: SingleWorldMesh, text: ChatComponent, light: Int) { when (text) { is BaseComponent -> BaseComponentRenderer.render3dFlat(renderWindow, matrix, scale, mesh, text, light) is TextComponent -> TextComponentRenderer.render3dFlat(renderWindow, matrix, scale, mesh, text, light) @@ -61,7 +62,7 @@ interface ChatComponentRenderer { .translateAssign(Vec3(0, 0, -1)) - render3dFlat(renderWindow, matrix, scale, mesh, text, light) + render3dFlat(renderWindow, matrix, scale, mesh.textMesh!!, text, light) } } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/font/renderer/TextComponentRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/font/renderer/TextComponentRenderer.kt index b9df828bb..79bbcfb71 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/font/renderer/TextComponentRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/font/renderer/TextComponentRenderer.kt @@ -25,7 +25,7 @@ import de.bixilon.minosoft.gui.rendering.gui.elements.Element import de.bixilon.minosoft.gui.rendering.gui.elements.HorizontalAlignments.Companion.getOffset import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions -import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh +import de.bixilon.minosoft.gui.rendering.world.mesh.SingleWorldMesh object TextComponentRenderer : ChatComponentRenderer { @@ -190,7 +190,7 @@ object TextComponentRenderer : ChatComponentRenderer { return false } - override fun render3dFlat(renderWindow: RenderWindow, matrix: Mat4, scale: Float, mesh: WorldMesh, text: TextComponent, light: Int) { + override fun render3dFlat(renderWindow: RenderWindow, matrix: Mat4, scale: Float, mesh: SingleWorldMesh, text: TextComponent, light: Int) { for ((index, char) in text.message.codePoints().toArray().withIndex()) { val data = renderWindow.font[char] ?: continue val color = ChatColors[index % ChatColors.VALUES.size] diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/phases/OpaqueDrawable.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/phases/OpaqueDrawable.kt index 4453955b6..b246e810c 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/phases/OpaqueDrawable.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/system/base/phases/OpaqueDrawable.kt @@ -20,7 +20,7 @@ interface OpaqueDrawable : Renderer { get() = false fun setupOpaque() { - renderSystem.reset(faceCulling = false) + renderSystem.reset() } fun drawOpaque() diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldRenderer.kt index 042e9f4fb..d9a0d4a56 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/WorldRenderer.kt @@ -48,6 +48,7 @@ import de.bixilon.minosoft.gui.rendering.system.base.RenderSystem import de.bixilon.minosoft.gui.rendering.system.base.phases.OpaqueDrawable import de.bixilon.minosoft.gui.rendering.system.base.phases.TranslucentDrawable import de.bixilon.minosoft.gui.rendering.system.base.phases.TransparentDrawable +import de.bixilon.minosoft.gui.rendering.system.base.shader.Shader import de.bixilon.minosoft.gui.rendering.textures.TextureUtil.texture import de.bixilon.minosoft.gui.rendering.util.VecUtil.chunkPosition import de.bixilon.minosoft.gui.rendering.util.VecUtil.empty @@ -87,6 +88,7 @@ class WorldRenderer( private val frustum = renderWindow.camera.matrixHandler.frustum private val shader = renderSystem.createShader("minosoft:world".toResourceLocation()) private val transparentShader = renderSystem.createShader("minosoft:world".toResourceLocation()) + private val textShader = renderSystem.createShader("minosoft:world/text".toResourceLocation()) private val world: World = connection.world private val solidSectionPreparer: SolidSectionPreparer = SolidCullSectionPreparer(renderWindow) private val fluidSectionPreparer: FluidSectionPreparer = FluidCullSectionPreparer(renderWindow) @@ -138,17 +140,22 @@ class WorldRenderer( } } - override fun postInit(latch: CountUpAndDownLatch) { + private fun loadWorldShader(shader: Shader, animations: Boolean = true) { shader.load() renderWindow.textureManager.staticTextures.use(shader) - renderWindow.textureManager.staticTextures.animator.use(shader) + if (animations) { + renderWindow.textureManager.staticTextures.animator.use(shader) + } renderWindow.lightMap.use(shader) + } + + override fun postInit(latch: CountUpAndDownLatch) { + loadWorldShader(this.shader) transparentShader.defines["TRANSPARENT"] = "" - transparentShader.load() - renderWindow.textureManager.staticTextures.use(transparentShader) - renderWindow.textureManager.staticTextures.animator.use(transparentShader) - renderWindow.lightMap.use(transparentShader) + loadWorldShader(this.transparentShader) + + loadWorldShader(this.textShader, false) connection.registerEvent(CallbackEventInvoker.of { onFrustumChange() }) @@ -680,6 +687,11 @@ class WorldRenderer( for (mesh in visible.transparent) { mesh.draw() } + + textShader.use() + for (mesh in visible.text) { + mesh.draw() + } } private fun isChunkVisible(chunkPosition: Vec2i): Boolean { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/mesh/VisibleMeshes.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/mesh/VisibleMeshes.kt index 9725a6e00..ec6f41e8b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/mesh/VisibleMeshes.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/mesh/VisibleMeshes.kt @@ -22,10 +22,11 @@ class VisibleMeshes(val cameraPosition: Vec3 = Vec3.EMPTY) { val opaque: MutableList = mutableListOf() val translucent: MutableList = mutableListOf() val transparent: MutableList = mutableListOf() + val text: MutableList = mutableListOf() val blockEntities: MutableList> = mutableListOf() val sizeString: String - get() = "${opaque.size.format()}|${translucent.size.format()}|${transparent.size.format()}|${blockEntities.size.format()}" + get() = "${opaque.size.format()}|${translucent.size.format()}|${transparent.size.format()}|${text.size.format()}|${blockEntities.size.format()}" fun addMesh(mesh: WorldMesh) { @@ -42,6 +43,10 @@ class VisibleMeshes(val cameraPosition: Vec3 = Vec3.EMPTY) { it.distance = distance transparent += it } + mesh.textMesh?.let { + it.distance = distance + text += it + } mesh.blockEntities?.let { blockEntities += it } @@ -52,6 +57,7 @@ class VisibleMeshes(val cameraPosition: Vec3 = Vec3.EMPTY) { opaque.sortBy { it.distance } translucent.sortBy { -it.distance } transparent.sortBy { it.distance } + text.sortBy { it.distance } } @@ -59,6 +65,7 @@ class VisibleMeshes(val cameraPosition: Vec3 = Vec3.EMPTY) { mesh.opaqueMesh?.let { opaque -= it } mesh.translucentMesh?.let { translucent -= it } mesh.transparentMesh?.let { transparent -= it } + mesh.textMesh?.let { text -= it } mesh.blockEntities?.let { blockEntities -= it } } @@ -66,6 +73,7 @@ class VisibleMeshes(val cameraPosition: Vec3 = Vec3.EMPTY) { opaque.clear() translucent.clear() transparent.clear() + text.clear() blockEntities.clear() } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/mesh/WorldMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/mesh/WorldMesh.kt index b35b35e8f..bd2c3c96a 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/mesh/WorldMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/mesh/WorldMesh.kt @@ -30,6 +30,7 @@ class WorldMesh( var opaqueMesh: SingleWorldMesh? = SingleWorldMesh(renderWindow, if (smallMesh) 1000 else 100000) var translucentMesh: SingleWorldMesh? = SingleWorldMesh(renderWindow, if (smallMesh) 1000 else 10000) var transparentMesh: SingleWorldMesh? = SingleWorldMesh(renderWindow, if (smallMesh) 1000 else 20000) + var textMesh: SingleWorldMesh? = SingleWorldMesh(renderWindow, if (smallMesh) 1000 else 20000) var blockEntities: Set>? = null // used for frustum culling @@ -41,6 +42,7 @@ class WorldMesh( this.opaqueMesh?.load() this.translucentMesh?.load() this.transparentMesh?.load() + this.textMesh?.load() val blockEntities = this.blockEntities if (blockEntities != null) { for (blockEntity in blockEntities) { @@ -76,6 +78,14 @@ class WorldMesh( meshes++ } } + textMesh?.let { + if (it.data.isEmpty) { + it.data.unload() + textMesh = null + } else { + meshes++ + } + } blockEntities?.let { if (it.isEmpty()) { blockEntities = null @@ -91,6 +101,7 @@ class WorldMesh( opaqueMesh?.unload() translucentMesh?.unload() transparentMesh?.unload() + textMesh?.unload() val blockEntities = blockEntities if (blockEntities != null) { diff --git a/src/main/resources/assets/minosoft/rendering/shader/hud/hud.fsh b/src/main/resources/assets/minosoft/rendering/shader/hud/hud.fsh index a2ee90bbb..8ab3c2ded 100644 --- a/src/main/resources/assets/minosoft/rendering/shader/hud/hud.fsh +++ b/src/main/resources/assets/minosoft/rendering/shader/hud/hud.fsh @@ -20,6 +20,8 @@ out vec4 foutColor; #include "minosoft:texture" #include "minosoft:alpha" +#define MIPMAP_LEVEL 0.0f + void main() { #include "minosoft:animation/main_fragment" } diff --git a/src/main/resources/assets/minosoft/rendering/shader/includes/animation/main_fragment.glsl b/src/main/resources/assets/minosoft/rendering/shader/includes/animation/main_fragment.glsl index 8fee1e482..ed0246272 100644 --- a/src/main/resources/assets/minosoft/rendering/shader/includes/animation/main_fragment.glsl +++ b/src/main/resources/assets/minosoft/rendering/shader/includes/animation/main_fragment.glsl @@ -12,7 +12,11 @@ */ +#ifdef MIPMAP_LEVEL +vec4 firstTexelColor = getTexture(finTextureIndex1, finTextureCoordinates1, MIPMAP_LEVEL); +#else vec4 firstTexelColor = getTexture(finTextureIndex1, finTextureCoordinates1); +#endif discard_if_0(firstTexelColor.a); if (finInterpolation == 0.0f) { @@ -26,8 +30,11 @@ if (finInterpolation == 0.0f) { #endif return; } - + #ifdef MIPMAP_LEVEL +vec4 secondTexelColor = getTexture(finTextureIndex2, finTextureCoordinates2, MIPMAP_LEVEL); +#else vec4 secondTexelColor = getTexture(finTextureIndex2, finTextureCoordinates2); +#endif discard_if_0(secondTexelColor.a); diff --git a/src/main/resources/assets/minosoft/rendering/shader/world/text/text.fsh b/src/main/resources/assets/minosoft/rendering/shader/world/text/text.fsh new file mode 100644 index 000000000..b620c244a --- /dev/null +++ b/src/main/resources/assets/minosoft/rendering/shader/world/text/text.fsh @@ -0,0 +1,37 @@ +/* + * Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +#version 330 core + +out vec4 foutColor; + + +flat in uint finTextureIndex; +in vec3 finTextureCoordinates; + +in vec4 finTintColor; + + +#include "minosoft:texture" +#include "minosoft:alpha" +#include "minosoft:fog" + +void main() { + vec4 texelColor = getTexture(finTextureIndex, finTextureCoordinates, 0.0f); + discard_if_0(texelColor.a); + + foutColor = texelColor * finTintColor; + set_alpha_transparent(); + + set_fog(); +} diff --git a/src/main/resources/assets/minosoft/rendering/shader/world/text/text.vsh b/src/main/resources/assets/minosoft/rendering/shader/world/text/text.vsh new file mode 100644 index 000000000..0362aba35 --- /dev/null +++ b/src/main/resources/assets/minosoft/rendering/shader/world/text/text.vsh @@ -0,0 +1,42 @@ +/* + * Minosoft + * Copyright (C) 2020 Moritz Zwerger + * + * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with this program. If not, see . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +#version 330 core + +layout (location = 0) in vec3 vinPosition; +layout (location = 1) in vec2 vinUV; +layout (location = 2) in uint vinIndexLayerAnimation;// texture index (0xF0000000), texture layer (0x0FFFF000) +layout (location = 3) in uint vinTintColorAndLight;// Light (0xFF000000); 3 bytes color (0x00FFFFFF) + +uniform mat4 uViewProjectionMatrix; + + +flat out uint finTextureIndex; +out vec3 finTextureCoordinates; +out vec3 finFragmentPosition; + +out vec4 finTintColor; + + + +#include "minosoft:color" +#include "minosoft:light" + +void main() { + gl_Position = uViewProjectionMatrix * vec4(vinPosition, 1.0f); + finTintColor = getRGBColor(vinTintColorAndLight & 0xFFFFFFu) * getLight(vinTintColorAndLight >> 24u); + finFragmentPosition = vinPosition; + + finTextureIndex = vinIndexLayerAnimation >> 28u; + finTextureCoordinates = vec3(vinUV, ((vinIndexLayerAnimation >> 12) & 0xFFFFu)); +}