rendering: improve cullfacing (2)

This commit is contained in:
Bixilon 2021-03-27 01:04:43 +01:00
parent 6cc781a724
commit bdfe1345fa
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
8 changed files with 50 additions and 65 deletions

View File

@ -12,7 +12,7 @@
*/ */
package de.bixilon.minosoft.data package de.bixilon.minosoft.data
import de.bixilon.minosoft.gui.rendering.chunk.models.FaceBorderSize import de.bixilon.minosoft.gui.rendering.chunk.models.FaceSize
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelElement import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelElement
import glm_.vec2.Vec2i import glm_.vec2.Vec2i
import glm_.vec3.Vec3 import glm_.vec3.Vec3
@ -27,8 +27,6 @@ enum class Directions(val directionVector: Vec3i) {
EAST(Vec3i(1, 0, 0)); EAST(Vec3i(1, 0, 0));
val floatDirectionVector = Vec3(directionVector) val floatDirectionVector = Vec3(directionVector)
val blockResolutionVector = directionVector * BlockModelElement.BLOCK_RESOLUTION
val blockResolutionVectorFloat = Vec3(blockResolutionVector)
lateinit var inverse: Directions lateinit var inverse: Directions
private set private set
@ -53,54 +51,43 @@ enum class Directions(val directionVector: Vec3i) {
/** /**
* @return the size of the face in this direction. null if the face is not touching the border (determinated by the block resolution) * @return the size of the face in this direction. null if the face is not touching the border (determinated by the block resolution)
*/ */
fun getFaceBorderSizes(start: Vec3, end: Vec3): FaceBorderSize? { fun getFaceBorderSizes(start: Vec3, end: Vec3): FaceSize? {
// check if face is touching the border of a block // check if face is touching the border of a block
if (!isBlockResolutionBorder(start, end)) {
return null
}
return getFaceSize(start, end)
}
fun getFaceSize(start: Vec3, end: Vec3): FaceSize {
return when (this) { return when (this) {
DOWN -> { DOWN, UP -> {
if (start.y != 0.0f && end.y != 0.0f) { FaceSize(Vec2i(start.x, start.z), Vec2i(end.x, end.z))
null
} else {
FaceBorderSize(Vec2i(start.x, start.z), Vec2i(end.x, end.z))
}
} }
UP -> { NORTH, SOUTH -> {
if (start.y != BlockModelElement.BLOCK_RESOLUTION_FLOAT && end.y != BlockModelElement.BLOCK_RESOLUTION_FLOAT) { FaceSize(Vec2i(start.x, start.y), Vec2i(end.x, end.y))
null
} else {
FaceBorderSize(Vec2i(start.x, start.z), Vec2i(end.x, end.z))
}
} }
NORTH -> { EAST, WEST -> {
if (start.z != 0.0f && end.z != 0.0f) { FaceSize(Vec2i(start.y, start.z), Vec2i(end.y, end.z))
null
} else {
FaceBorderSize(Vec2i(start.x, start.y), Vec2i(end.x, end.y))
}
}
SOUTH -> {
if (start.z != BlockModelElement.BLOCK_RESOLUTION_FLOAT && end.z != BlockModelElement.BLOCK_RESOLUTION_FLOAT) {
null
} else {
FaceBorderSize(Vec2i(start.x, start.y), Vec2i(end.x, end.y))
}
}
WEST -> {
if (start.x != 0.0f && end.x != 0.0f) {
null
} else {
FaceBorderSize(Vec2i(start.y, start.z), Vec2i(end.y, end.z))
}
}
EAST -> {
if (start.x != BlockModelElement.BLOCK_RESOLUTION_FLOAT && end.x != BlockModelElement.BLOCK_RESOLUTION_FLOAT) {
null
} else {
FaceBorderSize(Vec2i(start.y, start.z), Vec2i(end.y, end.z))
}
} }
} }
} }
private fun isBlockResolutionBorder(start: Vec3, end: Vec3): Boolean {
return isCoordinateBorder(directionVector.x, start.x, end.x) || isCoordinateBorder(directionVector.y, start.y, end.y) || isCoordinateBorder(directionVector.z, start.z, end.z)
}
private fun isCoordinateBorder(directionValue: Int, start: Float, end: Float): Boolean {
if (directionValue == 1) {
return start == BlockModelElement.BLOCK_RESOLUTION_FLOAT || end == BlockModelElement.BLOCK_RESOLUTION_FLOAT
}
if (directionValue == -1) {
return start == 0.0f || end == 0.0f
}
return false
}
companion object { companion object {
val DIRECTIONS = values() val DIRECTIONS = values()

View File

@ -15,7 +15,7 @@ package de.bixilon.minosoft.gui.rendering.chunk.models
import glm_.vec2.Vec2i import glm_.vec2.Vec2i
data class FaceBorderSize( data class FaceSize(
val start: Vec2i = Vec2i(0, 0), val start: Vec2i = Vec2i(0, 0),
val end: Vec2i = Vec2i(16, 16), val end: Vec2i = Vec2i(16, 16),
) )

View File

@ -13,10 +13,10 @@
package de.bixilon.minosoft.gui.rendering.chunk.models.loading package de.bixilon.minosoft.gui.rendering.chunk.models.loading
import com.google.gson.JsonArray
import com.google.gson.JsonObject import com.google.gson.JsonObject
import de.bixilon.minosoft.data.Directions import de.bixilon.minosoft.data.Directions
import de.bixilon.minosoft.gui.rendering.util.VecUtil import de.bixilon.minosoft.gui.rendering.util.VecUtil
import de.bixilon.minosoft.gui.rendering.util.VecUtil.readUV
import glm_.Java.Companion.glm import glm_.Java.Companion.glm
import glm_.vec2.Vec2 import glm_.vec2.Vec2
import glm_.vec3.Vec3 import glm_.vec3.Vec3
@ -44,9 +44,7 @@ class BlockModelFace {
} }
private fun calculateTexturePositions(data: JsonObject?, from: Vec3, to: Vec3, direction: Directions): MutableList<Vec2> { private fun calculateTexturePositions(data: JsonObject?, from: Vec3, to: Vec3, direction: Directions): MutableList<Vec2> {
val (textureTopLeft: Vec2, textureBottomRight: Vec2) = data?.get("uv")?.asJsonArray?.let { val (textureTopLeft: Vec2, textureBottomRight: Vec2) = data?.get("uv")?.asJsonArray?.readUV() ?: getTexturePositionsFromRegion(from, to, direction)
readUV(it)
} ?: getTexturePositionsFromRegion(from, to, direction)
return mutableListOf( return mutableListOf(
uvToFloat(Vec2(textureTopLeft.x, textureTopLeft.y)), uvToFloat(Vec2(textureTopLeft.x, textureTopLeft.y)),
uvToFloat(Vec2(textureTopLeft.x, textureBottomRight.y)), uvToFloat(Vec2(textureTopLeft.x, textureBottomRight.y)),
@ -55,15 +53,12 @@ class BlockModelFace {
) )
} }
private fun readUV(data: JsonArray): Pair<Vec2, Vec2> {
return Pair(Vec2(data[0].asFloat, data[3].asFloat), Vec2(data[2].asFloat, data[1].asFloat))
}
private fun getTexturePositionsFromRegion(from: Vec3, to: Vec3, direction: Directions): Pair<Vec2, Vec2> { private fun getTexturePositionsFromRegion(from: Vec3, to: Vec3, direction: Directions): Pair<Vec2, Vec2> {
// ToDo: Remove the duplicated code in Directions
return when (direction) { return when (direction) {
Directions.EAST, Directions.WEST -> Pair(Vec2(from.z.toInt(), to.y.toInt()), Vec2(to.z.toInt(), from.y.toInt()))
Directions.UP, Directions.DOWN -> Pair(Vec2(from.x.toInt(), to.z.toInt()), Vec2(to.x.toInt(), from.z.toInt())) Directions.UP, Directions.DOWN -> Pair(Vec2(from.x.toInt(), to.z.toInt()), Vec2(to.x.toInt(), from.z.toInt()))
Directions.NORTH, Directions.SOUTH -> Pair(Vec2(from.x.toInt(), to.y.toInt()), Vec2(to.x.toInt(), from.y.toInt())) Directions.NORTH, Directions.SOUTH -> Pair(Vec2(from.x.toInt(), to.y.toInt()), Vec2(to.x.toInt(), from.y.toInt()))
Directions.EAST, Directions.WEST -> Pair(Vec2(from.z.toInt(), to.y.toInt()), Vec2(to.z.toInt(), from.y.toInt()))
} }
} }

View File

@ -6,11 +6,11 @@ import de.bixilon.minosoft.data.world.BlockPosition
import de.bixilon.minosoft.data.world.World import de.bixilon.minosoft.data.world.World
import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.data.world.light.LightAccessor
import de.bixilon.minosoft.gui.rendering.chunk.ChunkMeshCollection import de.bixilon.minosoft.gui.rendering.chunk.ChunkMeshCollection
import de.bixilon.minosoft.gui.rendering.chunk.models.FaceBorderSize import de.bixilon.minosoft.gui.rendering.chunk.models.FaceSize
import de.bixilon.minosoft.gui.rendering.textures.Texture import de.bixilon.minosoft.gui.rendering.textures.Texture
interface BlockRenderInterface { interface BlockRenderInterface {
val faceBorderSizes: Array<Array<FaceBorderSize>?> // direction indexed val faceBorderSizes: Array<Array<FaceSize>?> // direction indexed
val transparentFaces: BooleanArray val transparentFaces: BooleanArray
fun render(blockState: BlockState, lightAccessor: LightAccessor, tintColor: RGBColor?, position: BlockPosition, meshCollection: ChunkMeshCollection, neighbourBlocks: Array<BlockState?>, world: World) fun render(blockState: BlockState, lightAccessor: LightAccessor, tintColor: RGBColor?, position: BlockPosition, meshCollection: ChunkMeshCollection, neighbourBlocks: Array<BlockState?>, world: World)

View File

@ -23,7 +23,7 @@ import de.bixilon.minosoft.data.world.World
import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.data.world.light.LightAccessor
import de.bixilon.minosoft.gui.rendering.RenderConstants import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.chunk.ChunkMeshCollection import de.bixilon.minosoft.gui.rendering.chunk.ChunkMeshCollection
import de.bixilon.minosoft.gui.rendering.chunk.models.FaceBorderSize import de.bixilon.minosoft.gui.rendering.chunk.models.FaceSize
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModel import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModel
import de.bixilon.minosoft.gui.rendering.textures.Texture import de.bixilon.minosoft.gui.rendering.textures.Texture
import de.bixilon.minosoft.gui.rendering.textures.TextureTransparencies import de.bixilon.minosoft.gui.rendering.textures.TextureTransparencies
@ -33,7 +33,7 @@ class BlockRenderer : BlockRenderInterface {
val textures: MutableMap<String, String> = mutableMapOf() val textures: MutableMap<String, String> = mutableMapOf()
private val elements: MutableSet<ElementRenderer> = mutableSetOf() private val elements: MutableSet<ElementRenderer> = mutableSetOf()
private val textureMapping: MutableMap<String, Texture> = mutableMapOf() private val textureMapping: MutableMap<String, Texture> = mutableMapOf()
override val faceBorderSizes: Array<Array<FaceBorderSize>?> = arrayOfNulls(Directions.DIRECTIONS.size) override val faceBorderSizes: Array<Array<FaceSize>?> = arrayOfNulls(Directions.DIRECTIONS.size)
override val transparentFaces: BooleanArray = BooleanArray(Directions.DIRECTIONS.size) override val transparentFaces: BooleanArray = BooleanArray(Directions.DIRECTIONS.size)
constructor(data: JsonObject, parent: BlockModel) { constructor(data: JsonObject, parent: BlockModel) {
@ -64,7 +64,7 @@ class BlockRenderer : BlockRenderInterface {
for (direction in Directions.DIRECTIONS) { for (direction in Directions.DIRECTIONS) {
var directionIsCullFace: Boolean? = null var directionIsCullFace: Boolean? = null
var directionIsNotTransparent: Boolean? = null var directionIsNotTransparent: Boolean? = null
var faceBorderSites: MutableList<FaceBorderSize> = mutableListOf() var faceBorderSites: MutableList<FaceSize> = mutableListOf()
for (element in elements) { for (element in elements) {
if (element.isCullFace(direction)) { if (element.isCullFace(direction)) {
directionIsCullFace = true directionIsCullFace = true
@ -98,11 +98,9 @@ class BlockRenderer : BlockRenderInterface {
return return
} }
for (direction in Directions.DIRECTIONS) { for (direction in Directions.DIRECTIONS) {
val cullFace = cullFaces[direction.ordinal] != null
val invertedDirection = direction.inverse val invertedDirection = direction.inverse
var isNeighbourTransparent = false var isNeighbourTransparent = false
var neighbourFaceSize: Array<FaceBorderSize>? = null var neighbourFaceSize: Array<FaceSize>? = null
neighbourBlocks[direction.ordinal]?.getBlockRenderer(position + direction)?.let { neighbourBlocks[direction.ordinal]?.getBlockRenderer(position + direction)?.let {
if (it.transparentFaces[invertedDirection.ordinal]) { if (it.transparentFaces[invertedDirection.ordinal]) {
isNeighbourTransparent = true isNeighbourTransparent = true
@ -110,6 +108,8 @@ class BlockRenderer : BlockRenderInterface {
neighbourFaceSize = it.faceBorderSizes[invertedDirection.ordinal] neighbourFaceSize = it.faceBorderSizes[invertedDirection.ordinal]
} }
// ToDo: Should we preserve the cullface attribute? It seems to has no point here.
for (element in elements) { for (element in elements) {
var drawElementFace = true var drawElementFace = true

View File

@ -22,7 +22,7 @@ import de.bixilon.minosoft.data.world.BlockPosition
import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.data.world.light.LightAccessor
import de.bixilon.minosoft.gui.rendering.chunk.ChunkMeshCollection import de.bixilon.minosoft.gui.rendering.chunk.ChunkMeshCollection
import de.bixilon.minosoft.gui.rendering.chunk.SectionArrayMesh import de.bixilon.minosoft.gui.rendering.chunk.SectionArrayMesh
import de.bixilon.minosoft.gui.rendering.chunk.models.FaceBorderSize import de.bixilon.minosoft.gui.rendering.chunk.models.FaceSize
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModel import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModel
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelElement import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelElement
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelFace import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelFace
@ -35,7 +35,7 @@ import glm_.vec2.Vec2
import glm_.vec3.Vec3 import glm_.vec3.Vec3
class ElementRenderer(parent: BlockModelElement, val rotation: Vec3, uvLock: Boolean, rescale: Boolean) { class ElementRenderer(parent: BlockModelElement, val rotation: Vec3, uvLock: Boolean, rescale: Boolean) {
val faceBorderSize: Array<FaceBorderSize?> = arrayOfNulls(Directions.DIRECTIONS.size) val faceBorderSize: Array<FaceSize?> = arrayOfNulls(Directions.DIRECTIONS.size)
private val faces: MutableMap<Directions, BlockModelFace> = mutableMapOf() private val faces: MutableMap<Directions, BlockModelFace> = mutableMapOf()
private var transformedPositions: Array<Vec3> = parent.transformedPositions.clone() private var transformedPositions: Array<Vec3> = parent.transformedPositions.clone()
private val directionMapping: HashBiMap<Directions, Directions> = HashBiMap.create() private val directionMapping: HashBiMap<Directions, Directions> = HashBiMap.create()

View File

@ -9,7 +9,7 @@ import de.bixilon.minosoft.data.world.World
import de.bixilon.minosoft.data.world.light.LightAccessor import de.bixilon.minosoft.data.world.light.LightAccessor
import de.bixilon.minosoft.gui.rendering.RenderConstants import de.bixilon.minosoft.gui.rendering.RenderConstants
import de.bixilon.minosoft.gui.rendering.chunk.ChunkMeshCollection import de.bixilon.minosoft.gui.rendering.chunk.ChunkMeshCollection
import de.bixilon.minosoft.gui.rendering.chunk.models.FaceBorderSize import de.bixilon.minosoft.gui.rendering.chunk.models.FaceSize
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelElement import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelElement
import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelFace import de.bixilon.minosoft.gui.rendering.chunk.models.loading.BlockModelFace
import de.bixilon.minosoft.gui.rendering.textures.Texture import de.bixilon.minosoft.gui.rendering.textures.Texture
@ -25,7 +25,7 @@ class FluidRenderer(
private val flowingTextureName: String, private val flowingTextureName: String,
private val regex: String, private val regex: String,
) : BlockRenderInterface { ) : BlockRenderInterface {
override val faceBorderSizes: Array<Array<FaceBorderSize>?> = arrayOfNulls(Directions.DIRECTIONS.size) override val faceBorderSizes: Array<Array<FaceSize>?> = arrayOfNulls(Directions.DIRECTIONS.size)
override val transparentFaces: BooleanArray = BooleanArray(Directions.DIRECTIONS.size) override val transparentFaces: BooleanArray = BooleanArray(Directions.DIRECTIONS.size)
private lateinit var stillTexture: Texture private lateinit var stillTexture: Texture
private lateinit var flowingTexture: Texture private lateinit var flowingTexture: Texture

View File

@ -75,4 +75,7 @@ object VecUtil {
return false return false
} }
fun JsonArray.readUV(): Pair<Vec2, Vec2> {
return Pair(Vec2(this[0].asFloat, this[3].asFloat), Vec2(this[2].asFloat, this[1].asFloat))
}
} }