mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-06 08:38:30 +09:00
half-assed but working radiator with no directional quirks
This commit is contained in:
@@ -1,6 +1,6 @@
|
|||||||
*Terrarum*
|
*Terrarum*
|
||||||
|
|
||||||
Copyright (C) 2013-2019 Minjaesong (Torvald)
|
Copyright (C) 2013-2020 Minjaesong (Torvald)
|
||||||
|
|
||||||
This program is free software: you can redistribute it and/or modify
|
This program is free software: you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
|
|||||||
@@ -235,8 +235,8 @@ object LightmapRenderer {
|
|||||||
|
|
||||||
|
|
||||||
// pre-seed the lightmap with known value
|
// pre-seed the lightmap with known value
|
||||||
for (x in for_x_start - overscan_open + 1..for_x_end + overscan_open - 1) {
|
for (x in for_x_start - overscan_open..for_x_end + overscan_open) {
|
||||||
for (y in for_y_start - overscan_open + 1..for_y_end + overscan_open - 1) {
|
for (y in for_y_start - overscan_open..for_y_end + overscan_open) {
|
||||||
val tile = world.getTileFromTerrain(x, y)
|
val tile = world.getTileFromTerrain(x, y)
|
||||||
val wall = world.getTileFromWall(x, y)
|
val wall = world.getTileFromWall(x, y)
|
||||||
|
|
||||||
@@ -267,6 +267,39 @@ object LightmapRenderer {
|
|||||||
// O((5*9)n) == O(n) where n is a size of the map.
|
// O((5*9)n) == O(n) where n is a size of the map.
|
||||||
// Because of inevitable overlaps on the area, it only works with MAX blend
|
// Because of inevitable overlaps on the area, it only works with MAX blend
|
||||||
|
|
||||||
|
fun r1() {
|
||||||
|
// Round 1
|
||||||
|
for (y in for_y_start - overscan_open..for_y_end + overscan_open) {
|
||||||
|
for (x in for_x_start - overscan_open..for_x_end + overscan_open) {
|
||||||
|
calculateAndAssign(lightmap, x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun r2() {
|
||||||
|
// Round 2
|
||||||
|
for (y in for_y_end + overscan_open downTo for_y_start - overscan_open) {
|
||||||
|
for (x in for_x_start - overscan_open..for_x_end + overscan_open) {
|
||||||
|
calculateAndAssign(lightmap, x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun r3() {
|
||||||
|
// Round 3
|
||||||
|
for (y in for_y_end + overscan_open downTo for_y_start - overscan_open) {
|
||||||
|
for (x in for_x_end + overscan_open downTo for_x_start - overscan_open) {
|
||||||
|
calculateAndAssign(lightmap, x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fun r4() {
|
||||||
|
// Round 4
|
||||||
|
for (y in for_y_start - overscan_open..for_y_end + overscan_open) {
|
||||||
|
for (x in for_x_end + overscan_open downTo for_x_start - overscan_open) {
|
||||||
|
calculateAndAssign(lightmap, x, y)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// each usually takes 8 000 000..12 000 000 miliseconds total when not threaded
|
// each usually takes 8 000 000..12 000 000 miliseconds total when not threaded
|
||||||
|
|
||||||
@@ -276,80 +309,25 @@ object LightmapRenderer {
|
|||||||
// in this case we have 'spillage' due to the fact calculate() samples 3x3 area.
|
// in this case we have 'spillage' due to the fact calculate() samples 3x3 area.
|
||||||
|
|
||||||
AppLoader.measureDebugTime("Renderer.LightTotal") {
|
AppLoader.measureDebugTime("Renderer.LightTotal") {
|
||||||
// Round 1
|
|
||||||
for (y in for_y_start - overscan_open..for_y_end) {
|
|
||||||
for (x in for_x_start - overscan_open..for_x_end) {
|
|
||||||
calculateAndAssign(lightmap, x, y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Round 2
|
|
||||||
for (y in for_y_end + overscan_open downTo for_y_start) {
|
|
||||||
for (x in for_x_start - overscan_open..for_x_end) {
|
|
||||||
calculateAndAssign(lightmap, x, y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Round 3
|
|
||||||
for (y in for_y_end + overscan_open downTo for_y_start) {
|
|
||||||
for (x in for_x_end + overscan_open downTo for_x_start) {
|
|
||||||
calculateAndAssign(lightmap, x, y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Round 4
|
|
||||||
for (y in for_y_start - overscan_open..for_y_end) {
|
|
||||||
for (x in for_x_end + overscan_open downTo for_x_start) {
|
|
||||||
calculateAndAssign(lightmap, x, y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Round 1
|
|
||||||
for (y in for_y_start - overscan_open..for_y_end) {
|
|
||||||
for (x in for_x_start - overscan_open..for_x_end) {
|
|
||||||
calculateAndAssign(lightmap, x, y)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// per-channel version is slower...
|
|
||||||
/*repeat(4) { channel ->
|
//r1();r2();r3();r4()
|
||||||
// Round 1
|
|
||||||
for (y in for_y_start - overscan_open..for_y_end) {
|
|
||||||
for (x in for_x_start - overscan_open..for_x_end) {
|
// ANECDOTES
|
||||||
calculateAndAssign(lightmap, x, y, channel)
|
// * Radiate-from-light-source idea is doomed because skippable cells are completely random
|
||||||
}
|
// * Spread-every-cell idea might work as skippable cells are predictable, and they're related
|
||||||
}
|
// to the pos of lightsources
|
||||||
// Round 2
|
// * No-op masks cause some ambient ray to disappear when they're on the screen edge
|
||||||
for (y in for_y_end + overscan_open downTo for_y_start) {
|
|
||||||
for (x in for_x_start - overscan_open..for_x_end) {
|
|
||||||
calculateAndAssign(lightmap, x, y, channel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Round 3
|
|
||||||
for (y in for_y_end + overscan_open downTo for_y_start) {
|
|
||||||
for (x in for_x_end + overscan_open downTo for_x_start) {
|
|
||||||
calculateAndAssign(lightmap, x, y, channel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Round 4
|
|
||||||
for (y in for_y_start - overscan_open..for_y_end) {
|
|
||||||
for (x in for_x_end + overscan_open downTo for_x_start) {
|
|
||||||
calculateAndAssign(lightmap, x, y, channel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Round 1
|
|
||||||
for (y in for_y_start - overscan_open..for_y_end) {
|
|
||||||
for (x in for_x_start - overscan_open..for_x_end) {
|
|
||||||
calculateAndAssign(lightmap, x, y, channel)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}*/
|
|
||||||
|
|
||||||
// per-channel operation for bit more aggressive optimisation
|
// per-channel operation for bit more aggressive optimisation
|
||||||
/*for (lightsource in lightsourceMap) {
|
for (lightsource in lightsourceMap) {
|
||||||
val (lsx, lsy) = LandUtil.resolveBlockAddr(world, lightsource.key)
|
val (lsx, lsy) = LandUtil.resolveBlockAddr(world, lightsource.key)
|
||||||
|
|
||||||
if (lsx !in for_x_start - overscan_open + 1..for_x_end + overscan_open - 1 || lsy !in for_y_start - overscan_open + 1..for_y_end + overscan_open - 1)
|
// lightmap MUST BE PRE-SEEDED from known lightsources!
|
||||||
continue
|
|
||||||
|
|
||||||
repeat(4) { rgbaOffset ->
|
repeat(4) { rgbaOffset ->
|
||||||
for (genus in 1..6) { // use of overscan_open for loop limit is completely arbitrary
|
for (genus in 1..12) { // use of overscan_open for loop limit is completely arbitrary
|
||||||
val rimSize = 1 + 2 * genus
|
val rimSize = 1 + 2 * genus
|
||||||
|
|
||||||
var skip = true
|
var skip = true
|
||||||
@@ -378,7 +356,7 @@ object LightmapRenderer {
|
|||||||
if (skip) break
|
if (skip) break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}*/
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else if (world.worldIndex != -1) { // to avoid updating on the null world
|
else if (world.worldIndex != -1) { // to avoid updating on the null world
|
||||||
@@ -426,7 +404,7 @@ object LightmapRenderer {
|
|||||||
private fun radiate(channel: Int, wx: Int, wy: Int, lightsource: Cvec, distSqr: Int): Boolean {
|
private fun radiate(channel: Int, wx: Int, wy: Int, lightsource: Cvec, distSqr: Int): Boolean {
|
||||||
val lx = wx.convX(); val ly = wy.convY()
|
val lx = wx.convX(); val ly = wy.convY()
|
||||||
|
|
||||||
if (lx !in 1..lightmap.width - 1 || ly !in 1..lightmap.height - 1)
|
if (lx !in 0 until LIGHTMAP_WIDTH || ly !in 0 until LIGHTMAP_HEIGHT)
|
||||||
return true
|
return true
|
||||||
|
|
||||||
val currentLightLevel = lightmap.channelGet(lx, ly, channel)
|
val currentLightLevel = lightmap.channelGet(lx, ly, channel)
|
||||||
@@ -441,15 +419,42 @@ object LightmapRenderer {
|
|||||||
//brightestNeighbour = maxOf(brightestNeighbour, lightmap.channelGet(lx + 1, ly - 1, channel) * 0.70710678f)
|
//brightestNeighbour = maxOf(brightestNeighbour, lightmap.channelGet(lx + 1, ly - 1, channel) * 0.70710678f)
|
||||||
//brightestNeighbour = maxOf(brightestNeighbour, lightmap.channelGet(lx + 1, ly + 1, channel) * 0.70710678f)
|
//brightestNeighbour = maxOf(brightestNeighbour, lightmap.channelGet(lx + 1, ly + 1, channel) * 0.70710678f)
|
||||||
|
|
||||||
val newLight = brightestNeighbour - attenuate
|
val newLight = brightestNeighbour * (1f - attenuate * lightScalingMagic)
|
||||||
|
|
||||||
if (newLight <= currentLightLevel) return true
|
if (newLight <= currentLightLevel || newLight < epsilon) return true
|
||||||
|
|
||||||
lightmap.channelSet(lx, ly, channel, newLight)
|
lightmap.channelSet(lx, ly, channel, newLight)
|
||||||
|
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private fun radiate2(lightmap: UnsafeCvecArray, worldX: Int, worldY: Int, lightsource: Cvec): Boolean {
|
||||||
|
if (inNoopMask(worldX, worldY)) return false
|
||||||
|
|
||||||
|
// just quick snippets to make test work
|
||||||
|
lightLevelThis.set(colourNull)
|
||||||
|
thisTileOpacity.set(BlockCodex[world.getTileFromTerrain(worldX, worldY)].opacity)
|
||||||
|
|
||||||
|
val x = worldX.convX()
|
||||||
|
val y = worldY.convY()
|
||||||
|
|
||||||
|
/* + *///lightLevelThis.maxAndAssign(darkenColoured(x - 1, y - 1, thisTileOpacity2))
|
||||||
|
/* + *///lightLevelThis.maxAndAssign(darkenColoured(x + 1, y - 1, thisTileOpacity2))
|
||||||
|
/* + *///lightLevelThis.maxAndAssign(darkenColoured(x - 1, y + 1, thisTileOpacity2))
|
||||||
|
/* + *///lightLevelThis.maxAndAssign(darkenColoured(x + 1, y + 1, thisTileOpacity2))
|
||||||
|
/* * */lightLevelThis.maxAndAssign(darkenColoured(x, y - 1, thisTileOpacity))
|
||||||
|
/* * */lightLevelThis.maxAndAssign(darkenColoured(x, y + 1, thisTileOpacity))
|
||||||
|
/* * */lightLevelThis.maxAndAssign(darkenColoured(x - 1, y, thisTileOpacity))
|
||||||
|
/* * */lightLevelThis.maxAndAssign(darkenColoured(x + 1, y, thisTileOpacity))
|
||||||
|
|
||||||
|
lightmap.setR(x, y, lightLevelThis.r)
|
||||||
|
lightmap.setG(x, y, lightLevelThis.g)
|
||||||
|
lightmap.setB(x, y, lightLevelThis.b)
|
||||||
|
lightmap.setA(x, y, lightLevelThis.a)
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// TODO re-init at every resize
|
// TODO re-init at every resize
|
||||||
private lateinit var updateMessages: List<Array<ThreadedLightmapUpdateMessage>>
|
private lateinit var updateMessages: List<Array<ThreadedLightmapUpdateMessage>>
|
||||||
@@ -597,9 +602,9 @@ object LightmapRenderer {
|
|||||||
*/
|
*/
|
||||||
private fun getLightsAndShades(x: Int, y: Int) {
|
private fun getLightsAndShades(x: Int, y: Int) {
|
||||||
lightLevelThis.set(colourNull)
|
lightLevelThis.set(colourNull)
|
||||||
thisTerrain = world.getTileFromTerrain(x, y) ?: Block.STONE
|
thisTerrain = world.getTileFromTerrain(x, y)
|
||||||
thisFluid = world.getFluid(x, y)
|
thisFluid = world.getFluid(x, y)
|
||||||
thisWall = world.getTileFromWall(x, y) ?: Block.STONE
|
thisWall = world.getTileFromWall(x, y)
|
||||||
|
|
||||||
// regarding the issue #26
|
// regarding the issue #26
|
||||||
try {
|
try {
|
||||||
@@ -757,7 +762,7 @@ object LightmapRenderer {
|
|||||||
*/
|
*/
|
||||||
private fun calculateAndAssign(lightmap: UnsafeCvecArray, worldX: Int, worldY: Int) {
|
private fun calculateAndAssign(lightmap: UnsafeCvecArray, worldX: Int, worldY: Int) {
|
||||||
|
|
||||||
if (inNoopMask(worldX, worldY)) return
|
//if (inNoopMask(worldX, worldY)) return
|
||||||
|
|
||||||
// O(9n) == O(n) where n is a size of the map
|
// O(9n) == O(n) where n is a size of the map
|
||||||
|
|
||||||
|
|||||||
9
work_files/.directory
Normal file
9
work_files/.directory
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
[Dolphin]
|
||||||
|
SortRole=type
|
||||||
|
Timestamp=2020,2,22,4,4,10
|
||||||
|
Version=4
|
||||||
|
ViewMode=1
|
||||||
|
VisibleRoles=Details_text,Details_size,Details_modificationtime,Details_type,CustomizedDetails
|
||||||
|
|
||||||
|
[Settings]
|
||||||
|
HiddenFilesShown=true
|
||||||
8
work_files/GameDesign/.directory
Normal file
8
work_files/GameDesign/.directory
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[Dolphin]
|
||||||
|
Timestamp=2020,2,22,4,6,10
|
||||||
|
Version=4
|
||||||
|
ViewMode=1
|
||||||
|
VisibleRoles=Details_text,Details_size,Details_modificationtime,Details_type,CustomizedDetails
|
||||||
|
|
||||||
|
[Settings]
|
||||||
|
HiddenFilesShown=true
|
||||||
Binary file not shown.
BIN
work_files/spreadeverycell_overlapping_investigation.kra
Normal file
BIN
work_files/spreadeverycell_overlapping_investigation.kra
Normal file
Binary file not shown.
Reference in New Issue
Block a user