From d02282a64dbb848d5739ebcc7222525cbad9b019 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Wed, 28 Aug 2024 18:40:21 +0900 Subject: [PATCH] deblocking wip 2 --- assets/graphics/blocks/init.tga | 4 +- .../terrarum/worlddrawer/BlocksDrawer.kt | 64 +++++++++++++++---- .../terrarum/worlddrawer/CreateTileAtlas.kt | 8 +-- src/shaders/tiling.frag | 45 ++++++++----- .../terrain_variable_subtiling_full.kra | 4 +- 5 files changed, 90 insertions(+), 35 deletions(-) diff --git a/assets/graphics/blocks/init.tga b/assets/graphics/blocks/init.tga index 74bc69de5..0bce37c20 100644 --- a/assets/graphics/blocks/init.tga +++ b/assets/graphics/blocks/init.tga @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:244dcfe3b345c0e18dff4af6412400cd41fed108fad7716643b1c453c6fec882 -size 65554 +oid sha256:c931ae5000269636172b2413fa38d1db04f303bda324fadd372e3127261368e1 +size 67602 diff --git a/src/net/torvald/terrarum/worlddrawer/BlocksDrawer.kt b/src/net/torvald/terrarum/worlddrawer/BlocksDrawer.kt index c010402b9..c60b5efd1 100644 --- a/src/net/torvald/terrarum/worlddrawer/BlocksDrawer.kt +++ b/src/net/torvald/terrarum/worlddrawer/BlocksDrawer.kt @@ -64,6 +64,7 @@ internal object BlocksDrawer { val tileItemWallEmissive: TextureRegionPack val tilesGlow: TextureRegionPack val tilesEmissive: TextureRegionPack + val nullTex = Texture(1, 1, Pixmap.Format.RGBA8888); //val tileItemWall = Image(TILE_SIZE * 16, TILE_SIZE * GameWorld.TILES_SUPPORTED / 16) // 4 MB @@ -74,6 +75,7 @@ internal object BlocksDrawer { val ORES = GameWorld.ORES val FLUID = -2 val OCCLUSION = 31337 + val BLURMAP = 31338 private const val OCCLUSION_TILE_NUM_BASE = 16 @@ -96,9 +98,11 @@ 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 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) + private var blurTilesBuffer: Pixmap = Pixmap(1, 1, Pixmap.Format.RGBA8888) private lateinit var tilesQuad: Mesh private val shaderTiling = App.loadShaderFromClasspath("shaders/default.vert", "shaders/tiling.frag") @@ -283,8 +287,6 @@ internal object BlocksDrawer { batch.projectionMatrix = camera.combined } - private val testTexture = Texture(Gdx.files.internal("./assets/test_texture.tga")) - internal fun drawTerrain(projectionMatrix: Matrix4, drawGlow: Boolean, drawEmissive: Boolean = false) { gdxBlendNormalStraightAlpha() @@ -580,6 +582,22 @@ internal object BlocksDrawer { (breakage / maxHealth).coerceIn(0f, 1f).times(BREAKAGE_STEPS).roundToInt() 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), + ) + /*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) + } + if (renderTag.maskType >= CreateTileAtlas.RenderTag.MASK_SUBTILE_GENERIC) { hash = getHashCoord(x, y, 268435456, mode, renderTag.tileNumber) @@ -1057,6 +1075,7 @@ internal object BlocksDrawer { ORES -> oreTilesBuffer FLUID -> fluidTilesBuffer OCCLUSION -> occlusionBuffer + BLURMAP -> blurMap else -> throw IllegalArgumentException() } @@ -1073,6 +1092,7 @@ internal object BlocksDrawer { ORES -> oreTilesBuffer FLUID -> fluidTilesBuffer OCCLUSION -> occlusionBuffer + BLURMAP -> blurMap else -> throw IllegalArgumentException() } @@ -1084,7 +1104,8 @@ internal object BlocksDrawer { private var _tilesBufferAsTex: Texture = Texture(1, 1, Pixmap.Format.RGBA8888) private var _tilesBufferAsTex2: Texture = Texture(1, 1, Pixmap.Format.RGBA8888) - private val occlusionIntensity = 0.22222222f // too low value and dark-coloured walls won't darken enough + 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 fun renderUsingBuffer(mode: Int, projectionMatrix: Matrix4, drawGlow: Boolean, drawEmissive: Boolean) { //Gdx.gl.glClearColor(.094f, .094f, .094f, 0f) @@ -1096,7 +1117,7 @@ internal object BlocksDrawer { val tileAtlas = when (mode) { - TERRAIN, ORES, WALL, OCCLUSION, FLUID -> tilesTerrain + TERRAIN, ORES, WALL, OCCLUSION, FLUID, BLURMAP -> tilesTerrain else -> throw IllegalArgumentException() } val sourceBuffer = when(mode) { @@ -1108,9 +1129,8 @@ internal object BlocksDrawer { else -> throw IllegalArgumentException() } val vertexColour = when (mode) { - TERRAIN, ORES, FLUID, OCCLUSION -> Color.WHITE WALL -> WALL_OVERLAY_COLOUR - else -> throw IllegalArgumentException() + else -> Color.WHITE } @@ -1130,6 +1150,19 @@ internal object BlocksDrawer { } } + // 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 colMain = colRaw.toInt() + + blurTilesBuffer.setColor(colMain) + blurTilesBuffer.drawPixel(x, y) + } + } + } + _tilesBufferAsTex.dispose() _tilesBufferAsTex = Texture(tilesBuffer) @@ -1139,25 +1172,27 @@ internal object BlocksDrawer { _tilesBufferAsTex2 = Texture(tilesBuffer2) _tilesBufferAsTex2.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest) + _blurTilesBuffer.dispose() + _blurTilesBuffer = Texture(blurTilesBuffer) + _blurTilesBuffer.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest) + if (drawEmissive) { + nullTex.bind(4) _tilesBufferAsTex2.bind(3) _tilesBufferAsTex.bind(2) tilesEmissive.texture.bind(1) tilesEmissive.texture.bind(0) // for some fuck reason, it must be bound as last } else if (drawGlow) { + nullTex.bind(4) _tilesBufferAsTex2.bind(3) _tilesBufferAsTex.bind(2) tilesGlow.texture.bind(1) tilesGlow.texture.bind(0) // for some fuck reason, it must be bound as last } else { - // bind map for deblocking - if (mode == TERRAIN || mode == WALL) { - blurmapFBO.colorBufferTexture.bind(4) - } - + _blurTilesBuffer.bind(4) _tilesBufferAsTex2.bind(3) _tilesBufferAsTex.bind(2) tilesTerrainNext.texture.bind(1) @@ -1221,12 +1256,15 @@ internal object BlocksDrawer { oreTilesBuffer = UnsafeLong2D(tilesInHorizontal, tilesInVertical) fluidTilesBuffer = UnsafeLong2D(tilesInHorizontal, tilesInVertical) occlusionBuffer = UnsafeLong2D(tilesInHorizontal, tilesInVertical) + blurMap = UnsafeLong2D(tilesInHorizontal, tilesInVertical) tempRenderTypeBuffer = UnsafeLong2D(hTilesInHorizontal, hTilesInVertical) tilesBuffer.dispose() tilesBuffer = Pixmap(tilesInHorizontal, tilesInVertical, Pixmap.Format.RGBA8888) tilesBuffer2.dispose() tilesBuffer2 = Pixmap(tilesInHorizontal, tilesInVertical, Pixmap.Format.RGBA8888) + blurTilesBuffer.dispose() + blurTilesBuffer = Pixmap(tilesInHorizontal, tilesInVertical, Pixmap.Format.RGBA8888) } if (oldScreenW != screenW || oldScreenH != screenH) { @@ -1294,17 +1332,21 @@ internal object BlocksDrawer { tileItemWallEmissive.dispose() tilesBuffer.dispose() tilesBuffer2.dispose() + blurTilesBuffer.dispose() _tilesBufferAsTex.dispose() _tilesBufferAsTex2.dispose() + _blurTilesBuffer.dispose() tilesQuad.tryDispose() shaderTiling.dispose() shaderDeblock.dispose() + nullTex.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 (::blurMap.isInitialized) blurMap.destroy() if (::tempRenderTypeBuffer.isInitialized) tempRenderTypeBuffer.destroy() if (::batch.isInitialized) batch.tryDispose() diff --git a/src/net/torvald/terrarum/worlddrawer/CreateTileAtlas.kt b/src/net/torvald/terrarum/worlddrawer/CreateTileAtlas.kt index a25781bdd..977fd0592 100644 --- a/src/net/torvald/terrarum/worlddrawer/CreateTileAtlas.kt +++ b/src/net/torvald/terrarum/worlddrawer/CreateTileAtlas.kt @@ -39,7 +39,7 @@ import kotlin.math.sqrt class CreateTileAtlas { companion object { - val WALL_OVERLAY_COLOUR = Color(.65f, .65f, .65f, 1f) + val WALL_OVERLAY_COLOUR = Color(.72f, .72f, .72f, 1f) val W_SUBTILE_GENERIC = 104 val W_SUBTILE_GRASS = 168 @@ -59,7 +59,7 @@ class CreateTileAtlas { ) } - var MAX_TEX_SIZE = 1024; private set + var MAX_TEX_SIZE = 2048; private set var TILES_IN_X = MAX_TEX_SIZE / TILE_SIZE; private set var SUBTILES_IN_X = MAX_TEX_SIZE / SUBTILE_SIZE; private set @@ -96,7 +96,7 @@ class CreateTileAtlas { // 16 tiles are reserved for internal use: solid black, solid white, breakage stages. // 0th tile is complete transparent tile and is also a BlockID of zero: air. - private var atlasCursor = 64 // 64 predefined tiles. The normal blocks (e.g. Air) should start from this number + private var atlasCursor = 66 // 66 predefined tiles. The normal blocks (e.g. Air) should start from this number private val atlasInit = "./assets/graphics/blocks/init.tga" private var itemSheetCursor = 16 @@ -260,7 +260,7 @@ class CreateTileAtlas { } // test print -// PixmapIO2.writeTGA(Gdx.files.absolute("${App.defaultDir}/atlas.tga"), atlas, false) + PixmapIO2.writeTGA(Gdx.files.absolute("${App.defaultDir}/atlas.tga"), atlas, false) // PixmapIO2.writeTGA(Gdx.files.absolute("${AppLoader.defaultDir}/atlasGlow.tga"), atlasGlow, false) // PixmapIO2.writeTGA(Gdx.files.absolute("${App.defaultDir}/atlas_0.tga"), atlasPrevernal, false) diff --git a/src/shaders/tiling.frag b/src/shaders/tiling.frag index 598dd15d5..91697a6eb 100644 --- a/src/shaders/tiling.frag +++ b/src/shaders/tiling.frag @@ -89,6 +89,7 @@ vec2 uvFlipRot(int op, vec2 uv) { const vec4 _four = vec4(1.0 / 4.0); const vec4 _three = vec4(1.0 / 3.0); const vec4 _two = vec4(1.0 / 2.0); +const vec4 zero = vec4(0.0); const float blur = 1.0; vec2 blurU = vec2(0.0, -blur); vec2 blurD = vec2(0.0, +blur); @@ -103,7 +104,11 @@ vec4[2] getTileNumbersFromMap(vec2 fragCoord) { return vec4[2](tileFromMap, tileFromMap2); } -vec4[2] getFragColorForOnscreenCoord(vec2 fragCoord) { +vec4 getBlurmapNumbersFromMap(vec2 fragCoord) { + return texture(deblockingMap, fragCoord / overscannedScreenDimension);// raw tile number +} + +vec4[3] getFragColorForOnscreenCoord(vec2 fragCoord) { vec4[] tileFromMap = getTileNumbersFromMap(fragCoord); ivec3 tbf = _colToInt(tileFromMap[0], tileFromMap[1]); int tile = tbf.x; @@ -114,6 +119,12 @@ vec4[2] getFragColorForOnscreenCoord(vec2 fragCoord) { ivec2 tileQ = tileXYnQ.zw; ivec2 breakageXY = tileNumberToXY(2*(breakage + 5)).xy; // +5 is hard-coded constant that depends on the contents of the atlas + vec4 blurFromMap = getBlurmapNumbersFromMap(fragCoord); + ivec3 tbf2 = _colToInt(blurFromMap, zero); + int blurTileNum = tbf2.x; + ivec4 blurXYnQ = tileNumberToXY(blurTileNum); + ivec2 blurXY = blurXYnQ.xy; + // calculate the UV coord value for texture sampling // // don't really need highp here; read the GLES spec @@ -121,11 +132,13 @@ vec4[2] getFragColorForOnscreenCoord(vec2 fragCoord) { vec2 uvCoordForTile1 = mod(fragCoord, tileSizeInPx) * _tileSizeInPx * _tilesInAtlas;// 0..0.00390625 regardless of tile position in atlas vec2 uvCoordOffsetTile = tileXY * _tilesInAtlas; // where the tile starts in the atlas, using uv coord (0..1) vec2 uvCoordOffsetBreakage = (breakageXY + tileQ) * _tilesInAtlas; + vec2 uvCoordOffsetBlurmap = blurXY * _tilesInAtlas; // get final UV coord for the actual sampling // vec2 finalUVCoordForTile = uvCoordForTile + uvCoordOffsetTile;// where we should be actually looking for in atlas, using UV coord (0..1) vec2 finalUVCoordForBreakage = uvCoordForTile1 + uvCoordOffsetBreakage; + vec2 finalUVCoordForBlurmap = uvCoordForTile1 + uvCoordOffsetBlurmap; // blending a breakage tex with main tex // @@ -134,7 +147,8 @@ vec4[2] getFragColorForOnscreenCoord(vec2 fragCoord) { return vec4[]( mix(tileCol, tileAltCol, tilesBlend), - finalUVCoordForBreakage.xyxy + texture(tilesAtlas, finalUVCoordForBreakage), + texture(tilesAtlas, finalUVCoordForBlurmap) ); } @@ -169,29 +183,28 @@ vec4 getFragColorForOnscreenCoord1(vec2 fragCoord) { void main() { vec2 fragCoord = gl_FragCoord.xy + cameraTranslation + haalf; // manually adding half-int to the flipped gl_FragCoord: this avoids driver bug present on the Asahi Linux and possibly (but unlikely) others - vec4[] fv = getFragColorForOnscreenCoord(fragCoord); - vec2 finalUVCoordForBreakage = fv[1].xy; + vec4[] tile_breakage_blur = getFragColorForOnscreenCoord(fragCoord); - vec4 finalTileC = fv[0]; - vec4 finalTileL = getFragColorForOnscreenCoord1(fragCoord + blurL); - vec4 finalTileR = getFragColorForOnscreenCoord1(fragCoord + blurR); - vec4 finalTileU = getFragColorForOnscreenCoord1(fragCoord + blurU); - vec4 finalTileD = getFragColorForOnscreenCoord1(fragCoord + blurD); + vec4 tileC = tile_breakage_blur[0]; + vec4 tileL = getFragColorForOnscreenCoord1(fragCoord + blurL); + vec4 tileR = getFragColorForOnscreenCoord1(fragCoord + blurR); + vec4 tileU = getFragColorForOnscreenCoord1(fragCoord + blurU); + vec4 tileD = getFragColorForOnscreenCoord1(fragCoord + blurD); - vec4 blurH = (finalTileC + finalTileL + finalTileR) * _three; - vec4 blurV = (finalTileC + finalTileU + finalTileD) * _three; - - vec4 mapCol = vec4(1.0, 0.0, 1.0, finalTileC.a);//texture(u_blurmap, v_texCoords); + vec4 blurH = (tileC + tileC + tileL + tileR) * _four; + vec4 blurV = (tileC + tileC + tileU + tileD) * _four; + vec4 blurPower = tile_breakage_blur[2]; vec4 finalTile = mix( - mix(finalTileC, blurH, mapCol.x), - mix(finalTileC, blurV, mapCol.y), + mix(tileC, blurH, blurPower.x), + mix(tileC, blurV, blurPower.y), 0.5 ); - vec4 finalBreakage = drawBreakage * texture(tilesAtlas, finalUVCoordForBreakage); // drawBreakeage = 0 to not draw, = 1 to draw + vec4 finalBreakage = drawBreakage * tile_breakage_blur[1]; // drawBreakeage = 0 to not draw, = 1 to draw vec4 finalColor = fma(mix(finalTile, finalBreakage, finalBreakage.a), bc.xxxy, finalTile * bc.yyyx); fragColor = mix(colourFilter, colourFilter * finalColor, mulBlendIntensity); +// fragColor = blurPower; } diff --git a/work_files/graphics/terrain/terrain_variable_subtiling_full.kra b/work_files/graphics/terrain/terrain_variable_subtiling_full.kra index 54a1200c2..3f1141b3e 100644 --- a/work_files/graphics/terrain/terrain_variable_subtiling_full.kra +++ b/work_files/graphics/terrain/terrain_variable_subtiling_full.kra @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:5875f0a3f9dfd3cb87def3d131d77e73b01ccb6a01b351e2423efa227f7fa198 -size 1470732 +oid sha256:273ad3fd52122da5fb7457596de9155c9f0d709e8057603a243659bc614e12ea +size 1498483