fix: water stripes on blocksdrawer

This commit is contained in:
minjaesong
2024-07-22 14:23:58 +09:00
parent 91e25da54f
commit 1fddb5f0da
2 changed files with 82 additions and 31 deletions

View File

@@ -21,6 +21,7 @@ import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.serialise.toBig64
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.Companion.WALL_OVERLAY_COLOUR
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import net.torvald.unsafe.UnsafeInt2D
import kotlin.math.roundToInt
@@ -87,11 +88,12 @@ internal object BlocksDrawer {
private const val GZIP_READBUF_SIZE = 8192
private lateinit var terrainTilesBuffer: Array<IntArray>
private lateinit var wallTilesBuffer: Array<IntArray>
private lateinit var oreTilesBuffer: Array<IntArray>
private lateinit var fluidTilesBuffer: Array<IntArray>
private lateinit var occlusionBuffer: Array<IntArray>
private lateinit var terrainTilesBuffer: UnsafeInt2D
private lateinit var wallTilesBuffer: UnsafeInt2D
private lateinit var oreTilesBuffer: UnsafeInt2D
private lateinit var fluidTilesBuffer: UnsafeInt2D
private lateinit var occlusionBuffer: UnsafeInt2D
private lateinit var tempRenderTypeBuffer: UnsafeInt2D // 0x tttt 00 ii; where t=rawTileNum, i=nearbyTilesInfo
private var tilesBuffer: Pixmap = Pixmap(1, 1, Pixmap.Format.RGBA8888)
private lateinit var tilesQuad: Mesh
@@ -312,6 +314,8 @@ internal object BlocksDrawer {
return (XXHash64.hash(LandUtil.getBlockAddr(world, x, y).toBig64(), ((x*16777619) xor (y+1+layer)).toLong()) fmod mod.toLong()).toInt()
}
/**
* Autotiling; writes to buffer. Actual draw code must be called after this operation.
*
@@ -346,7 +350,7 @@ internal object BlocksDrawer {
val (wx, wy) = world.coerceXY(x, y)
var thisTile: Int = when (mode) {
var rawTileNum: Int = when (mode) {
WALL -> world.layerWall.unsafeGetTile(wx, wy)
TERRAIN -> world.layerTerrain.unsafeGetTile(wx, wy)
ORES -> world.layerOres.unsafeGetTile(wx, wy)//.also { println(it) }
@@ -358,7 +362,7 @@ internal object BlocksDrawer {
else -> throw IllegalArgumentException()
}
var hash = if ((mode == WALL || mode == TERRAIN) && !BlockCodex[world.tileNumberToNameMap[thisTile.toLong()]].hasTag("NORANDTILE"))
var hash = if ((mode == WALL || mode == TERRAIN) && !BlockCodex[world.tileNumberToNameMap[rawTileNum.toLong()]].hasTag("NORANDTILE"))
getHashCoord(x, y, 8, mode)
else 0
@@ -387,51 +391,59 @@ internal object BlocksDrawer {
world.getTileFromTerrain(wx, wy)
if (/*fluidCornerLut[solids] != 0 &&*/ BlockCodex[tile].isSolidForTileCnx && nearbyFluidType != null) {
thisTile = world.tileNameToNumberMap[nearbyFluidType]!!
rawTileNum = world.tileNameToNumberMap[nearbyFluidType]!!
18 + tileToUse
}
else if (thisTile == 0)
else if (rawTileNum == 0)
0
else if (fluids[3].amount >= 1.5f / 16f)
17
else if (fluids[3].amount >= 0.5f / 16f)
16
else if (fluids[3].amount >= 0.5f / 16f) {
//if tile above is fluid tile which use 16, use 17
if (bufferY > 0 && tempRenderTypeBuffer[bufferY - 1, bufferX].let {
(it.ushr(16) == rawTileNum && it.and(255) >= 16) ||
(it.ushr(16) == rawTileNum && it.and(255) == 1)
})
17
// else, use 16
else 16
}
else if (fillThis < 0.5f / 16f)
0
else
(fillThis * 16f - 0.5f).roundToInt().coerceIn(0, 15)
}
else if (treeLeavesTiles.binarySearch(thisTile) >= 0) {
getNearbyTilesInfoTrees(x, y, mode).swizzle8(thisTile, hash)
else if (treeLeavesTiles.binarySearch(rawTileNum) >= 0) {
getNearbyTilesInfoTrees(x, y, mode).swizzle8(rawTileNum, hash)
}
else if (treeTrunkTiles.binarySearch(thisTile) >= 0) {
else if (treeTrunkTiles.binarySearch(rawTileNum) >= 0) {
hash = 0
getNearbyTilesInfoTrees(x, y, mode)
}
else if (platformTiles.binarySearch(thisTile) >= 0) {
else if (platformTiles.binarySearch(rawTileNum) >= 0) {
hash %= 2
getNearbyTilesInfoPlatform(x, y).swizzleH2(thisTile, hash)
getNearbyTilesInfoPlatform(x, y).swizzleH2(rawTileNum, hash)
}
else if (wallStickerTiles.binarySearch(thisTile) >= 0) {
else if (wallStickerTiles.binarySearch(rawTileNum) >= 0) {
hash = 0
getNearbyTilesInfoWallSticker(x, y)
}
else if (connectMutualTiles.binarySearch(thisTile) >= 0) {
getNearbyTilesInfoConMutual(x, y, mode).swizzle8(thisTile, hash)
else if (connectMutualTiles.binarySearch(rawTileNum) >= 0) {
getNearbyTilesInfoConMutual(x, y, mode).swizzle8(rawTileNum, hash)
}
else if (connectSelfTiles.binarySearch(thisTile) >= 0) {
getNearbyTilesInfoConSelf(x, y, mode, thisTile).swizzle8(thisTile, hash)
else if (connectSelfTiles.binarySearch(rawTileNum) >= 0) {
getNearbyTilesInfoConSelf(x, y, mode, rawTileNum).swizzle8(rawTileNum, hash)
}
else {
0
}
val renderTag = if (mode == OCCLUSION) occlusionRenderTag else App.tileMaker.getRenderTag(thisTile)
val renderTag = if (mode == OCCLUSION) occlusionRenderTag else App.tileMaker.getRenderTag(rawTileNum)
val tileNumberBase = renderTag.tileNumber
var tileNumber = if (thisTile == 0 && mode != OCCLUSION) 0
var tileNumber = if (rawTileNum == 0 && mode != OCCLUSION) 0
// special case: actorblocks and F3 key
else if (renderOnF3Only.binarySearch(thisTile) >= 0 && !KeyToggler.isOn(Keys.F3))
else if (renderOnF3Only.binarySearch(rawTileNum) >= 0 && !KeyToggler.isOn(Keys.F3))
0
// special case: fluids
else if (mode == FLUID)
@@ -464,6 +476,7 @@ internal object BlocksDrawer {
// draw a tile
writeToBuffer(mode, bufferX, bufferY, thisTileX, thisTileY, breakingStage, hash)
tempRenderTypeBuffer[bufferY, bufferX] = nearbyTilesInfo or rawTileNum.shl(16)
}
}
}
@@ -763,7 +776,7 @@ internal object BlocksDrawer {
}
sourceBuffer[bufferPosY][bufferPosX] = sheetXYToTilemapColour(mode, sheetX, sheetY, breakage, hash)
sourceBuffer[bufferPosY, bufferPosX] = sheetXYToTilemapColour(mode, sheetX, sheetY, breakage, hash)
}
private var _tilesBufferAsTex: Texture = Texture(1, 1, Pixmap.Format.RGBA8888)
@@ -801,7 +814,7 @@ internal object BlocksDrawer {
// As the texture size is very small, multithreading it would be less effective
for (y in 0 until tilesBuffer.height) {
for (x in 0 until tilesBuffer.width) {
val color = sourceBuffer[y][x]
val color = sourceBuffer[y, x]
tilesBuffer.setColor(color)
tilesBuffer.drawPixel(x, y)
}
@@ -871,11 +884,19 @@ internal object BlocksDrawer {
// only update if it's really necessary
if (oldTH != tilesInHorizontal || oldTV != tilesInVertical) {
terrainTilesBuffer = Array(tilesInVertical) { IntArray(tilesInHorizontal) }
wallTilesBuffer = Array(tilesInVertical) { IntArray(tilesInHorizontal) }
oreTilesBuffer = Array(tilesInVertical) { IntArray(tilesInHorizontal) }
fluidTilesBuffer = Array(tilesInVertical) { IntArray(tilesInHorizontal) }
occlusionBuffer = Array(tilesInVertical) { IntArray(tilesInHorizontal) }
if (::terrainTilesBuffer.isInitialized) terrainTilesBuffer.destroy()
if (::wallTilesBuffer.isInitialized) wallTilesBuffer.destroy()
if (::oreTilesBuffer.isInitialized) oreTilesBuffer.destroy()
if (::fluidTilesBuffer.isInitialized) fluidTilesBuffer.destroy()
if (::occlusionBuffer.isInitialized) occlusionBuffer.destroy()
if (::tempRenderTypeBuffer.isInitialized) tempRenderTypeBuffer.destroy()
terrainTilesBuffer = UnsafeInt2D(tilesInHorizontal, tilesInVertical)
wallTilesBuffer = UnsafeInt2D(tilesInHorizontal, tilesInVertical)
oreTilesBuffer = UnsafeInt2D(tilesInHorizontal, tilesInVertical)
fluidTilesBuffer = UnsafeInt2D(tilesInHorizontal, tilesInVertical)
occlusionBuffer = UnsafeInt2D(tilesInHorizontal, tilesInVertical)
tempRenderTypeBuffer = UnsafeInt2D(tilesInHorizontal, tilesInVertical)
tilesBuffer.dispose()
tilesBuffer = Pixmap(tilesInHorizontal, tilesInVertical, Pixmap.Format.RGBA8888)
@@ -954,6 +975,14 @@ internal object BlocksDrawer {
tilesQuad.tryDispose()
shader.dispose()
if (::terrainTilesBuffer.isInitialized) terrainTilesBuffer.destroy()
if (::wallTilesBuffer.isInitialized) wallTilesBuffer.destroy()
if (::oreTilesBuffer.isInitialized) oreTilesBuffer.destroy()
if (::fluidTilesBuffer.isInitialized) fluidTilesBuffer.destroy()
if (::occlusionBuffer.isInitialized) occlusionBuffer.destroy()
if (::tempRenderTypeBuffer.isInitialized) tempRenderTypeBuffer.destroy()
App.tileMaker.dispose()
}

View File

@@ -0,0 +1,22 @@
package net.torvald.unsafe
/**
* Created by minjaesong on 2024-07-22.
*/
class UnsafeInt2D(width: Int, height: Int) {
val width = width.toLong()
val height = height.toLong()
private val ptr = UnsafeHelper.allocate(4L * width * height)
private inline fun toIndex(y: Int, x: Int) = width * y + x
operator fun set(y: Int, x: Int, value: Int) = ptr.setInt(toIndex(y, x), value)
operator fun get(y: Int, x: Int) = ptr.getInt(toIndex(y, x))
fun destroy() = ptr.destroy()
val destroyed: Boolean
get() = ptr.destroyed
}