From 940ca35471edd615bc36e4928e82545479bb56f6 Mon Sep 17 00:00:00 2001 From: Bixilon Date: Wed, 20 Apr 2022 18:25:50 +0200 Subject: [PATCH] wip 3d text rendering --- .../data/entities/block/SignBlockEntity.kt | 2 +- .../minosoft/gui/rendering/RenderConstants.kt | 4 +- .../minosoft/gui/rendering/font/CharData.kt | 28 +++++++++++++ .../font/renderer/BaseComponentRenderer.kt | 8 ++++ .../font/renderer/ChatComponentRenderer.kt | 40 +++++++++++++++++++ .../font/renderer/TextComponentRenderer.kt | 6 +++ .../system/base/phases/OpaqueDrawable.kt | 2 +- .../renderer/sign/SignBlockEntityRenderer.kt | 11 ++++- .../preparer/cull/SolidCullSectionPreparer.kt | 2 +- 9 files changed, 97 insertions(+), 6 deletions(-) diff --git a/src/main/java/de/bixilon/minosoft/data/entities/block/SignBlockEntity.kt b/src/main/java/de/bixilon/minosoft/data/entities/block/SignBlockEntity.kt index db19cdd43..5233a7d01 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/block/SignBlockEntity.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/block/SignBlockEntity.kt @@ -42,7 +42,7 @@ class SignBlockEntity(connection: PlayConnection) : MeshedBlockEntity(connection } override fun createMeshedRenderer(renderWindow: RenderWindow, blockState: BlockState, blockPosition: Vec3i): SignBlockEntityRenderer { - return SignBlockEntityRenderer(this, blockState) + return SignBlockEntityRenderer(this, renderWindow, blockState) } companion object : BlockEntityFactory { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.kt index 84a697a95..854df9f7b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/RenderConstants.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2021 Moritz Zwerger + * Copyright (C) 2020-2022 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. * @@ -33,7 +33,7 @@ object RenderConstants { val TEXT_BACKGROUND_COLOR = RGBColor(0, 0, 0, 80) - const val FRUSTUM_CULLING_ENABLED = true + const val FRUSTUM_CULLING_ENABLED = false const val SHOW_FPS_IN_WINDOW_TITLE = true const val MAXIMUM_QUEUE_TIME_PER_FRAME = 20L 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 a3d9a2663..443a30062 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 @@ -13,15 +13,19 @@ package de.bixilon.minosoft.gui.rendering.font +import de.bixilon.kotlinglm.mat4x4.Mat4 import de.bixilon.kotlinglm.vec2.Vec2 import de.bixilon.kotlinglm.vec2.Vec2i import de.bixilon.kotlinglm.vec2.Vec2t +import de.bixilon.kotlinglm.vec3.Vec3 +import de.bixilon.kotlinglm.vec4.Vec4 import de.bixilon.kutil.math.simple.FloatMath.ceil import de.bixilon.minosoft.data.text.RGBColor import de.bixilon.minosoft.gui.rendering.RenderWindow 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.WorldMesh class CharData( private val renderWindow: RenderWindow, @@ -122,6 +126,30 @@ class CharData( return (width * scale).ceil } + fun render3d(matrix: Mat4, mesh: WorldMesh, color: RGBColor): Float { + val endMatrix = matrix * Mat4().translateAssign(Vec3(width, Font.CHAR_HEIGHT.toFloat(), 0)) + val startPosition = matrix * Vec4(1, 1, 1, 1) + val endPosition = endMatrix * Vec4(1, 1, 1, 1) + val positions = arrayOf( + Vec3(startPosition.x, startPosition.y, startPosition.z), + Vec3(endPosition.x, startPosition.y, endPosition.z), + Vec3(endPosition.x, endPosition.y, endPosition.z), + Vec3(startPosition.x, endPosition.y, startPosition.z), + ) + val texturePositions = arrayOf( + Vec2(uvEnd.x, uvStart.y), + uvStart, + Vec2(uvStart.x, uvEnd.y), + uvEnd, + ) + + val opaqueMesh = mesh.opaqueMesh ?: return 0.0f + for ((vertexIndex, textureIndex) in opaqueMesh.order) { + opaqueMesh.addVertex(positions[vertexIndex].array, texturePositions[textureIndex], texture ?: return 0.0f, color.rgb, 0xFF) + } + return width.toFloat() + } + companion object { const val ITALIC_OFFSET = 2.5f 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 d4b223c2b..5abf9dece 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 @@ -13,12 +13,14 @@ package de.bixilon.minosoft.gui.rendering.font.renderer +import de.bixilon.kotlinglm.mat4x4.Mat4 import de.bixilon.kotlinglm.vec2.Vec2i import de.bixilon.minosoft.data.text.BaseComponent 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 object BaseComponentRenderer : ChatComponentRenderer { @@ -30,4 +32,10 @@ object BaseComponentRenderer : ChatComponentRenderer { } return false } + + override fun render3DFlat(matrix: Mat4, mesh: WorldMesh, text: BaseComponent) { + for (part in text.parts) { + ChatComponentRenderer.render3DFlat(matrix, mesh, text) + } + } } 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 2db4f3160..bf2f49dd5 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 @@ -13,14 +13,20 @@ package de.bixilon.minosoft.gui.rendering.font.renderer +import de.bixilon.kotlinglm.GLM +import de.bixilon.kotlinglm.func.rad +import de.bixilon.kotlinglm.mat4x4.Mat4 import de.bixilon.kotlinglm.vec2.Vec2i +import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.minosoft.data.text.BaseComponent +import de.bixilon.minosoft.data.text.ChatColors import de.bixilon.minosoft.data.text.ChatComponent import de.bixilon.minosoft.data.text.TextComponent 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 interface ChatComponentRenderer { @@ -29,8 +35,11 @@ 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(matrix: Mat4, mesh: WorldMesh, text: T) companion object : ChatComponentRenderer { + const val TEXT_BLOCK_RESOLUTION = 64 + var a = 0.0f override fun render(initialOffset: Vec2i, offset: Vec2i, size: Vec2i, element: Element, renderWindow: RenderWindow, consumer: GUIVertexConsumer?, options: GUIVertexOptions?, renderInfo: TextRenderInfo, text: ChatComponent): Boolean { return when (text) { @@ -39,5 +48,36 @@ interface ChatComponentRenderer { else -> TODO("Don't know how to render ${text::class.java}") } } + + override fun render3DFlat(matrix: Mat4, mesh: WorldMesh, text: ChatComponent) { + when (text) { + is BaseComponent -> BaseComponentRenderer.render3DFlat(matrix, mesh, text) + is TextComponent -> TextComponentRenderer.render3DFlat(matrix, mesh, text) + else -> TODO("Don't know how to render ${text::class.java}") + } + } + + fun render3dFlat(renderWindow: RenderWindow, position: Vec3, scale: Float, rotation: Vec3, mesh: WorldMesh, text: ChatComponent) { + val positionMatrix = Mat4() + .translateAssign(position) + .rotateAssign(a.rad, Vec3(0, 1, 0)) * Mat4() + .translateAssign(-position) + + var orthoMatrix = positionMatrix * GLM.ortho(0.0f, TEXT_BLOCK_RESOLUTION.toFloat(), TEXT_BLOCK_RESOLUTION.toFloat(), 0.0f) + a += 3.0f + if (a > 360) { + a = 0.0f + } + + val text = "abcdefghijkl" + + + for ((index, char) in text.codePoints().toArray().withIndex()) { + val data = renderWindow.font[char] ?: continue + val width = data.render3d(orthoMatrix, mesh, ChatColors[index % ChatColors.VALUES.size]) + val translated = Mat4().translateAssign(Vec3(width, 0, 0)) + orthoMatrix = orthoMatrix * translated + } + } } } 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 eb688be1c..9dd204d7d 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 @@ -13,6 +13,7 @@ package de.bixilon.minosoft.gui.rendering.font.renderer +import de.bixilon.kotlinglm.mat4x4.Mat4 import de.bixilon.kotlinglm.vec2.Vec2i import de.bixilon.minosoft.data.text.ChatColors import de.bixilon.minosoft.data.text.PreChatFormattingCodes @@ -23,6 +24,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 object TextComponentRenderer : ChatComponentRenderer { @@ -186,4 +188,8 @@ object TextComponentRenderer : ChatComponentRenderer { pushLine() return false } + + override fun render3DFlat(matrix: Mat4, mesh: WorldMesh, text: TextComponent) { + TODO("Not yet implemented") + } } 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 b246e810c..4453955b6 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() + renderSystem.reset(faceCulling = false) } fun drawOpaque() diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/renderer/sign/SignBlockEntityRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/renderer/sign/SignBlockEntityRenderer.kt index 4ba50796a..dd0e059d0 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/renderer/sign/SignBlockEntityRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/entities/renderer/sign/SignBlockEntityRenderer.kt @@ -13,28 +13,37 @@ package de.bixilon.minosoft.gui.rendering.world.entities.renderer.sign +import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.kotlinglm.vec3.Vec3i import de.bixilon.minosoft.data.entities.block.SignBlockEntity import de.bixilon.minosoft.data.registries.blocks.BlockState import de.bixilon.minosoft.data.registries.blocks.types.entity.sign.StandingSignBlock import de.bixilon.minosoft.data.registries.blocks.types.entity.sign.WallSignBlock +import de.bixilon.minosoft.gui.rendering.RenderWindow +import de.bixilon.minosoft.gui.rendering.font.renderer.ChatComponentRenderer +import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3 import de.bixilon.minosoft.gui.rendering.world.entities.MeshedBlockEntityRenderer import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh import java.util.* class SignBlockEntityRenderer( val sign: SignBlockEntity, + val renderWindow: RenderWindow, override val blockState: BlockState, ) : MeshedBlockEntityRenderer { override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array, light: ByteArray, ambientLight: FloatArray, tints: IntArray?): Boolean { val block = this.blockState.block + if (position.x != 0 || position.y != 1 || position.z != 0) { + return false + } if (block is StandingSignBlock) { - println("Rendering standing sign at $position (${block.resourceLocation})") + // println("Rendering standing sign at $position (${block.resourceLocation})") } else if (block is WallSignBlock) { println("Rendering wall sign at $position (${block.resourceLocation})") } + ChatComponentRenderer.render3dFlat(renderWindow, position.toVec3 + Vec3(0, 1.0f, 0.0f), 1.0f, Vec3(), mesh, sign.lines[0]) // ToDo return true diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/SolidCullSectionPreparer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/SolidCullSectionPreparer.kt index fed77fae0..ef62d00b0 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/SolidCullSectionPreparer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/world/preparer/cull/SolidCullSectionPreparer.kt @@ -166,7 +166,7 @@ class SolidCullSectionPreparer( random.setSeed(0L) } tints = tintColorCalculator.getAverageTint(chunk, neighbourChunks, blockState, x, y, z) - rendered = model.singleRender(position, mesh, random, blockState, neighbourBlocks, light, ambientLight, tints) + rendered = false // rendered = model.singleRender(position, mesh, random, blockState, neighbourBlocks, light, ambientLight, tints) if (blockEntityModel is MeshedBlockEntityRenderer<*>) { rendered = blockEntityModel.singleRender(position, mesh, random, blockState, neighbourBlocks, light, ambientLight, tints) || rendered