mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-16 08:36:07 +09:00
Lightmap: i'm only doing round 2-4-2 and it works?!
This commit is contained in:
176
src/net/torvald/terrarum/tests/NoopRectTest.kt
Normal file
176
src/net/torvald/terrarum/tests/NoopRectTest.kt
Normal file
@@ -0,0 +1,176 @@
|
|||||||
|
|
||||||
|
import com.badlogic.gdx.Game
|
||||||
|
import com.badlogic.gdx.Gdx
|
||||||
|
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.OrthographicCamera
|
||||||
|
import com.badlogic.gdx.graphics.Pixmap
|
||||||
|
import com.badlogic.gdx.graphics.Texture
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import net.torvald.random.HQRNG
|
||||||
|
import net.torvald.terrarum.Point2i
|
||||||
|
import net.torvald.terrarum.inUse
|
||||||
|
import net.torvald.terrarum.worlddrawer.toRGBA
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2019-02-04.
|
||||||
|
*/
|
||||||
|
class NoopRectTest(val appConfig: LwjglApplicationConfiguration) : Game() {
|
||||||
|
|
||||||
|
private val SIZE = 100
|
||||||
|
|
||||||
|
private val map = Array(SIZE + 2) { Array(SIZE + 2) { Color(0) } }
|
||||||
|
private lateinit var pixmap: Pixmap
|
||||||
|
private lateinit var texture: Texture
|
||||||
|
|
||||||
|
private lateinit var batch: SpriteBatch
|
||||||
|
private lateinit var camera: OrthographicCamera
|
||||||
|
|
||||||
|
private val DECAY_CONST = 16f/256f
|
||||||
|
private val DECAY_CONST2 = DECAY_CONST * 1.41421356f
|
||||||
|
|
||||||
|
val rng = HQRNG()
|
||||||
|
|
||||||
|
private val lightSources = Array<Point2i>(6) {
|
||||||
|
val rx = rng.nextInt(SIZE) + 1
|
||||||
|
val ry = rng.nextInt(SIZE) + 1
|
||||||
|
|
||||||
|
Point2i(rx, ry)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun create() {
|
||||||
|
pixmap = Pixmap(SIZE, SIZE, Pixmap.Format.RGBA8888)
|
||||||
|
pixmap.blending = Pixmap.Blending.None
|
||||||
|
texture = Texture(1, 1, Pixmap.Format.RGBA8888)
|
||||||
|
|
||||||
|
batch = SpriteBatch()
|
||||||
|
camera = OrthographicCamera(appConfig.width.toFloat(), appConfig.height.toFloat())
|
||||||
|
camera.setToOrtho(true)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun render() {
|
||||||
|
// clear
|
||||||
|
for (y in 0 until SIZE + 2) {
|
||||||
|
for (x in 0 until SIZE + 2) {
|
||||||
|
map[y][x] = Color(0)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// set light sources
|
||||||
|
lightSources.forEach {
|
||||||
|
map[it.y][it.x] = Color(-1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Round 2
|
||||||
|
for (y in SIZE - 1 downTo 0) {
|
||||||
|
for (x in 0 until SIZE) {
|
||||||
|
calculateAndAssign(x + 1, y + 1, 1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Round 3
|
||||||
|
for (y in SIZE - 1 downTo 0) {
|
||||||
|
for (x in SIZE - 1 downTo 0) {
|
||||||
|
calculateAndAssign(x + 1, y + 1, 2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Round 4
|
||||||
|
for (y in 0 until SIZE) {
|
||||||
|
for (x in SIZE - 1 downTo 0) {
|
||||||
|
calculateAndAssign(x + 1, y + 1, 3)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Round 1
|
||||||
|
for (y in 0 until SIZE) {
|
||||||
|
for (x in 0 until SIZE) {
|
||||||
|
calculateAndAssign(x + 1, y + 1, 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// make image
|
||||||
|
for (y in 0 until SIZE + 2) {
|
||||||
|
for (x in 0 until SIZE + 2) {
|
||||||
|
pixmap.drawPixel(x, y, map[y][x].toRGBA())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// draw image
|
||||||
|
texture.dispose()
|
||||||
|
texture = Texture(pixmap)
|
||||||
|
|
||||||
|
Gdx.graphics.setTitle("No-op Rectangle Test — F: ${Gdx.graphics.framesPerSecond}")
|
||||||
|
|
||||||
|
batch.inUse {
|
||||||
|
batch.projectionMatrix = camera.combined
|
||||||
|
batch.draw(texture, 0f, 0f, appConfig.width.toFloat(), appConfig.height.toFloat())
|
||||||
|
}
|
||||||
|
|
||||||
|
println()
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
private fun calculateAndAssign(x: Int, y: Int, pass: Int) {
|
||||||
|
val lightLevelThis = map[y][x]
|
||||||
|
|
||||||
|
lightLevelThis.maxAndAssign(map[y-1][x-1].darken2())
|
||||||
|
lightLevelThis.maxAndAssign(map[y-1][x+1].darken2())
|
||||||
|
lightLevelThis.maxAndAssign(map[y+1][x-1].darken2())
|
||||||
|
lightLevelThis.maxAndAssign(map[y+1][x+1].darken2())
|
||||||
|
|
||||||
|
lightLevelThis.maxAndAssign(map[y-1][x ].darken())
|
||||||
|
lightLevelThis.maxAndAssign(map[y+1][x ].darken())
|
||||||
|
lightLevelThis.maxAndAssign(map[y ][x-1].darken())
|
||||||
|
lightLevelThis.maxAndAssign(map[y ][x+1].darken())
|
||||||
|
|
||||||
|
if (map[y][x] == lightLevelThis) {
|
||||||
|
markDupes(x, y, pass)
|
||||||
|
}
|
||||||
|
|
||||||
|
map[y][x] = lightLevelThis
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun markDupes(x: Int, y: Int, pass: Int) {
|
||||||
|
//println("Duplicate at:\t$x\t$y\t$pass")
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Color.darken(): Color {
|
||||||
|
return Color(
|
||||||
|
this.r * (1f - DECAY_CONST),
|
||||||
|
this.g * (1f - DECAY_CONST),
|
||||||
|
this.b * (1f - DECAY_CONST),
|
||||||
|
this.a * (1f - DECAY_CONST)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Color.darken2(): Color {
|
||||||
|
return Color(
|
||||||
|
this.r * (1f - DECAY_CONST2),
|
||||||
|
this.g * (1f - DECAY_CONST2),
|
||||||
|
this.b * (1f - DECAY_CONST2),
|
||||||
|
this.a * (1f - DECAY_CONST2)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun Color.maxAndAssign(other: Color): Color {
|
||||||
|
this.set(
|
||||||
|
if (this.r > other.r) this.r else other.r,
|
||||||
|
if (this.g > other.g) this.g else other.g,
|
||||||
|
if (this.b > other.b) this.b else other.b,
|
||||||
|
if (this.a > other.a) this.a else other.a
|
||||||
|
)
|
||||||
|
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
fun main(args: Array<String>) {
|
||||||
|
val appConfig = LwjglApplicationConfiguration()
|
||||||
|
appConfig.forceExit = false
|
||||||
|
appConfig.width = 768
|
||||||
|
appConfig.height = 768
|
||||||
|
appConfig.backgroundFPS = 2
|
||||||
|
appConfig.foregroundFPS = 2
|
||||||
|
|
||||||
|
LwjglApplication(NoopRectTest(appConfig), appConfig)
|
||||||
|
}
|
||||||
@@ -12,14 +12,12 @@ import net.torvald.terrarum.blockproperties.Block
|
|||||||
import net.torvald.terrarum.blockproperties.BlockCodex
|
import net.torvald.terrarum.blockproperties.BlockCodex
|
||||||
import net.torvald.terrarum.blockproperties.Fluid
|
import net.torvald.terrarum.blockproperties.Fluid
|
||||||
import net.torvald.terrarum.concurrent.ParallelUtils.sliceEvenly
|
import net.torvald.terrarum.concurrent.ParallelUtils.sliceEvenly
|
||||||
import net.torvald.terrarum.concurrent.ThreadParallel
|
|
||||||
import net.torvald.terrarum.gameactors.ActorWBMovable
|
import net.torvald.terrarum.gameactors.ActorWBMovable
|
||||||
import net.torvald.terrarum.gameactors.Luminous
|
import net.torvald.terrarum.gameactors.Luminous
|
||||||
import net.torvald.terrarum.gameworld.BlockAddress
|
import net.torvald.terrarum.gameworld.BlockAddress
|
||||||
import net.torvald.terrarum.gameworld.GameWorld
|
import net.torvald.terrarum.gameworld.GameWorld
|
||||||
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
import net.torvald.terrarum.modulebasegame.IngameRenderer
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import java.util.concurrent.atomic.AtomicReferenceArray
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sub-portion of IngameRenderer. You are not supposed to directly deal with this.
|
* Sub-portion of IngameRenderer. You are not supposed to directly deal with this.
|
||||||
@@ -303,88 +301,41 @@ object LightmapRenderer {
|
|||||||
// because things are filled in subsequent frames ?
|
// because things are filled in subsequent frames ?
|
||||||
// because of not wiping out prev map ! (if pass=1 also calculates ambience, was disabled to not have to wipe out)
|
// because of not wiping out prev map ! (if pass=1 also calculates ambience, was disabled to not have to wipe out)
|
||||||
|
|
||||||
// Round 2
|
AppLoader.measureDebugTime("Renderer.LightTotal") {
|
||||||
AppLoader.measureDebugTime("Renderer.Light1") {
|
// Round 2
|
||||||
for (y in for_y_end + overscan_open downTo for_y_start) {
|
for (y in for_y_end + overscan_open downTo for_y_start) {
|
||||||
for (x in for_x_start - overscan_open..for_x_end) {
|
for (x in for_x_start - overscan_open..for_x_end) {
|
||||||
setLightOf(lightmap, x, y, calculate(x, y))
|
calculateAndAssign(lightmap, x, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// Round 3
|
||||||
|
/*for (y in for_y_end + overscan_open downTo for_y_start) {
|
||||||
// Round 3
|
|
||||||
AppLoader.measureDebugTime("Renderer.Light2") {
|
|
||||||
for (y in for_y_end + overscan_open downTo for_y_start) {
|
|
||||||
for (x in for_x_end + overscan_open downTo for_x_start) {
|
for (x in for_x_end + overscan_open downTo for_x_start) {
|
||||||
setLightOf(lightmap, x, y, calculate(x, y))
|
calculateAndAssign(lightmap, x, y)
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
}
|
// Round 4
|
||||||
|
|
||||||
// Round 4
|
|
||||||
AppLoader.measureDebugTime("Renderer.Light3") {
|
|
||||||
for (y in for_y_start - overscan_open..for_y_end) {
|
for (y in for_y_start - overscan_open..for_y_end) {
|
||||||
for (x in for_x_end + overscan_open downTo for_x_start) {
|
for (x in for_x_end + overscan_open downTo for_x_start) {
|
||||||
setLightOf(lightmap, x, y, calculate(x, y))
|
calculateAndAssign(lightmap, x, y)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
// Round 1
|
||||||
|
/*for (y in for_y_start - overscan_open..for_y_end) {
|
||||||
// Round 1
|
|
||||||
AppLoader.measureDebugTime("Renderer.Light4") {
|
|
||||||
for (y in for_y_start - overscan_open..for_y_end) {
|
|
||||||
for (x in for_x_start - overscan_open..for_x_end) {
|
for (x in for_x_start - overscan_open..for_x_end) {
|
||||||
setLightOf(lightmap, x, y, calculate(x, y))
|
calculateAndAssign(lightmap, x, y)
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
// Round 2 again
|
||||||
|
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)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
AppLoader.addDebugTime("Renderer.LightTotal",
|
|
||||||
"Renderer.Light1",
|
|
||||||
"Renderer.Light2",
|
|
||||||
"Renderer.Light3",
|
|
||||||
"Renderer.Light4",
|
|
||||||
"Renderer.Light0"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
else if (world.worldIndex != -1) { // to avoid updating on the null world
|
else if (world.worldIndex != -1) { // to avoid updating on the null world
|
||||||
val buf = AtomicReferenceArray<Color>(lightmap.size)
|
TODO()
|
||||||
|
|
||||||
AppLoader.measureDebugTime("Renderer.LightPrlPre") {
|
|
||||||
// update the content of buf using maxBlend -- it's not meant for overwrite
|
|
||||||
|
|
||||||
updateMessages.forEachIndexed { index, msg ->
|
|
||||||
ThreadParallel.map(index, "Light") {
|
|
||||||
// for the message slices...
|
|
||||||
msg.forEach { m ->
|
|
||||||
// update the content of buf using maxBlend -- it's not meant for overwrite
|
|
||||||
buf.getAndUpdate(m.y * LIGHTMAP_WIDTH + m.x) { oldCol ->
|
|
||||||
val ux = m.x + for_x_start - overscan_open
|
|
||||||
val uy = m.y + for_y_start - overscan_open
|
|
||||||
|
|
||||||
(oldCol ?: colourNull).cpy().maxAndAssign(calculate(ux, uy))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AppLoader.measureDebugTime("Renderer.LightPrlRun") {
|
|
||||||
ThreadParallel.startAllWaitForDie()
|
|
||||||
}
|
|
||||||
|
|
||||||
AppLoader.measureDebugTime("Renderer.LightPrlPost") {
|
|
||||||
// copy to lightmap
|
|
||||||
for (k in 0 until lightmap.size) {
|
|
||||||
lightmap[k] = buf.getPlain(k) ?: colourNull
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
AppLoader.addDebugTime("Renderer.LightTotal",
|
|
||||||
"Renderer.LightPrlPre",
|
|
||||||
"Renderer.LightPrlRun",
|
|
||||||
"Renderer.LightPrlPost"
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
@@ -584,7 +535,7 @@ object LightmapRenderer {
|
|||||||
/**
|
/**
|
||||||
* Calculates the light simulation, using main lightmap as one of the input.
|
* Calculates the light simulation, using main lightmap as one of the input.
|
||||||
*/
|
*/
|
||||||
private fun calculate(x: Int, y: Int): Color {
|
private fun calculateAndAssign(lightmap: Array<Color>, x: Int, y: Int) {
|
||||||
|
|
||||||
// TODO is JEP 338 released yet?
|
// TODO is JEP 338 released yet?
|
||||||
|
|
||||||
@@ -618,7 +569,8 @@ object LightmapRenderer {
|
|||||||
/* * */lightLevelThis.maxAndAssign(darkenColoured(getLightInternal(x + 1, y) ?: colourNull, thisTileOpacity))
|
/* * */lightLevelThis.maxAndAssign(darkenColoured(getLightInternal(x + 1, y) ?: colourNull, thisTileOpacity))
|
||||||
|
|
||||||
|
|
||||||
return lightLevelThis.cpy() // it HAS to be a cpy(), otherwise all cells gets the same instance
|
//return lightLevelThis.cpy() // it HAS to be a cpy(), otherwise all cells gets the same instance
|
||||||
|
setLightOf(lightmap, x, y, lightLevelThis.cpy())
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getLightForOpaque(x: Int, y: Int): Color? { // ...so that they wouldn't appear too dark
|
private fun getLightForOpaque(x: Int, y: Int): Color? { // ...so that they wouldn't appear too dark
|
||||||
@@ -725,22 +677,6 @@ object LightmapRenderer {
|
|||||||
data.a * (1f - darken.a * lightScalingMagic))
|
data.a * (1f - darken.a * lightScalingMagic))
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Add each channel's RGB value.
|
|
||||||
*
|
|
||||||
* @param data Raw channel value (0-255) per channel
|
|
||||||
* @param brighten (0-255) per channel
|
|
||||||
* @return brightened data (0-255) per channel
|
|
||||||
*/
|
|
||||||
fun brightenColoured(data: Color, brighten: Color): Color {
|
|
||||||
return Color(
|
|
||||||
data.r * (1f + brighten.r * lightScalingMagic),
|
|
||||||
data.g * (1f + brighten.g * lightScalingMagic),
|
|
||||||
data.b * (1f + brighten.b * lightScalingMagic),
|
|
||||||
data.a * (1f + brighten.a * lightScalingMagic)
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Darken each channel by 'darken' argument
|
* Darken each channel by 'darken' argument
|
||||||
*
|
*
|
||||||
@@ -904,10 +840,10 @@ object LightmapRenderer {
|
|||||||
)
|
)
|
||||||
/** To eliminated visible edge on the gradient when 255/1023 is exceeded */
|
/** To eliminated visible edge on the gradient when 255/1023 is exceeded */
|
||||||
internal fun Color.normaliseToHDR() = Color(
|
internal fun Color.normaliseToHDR() = Color(
|
||||||
hdr(this.r),
|
hdr(this.r.coerceIn(0f,1f)),
|
||||||
hdr(this.g),
|
hdr(this.g.coerceIn(0f,1f)),
|
||||||
hdr(this.b),
|
hdr(this.b.coerceIn(0f,1f)),
|
||||||
hdr(this.a)
|
hdr(this.a.coerceIn(0f,1f))
|
||||||
)
|
)
|
||||||
|
|
||||||
private fun Color.nonZero() = this.r + this.g + this.b + this.a > epsilon
|
private fun Color.nonZero() = this.r + this.g + this.b + this.a > epsilon
|
||||||
|
|||||||
Reference in New Issue
Block a user