world-rendering: fix some transparent rendering

This commit is contained in:
Bixilon 2021-11-13 20:10:42 +01:00
parent 831fd25444
commit 95c4898f4a
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
11 changed files with 73 additions and 60 deletions

View File

@ -15,7 +15,6 @@ package de.bixilon.minosoft.data.direction
import de.bixilon.minosoft.data.Axes import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.data.registries.blocks.properties.serializer.BlockPropertiesSerializer import de.bixilon.minosoft.data.registries.blocks.properties.serializer.BlockPropertiesSerializer
import de.bixilon.minosoft.data.text.ChatColors import de.bixilon.minosoft.data.text.ChatColors
import de.bixilon.minosoft.gui.rendering.models.FaceSize
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.get import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.get
import de.bixilon.minosoft.util.KUtil import de.bixilon.minosoft.util.KUtil
import de.bixilon.minosoft.util.enum.ValuesEnum import de.bixilon.minosoft.util.enum.ValuesEnum
@ -82,11 +81,11 @@ enum class Directions(
} }
} }
fun getSize(from: Vec3, to: Vec3): FaceSize { fun getSize(from: Vec3, to: Vec3): Pair<Vec2, Vec2> {
return when (this) { return when (this) {
DOWN, UP -> FaceSize(from.xz, to.xz) DOWN, UP -> Pair(from.xz, to.xz)
NORTH, SOUTH -> FaceSize(from.xy, to.xy) NORTH, SOUTH -> Pair(from.xy, to.xy)
WEST, EAST -> FaceSize(from.yz, to.yz) WEST, EAST -> Pair(from.yz, to.yz)
} }
} }

View File

@ -14,6 +14,7 @@ import java.util.*
class CullSectionPreparer( class CullSectionPreparer(
val renderWindow: RenderWindow, val renderWindow: RenderWindow,
) : AbstractSectionPreparer { ) : AbstractSectionPreparer {
private val ambientLight = floatArrayOf(1.0f, 1.0f, 1.0f, 1.0f)
override fun prepare(chunkPosition: Vec2i, sectionHeight: Int, section: ChunkSection, neighbours: Array<ChunkSection?>): ChunkSectionMeshes { override fun prepare(chunkPosition: Vec2i, sectionHeight: Int, section: ChunkSection, neighbours: Array<ChunkSection?>): ChunkSectionMeshes {
val mesh = ChunkSectionMeshes(renderWindow, chunkPosition, sectionHeight) val mesh = ChunkSectionMeshes(renderWindow, chunkPosition, sectionHeight)
@ -69,7 +70,7 @@ class CullSectionPreparer(
val position = Vec3i(offsetX + x, offsetY + y, offsetZ + z) val position = Vec3i(offsetX + x, offsetY + y, offsetZ + z)
random.setSeed(VecUtil.generatePositionHash(position.x, position.y, position.z)) random.setSeed(VecUtil.generatePositionHash(position.x, position.y, position.z))
val rendered = model.singleRender(position, mesh, random, neighbourBlocks, 0xFF, floatArrayOf(1.0f, 1.0f, 1.0f, 1.0f)) val rendered = model.singleRender(position, mesh, random, block, neighbourBlocks, 0xFF, ambientLight)
if (rendered) { if (rendered) {
mesh.addBlock(x, y, z) mesh.addBlock(x, y, z)
} }

View File

@ -1,14 +1,18 @@
package de.bixilon.minosoft.gui.rendering.models package de.bixilon.minosoft.gui.rendering.models
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureTransparencies
object CullUtil { object CullUtil {
fun Array<FaceSize>.canCull(size: FaceSize): Boolean { fun Array<FaceProperties>.canCull(properties: FaceProperties, sameBlock: Boolean): Boolean {
for (faceSize in this) { for (property in this) {
if ( if (
faceSize.start.x <= size.start.x property.sizeStart.x <= properties.sizeStart.x
&& faceSize.start.y <= size.start.y && property.sizeStart.y <= properties.sizeStart.y
&& faceSize.end.x >= size.end.x && property.sizeEnd.x >= properties.sizeEnd.x
&& faceSize.end.y >= size.end.y && property.sizeEnd.y >= properties.sizeEnd.y
&& !((properties.transparency == TextureTransparencies.OPAQUE && property.transparency != TextureTransparencies.OPAQUE)
|| (properties.transparency != TextureTransparencies.OPAQUE && property.transparency == properties.transparency && !sameBlock))
) { ) {
return true return true
} }

View File

@ -13,9 +13,11 @@
package de.bixilon.minosoft.gui.rendering.models package de.bixilon.minosoft.gui.rendering.models
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureTransparencies
import glm_.vec2.Vec2 import glm_.vec2.Vec2
class FaceSize( interface FaceProperties {
val start: Vec2, val sizeStart: Vec2
val end: Vec2, val sizeEnd: Vec2
) val transparency: TextureTransparencies
}

View File

@ -17,17 +17,17 @@ import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.data.registries.blocks.BlockState import de.bixilon.minosoft.data.registries.blocks.BlockState
import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.data.world.light.LightAccessor
import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMeshes import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMeshes
import de.bixilon.minosoft.gui.rendering.models.FaceSize import de.bixilon.minosoft.gui.rendering.models.FaceProperties
import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel
import glm_.vec3.Vec3i import glm_.vec3.Vec3i
import java.util.* import java.util.*
class MultipartBakedModel( class MultipartBakedModel(
val models: Array<BakedBlockModel>, val models: Array<BakedBlockModel>,
val sizes: Array<Array<FaceSize>>, val sizes: Array<Array<FaceProperties>>,
) : BakedBlockModel { ) : BakedBlockModel {
override fun getSize(random: Random, direction: Directions): Array<FaceSize> { override fun getTouchingFaceProperties(random: Random, direction: Directions): Array<FaceProperties> {
return sizes[direction.ordinal] return sizes[direction.ordinal]
} }
@ -35,10 +35,10 @@ class MultipartBakedModel(
return 0xFF return 0xFF
} }
override fun singleRender(position: Vec3i, mesh: ChunkSectionMeshes, random: Random, neighbours: Array<BlockState?>, light: Int, ambientLight: FloatArray): Boolean { override fun singleRender(position: Vec3i, mesh: ChunkSectionMeshes, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: Int, ambientLight: FloatArray): Boolean {
var rendered = false var rendered = false
for (model in models) { for (model in models) {
if (model.singleRender(position, mesh, random, neighbours, light, ambientLight) && !rendered) { if (model.singleRender(position, mesh, random, blockState, neighbours, light, ambientLight) && !rendered) {
rendered = true rendered = true
} }
} }

View File

@ -17,7 +17,7 @@ import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.data.registries.blocks.BlockState import de.bixilon.minosoft.data.registries.blocks.BlockState
import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.data.world.light.LightAccessor
import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMeshes import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMeshes
import de.bixilon.minosoft.gui.rendering.models.FaceSize import de.bixilon.minosoft.gui.rendering.models.FaceProperties
import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel
import glm_.vec3.Vec3i import glm_.vec3.Vec3i
import java.util.* import java.util.*
@ -37,8 +37,8 @@ class WeightedBakedModel(
this.totalWeight = totalWeight this.totalWeight = totalWeight
} }
override fun getSize(random: Random, direction: Directions): Array<FaceSize> { override fun getTouchingFaceProperties(random: Random, direction: Directions): Array<FaceProperties> {
return getModel(random).getSize(random, direction) return getModel(random).getTouchingFaceProperties(random, direction)
} }
private fun getModel(random: Random): BakedBlockModel { private fun getModel(random: Random): BakedBlockModel {
@ -60,8 +60,8 @@ class WeightedBakedModel(
return getModel(random).getLight(position, random, side, lightAccessor) return getModel(random).getLight(position, random, side, lightAccessor)
} }
override fun singleRender(position: Vec3i, mesh: ChunkSectionMeshes, random: Random, neighbours: Array<BlockState?>, light: Int, ambientLight: FloatArray): Boolean { override fun singleRender(position: Vec3i, mesh: ChunkSectionMeshes, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: Int, ambientLight: FloatArray): Boolean {
return getModel(random).singleRender(position, mesh, random, neighbours, light, ambientLight) return getModel(random).singleRender(position, mesh, random, blockState, neighbours, light, ambientLight)
} }
} }

View File

@ -17,17 +17,17 @@ import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.data.registries.blocks.BlockState import de.bixilon.minosoft.data.registries.blocks.BlockState
import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.data.world.light.LightAccessor
import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMeshes import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMeshes
import de.bixilon.minosoft.gui.rendering.models.FaceSize import de.bixilon.minosoft.gui.rendering.models.FaceProperties
import de.bixilon.minosoft.gui.rendering.models.baked.BakedModel import de.bixilon.minosoft.gui.rendering.models.baked.BakedModel
import glm_.vec3.Vec3i import glm_.vec3.Vec3i
import java.util.* import java.util.*
interface BakedBlockModel : BakedModel { interface BakedBlockModel : BakedModel {
fun getSize(random: Random, direction: Directions): Array<FaceSize> fun getTouchingFaceProperties(random: Random, direction: Directions): Array<FaceProperties>
// ToDo: Tint // ToDo: Tint
fun singleRender(position: Vec3i, mesh: ChunkSectionMeshes, random: Random, neighbours: Array<BlockState?>, light: Int, ambientLight: FloatArray): Boolean fun singleRender(position: Vec3i, mesh: ChunkSectionMeshes, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: Int, ambientLight: FloatArray): Boolean
// ToDo: Get ambient light // ToDo: Get ambient light
fun getLight(position: Vec3i, random: Random, side: Directions, lightAccessor: LightAccessor): Int fun getLight(position: Vec3i, random: Random, side: Directions, lightAccessor: LightAccessor): Int

View File

@ -19,35 +19,36 @@ import de.bixilon.minosoft.data.world.light.LightAccessor
import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh
import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMeshes import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMeshes
import de.bixilon.minosoft.gui.rendering.models.CullUtil.canCull import de.bixilon.minosoft.gui.rendering.models.CullUtil.canCull
import de.bixilon.minosoft.gui.rendering.models.FaceSize import de.bixilon.minosoft.gui.rendering.models.FaceProperties
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.toVec3 import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3iUtil.toVec3
import glm_.vec3.Vec3i import glm_.vec3.Vec3i
import java.util.* import java.util.*
class BakedBlockStateModel( class BakedBlockStateModel(
val faces: Array<Array<BakedFace>>, private val faces: Array<Array<BakedFace>>,
val sizes: Array<Array<FaceSize>>, private val touchingFaceProperties: Array<Array<FaceProperties>>,
) : BakedBlockModel, GreedyBakedBlockModel { // ToDo: Greedy meshable ) : BakedBlockModel, GreedyBakedBlockModel { // ToDo: Greedy meshable
override val canGreedyMesh: Boolean = true override val canGreedyMesh: Boolean = true
override val greedyMeshableFaces: BooleanArray = booleanArrayOf(true, false, true, true, true, true) override val greedyMeshableFaces: BooleanArray = booleanArrayOf(true, false, true, true, true, true)
override fun getSize(random: Random, direction: Directions): Array<FaceSize> { override fun getTouchingFaceProperties(random: Random, direction: Directions): Array<FaceProperties> {
return sizes[direction.ordinal] return touchingFaceProperties[direction.ordinal]
} }
override fun singleRender(position: Vec3i, mesh: ChunkSectionMeshes, random: Random, neighbours: Array<BlockState?>, light: Int, ambientLight: FloatArray): Boolean { override fun singleRender(position: Vec3i, mesh: ChunkSectionMeshes, random: Random, blockState: BlockState, neighbours: Array<BlockState?>, light: Int, ambientLight: FloatArray): Boolean {
val floatPosition = position.toVec3().array val floatPosition = position.toVec3().array
var rendered = false var rendered = false
for ((index, faces) in faces.withIndex()) { for ((index, faces) in faces.withIndex()) {
val direction = Directions.VALUES[index] val direction = Directions.VALUES[index]
val neighbour = neighbours[index]?.model val neighbour = neighbours[index]
var neighbourSize: Array<FaceSize>? = null val neighboursModel = neighbour?.model
if (neighbour != null) { var neighbourProperties: Array<FaceProperties>? = null
if (neighboursModel != null) {
random.setSeed(0L) // ToDo random.setSeed(0L) // ToDo
neighbourSize = neighbour.getSize(random, direction.inverted) neighbourProperties = neighboursModel.getTouchingFaceProperties(random, direction.inverted)
} }
for (face in faces) { for (face in faces) {
if (face.touching && neighbourSize != null && neighbourSize.isNotEmpty() && neighbourSize.canCull(face.faceSize)) { if (face.touching && neighbourProperties != null && neighbourProperties.isNotEmpty() && neighbourProperties.canCull(face, blockState == neighbour)) {
continue continue
} }
face.singleRender(floatPosition, mesh, light, ambientLight) face.singleRender(floatPosition, mesh, light, ambientLight)

View File

@ -17,7 +17,7 @@ import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMesh
import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMeshes import de.bixilon.minosoft.gui.rendering.block.mesh.ChunkSectionMeshes
import de.bixilon.minosoft.gui.rendering.models.FaceSize import de.bixilon.minosoft.gui.rendering.models.FaceProperties
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureTransparencies import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureTransparencies
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.util.mesh.Mesh import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh
@ -27,7 +27,8 @@ import glm_.vec2.Vec2
import glm_.vec3.Vec3 import glm_.vec3.Vec3
class BakedFace( class BakedFace(
val faceSize: FaceSize, override val sizeStart: Vec2,
override val sizeEnd: Vec2,
val positions: Array<Vec3>, val positions: Array<Vec3>,
val uv: Array<Vec2>, val uv: Array<Vec2>,
val shade: Float, val shade: Float,
@ -35,7 +36,10 @@ class BakedFace(
val cullFace: Directions?, val cullFace: Directions?,
val texture: AbstractTexture, val texture: AbstractTexture,
val touching: Boolean, val touching: Boolean,
) { ) : FaceProperties {
override val transparency: TextureTransparencies
get() = texture.transparency // ToDo
fun singleRender(position: FloatArray, mesh: ChunkSectionMeshes, light: Int, ambientLight: FloatArray) { fun singleRender(position: FloatArray, mesh: ChunkSectionMeshes, light: Int, ambientLight: FloatArray) {
val meshToUse = when (texture.transparency) { val meshToUse = when (texture.transparency) {
TextureTransparencies.OPAQUE -> mesh.opaqueMesh TextureTransparencies.OPAQUE -> mesh.opaqueMesh

View File

@ -17,7 +17,7 @@ import de.bixilon.minosoft.data.Axes
import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.data.registries.ResourceLocation import de.bixilon.minosoft.data.registries.ResourceLocation
import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.models.FaceSize import de.bixilon.minosoft.gui.rendering.models.FaceProperties
import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel
import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockStateModel import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockStateModel
import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedFace import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedFace
@ -84,7 +84,7 @@ data class UnbakedBlockStateModel(
val faces: Array<MutableList<BakedFace>> = Array(Directions.SIZE) { mutableListOf() } val faces: Array<MutableList<BakedFace>> = Array(Directions.SIZE) { mutableListOf() }
val sizes: Array<MutableList<FaceSize>> = Array(Directions.SIZE) { mutableListOf() } val touchingFaceProperties: Array<MutableList<FaceProperties>> = Array(Directions.SIZE) { mutableListOf() }
for (element in model.elements) { for (element in model.elements) {
val rescale = element.rotation?.rescale ?: false val rescale = element.rotation?.rescale ?: false
@ -129,11 +129,8 @@ data class UnbakedBlockStateModel(
} }
} }
val size = face.direction.getSize(element.from, element.to) val (sizeStart, sizeEnd) = face.direction.getSize(element.from, element.to)
val touching = (if (face.direction.negative) element.from[face.direction.axis] else element.to[face.direction.axis] - 1.0f) == 0.0f val touching = (if (face.direction.negative) element.from[face.direction.axis] else element.to[face.direction.axis] - 1.0f) == 0.0f
if (touching) {
sizes[direction.ordinal] += size
}
var shade = 1.0f var shade = 1.0f
if (element.shade) { if (element.shade) {
shade = when (direction) { shade = when (direction) {
@ -143,8 +140,9 @@ data class UnbakedBlockStateModel(
Directions.WEST, Directions.EAST -> 0.6f Directions.WEST, Directions.EAST -> 0.6f
} }
} }
faces[direction.ordinal] += BakedFace( val bakedFace = BakedFace(
faceSize = size, sizeStart = sizeStart,
sizeEnd = sizeEnd,
positions = positions, positions = positions,
uv = texturePositions, uv = texturePositions,
shade = shade, shade = shade,
@ -153,21 +151,25 @@ data class UnbakedBlockStateModel(
texture = texture, texture = texture,
touching = touching, touching = touching,
) )
faces[direction.ordinal] += bakedFace
if (touching) {
touchingFaceProperties[direction.ordinal] += bakedFace
}
} }
} }
val finalFaces: Array<Array<BakedFace>?> = arrayOfNulls(faces.size) val finalFaces: Array<Array<BakedFace>?> = arrayOfNulls(faces.size)
for ((index, faceArray) in faces.withIndex()) { for ((index, faceArray) in faces.withIndex()) {
finalFaces[index] = faceArray.toTypedArray() finalFaces[index] = faceArray.toTypedArray()
} }
val finalSizes: Array<Array<FaceSize>?> = arrayOfNulls(faces.size)
for ((index, sizeArray) in sizes.withIndex()) { val finalTouchingProperties: Array<Array<FaceProperties>?> = arrayOfNulls(faces.size)
finalSizes[index] = sizeArray.toTypedArray() for ((index, sizeArray) in touchingFaceProperties.withIndex()) {
finalTouchingProperties[index] = sizeArray.toTypedArray()
} }
val baked = BakedBlockStateModel(finalFaces.unsafeCast(), finalSizes.unsafeCast()) val baked = BakedBlockStateModel(finalFaces.unsafeCast(), finalTouchingProperties.unsafeCast())
this.baked = baked this.baked = baked
return baked return baked
} }

View File

@ -2,7 +2,7 @@ package de.bixilon.minosoft.gui.rendering.models.unbaked.block
import de.bixilon.minosoft.data.direction.Directions import de.bixilon.minosoft.data.direction.Directions
import de.bixilon.minosoft.gui.rendering.RenderWindow import de.bixilon.minosoft.gui.rendering.RenderWindow
import de.bixilon.minosoft.gui.rendering.models.FaceSize import de.bixilon.minosoft.gui.rendering.models.FaceProperties
import de.bixilon.minosoft.gui.rendering.models.baked.BakedModel import de.bixilon.minosoft.gui.rendering.models.baked.BakedModel
import de.bixilon.minosoft.gui.rendering.models.baked.MultipartBakedModel import de.bixilon.minosoft.gui.rendering.models.baked.MultipartBakedModel
import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel
@ -16,16 +16,16 @@ class UnbakedMultipartModel(
override fun bake(renderWindow: RenderWindow): BakedModel { override fun bake(renderWindow: RenderWindow): BakedModel {
val baked: Array<BakedBlockModel?> = arrayOfNulls(this.models.size) val baked: Array<BakedBlockModel?> = arrayOfNulls(this.models.size)
val sizes: Array<MutableList<FaceSize>> = Array(Directions.SIZE) { mutableListOf() } val sizes: Array<MutableList<FaceProperties>> = Array(Directions.SIZE) { mutableListOf() }
for ((index, model) in this.models.withIndex()) { for ((index, model) in this.models.withIndex()) {
val bakedModel = model.bake(renderWindow) val bakedModel = model.bake(renderWindow)
for (direction in Directions.VALUES) { for (direction in Directions.VALUES) {
sizes[direction.ordinal] += bakedModel.getSize(RANDOM, direction) // There is no random here! sizes[direction.ordinal] += bakedModel.getTouchingFaceProperties(RANDOM, direction) // There is no random here!
} }
baked[index] = bakedModel baked[index] = bakedModel
} }
val finalFaces: Array<Array<FaceSize>?> = arrayOfNulls(Directions.SIZE) val finalFaces: Array<Array<FaceProperties>?> = arrayOfNulls(Directions.SIZE)
for (index in 0 until Directions.SIZE) { for (index in 0 until Directions.SIZE) {
finalFaces[index] = sizes[index].toTypedArray() finalFaces[index] = sizes[index].toTypedArray()
} }