diff --git a/assets/tiling.frag b/assets/tiling.frag index 7e1f0ad64..e3c21e195 100644 --- a/assets/tiling.frag +++ b/assets/tiling.frag @@ -21,7 +21,7 @@ uniform sampler2D tilemap; // MUST be RGBA8888 uniform sampler2D tilesAtlas; uniform sampler2D backgroundTexture; -uniform ivec2 tileInAtlas = ivec2(256, 256); +uniform ivec2 tilesInAtlas = ivec2(256, 256); uniform ivec2 atlasTexSize = ivec2(4096, 4096); @@ -29,9 +29,8 @@ uniform vec2 cameraTranslation = vec2(0, 0); // Y-flipped uniform int tileSizeInPx = 16; - ivec2 getTileXY(int tileNumber) { - return ivec2(tileNumber % int(tileInAtlas.x), tileNumber / int(tileInAtlas.x)); + return ivec2(tileNumber % int(tilesInAtlas.x), tileNumber / int(tilesInAtlas.x)); } int getTileFromColor(vec4 color) { @@ -61,7 +60,7 @@ void main() { vec2 coordInTile = mod(pxCoord, tileSizeInPx) / tileSizeInPx; // 0..1 regardless of tile position in atlas - highp vec2 singleTileSizeInUV = vec2(1) / tileInAtlas; // constant 0.00390625 + highp vec2 singleTileSizeInUV = vec2(1) / tilesInAtlas; // constant 0.00390625 highp vec2 uvCoordForTile = coordInTile * singleTileSizeInUV; // 0..0.00390625 regardless of tile position in atlas highp vec2 uvCoordOffset = (tileXY + cameraTranslation / tileSizeInPx) * singleTileSizeInUV; // where the tile starts in the atlas, using uv coord (0..1) @@ -69,5 +68,5 @@ void main() { highp vec2 finalUVCoordForTile = uvCoordForTile + uvCoordOffset;// where we should be actually looking for in atlas, using UV coord (0..1) - gl_FragColor = texture2D(tilesAtlas, finalUVCoordForTile); + gl_FragColor = v_color * texture2D(tilesAtlas, finalUVCoordForTile); } diff --git a/src/net/torvald/terrarum/GlslTilingTest.kt b/src/net/torvald/terrarum/GlslTilingTest.kt index e4c961ee1..aaadc7ef9 100644 --- a/src/net/torvald/terrarum/GlslTilingTest.kt +++ b/src/net/torvald/terrarum/GlslTilingTest.kt @@ -153,6 +153,9 @@ object GlslTilingTest : ApplicationAdapter() { shader.setUniformi("tilemapDimension", tilesBuffer.width, tilesBuffer.height) shader.setUniformf("tilesInAxes", tilesInHorizontal, tilesInVertical) shader.setUniformf("cameraTranslation", cameraX, cameraY) + shader.setUniformi("tileSizeInPx", 16) + shader.setUniformi("tilesInAtlas", 256, 256) //depends on the tile atlas + shader.setUniformi("atlasTexSize", 4096, 4096) //depends on the tile atlas tilesQuad.render(shader, GL20.GL_TRIANGLES) shader.end() tilesBufferAsTex.dispose() diff --git a/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt b/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt index 42737298f..6ae62819b 100644 --- a/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt +++ b/src/net/torvald/terrarum/gameactors/ActorWithPhysics.kt @@ -1466,6 +1466,7 @@ inline fun Double.floorInt() = Math.floor(this).toInt() inline fun Float.floorInt() = FastMath.floor(this) inline fun Float.floor() = FastMath.floor(this).toFloat() inline fun Double.ceilInt() = Math.ceil(this).toInt() +inline fun Float.ceil(): Float = FastMath.ceil(this).toFloat() inline fun Float.ceilInt() = FastMath.ceil(this) inline fun Double.round() = Math.round(this).toDouble() inline fun Double.floor() = Math.floor(this) diff --git a/src/net/torvald/terrarum/worlddrawer/BlocksDrawerNew.kt b/src/net/torvald/terrarum/worlddrawer/BlocksDrawerNew.kt index a9d478cf5..2f89877b2 100644 --- a/src/net/torvald/terrarum/worlddrawer/BlocksDrawerNew.kt +++ b/src/net/torvald/terrarum/worlddrawer/BlocksDrawerNew.kt @@ -10,6 +10,7 @@ import net.torvald.terrarum.gameworld.PairedMapLayer import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.blockproperties.BlockCodex import net.torvald.terrarum.* +import net.torvald.terrarum.gameactors.ceilInt import net.torvald.terrarum.gameactors.roundInt import net.torvald.terrarum.itemproperties.ItemCodex.ITEM_TILES import net.torvald.terrarum.worlddrawer.WorldCamera.x @@ -65,6 +66,12 @@ object BlocksDrawerNew { private val GZIP_READBUF_SIZE = 8192 + + private lateinit var terrainTilesBuffer: Array + private lateinit var wallTilesBuffer: Array + private lateinit var wireTilesBuffer: Array + + init { // hard-coded as tga.gz val gzFileList = listOf("blocks/terrain.tga.gz", "blocks/wire.tga.gz") @@ -356,6 +363,7 @@ object BlocksDrawerNew { blendNormal() drawTiles(batch, WALL, false, wallOverlayColour) + renderUsingBuffer(WALL) } fun renderTerrain(batch: SpriteBatch) { @@ -365,6 +373,7 @@ object BlocksDrawerNew { blendNormal() drawTiles(batch, TERRAIN, false, Color.WHITE) // regular tiles + renderUsingBuffer(TERRAIN) } fun renderFront(batch: SpriteBatch, drawWires: Boolean) { @@ -374,9 +383,11 @@ object BlocksDrawerNew { blendMul() drawTiles(batch, TERRAIN, true, Color.WHITE) // blendmul tiles + renderUsingBuffer(TERRAIN) if (drawWires) { drawTiles(batch, WIRE, false, Color.WHITE) + renderUsingBuffer(WIRE) } blendNormal() @@ -414,20 +425,21 @@ object BlocksDrawerNew { LightmapRenderer.getHighestRGB(x - 1, y + 1) ?: 0f >= tileDrawLightThreshold ) + /** + * Writes to buffer. Actual draw code must be called after this operation. + */ private fun drawTiles(batch: SpriteBatch, mode: Int, drawModeTilesBlendMul: Boolean, color: Color) { - val for_y_start = y / TILE_SIZE - val for_y_end = BlocksDrawer.clampHTile(for_y_start + (height / TILE_SIZE) + 2) + val for_y_start = WorldCamera.y / TILE_SIZE + val for_y_end = clampHTile(for_y_start + (WorldCamera.height / TILE_SIZE) + 2) - val for_x_start = x / TILE_SIZE - 1 - val for_x_end = for_x_start + (width / TILE_SIZE) + 3 + val for_x_start = WorldCamera.x / TILE_SIZE - 1 + val for_x_end = for_x_start + (WorldCamera.width / TILE_SIZE) + 3 val originalBatchColour = batch.color.cpy() batch.color = color // loop for (y in for_y_start..for_y_end) { - var zeroTileCounter = 0 - for (x in for_x_start..for_x_end) { val thisTile: Int? @@ -448,21 +460,9 @@ object BlocksDrawerNew { if (!hasLightNearby(x, y)) { // draw black patch - zeroTileCounter += 1 // unused for now - - // temporary solution; FIXME bad scanlines bug - batch.color = Color.BLACK - batch.fillRect(x * TILE_SIZEF, y * TILE_SIZEF, TILE_SIZEF, TILE_SIZEF) + writeToBuffer(mode, x, y, 2, 0) } else { - // commented out; FIXME bad scanlines bug - if (zeroTileCounter > 0) { - /*batch.color = Color.BLACK - batch.fillRect(x * TILE_SIZEF, y * TILE_SIZEF, -zeroTileCounter * TILE_SIZEF, TILE_SIZEF) - batch.color = color - zeroTileCounter = 0*/ - } - val nearbyTilesInfo: Int if (isPlatform(thisTile)) { @@ -494,16 +494,14 @@ object BlocksDrawerNew { if (drawModeTilesBlendMul) { if (BlocksDrawer.isBlendMul(thisTile)) { batch.color = color - drawTile(batch, mode, x, y, thisTileX, thisTileY) - // TODO: store to the buffer (floatArray) instead of draw right away + writeToBuffer(mode, x, y, thisTileX, thisTileY) } } else { // do NOT add "if (!isBlendMul(thisTile))"! // or else they will not look like they should be when backed with wall batch.color = color - drawTile(batch, mode, x, y, thisTileX, thisTileY) - // TODO: store to the buffer (floatArray) instead of draw right away + writeToBuffer(mode, x, y, thisTileX, thisTileY) } // draw a breakage @@ -514,8 +512,7 @@ object BlocksDrawerNew { // actual drawing if (stage > 0) { batch.color = color - drawTile(batch, mode, x, y, 5 + stage, 0) - // TODO: store to the buffer (floatArray) instead of draw right away + writeToBuffer(mode, x, y, 5 + stage, 0) } } @@ -525,17 +522,6 @@ object BlocksDrawerNew { } catch (e: NullPointerException) { // do nothing. WARNING: This exception handling may hide erratic behaviour completely. } - - - // hit the end of the current scanline - // FIXME bad scanlines bug - /*if (x == for_x_end) { - val x = x + 1 // because current tile is also counted - batch.color = Color.BLACK - batch.fillRect(x * TILE_SIZEF, y * TILE_SIZEF, -zeroTileCounter * TILE_SIZEF, TILE_SIZEF) - batch.color = color - zeroTileCounter = 0 - }*/ } } @@ -671,21 +657,44 @@ object BlocksDrawerNew { return 7 } - private fun drawTile(batch: SpriteBatch, mode: Int, tilewisePosX: Int, tilewisePosY: Int, sheetX: Int, sheetY: Int) { - if (mode == TERRAIN || mode == WALL) - batch.draw( - tilesTerrain.get(sheetX, sheetY), - tilewisePosX * TILE_SIZEF, - tilewisePosY * TILE_SIZEF - ) - else if (mode == WIRE) - batch.draw( - tilesWire.get(sheetX, sheetY), - tilewisePosX * TILE_SIZEF, - tilewisePosY * TILE_SIZEF - ) - else - throw IllegalArgumentException() + /** + * Raw format of RGBA8888, where RGB portion actually encodes the absolute tile number and A is always 255. + * + * @return Raw colour bits in RGBA8888 format + */ + private fun sheetXYToTilemapColour(mode: Int, sheetX: Int, sheetY: Int): Int = when (mode) { + TERRAIN, WALL -> (tilesTerrain.tileW * sheetY + sheetX).shl(8) or 255 + WIRE -> (tilesWire.tileW * sheetY + sheetX).shl(8) or 255 + else -> throw IllegalArgumentException() + } + + private fun writeToBuffer(mode: Int, bufferPosX: Int, bufferPosY: Int, sheetX: Int, sheetY: Int) { + terrainTilesBuffer[bufferPosY][bufferPosX] = sheetXYToTilemapColour(mode, sheetX, sheetY) + } + + private fun renderUsingBuffer(mode: Int) { + // TODO TODO TODO GlslTilingTest + } + + private var oldScreenW = 0 + private var oldScreenH = 0 + + fun resize(screenW: Int, screenH: Int) { + val tilesInHorizontal = (screenW.toFloat() / TILE_SIZE).ceilInt() + 1 + val tilesInVertical = (screenH.toFloat() / TILE_SIZE).ceilInt() + 1 + + val oldTH = (oldScreenW.toFloat() / TILE_SIZE).ceilInt() + 1 + val oldTV = (oldScreenH.toFloat() / TILE_SIZE).ceilInt() + 1 + + // only update if it's really necessary + if (oldTH != tilesInHorizontal || oldTV != tilesInVertical) { + terrainTilesBuffer = Array(tilesInVertical, { kotlin.IntArray(tilesInHorizontal) }) + wallTilesBuffer = Array(tilesInVertical, { kotlin.IntArray(tilesInHorizontal) }) + wireTilesBuffer = Array(tilesInVertical, { kotlin.IntArray(tilesInHorizontal) }) + } + + oldScreenW = screenW + oldScreenH = screenH } fun clampH(x: Int): Int { diff --git a/src/net/torvald/terrarum/worlddrawer/BlocksDrawer_old.kt b/src/net/torvald/terrarum/worlddrawer/BlocksDrawer_old.kt index 65ec4668a..12c5fccf9 100644 --- a/src/net/torvald/terrarum/worlddrawer/BlocksDrawer_old.kt +++ b/src/net/torvald/terrarum/worlddrawer/BlocksDrawer_old.kt @@ -415,11 +415,11 @@ object BlocksDrawer { ) private fun drawTiles(batch: SpriteBatch, mode: Int, drawModeTilesBlendMul: Boolean, color: Color) { - val for_y_start = y / TILE_SIZE - val for_y_end = BlocksDrawer.clampHTile(for_y_start + (height / TILE_SIZE) + 2) + val for_y_start = WorldCamera.y / TILE_SIZE + val for_y_end = clampHTile(for_y_start + (WorldCamera.height / TILE_SIZE) + 2) - val for_x_start = x / TILE_SIZE - 1 - val for_x_end = for_x_start + (width / TILE_SIZE) + 3 + val for_x_start = WorldCamera.x / TILE_SIZE - 1 + val for_x_end = for_x_start + (WorldCamera.width / TILE_SIZE) + 3 val originalBatchColour = batch.color.cpy() batch.color = color