wip 3d text rendering

This commit is contained in:
Bixilon 2022-04-20 18:25:50 +02:00
parent 4db50e521e
commit 940ca35471
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
9 changed files with 97 additions and 6 deletions

View File

@ -42,7 +42,7 @@ class SignBlockEntity(connection: PlayConnection) : MeshedBlockEntity(connection
} }
override fun createMeshedRenderer(renderWindow: RenderWindow, blockState: BlockState, blockPosition: Vec3i): SignBlockEntityRenderer { override fun createMeshedRenderer(renderWindow: RenderWindow, blockState: BlockState, blockPosition: Vec3i): SignBlockEntityRenderer {
return SignBlockEntityRenderer(this, blockState) return SignBlockEntityRenderer(this, renderWindow, blockState)
} }
companion object : BlockEntityFactory<SignBlockEntity> { companion object : BlockEntityFactory<SignBlockEntity> {

View File

@ -1,6 +1,6 @@
/* /*
* Minosoft * 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. * 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) 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 SHOW_FPS_IN_WINDOW_TITLE = true
const val MAXIMUM_QUEUE_TIME_PER_FRAME = 20L const val MAXIMUM_QUEUE_TIME_PER_FRAME = 20L

View File

@ -13,15 +13,19 @@
package de.bixilon.minosoft.gui.rendering.font package de.bixilon.minosoft.gui.rendering.font
import de.bixilon.kotlinglm.mat4x4.Mat4
import de.bixilon.kotlinglm.vec2.Vec2 import de.bixilon.kotlinglm.vec2.Vec2
import de.bixilon.kotlinglm.vec2.Vec2i import de.bixilon.kotlinglm.vec2.Vec2i
import de.bixilon.kotlinglm.vec2.Vec2t 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.kutil.math.simple.FloatMath.ceil
import de.bixilon.minosoft.data.text.RGBColor import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions 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.system.base.texture.texture.AbstractTexture
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
class CharData( class CharData(
private val renderWindow: RenderWindow, private val renderWindow: RenderWindow,
@ -122,6 +126,30 @@ class CharData(
return (width * scale).ceil 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 { companion object {
const val ITALIC_OFFSET = 2.5f const val ITALIC_OFFSET = 2.5f

View File

@ -13,12 +13,14 @@
package de.bixilon.minosoft.gui.rendering.font.renderer package de.bixilon.minosoft.gui.rendering.font.renderer
import de.bixilon.kotlinglm.mat4x4.Mat4
import de.bixilon.kotlinglm.vec2.Vec2i import de.bixilon.kotlinglm.vec2.Vec2i
import de.bixilon.minosoft.data.text.BaseComponent import de.bixilon.minosoft.data.text.BaseComponent
import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.gui.elements.Element 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.GUIVertexConsumer
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
object BaseComponentRenderer : ChatComponentRenderer<BaseComponent> { object BaseComponentRenderer : ChatComponentRenderer<BaseComponent> {
@ -30,4 +32,10 @@ object BaseComponentRenderer : ChatComponentRenderer<BaseComponent> {
} }
return false return false
} }
override fun render3DFlat(matrix: Mat4, mesh: WorldMesh, text: BaseComponent) {
for (part in text.parts) {
ChatComponentRenderer.render3DFlat(matrix, mesh, text)
}
}
} }

View File

@ -13,14 +13,20 @@
package de.bixilon.minosoft.gui.rendering.font.renderer 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.vec2.Vec2i
import de.bixilon.kotlinglm.vec3.Vec3
import de.bixilon.minosoft.data.text.BaseComponent 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.ChatComponent
import de.bixilon.minosoft.data.text.TextComponent import de.bixilon.minosoft.data.text.TextComponent
import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.gui.elements.Element 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.GUIVertexConsumer
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
interface ChatComponentRenderer<T : ChatComponent> { interface ChatComponentRenderer<T : ChatComponent> {
@ -29,8 +35,11 @@ interface ChatComponentRenderer<T : ChatComponent> {
*/ */
fun render(initialOffset: Vec2i, offset: Vec2i, size: Vec2i, element: Element, renderWindow: RenderWindow, consumer: GUIVertexConsumer?, options: GUIVertexOptions?, renderInfo: TextRenderInfo, text: T): Boolean 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<ChatComponent> { companion object : ChatComponentRenderer<ChatComponent> {
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 { 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) { return when (text) {
@ -39,5 +48,36 @@ interface ChatComponentRenderer<T : ChatComponent> {
else -> TODO("Don't know how to render ${text::class.java}") 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
}
}
} }
} }

View File

@ -13,6 +13,7 @@
package de.bixilon.minosoft.gui.rendering.font.renderer package de.bixilon.minosoft.gui.rendering.font.renderer
import de.bixilon.kotlinglm.mat4x4.Mat4
import de.bixilon.kotlinglm.vec2.Vec2i import de.bixilon.kotlinglm.vec2.Vec2i
import de.bixilon.minosoft.data.text.ChatColors import de.bixilon.minosoft.data.text.ChatColors
import de.bixilon.minosoft.data.text.PreChatFormattingCodes 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.elements.HorizontalAlignments.Companion.getOffset
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexConsumer
import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions import de.bixilon.minosoft.gui.rendering.gui.mesh.GUIVertexOptions
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
object TextComponentRenderer : ChatComponentRenderer<TextComponent> { object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
@ -186,4 +188,8 @@ object TextComponentRenderer : ChatComponentRenderer<TextComponent> {
pushLine() pushLine()
return false return false
} }
override fun render3DFlat(matrix: Mat4, mesh: WorldMesh, text: TextComponent) {
TODO("Not yet implemented")
}
} }

View File

@ -20,7 +20,7 @@ interface OpaqueDrawable : Renderer {
get() = false get() = false
fun setupOpaque() { fun setupOpaque() {
renderSystem.reset() renderSystem.reset(faceCulling = false)
} }
fun drawOpaque() fun drawOpaque()

View File

@ -13,28 +13,37 @@
package de.bixilon.minosoft.gui.rendering.world.entities.renderer.sign 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.kotlinglm.vec3.Vec3i
import de.bixilon.minosoft.data.entities.block.SignBlockEntity import de.bixilon.minosoft.data.entities.block.SignBlockEntity
import de.bixilon.minosoft.data.registries.blocks.BlockState 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.StandingSignBlock
import de.bixilon.minosoft.data.registries.blocks.types.entity.sign.WallSignBlock 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.entities.MeshedBlockEntityRenderer
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
import java.util.* import java.util.*
class SignBlockEntityRenderer( class SignBlockEntityRenderer(
val sign: SignBlockEntity, val sign: SignBlockEntity,
val renderWindow: RenderWindow,
override val blockState: BlockState, override val blockState: BlockState,
) : MeshedBlockEntityRenderer<SignBlockEntity> { ) : MeshedBlockEntityRenderer<SignBlockEntity> {
override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, ambientLight: FloatArray, tints: IntArray?): Boolean { override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, ambientLight: FloatArray, tints: IntArray?): Boolean {
val block = this.blockState.block val block = this.blockState.block
if (position.x != 0 || position.y != 1 || position.z != 0) {
return false
}
if (block is StandingSignBlock) { 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) { } else if (block is WallSignBlock) {
println("Rendering wall sign at $position (${block.resourceLocation})") 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 // ToDo
return true return true

View File

@ -166,7 +166,7 @@ class SolidCullSectionPreparer(
random.setSeed(0L) random.setSeed(0L)
} }
tints = tintColorCalculator.getAverageTint(chunk, neighbourChunks, blockState, x, y, z) 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<*>) { if (blockEntityModel is MeshedBlockEntityRenderer<*>) {
rendered = blockEntityModel.singleRender(position, mesh, random, blockState, neighbourBlocks, light, ambientLight, tints) || rendered rendered = blockEntityModel.singleRender(position, mesh, random, blockState, neighbourBlocks, light, ambientLight, tints) || rendered