working deblocking

This commit is contained in:
minjaesong
2024-08-29 03:00:39 +09:00
parent d02282a64d
commit 43e8d1a8d0
12 changed files with 118 additions and 61 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -277,7 +277,7 @@ object IngameRenderer : Disposable {
if ((!gamePaused && !App.isScreenshotRequested()) || newWorldLoadedLatch) {
measureDebugTime("Renderer.LightRun*") {
// recalculate for even frames, or if the sign of the cam-x changed
// recalculate for every three frame, or if the sign of the cam-x changed
if (App.GLOBAL_RENDER_TIMER % 3 == 0L || Math.abs(WorldCamera.x - oldCamX) >= world.width * 0.85f * TILE_SIZEF || newWorldLoadedLatch) {
LightmapRenderer.recalculate(actorsRenderFarBehind + actorsRenderBehind + actorsRenderFront + actorsRenderMidTop + actorsRenderMiddle + actorsRenderOverlay)
}

View File

@@ -75,7 +75,9 @@ internal object BlocksDrawer {
val ORES = GameWorld.ORES
val FLUID = -2
val OCCLUSION = 31337
val BLURMAP = 31338
val BLURMAP_BASE = 31338
val BLURMAP_TERR = BLURMAP_BASE + TERRAIN
val BLURMAP_WALL = BLURMAP_BASE + WALL
private const val OCCLUSION_TILE_NUM_BASE = 16
@@ -98,7 +100,8 @@ internal object BlocksDrawer {
private lateinit var oreTilesBuffer: UnsafeLong2D // stores subtiles (dimension is doubled)
private lateinit var fluidTilesBuffer: UnsafeLong2D // stores subtiles (dimension is doubled)
private lateinit var occlusionBuffer: UnsafeLong2D // stores subtiles (dimension is doubled)
private lateinit var blurMap: UnsafeLong2D // stores subtiles (dimension is doubled)
private lateinit var blurMapTerr: UnsafeLong2D // stores subtiles (dimension is doubled)
private lateinit var blurMapWall: UnsafeLong2D // stores subtiles (dimension is doubled)
private lateinit var tempRenderTypeBuffer: UnsafeLong2D // this one is NOT dimension doubled; 0x tttt 00 ii where t=rawTileNum, i=nearbyTilesInfo
private var tilesBuffer: Pixmap = Pixmap(1, 1, Pixmap.Format.RGBA8888)
private var tilesBuffer2: Pixmap = Pixmap(1, 1, Pixmap.Format.RGBA8888)
@@ -257,8 +260,9 @@ internal object BlocksDrawer {
}
catch (e: ClassCastException) { }
if (!world.layerTerrain.ptrDestroyed) {
measureDebugTime("Renderer.Tiling") {
if (doTilemapUpdate) {
// rendering tilemap only updates every three frame
measureDebugTime("Renderer.Tiling*") {
drawTiles(WALL)
drawTiles(TERRAIN) // regular tiles
drawTiles(ORES)
@@ -334,7 +338,7 @@ internal object BlocksDrawer {
}
private val occlusionRenderTag = CreateTileAtlas.RenderTag(
OCCLUSION_TILE_NUM_BASE, CreateTileAtlas.RenderTag.CONNECT_SELF, CreateTileAtlas.RenderTag.MASK_47, 0
OCCLUSION_TILE_NUM_BASE, CreateTileAtlas.RenderTag.CONNECT_SELF, CreateTileAtlas.RenderTag.MASK_47, 0, 0
)
private lateinit var renderOnF3Only: Array<Int>
@@ -583,19 +587,21 @@ internal object BlocksDrawer {
else 0
if (mode == TERRAIN || mode == WALL) {
// TODO translate nearbyTilesInfo into proper subtile number
// TEST CODE
val subtiles = arrayOf(
Point2i(130, 0),
Point2i(131, 0),
Point2i(131, 1),
Point2i(130, 1),
// translate nearbyTilesInfo into proper subtile number
val nearbyTilesInfo = getNearbyTilesInfoDeblocking(mode, x, y)
val subtiles = if (nearbyTilesInfo == null)
listOf(
Point2i(130, 1), Point2i(130, 1), Point2i(130, 1), Point2i(130, 1)
)
/*TL*/writeToBufferSubtile(BLURMAP, bufferBaseX * 2 + 0, bufferBaseY * 2 + 0, subtiles[0].x, subtiles[0].y, 0, 0)
/*TR*/writeToBufferSubtile(BLURMAP, bufferBaseX * 2 + 1, bufferBaseY * 2 + 0, subtiles[1].x, subtiles[1].y, 0, 0)
/*BR*/writeToBufferSubtile(BLURMAP, bufferBaseX * 2 + 1, bufferBaseY * 2 + 1, subtiles[2].x, subtiles[2].y, 0, 0)
/*BL*/writeToBufferSubtile(BLURMAP, bufferBaseX * 2 + 0, bufferBaseY * 2 + 1, subtiles[3].x, subtiles[3].y, 0, 0)
else
(0..3).map {
Point2i(126, 0) + deblockerNearbyTilesToSubtile[it][nearbyTilesInfo]
}
/*TL*/writeToBufferSubtile(BLURMAP_BASE + mode, bufferBaseX * 2 + 0, bufferBaseY * 2 + 0, subtiles[0].x, subtiles[0].y, 0, 0)
/*TR*/writeToBufferSubtile(BLURMAP_BASE + mode, bufferBaseX * 2 + 1, bufferBaseY * 2 + 0, subtiles[1].x, subtiles[1].y, 0, 0)
/*BR*/writeToBufferSubtile(BLURMAP_BASE + mode, bufferBaseX * 2 + 1, bufferBaseY * 2 + 1, subtiles[2].x, subtiles[2].y, 0, 0)
/*BL*/writeToBufferSubtile(BLURMAP_BASE + mode, bufferBaseX * 2 + 0, bufferBaseY * 2 + 1, subtiles[3].x, subtiles[3].y, 0, 0)
}
if (renderTag.maskType >= CreateTileAtlas.RenderTag.MASK_SUBTILE_GENERIC) {
@@ -796,6 +802,48 @@ internal object BlocksDrawer {
return ret
}
private fun getNearbyTilesInfoDeblocking(mode: Int, x: Int, y: Int): Int? {
val tileThis = world.getTileFrom(mode, x, y)
val nearbyTiles = getNearbyTilesPos4(x, y).map { world.getTileFrom(mode, it.x, it.y) }
val renderTagThis = App.tileMaker.getRenderTag(tileThis)
if (renderTagThis.postProcessing != CreateTileAtlas.RenderTag.POSTPROCESS_DEBLOCKING) return null
when (renderTagThis.connectionType) {
CreateTileAtlas.RenderTag.CONNECT_SELF -> {
var ret = 0
for (i in nearbyTiles.indices) {
if (nearbyTiles[i] == tileThis) {
ret += (1 shl i) // add 1, 2, 4, 8 for i = 0, 1, 2, 3
}
}
return ret
}
CreateTileAtlas.RenderTag.CONNECT_MUTUAL -> {
// make sure to not connect to tiles with no deblocking
var ret = 0
for (i in nearbyTiles.indices) {
if (BlockCodex[nearbyTiles[i]].isSolidForTileCnx && isConnectMutual(nearbyTiles[i]) &&
App.tileMaker.getRenderTag(nearbyTiles[i]).postProcessing == CreateTileAtlas.RenderTag.POSTPROCESS_DEBLOCKING
) {
ret += (1 shl i) // add 1, 2, 4, 8 for i = 0, 1, 2, 3
}
}
return ret
}
else -> return null
}
}
private val deblockerNearbyTilesToSubtile: Array<Array<Point2i>> = arrayOf(
arrayOf(Point2i(0,0),Point2i(0,0),Point2i(0,0),Point2i(0,0),Point2i(3,0),Point2i(3,0),Point2i(3,0),Point2i(3,0),Point2i(2,0),Point2i(2,0),Point2i(2,0),Point2i(2,0),Point2i(4,0),Point2i(4,0),Point2i(4,0),Point2i(4,0)), /*TL*/
arrayOf(Point2i(1,0),Point2i(3,0),Point2i(1,0),Point2i(3,0),Point2i(1,0),Point2i(3,0),Point2i(1,0),Point2i(3,0),Point2i(3,1),Point2i(4,0),Point2i(3,1),Point2i(4,0),Point2i(3,1),Point2i(4,0),Point2i(3,1),Point2i(4,0)), /*TR*/
arrayOf(Point2i(1,1),Point2i(2,1),Point2i(3,1),Point2i(4,0),Point2i(1,1),Point2i(2,1),Point2i(3,1),Point2i(4,0),Point2i(1,1),Point2i(2,1),Point2i(3,1),Point2i(4,0),Point2i(1,1),Point2i(2,1),Point2i(3,1),Point2i(4,0)), /*BR*/
arrayOf(Point2i(0,1),Point2i(0,1),Point2i(2,0),Point2i(2,0),Point2i(2,1),Point2i(2,1),Point2i(4,0),Point2i(4,0),Point2i(0,1),Point2i(0,1),Point2i(2,0),Point2i(2,0),Point2i(2,1),Point2i(2,1),Point2i(4,0),Point2i(4,0)), /*BL*/
)
private fun getNearbyTilesInfoConMutual(x: Int, y: Int, mode: Int): Int {
val nearbyTiles: List<ItemID> = getNearbyTilesPos(x, y).map { world.getTileFrom(mode, it.x, it.y) }
@@ -1075,7 +1123,6 @@ internal object BlocksDrawer {
ORES -> oreTilesBuffer
FLUID -> fluidTilesBuffer
OCCLUSION -> occlusionBuffer
BLURMAP -> blurMap
else -> throw IllegalArgumentException()
}
@@ -1092,7 +1139,8 @@ internal object BlocksDrawer {
ORES -> oreTilesBuffer
FLUID -> fluidTilesBuffer
OCCLUSION -> occlusionBuffer
BLURMAP -> blurMap
BLURMAP_TERR -> blurMapTerr
BLURMAP_WALL -> blurMapWall
else -> throw IllegalArgumentException()
}
@@ -1107,6 +1155,9 @@ internal object BlocksDrawer {
private var _blurTilesBuffer: Texture = Texture(1, 1, Pixmap.Format.RGBA8888)
private val occlusionIntensity = 0.25f // too low value and dark-coloured walls won't darken enough
private val doTilemapUpdate: Boolean
get() = (!world.layerTerrain.ptrDestroyed && App.GLOBAL_RENDER_TIMER % 3 == 0L)
private fun renderUsingBuffer(mode: Int, projectionMatrix: Matrix4, drawGlow: Boolean, drawEmissive: Boolean) {
//Gdx.gl.glClearColor(.094f, .094f, .094f, 0f)
//Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
@@ -1117,7 +1168,7 @@ internal object BlocksDrawer {
val tileAtlas = when (mode) {
TERRAIN, ORES, WALL, OCCLUSION, FLUID, BLURMAP -> tilesTerrain
TERRAIN, ORES, WALL, OCCLUSION, FLUID, BLURMAP_TERR, BLURMAP_WALL -> tilesTerrain
else -> throw IllegalArgumentException()
}
val sourceBuffer = when(mode) {
@@ -1133,9 +1184,10 @@ internal object BlocksDrawer {
else -> Color.WHITE
}
// write to colour buffer
// As the texture size is very small, multithreading it would be less effective
// TODO making it run sporadically without graphical issue would improve the tiling performance
// if (doTilemapUpdate) {
for (y in 0 until tilesBuffer.height) {
for (x in 0 until tilesBuffer.width) {
val colRaw = sourceBuffer[y, x]
@@ -1147,14 +1199,10 @@ internal object BlocksDrawer {
tilesBuffer2.setColor(colSub)
tilesBuffer2.drawPixel(x, y)
}
}
// write blurmap to its own buffer for TERRAIN and WALL
if (mode == TERRAIN || mode == WALL) {
for (y in 0 until tilesBuffer.height) {
for (x in 0 until tilesBuffer.width) {
val colRaw = blurMap[y, x]
val colRaw = (if (mode == TERRAIN) blurMapTerr else blurMapWall)[y, x]
val colMain = colRaw.toInt()
blurTilesBuffer.setColor(colMain)
@@ -1162,6 +1210,7 @@ internal object BlocksDrawer {
}
}
}
// }
_tilesBufferAsTex.dispose()
@@ -1256,7 +1305,8 @@ internal object BlocksDrawer {
oreTilesBuffer = UnsafeLong2D(tilesInHorizontal, tilesInVertical)
fluidTilesBuffer = UnsafeLong2D(tilesInHorizontal, tilesInVertical)
occlusionBuffer = UnsafeLong2D(tilesInHorizontal, tilesInVertical)
blurMap = UnsafeLong2D(tilesInHorizontal, tilesInVertical)
blurMapTerr = UnsafeLong2D(tilesInHorizontal, tilesInVertical)
blurMapWall = UnsafeLong2D(tilesInHorizontal, tilesInVertical)
tempRenderTypeBuffer = UnsafeLong2D(hTilesInHorizontal, hTilesInVertical)
tilesBuffer.dispose()
@@ -1346,7 +1396,8 @@ internal object BlocksDrawer {
if (::oreTilesBuffer.isInitialized) oreTilesBuffer.destroy()
if (::fluidTilesBuffer.isInitialized) fluidTilesBuffer.destroy()
if (::occlusionBuffer.isInitialized) occlusionBuffer.destroy()
if (::blurMap.isInitialized) blurMap.destroy()
if (::blurMapTerr.isInitialized) blurMapTerr.destroy()
if (::blurMapWall.isInitialized) blurMapWall.destroy()
if (::tempRenderTypeBuffer.isInitialized) tempRenderTypeBuffer.destroy()
if (::batch.isInitialized) batch.tryDispose()

View File

@@ -87,7 +87,7 @@ class CreateTileAtlas {
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, 0) // 'update' block
private val defaultRenderTag = RenderTag(3, RenderTag.CONNECT_SELF, RenderTag.MASK_NA, 0, 0) // 'update' block
var initialised = false
private set
@@ -478,20 +478,23 @@ class CreateTileAtlas {
val maskType = if (tilesPixmap.width >= 3*W_SUBTILE_GENERIC) MASK_SUBTILE_GRASS else MASK_SUBTILE_GENERIC
var connectionType0 = 0
var tilingMode = 0
var postProcessing = 0
for (x in 0 until 4) {
// val pixelY0 = (tilesPixmap.getPixel(x, 0).and(255) >= 128).toInt(x)
val pixelY1 = (tilesPixmap.getPixel(x, 1).and(255) >= 128).toInt(x)
val pixelY2 = (tilesPixmap.getPixel(x, 2).and(255) >= 128).toInt(x)
val pixelY3 = (tilesPixmap.getPixel(x, 3).and(255) >= 128).toInt(x)
tilingMode += pixelY1
connectionType0 += pixelY2
postProcessing += pixelY3
}
val connectionType = when (connectionType0) {
1 -> CONNECT_MUTUAL
2 -> CONNECT_SELF
else -> throw IllegalArgumentException("$connectionType0")
}
addTag(blockID, connectionType, maskType, tilingMode)
addTag(blockID, connectionType, maskType, tilingMode, postProcessing)
// println("drawToAtlantes tile: $blockID with mode $tilingMode")
drawToAtlantes(tilesPixmap, tilesGlowPixmap, tilesEmissivePixmap, maskType)
}
@@ -541,13 +544,13 @@ class CreateTileAtlas {
* This function must precede the drawToAtlantes() function, as the marking requires the variable
* 'atlasCursor' and the draw function modifies it!
*/
private fun addTag(id: ItemID, connectionType: Int, maskType: Int, tilingMode: Int = TILING_FULL) {
private fun addTag(id: ItemID, connectionType: Int, maskType: Int, tilingMode: Int = TILING_FULL, postProcessing: Int = 0) {
if (tags.containsKey(id)) {
throw Error("Block $id already exists")
}
tags[id] = RenderTag(atlasCursor, connectionType, maskType, tilingMode)
tagsByTileNum[atlasCursor.toLong()] = RenderTag(atlasCursor, connectionType, maskType, tilingMode)
tags[id] = RenderTag(atlasCursor, connectionType, maskType, tilingMode, postProcessing)
tagsByTileNum[atlasCursor.toLong()] = RenderTag(atlasCursor, connectionType, maskType, tilingMode, postProcessing)
printdbg(this, "tileName ${id} ->> tileNumber ${atlasCursor}")
}
@@ -714,7 +717,7 @@ class CreateTileAtlas {
/**
* @param tileNumber ordinal number of a tile in the texture atlas
*/
data class RenderTag(val tileNumber: Int, val connectionType: Int, val maskType: Int, val tilingMode: Int) {
data class RenderTag(val tileNumber: Int, val connectionType: Int, val maskType: Int, val tilingMode: Int, val postProcessing: Int) {
companion object {
const val CONNECT_MUTUAL = 0
const val CONNECT_SELF = 1
@@ -740,6 +743,9 @@ class CreateTileAtlas {
const val TILING_BRICK_LARGE = 4
const val TILING_BRICK_LARGE_NOFLIP = 5
const val POSTPROCESS_NONE = 0
const val POSTPROCESS_DEBLOCKING = 1
fun maskTypeToTileCount(maskType: Int) = when (maskType) {
MASK_NA -> 1
MASK_16 -> 16

View File

@@ -191,8 +191,8 @@ void main() {
vec4 tileU = getFragColorForOnscreenCoord1(fragCoord + blurU);
vec4 tileD = getFragColorForOnscreenCoord1(fragCoord + blurD);
vec4 blurH = (tileC + tileC + tileL + tileR) * _four;
vec4 blurV = (tileC + tileC + tileU + tileD) * _four;
vec4 blurH = (tileC + tileL + tileR) * _three;
vec4 blurV = (tileC + tileU + tileD) * _three;
vec4 blurPower = tile_breakage_blur[2];
vec4 finalTile = mix(
@@ -206,5 +206,5 @@ void main() {
vec4 finalColor = fma(mix(finalTile, finalBreakage, finalBreakage.a), bc.xxxy, finalTile * bc.yyyx);
fragColor = mix(colourFilter, colourFilter * finalColor, mulBlendIntensity);
// fragColor = blurPower;
// fragColor = mix(fragColor, blurPower, 0.18); // debug overlay
}