From aff64f6a8e275f36bbc193133862fd4deb37d435 Mon Sep 17 00:00:00 2001 From: minjaesong Date: Tue, 4 Oct 2022 22:01:28 +0900 Subject: [PATCH] new lighting wip --- src/net/torvald/gdx/graphics/Cvec.kt | 16 +++- .../torvald/gdx/graphics/UnsafeCvecArray.kt | 2 +- .../terrarum/blockproperties/BlockProp.kt | 4 +- .../terrarum/worlddrawer/LightmapRenderer.kt | 73 ++++++------------- 4 files changed, 39 insertions(+), 56 deletions(-) diff --git a/src/net/torvald/gdx/graphics/Cvec.kt b/src/net/torvald/gdx/graphics/Cvec.kt index f71f4e567..399729795 100644 --- a/src/net/torvald/gdx/graphics/Cvec.kt +++ b/src/net/torvald/gdx/graphics/Cvec.kt @@ -89,7 +89,7 @@ class Cvec { * - 2: B * - 3: A */ - fun getElem(index: Int) = when(index) { + fun lane(index: Int) = when(index) { 0 -> r 1 -> g 2 -> b @@ -419,6 +419,20 @@ class Cvec { return Cvec(this) } + /** + * Creates a new Cvec that this Cvec transformed by the given function. + * + * @param transformation a function with two parameters: (`this.lane(i)`, `i`) and returns a float value + */ + fun lanewise(transformation: (Float, Int) -> Float): Cvec { + return Cvec( + transformation(this.r, 0), + transformation(this.g, 1), + transformation(this.b, 2), + transformation(this.a, 3) + ) + } + companion object { val WHITE = Cvec(1f, 1f, 1f, 1f) diff --git a/src/net/torvald/gdx/graphics/UnsafeCvecArray.kt b/src/net/torvald/gdx/graphics/UnsafeCvecArray.kt index ca1c36f70..4664bc137 100644 --- a/src/net/torvald/gdx/graphics/UnsafeCvecArray.kt +++ b/src/net/torvald/gdx/graphics/UnsafeCvecArray.kt @@ -95,7 +95,7 @@ internal class UnsafeCvecArray(val width: Int, val height: Int) { fun forAllMulAssign(vector: Cvec) { for (i in 0 until TOTAL_SIZE_IN_BYTES / 4 step 4) { for (k in 0 until 4) { - array.setFloat(i + 4*k, array.getFloat(i + k) * vector.getElem(k)) + array.setFloat(i + 4*k, array.getFloat(i + k) * vector.lane(k)) } } } diff --git a/src/net/torvald/terrarum/blockproperties/BlockProp.kt b/src/net/torvald/terrarum/blockproperties/BlockProp.kt index 4f2f900eb..ee2eefc45 100644 --- a/src/net/torvald/terrarum/blockproperties/BlockProp.kt +++ b/src/net/torvald/terrarum/blockproperties/BlockProp.kt @@ -69,10 +69,10 @@ class BlockProp { } fun getLumCol(x: Int, y: Int, channel: Int): Float = if (dynamicLuminosityFunction == 0) { - baseLumCol.getElem(channel) + baseLumCol.lane(channel) } else { val offset = XXHash32.hashGeoCoord(x, y).fmod(BlockCodex.DYNAMIC_RANDOM_CASES) - BlockCodex[BlockCodex.tileToVirtual[id]!![offset]]._lumCol.getElem(channel) + BlockCodex[BlockCodex.tileToVirtual[id]!![offset]]._lumCol.lane(channel) } /** diff --git a/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt b/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt index fd099202a..b6f71ca31 100644 --- a/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt +++ b/src/net/torvald/terrarum/worlddrawer/LightmapRenderer.kt @@ -551,48 +551,6 @@ object LightmapRenderer { private var swipeY = -1 private var swipeDiag = false private val distFromLightSrc = Ivec4() - private val gaussianMap = doubleArrayOf( - 8.892787877390726E-02, - 8.458993346786304E-02, - 7.653374932806653E-02, - 6.585462151484795E-02, - 5.388105396669377E-02, - 4.190748641853961E-02, - 3.097509865718143E-02, - 2.174847352525505E-02, - 1.449898235017003E-02, - 9.172825568474920E-03, - 5.503695341084953E-03, - 3.129552252773797E-03, - 1.685143520724352E-03, - 8.584693407463680E-04, - 4.133370899889921E-04, - 1.878804954495418E-04, - 8.052021233551793E-05, - 3.249061199503355E-05, - 1.232402523949548E-05, - 4.386517458125512E-06, - 1.462172486041837E-06, - 4.554307743409001E-07, - 1.322218377118743E-07, - 3.567890858891845E-08, - 8.919727147229610E-09, - 2.058398572437603E-09, - 4.366300002140369E-10, - 8.471925377287283E-11, - 1.495045654815403E-11, - 2.383406116372381E-12, - 3.404865880531974E-13, - 4.316027172505319E-14, - 4.795585747228131E-15, - 4.598506880903687E-16, - 3.728519092624612E-17, - 2.485679395083075E-18, - 1.308252313201618E-19, - 5.097086934551759E-21, - 1.306945367833784E-22, - 1.654361225106056E-24 - ).map { it.toFloat() }.toFloatArray() private fun _swipeTask(x: Int, y: Int, x2: Int, y2: Int, lightmap: UnsafeCvecArray, distFromLightSrc: Ivec4) { if (x2 < 0 || y2 < 0 || x2 >= LIGHTMAP_WIDTH || y2 >= LIGHTMAP_HEIGHT) return @@ -606,14 +564,14 @@ 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, lightmap)) + _ambientAccumulator.maxAndAssign(darkenColoured(x2, y2, _thisTileOpacity, lightmap, distFromLightSrc)) } 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, lightmap)) + _ambientAccumulator.maxAndAssign(darkenColoured(x2, y2, _thisTileOpacity2, lightmap, distFromLightSrc)) } _mapLightLevelThis.setVec(x, y, _ambientAccumulator) @@ -665,7 +623,7 @@ object LightmapRenderer { return if (BlockCodex[world.getTileFromTerrain(x, y)].isSolid) 1.2f else 1f } - private class Ivec4 { + internal class Ivec4 { var r = 0 var g = 0 @@ -685,6 +643,14 @@ object LightmapRenderer { a+=scalar } + fun lane(index: Int) = when(index) { + 0 -> r + 1 -> g + 2 -> b + 3 -> a + else -> throw IndexOutOfBoundsException("Invalid index $index") + } + } var lightBuffer: Pixmap = Pixmap(64, 64, Pixmap.Format.RGBA8888) // must not be too small @@ -792,18 +758,21 @@ object LightmapRenderer { * @param darken (0-255) per channel * @return darkened data (0-255) per channel */ - internal fun darkenColoured(x: Int, y: Int, darken: Cvec, lightmap: UnsafeCvecArray): Cvec { + internal fun darkenColoured(x: Int, y: Int, darken: Cvec, lightmap: UnsafeCvecArray, distFromLightSrc: Ivec4 = Ivec4()): 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) if (x !in 0 until LIGHTMAP_WIDTH || y !in 0 until LIGHTMAP_HEIGHT) return colourNull - return Cvec( - lightmap.getR(x, y) * (1f - darken.r * lightScalingMagic), - lightmap.getG(x, y) * (1f - darken.g * lightScalingMagic), - lightmap.getB(x, y) * (1f - darken.b * lightScalingMagic), - lightmap.getA(x, y) * (1f - darken.a * lightScalingMagic) - ) + return lightmap.getVec(x, y).lanewise { it, ch -> + it * (1f - darken.lane(ch) * lightScalingMagic) + } + + /*val newDarken: Cvec = darken.lanewise(darkenFit) + + return lightmap.getVec(x, y).lanewise { it, ch -> + it * ((newDarken.lane(ch) - distFromLightSrc.lane(ch)) / newDarken.lane(ch)) + }*/ }