tiling optimisation 2.2ms -> 1.7ms

This commit is contained in:
minjaesong
2023-10-10 18:16:35 +09:00
parent 26936fde09
commit 3b32242a2b
16 changed files with 177 additions and 56 deletions

View File

@@ -14,8 +14,6 @@ import net.torvald.terrarum.blockproperties.Block
import net.torvald.terrarum.gamecontroller.KeyToggler
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.WorldSimulator
import net.torvald.terrarum.gameworld.WorldTime
import net.torvald.terrarum.gameworld.fmod
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import kotlin.math.roundToInt
@@ -85,12 +83,12 @@ internal object BlocksDrawer {
private lateinit var terrainTilesBuffer: Array<IntArray>
private lateinit var wallTilesBuffer: Array<IntArray>
private lateinit var oreTilesBuffer: Array<IntArray>
//private lateinit var wireTilesBuffer: Array<IntArray>
private lateinit var fluidTilesBuffer: Array<IntArray>
private lateinit var occlusionBuffer: Array<IntArray>
private var tilesBuffer: Pixmap = Pixmap(1, 1, Pixmap.Format.RGBA8888)
private lateinit var tilesQuad: Mesh
private val shader = App.loadShaderFromClasspath("shaders/default.vert", "shaders/tiling.frag")
@@ -207,6 +205,7 @@ internal object BlocksDrawer {
measureDebugTime("Renderer.Tiling") {
drawTiles(WALL)
drawTiles(TERRAIN) // regular tiles
drawTiles(ORES)
drawTiles(FLUID)
drawTiles(OCCLUSION)
//drawTiles(WIRE)
@@ -226,6 +225,7 @@ internal object BlocksDrawer {
gdxBlendNormalStraightAlpha()
renderUsingBuffer(TERRAIN, projectionMatrix, drawGlow)
renderUsingBuffer(ORES, projectionMatrix, drawGlow)
renderUsingBuffer(FLUID, projectionMatrix, drawGlow)
}
@@ -259,6 +259,43 @@ internal object BlocksDrawer {
OCCLUSION_TILE_NUM_BASE, CreateTileAtlas.RenderTag.CONNECT_SELF, CreateTileAtlas.RenderTag.MASK_47
)
private lateinit var renderOnF3Only: Array<Int>
private lateinit var platformTiles: Array<Int>
private lateinit var wallStickerTiles: Array<Int>
private lateinit var connectMutualTiles: Array<Int>
private lateinit var connectSelfTiles: Array<Int>
internal fun rebuildInternalPrecalculations() {
if (App.IS_DEVELOPMENT_BUILD) {
printdbg(this, "Current TileName to Number map:")
world.tileNameToNumberMap.forEach { id, num ->
println("$id -> $num")
}
println("================================")
}
renderOnF3Only = BlockCodex.blockProps.filter { (id, prop) ->
prop.isActorBlock && !prop.hasTag("DORENDER") && !id.startsWith("virt:") && id != Block.NULL
}.map { world.tileNameToNumberMap[it.key] ?: throw NullPointerException("No tilenumber for ${it.key} exists") }.sorted().toTypedArray()
platformTiles = BlockCodex.blockProps.filter { (id, prop) ->
isPlatform(id) && !id.startsWith("virt:") && id != Block.NULL
}.map { world.tileNameToNumberMap[it.key] ?: throw NullPointerException("No tilenumber for ${it.key} exists") }.sorted().toTypedArray()
wallStickerTiles = BlockCodex.blockProps.filter { (id, prop) ->
isWallSticker(id) && !id.startsWith("virt:") && id != Block.NULL
}.map { world.tileNameToNumberMap[it.key] ?: throw NullPointerException("No tilenumber for ${it.key} exists") }.sorted().toTypedArray()
connectMutualTiles = BlockCodex.blockProps.filter { (id, prop) ->
isConnectMutual(id) && !id.startsWith("virt:") && id != Block.NULL
}.map { world.tileNameToNumberMap[it.key] ?: throw NullPointerException("No tilenumber for ${it.key} exists") }.sorted().toTypedArray()
connectSelfTiles = BlockCodex.blockProps.filter { (id, prop) ->
isConnectSelf(id) && !id.startsWith("virt:") && id != Block.NULL
}.map { world.tileNameToNumberMap[it.key] ?: throw NullPointerException("No tilenumber for ${it.key} exists") }.sorted().toTypedArray()
}
/**
* Autotiling; writes to buffer. Actual draw code must be called after this operation.
*
@@ -293,12 +330,14 @@ internal object BlocksDrawer {
val bufferX = x - for_x_start
val bufferY = y - for_y_start
val thisTile: ItemID = when (mode) {
WALL -> world.getTileFromWall(x, y)
TERRAIN -> world.getTileFromTerrain(x, y)
ORES -> world.getTileFromOre(x, y).item
FLUID -> "basegame:-1" // TODO need new wire storing format //world.getFluid(x, y).type.abs()
OCCLUSION -> "placeholder_occlusion"
val (wx, wy) = world.coerceXY(x, y)
val thisTile: Int = when (mode) {
WALL -> world.layerWall.unsafeGetTile(wx, wy)
TERRAIN -> world.layerTerrain.unsafeGetTile(wx, wy)
ORES -> world.layerOres.unsafeGetTile(wx, wy)//.also { println(it) }
FLUID -> 0 // TODO need new wire storing format //world.getFluid(x, y).type.abs()
OCCLUSION -> 0
else -> throw IllegalArgumentException()
}
@@ -307,19 +346,22 @@ internal object BlocksDrawer {
val nearbyTilesInfo = if (mode == OCCLUSION) {
getNearbyTilesInfoFakeOcc(x, y)
}
else if (mode == ORES) {
0
}
/*else if (mode == FLUID) {
getNearbyTilesInfoFluids(x, y)
}*/
else if (isPlatform(thisTile)) {
else if (platformTiles.binarySearch(thisTile) >= 0) {
getNearbyTilesInfoPlatform(x, y)
}
else if (isWallSticker(thisTile)) {
else if (wallStickerTiles.binarySearch(thisTile) >= 0) {
getNearbyTilesInfoWallSticker(x, y)
}
else if (isConnectMutual(thisTile)) {
else if (connectMutualTiles.binarySearch(thisTile) >= 0) {
getNearbyTilesInfoConMutual(x, y, mode)
}
else if (isConnectSelf(thisTile)) {
else if (connectSelfTiles.binarySearch(thisTile) >= 0) {
getNearbyTilesInfoConSelf(x, y, mode, thisTile)
}
else {
@@ -332,17 +374,16 @@ internal object BlocksDrawer {
// App.tileMaker.fluidToTileNumber(world.getFluid(x, y))
// else
renderTag.tileNumber
var tileNumber = if (thisTile == Block.AIR) 0
var tileNumber = if (thisTile == 0) 0
// special case: actorblocks and F3 key
else if (BlockCodex.hasProp(thisTile) && BlockCodex[thisTile].isActorBlock &&
!BlockCodex[thisTile].hasTag("DORENDER") && !KeyToggler.isOn(Keys.F3))
else if (renderOnF3Only.binarySearch(thisTile) >= 0 && !KeyToggler.isOn(Keys.F3))
0
// special case: fluids
else if (mode == FLUID)
tileNumberBase + connectLut47[nearbyTilesInfo]
// special case: ores
else if (mode == ORES)
tileNumberBase + world.getTileFromOre(x, y).tilePlacement
tileNumberBase + world.layerOres.unsafeGetTile1(wx, wy).second
// rest of the cases: terrain and walls
else tileNumberBase + when (renderTag.maskType) {
CreateTileAtlas.RenderTag.MASK_NA -> 0
@@ -401,6 +442,27 @@ internal object BlocksDrawer {
return ret
}
private fun getNearbyTilesInfoConSelf(x: Int, y: Int, mode: Int, mark: Int): Int {
val layer = when (mode) {
TERRAIN -> world.layerTerrain
WALL -> world.layerWall
ORES -> world.layerOres
FLUID -> world.layerFluids
else -> throw IllegalArgumentException()
}
val nearbyTiles = getNearbyTilesPos(x, y).map { layer.unsafeGetTile(x, y) }
var ret = 0
for (i in nearbyTiles.indices) {
if (nearbyTiles[i] == mark) {
ret += (1 shl i) // add 1, 2, 4, 8 for i = 0, 1, 2, 3
}
}
return ret
}
private fun getNearbyTilesInfoFakeOcc(x: Int, y: Int): Int {
val eligible = BlockCodex[world.getTileFromWall(x, y)].isSolidForTileCnx && !BlockCodex[world.getTileFromTerrain(x, y)].isSolidForTileCnx
val nearbyTiles = getNearbyTilesPos(x, y).map {
@@ -544,6 +606,7 @@ internal object BlocksDrawer {
val sourceBuffer = when(mode) {
TERRAIN -> terrainTilesBuffer
WALL -> wallTilesBuffer
ORES -> oreTilesBuffer
//WIRE -> wireTilesBuffer
FLUID -> fluidTilesBuffer
OCCLUSION -> occlusionBuffer
@@ -567,7 +630,7 @@ internal object BlocksDrawer {
val tileAtlas = when (mode) {
TERRAIN, WALL, OCCLUSION -> tilesTerrain
TERRAIN, ORES, WALL, OCCLUSION -> tilesTerrain
//WIRE -> tilesWire
FLUID -> tilesFluid
else -> throw IllegalArgumentException()
@@ -575,13 +638,14 @@ internal object BlocksDrawer {
val sourceBuffer = when(mode) {
TERRAIN -> terrainTilesBuffer
WALL -> wallTilesBuffer
ORES -> oreTilesBuffer
//WIRE -> wireTilesBuffer
FLUID -> fluidTilesBuffer
OCCLUSION -> occlusionBuffer
else -> throw IllegalArgumentException()
}
val vertexColour = when (mode) {
TERRAIN, /*WIRE,*/ FLUID, OCCLUSION -> Color.WHITE
TERRAIN, /*WIRE,*/ ORES, FLUID, OCCLUSION -> Color.WHITE
WALL -> App.tileMaker.wallOverlayColour
else -> throw IllegalArgumentException()
}
@@ -659,6 +723,7 @@ internal object BlocksDrawer {
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) }

View File

@@ -14,6 +14,7 @@ import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.blockproperties.Fluid
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.utils.HashArray
import net.torvald.terrarum.worlddrawer.CreateTileAtlas.AtlasSource.*
import kotlin.math.roundToInt
import kotlin.math.sqrt
@@ -54,6 +55,7 @@ class CreateTileAtlas {
lateinit var terrainTileColourMap: HashMap<ItemID, Cvec>
lateinit var tags: HashMap<ItemID, RenderTag> // TileID, RenderTag
private set
lateinit var tagsByTileNum: HashArray<RenderTag>; private set
lateinit var itemSheetNumbers: HashMap<ItemID, Int> // TileID, Int
private set
private val defaultRenderTag = RenderTag(3, RenderTag.CONNECT_SELF, RenderTag.MASK_NA) // 'update' block
@@ -129,6 +131,7 @@ class CreateTileAtlas {
operator fun invoke(updateExisting: Boolean = false) { if (updateExisting || !initialised) {
tags = HashMap<ItemID, RenderTag>()
tagsByTileNum = HashArray()
itemSheetNumbers = HashMap<ItemID, Int>()
atlasPrevernal = Pixmap(TILES_IN_X * TILE_SIZE, TILES_IN_X * TILE_SIZE, Pixmap.Format.RGBA8888).also { it.blending = Pixmap.Blending.None }
@@ -296,6 +299,11 @@ class CreateTileAtlas {
return tags.getOrDefault(blockID, defaultRenderTag)
}
fun getRenderTag(tilenum: Int): RenderTag {
return tagsByTileNum.getOrDefault(tilenum.toLong(), defaultRenderTag)
}
val nullTile = Pixmap(TILE_SIZE * 16, TILE_SIZE * 16, Pixmap.Format.RGBA8888)
private fun fileToAtlantes(modname: String, matte: FileHandle, glow: FileHandle?, mode: String?) {
@@ -370,6 +378,7 @@ class CreateTileAtlas {
}
tags[id] = RenderTag(atlasCursor, connectionType, maskType)
tagsByTileNum[atlasCursor.toLong()] = RenderTag(atlasCursor, connectionType, maskType)
printdbg(this, "tileName ${id} ->> tileNumber ${atlasCursor}")
}