now I can't even tell if it's working as intended or not

This commit is contained in:
minjaesong
2017-08-30 22:16:10 +09:00
parent d8fe375c0c
commit 959019f9b3
6 changed files with 169 additions and 76 deletions

View File

@@ -24,11 +24,15 @@ uniform sampler2D backgroundTexture;
uniform ivec2 tilesInAtlas = ivec2(256, 256);
uniform ivec2 atlasTexSize = ivec2(4096, 4096);
uniform vec4 colourFilter = vec4(1, 1, 1, 1);
uniform vec2 cameraTranslation = vec2(0, 0); // Y-flipped
uniform ivec2 cameraTranslation = ivec2(0, 0);
uniform int tileSizeInPx = 16;
vec4 nocolour = vec4(0,0,0,0);
ivec2 getTileXY(int tileNumber) {
return ivec2(tileNumber % int(tilesInAtlas.x), tileNumber / int(tilesInAtlas.x));
}
@@ -47,7 +51,7 @@ void main() {
// default gl_FragCoord takes half-integer (represeting centre of the pixel) -- could be useful for phys solver?
// This one, however, takes exact integer by rounding down. //
vec2 overscannedScreenDimension = tilesInAxes * tileSizeInPx; // one used by the tileFromMap
vec2 flippedFragCoord = vec2(gl_FragCoord.x, screenDimension.y - gl_FragCoord.y); // NO IVEC2!!; this flips Y
vec2 flippedFragCoord = vec2(gl_FragCoord.x, screenDimension.y - gl_FragCoord.y) + cameraTranslation; // NO IVEC2!!; this flips Y
vec2 pxCoord = flippedFragCoord.xy;
@@ -63,10 +67,13 @@ void main() {
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)
highp vec2 uvCoordOffset = tileXY * singleTileSizeInUV; // where the tile starts in the atlas, using uv coord (0..1)
highp vec2 finalUVCoordForTile = uvCoordForTile + uvCoordOffset;// where we should be actually looking for in atlas, using UV coord (0..1)
gl_FragColor = v_color * texture2D(tilesAtlas, finalUVCoordForTile);
if (tileXY.x == 0 && tileXY.y == 0)
gl_FragColor = nocolour;
else
gl_FragColor = colourFilter * texture2D(tilesAtlas, finalUVCoordForTile);
}

View File

@@ -147,6 +147,7 @@ object GlslTilingTest : ApplicationAdapter() {
shader.begin()
shader.setUniformMatrix("u_projTrans", batch.projectionMatrix)//camera.combined)
//shader.setUniformf("colourFilter", Color.RED)
shader.setUniformf("screenDimension", Gdx.graphics.width.toFloat(), Gdx.graphics.height.toFloat())
shader.setUniformi("tilesAtlas", 1)
shader.setUniformi("tilemap", 2)

View File

@@ -529,6 +529,9 @@ class Ingame(val batch: SpriteBatch) : Screen {
private fun renderGame(batch: SpriteBatch) {
Gdx.gl.glClearColor(.094f, .094f, .094f, 0f)
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT)
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D)
Gdx.gl.glEnable(GL20.GL_BLEND)
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA)
//camera.position.set(-WorldCamera.x.toFloat(), -WorldCamera.y.toFloat(), 0f) // make camara work
//camera.position.set(0f, 0f, 0f) // make camara work
@@ -1350,6 +1353,8 @@ class Ingame(val batch: SpriteBatch) : Screen {
*/
override fun resize(width: Int, height: Int) {
BlocksDrawer.resize(Terrarum.WIDTH, Terrarum.HEIGHT)
worldDrawFrameBuffer.dispose()
worldDrawFrameBuffer = FrameBuffer(worldFBOformat, Terrarum.WIDTH, Terrarum.HEIGHT, false)
worldGlowFrameBuffer.dispose()

View File

@@ -199,8 +199,13 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
}
fun updateScreen(delta: Float) {
Gdx.graphics.setTitle(TerrarumAppLoader.GAME_NAME +
" — F: ${Gdx.graphics.framesPerSecond} (${Terrarum.TARGET_INTERNAL_FPS})" +
" — M: ${Terrarum.memInUse}M / ${Terrarum.memTotal}M / ${Terrarum.memXmx}M"
)
demoWorld.globalLight = WeatherMixer.globalLightNow
demoWorld.updateWorldTime(delta)
//demoWorld.updateWorldTime(delta)
WeatherMixer.update(delta, cameraPlayer)
cameraPlayer.update(delta)
// worldcamera update AFTER cameraplayer in this case; the other way is just an exception for actual ingame SFX
@@ -222,7 +227,11 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
//camera.setToOrtho(true, Terrarum.WIDTH.toFloat(), Terrarum.HEIGHT.toFloat())
// render world
batch.inUse {
BlocksDrawer.renderWall(batch)
BlocksDrawer.renderTerrain(batch)
//BlocksDrawer.renderFront(batch, false)
/*batch.inUse {
setCameraPosition(0f, 0f)
batch.color = Color.WHITE
batch.shader = null
@@ -239,7 +248,7 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
renderMenus()
renderOverlayTexts()
}
}*/
}
private fun renderDemoWorld() {
@@ -260,9 +269,19 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
batch.shader = null
blendNormal()
batch.end()
BlocksDrawer.renderWall(batch)
BlocksDrawer.renderTerrain(batch)
BlocksDrawer.renderFront(batch, false)
batch.begin()
FeaturesDrawer.drawEnvOverlay(batch)
@@ -331,6 +350,7 @@ class TitleScreen(val batch: SpriteBatch) : Screen {
// Set up viewport when window is resized
initViewPort(Terrarum.WIDTH, Terrarum.HEIGHT)
BlocksDrawer.resize(Terrarum.WIDTH, Terrarum.HEIGHT)
if (loadDone) {
// resize UI by re-creating it (!!)

View File

@@ -1,10 +1,10 @@
package net.torvald.terrarum.worlddrawer
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
import com.badlogic.gdx.graphics.*
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.glutils.ShaderProgram
import com.badlogic.gdx.math.Matrix4
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.PairedMapLayer
import net.torvald.terrarum.blockproperties.Block
@@ -13,10 +13,6 @@ 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
import net.torvald.terrarum.worlddrawer.WorldCamera.y
import net.torvald.terrarum.worlddrawer.WorldCamera.height
import net.torvald.terrarum.worlddrawer.WorldCamera.width
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import java.io.BufferedOutputStream
import java.io.File
@@ -27,7 +23,7 @@ import java.util.zip.GZIPInputStream
/**
* Created by minjaesong on 16-01-19.
*/
object BlocksDrawerNew {
object BlocksDrawer {
lateinit var world: GameWorld
@@ -70,8 +66,12 @@ object BlocksDrawerNew {
private lateinit var terrainTilesBuffer: Array<IntArray>
private lateinit var wallTilesBuffer: Array<IntArray>
private lateinit var wireTilesBuffer: Array<IntArray>
private lateinit var tilesBuffer: Pixmap
private lateinit var tilesQuad: Mesh
private val shader = ShaderProgram(Gdx.files.internal("assets/4096.vert"), Gdx.files.internal("assets/tiling.frag"))
init {
// hard-coded as tga.gz
val gzFileList = listOf("blocks/terrain.tga.gz", "blocks/wire.tga.gz")
@@ -362,8 +362,8 @@ object BlocksDrawerNew {
*/
blendNormal()
drawTiles(batch, WALL, false, wallOverlayColour)
renderUsingBuffer(WALL)
drawTiles(WALL, false, wallOverlayColour)
renderUsingBuffer(WALL, batch.projectionMatrix)
}
fun renderTerrain(batch: SpriteBatch) {
@@ -372,8 +372,8 @@ object BlocksDrawerNew {
*/
blendNormal()
drawTiles(batch, TERRAIN, false, Color.WHITE) // regular tiles
renderUsingBuffer(TERRAIN)
drawTiles(TERRAIN, false, Color.WHITE) // regular tiles
renderUsingBuffer(TERRAIN, batch.projectionMatrix)
}
fun renderFront(batch: SpriteBatch, drawWires: Boolean) {
@@ -382,12 +382,12 @@ object BlocksDrawerNew {
*/
blendMul()
drawTiles(batch, TERRAIN, true, Color.WHITE) // blendmul tiles
renderUsingBuffer(TERRAIN)
drawTiles(TERRAIN, true, Color.WHITE) // blendmul tiles
renderUsingBuffer(TERRAIN, batch.projectionMatrix)
if (drawWires) {
drawTiles(batch, WIRE, false, Color.WHITE)
renderUsingBuffer(WIRE)
drawTiles(WIRE, false, Color.WHITE)
renderUsingBuffer(WIRE, batch.projectionMatrix)
}
blendNormal()
@@ -396,8 +396,9 @@ object BlocksDrawerNew {
private val tileDrawLightThreshold = 2f / LightmapRenderer.MUL
private fun canIHazRender(mode: Int, x: Int, y: Int) =
(world.getTileFrom(mode, x, y) != 0) // not an air tile
&&
//(world.getTileFrom(mode, x, y) != 0) // not an air tile
//&&
// for WALLs; else: ret true
if (mode == WALL) { // DRAW WHEN it is visible and 'is a lip'
( BlockCodex[world.getTileFromTerrain(x, y) ?: 0].isClear ||
@@ -428,15 +429,12 @@ object BlocksDrawerNew {
/**
* Writes to buffer. Actual draw code must be called after this operation.
*/
private fun drawTiles(batch: SpriteBatch, mode: Int, drawModeTilesBlendMul: Boolean, color: Color) {
private fun drawTiles(mode: Int, drawModeTilesBlendMul: Boolean, color: Color) {
val for_y_start = WorldCamera.y / TILE_SIZE
val for_y_end = clampHTile(for_y_start + (WorldCamera.height / TILE_SIZE) + 2)
val for_y_end = for_y_start + tilesBuffer.height - 1//clampHTile(for_y_start + (WorldCamera.height / TILE_SIZE) + 2)
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
val for_x_end = for_x_start + tilesBuffer.width - 1//for_x_start + (WorldCamera.width / TILE_SIZE) + 3
// loop
for (y in for_y_start..for_y_end) {
@@ -458,11 +456,11 @@ object BlocksDrawerNew {
try {
if (canIHazRender(mode, x, y)) {
if (!hasLightNearby(x, y)) {
// draw black patch
writeToBuffer(mode, x, y, 2, 0)
}
else {
//if (!hasLightNearby(x, y)) {
// // draw black patch
// writeToBuffer(mode, x - for_x_start, y - for_y_start, 2, 0)
//}
//else {
val nearbyTilesInfo: Int
if (isPlatform(thisTile)) {
@@ -492,46 +490,35 @@ object BlocksDrawerNew {
// draw a tile
if (drawModeTilesBlendMul) {
if (BlocksDrawer.isBlendMul(thisTile)) {
batch.color = color
writeToBuffer(mode, x, y, thisTileX, thisTileY)
if (isBlendMul(thisTile)) {
writeToBuffer(mode, x - for_x_start, y - for_y_start, 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
writeToBuffer(mode, x, y, thisTileX, thisTileY)
writeToBuffer(mode, x - for_x_start, y - for_y_start, thisTileX, thisTileY)
}
// draw a breakage
if (mode == TERRAIN || mode == WALL) {
/*if (mode == TERRAIN || mode == WALL) {
val breakage = if (mode == TERRAIN) world.getTerrainDamage(x, y) else world.getWallDamage(x, y)
val maxHealth = BlockCodex[world.getTileFromTerrain(x, y)].strength
val stage = (breakage / maxHealth).times(breakAnimSteps).roundInt()
// actual drawing
if (stage > 0) {
batch.color = color
writeToBuffer(mode, x, y, 5 + stage, 0)
writeToBuffer(mode, x - for_x_start, y - for_y_start, 5 + stage, 0)
}
}
}*/
} // end if (is illuminated)
//} // end if (is illuminated)
} // end if (not an air)
} catch (e: NullPointerException) {
// do nothing. WARNING: This exception handling may hide erratic behaviour completely.
}
}
}
// TODO: with the tiles buffer, draw tiles with tiling shader so that GPU would tile itself, COMPUTED IN PARALLEL!
batch.color = originalBatchColour
}
/**
@@ -586,10 +573,10 @@ object BlocksDrawerNew {
fun getNearbyTilesInfoWallSticker(x: Int, y: Int): Int {
val nearbyTiles = IntArray(4)
val NEARBY_TILE_KEY_BACK = NEARBY_TILE_KEY_UP
nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(TERRAIN, x - 1, y) ?: Block.NULL
nearbyTiles[NEARBY_TILE_KEY_LEFT] = world.getTileFrom(TERRAIN, x - 1, y) ?: Block.NULL
nearbyTiles[NEARBY_TILE_KEY_RIGHT] = world.getTileFrom(TERRAIN, x + 1, y) ?: Block.NULL
nearbyTiles[NEARBY_TILE_KEY_DOWN] = world.getTileFrom(TERRAIN, x , y + 1) ?: Block.NULL
nearbyTiles[NEARBY_TILE_KEY_BACK] = world.getTileFrom(WALL, x , y) ?: Block.NULL
nearbyTiles[NEARBY_TILE_KEY_DOWN] = world.getTileFrom(TERRAIN, x , y + 1) ?: Block.NULL
nearbyTiles[NEARBY_TILE_KEY_BACK] = world.getTileFrom(WALL, x , y) ?: Block.NULL
try {
if (BlockCodex[nearbyTiles[NEARBY_TILE_KEY_DOWN]].isSolid)
@@ -663,8 +650,8 @@ object BlocksDrawerNew {
* @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
TERRAIN, WALL -> (tilesTerrain.horizontalCount * sheetY + sheetX).shl(8) or 255
WIRE -> (tilesWire.horizontalCount * sheetY + sheetX).shl(8) or 255
else -> throw IllegalArgumentException()
}
@@ -672,8 +659,66 @@ object BlocksDrawerNew {
terrainTilesBuffer[bufferPosY][bufferPosX] = sheetXYToTilemapColour(mode, sheetX, sheetY)
}
private fun renderUsingBuffer(mode: Int) {
// TODO TODO TODO GlslTilingTest
private fun renderUsingBuffer(mode: Int, projectionMatrix: Matrix4) {
Gdx.gl.glEnable(GL20.GL_TEXTURE_2D)
Gdx.gl.glEnable(GL20.GL_BLEND)
Gdx.gl.glBlendFunc(GL20.GL_SRC_ALPHA, GL20.GL_ONE_MINUS_SRC_ALPHA)
val tilesInHorizontal = tilesBuffer.width
val tilesInVertical = tilesBuffer.height
val tileAtlas = when (mode) {
TERRAIN, WALL -> tilesTerrain
WIRE -> tilesWire
else -> throw IllegalArgumentException()
}
val sourceBuffer = when(mode) {
TERRAIN -> terrainTilesBuffer
WALL -> wallTilesBuffer
WIRE -> wireTilesBuffer
else -> throw IllegalArgumentException()
}
val vertexColour = when (mode) {
TERRAIN, WIRE -> Color.WHITE
WALL -> wallOverlayColour
else -> throw IllegalArgumentException()
}
// write to colour buffer
for (y in 0 until tilesBuffer.height) {
for (x in 0 until tilesBuffer.width) {
tilesBuffer.setColor(0)
tilesBuffer.drawPixel(x, y)
val color = sourceBuffer[y][x]
tilesBuffer.setColor(color)
tilesBuffer.drawPixel(x, y)
}
}
val tilesBufferAsTex = Texture(tilesBuffer)
tilesBufferAsTex.setFilter(Texture.TextureFilter.Nearest, Texture.TextureFilter.Nearest)
tilesBufferAsTex.bind(2)
tileAtlas.texture.bind(1) // for some fuck reason, it must be bound as last
shader.begin()
shader.setUniformMatrix("u_projTrans", projectionMatrix)//camera.combined)
shader.setUniformf("colourFilter", vertexColour)
shader.setUniformf("screenDimension", Gdx.graphics.width.toFloat(), Gdx.graphics.height.toFloat())
shader.setUniformi("tilesAtlas", 1)
shader.setUniformi("tilemap", 2)
shader.setUniformi("tilemapDimension", tilesBuffer.width, tilesBuffer.height)
shader.setUniformf("tilesInAxes", tilesInHorizontal.toFloat(), tilesInVertical.toFloat())
shader.setUniformi("cameraTranslation", WorldCamera.x % TILE_SIZE, WorldCamera.y % TILE_SIZE)
shader.setUniformi("tileSizeInPx", TILE_SIZE)
shader.setUniformi("tilesInAtlas", tileAtlas.horizontalCount, tileAtlas.verticalCount) //depends on the tile atlas
shader.setUniformi("atlasTexSize", tileAtlas.texture.width, tileAtlas.texture.height) //depends on the tile atlas
tilesQuad.render(shader, GL20.GL_TRIANGLES)
shader.end()
tilesBufferAsTex.dispose()
}
private var oldScreenW = 0
@@ -691,6 +736,25 @@ object BlocksDrawerNew {
terrainTilesBuffer = Array<IntArray>(tilesInVertical, { kotlin.IntArray(tilesInHorizontal) })
wallTilesBuffer = Array<IntArray>(tilesInVertical, { kotlin.IntArray(tilesInHorizontal) })
wireTilesBuffer = Array<IntArray>(tilesInVertical, { kotlin.IntArray(tilesInHorizontal) })
tilesBuffer = Pixmap(tilesInHorizontal, tilesInVertical, Pixmap.Format.RGBA8888)
}
if (oldScreenW != screenW || oldScreenH != screenH) {
tilesQuad = Mesh(
true, 4, 6,
VertexAttribute.Position(),
VertexAttribute.ColorUnpacked(),
VertexAttribute.TexCoords(0)
)
tilesQuad.setVertices(floatArrayOf( // WARNING! not ususal quads; TexCoords of Y is flipped
0f, 0f, 0f, 1f, 1f, 1f, 1f, 0f, 0f,
screenW.toFloat(), 0f, 0f, 1f, 1f, 1f, 1f, 1f, 0f,
screenW.toFloat(), screenH.toFloat(), 0f, 1f, 1f, 1f, 1f, 1f, 1f,
0f, screenH.toFloat(), 0f, 1f, 1f, 1f, 1f, 0f, 1f
))
tilesQuad.setIndices(shortArrayOf(0, 1, 2, 2, 3, 0))
}
oldScreenW = screenW
@@ -727,11 +791,11 @@ object BlocksDrawerNew {
}
}
fun getRenderStartX(): Int = x / TILE_SIZE
fun getRenderStartY(): Int = y / TILE_SIZE
fun getRenderStartX(): Int = WorldCamera.x / TILE_SIZE
fun getRenderStartY(): Int = WorldCamera.y / TILE_SIZE
fun getRenderEndX(): Int = clampWTile(getRenderStartX() + (width / TILE_SIZE) + 2)
fun getRenderEndY(): Int = clampHTile(getRenderStartY() + (height / TILE_SIZE) + 2)
fun getRenderEndX(): Int = clampWTile(getRenderStartX() + (WorldCamera.width / TILE_SIZE) + 2)
fun getRenderEndY(): Int = clampHTile(getRenderStartY() + (WorldCamera.height / TILE_SIZE) + 2)
fun isConnectSelf(b: Int?): Boolean = TILES_CONNECT_SELF.contains(b)
fun isConnectMutual(b: Int?): Boolean = TILES_CONNECT_MUTUAL.contains(b)
@@ -741,5 +805,5 @@ object BlocksDrawerNew {
fun tileInCamera(x: Int, y: Int) =
x >= WorldCamera.x.div(TILE_SIZE) && y >= WorldCamera.y.div(TILE_SIZE) &&
x <= WorldCamera.x.plus(width).div(TILE_SIZE) && y <= WorldCamera.y.plus(width).div(TILE_SIZE)
x <= WorldCamera.x.plus(WorldCamera.width).div(TILE_SIZE) && y <= WorldCamera.y.plus(WorldCamera.width).div(TILE_SIZE)
}

View File

@@ -12,10 +12,6 @@ import net.torvald.terrarum.blockproperties.BlockCodex
import net.torvald.terrarum.*
import net.torvald.terrarum.gameactors.roundInt
import net.torvald.terrarum.itemproperties.ItemCodex.ITEM_TILES
import net.torvald.terrarum.worlddrawer.WorldCamera.x
import net.torvald.terrarum.worlddrawer.WorldCamera.y
import net.torvald.terrarum.worlddrawer.WorldCamera.height
import net.torvald.terrarum.worlddrawer.WorldCamera.width
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import java.io.BufferedOutputStream
import java.io.File
@@ -26,7 +22,7 @@ import java.util.zip.GZIPInputStream
/**
* Created by minjaesong on 16-01-19.
*/
object BlocksDrawer {
object BlocksDrawerOLD {
lateinit var world: GameWorld
@@ -710,11 +706,11 @@ object BlocksDrawer {
}
}
fun getRenderStartX(): Int = x / TILE_SIZE
fun getRenderStartY(): Int = y / TILE_SIZE
fun getRenderStartX(): Int = WorldCamera.x / TILE_SIZE
fun getRenderStartY(): Int = WorldCamera.y / TILE_SIZE
fun getRenderEndX(): Int = clampWTile(getRenderStartX() + (width / TILE_SIZE) + 2)
fun getRenderEndY(): Int = clampHTile(getRenderStartY() + (height / TILE_SIZE) + 2)
fun getRenderEndX(): Int = clampWTile(getRenderStartX() + (WorldCamera.width / TILE_SIZE) + 2)
fun getRenderEndY(): Int = clampHTile(getRenderStartY() + (WorldCamera.height / TILE_SIZE) + 2)
fun isConnectSelf(b: Int?): Boolean = TILES_CONNECT_SELF.contains(b)
fun isConnectMutual(b: Int?): Boolean = TILES_CONNECT_MUTUAL.contains(b)
@@ -724,5 +720,5 @@ object BlocksDrawer {
fun tileInCamera(x: Int, y: Int) =
x >= WorldCamera.x.div(TILE_SIZE) && y >= WorldCamera.y.div(TILE_SIZE) &&
x <= WorldCamera.x.plus(width).div(TILE_SIZE) && y <= WorldCamera.y.plus(width).div(TILE_SIZE)
x <= WorldCamera.x.plus(WorldCamera.width).div(TILE_SIZE) && y <= WorldCamera.y.plus(WorldCamera.width).div(TILE_SIZE)
}