mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-06-11 11:04:05 +09:00
more clouds
This commit is contained in:
@@ -2,15 +2,17 @@
|
|||||||
"skyboxGradColourMap": "generic_skybox.tga",
|
"skyboxGradColourMap": "generic_skybox.tga",
|
||||||
"daylightClut": "clut_daylight.tga",
|
"daylightClut": "clut_daylight.tga",
|
||||||
"classification": "generic",
|
"classification": "generic",
|
||||||
"cloudGamma": [0.44, 2.0],
|
"cloudChance": 6,
|
||||||
|
"cloudGamma": [0.59, 2.0],
|
||||||
|
"cloudDriftSpeed": 0.4,
|
||||||
"clouds": {
|
"clouds": {
|
||||||
"normal": {
|
"normal": {
|
||||||
"filename": "cloud_normal.png",
|
"filename": "cloud_normal.png",
|
||||||
"tw": 1024, "th": 512
|
"tw": 1024, "th": 512, "probability": 1.0, "baseScale": 0.4, "scaleVariance": 0.2
|
||||||
},
|
},
|
||||||
"large": {
|
"large": {
|
||||||
"filename": "cloud_large.png",
|
"filename": "cloud_large.png",
|
||||||
"tw": 2048, "th": 1024
|
"tw": 2048, "th": 1024, "probability": 0.1, "baseScale": 0.26, "scaleVariance": 0.2
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@@ -302,6 +302,7 @@ class BuildingMaker(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
|
|
||||||
IngameRenderer.setRenderedWorld(gameWorld)
|
IngameRenderer.setRenderedWorld(gameWorld)
|
||||||
|
WeatherMixer.internalReset()
|
||||||
}
|
}
|
||||||
|
|
||||||
override fun show() {
|
override fun show() {
|
||||||
|
|||||||
@@ -210,6 +210,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
|
|||||||
|
|
||||||
|
|
||||||
IngameRenderer.setRenderedWorld(demoWorld)
|
IngameRenderer.setRenderedWorld(demoWorld)
|
||||||
|
WeatherMixer.internalReset()
|
||||||
|
|
||||||
|
|
||||||
// load a half-gradient texture that would be used throughout the titlescreen and its sub UIs
|
// load a half-gradient texture that would be used throughout the titlescreen and its sub UIs
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
package net.torvald.terrarum.weather
|
package net.torvald.terrarum.weather
|
||||||
|
|
||||||
import com.badlogic.gdx.graphics.Texture
|
import com.badlogic.gdx.math.Vector2
|
||||||
|
import com.badlogic.gdx.utils.JsonValue
|
||||||
import net.torvald.terrarum.GdxColorMap
|
import net.torvald.terrarum.GdxColorMap
|
||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
import java.util.*
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note: Colour maps are likely to have sparse data points
|
* Note: Colour maps are likely to have sparse data points
|
||||||
@@ -13,11 +13,23 @@ import java.util.*
|
|||||||
* Created by minjaesong on 2016-07-11.
|
* Created by minjaesong on 2016-07-11.
|
||||||
*/
|
*/
|
||||||
data class BaseModularWeather(
|
data class BaseModularWeather(
|
||||||
|
val json: JsonValue,
|
||||||
var skyboxGradColourMap: GdxColorMap, // row 0: skybox grad top, row 1: skybox grad bottom, row 2: sunlight (RGBA)
|
var skyboxGradColourMap: GdxColorMap, // row 0: skybox grad top, row 1: skybox grad bottom, row 2: sunlight (RGBA)
|
||||||
val daylightClut: GdxColorMap,
|
val daylightClut: GdxColorMap,
|
||||||
val classification: String,
|
val classification: String,
|
||||||
val cloudGamma: FloatArray,
|
val cloudChance: Float,
|
||||||
var clouds: HashMap<String, TextureRegionPack>,
|
val cloudDriftSpeed: Float,
|
||||||
|
val cloudGamma: Vector2,
|
||||||
|
var clouds: List<CloudProps>, // sorted by CloudProps.probability
|
||||||
|
|
||||||
val mixFrom: String? = null,
|
val mixFrom: String? = null,
|
||||||
val mixPercentage: Double? = null
|
val mixPercentage: Double? = null
|
||||||
|
)
|
||||||
|
|
||||||
|
data class CloudProps(
|
||||||
|
val category: String,
|
||||||
|
val spriteSheet: TextureRegionPack,
|
||||||
|
val probability: Float,
|
||||||
|
val baseScale: Float,
|
||||||
|
val scaleVariance: Float
|
||||||
)
|
)
|
||||||
@@ -3,6 +3,9 @@ package net.torvald.terrarum.weather
|
|||||||
import com.badlogic.gdx.Gdx
|
import com.badlogic.gdx.Gdx
|
||||||
import com.badlogic.gdx.graphics.*
|
import com.badlogic.gdx.graphics.*
|
||||||
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
import com.badlogic.gdx.graphics.g2d.TextureRegion
|
||||||
|
import com.badlogic.gdx.math.Vector2
|
||||||
|
import com.badlogic.gdx.math.Vector3
|
||||||
|
import com.badlogic.gdx.utils.JsonValue
|
||||||
import com.jme3.math.FastMath
|
import com.jme3.math.FastMath
|
||||||
import net.torvald.gdx.graphics.Cvec
|
import net.torvald.gdx.graphics.Cvec
|
||||||
import net.torvald.random.HQRNG
|
import net.torvald.random.HQRNG
|
||||||
@@ -21,6 +24,11 @@ import net.torvald.terrarum.worlddrawer.WorldCamera
|
|||||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||||
import java.io.File
|
import java.io.File
|
||||||
import java.io.FileFilter
|
import java.io.FileFilter
|
||||||
|
import java.lang.Double.doubleToLongBits
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.collections.ArrayList
|
||||||
|
import kotlin.collections.HashMap
|
||||||
|
import kotlin.math.absoluteValue
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Currently there is a debate whether this module must be part of the engine or the basegame
|
* Currently there is a debate whether this module must be part of the engine or the basegame
|
||||||
@@ -52,6 +60,7 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
lateinit var mixedWeather: BaseModularWeather
|
lateinit var mixedWeather: BaseModularWeather
|
||||||
|
|
||||||
val globalLightNow = Cvec(0)
|
val globalLightNow = Cvec(0)
|
||||||
|
private val moonlightMax = Cvec(0.23f, 0.24f, 0.25f, 0.21f) // actual moonlight is around ~4100K but our mesopic vision makes it appear blueish (wikipedia: Purkinje effect)
|
||||||
|
|
||||||
// Weather indices
|
// Weather indices
|
||||||
const val WEATHER_GENERIC = "generic"
|
const val WEATHER_GENERIC = "generic"
|
||||||
@@ -76,10 +85,10 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
private var astrumOffX = 0f
|
private var astrumOffX = 0f
|
||||||
private var astrumOffY = 0f
|
private var astrumOffY = 0f
|
||||||
|
|
||||||
private var cloudGamma1 = 0.5f
|
private val clouds = Array<WeatherObjectCloud?>(256) { null }
|
||||||
private var cloudGamma2 = 2f
|
private var cloudsSpawned = 0
|
||||||
|
private var cloudDriftVector = Vector3(-1f, 0f, 1f) // this is a direction vector
|
||||||
|
|
||||||
private val moonlightMax = Cvec(0.23f, 0.24f, 0.25f, 0.21f) // actual moonlight is around ~4100K but our mesopic vision makes it appear blueish (wikipedia: Purkinje effect)
|
|
||||||
|
|
||||||
override fun loadFromSave(s0: Long, s1: Long) {
|
override fun loadFromSave(s0: Long, s1: Long) {
|
||||||
super.loadFromSave(s0, s1)
|
super.loadFromSave(s0, s1)
|
||||||
@@ -96,6 +105,10 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
astrumOffX = s0.and(0xFFFFL).toFloat() / 65535f * starmapTex.regionWidth
|
astrumOffX = s0.and(0xFFFFL).toFloat() / 65535f * starmapTex.regionWidth
|
||||||
astrumOffY = s1.and(0xFFFFL).toFloat() / 65535f * starmapTex.regionHeight
|
astrumOffY = s1.and(0xFFFFL).toFloat() / 65535f * starmapTex.regionHeight
|
||||||
|
|
||||||
|
Arrays.fill(clouds, null)
|
||||||
|
cloudsSpawned = 0
|
||||||
|
cloudDriftVector = Vector3(-1f, 0f, 1f)
|
||||||
}
|
}
|
||||||
|
|
||||||
init {
|
init {
|
||||||
@@ -134,11 +147,14 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
|
||||||
val defaultWeather = BaseModularWeather(
|
val defaultWeather = BaseModularWeather(
|
||||||
|
JsonValue(JsonValue.ValueType.`object`),
|
||||||
GdxColorMap(1, 3, Color(0x55aaffff), Color(0xaaffffff.toInt()), Color.WHITE),
|
GdxColorMap(1, 3, Color(0x55aaffff), Color(0xaaffffff.toInt()), Color.WHITE),
|
||||||
GdxColorMap(2, 2, Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE),
|
GdxColorMap(2, 2, Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE),
|
||||||
"default",
|
"default",
|
||||||
floatArrayOf(1f, 1f),
|
0f,
|
||||||
HashMap()
|
0f,
|
||||||
|
Vector2(1f, 1f),
|
||||||
|
listOf()
|
||||||
)
|
)
|
||||||
|
|
||||||
currentWeather = defaultWeather
|
currentWeather = defaultWeather
|
||||||
@@ -154,9 +170,7 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
// currentWeather = weatherList[WEATHER_GENERIC]!![0] // force set weather
|
// currentWeather = weatherList[WEATHER_GENERIC]!![0] // force set weather
|
||||||
|
|
||||||
// update clouds
|
updateClouds(delta, world)
|
||||||
cloudGamma1 = currentWeather.cloudGamma[0]
|
|
||||||
cloudGamma2 = currentWeather.cloudGamma[1]
|
|
||||||
|
|
||||||
|
|
||||||
if (!globalLightOverridden) {
|
if (!globalLightOverridden) {
|
||||||
@@ -165,6 +179,104 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private var cloudUpdateAkku = 0f
|
||||||
|
private fun updateClouds(delta: Float, world: GameWorld) {
|
||||||
|
val cloudChanceEveryMin = 60f / (currentWeather.cloudChance * currentWeather.cloudDriftSpeed) // if chance = 0, the result will be +inf
|
||||||
|
|
||||||
|
if (cloudUpdateAkku >= cloudChanceEveryMin) {
|
||||||
|
cloudUpdateAkku -= cloudChanceEveryMin
|
||||||
|
tryToSpawnCloud(currentWeather)
|
||||||
|
}
|
||||||
|
|
||||||
|
clouds.forEach {
|
||||||
|
it?.let {
|
||||||
|
it.update(cloudDriftVector, currentWeather.cloudDriftSpeed)
|
||||||
|
|
||||||
|
if (it.posX < -1500f || it.posX > App.scr.width + 1500f || it.scale < 1f / 2048f) {
|
||||||
|
it.flagToDespawn = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
clouds.indices.forEach { i ->
|
||||||
|
if (clouds[i]?.flagToDespawn == true) {
|
||||||
|
clouds[i]?.dispose()
|
||||||
|
clouds[i] = null
|
||||||
|
cloudsSpawned -= 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
cloudUpdateAkku += delta
|
||||||
|
}
|
||||||
|
|
||||||
|
private val scrHscaler = App.scr.height / 720f
|
||||||
|
|
||||||
|
private fun tryToSpawnCloud(currentWeather: BaseModularWeather) {
|
||||||
|
printdbg(this, "Trying to spawn a cloud... (${cloudsSpawned} / ${clouds.size})")
|
||||||
|
|
||||||
|
if (cloudsSpawned < clouds.size) {
|
||||||
|
val rC = Math.random().toFloat()
|
||||||
|
val r0 = (Math.random() * 2.0 - 1.0).toFloat() // -1..1
|
||||||
|
val r1 = (Math.random() * 2.0 - 1.0).toFloat() // -1..1
|
||||||
|
val r2 = (Math.random() * 2.0 - 1.0).toFloat() // -1..1
|
||||||
|
val rT1 = ((Math.random() + Math.random()) - 1.0).toFloat() // -1..1
|
||||||
|
val (rA, rB) = doubleToLongBits(Math.random()).let {
|
||||||
|
it.ushr(20).and(0xFFFF).toInt() to it.ushr(36).and(0xFFFF).toInt()
|
||||||
|
}
|
||||||
|
|
||||||
|
var cloudsToSpawn: CloudProps? = null
|
||||||
|
var c = 0
|
||||||
|
while (c < currentWeather.clouds.size) {
|
||||||
|
if (rC < currentWeather.clouds[c].probability) {
|
||||||
|
cloudsToSpawn = currentWeather.clouds[c]
|
||||||
|
break
|
||||||
|
}
|
||||||
|
c += 1
|
||||||
|
}
|
||||||
|
|
||||||
|
cloudsToSpawn?.let { cloud ->
|
||||||
|
val scaleVariance = 1f + rT1.absoluteValue * cloud.scaleVariance
|
||||||
|
val cloudScale = cloud.baseScale * (if (rT1 < 0) 1f / scaleVariance else scaleVariance)
|
||||||
|
val hCloudSize = cloud.spriteSheet.tileW * cloudScale + 1f
|
||||||
|
val posX = if (cloudDriftVector.x < 0) App.scr.width + hCloudSize else -hCloudSize
|
||||||
|
val posY = when (cloud.category) {
|
||||||
|
"large" -> (100f + r0 * 80f) * scrHscaler
|
||||||
|
else -> (150f + r0 * 50f) * scrHscaler
|
||||||
|
}
|
||||||
|
val sheetX = rA % cloud.spriteSheet.horizontalCount
|
||||||
|
val sheetY = rB % cloud.spriteSheet.verticalCount
|
||||||
|
WeatherObjectCloud(cloud.spriteSheet.get(sheetX, sheetY)).also {
|
||||||
|
it.scale = cloudScale
|
||||||
|
|
||||||
|
it.darkness.set(currentWeather.cloudGamma)
|
||||||
|
it.darkness.x *= it.scale
|
||||||
|
it.darkness.x *= 1f + r1 * 0.1f
|
||||||
|
it.darkness.y *= 1f + r2 * 0.1f
|
||||||
|
|
||||||
|
it.posX = posX
|
||||||
|
it.posY = posY
|
||||||
|
|
||||||
|
clouds.addAtFreeSpot(it)
|
||||||
|
cloudsSpawned += 1
|
||||||
|
|
||||||
|
|
||||||
|
printdbg(this, "... Spawning ${cloud.category}($sheetX, $sheetY) cloud at pos ${it.pos}, invGamma ${it.darkness}")
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun <T> Array<T?>.addAtFreeSpot(obj: T) {
|
||||||
|
var c = 0
|
||||||
|
while (true) {
|
||||||
|
if (this[c] == null) break
|
||||||
|
c += 1
|
||||||
|
}
|
||||||
|
this[c] = obj
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var turbidity = 1.0; private set
|
var turbidity = 1.0; private set
|
||||||
private var gH = 1.8f * App.scr.height
|
private var gH = 1.8f * App.scr.height
|
||||||
// private var gH = 0.8f * App.scr.height
|
// private var gH = 0.8f * App.scr.height
|
||||||
@@ -185,15 +297,16 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
it.a = 1f
|
it.a = 1f
|
||||||
} // TODO add cloud-only colour strip on the CLUT
|
} // TODO add cloud-only colour strip on the CLUT
|
||||||
batch.shader = shaderClouds
|
batch.shader = shaderClouds
|
||||||
batch.inUse {
|
clouds.forEach {
|
||||||
batch.shader.setUniformf("inverseGamma", cloudGamma1, cloudGamma2)
|
it?.let {
|
||||||
currentWeather.clouds["large"]?.get(0, 0)?.let { batch.draw(it, -400f - INGAME.WORLD_UPDATE_TIMER * 0.06f, -600f) }
|
batch.inUse { _ ->
|
||||||
currentWeather.clouds["normal"]?.get(0, 1)?.let { batch.draw(it, 600f - INGAME.WORLD_UPDATE_TIMER * 0.09f, -300f) }
|
batch.shader.setUniformf("gamma", it.darkness)
|
||||||
currentWeather.clouds["normal"]?.get(0, 0)?.let { batch.draw(it, 200f - INGAME.WORLD_UPDATE_TIMER * 0.13f, -150f) }
|
it.render(batch, 0f, 0f) // TODO parallax
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
batch.color = Color.WHITE
|
batch.color = Color.WHITE
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -402,13 +515,27 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
val classification = JSON.getString("classification")
|
val classification = JSON.getString("classification")
|
||||||
|
|
||||||
val cloudGamma = JSON["cloudGamma"].asFloatArray()
|
|
||||||
|
|
||||||
val cloudsMap = HashMap<String, TextureRegionPack>()
|
val cloudsMap = ArrayList<CloudProps>()
|
||||||
val clouds = JSON["clouds"]
|
val clouds = JSON["clouds"]
|
||||||
clouds.forEachSiblings { name, json ->
|
clouds.forEachSiblings { name, json ->
|
||||||
cloudsMap[name] = TextureRegionPack(ModMgr.getGdxFile(modname, "$pathToImage/${json.getString("filename")}"), json.getInt("tw"), json.getInt("th"))
|
cloudsMap.add(CloudProps(
|
||||||
|
name,
|
||||||
|
TextureRegionPack(ModMgr.getGdxFile(modname, "$pathToImage/${json.getString("filename")}"), json.getInt("tw"), json.getInt("th")),
|
||||||
|
json.getFloat("probability"),
|
||||||
|
json.getFloat("baseScale"),
|
||||||
|
json.getFloat("scaleVariance")
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
cloudsMap.sortBy { it.probability }
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var mixFrom: String?
|
var mixFrom: String?
|
||||||
try { mixFrom = JSON.getString("mixFrom") }
|
try { mixFrom = JSON.getString("mixFrom") }
|
||||||
@@ -423,10 +550,13 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
|
|
||||||
|
|
||||||
return BaseModularWeather(
|
return BaseModularWeather(
|
||||||
|
json = JSON,
|
||||||
skyboxGradColourMap = skybox,
|
skyboxGradColourMap = skybox,
|
||||||
daylightClut = daylight,
|
daylightClut = daylight,
|
||||||
classification = classification,
|
classification = classification,
|
||||||
cloudGamma = cloudGamma,
|
cloudChance = JSON.getFloat("cloudChance"),
|
||||||
|
cloudDriftSpeed = JSON.getFloat("cloudDriftSpeed"),
|
||||||
|
cloudGamma = JSON["cloudGamma"].asFloatArray().let { Vector2(it[0], it[1]) },
|
||||||
clouds = cloudsMap,
|
clouds = cloudsMap,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
@@ -434,7 +564,7 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
fun dispose() {
|
fun dispose() {
|
||||||
weatherList.values.forEach { list ->
|
weatherList.values.forEach { list ->
|
||||||
list.forEach { weather ->
|
list.forEach { weather ->
|
||||||
weather.clouds.forEach { it.value.dispose() }
|
weather.clouds.forEach { it.spriteSheet.dispose() }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
starmapTex.texture.dispose()
|
starmapTex.texture.dispose()
|
||||||
@@ -442,3 +572,4 @@ internal object WeatherMixer : RNGConsumer {
|
|||||||
shaderClouds.dispose()
|
shaderClouds.dispose()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
30
src/net/torvald/terrarum/weather/WeatherObject.kt
Normal file
30
src/net/torvald/terrarum/weather/WeatherObject.kt
Normal file
@@ -0,0 +1,30 @@
|
|||||||
|
package net.torvald.terrarum.weather
|
||||||
|
|
||||||
|
import com.badlogic.gdx.graphics.g2d.SpriteBatch
|
||||||
|
import com.badlogic.gdx.math.Vector3
|
||||||
|
import com.badlogic.gdx.utils.Disposable
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-21.
|
||||||
|
*/
|
||||||
|
abstract class WeatherObject : Disposable {
|
||||||
|
|
||||||
|
/** vec3(posX, posY, scale) */
|
||||||
|
var pos: Vector3 = Vector3()
|
||||||
|
|
||||||
|
var posX: Float
|
||||||
|
get() = pos.x
|
||||||
|
set(value) { pos.x = value }
|
||||||
|
var posY: Float
|
||||||
|
get() = pos.y
|
||||||
|
set(value) { pos.y = value }
|
||||||
|
var scale: Float
|
||||||
|
get() = pos.z
|
||||||
|
set(value) { pos.z = value }
|
||||||
|
|
||||||
|
var flagToDespawn = false
|
||||||
|
|
||||||
|
abstract fun update()
|
||||||
|
abstract fun render(batch: SpriteBatch, offsetX: Float, offsetY: Float)
|
||||||
|
|
||||||
|
}
|
||||||
52
src/net/torvald/terrarum/weather/WeatherObjectCloud.kt
Normal file
52
src/net/torvald/terrarum/weather/WeatherObjectCloud.kt
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
package net.torvald.terrarum.weather
|
||||||
|
|
||||||
|
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 kotlin.math.sign
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Created by minjaesong on 2023-08-21.
|
||||||
|
*/
|
||||||
|
class WeatherObjectCloud(private val texture: TextureRegion) : WeatherObject() {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* To actually utilise this value, your render code must begin the spritebatch per-object, like so:
|
||||||
|
* ```
|
||||||
|
* batch.shader = cloudShader
|
||||||
|
* for (it in clouds) {
|
||||||
|
* batch.begin()
|
||||||
|
* batch.shader.setUniformf("gamma", it.darkness)
|
||||||
|
* batch.draw(it, ...)
|
||||||
|
* batch.end()
|
||||||
|
* }
|
||||||
|
*/
|
||||||
|
var darkness: Vector2 = Vector2(0.5f, 2.0f) // the "gamma" value fed into the clouds shader
|
||||||
|
|
||||||
|
override fun update() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* FlowVector: In which direction the cloud flows. Vec3(dX, dY, dScale)
|
||||||
|
* Resulting vector: (x + dX, y + dY, scale * dScale)
|
||||||
|
*/
|
||||||
|
fun update(flowVector: Vector3, gait: Float) {
|
||||||
|
posX += flowVector.x * gait * scale * scale
|
||||||
|
posY += flowVector.y * gait * scale * scale
|
||||||
|
scale *= flowVector.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) {
|
||||||
|
val x = posX + offsetX - texture.regionWidth * scale * 0.5f
|
||||||
|
val y = posY + offsetY - texture.regionHeight * scale
|
||||||
|
|
||||||
|
batch.draw(texture, x, y, texture.regionWidth * scale, texture.regionHeight * scale)
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun dispose() { /* cloud texture will be disposed of by the WeatherMixer */ }
|
||||||
|
}
|
||||||
@@ -14,12 +14,12 @@ out vec4 fragColor;
|
|||||||
|
|
||||||
const vec2 boolean = vec2(0.0, 1.0);
|
const vec2 boolean = vec2(0.0, 1.0);
|
||||||
|
|
||||||
uniform vec2 inverseGamma = vec2(10, 2.0); // vec2(inverse gamma RGB, inverse gamma RGA)
|
uniform vec2 gamma = vec2(10, 2.0); // vec2(gamma for RGB, gamma for A)
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
vec4 inCol = v_color * texture(u_texture, v_texCoords);
|
vec4 inCol = texture(u_texture, v_texCoords);
|
||||||
|
|
||||||
vec4 outCol = pow(inCol, inverseGamma.xxxy);
|
vec4 outCol = pow(inCol, gamma.xxxy);
|
||||||
|
|
||||||
fragColor = outCol;
|
fragColor = outCol * v_color;
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user