mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-06 08:38:30 +09:00
simpler light tone mapping
This commit is contained in:
@@ -3,6 +3,7 @@ package net.torvald.terrarum.audio.dsp
|
|||||||
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
import kotlin.math.absoluteValue
|
import kotlin.math.absoluteValue
|
||||||
import kotlin.math.pow
|
import kotlin.math.pow
|
||||||
|
import kotlin.math.sign
|
||||||
import kotlin.math.sqrt
|
import kotlin.math.sqrt
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -36,31 +37,29 @@ object SoftClp : TerrarumAudioFilter(), DspCompressor {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// private const val clip_p = 0.277777f // knee of around -1.94dB
|
||||||
|
private const val clip_p = 0.349f // knee of around -3.01dB
|
||||||
|
// private const val clip_p = 0.44444f // knee of around -6.02dB
|
||||||
|
private val clip_p1 = sqrt(1.0f - 2.0f * clip_p)
|
||||||
|
private val clip_lim = 1.0f / (1.0f + clip_p1)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* https://www.desmos.com/calculator/syqd1byzzl
|
* https://www.desmos.com/calculator/syqd1byzzl
|
||||||
* @param x0 -0.5..0.5 ish
|
* @param x0 -0.5..0.5 ish
|
||||||
* @return -0.5..0.5
|
* @return -0.5..0.5
|
||||||
*/
|
*/
|
||||||
private fun clipfun0(x0: Double): Double {
|
private fun clipfun0(x0: Double): Double {
|
||||||
// val p = 0.277777 // knee of around -1.94dB
|
val x = x0 * (1.0f + clip_p1) / 2.0f
|
||||||
val p = 0.349 // knee of around -3.01dB
|
val t = 0.5f * clip_p1
|
||||||
// val p = 0.44444 // knee of around -6.02dB
|
|
||||||
val p1 = sqrt(1.0 - 2.0 * p)
|
|
||||||
|
|
||||||
val x = x0 * (1.0 + p1) / 2.0
|
if (x0.absoluteValue >= clip_lim) return 0.5f * sign(x0)
|
||||||
val t = 0.5 * p1
|
|
||||||
|
|
||||||
val lim = 1.0 / (1.0 + p1)
|
|
||||||
|
|
||||||
if (x0 >= lim) return 0.5
|
|
||||||
if (x0 <= -lim) return -0.5
|
|
||||||
|
|
||||||
val y0 = if (x < -t)
|
val y0 = if (x < -t)
|
||||||
(1.0 / p) * (x + 0.5).pow(2) - 0.5
|
(x*x + x + 0.25f) / clip_p - 0.5f
|
||||||
else if (x > t)
|
else if (x > t)
|
||||||
-(1.0 / p) * (x - 0.5).pow(2) + 0.5
|
-(x*x - x + 0.25f) / clip_p + 0.5f
|
||||||
else
|
else
|
||||||
x * 2.0 * lim
|
x * 2.0f * clip_lim
|
||||||
|
|
||||||
return y0
|
return y0
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import net.torvald.unsafe.UnsafeHelper
|
|||||||
*
|
*
|
||||||
* Created by Torvald on 2019-12-05.
|
* Created by Torvald on 2019-12-05.
|
||||||
*/
|
*/
|
||||||
internal object LightmapHDRMap : Disposable {
|
/*internal object LightmapHDRMap : Disposable {
|
||||||
/*private val THE_LUT = floatArrayOf( // polynomial of 6.0 please refer to work_files/HDRcurveBezierLinIntp.kts
|
/*private val THE_LUT = floatArrayOf( // polynomial of 6.0 please refer to work_files/HDRcurveBezierLinIntp.kts
|
||||||
0.0000f,0.0004f,0.0020f,0.0060f,0.0100f,0.0139f,0.0179f,0.0219f,0.0259f,0.0299f,0.0338f,0.0378f,0.0418f,0.0458f,0.0497f,0.0537f,
|
0.0000f,0.0004f,0.0020f,0.0060f,0.0100f,0.0139f,0.0179f,0.0219f,0.0259f,0.0299f,0.0338f,0.0378f,0.0418f,0.0458f,0.0497f,0.0537f,
|
||||||
0.0577f,0.0617f,0.0656f,0.0696f,0.0736f,0.0776f,0.0816f,0.0855f,0.0895f,0.0935f,0.0975f,0.1014f,0.1054f,0.1094f,0.1134f,0.1173f,
|
0.0577f,0.0617f,0.0656f,0.0696f,0.0736f,0.0776f,0.0816f,0.0855f,0.0895f,0.0935f,0.0975f,0.1014f,0.1054f,0.1094f,0.1134f,0.1173f,
|
||||||
@@ -94,4 +94,4 @@ internal object LightmapHDRMap : Disposable {
|
|||||||
override fun dispose() {
|
override fun dispose() {
|
||||||
ptr.destroy()
|
ptr.destroy()
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
@@ -17,9 +17,7 @@ import net.torvald.terrarum.modulebasegame.IngameRenderer
|
|||||||
import net.torvald.terrarum.modulebasegame.ui.abs
|
import net.torvald.terrarum.modulebasegame.ui.abs
|
||||||
import net.torvald.terrarum.realestate.LandUtil
|
import net.torvald.terrarum.realestate.LandUtil
|
||||||
import java.util.*
|
import java.util.*
|
||||||
import kotlin.math.max
|
import kotlin.math.*
|
||||||
import kotlin.math.min
|
|
||||||
import kotlin.math.roundToInt
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
@@ -133,7 +131,6 @@ object LightmapRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
LightmapHDRMap.invoke()
|
|
||||||
printdbg(this, "Overscan open: $overscan_open; opaque: $overscan_opaque")
|
printdbg(this, "Overscan open: $overscan_open; opaque: $overscan_opaque")
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -730,18 +727,18 @@ object LightmapRenderer {
|
|||||||
/*lightBuffer.drawPixel(
|
/*lightBuffer.drawPixel(
|
||||||
x - this_x_start,
|
x - this_x_start,
|
||||||
lightBuffer.height - 1 - y + this_y_start, // flip Y
|
lightBuffer.height - 1 - y + this_y_start, // flip Y
|
||||||
(max(red,grnw,bluw,uvlwr) * solidMultMagic).hdnorm().times(255f).roundToInt().shl(24) or
|
(max(red,grnw,bluw,uvlwr) * solidMultMagic).tonemap().times(255f).roundToInt().shl(24) or
|
||||||
(max(redw,grn,bluw,uvlwg) * solidMultMagic).hdnorm().times(255f).roundToInt().shl(16) or
|
(max(redw,grn,bluw,uvlwg) * solidMultMagic).tonemap().times(255f).roundToInt().shl(16) or
|
||||||
(max(redw,grnw,blu,uvlwb) * solidMultMagic).hdnorm().times(255f).roundToInt().shl(8) or
|
(max(redw,grnw,blu,uvlwb) * solidMultMagic).tonemap().times(255f).roundToInt().shl(8) or
|
||||||
(max(bluwv,uvl) * solidMultMagic).hdnorm().times(255f).roundToInt()
|
(max(bluwv,uvl) * solidMultMagic).tonemap().times(255f).roundToInt()
|
||||||
)*/
|
)*/
|
||||||
lightBuffer.drawPixel(
|
lightBuffer.drawPixel(
|
||||||
x - this_x_start,
|
x - this_x_start,
|
||||||
lightBuffer.height - 1 - y + this_y_start, // flip Y
|
lightBuffer.height - 1 - y + this_y_start, // flip Y
|
||||||
(red * solidMultMagic).hdnorm().times(255f).roundToInt().shl(24) or
|
(red * solidMultMagic).tonemap().times(255f).roundToInt().shl(24) or
|
||||||
(grn * solidMultMagic).hdnorm().times(255f).roundToInt().shl(16) or
|
(grn * solidMultMagic).tonemap().times(255f).roundToInt().shl(16) or
|
||||||
(blu * solidMultMagic).hdnorm().times(255f).roundToInt().shl(8) or
|
(blu * solidMultMagic).tonemap().times(255f).roundToInt().shl(8) or
|
||||||
(uvl * solidMultMagic).hdnorm().times(255f).roundToInt()
|
(uvl * solidMultMagic).tonemap().times(255f).roundToInt()
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -764,7 +761,6 @@ object LightmapRenderer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fun dispose() {
|
fun dispose() {
|
||||||
LightmapHDRMap.dispose()
|
|
||||||
_lightBufferAsTex.dispose()
|
_lightBufferAsTex.dispose()
|
||||||
lightBuffer.dispose()
|
lightBuffer.dispose()
|
||||||
|
|
||||||
@@ -846,26 +842,6 @@ object LightmapRenderer {
|
|||||||
fun Int.even(): Boolean = this and 1 == 0
|
fun Int.even(): Boolean = this and 1 == 0
|
||||||
fun Int.odd(): Boolean = this and 1 == 1
|
fun Int.odd(): Boolean = this and 1 == 1
|
||||||
|
|
||||||
// TODO: float LUT lookup using linear interpolation
|
|
||||||
|
|
||||||
// input: 0..1 for int 0..1023
|
|
||||||
fun hdr(intensity: Float): Float {
|
|
||||||
val intervalStart = (intensity / 4f * LightmapHDRMap.size).floorToInt()
|
|
||||||
val intervalEnd = (intensity / 4f * LightmapHDRMap.size).floorToInt() + 1
|
|
||||||
|
|
||||||
if (intervalStart == intervalEnd) return LightmapHDRMap[intervalStart]
|
|
||||||
|
|
||||||
val intervalPos = (intensity / 4f * LightmapHDRMap.size) - (intensity / 4f * LightmapHDRMap.size).toInt()
|
|
||||||
|
|
||||||
val ret = interpolateLinear(
|
|
||||||
intervalPos,
|
|
||||||
LightmapHDRMap[intervalStart],
|
|
||||||
LightmapHDRMap[intervalEnd]
|
|
||||||
)
|
|
||||||
|
|
||||||
return ret
|
|
||||||
}
|
|
||||||
|
|
||||||
private var _init = false
|
private var _init = false
|
||||||
|
|
||||||
fun resize(screenW: Int, screenH: Int) {
|
fun resize(screenW: Int, screenH: Int) {
|
||||||
@@ -901,16 +877,33 @@ object LightmapRenderer {
|
|||||||
printdbg(this, "Resize event")
|
printdbg(this, "Resize event")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// private const val clip_p = 0.277777f // knee of around -1.94dB
|
||||||
|
private const val clip_p = 0.349f // knee of around -3.01dB
|
||||||
|
// private const val clip_p = 0.44444f // knee of around -6.02dB
|
||||||
|
private val clip_p1 = sqrt(1.0f - 2.0f * clip_p)
|
||||||
|
private val clip_lim = 1.0f / (1.0f + clip_p1)
|
||||||
|
/**
|
||||||
|
* https://www.desmos.com/calculator/syqd1byzzl
|
||||||
|
* @param x0 -0.5..0.5 ish
|
||||||
|
* @return -0.5..0.5
|
||||||
|
*/
|
||||||
|
private fun clipfun0(x0: Float): Float {
|
||||||
|
val x = x0 * (1.0f + clip_p1) / 2.0f
|
||||||
|
val t = 0.5f * clip_p1
|
||||||
|
|
||||||
/** To eliminated visible edge on the gradient when 255/1023 is exceeded */
|
if (x0.absoluteValue >= clip_lim) return 0.5f * sign(x0)
|
||||||
fun Color.normaliseToHDR() = Color(
|
|
||||||
hdr(this.r.coerceIn(0f, 1f)),
|
|
||||||
hdr(this.g.coerceIn(0f, 1f)),
|
|
||||||
hdr(this.b.coerceIn(0f, 1f)),
|
|
||||||
hdr(this.a.coerceIn(0f, 1f))
|
|
||||||
)
|
|
||||||
|
|
||||||
inline fun Float.hdnorm() = hdr(this.coerceIn(0f, 1f))
|
val y0 = if (x < -t)
|
||||||
|
(x*x + x + 0.25f) / clip_p - 0.5f
|
||||||
|
else if (x > t)
|
||||||
|
-(x*x - x + 0.25f) / clip_p + 0.5f
|
||||||
|
else
|
||||||
|
x * 2.0f * clip_lim
|
||||||
|
|
||||||
|
return y0
|
||||||
|
}
|
||||||
|
|
||||||
|
fun Float.tonemap() = clipfun0(this / 2f) * 2f
|
||||||
|
|
||||||
private fun Cvec.nonZero() = this.r.abs() > epsilon ||
|
private fun Cvec.nonZero() = this.r.abs() > epsilon ||
|
||||||
this.g.abs() > epsilon ||
|
this.g.abs() > epsilon ||
|
||||||
|
|||||||
Reference in New Issue
Block a user