diff --git a/assets/blur.frag b/assets/blur.frag index babfa6f5f..98ecb63fa 100644 --- a/assets/blur.frag +++ b/assets/blur.frag @@ -5,7 +5,7 @@ uniform sampler2D u_texture; -uniform vec3 iResolution; +uniform vec2 iResolution; uniform float flip; uniform vec2 direction; diff --git a/assets/testimage2.png b/assets/testimage2.png new file mode 100644 index 000000000..266935e75 Binary files /dev/null and b/assets/testimage2.png differ diff --git a/src/net/torvald/terrarum/StateInGameGDX.kt b/src/net/torvald/terrarum/StateInGameGDX.kt index f721829cb..d432494c6 100644 --- a/src/net/torvald/terrarum/StateInGameGDX.kt +++ b/src/net/torvald/terrarum/StateInGameGDX.kt @@ -77,8 +77,9 @@ class StateInGameGDX(val batch: SpriteBatch) : Screen { } var worldDrawFrameBuffer = FrameBuffer(Pixmap.Format.RGBA8888, Gdx.graphics.width, Gdx.graphics.height, false) - var lightmapFrameBuffer = FrameBuffer(Pixmap.Format.RGBA8888, Gdx.graphics.width.div(lightmapDownsample).ceilInt(), Gdx.graphics.height.div(lightmapDownsample).ceilInt(), false) - // lightmapFrameBuffer: used to smooth out lightmap using shader + var lightmapFboA = FrameBuffer(Pixmap.Format.RGBA8888, Gdx.graphics.width.div(lightmapDownsample).ceilInt(), Gdx.graphics.height.div(lightmapDownsample).ceilInt(), false) + var lightmapFboB = FrameBuffer(Pixmap.Format.RGBA8888, Gdx.graphics.width.div(lightmapDownsample).ceilInt(), Gdx.graphics.height.div(lightmapDownsample).ceilInt(), false) + //private lateinit var shader12BitCol: Shader // grab LibGDX if you want some shader //private lateinit var shaderBlur: Shader @@ -370,6 +371,8 @@ class StateInGameGDX(val batch: SpriteBatch) : Screen { } + val testTex = Texture("assets/test_texture.tga") + private fun renderGame(batch: SpriteBatch) { Gdx.gl.glClearColor(.157f, .157f, .157f, 0f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) @@ -379,16 +382,6 @@ class StateInGameGDX(val batch: SpriteBatch) : Screen { //batch.projectionMatrix = camera.combined - // clean the shit beforehand - worldDrawFrameBuffer.inAction { - Gdx.gl.glClearColor(0f,0f,0f,0f) - Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) - } - lightmapFrameBuffer.inAction { - Gdx.gl.glClearColor(0f,0f,0f,0f) - Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) - } - // Post-update; ones that needs everything is completed // FeaturesDrawer.render(batch) // @@ -396,20 +389,42 @@ class StateInGameGDX(val batch: SpriteBatch) : Screen { if (TerrarumGDX.getConfigBoolean("fullframelightupdate") or (TerrarumGDX.GLOBAL_RENDER_TIMER % 2 == 1)) { // LightmapRenderer.fireRecalculateEvent() // } // - // end of post-update // + // end of post-update / - // now the actual drawing part // - lightmapFrameBuffer.inAction { - // TODO gaussian blur p=8 - batch.shader = TerrarumGDX.shaderBlur + + /////////////////// + // blur lightmap // + /////////////////// + val blurIterations = 16 // ideally, 4 * radius; must be even number -- odd number will flip the image + val blurRadius = 4f + + + + lightmapFboA.inAction(null, null) { + Gdx.gl.glClearColor(0f, 0f, 0f, 0f) + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) + } + + lightmapFboA.inAction(null, null) { + Gdx.gl.glClearColor(0f, 0f, 0f, 0f) + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) + } + + + + var blurWriteBuffer = lightmapFboA + var blurReadBuffer = lightmapFboB + + + KeyToggler.forceSet(Input.Keys.F6, false) + KeyToggler.forceSet(Input.Keys.F7, true) + + + // initialise readBuffer with untreated lightmap + blurReadBuffer.inAction(camera, batch) { batch.inUse { - //batch.shader.setUniform3fv("iResolution", floatArrayOf(lightmapFrameBuffer.width.toFloat(), lightmapFrameBuffer.height.toFloat(), 0f), 0, 12) - //batch.shader.setUniformi("iChannel0", 0) - //batch.shader.setUniform2fv("direction", floatArrayOf(8f, 8f), 0, 8) - - // using custom code for camera; this is obscure and tricky camera.position.set(WorldCamera.gdxCamX, WorldCamera.gdxCamY, 0f) // make camara work camera.update() @@ -417,11 +432,67 @@ class StateInGameGDX(val batch: SpriteBatch) : Screen { blendNormal() - LightmapRenderer.draw(batch) + batch.color = Color.WHITE + //LightmapRenderer.draw(batch) + + batch.draw(testTex, 0f, 0f) } } - worldDrawFrameBuffer.inAction { + + for (i in 0..blurIterations - 1) { + blurWriteBuffer.inAction(camera, batch) { + + batch.inUse { + val texture = if (i == 0) + testTex + else + blurReadBuffer.colorBufferTexture + + texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear) + + + batch.shader = TerrarumGDX.shaderBlur + batch.shader.setUniformf("iResolution", blurWriteBuffer.width.toFloat(), blurWriteBuffer.height.toFloat()) + batch.shader.setUniformf("flip", 1f) + if (i % 2 == 0) + batch.shader.setUniformf("direction", blurRadius, 0f) + else + batch.shader.setUniformf("direction", 0f, blurRadius) + + + batch.color = Color.WHITE + batch.draw(texture, 0f, 0f) + + + // swap + val t = blurWriteBuffer + blurWriteBuffer = blurReadBuffer + blurReadBuffer = t + } + } + } + + + // TEST: passthru to writeBuffer + /*blurWriteBuffer.inAction(camera, batch) { + batch.inUse { + batch.color = Color.WHITE + batch.draw(testTex, 0f, 0f) + } + }*/ + + + + /////////////////////////// + // draw world to the FBO // + /////////////////////////// + + worldDrawFrameBuffer.inAction(camera, batch) { + Gdx.gl.glClearColor(0f,0f,0f,0f) + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) + + batch.inUse { batch.shader = null @@ -464,10 +535,14 @@ class StateInGameGDX(val batch: SpriteBatch) : Screen { if (!KeyToggler.isOn(Input.Keys.F6)) { // F6 to disable lightmap draw setCameraPosition(0f, 0f) - val lightTex = lightmapFrameBuffer.colorBufferTexture // TODO zoom! + val lightTex = blurWriteBuffer.colorBufferTexture // TODO zoom! if (KeyToggler.isOn(Input.Keys.F7)) blendNormal() else blendMul() - batch.draw(lightTex, 0f, 0f, lightTex.width * lightmapDownsample, lightTex.height * lightmapDownsample) + batch.color = Color.WHITE + //batch.draw(lightTex, 0f, 0f, lightTex.width * lightmapDownsample, lightTex.height * lightmapDownsample) + + TerrarumGDX.fontGame.draw(batch, "Thumbnail:", 100f, 80f) + batch.draw(lightTex, 100f, 100f, 100f, 100f) } @@ -496,6 +571,8 @@ class StateInGameGDX(val batch: SpriteBatch) : Screen { ///////////////////////// // draw to main screen // ///////////////////////// + camera.setToOrtho(true, Gdx.graphics.width.toFloat(), Gdx.graphics.height.toFloat()) + batch.projectionMatrix = camera.combined batch.inUse { batch.shader = null @@ -1143,8 +1220,11 @@ class StateInGameGDX(val batch: SpriteBatch) : Screen { override fun resize(width: Int, height: Int) { worldDrawFrameBuffer.dispose() worldDrawFrameBuffer = FrameBuffer(Pixmap.Format.RGBA8888, width, height, false) - lightmapFrameBuffer.dispose() - lightmapFrameBuffer = FrameBuffer(Pixmap.Format.RGBA8888, width.div(lightmapDownsample).ceilInt(), height.div(lightmapDownsample).ceilInt(), false) + lightmapFboA.dispose() + lightmapFboA = FrameBuffer(Pixmap.Format.RGBA8888, width.div(lightmapDownsample).ceilInt(), height.div(lightmapDownsample).ceilInt(), false) + lightmapFboB.dispose() + lightmapFboB = FrameBuffer(Pixmap.Format.RGBA8888, width.div(lightmapDownsample).ceilInt(), height.div(lightmapDownsample).ceilInt(), false) + // Set up viewport when window is resized initViewPort(width, height) diff --git a/src/net/torvald/terrarum/TerrarumGDX.kt b/src/net/torvald/terrarum/TerrarumGDX.kt index d2184a8ff..bfc4e1e55 100644 --- a/src/net/torvald/terrarum/TerrarumGDX.kt +++ b/src/net/torvald/terrarum/TerrarumGDX.kt @@ -6,10 +6,7 @@ import com.badlogic.gdx.Screen import com.badlogic.gdx.assets.loaders.ShaderProgramLoader import com.badlogic.gdx.backends.lwjgl.LwjglApplication import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration -import com.badlogic.gdx.graphics.Color -import com.badlogic.gdx.graphics.GL20 -import com.badlogic.gdx.graphics.GL30 -import com.badlogic.gdx.graphics.Texture +import com.badlogic.gdx.graphics.* import com.badlogic.gdx.graphics.g2d.Batch import com.badlogic.gdx.graphics.g2d.BitmapFont import com.badlogic.gdx.graphics.g2d.CpuSpriteBatch @@ -46,9 +43,9 @@ fun main(args: Array) { config.foregroundFPS = TerrarumGDX.RENDER_FPS config.backgroundFPS = TerrarumGDX.RENDER_FPS //config.vSyncEnabled = true - config.resizable = true - config.width = 1072 - config.height = 742 + config.resizable = false + config.width = 512//1072 + config.height = 512//742 config.backgroundFPS = 9999 config.foregroundFPS = 9999 //config.useGL30 = true @@ -297,7 +294,6 @@ object TerrarumGDX : ApplicationAdapter() { ShaderProgram.pedantic = false shaderBlur = ShaderProgram(Gdx.files.internal("assets/blur.vert"), Gdx.files.internal("assets/blur.frag")) - ModMgr // invoke Module Manager, will also invoke BlockCodex ItemCodex // invoke Item Codex @@ -305,8 +301,9 @@ object TerrarumGDX : ApplicationAdapter() { ingame = StateInGameGDX(batch) - ingame!!.enter() currentScreen = ingame as Screen + ingame!!.enter() + } override fun render() { @@ -522,8 +519,12 @@ inline fun ShapeRenderer.inUse(shapeRendererType: ShapeRenderer.ShapeType = Shap } /** Use Batch inside of it! */ -inline fun FrameBuffer.inAction(action: (FrameBuffer) -> Unit) { +inline fun FrameBuffer.inAction(camera: OrthographicCamera?, batch: SpriteBatch?, action: (FrameBuffer) -> Unit) { this.begin() + camera?.setToOrtho(true, this.width.toFloat(), this.height.toFloat()) + camera?.position?.set(this.width / 2f, this.height / 2f, 0f) // are these actually needed? + camera?.update() // are these actually needed? + batch?.projectionMatrix = camera?.combined action(this) this.end() } diff --git a/src/net/torvald/terrarum/TestTestTest.kt b/src/net/torvald/terrarum/TestTestTest.kt index ab0346de4..e224e119e 100644 --- a/src/net/torvald/terrarum/TestTestTest.kt +++ b/src/net/torvald/terrarum/TestTestTest.kt @@ -2,40 +2,50 @@ package net.torvald.terrarum import com.badlogic.gdx.ApplicationAdapter import com.badlogic.gdx.Gdx +import com.badlogic.gdx.Screen import com.badlogic.gdx.backends.lwjgl.LwjglApplication import com.badlogic.gdx.backends.lwjgl.LwjglApplicationConfiguration -import com.badlogic.gdx.graphics.GL20 -import com.badlogic.gdx.graphics.Pixmap -import com.badlogic.gdx.graphics.Texture +import com.badlogic.gdx.graphics.* import com.badlogic.gdx.graphics.g2d.BitmapFont import com.badlogic.gdx.graphics.g2d.SpriteBatch import com.badlogic.gdx.graphics.glutils.FrameBuffer import com.badlogic.gdx.graphics.glutils.ShaderProgram import net.torvald.terrarumsansbitmap.gdx.GameFontBase -import com.badlogic.gdx.graphics.OrthographicCamera - - /** * Created by minjaesong on 2017-06-11. */ -class TestTestTest : ApplicationAdapter() { +class TestTestTest(val batch: SpriteBatch) : Screen { - lateinit var batch: SpriteBatch lateinit var img: Texture lateinit var gameFont: BitmapFont - lateinit var blurShader: ShaderProgram - lateinit var blurFboA: FrameBuffer lateinit var blurFboB: FrameBuffer - lateinit var cam: OrthographicCamera + lateinit var worldFbo: FrameBuffer + + lateinit var camera: OrthographicCamera + + // invert Y + fun initViewPort(width: Int, height: Int) { + // Set Y to point downwards + camera.setToOrtho(true, width.toFloat(), height.toFloat()) + + // Update camera matrix + camera.update() + + // Set viewport to restrict drawing + Gdx.gl20.glViewport(0, 0, width, height) + } + + fun enter() { + // init view port + camera = OrthographicCamera(Gdx.graphics.width.toFloat(), Gdx.graphics.height.toFloat()) + - override fun create() { - batch = SpriteBatch() img = Texture("assets/test_texture.tga") gameFont = GameFontBase("assets/graphics/fonts/terrarum-sans-bitmap") @@ -45,20 +55,21 @@ class TestTestTest : ApplicationAdapter() { blurFboA = FrameBuffer(Pixmap.Format.RGBA8888, img.width, img.height, false) blurFboB = FrameBuffer(Pixmap.Format.RGBA8888, img.width, img.height, false) - ShaderProgram.pedantic = false - blurShader = ShaderProgram(Gdx.files.internal("assets/blur.vert"), Gdx.files.internal("assets/blur.frag")) + worldFbo = FrameBuffer(Pixmap.Format.RGBA8888, Gdx.graphics.width, Gdx.graphics.height, false) - blurShader.begin() - blurShader.setUniformf("iResolution", img.width.toFloat(), img.height.toFloat(), 0f) - blurShader.end() + //blurShader.begin() + //blurShader.setUniformf("iResolution", img.width.toFloat(), img.height.toFloat(), 0f) + //blurShader.end() - cam = OrthographicCamera(Gdx.graphics.width.toFloat(), Gdx.graphics.height.toFloat()) - cam.setToOrtho(false) + initViewPort(Gdx.graphics.width, Gdx.graphics.height) } - override fun render() { - val iterations = 16 + override fun render(delta: Float) { + Gdx.graphics.setTitle("TestTestTest — F: ${Gdx.graphics.framesPerSecond}") + + + val iterations = 16 // ideally, 4 * radius; must be even number -- odd number will flip the image val radius = 4f @@ -66,12 +77,12 @@ class TestTestTest : ApplicationAdapter() { Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) - blurFboA.inAction { + blurFboA.inAction(null, null) { Gdx.gl.glClearColor(0f, 0f, 0f, 0f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) } - blurFboB.inAction { + blurFboB.inAction(null, null) { Gdx.gl.glClearColor(0f, 0f, 0f, 0f) Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) } @@ -82,12 +93,9 @@ class TestTestTest : ApplicationAdapter() { for (i in 0..iterations - 1) { - writeBuffer.inAction { + writeBuffer.inAction(camera, batch) { + batch.inUse { - cam.setToOrtho(false, writeBuffer.width.toFloat(), writeBuffer.height.toFloat()) - batch.projectionMatrix = cam.combined - - val texture = if (i == 0) img else @@ -95,7 +103,9 @@ class TestTestTest : ApplicationAdapter() { texture.setFilter(Texture.TextureFilter.Linear, Texture.TextureFilter.Linear) - batch.shader = blurShader + + batch.shader = TestTestMain.blurShader + batch.shader.setUniformf("iResolution", writeBuffer.width.toFloat(), writeBuffer.height.toFloat()) batch.shader.setUniformf("flip", 1f) if (i % 2 == 0) batch.shader.setUniformf("direction", radius, 0f) @@ -103,7 +113,7 @@ class TestTestTest : ApplicationAdapter() { batch.shader.setUniformf("direction", 0f, radius) - + batch.color = Color.WHITE batch.draw(texture, 0f, 0f) @@ -115,16 +125,57 @@ class TestTestTest : ApplicationAdapter() { } } - // draw last FBO to screen - batch.inUse { - cam.setToOrtho(false, Gdx.graphics.width.toFloat(), Gdx.graphics.height.toFloat()) - batch.projectionMatrix = cam.combined + + worldFbo.inAction(camera, batch) { + Gdx.gl.glClearColor(0f,0f,0f,0f) + Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT) + + batch.inUse { + batch.shader = null + + camera.position.set(Gdx.graphics.width / 2f - 50f, Gdx.graphics.height / 2f - 50f, 0f) + camera.update() + batch.projectionMatrix = camera.combined - batch.shader.setUniformf("direction", 0f, 0f) - batch.shader.setUniformf("flip", if (iterations % 2 != 0) 1f else 0f) - batch.draw(writeBuffer.colorBufferTexture, 0f, 0f) + + batch.color = Color.WHITE + batch.draw(writeBuffer.colorBufferTexture, 0f, 0f) + } } + + + camera.setToOrtho(true, Gdx.graphics.width.toFloat(), Gdx.graphics.height.toFloat()) + batch.projectionMatrix = camera.combined + batch.inUse { + + camera.position.set(Gdx.graphics.width / 2f, Gdx.graphics.height / 2f, 0f) + camera.update() + batch.projectionMatrix = camera.combined + + + batch.color = Color.WHITE + batch.draw(worldFbo.colorBufferTexture, 0f, 0f) + + + batch.draw(img, 0f, 0f, 100f, 100f) + } + } + + override fun hide() { + } + + override fun show() { + initViewPort(Gdx.graphics.width, Gdx.graphics.height) + } + + override fun pause() { + } + + override fun resume() { + } + + override fun resize(width: Int, height: Int) { } override fun dispose() { @@ -133,18 +184,42 @@ class TestTestTest : ApplicationAdapter() { } - private inline fun SpriteBatch.inUse(action: () -> Unit) { - this.begin() - action() - this.end() +} + +object TestTestMain : ApplicationAdapter() { + lateinit var blurShader: ShaderProgram + lateinit var batch: SpriteBatch + + lateinit var currentScreen: TestTestTest + + override fun create() { + ShaderProgram.pedantic = false + blurShader = ShaderProgram(Gdx.files.internal("assets/blur.vert"), Gdx.files.internal("assets/blur.frag")) + + // culprit #4 + blurShader.begin() + blurShader.setUniformf("dir", 0f, 0f); //direction of blur; nil for now + blurShader.setUniformf("resolution", maxOf(Gdx.graphics.width.toFloat(), Gdx.graphics.height.toFloat())) //size of FBO texture + blurShader.setUniformf("radius", 9f) //radius of blur + blurShader.end() + + Gdx.graphics.isContinuousRendering = true // culprit #3 + + + batch = SpriteBatch() + + + currentScreen = TestTestTest(batch) + currentScreen.enter() } - inline fun FrameBuffer.inAction(action: (FrameBuffer) -> Unit) { - this.begin() - action(this) - this.end() + override fun render() { + currentScreen.render(Gdx.graphics.deltaTime) } + override fun dispose() { + currentScreen.dispose() + } } fun main(args: Array) { // LWJGL 3 won't work? java.lang.VerifyError @@ -155,5 +230,5 @@ fun main(args: Array) { // LWJGL 3 won't work? java.lang.VerifyError config.width = 1072 config.height = 742 config.foregroundFPS = 9999 - LwjglApplication(TestTestTest(), config) + LwjglApplication(TestTestMain, config) } \ No newline at end of file diff --git a/src/net/torvald/terrarum/ui/UIBasicNotifier.kt b/src/net/torvald/terrarum/ui/UIBasicNotifier.kt index cd85c05af..ff234aa74 100644 --- a/src/net/torvald/terrarum/ui/UIBasicNotifier.kt +++ b/src/net/torvald/terrarum/ui/UIBasicNotifier.kt @@ -83,14 +83,6 @@ class UIBasicNotifier(private val player: ActorHumanoid?) : UICanvas { } override fun render(batch: SpriteBatch) { - // backplate - batch.draw(atlas.get(0, 0), 0f, 0f) - - // because what the fuck (rendered darker than what it supposed to be) - /*blendScreen() - batch.color = Color(0x0c0c0c_ff) - batch.draw(atlas.get(0, 1), 0f, 0f)*/ - // light overlay or EL if (ELon) { blendNormal() @@ -108,9 +100,11 @@ class UIBasicNotifier(private val player: ActorHumanoid?) : UICanvas { else { lightLevel = TerrarumGDX.ingame!!.world.globalLight.normaliseToColour() } - blendMul() + + + // backplate batch.color = lightLevel - batch.draw(atlas.get(0, 1), 0f, 0f) + batch.draw(atlas.get(0, 0), 0f, 0f) } // LCD back diff --git a/src/net/torvald/terrarum/ui/UITierOneWatch.kt b/src/net/torvald/terrarum/ui/UITierOneWatch.kt index 7d645c273..cd21423c0 100644 --- a/src/net/torvald/terrarum/ui/UITierOneWatch.kt +++ b/src/net/torvald/terrarum/ui/UITierOneWatch.kt @@ -58,14 +58,6 @@ class UITierOneWatch(private val player: ActorHumanoid?) : UICanvas { } override fun render(batch: SpriteBatch) { - // backplate - batch.draw(atlas.get(0, 0), 0f, 0f) - - // because what the fuck (rendered darker than what it supposed to be) - /*blendScreen() - batch.color = Color(0x0c0c0c_ff) - batch.draw(atlas.get(0, 1), 0f, 0f)*/ - // light overlay or EL if (ELon) { blendNormal() @@ -83,9 +75,10 @@ class UITierOneWatch(private val player: ActorHumanoid?) : UICanvas { else { lightLevel = TerrarumGDX.ingame!!.world.globalLight.normaliseToColour() } - blendMul() + + // backplate batch.color = lightLevel - batch.draw(atlas.get(0, 1), 0f, 0f) + batch.draw(atlas.get(0, 0), 0f, 0f) } // LCD back diff --git a/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt b/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt index b6adbf64d..ba6b75d9a 100644 --- a/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt +++ b/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt @@ -13,6 +13,7 @@ import net.torvald.terrarum.gameactors.ActorWithPhysics import net.torvald.terrarum.gameworld.GameWorld import net.torvald.terrarum.blockproperties.Block import net.torvald.terrarum.fillRect +import net.torvald.terrarum.gameactors.roundInt import net.torvald.terrarum.inUse import java.util.* @@ -285,10 +286,10 @@ object LightmapRenderer { * sample ambient for eight points and apply attenuation for those * maxblend eight values and use it */ - /* + */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x - 1, y - 1) ?: 0, scaleColour(thisTileOpacity, 1.4142f)) - /* + */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x + 1, y - 1) ?: 0, scaleColour(thisTileOpacity, 1.4142f)) - /* + */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x - 1, y + 1) ?: 0, scaleColour(thisTileOpacity, 1.4142f)) - /* + */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x + 1, y + 1) ?: 0, scaleColour(thisTileOpacity, 1.4142f)) + /* + */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x - 1, y - 1) ?: 0, scaleSqrt2(thisTileOpacity)) + /* + */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x + 1, y - 1) ?: 0, scaleSqrt2(thisTileOpacity)) + /* + */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x - 1, y + 1) ?: 0, scaleSqrt2(thisTileOpacity)) + /* + */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x + 1, y + 1) ?: 0, scaleSqrt2(thisTileOpacity)) /* * */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x , y - 1) ?: 0, thisTileOpacity) /* * */ambientAccumulator = ambientAccumulator maxBlend darkenColoured(getLight(x , y + 1) ?: 0, thisTileOpacity) @@ -462,17 +463,25 @@ object LightmapRenderer { // use equation with magic number 8.0 // should draw somewhat exponential curve when you plot the propagation of light in-game - return ((data.r() * (1f - darken.r() * lightScalingMagic)).clampZero() * CHANNEL_MAX).round() * MUL_2 + - ((data.g() * (1f - darken.g() * lightScalingMagic)).clampZero() * CHANNEL_MAX).round() * MUL + + return ((data.r() * (1f - darken.r() * lightScalingMagic)).clampZero() * CHANNEL_MAX).round().shl(20) or + ((data.g() * (1f - darken.g() * lightScalingMagic)).clampZero() * CHANNEL_MAX).round().shl(10) or ((data.b() * (1f - darken.b() * lightScalingMagic)).clampZero() * CHANNEL_MAX).round() } fun scaleColour(data: Int, scale: Float): RGB10 { - return ((data.r() * scale).clampOne() * CHANNEL_MAX).round() * MUL_2 + - ((data.g() * scale).clampOne() * CHANNEL_MAX).round() * MUL + + return ((data.r() * scale).clampOne() * CHANNEL_MAX).round().shl(20) or + ((data.g() * scale).clampOne() * CHANNEL_MAX).round().shl(10) or ((data.b() * scale).clampOne() * CHANNEL_MAX).round() } + private fun scaleSqrt2(data: Int): RGB10 { + return scaleSqrt2Lookup[data.rawR()].shl(20) or + scaleSqrt2Lookup[data.rawG()].shl(10) or + scaleSqrt2Lookup[data.rawB()] + } + + private val scaleSqrt2Lookup = IntArray(MUL, { it -> minOf(MUL - 1, (it * 1.41421356).roundInt()) }) + /** * Add each channel's RGB value. * @@ -559,37 +568,37 @@ object LightmapRenderer { * @return */ private infix fun RGB10.maxBlend(other: Int): RGB10 { - return (if (this.rawR() > other.rawR()) this.rawR() else other.rawR()) * MUL_2 + - (if (this.rawG() > other.rawG()) this.rawG() else other.rawG()) * MUL + + return (if (this.rawR() > other.rawR()) this.rawR() else other.rawR()).shl(20) or + (if (this.rawG() > other.rawG()) this.rawG() else other.rawG()).shl(10) or (if (this.rawB() > other.rawB()) this.rawB() else other.rawB()) } private infix fun RGB10.linMix(other: Int): RGB10 { - return ((this.rawR() + other.rawR()) ushr 1) * MUL_2 + - ((this.rawG() + other.rawG()) ushr 1) * MUL + + return ((this.rawR() + other.rawR()) ushr 1).shl(20) or + ((this.rawG() + other.rawG()) ushr 1).shl(10) or ((this.rawB() + other.rawB()) ushr 1) } private infix fun RGB10.colSub(other: Int): RGB10 { - return ((this.rawR() - other.rawR()).clampChannel()) * MUL_2 + - ((this.rawG() - other.rawG()).clampChannel()) * MUL + + return ((this.rawR() - other.rawR()).clampChannel()).shl(20) or + ((this.rawG() - other.rawG()).clampChannel()).shl(10) or ((this.rawB() - other.rawB()).clampChannel()) } private infix fun RGB10.colAdd(other: Int): RGB10 { - return ((this.rawR() + other.rawR()).clampChannel()) * MUL_2 + - ((this.rawG() + other.rawG()).clampChannel()) * MUL + + return ((this.rawR() + other.rawR()).clampChannel()).shl(20) or + ((this.rawG() + other.rawG()).clampChannel()).shl(10) or ((this.rawB() + other.rawB()).clampChannel()) } - fun RGB10.rawR() = this / MUL_2 - fun RGB10.rawG() = this % MUL_2 / MUL - fun RGB10.rawB() = this % MUL + inline fun RGB10.rawR() = this.ushr(20) and 1023 + inline fun RGB10.rawG() = this.ushr(10) and 1023 + inline fun RGB10.rawB() = this and 1023 /** 0.0 - 1.0 for 0-1023 (0.0 - 0.25 for 0-255) */ - fun RGB10.r(): Float = this.rawR() / CHANNEL_MAX_FLOAT - fun RGB10.g(): Float = this.rawG() / CHANNEL_MAX_FLOAT - fun RGB10.b(): Float = this.rawB() / CHANNEL_MAX_FLOAT + inline fun RGB10.r(): Float = this.rawR() / CHANNEL_MAX_FLOAT + inline fun RGB10.g(): Float = this.rawG() / CHANNEL_MAX_FLOAT + inline fun RGB10.b(): Float = this.rawB() / CHANNEL_MAX_FLOAT /** @@ -617,8 +626,8 @@ object LightmapRenderer { //if (g !in 0..CHANNEL_MAX) throw IllegalArgumentException("Green: out of range ($g)") //if (b !in 0..CHANNEL_MAX) throw IllegalArgumentException("Blue: out of range ($b)") - return r * MUL_2 + - g * MUL + + return r.shl(20) or + g.shl(10) or b } @@ -627,8 +636,8 @@ object LightmapRenderer { //if (g < 0 || g > CHANNEL_MAX_DECIMAL) throw IllegalArgumentException("Green: out of range ($g)") //if (b < 0 || b > CHANNEL_MAX_DECIMAL) throw IllegalArgumentException("Blue: out of range ($b)") - return (r * CHANNEL_MAX).round() * MUL_2 + - (g * CHANNEL_MAX).round() * MUL + + return (r * CHANNEL_MAX).round().shl(20) or + (g * CHANNEL_MAX).round().shl(10) or (b * CHANNEL_MAX).round() }