From 85a4c462402d993ff0367e829938240f9a6bb817 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Fri, 30 Aug 2024 02:37:53 +0900 Subject: [PATCH] trying to optimise the tiling code (its broken now) --- .../terrarum/worlddrawer/BlocksDrawer.kt | 60 ++++++++++++------- src/shaders/tiling.frag | 28 ++++----- 2 files changed, 47 insertions(+), 41 deletions(-) diff --git a/src/net/torvald/terrarum/worlddrawer/BlocksDrawer.kt b/src/net/torvald/terrarum/worlddrawer/BlocksDrawer.kt index 998d83b84..37c348bad 100644 --- a/src/net/torvald/terrarum/worlddrawer/BlocksDrawer.kt +++ b/src/net/torvald/terrarum/worlddrawer/BlocksDrawer.kt @@ -250,7 +250,6 @@ internal object BlocksDrawer { // var selectedWireRenderClass = "" internal fun renderData() { - try { val seasonalMonth = world.worldTime.ecologicalSeason @@ -260,6 +259,16 @@ internal object BlocksDrawer { } catch (e: ClassCastException) { } + + + + if (doTilemapUpdate) { + wrapCamera() + } + + camTransX = WorldCamera.x - camX + camTransY = WorldCamera.y - camY + if (doTilemapUpdate) { // rendering tilemap only updates every three frame measureDebugTime("Renderer.Tiling*") { @@ -398,6 +407,28 @@ internal object BlocksDrawer { ) fmod mod).toInt() } + private var for_y_start = 0 + private var for_y_end = 0 + private var for_x_start = 0 + private var for_x_end = 0 + private var camX = 0 + private var camY = 0 + + private fun wrapCamera() { + camX = WorldCamera.x + camY = WorldCamera.y + + // can't be "WorldCamera.y / TILE_SIZE": + // ( 3 / 16) == 0 + // (-3 / 16) == -1 <-- We want it to be '-1', not zero + // using cast and floor instead of IF on ints: the other way causes jitter artefact, which I don't fucking know why + + for_y_start = (camY.toFloat() / TILE_SIZE).floorToInt() + for_y_end = for_y_start + hTilesInVertical - 1 + for_x_start = (camX.toFloat() / TILE_SIZE).floorToInt() + for_x_end = for_x_start + hTilesInHorizontal - 1 + } + /** * Autotiling; writes to buffer. Actual draw code must be called after this operation. * @@ -405,10 +436,6 @@ internal object BlocksDrawer { * @param wire coduitTypes bit that is selected to be drawn. Must be the power of two. */ private fun drawTiles(mode: Int) { - // can't be "WorldCamera.y / TILE_SIZE": - // ( 3 / 16) == 0 - // (-3 / 16) == -1 <-- We want it to be '-1', not zero - // using cast and floor instead of IF on ints: the other way causes jitter artefact, which I don't fucking know why // TODO the real fluid rendering must use separate function, but its code should be similar to this. // shader's tileAtlas will be fluid.tga, pixels written to the buffer is in accordance with the new @@ -416,13 +443,6 @@ internal object BlocksDrawer { // The MUL draw mode can be removed from this (it turns out drawing tinted glass is tricky because of // the window frame which should NOT be MUL'd) - - val for_y_start = (WorldCamera.y.toFloat() / TILE_SIZE).floorToInt() - val for_y_end = for_y_start + hTilesInVertical - 1 - - val for_x_start = (WorldCamera.x.toFloat() / TILE_SIZE).floorToInt() - val for_x_end = for_x_start + hTilesInHorizontal - 1 - // loop for (y in for_y_start..for_y_end) { for (x in for_x_start..for_x_end) { @@ -1156,7 +1176,10 @@ internal object BlocksDrawer { 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) + get() = (!world.layerTerrain.ptrDestroyed && App.GLOBAL_RENDER_TIMER % 30 == 0L) + + private var camTransX = 0 + private var camTransY = 0 private fun renderUsingBuffer(mode: Int, projectionMatrix: Matrix4, drawGlow: Boolean, drawEmissive: Boolean) { //Gdx.gl.glClearColor(.094f, .094f, .094f, 0f) @@ -1258,7 +1281,7 @@ internal object BlocksDrawer { shaderTiling.setUniformi("deblockingMap", 4) shaderTiling.setUniformi("tilemapDimension", tilesBuffer.width, tilesBuffer.height) shaderTiling.setUniformf("tilesInAxes", tilesInHorizontal.toFloat(), tilesInVertical.toFloat()) - shaderTiling.setUniformi("cameraTranslation", WorldCamera.x fmod TILE_SIZE, WorldCamera.y fmod TILE_SIZE) // usage of 'fmod' and '%' were depend on the for_x_start, which I can't just do naive int div + shaderTiling.setUniformi("cameraTranslation", camTransX, camTransY) // usage of 'fmod' and '%' were depend on the for_x_start, which I can't just do naive int div shaderTiling.setUniformf("tilesInAtlas", tileAtlas.horizontalCount * 2f, tileAtlas.verticalCount * 2f) //depends on the tile atlas shaderTiling.setUniformf("atlasTexSize", tileAtlas.texture.width.toFloat(), tileAtlas.texture.height.toFloat()) //depends on the tile atlas // set the blend value as world's time progresses, in linear fashion @@ -1405,12 +1428,6 @@ internal object BlocksDrawer { App.tileMaker.dispose() } - fun getRenderStartX(): Int = WorldCamera.x / TILE_SIZE - fun getRenderStartY(): Int = WorldCamera.y / TILE_SIZE - - fun getRenderEndX(): Int = clampWTile(getRenderStartX() + (WorldCamera.width / TILE_SIZE) + 2) - fun getRenderEndY(): Int = clampHTile(getRenderStartY() + (WorldCamera.height / TILE_SIZE) + 2) - fun isConnectSelf(b: ItemID) = App.tileMaker.getRenderTag(b).connectionType == CreateTileAtlas.RenderTag.CONNECT_SELF fun isConnectMutual(b: ItemID) = App.tileMaker.getRenderTag(b).connectionType == CreateTileAtlas.RenderTag.CONNECT_MUTUAL fun isWallSticker(b: ItemID) = App.tileMaker.getRenderTag(b).connectionType == CreateTileAtlas.RenderTag.CONNECT_WALL_STICKER @@ -1420,7 +1437,4 @@ internal object BlocksDrawer { fun isTreeTrunk(b: ItemID) = BlockCodex[b].hasAllTagsOf("TREE", "TREETRUNK") fun isCultivable(b: ItemID) = BlockCodex[b].hasAllTagsOf("NATURAL", "CULTIVABLE") - fun tileInCamera(x: Int, y: Int) = - x >= WorldCamera.x.div(TILE_SIZE) && y >= WorldCamera.y.div(TILE_SIZE) && - x <= WorldCamera.x.plus(WorldCamera.width).div(TILE_SIZE) && y <= WorldCamera.y.plus(WorldCamera.width).div(TILE_SIZE) } diff --git a/src/shaders/tiling.frag b/src/shaders/tiling.frag index 265374a46..545b095fe 100644 --- a/src/shaders/tiling.frag +++ b/src/shaders/tiling.frag @@ -8,34 +8,26 @@ layout(origin_upper_left,pixel_center_integer) in vec4 gl_FragCoord; // is now t in vec4 v_color; in vec2 v_texCoords; -uniform sampler2D u_texture; - - -uniform vec2 tilesInAxes; // 8x8 - uniform sampler2D tilemap; // RGBA8888 uniform sampler2D tilemap2; // RGBA8888 uniform sampler2D tilesAtlas; // terrain, wire, fluids, etc. uniform sampler2D tilesBlendAtlas; // alternative terrain for the weather mix (e.g. yellowed grass) uniform sampler2D deblockingMap; +uniform vec2 tilesInAxes; // 8x8 uniform float tilesBlend = 0.0; // percentage of blending [0f..1f]. 0: draws tilesAtlas, 1: draws tilesBlendAtlas uniform vec2 tilesInAtlas = vec2(256.0, 256.0); uniform vec2 atlasTexSize = vec2(2048.0, 2048.0); +uniform vec4 colourFilter = vec4(1, 1, 1, 1); // used by WALL to darken it +uniform ivec2 cameraTranslation = ivec2(0, 0); // used to offset the drawing; it's integer because we want the drawing to be pixel-aligned +uniform float drawBreakage = 1.0; // set it to 0f to not draw breakage, 1f to draw it; NEVER set to any other values. +uniform float mulBlendIntensity = 1.0; // used my MUL-blending drawings; works about the same way as the Layer Opacity slider of Photoshop/Krita/etc. + vec2 _tilesInAtlas = vec2(1.0, 1.0) / tilesInAtlas; vec2 tileSizeInPx = atlasTexSize * _tilesInAtlas; // should be like ivec2(8.0, 8.0) vec2 _tileSizeInPx = vec2(1.0, 1.0) / tileSizeInPx; // should be like ivec2(0.125, 0.125) - -uniform vec4 colourFilter = vec4(1, 1, 1, 1); // used by WALL to darken it - -uniform ivec2 cameraTranslation = ivec2(0, 0); // used to offset the drawing; it's integer because we want the drawing to be pixel-aligned - -uniform float drawBreakage = 1.0; // set it to 0f to not draw breakage, 1f to draw it; NEVER set to any other values. - -uniform float mulBlendIntensity = 1.0; // used my MUL-blending drawings; works about the same way as the Layer Opacity slider of Photoshop/Krita/etc. - const vec2 bc = vec2(1.0, 0.0); //binary constant const vec2 haalf = vec2(0.5, 0.5); @@ -91,10 +83,10 @@ 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); -vec2 blurL = vec2(-blur, 0.0); -vec2 blurR = vec2(+blur, 0.0); +const vec2 blurU = vec2(0.0, -blur); +const vec2 blurD = vec2(0.0, +blur); +const vec2 blurL = vec2(-blur, 0.0); +const vec2 blurR = vec2(+blur, 0.0); vec2 overscannedScreenDimension = tilesInAxes * tileSizeInPx; // how many tiles will fit into a screen; one used by the tileFromMap; we need this because screen size is not integer multiple of the tile size