each cloud now carry its own gamma value

This commit is contained in:
minjaesong
2023-09-02 02:40:27 +09:00
parent 721a24d9dc
commit 78075d779b
9 changed files with 157 additions and 35 deletions

View File

@@ -40,6 +40,16 @@ data class BaseModularWeather(
val v = 1f + rnd.absoluteValue * windSpeedVariance
return if (rnd < 0) windSpeed / v else windSpeed * v
}
fun getRandomCloudGamma(rnd1: Float, rnd2: Float): Vector2 {
val v = 1f + rnd1.absoluteValue * cloudGammaVariance.x
val gx = if (rnd1 < 0) cloudGamma.x / v else cloudGamma.x * v
val u = 1f + rnd2.absoluteValue * cloudGammaVariance.y
val gy = if (rnd2 < 0) cloudGamma.y / u else cloudGamma.y * u
return Vector2(gx, gy)
}
}
data class CloudProps(

View File

@@ -146,24 +146,22 @@ internal object WeatherMixer : RNGConsumer {
oldCamPos.set(WorldCamera.camVector)
weatherbox = Weatherbox()
weatherbox.initWith(weatherDict["generic01"]!!, 3600L)
weatherbox.initWith(weatherDict["generic01"]!!, 7200L)
// TEST FILL WITH RANDOM VALUES
(0..5).map { takeUniformRand(0f..1f) }.let {
(0..4).map { takeUniformRand(0f..1f) }.let {
weatherbox.windDir.pM1 = it[0]
weatherbox.windDir.p0 = it[1]
weatherbox.windDir.p1 = it[2]
weatherbox.windDir.p2 = it[3]
weatherbox.windDir.p3 = it[4]
// weatherbox.windDir.p4 = it[5]
}
(0..5).map { takeUniformRand(-1f..1f) }.let {
(0..4).map { takeUniformRand(-1f..1f) }.let {
weatherbox.windSpeed.pM1 = currentWeather.getRandomWindSpeed(it[0])
weatherbox.windSpeed.p0 = currentWeather.getRandomWindSpeed(it[1])
weatherbox.windSpeed.p1 = currentWeather.getRandomWindSpeed(it[2])
weatherbox.windSpeed.p2 = currentWeather.getRandomWindSpeed(it[3])
weatherbox.windSpeed.p3 = currentWeather.getRandomWindSpeed(it[4])
// weatherbox.windSpeed.p4 = currentWeather.getRandomWindSpeed(it[5])
}
}
@@ -301,7 +299,7 @@ internal object WeatherMixer : RNGConsumer {
it.posX += camDelta.x * cloudParallaxMultX
it.posY += camDelta.y * cloudParallaxMultY
it.update(windVector)
it.update(world, windVector)
if (DEBUG_CAUSE_OF_DESPAWN && it.life == 0) {
immDespawnCount += 1
@@ -450,7 +448,15 @@ internal object WeatherMixer : RNGConsumer {
val sheetX = rA % cloud.spriteSheet.horizontalCount
val sheetY = rB % cloud.spriteSheet.verticalCount
WeatherObjectCloud(cloud.spriteSheet.get(sheetX, sheetY), flip).also {
val cloudGamma = currentWeather.getRandomCloudGamma(takeUniformRand(-1f..1f), takeUniformRand(-1f..1f))
WeatherObjectCloud(
cloud.spriteSheet.get(sheetX, sheetY),
flip,
cloudGamma.x,
cloudGamma.y
).also {
it.scale = cloudScale * cloudSizeMult
it.pos.set(precalculatedPos ?: getCloudSpawningPosition(cloud, hCloudSize, windVector))
@@ -492,7 +498,7 @@ internal object WeatherMixer : RNGConsumer {
internal fun titleScreenInitWeather() {
weatherbox.initWith(weatherDict["titlescreen"]!!, Long.MAX_VALUE)
forceWindVec = Vector3(-0.98f, 0f, -0.21f)
forceWindVec = Vector3(-0.98f, 0f, -0.21f).scl(1f/30f) // value taken from TitleScreen.kt; search for 'demoWorld.worldTime.timeDelta = '
initClouds()
}
@@ -525,12 +531,10 @@ internal object WeatherMixer : RNGConsumer {
private fun drawClouds(batch: SpriteBatch) {
batch.inUse { _ ->
batch.shader = shaderClouds
batch.shader.setUniformf("gamma", currentWeather.cloudGamma)
batch.shader.setUniformf("shadeCol", 0.06f, 0.07f, 0.08f, 1f) // TODO temporary value
clouds.forEach {
batch.color = Color(cloudDrawColour.r, cloudDrawColour.g, cloudDrawColour.b, it.alpha)
it.render(batch, 0f, 0f)
it.render(batch, cloudDrawColour)
}
}
}

View File

@@ -1,12 +1,14 @@
package net.torvald.terrarum.weather
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.graphics.g2d.SpriteBatch
import com.badlogic.gdx.graphics.g2d.TextureRegion
import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.math.Vector3
import com.jme3.math.FastMath
import net.torvald.terrarum.App
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.gameworld.GameWorld
import kotlin.math.absoluteValue
import kotlin.math.pow
import kotlin.math.roundToInt
import kotlin.math.sign
@@ -14,7 +16,12 @@ import kotlin.math.sign
/**
* Created by minjaesong on 2023-08-21.
*/
class WeatherObjectCloud(private val texture: TextureRegion, private val flipW: Boolean) : WeatherObject(), Comparable<WeatherObjectCloud> {
class WeatherObjectCloud(
private val texture: TextureRegion,
private val flipW: Boolean,
private val rgbGamma: Float,
private val aGamma: Float
) : WeatherObject(), Comparable<WeatherObjectCloud> {
override fun update() {
throw UnsupportedOperationException()
@@ -33,11 +40,12 @@ class WeatherObjectCloud(private val texture: TextureRegion, private val flipW:
* FlowVector: In which direction the cloud flows. Vec3(dX, dY, dScale)
* Resulting vector: (x + dX, y + dY, scale * dScale)
*/
fun update(flowVector: Vector3) {
fun update(world: GameWorld, flowVector: Vector3) {
pos.add(
flowVector.cpy().
scl(1f, 1f, getZflowMult(posZ)). // this will break the perspective if flowVector.z.abs() is close to 1, but it has to be here to "keep the distance"
scl(vecMult)
scl(vecMult).
scl(world.worldTime.timeDelta.toFloat())
)
eigenAlpha = if (posZ < 1f) posZ.pow(0.5f) else -((posZ - 1f) / ALPHA_ROLLOFF_Z) + 1f
@@ -66,19 +74,43 @@ class WeatherObjectCloud(private val texture: TextureRegion, private val flipW:
private val h = App.scr.hf * 0.5f
private val vecMult = Vector3(1f, 1f, 1f / (4f * h))
/**
* X/Y position is a bottom-centre point of the image
* Shader must be prepared prior to the render() call
*/
override fun render(batch: SpriteBatch, offsetX: Float, offsetY: Float) {
private fun roundRgbGamma(x: Float): Int {
return RGB_GAMMA_TABLE.mapIndexed { i, f -> (f - x).absoluteValue to i }.minBy { it.first }.second
}
private fun roundAgamma(x: Float): Int {
return A_GAMMA_TABLE.mapIndexed { i, f -> (f - x).absoluteValue to i }.minBy { it.first }.second
}
fun render(batch: SpriteBatch, cloudDrawColour: Color) {
val sc = screenCoord
val rgbGammaIndex = roundRgbGamma(rgbGamma)
val aGammaIndex = roundAgamma(aGamma)
// printdbg(this, "gamma: (${rgbGamma}, ${aGamma}) index: ($rgbGammaIndex, $aGammaIndex)")
val lightBits = cloudDrawColour.toIntBits()
val rbits = lightBits.ushr( 0).and(252) or rgbGammaIndex.ushr(2).and(3)
val gbits = lightBits.ushr( 8).and(252) or rgbGammaIndex.ushr(0).and(3)
val bbits = lightBits.ushr(16).and(252) or aGammaIndex
val abits = (alpha * 255).toInt()
batch.color = Color(rbits.shl(24) or gbits.shl(16) or bbits.shl(8) or abits)
if (flipW)
batch.draw(texture, sc.x + texture.regionWidth / posZ, sc.y, -texture.regionWidth * sc.z, texture.regionHeight * sc.z)
else
batch.draw(texture, sc.x, sc.y, texture.regionWidth * sc.z, texture.regionHeight * sc.z)
}
/**
* X/Y position is a bottom-centre point of the image
* Shader must be prepared prior to the render() call
*/
override fun render(batch: SpriteBatch, offsetX: Float, offsetY: Float) {
throw UnsupportedOperationException()
}
/**
* vec3(screen X, screenY, draw scale)
*/
@@ -133,5 +165,34 @@ class WeatherObjectCloud(private val texture: TextureRegion, private val flipW:
fun screenXtoWorldX(screenX: Float, z: Float) = screenX * z - App.scr.halfwf * (z - 1f)
const val ALPHA_ROLLOFF_Z = 64f
const val OLD_AGE_DECAY = 4000f
val RGB_GAMMA_TABLE = floatArrayOf(
0.2f,
0.3f,
0.4f,
0.5f,
0.7f,
0.9f,
1.1f,
1.3f,
1.7f,
2.1f,
2.5f,
2.9f,
3.7f,
4.5f,
5.3f,
6.1f
)
val A_GAMMA_TABLE = floatArrayOf(
1.6f,
2.0f,
2.4f,
2.8f
)
}
}

View File

@@ -1,6 +1,7 @@
package net.torvald.terrarum.weather
import com.jme3.math.FastMath
import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.floorToInt
import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.fmod
@@ -11,7 +12,7 @@ data class WeatherSchedule(val weather: BaseModularWeather = WeatherMixer.DEFAUL
class Weatherbox {
companion object {
private val WIND_DIR_TIME_UNIT = 3600f * 5 // every 5hr
private val WIND_DIR_TIME_UNIT = 3600f * 6 // every 6hr
private val WIND_SPEED_TIME_UNIT = 3600f * 2 // every 2hr
private val HALF_PIF = 1.5707964f
@@ -53,10 +54,10 @@ class Weatherbox {
// TODO add more random weathers
if (weatherSchedule.size == 1) {
val newName = if (currentWeather.identifier == "generic01") "overcast01" else "generic01"
val newDuration = 3600L
val newDuration = 7200L
weatherSchedule.add(WeatherSchedule(WeatherMixer.weatherDict[newName]!!, newDuration))
println("Queueing next weather '$newName' that will last $newDuration seconds")
// printdbg(this, "Queueing next weather '$newName' that will last $newDuration seconds")
}
// subtract akku by old currentWeatherDuration