render baked faces

This commit is contained in:
Bixilon 2023-03-24 22:13:28 +01:00
parent d500febd27
commit 5b8a7bf843
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
12 changed files with 107 additions and 68 deletions

View File

@ -54,7 +54,7 @@ object BakedModelTestUtil {
}
fun BakedModel.assertFace(direction: Directions, positions: FloatArray, uv: FloatArray, shade: Float, texture: String? = null) {
val faces = this.face[direction.ordinal]
val faces = this.faces[direction.ordinal]
if (faces.size != 1) throw IllegalArgumentException("Model has more/less than once face!")
val face = faces.first()

View File

@ -17,13 +17,13 @@ import de.bixilon.minosoft.data.registries.blocks.state.builder.BlockStateSettin
import de.bixilon.minosoft.data.registries.blocks.state.error.StatelessBlockError
import de.bixilon.minosoft.data.registries.blocks.types.Block
import de.bixilon.minosoft.data.registries.identified.ResourceLocation
import de.bixilon.minosoft.gui.rendering.models.block.legacy.BakedBlockModel
import de.bixilon.minosoft.gui.rendering.models.block.state.render.BlockRender
open class BlockState(
val block: Block,
val luminance: Int,
) {
var model: BakedBlockModel? = null
var model: BlockRender? = null
constructor(block: Block, settings: BlockStateSettings) : this(block, settings.luminance)

View File

@ -1,18 +0,0 @@
/*
* Minosoft
* Copyright (C) 2020-2023 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.models.block.legacy
@Deprecated("legacy")
interface BakedBlockStateModel : BakedBlockModel

View File

@ -1,17 +0,0 @@
/*
* Minosoft
* Copyright (C) 2020-2023 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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.models.block.legacy
@Deprecated("legacy")
interface SingleBlockRenderable

View File

@ -16,6 +16,7 @@ package de.bixilon.minosoft.gui.rendering.models.block.state.apply
import de.bixilon.kutil.json.JsonObject
import de.bixilon.kutil.primitive.BooleanUtil.toBoolean
import de.bixilon.kutil.primitive.IntUtil.toInt
import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.data.direction.DirectionUtil.rotateY
import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.gui.rendering.models.block.BlockModel
@ -55,19 +56,19 @@ data class SingleBlockStateApply(
val positions = positions(rotatedDirection, element.from, element.to)
var uv = face.uv.toArray(direction, face.rotation)
if (y != 0 && !uvLock) {
var uv = face.uv.toArray(rotatedDirection, face.rotation)
if (direction.axis == Axes.Y && y != 0 && !uvLock) {
uv = uv.pushRight(2, if (rotatedDirection.negative) -y else y)
}
val shade = direction.shade
val shade = rotatedDirection.shade
val bakedFace = BakedFace(positions, uv, shade, face.tintIndex, face.cull, texture)
bakedFaces[direction.ordinal] += bakedFace
bakedFaces[rotatedDirection.ordinal] += bakedFace
}
}
return BakedModel(bakedFaces.compact(), emptyArray())
return BakedModel(bakedFaces.compact(), emptyArray(), null) // TODO
}
companion object {

View File

@ -13,8 +13,14 @@
package de.bixilon.minosoft.gui.rendering.models.block.state.baked
import de.bixilon.kotlinglm.vec3.Vec3
import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.data.text.formatting.color.RGBColor
import de.bixilon.minosoft.gui.rendering.system.base.MeshUtil.buffer
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rgb
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
import de.bixilon.minosoft.gui.rendering.world.preparer.cull.SolidCullSectionPreparer.Companion.SELF_LIGHT_INDEX
class BakedFace(
val positions: FloatArray,
@ -23,4 +29,38 @@ class BakedFace(
val tintIndex: Int,
val cull: Directions?,
val texture: AbstractTexture,
)
) {
private var cullIndex = cull?.ordinal ?: SELF_LIGHT_INDEX
private fun color(tint: Int): Int {
val color = Vec3(this.shade)
if (tint > 0) {
color.r *= (tint shr 16) / RGBColor.COLOR_FLOAT_DIVIDER
color.g *= ((tint shr 8) and 0xFF) / RGBColor.COLOR_FLOAT_DIVIDER
color.b *= (tint and 0xFF) / RGBColor.COLOR_FLOAT_DIVIDER
}
return color.rgb
}
fun render(offset: FloatArray, mesh: WorldMesh, light: ByteArray, tints: IntArray?) {
val tint = color(tints?.getOrNull(tintIndex) ?: 0)
val tintLight = ((light[cullIndex].toInt() shl 24) or tint).buffer()
val textureId = this.texture.shaderId.buffer()
val mesh = mesh.opaqueMesh!! // TODO: use correct mesh
for ((vertexIndex, textureIndex) in mesh.order) {
val vertexOffset = vertexIndex * 3
val uvOffset = textureIndex * 2
mesh.addVertex(
x = offset[0] + positions[vertexOffset], y = offset[1] + positions[vertexOffset + 1], z = offset[2] + positions[vertexOffset + 2],
uv = floatArrayOf(uv[uvOffset], uv[uvOffset + 1]),
texture = this.texture,
shaderTextureId = textureId,
tintLight = tintLight,
)
}
}
}

View File

@ -13,7 +13,38 @@
package de.bixilon.minosoft.gui.rendering.models.block.state.baked
import de.bixilon.kotlinglm.vec3.Vec3i
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
import de.bixilon.minosoft.data.world.positions.BlockPosition
import de.bixilon.minosoft.gui.rendering.models.block.state.render.BlockRender
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
import java.util.*
class BakedModel(
val face: Array<Array<BakedFace>>,
val faces: Array<Array<BakedFace>>,
val sizes: Array<SideSize>,
)
val particle: AbstractTexture?,
) : BlockRender {
override fun getParticleTexture(random: Random, position: Vec3i) = particle
override fun render(position: BlockPosition, mesh: WorldMesh, random: Random, state: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean {
val float = position.toVec3
val array = float.array
var rendered = true
for ((index, faces) in faces.withIndex()) {
for (face in faces) {
face.render(array, mesh, light, tints)
rendered = true
}
}
return rendered
}
}

View File

@ -11,14 +11,17 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.models.block.legacy
package de.bixilon.minosoft.gui.rendering.models.block.state.render
import de.bixilon.kotlinglm.vec3.Vec3i
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
import de.bixilon.minosoft.data.world.positions.BlockPosition
import de.bixilon.minosoft.gui.rendering.system.base.texture.texture.AbstractTexture
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
import java.util.*
@Deprecated("legacy")
interface BakedBlockModel {
interface BlockRender {
fun getParticleTexture(random: Random, position: Vec3i): AbstractTexture? = null
fun getParticleTexture(random: Random, position: Vec3i): AbstractTexture?
fun render(position: BlockPosition, mesh: WorldMesh, random: Random, state: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean
}

View File

@ -15,9 +15,9 @@ package de.bixilon.minosoft.gui.rendering.world.entities
import de.bixilon.minosoft.data.entities.block.BlockEntity
import de.bixilon.minosoft.gui.rendering.RenderContext
import de.bixilon.minosoft.gui.rendering.models.block.legacy.SingleBlockRenderable
import de.bixilon.minosoft.gui.rendering.models.block.state.render.BlockRender
interface MeshedBlockEntityRenderer<E : BlockEntity> : BlockEntityRenderer<E>, SingleBlockRenderable {
interface MeshedBlockEntityRenderer<E : BlockEntity> : BlockEntityRenderer<E>, BlockRender {
override var light: Int
get() = 0
set(value) {}

View File

@ -26,6 +26,8 @@ import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties
import de.bixilon.minosoft.data.registries.blocks.properties.BlockProperties.Companion.getFacing
import de.bixilon.minosoft.data.registries.blocks.state.BlockState
import de.bixilon.minosoft.data.registries.blocks.state.PropertyBlockState
import de.bixilon.minosoft.data.registries.blocks.types.pixlyzer.entity.sign.StandingSignBlock
import de.bixilon.minosoft.data.registries.blocks.types.pixlyzer.entity.sign.WallSignBlock
import de.bixilon.minosoft.gui.rendering.RenderContext
import de.bixilon.minosoft.gui.rendering.font.Font
import de.bixilon.minosoft.gui.rendering.font.renderer.ChatComponentRenderer
@ -35,6 +37,8 @@ import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.rotateAssign
import de.bixilon.minosoft.gui.rendering.world.entities.OnlyMeshedBlockEntityRenderer
import de.bixilon.minosoft.gui.rendering.world.mesh.SingleWorldMesh
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
import de.bixilon.minosoft.gui.rendering.world.preparer.cull.SolidCullSectionPreparer.Companion.SELF_LIGHT_INDEX
import java.util.*
class SignBlockEntityRenderer(
val sign: SignBlockEntity,
@ -48,19 +52,16 @@ class SignBlockEntityRenderer(
return rotation * 22.5f
}
/*
override fun singleRender(position: Vec3i, mesh: WorldMesh, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean {
override fun render(position: Vec3i, mesh: WorldMesh, random: Random, state: BlockState, neighbours: Array<BlockState?>, light: ByteArray, tints: IntArray?): Boolean {
val block = this.blockState.block
if (block is StandingSignBlock) {
renderStandingText(position, mesh, light[SolidCullSectionPreparer.SELF_LIGHT_INDEX].toInt())
renderStandingText(position, mesh, light[SELF_LIGHT_INDEX].toInt())
} else if (block is WallSignBlock) {
renderWallText(position, mesh, light[SolidCullSectionPreparer.SELF_LIGHT_INDEX].toInt())
renderWallText(position, mesh, light[SELF_LIGHT_INDEX].toInt())
}
return true
}
// TODO
*/
private fun renderText(position: Vec3i, rotationVector: Vec3, yRotation: Float, mesh: WorldMesh, light: Int) {
val textPosition = position.toVec3 + rotationVector

View File

@ -1,6 +1,6 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
* Copyright (C) 2020-2023 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.
*
@ -35,9 +35,9 @@ class SingleWorldMesh(context: RenderContext, initialCacheSize: Int, onDemand: B
data.add((tintColor or (light shl 24)).buffer())
}
fun addVertex(x: Float, y: Float, z: Float, uv: Vec2, texture: AbstractTexture, shaderTextureId: Float, tintLight: Float) {
fun addVertex(x: Float, y: Float, z: Float, uv: FloatArray, texture: AbstractTexture, shaderTextureId: Float, tintLight: Float) {
data.ensureSize(WorldMeshStruct.FLOATS_PER_VERTEX)
val transformedUV = texture.renderData.transformUV(uv.array)
val transformedUV = texture.renderData.transformUV(uv)
data.add(x)
data.add(y)
data.add(z)

View File

@ -34,7 +34,9 @@ import de.bixilon.minosoft.data.world.chunk.neighbours.ChunkNeighbours
import de.bixilon.minosoft.data.world.positions.BlockPosition
import de.bixilon.minosoft.data.world.positions.BlockPositionUtil.positionHash
import de.bixilon.minosoft.gui.rendering.RenderContext
import de.bixilon.minosoft.gui.rendering.models.block.state.render.BlockRender
import de.bixilon.minosoft.gui.rendering.world.entities.BlockEntityRenderer
import de.bixilon.minosoft.gui.rendering.world.entities.MeshedBlockEntityRenderer
import de.bixilon.minosoft.gui.rendering.world.entities.OnlyMeshedBlockEntityRenderer
import de.bixilon.minosoft.gui.rendering.world.mesh.WorldMesh
import de.bixilon.minosoft.gui.rendering.world.preparer.SolidSectionPreparer
@ -66,7 +68,7 @@ class SolidCullSectionPreparer(
val sectionLight = section.light
val blockEntities: MutableSet<BlockEntityRenderer<*>> = mutableSetOf()
var blockEntity: BlockEntity?
// var model: SingleBlockRenderable
var model: BlockRender
var blockState: BlockState
val position = BlockPosition()
var rendered: Boolean
@ -104,13 +106,11 @@ class SolidCullSectionPreparer(
blockEntities += blockEntityModel
mesh.addBlock(x, y, z)
}
/*
model = blockState.model ?: if (blockEntityModel is MeshedBlockEntityRenderer) {
blockEntityModel
} else {
continue
}
*/
if (y == 0) {
if (fastBedrock && blockState === bedrock) {
@ -157,18 +157,16 @@ class SolidCullSectionPreparer(
random.setSeed(0L)
}
tints = tintColorCalculator.getAverageBlockTint(chunk, neighbourChunks, blockState, x, y, z)
/*
rendered = model.singleRender(position, mesh, random, blockState, neighbourBlocks, light, tints)
rendered = model.render(position, mesh, random, blockState, neighbourBlocks, light, tints)
if (blockEntityModel is MeshedBlockEntityRenderer<*>) {
rendered = blockEntityModel.singleRender(position, mesh, random, blockState, neighbourBlocks, light, tints) || rendered
rendered = blockEntityModel.render(position, mesh, random, blockState, neighbourBlocks, light, tints) || rendered
}
if (rendered) {
mesh.addBlock(x, y, z)
}
*/
if (Thread.interrupted()) throw InterruptedException()
}
}