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.registries.blocks.properties.serializer.BlockPropertiesSerializer
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.util.KUtil
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) {
DOWN, UP -> FaceSize(from.xz, to.xz)
NORTH, SOUTH -> FaceSize(from.xy, to.xy)
WEST, EAST -> FaceSize(from.yz, to.yz)
DOWN, UP -> Pair(from.xz, to.xz)
NORTH, SOUTH -> Pair(from.xy, to.xy)
WEST, EAST -> Pair(from.yz, to.yz)
}
}

View File

@ -14,6 +14,7 @@ import java.util.*
class CullSectionPreparer(
val renderWindow: RenderWindow,
) : 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 {
val mesh = ChunkSectionMeshes(renderWindow, chunkPosition, sectionHeight)
@ -69,7 +70,7 @@ class CullSectionPreparer(
val position = Vec3i(offsetX + x, offsetY + y, offsetZ + 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) {
mesh.addBlock(x, y, z)
}

View File

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

View File

@ -13,9 +13,11 @@
package de.bixilon.minosoft.gui.rendering.models
import de.bixilon.minosoft.gui.rendering.system.base.texture.TextureTransparencies
import glm_.vec2.Vec2
class FaceSize(
val start: Vec2,
val end: Vec2,
)
interface FaceProperties {
val sizeStart: 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.world.light.LightAccessor
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 glm_.vec3.Vec3i
import java.util.*
class MultipartBakedModel(
val models: Array<BakedBlockModel>,
val sizes: Array<Array<FaceSize>>,
val sizes: Array<Array<FaceProperties>>,
) : BakedBlockModel {
override fun getSize(random: Random, direction: Directions): Array<FaceSize> {
override fun getTouchingFaceProperties(random: Random, direction: Directions): Array<FaceProperties> {
return sizes[direction.ordinal]
}
@ -35,10 +35,10 @@ class MultipartBakedModel(
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
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
}
}

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.world.light.LightAccessor
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 glm_.vec3.Vec3i
import java.util.*
@ -37,8 +37,8 @@ class WeightedBakedModel(
this.totalWeight = totalWeight
}
override fun getSize(random: Random, direction: Directions): Array<FaceSize> {
return getModel(random).getSize(random, direction)
override fun getTouchingFaceProperties(random: Random, direction: Directions): Array<FaceProperties> {
return getModel(random).getTouchingFaceProperties(random, direction)
}
private fun getModel(random: Random): BakedBlockModel {
@ -60,8 +60,8 @@ class WeightedBakedModel(
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 {
return getModel(random).singleRender(position, mesh, random, neighbours, light, ambientLight)
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, 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.world.light.LightAccessor
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 glm_.vec3.Vec3i
import java.util.*
interface BakedBlockModel : BakedModel {
fun getSize(random: Random, direction: Directions): Array<FaceSize>
fun getTouchingFaceProperties(random: Random, direction: Directions): Array<FaceProperties>
// 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
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.ChunkSectionMeshes
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 glm_.vec3.Vec3i
import java.util.*
class BakedBlockStateModel(
val faces: Array<Array<BakedFace>>,
val sizes: Array<Array<FaceSize>>,
private val faces: Array<Array<BakedFace>>,
private val touchingFaceProperties: Array<Array<FaceProperties>>,
) : BakedBlockModel, GreedyBakedBlockModel { // ToDo: Greedy meshable
override val canGreedyMesh: Boolean = true
override val greedyMeshableFaces: BooleanArray = booleanArrayOf(true, false, true, true, true, true)
override fun getSize(random: Random, direction: Directions): Array<FaceSize> {
return sizes[direction.ordinal]
override fun getTouchingFaceProperties(random: Random, direction: Directions): Array<FaceProperties> {
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
var rendered = false
for ((index, faces) in faces.withIndex()) {
val direction = Directions.VALUES[index]
val neighbour = neighbours[index]?.model
var neighbourSize: Array<FaceSize>? = null
if (neighbour != null) {
val neighbour = neighbours[index]
val neighboursModel = neighbour?.model
var neighbourProperties: Array<FaceProperties>? = null
if (neighboursModel != null) {
random.setSeed(0L) // ToDo
neighbourSize = neighbour.getSize(random, direction.inverted)
neighbourProperties = neighboursModel.getTouchingFaceProperties(random, direction.inverted)
}
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
}
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.gui.rendering.block.mesh.ChunkSectionMesh
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.texture.AbstractTexture
import de.bixilon.minosoft.gui.rendering.util.mesh.Mesh
@ -27,7 +27,8 @@ import glm_.vec2.Vec2
import glm_.vec3.Vec3
class BakedFace(
val faceSize: FaceSize,
override val sizeStart: Vec2,
override val sizeEnd: Vec2,
val positions: Array<Vec3>,
val uv: Array<Vec2>,
val shade: Float,
@ -35,7 +36,10 @@ class BakedFace(
val cullFace: Directions?,
val texture: AbstractTexture,
val touching: Boolean,
) {
) : FaceProperties {
override val transparency: TextureTransparencies
get() = texture.transparency // ToDo
fun singleRender(position: FloatArray, mesh: ChunkSectionMeshes, light: Int, ambientLight: FloatArray) {
val meshToUse = when (texture.transparency) {
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.registries.ResourceLocation
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.BakedBlockStateModel
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 sizes: Array<MutableList<FaceSize>> = Array(Directions.SIZE) { mutableListOf() }
val touchingFaceProperties: Array<MutableList<FaceProperties>> = Array(Directions.SIZE) { mutableListOf() }
for (element in model.elements) {
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
if (touching) {
sizes[direction.ordinal] += size
}
var shade = 1.0f
if (element.shade) {
shade = when (direction) {
@ -143,8 +140,9 @@ data class UnbakedBlockStateModel(
Directions.WEST, Directions.EAST -> 0.6f
}
}
faces[direction.ordinal] += BakedFace(
faceSize = size,
val bakedFace = BakedFace(
sizeStart = sizeStart,
sizeEnd = sizeEnd,
positions = positions,
uv = texturePositions,
shade = shade,
@ -153,21 +151,25 @@ data class UnbakedBlockStateModel(
texture = texture,
touching = touching,
)
faces[direction.ordinal] += bakedFace
if (touching) {
touchingFaceProperties[direction.ordinal] += bakedFace
}
}
}
val finalFaces: Array<Array<BakedFace>?> = arrayOfNulls(faces.size)
for ((index, faceArray) in faces.withIndex()) {
finalFaces[index] = faceArray.toTypedArray()
}
val finalSizes: Array<Array<FaceSize>?> = arrayOfNulls(faces.size)
for ((index, sizeArray) in sizes.withIndex()) {
finalSizes[index] = sizeArray.toTypedArray()
val finalTouchingProperties: Array<Array<FaceProperties>?> = arrayOfNulls(faces.size)
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
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.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.MultipartBakedModel
import de.bixilon.minosoft.gui.rendering.models.baked.block.BakedBlockModel
@ -16,16 +16,16 @@ class UnbakedMultipartModel(
override fun bake(renderWindow: RenderWindow): BakedModel {
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()) {
val bakedModel = model.bake(renderWindow)
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
}
val finalFaces: Array<Array<FaceSize>?> = arrayOfNulls(Directions.SIZE)
val finalFaces: Array<Array<FaceProperties>?> = arrayOfNulls(Directions.SIZE)
for (index in 0 until Directions.SIZE) {
finalFaces[index] = sizes[index].toTypedArray()
}