asynchronous lightmap update wip

This commit is contained in:
minjaesong
2022-01-27 17:11:09 +09:00
parent 119b7fc022
commit c500a5ca39
14 changed files with 232 additions and 201 deletions

View File

@@ -18,6 +18,8 @@ internal class UnsafeCvecArray(val width: Int, val height: Int) {
private inline fun toAddr(x: Int, y: Int) = 16L * (y * width + x)
fun isDestroyed() = array.destroyed
init {
zerofill()
}

View File

@@ -33,8 +33,11 @@ internal object Authenticator : ConsoleCommand {
val pwd = args[1]
val hashedPwd = DigestUtils.sha256Hex(pwd)
if ("65b9aa150332ed7096134efb20220e5ebec04d4dbe1c537ff3816f68c2391c1c".equals(hashedPwd, ignoreCase = true)) {
// aryll
println("auth passwd: '$pwd'")
println("hash: $hashedPwd")
if ("09ccf5067db6f58265b004829e33e715e819ba0984f1e1fcef49c36fcd5f745f".equals(hashedPwd, ignoreCase = true)) {
// beedle
val msg = if (a) "Locked" else "Authenticated"
Echo(msg)
println("[Authenticator] " + msg)

View File

@@ -13,15 +13,42 @@ object CommandDict {
internal val dict = hashMapOf<String, ConsoleCommand>()
private val engineCommandList = listOf(
"ActorsList",
"Authenticator",
"AVTracker",
"Batch",
"Echo",
"EchoConsole",
"EchoError",
"Pause",
"QuitApp",
"ResizeScreen",
"ScreencapNogui",
"SetGlobalLightOverride",
"SetLocale",
"TakeScreenshot",
"Unpause",
"Version"
)
init {
printdbg(this, ModMgr.loadOrder.reversed())
printdbg(this, ModMgr.loadOrder.reversed().map { ModMgr.moduleInfo[it]?.packageName })
(listOf("net.torvald.terrarum") + ModMgr.loadOrder.reversed().mapNotNull { ModMgr.moduleInfo[it]?.packageName }).forEach { packageRoot ->
printdbg(this, packageRoot)
((listOf("$" to "net.torvald.terrarum")) + ModMgr.loadOrder.reversed().map { it to ModMgr.moduleInfo[it]?.packageName }).forEach { (modName, packageRoot) ->
val commandsList = if (modName == "$") engineCommandList else ModMgr.getFile(modName, "commands.csv").readLines()
val packageConsole = "$packageRoot.console"
printdbg(this, "Loading console commands from '${packageConsole}'")
// TODO load commands using commandsList
val stream = ClassLoader.getSystemClassLoader().getResourceAsStream(packageConsole.replace('.', '/'))
if (stream != null) { // not all modules have extra console commands
val reader = BufferedReader(InputStreamReader(stream))

View File

@@ -1,5 +1,6 @@
package net.torvald.terrarum.console
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.ccG
import net.torvald.terrarum.ccW
import net.torvald.terrarum.ccY
@@ -32,8 +33,6 @@ internal object CommandInterpreter {
internal fun execute(command: String) {
val cmd: Array<CommandInput?> = parse(command)
val error = Error()
for (single_command in cmd) {
if (single_command == null || single_command.argsCount == 0) continue
@@ -65,6 +64,7 @@ internal object CommandInterpreter {
}
}
catch (e: NullPointerException) {
e.printStackTrace()
echoUnknownCmd(single_command.name)
}
}

View File

@@ -13,6 +13,7 @@ import net.torvald.terrarum.blockproperties.BlockPropUtil
import net.torvald.terrarum.gameactors.*
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
import net.torvald.terrarum.gameitems.ItemID
import net.torvald.terrarum.gameparticles.ParticleBase
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.modulebasegame.gameactors.ActorHumanoid
import net.torvald.terrarum.gameworld.WorldTime
@@ -22,6 +23,7 @@ import net.torvald.terrarum.modulebasegame.ui.UIPaletteSelector
import net.torvald.terrarum.weather.WeatherMixer
import net.torvald.terrarum.ui.UINSMenu
import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.util.CircularArray
/**
* Created by minjaesong on 2018-07-06.
@@ -385,10 +387,21 @@ class BuildingMaker(batch: SpriteBatch) : IngameInstance(batch) {
BlockPropUtil.dynamicLumFuncTickClock()
}
private val particles = CircularArray<ParticleBase>(16, true)
private fun renderGame() {
_testMarkerDrawCalls = 0L
IngameRenderer.invoke(false, actorsRenderOverlay = if (showSelection) actorsRenderOverlay + essentialOverlays else essentialOverlays, uiContainer = uiContainer)
IngameRenderer.invoke(false,
1f,
listOf(),
listOf(),
listOf(),
listOf(),
if (showSelection) actorsRenderOverlay + essentialOverlays else essentialOverlays,
particles,
uiContainer = uiContainer
)
App.setDebugTime("Test.MarkerDrawCalls", _testMarkerDrawCalls)
}

View File

@@ -12,6 +12,7 @@ import com.badlogic.gdx.utils.GdxRuntimeException
import net.torvald.random.HQRNG
import net.torvald.terrarum.*
import net.torvald.terrarum.App.measureDebugTime
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
import net.torvald.terrarum.gameactors.ActorWithBody
@@ -196,22 +197,20 @@ object IngameRenderer : Disposable {
operator fun invoke(
gamePaused: Boolean,
zoom: Float = 1f,
actorsRenderBehind : List<ActorWithBody>? = null,
actorsRenderMiddle : List<ActorWithBody>? = null,
actorsRenderMidTop : List<ActorWithBody>? = null,
actorsRenderFront : List<ActorWithBody>? = null,
actorsRenderOverlay: List<ActorWithBody>? = null,
particlesContainer : CircularArray<ParticleBase>? = null,
actorsRenderBehind : List<ActorWithBody>,
actorsRenderMiddle : List<ActorWithBody>,
actorsRenderMidTop : List<ActorWithBody>,
actorsRenderFront : List<ActorWithBody>,
actorsRenderOverlay: List<ActorWithBody>,
particlesContainer : CircularArray<ParticleBase>,
player: ActorWithBody? = null,
uiContainer: UIContainer? = null
) {
renderingActorsCount = (actorsRenderBehind?.size ?: 0) +
(actorsRenderMiddle?.size ?: 0) +
(actorsRenderMidTop?.size ?: 0) +
(actorsRenderFront?.size ?: 0) +
(actorsRenderOverlay?.size ?: 0)
//renderingParticleCount = particlesContainer?.size ?: 0
//renderingParticleCount = (particlesContainer?.buffer?.map { (!it.flagDespawn).toInt() } ?: listOf(0)).sum()
renderingActorsCount = (actorsRenderBehind.size) +
(actorsRenderMiddle.size) +
(actorsRenderMidTop.size) +
(actorsRenderFront.size) +
(actorsRenderOverlay.size)
renderingUIsCount = uiContainer?.countVisible() ?: 0
invokeInit()
@@ -225,8 +224,9 @@ object IngameRenderer : Disposable {
if (!gamePaused || newWorldLoadedLatch) {
measureDebugTime("Renderer.LightRun*") {
// recalculate for even frames, or if the sign of the cam-x changed
if (App.GLOBAL_RENDER_TIMER % 3 == 0 || Math.abs(WorldCamera.x - oldCamX) >= world.width * 0.85f * TILE_SIZEF || newWorldLoadedLatch) {
LightmapRenderer.fireRecalculateEvent(actorsRenderBehind, actorsRenderFront, actorsRenderMidTop, actorsRenderMiddle, actorsRenderOverlay)
if (App.GLOBAL_RENDER_TIMER % 80 == 0 || Math.abs(WorldCamera.x - oldCamX) >= world.width * 0.85f * TILE_SIZEF || newWorldLoadedLatch) {
printdbg(this, "LightmapRenderer requestRecalculation")
LightmapRenderer.requestRecalculation { actorsRenderBehind + actorsRenderFront + actorsRenderMidTop + actorsRenderMiddle + actorsRenderOverlay }
}
oldCamX = WorldCamera.x
}

View File

@@ -19,6 +19,7 @@ import net.torvald.terrarum.console.CommandDict
import net.torvald.terrarum.gameactors.*
import net.torvald.terrarum.gameactors.ai.ActorAI
import net.torvald.terrarum.gamecontroller.TerrarumKeyboardEvent
import net.torvald.terrarum.gameparticles.ParticleBase
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.WorldTime
import net.torvald.terrarum.gameworld.fmod
@@ -31,6 +32,7 @@ import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.weather.WeatherMixer
import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.util.CircularArray
import java.io.IOException
import kotlin.math.atan2
import kotlin.math.cos
@@ -285,6 +287,8 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
uiContainer.forEach { it?.update(delta) }
}
private val particles = CircularArray<ParticleBase>(16, true)
fun renderScreen() {
Gdx.graphics.setTitle(TerrarumIngame.getCanonicalTitle())
@@ -296,7 +300,17 @@ class TitleScreen(batch: SpriteBatch) : IngameInstance(batch) {
if (!demoWorld.layerTerrain.ptr.destroyed) { // FIXME q&d hack to circumvent the dangling pointer issue #26
IngameRenderer.invoke(gamePaused = false, uiContainer = uiContainer)
IngameRenderer.invoke(
false,
1f,
listOf(),
listOf(),
listOf(),
listOf(),
listOf(),
particles,
uiContainer = uiContainer
)
}
else {
printdbgerr(this, "Demoworld is already been destroyed")

View File

@@ -1,36 +0,0 @@
package net.torvald.terrarum.modulebasegame.console
import com.badlogic.gdx.Gdx
import com.badlogic.gdx.Input
import net.torvald.terrarum.console.ConsoleAlias
import net.torvald.terrarum.console.ConsoleCommand
import net.torvald.terrarum.console.Echo
//import net.torvald.terrarum.swingapp.IMStringReader
/**
* Created by minjaesong on 2017-02-05.
*/
@ConsoleAlias("imtest")
internal object JavaIMTest : ConsoleCommand {
override fun execute(args: Array<String>) {
/*IMStringReader(
{ Echo("[JavaIMTest -> IMStringReader] $it") }, // send input to Echo
"JavaIMTest"
)*/
val inputListener = object : Input.TextInputListener {
override fun input(text: String?) {
Echo("[TextInputText] $text")
}
override fun canceled() {
Echo("[TextInputText] (input canceled)")
}
}
Gdx.input.getTextInput(inputListener, "TextInputTest", "", "type anything!")
}
override fun printUsage() {
Echo("Tests Swing input window to get non-English text input")
}
}

View File

@@ -1,20 +0,0 @@
package net.torvald.terrarum.modulebasegame.console
import net.torvald.terrarum.console.ConsoleAlias
import net.torvald.terrarum.console.ConsoleCommand
import net.torvald.terrarum.console.Echo
/**
* Created by minjaesong on 2016-07-04.
*/
@ConsoleAlias("tips")
internal object PrintRandomTips : ConsoleCommand {
override fun execute(args: Array<String>) {
Echo("Nope.")
//Echo(Lang["GAME_TIPS_${Random().nextInt(Lang.TIPS_COUNT) + 1}"])
}
override fun printUsage() {
Echo("Prints random tips for game.")
}
}

View File

@@ -1,26 +0,0 @@
package net.torvald.terrarum.modulebasegame.console
import net.torvald.terrarum.INGAME
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.console.ConsoleCommand
import net.torvald.terrarum.console.Echo
import net.torvald.terrarum.modulebasegame.gameactors.PhysTestLuarLander
/**
* Created by minjaesong on 2018-01-18.
*/
internal object SpawnPhysTestLunarLander : ConsoleCommand {
override fun execute(args: Array<String>) {
val mouseX = Terrarum.mouseX
val mouseY = Terrarum.mouseY
val lander = PhysTestLuarLander()
lander.setPosition(mouseX, mouseY)
INGAME.queueActorAddition(lander)
}
override fun printUsage() {
Echo("control it with arrow keys")
}
}

View File

@@ -1,26 +0,0 @@
package net.torvald.terrarum.modulebasegame.console
import net.torvald.terrarum.INGAME
import net.torvald.terrarum.console.ConsoleCommand
import net.torvald.terrarum.console.Echo
import net.torvald.terrarum.modulebasegame.gameactors.DecodeTapestry
import java.io.File
/**
* Created by minjaesong on 2017-01-14.
*/
internal object SpawnTapestry : ConsoleCommand {
override fun execute(args: Array<String>) {
if (args.size < 2) {
printUsage()
return
}
val tapestry = DecodeTapestry(File(args[1]))
INGAME.queueActorAddition(tapestry)
}
override fun printUsage() {
Echo("Usage: spawntapestry <tapestry_file>")
}
}

View File

@@ -1,25 +0,0 @@
package net.torvald.terrarum.modulebasegame.console
import net.torvald.terrarum.INGAME
import net.torvald.terrarum.Terrarum
import net.torvald.terrarum.console.ConsoleCommand
import net.torvald.terrarum.console.ConsoleNoExport
import net.torvald.terrarum.console.Echo
import net.torvald.terrarum.modulebasegame.gameactors.FixtureTikiTorch
/**
* Created by minjaesong on 2016-12-17.
*/
@ConsoleNoExport
internal object SpawnTikiTorch : ConsoleCommand {
override fun execute(args: Array<String>) {
val torch = FixtureTikiTorch()
torch.setPosition(Terrarum.mouseX, Terrarum.mouseY)
INGAME.queueActorAddition(torch)
}
override fun printUsage() {
Echo("Usage: spawntorch")
}
}

View File

@@ -3,9 +3,11 @@ package net.torvald.terrarum.worlddrawer
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.Pixmap
import com.badlogic.gdx.graphics.Texture
import net.torvald.UnsafeHelper
import net.torvald.gdx.graphics.Cvec
import net.torvald.gdx.graphics.UnsafeCvecArray
import net.torvald.terrarum.*
import net.torvald.terrarum.App.measureDebugTime
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.blockproperties.Block
@@ -19,6 +21,8 @@ import net.torvald.terrarum.modulebasegame.IngameRenderer
import net.torvald.terrarum.modulebasegame.ui.abs
import net.torvald.terrarum.realestate.LandUtil
import java.util.*
import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicInteger
import kotlin.math.roundToInt
import kotlin.system.exitProcess
@@ -50,6 +54,7 @@ object LightmapRenderer {
printdbg(this, "World change detected -- old world: ${this.world.hashCode()}, new world: ${world.hashCode()}")
lightmap.zerofill()
_lightmap.zerofill()
_mapLightLevelThis.zerofill()
_mapThisTileOpacity.zerofill()
_mapThisTileOpacity2.zerofill()
@@ -60,8 +65,6 @@ object LightmapRenderer {
}
finally {
this.world = world
//fireRecalculateEvent()
}
}
@@ -82,15 +85,11 @@ object LightmapRenderer {
*/
// it utilises alpha channel to determine brightness of "glow" sprites (so that alpha channel works like UV light)
private var lightmap = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
private var _lightmap = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
private var _mapLightLevelThis = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
private var _mapThisTileOpacity = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
private var _mapThisTileOpacity2 = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
init {
LightmapHDRMap.invoke()
printdbg(this, "Overscan open: $overscan_open; opaque: $overscan_opaque")
}
private const val AIR = Block.AIR
const val DRAW_TILE_SIZE: Float = TILE_SIZE / IngameRenderer.lightmapDownsample
@@ -141,7 +140,67 @@ object LightmapRenderer {
}
}
fun fireRecalculateEvent(vararg actorContainers: List<ActorWithBody>?) {
internal var rendererStatus = AtomicInteger(2) // 0: processing queued, 1: processing, 2: done
private var lightmapPrepared = AtomicBoolean(false)
private val runnerLock = java.lang.Object()
private val runner = Runnable { while (!Thread.interrupted()) {
if (rendererStatus.get() == 0) {
measureDebugTime("Renderer.LightCalcThread") {
rendererStatus.incrementAndGet() // 0 -> 1
val unlock = lightmapPrepared.get()
if (unlock) {
try {
printdbg(this, "Recalculate!") // should recalculate once on request, not every f'ing frame
recalculate(actorsGetter(), _lightmap)
// dispatch _lightmap to lightmap
UnsafeHelper.memcpy(_lightmap.ptr, lightmap.ptr, lightmap.TOTAL_SIZE_IN_BYTES)
// visuals being "jittery" means you're not dispatching the lightmap correctly
}
catch (e: NullPointerException) {
System.err.println("NPE; lightmapPrepared = $unlock")
throw e
}
}
rendererStatus.incrementAndGet() // 1 -> 2
}
}
else {
// Thread.sleep(1L)
synchronized(runnerLock) { runnerLock.wait() }
}
} }
private val lightCalcThread = Thread(runner, "LightCalcThread")
init {
LightmapHDRMap.invoke()
printdbg(this, "Overscan open: $overscan_open; opaque: $overscan_opaque")
lightCalcThread.start()
}
/**
* Request recalculation of the light. When it's not a tick to recalculate, or recalculation is ongoing,
* the request will be silently disregarded.
*/
fun requestRecalculation(actorContainers: () -> List<ActorWithBody>) {
if (rendererStatus.get() == 2) {
actorsGetter = actorContainers
rendererStatus.set(0)
synchronized(runnerLock) { runnerLock.notifyAll() }
}
}
private var actorsGetter: () -> List<ActorWithBody> = { listOf() }
private fun recalculate(actorContainers: List<ActorWithBody>, lightmap: UnsafeCvecArray) {
try {
world.getTileFromTerrain(0, 0) // test inquiry
}
@@ -149,7 +208,7 @@ object LightmapRenderer {
return // quit prematurely
}
catch (e: NullPointerException) {
System.err.println("[LightmapRendererNew.fireRecalculateEvent] Attempted to refer destroyed unsafe array " +
System.err.println("[LightmapRendererNew.recalculate] Attempted to refer destroyed unsafe array " +
"(${world.layerTerrain.ptr})")
e.printStackTrace()
return // something's wrong but we'll ignore it like a trustful AK
@@ -205,27 +264,29 @@ object LightmapRenderer {
// 'NEWLIGHT2' LIGHT SWIPER
// O((8*2)n) where n is a size of the map.
/* - */fun r1() {
/* - */fun r1(lightmap: UnsafeCvecArray) {
swipeDiag = false
for (line in 1 until LIGHTMAP_HEIGHT - 1) {
swipeLight(
1, line,
LIGHTMAP_WIDTH - 2, line,
1, 0
1, 0,
lightmap
)
}
}
/* | */fun r2() {
/* | */fun r2(lightmap: UnsafeCvecArray) {
swipeDiag = false
for (line in 1 until LIGHTMAP_WIDTH - 1) {
swipeLight(
line, 1,
line, LIGHTMAP_HEIGHT - 2,
0, 1
0, 1,
lightmap
)
}
}
/* \ */fun r3() {
/* \ */fun r3(lightmap: UnsafeCvecArray) {
swipeDiag = true
/* construct indices such that:
56789ABC
@@ -258,11 +319,12 @@ object LightmapRenderer {
swipeLight(
maxOf(1, i - LIGHTMAP_HEIGHT + 4), maxOf(1, LIGHTMAP_HEIGHT - 2 - i),
minOf(LIGHTMAP_WIDTH - 2, i + 1), minOf(LIGHTMAP_HEIGHT - 2, (LIGHTMAP_WIDTH + LIGHTMAP_HEIGHT - 5) - i),
1, 1
1, 1,
lightmap
)
}
}
/* / */fun r4() {
/* / */fun r4(lightmap: UnsafeCvecArray) {
swipeDiag = true
/*
1 w-2
@@ -291,7 +353,8 @@ object LightmapRenderer {
swipeLight(
maxOf(1, i - LIGHTMAP_HEIGHT + 4), minOf(LIGHTMAP_HEIGHT - 2, i + 1),
minOf(LIGHTMAP_WIDTH - 2, i + 1), maxOf(1, (LIGHTMAP_HEIGHT - 2) - (LIGHTMAP_WIDTH + LIGHTMAP_HEIGHT - 6) + i),
1, -1
1, -1,
lightmap
)
}
}
@@ -313,34 +376,33 @@ object LightmapRenderer {
// why dark spots appear in the first place)
// - Multithreading? I have absolutely no idea.
// - If you naively slice the screen (job area) to multithread, the seam will appear.
r1();r2();r3();r4()
r1();r2();r3();r4() // two looks better than one
r1(lightmap);r2(lightmap);r3(lightmap);r4(lightmap)
r1(lightmap);r2(lightmap);r3(lightmap);r4(lightmap) // two looks better than one
// no rendering trickery will eliminate the need of 2nd pass, even the "decay out"
}
}
private fun buildLanternmap(actorContainers: Array<out List<ActorWithBody>?>) {
private fun buildLanternmap(actorContainer: List<ActorWithBody>) {
lanternMap.clear()
actorContainers.forEach { actorContainer ->
actorContainer?.forEach {
if (it is Luminous) {
// put lanterns to the area the luminantBox is occupying
for (lightBox in it.lightBoxList) {
val lightBoxX = it.hitbox.startX + lightBox.startX
val lightBoxY = it.hitbox.startY + lightBox.startY
val lightBoxW = lightBox.width
val lightBoxH = lightBox.height
for (y in lightBoxY.div(TILE_SIZE).floorInt()
..lightBoxY.plus(lightBoxH).div(TILE_SIZE).floorInt()) {
for (x in lightBoxX.div(TILE_SIZE).floorInt()
..lightBoxX.plus(lightBoxW).div(TILE_SIZE).floorInt()) {
actorContainer.forEach {
if (it is Luminous) {
val lightBoxCopy = it.lightBoxList.subList(0, it.lightBoxList.size) // make copy to prevent ConcurrentModificationException
val normalisedCvec = it.color//.cpy().mul(DIV_FLOAT)
// put lanterns to the area the luminantBox is occupying
for (lightBox in lightBoxCopy) {
val lightBoxX = it.hitbox.startX + lightBox.startX
val lightBoxY = it.hitbox.startY + lightBox.startY
val lightBoxW = lightBox.width
val lightBoxH = lightBox.height
for (y in lightBoxY.div(TILE_SIZE).floorInt()
..lightBoxY.plus(lightBoxH).div(TILE_SIZE).floorInt()) {
for (x in lightBoxX.div(TILE_SIZE).floorInt()
..lightBoxX.plus(lightBoxW).div(TILE_SIZE).floorInt()) {
lanternMap[LandUtil.getBlockAddr(world, x, y)] = normalisedCvec
}
val normalisedCvec = it.color//.cpy().mul(DIV_FLOAT)
lanternMap[LandUtil.getBlockAddr(world, x, y)] = normalisedCvec
}
}
}
@@ -522,7 +584,7 @@ object LightmapRenderer {
private var swipeX = -1
private var swipeY = -1
private var swipeDiag = false
private fun _swipeTask(x: Int, y: Int, x2: Int, y2: Int) {
private fun _swipeTask(x: Int, y: Int, x2: Int, y2: Int, lightmap: UnsafeCvecArray) {
if (x2 < 0 || y2 < 0 || x2 >= LIGHTMAP_WIDTH || y2 >= LIGHTMAP_HEIGHT) return
_ambientAccumulator.r = _mapLightLevelThis.getR(x, y)
@@ -535,25 +597,25 @@ object LightmapRenderer {
_thisTileOpacity.g = _mapThisTileOpacity.getG(x, y)
_thisTileOpacity.b = _mapThisTileOpacity.getB(x, y)
_thisTileOpacity.a = _mapThisTileOpacity.getA(x, y)
_ambientAccumulator.maxAndAssign(darkenColoured(x2, y2, _thisTileOpacity))
_ambientAccumulator.maxAndAssign(darkenColoured(x2, y2, _thisTileOpacity, lightmap))
}
else {
_thisTileOpacity2.r = _mapThisTileOpacity2.getR(x, y)
_thisTileOpacity2.g = _mapThisTileOpacity2.getG(x, y)
_thisTileOpacity2.b = _mapThisTileOpacity2.getB(x, y)
_thisTileOpacity2.a = _mapThisTileOpacity2.getA(x, y)
_ambientAccumulator.maxAndAssign(darkenColoured(x2, y2, _thisTileOpacity2))
_ambientAccumulator.maxAndAssign(darkenColoured(x2, y2, _thisTileOpacity2, lightmap))
}
_mapLightLevelThis.setVec(x, y, _ambientAccumulator)
lightmap.setVec(x, y, _ambientAccumulator)
}
private fun swipeLight(sx: Int, sy: Int, ex: Int, ey: Int, dx: Int, dy: Int) {
private fun swipeLight(sx: Int, sy: Int, ex: Int, ey: Int, dx: Int, dy: Int, lightmap: UnsafeCvecArray) {
swipeX = sx; swipeY = sy
while (swipeX*dx <= ex*dx && swipeY*dy <= ey*dy) {
// conduct the task #1
// spread towards the end
_swipeTask(swipeX, swipeY, swipeX-dx, swipeY-dy)
_swipeTask(swipeX, swipeY, swipeX-dx, swipeY-dy, lightmap)
swipeX += dx
swipeY += dy
@@ -563,7 +625,7 @@ object LightmapRenderer {
while (swipeX*dx >= sx*dx && swipeY*dy >= sy*dy) {
// conduct the task #2
// spread towards the start
_swipeTask(swipeX, swipeY, swipeX+dx, swipeY+dy)
_swipeTask(swipeX, swipeY, swipeX+dx, swipeY+dy, lightmap)
swipeX -= dx
swipeY -= dy
@@ -662,10 +724,14 @@ object LightmapRenderer {
}
fun dispose() {
lightCalcThread.interrupt()
LightmapHDRMap.dispose()
_lightBufferAsTex.dispose()
lightBuffer.dispose()
lightmapPrepared.set(false)
lightmap.destroy()
_mapLightLevelThis.destroy()
_mapThisTileOpacity.destroy()
@@ -682,7 +748,7 @@ object LightmapRenderer {
* @param darken (0-255) per channel
* @return darkened data (0-255) per channel
*/
fun darkenColoured(x: Int, y: Int, darken: Cvec): Cvec {
internal fun darkenColoured(x: Int, y: Int, darken: Cvec, lightmap: UnsafeCvecArray): Cvec {
// use equation with magic number 8.0
// this function, when done recursively (A_x = darken(A_x-1, C)), draws exponential curve. (R^2 = 1)
@@ -736,10 +802,13 @@ object LightmapRenderer {
private var _init = false
fun resize(screenW: Int, screenH: Int) {
lightmapPrepared.set(false)
/*
// make sure the BlocksDrawer is resized first!
// copied from BlocksDrawer, duh!
// FIXME 'lightBuffer' is not zoomable in this way
val tilesInHorizontal = (App.scr.wf / TILE_SIZE).ceilInt() + 1 + LIGHTMAP_OVERRENDER * 2
val tilesInVertical = (App.scr.hf / TILE_SIZE).ceilInt() + 1 + LIGHTMAP_OVERRENDER * 2
@@ -754,14 +823,19 @@ object LightmapRenderer {
}
lightBuffer = Pixmap(tilesInHorizontal, tilesInVertical, Pixmap.Format.RGBA8888)
lightmap.destroy()
_lightmap.destroy()
_mapLightLevelThis.destroy()
_mapThisTileOpacity.destroy()
_mapThisTileOpacity2.destroy()
lightmap = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
_lightmap = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
_mapLightLevelThis = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
_mapThisTileOpacity = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
_mapThisTileOpacity2 = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)
_mapThisTileOpacity2 = UnsafeCvecArray(LIGHTMAP_WIDTH, LIGHTMAP_HEIGHT)*/
lightmapPrepared.set(true)
printdbg(this, "Resize event")
}