more versatile weather CLUT defs

This commit is contained in:
minjaesong
2025-03-22 19:39:35 +09:00
parent c54cafae0f
commit 5c2d201151
15 changed files with 176 additions and 72 deletions

View File

@@ -1,7 +1,7 @@
{ {
"identifier": "clear01", "identifier": "clear01",
"skyboxGradColourMap": "generic_skybox.tga", "skyboxGradColourMap": "model:hosek",
"daylightClut": "clut_daylight.tga", "daylightClut": "lut:clut_daylight.tga",
"tags": "generic,clear", "tags": "generic,clear",
"cloudChance": 12, "cloudChance": 12,
"cloudGamma": [1.2, 2.4], "cloudGamma": [1.2, 2.4],

View File

@@ -1,7 +1,7 @@
{ {
"identifier": "generic01", "identifier": "generic01",
"skyboxGradColourMap": "generic_skybox.tga", "skyboxGradColourMap": "model:hosek",
"daylightClut": "clut_daylight.tga", "daylightClut": "lut:clut_daylight.tga",
"tags": "generic", "tags": "generic",
"cloudChance": 60, "cloudChance": 60,
"cloudGamma": [0.9, 2.4], "cloudGamma": [0.9, 2.4],

View File

@@ -1,7 +1,7 @@
{ {
"identifier": "generic02", "identifier": "generic02",
"skyboxGradColourMap": "generic_skybox.tga", "skyboxGradColourMap": "model:hosek",
"daylightClut": "clut_daylight.tga", "daylightClut": "lut:clut_daylight.tga",
"tags": "generic2", "tags": "generic2",
"cloudChance": 150, "cloudChance": 150,
"cloudGamma": [0.9, 2.4], "cloudGamma": [0.9, 2.4],

View File

@@ -1,7 +1,7 @@
{ {
"identifier": "overcast01", "identifier": "overcast01",
"skyboxGradColourMap": "generic_skybox.tga", "skyboxGradColourMap": "model:hosek",
"daylightClut": "clut_daylight.tga", "daylightClut": "lut:clut_daylight.tga",
"tags": "overcast", "tags": "overcast",
"cloudChance": 200, "cloudChance": 200,
"cloudGamma": [1.45, 1.0], "cloudGamma": [1.45, 1.0],

View File

@@ -0,0 +1,15 @@
{
"identifier": "space",
"skyboxGradColourMap": "static:#020202,#060604",
"daylightClut": "static:#FFFFFF",
"tags": "space",
"cloudChance": 0,
"cloudGamma": [1.0, 1.0],
"cloudGammaVariance": [0.0, 0.0],
"windSpeed": 0.0,
"windSpeedVariance": 0.0,
"windSpeedDamping": 0.0,
"clouds": {},
"atmoTurbidity": 1.0,
"shaderVibrancy": [1.0, 1.0]
}

View File

@@ -13,14 +13,11 @@ import net.torvald.unicode.EMDASH
import net.torvald.colourutil.* import net.torvald.colourutil.*
import net.torvald.parametricsky.datasets.DatasetCIEXYZ import net.torvald.parametricsky.datasets.DatasetCIEXYZ
import net.torvald.terrarum.abs import net.torvald.terrarum.abs
import net.torvald.terrarum.clut.Skybox
import net.torvald.terrarum.clut.Skybox.coerceInSmoothly
import net.torvald.terrarum.clut.Skybox.mapCircle
import net.torvald.terrarum.inUse import net.torvald.terrarum.inUse
import net.torvald.terrarum.modulebasegame.worldgenerator.HALF_PI import net.torvald.terrarum.modulebasegame.worldgenerator.HALF_PI
import net.torvald.terrarum.weather.SkyboxModelHosek.coerceInSmoothly
import java.awt.BorderLayout import java.awt.BorderLayout
import java.awt.Dimension import java.awt.Dimension
import java.lang.Math.pow
import javax.swing.* import javax.swing.*
import kotlin.math.* import kotlin.math.*

View File

@@ -61,6 +61,15 @@ class GdxColorMap {
is2D = (height > 1) is2D = (height > 1)
} }
constructor(width: Int, height: Int, colours: List<Color>) {
dataRaw = colours.map { it.toIntBits() }.toIntArray()
dataGdxColor = dataRaw.map { Color(it) }.toTypedArray()
dataCvec = dataRaw.map { Cvec(it) }.toTypedArray()
this.width = width
this.height = height
is2D = (height > 1)
}
private val dataRaw: IntArray private val dataRaw: IntArray
private val dataGdxColor: Array<Color> private val dataGdxColor: Array<Color>
private val dataCvec: Array<Cvec> private val dataCvec: Array<Cvec>

View File

@@ -8,12 +8,13 @@ import net.torvald.colourutil.toRGB
import net.torvald.gdx.graphics.Cvec import net.torvald.gdx.graphics.Cvec
import net.torvald.parametricsky.ArHosekSkyModel import net.torvald.parametricsky.ArHosekSkyModel
import net.torvald.terrarum.abs import net.torvald.terrarum.abs
import net.torvald.terrarum.clut.Skybox.coerceInSmoothly
import net.torvald.terrarum.clut.Skybox.mapCircle
import net.torvald.terrarum.clut.Skybox.scaleToFit
import net.torvald.terrarum.modulebasegame.worldgenerator.HALF_PI import net.torvald.terrarum.modulebasegame.worldgenerator.HALF_PI
import net.torvald.terrarum.serialise.toLittle import net.torvald.terrarum.serialise.toLittle
import net.torvald.terrarum.serialise.toUint import net.torvald.terrarum.serialise.toUint
import net.torvald.terrarum.weather.SkyboxModelHosek
import net.torvald.terrarum.weather.SkyboxModelHosek.coerceInSmoothly
import net.torvald.terrarum.weather.SkyboxModelHosek.mapCircle
import net.torvald.terrarum.weather.SkyboxModelHosek.scaleToFit
import java.io.File import java.io.File
import kotlin.math.PI import kotlin.math.PI
import kotlin.math.cos import kotlin.math.cos
@@ -42,7 +43,7 @@ class GenerateSkyboxTextureAtlas {
val state = val state =
ArHosekSkyModel.arhosek_xyz_skymodelstate_alloc_init(turbidity, albedo, elevationRad.abs()) ArHosekSkyModel.arhosek_xyz_skymodelstate_alloc_init(turbidity, albedo, elevationRad.abs())
for (yp in 0 until Skybox.gradSize) { for (yp in 0 until SkyboxModelHosek.gradSize) {
val yi = yp - 10 val yi = yp - 10
val xf = -elevationDeg / 90.0 val xf = -elevationDeg / 90.0
var yf = (yi / 58.0).coerceIn(0.0, 1.0).mapCircle().coerceInSmoothly(0.0, 0.95) var yf = (yi / 58.0).coerceIn(0.0, 1.0).mapCircle().coerceInSmoothly(0.0, 0.95)
@@ -81,9 +82,9 @@ class GenerateSkyboxTextureAtlas {
// y: increasing turbidity (1.0 .. 10.0, in steps of 0.333) // y: increasing turbidity (1.0 .. 10.0, in steps of 0.333)
// x: elevations (-75 .. 75 in steps of 1, then albedo of [0.1, 0.3, 0.5, 0.7, 0.9]) // x: elevations (-75 .. 75 in steps of 1, then albedo of [0.1, 0.3, 0.5, 0.7, 0.9])
val TGA_HEADER_SIZE = 18 val TGA_HEADER_SIZE = 18
val texh = Skybox.gradSize * Skybox.turbCnt val texh = SkyboxModelHosek.gradSize * SkyboxModelHosek.turbCnt
val texh2 = Skybox.turbCnt val texh2 = SkyboxModelHosek.turbCnt
val texw = Skybox.elevCnt * Skybox.albedoCnt * 2 val texw = SkyboxModelHosek.elevCnt * SkyboxModelHosek.albedoCnt * 2
val bytesSize = texw * texh val bytesSize = texw * texh
val bytes2Size = texw * texh2 val bytes2Size = texw * texh2
val bytes = ByteArray(TGA_HEADER_SIZE + bytesSize * 4 + 26) val bytes = ByteArray(TGA_HEADER_SIZE + bytesSize * 4 + 26)
@@ -113,18 +114,18 @@ class GenerateSkyboxTextureAtlas {
// write pixels // write pixels
for (gammaPair in 0..1) { for (gammaPair in 0..1) {
for (albedo0 in 0 until Skybox.albedoCnt) { for (albedo0 in 0 until SkyboxModelHosek.albedoCnt) {
val albedo = Skybox.albedos[albedo0] val albedo = SkyboxModelHosek.albedos[albedo0]
println("Albedo=$albedo") println("Albedo=$albedo")
for (turb0 in 0 until Skybox.turbCnt) { for (turb0 in 0 until SkyboxModelHosek.turbCnt) {
val turbidity = Skybox.turbiditiesD[turb0] val turbidity = SkyboxModelHosek.turbiditiesD[turb0]
println("....... Turbidity=$turbidity") println("....... Turbidity=$turbidity")
for (elev0 in 0 until Skybox.elevCnt) { for (elev0 in 0 until SkyboxModelHosek.elevCnt) {
var elevationDeg = Skybox.elevationsD[elev0] var elevationDeg = SkyboxModelHosek.elevationsD[elev0]
if (elevationDeg == 0.0) elevationDeg = 0.5 // dealing with the edge case if (elevationDeg == 0.0) elevationDeg = 0.5 // dealing with the edge case
generateStrip(gammaPair, albedo, turbidity, elevationDeg) { yp, i, colour -> generateStrip(gammaPair, albedo, turbidity, elevationDeg) { yp, i, colour ->
val imgOffX = albedo0 * Skybox.elevCnt + elev0 + Skybox.elevCnt * Skybox.albedoCnt * gammaPair val imgOffX = albedo0 * SkyboxModelHosek.elevCnt + elev0 + SkyboxModelHosek.elevCnt * SkyboxModelHosek.albedoCnt * gammaPair
val imgOffY = texh - 1 - (Skybox.gradSize * turb0 + yp) val imgOffY = texh - 1 - (SkyboxModelHosek.gradSize * turb0 + yp)
val fileOffset = TGA_HEADER_SIZE + 4 * (imgOffY * texw + imgOffX) val fileOffset = TGA_HEADER_SIZE + 4 * (imgOffY * texw + imgOffX)
bytes[fileOffset + i] = colour bytes[fileOffset + i] = colour
} }
@@ -140,8 +141,8 @@ class GenerateSkyboxTextureAtlas {
private val gradSizes = listOf(50) private val gradSizes = listOf(50)
private fun getByte(gammaPair: Int, albedo0: Int, turb0: Int, elev0: Int, yp: Int, channel: Int): Byte { private fun getByte(gammaPair: Int, albedo0: Int, turb0: Int, elev0: Int, yp: Int, channel: Int): Byte {
val imgOffX = albedo0 * Skybox.elevCnt + elev0 + Skybox.elevCnt * Skybox.albedoCnt * gammaPair val imgOffX = albedo0 * SkyboxModelHosek.elevCnt + elev0 + SkyboxModelHosek.elevCnt * SkyboxModelHosek.albedoCnt * gammaPair
val imgOffY = texh - 1 - (Skybox.gradSize * turb0 + yp) val imgOffY = texh - 1 - (SkyboxModelHosek.gradSize * turb0 + yp)
val fileOffset = TGA_HEADER_SIZE + 4 * (imgOffY * texw + imgOffX) val fileOffset = TGA_HEADER_SIZE + 4 * (imgOffY * texw + imgOffX)
return bytes[fileOffset + channel] return bytes[fileOffset + channel]
} }
@@ -171,13 +172,13 @@ class GenerateSkyboxTextureAtlas {
for (gammaPair in 0..1) { for (gammaPair in 0..1) {
for (albedo0 in 0 until Skybox.albedoCnt) { for (albedo0 in 0 until SkyboxModelHosek.albedoCnt) {
val albedo = Skybox.albedos[albedo0] val albedo = SkyboxModelHosek.albedos[albedo0]
println("Albedo=$albedo") println("Albedo=$albedo")
for (turb0 in 0 until Skybox.turbCnt) { for (turb0 in 0 until SkyboxModelHosek.turbCnt) {
val turbidity = Skybox.turbiditiesD[turb0] val turbidity = SkyboxModelHosek.turbiditiesD[turb0]
println("....... Turbidity=$turbidity") println("....... Turbidity=$turbidity")
for (elev0 in 0 until Skybox.elevCnt) { for (elev0 in 0 until SkyboxModelHosek.elevCnt) {
val avrB = (gradSizes.sumOf { getByte(gammaPair, albedo0, turb0, elev0, it, 0).toUint() }.toDouble() / gradSizes.size).div(255.0).toFloat() val avrB = (gradSizes.sumOf { getByte(gammaPair, albedo0, turb0, elev0, it, 0).toUint() }.toDouble() / gradSizes.size).div(255.0).toFloat()
val avrG = (gradSizes.sumOf { getByte(gammaPair, albedo0, turb0, elev0, it, 1).toUint() }.toDouble() / gradSizes.size).div(255.0).toFloat() val avrG = (gradSizes.sumOf { getByte(gammaPair, albedo0, turb0, elev0, it, 1).toUint() }.toDouble() / gradSizes.size).div(255.0).toFloat()
@@ -193,7 +194,7 @@ class GenerateSkyboxTextureAtlas {
colour.a.times(255f).roundToInt().coerceIn(0..255).toByte() colour.a.times(255f).roundToInt().coerceIn(0..255).toByte()
) )
val imgOffX = albedo0 * Skybox.elevCnt + elev0 + Skybox.elevCnt * Skybox.albedoCnt * gammaPair val imgOffX = albedo0 * SkyboxModelHosek.elevCnt + elev0 + SkyboxModelHosek.elevCnt * SkyboxModelHosek.albedoCnt * gammaPair
val imgOffY = texh2 - 1 - turb0 val imgOffY = texh2 - 1 - turb0
val fileOffset = TGA_HEADER_SIZE + 4 * (imgOffY * texw + imgOffX) val fileOffset = TGA_HEADER_SIZE + 4 * (imgOffY * texw + imgOffX)

View File

@@ -17,7 +17,6 @@ import net.torvald.terrarum.App.printdbgerr
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZE
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZED
import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF import net.torvald.terrarum.TerrarumAppConfiguration.TILE_SIZEF
import net.torvald.terrarum.clut.Skybox
import net.torvald.terrarum.console.CommandDict import net.torvald.terrarum.console.CommandDict
import net.torvald.terrarum.gameactors.* import net.torvald.terrarum.gameactors.*
import net.torvald.terrarum.gameactors.ai.ActorAI import net.torvald.terrarum.gameactors.ai.ActorAI
@@ -35,8 +34,8 @@ import net.torvald.terrarum.realestate.LandUtil
import net.torvald.terrarum.serialise.ReadSimpleWorld import net.torvald.terrarum.serialise.ReadSimpleWorld
import net.torvald.terrarum.ui.Toolkit import net.torvald.terrarum.ui.Toolkit
import net.torvald.terrarum.ui.UICanvas import net.torvald.terrarum.ui.UICanvas
import net.torvald.terrarum.ui.UIItemTextButton
import net.torvald.terrarum.utils.OpenURL import net.torvald.terrarum.utils.OpenURL
import net.torvald.terrarum.weather.SkyboxModelHosek
import net.torvald.terrarum.weather.WeatherMixer import net.torvald.terrarum.weather.WeatherMixer
import net.torvald.terrarum.worlddrawer.WorldCamera import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.util.CircularArray import net.torvald.util.CircularArray
@@ -247,7 +246,7 @@ class TitleScreen(batch: FlippingSpriteBatch) : IngameInstance(batch) {
uiContainer.add(uiRemoCon) uiContainer.add(uiRemoCon)
CommandDict // invoke CommandDict // invoke
Skybox.loadlut() // invoke SkyboxModelHosek.loadlut() // invoke
// Skybox.initiate() // invoke the lengthy calculation // Skybox.initiate() // invoke the lengthy calculation
// TODO add console here // TODO add console here

View File

@@ -19,7 +19,7 @@ import kotlin.math.absoluteValue
data class BaseModularWeather( data class BaseModularWeather(
val identifier: String, val identifier: String,
val json: JsonValue, val json: JsonValue,
var skyboxGradColourMap: GdxColorMap, // row 0: skybox grad top, row 1: skybox grad bottom, row 2: sunlight (RGBA) var skyboxGradColourMap: SkyboxModel, // row 0: skybox grad top, row 1: skybox grad bottom, row 2: sunlight (RGBA)
val daylightClut: GdxColorMap, val daylightClut: GdxColorMap,
val tags: List<String>, val tags: List<String>,
val cloudChance: Float, val cloudChance: Float,

View File

@@ -0,0 +1,12 @@
package net.torvald.terrarum.weather
import net.torvald.terrarum.GdxColorMap
/**
* Created by minjaesong on 2025-03-22.
*/
class SkyboxGradSimple(val clut: GdxColorMap): SkyboxModel {
override fun dispose() {}
}

View File

@@ -0,0 +1,9 @@
package net.torvald.terrarum.weather
import com.badlogic.gdx.utils.Disposable
/**
* Created by minjaesong on 2025-03-22.
*/
interface SkyboxModel : Disposable {
}

View File

@@ -1,4 +1,4 @@
package net.torvald.terrarum.clut package net.torvald.terrarum.weather
import com.badlogic.gdx.Gdx import com.badlogic.gdx.Gdx
import com.badlogic.gdx.graphics.Pixmap import com.badlogic.gdx.graphics.Pixmap
@@ -14,14 +14,13 @@ import net.torvald.terrarum.App
import net.torvald.terrarum.App.printdbg import net.torvald.terrarum.App.printdbg
import net.torvald.terrarum.abs import net.torvald.terrarum.abs
import net.torvald.terrarum.floorToInt import net.torvald.terrarum.floorToInt
import net.torvald.terrarum.toInt
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import kotlin.math.* import kotlin.math.*
/** /**
* Created by minjaesong on 2023-07-09. * Created by minjaesong on 2023-07-09.
*/ */
object Skybox : Disposable { object SkyboxModelHosek : SkyboxModel {
private const val HALF_PI = 1.5707963267948966 private const val HALF_PI = 1.5707963267948966
private const val PI = 3.141592653589793 private const val PI = 3.141592653589793
@@ -294,8 +293,8 @@ object Skybox : Disposable {
} }
override fun dispose() { override fun dispose() {
if (Skybox::gradTexBinLowAlbedo.isInitialized) gradTexBinLowAlbedo.forEach { it.texture.dispose() } if (SkyboxModelHosek::gradTexBinLowAlbedo.isInitialized) gradTexBinLowAlbedo.forEach { it.texture.dispose() }
if (Skybox::gradTexBinHighAlbedo.isInitialized) gradTexBinHighAlbedo.forEach { it.texture.dispose() } if (SkyboxModelHosek::gradTexBinHighAlbedo.isInitialized) gradTexBinHighAlbedo.forEach { it.texture.dispose() }
if (Skybox::tex.isInitialized) tex.dispose() if (SkyboxModelHosek::tex.isInitialized) tex.dispose()
} }
} }

View File

@@ -1,5 +1,6 @@
package net.torvald.terrarum.weather package net.torvald.terrarum.weather
import com.badlogic.gdx.graphics.Color
import com.badlogic.gdx.math.Vector2 import com.badlogic.gdx.math.Vector2
import com.badlogic.gdx.utils.Disposable import com.badlogic.gdx.utils.Disposable
import net.torvald.terrarum.App import net.torvald.terrarum.App
@@ -39,6 +40,8 @@ class WeatherCodex : Disposable {
fun readFromJson(modname: String, file: File) = readFromJson(modname, file.path) fun readFromJson(modname: String, file: File) = readFromJson(modname, file.path)
private val pathToImage = "weathers"
fun readFromJson(modname: String, path: String) { fun readFromJson(modname: String, path: String) {
/* JSON structure: /* JSON structure:
{ {
@@ -52,12 +55,11 @@ class WeatherCodex : Disposable {
] ]
} }
*/ */
val pathToImage = "weathers"
val JSON = JsonFetcher(path) val JSON = JsonFetcher(path)
val skyboxInJson = JSON.getString("skyboxGradColourMap") val skyboxModel = JSON.getString("skyboxGradColourMap")
val lightbox = JSON.getString("daylightClut") val lightboxModel = JSON.getString("daylightClut")
val cloudsMap = ArrayList<CloudProps>() val cloudsMap = ArrayList<CloudProps>()
val clouds = JSON["clouds"] val clouds = JSON["clouds"]
@@ -81,8 +83,8 @@ class WeatherCodex : Disposable {
val obj = BaseModularWeather( val obj = BaseModularWeather(
identifier = ident, identifier = ident,
json = JSON, json = JSON,
skyboxGradColourMap = GdxColorMap(ModMgr.getGdxFile(modname, "$pathToImage/${skyboxInJson}")), skyboxGradColourMap = getSkyboxModelByName(modname, skyboxModel),
daylightClut = GdxColorMap(ModMgr.getGdxFile(modname, "$pathToImage/${lightbox}")), daylightClut = getLightboxModelByName(modname, lightboxModel),
tags = tags, tags = tags,
cloudChance = JSON.getFloat("cloudChance"), cloudChance = JSON.getFloat("cloudChance"),
windSpeed = JSON.getFloat("windSpeed"), windSpeed = JSON.getFloat("windSpeed"),
@@ -118,4 +120,71 @@ class WeatherCodex : Disposable {
} }
else getByTag(tag)!!.random() else getByTag(tag)!!.random()
} }
private fun getSkyboxModelByName(modname: String, name: String): SkyboxModel {
return if (name.startsWith("model:")) {
when (name.substring(6)) {
"hosek" -> SkyboxModelHosek
else -> throw UnsupportedOperationException("Unknown skybox model: '$name'")
}
}
else if (name.startsWith("lut:")) {
val filename = name.substring(4)
val colourMap = GdxColorMap(ModMgr.getGdxFile(modname, "$pathToImage/${filename}"))
SkyboxGradSimple(colourMap)
}
else if (name.startsWith("static:")) {
val argstr = name.substring(7)
val args = argstr.split(',').map {
if (it.length == 7) // #RRGGBB
Color(
it.substring(1, 3).toInt(16) / 255.0f,
it.substring(3, 5).toInt(16) / 255.0f,
it.substring(5, 7).toInt(16) / 255.0f,
1f,
)
else if (it.length == 9) // #RRGGBBAA
Color(
it.substring(1, 3).toInt(16) / 255.0f,
it.substring(3, 5).toInt(16) / 255.0f,
it.substring(5, 7).toInt(16) / 255.0f,
it.substring(7, 9).toInt(16) / 255.0f,
)
else if (it.length == 4) // #RGB
Color(
it.substring(1, 2).toInt(16) / 15.0f,
it.substring(2, 3).toInt(16) / 15.0f,
it.substring(3, 4).toInt(16) / 15.0f,
1f,
)
else if (it.length == 5) // #RGBA
Color(
it.substring(1, 2).toInt(16) / 15.0f,
it.substring(2, 3).toInt(16) / 15.0f,
it.substring(3, 4).toInt(16) / 15.0f,
it.substring(4, 5).toInt(16) / 15.0f,
)
else throw IllegalArgumentException("Unknown colour code: $it")
}
SkyboxGradSimple(GdxColorMap(args.size, 1, args))
}
else {
throw UnsupportedOperationException("Unknown skybox: '$name'")
}
}
private fun getLightboxModelByName(modname: String, name: String): GdxColorMap {
return if (name.startsWith("lut:")) {
val filename = name.substring(4)
GdxColorMap(ModMgr.getGdxFile(modname, "$pathToImage/${filename}"))
}
else if (name.startsWith("static:")) {
val argstr = name.substring(7)
val args = argstr.split(',').map { Color.WHITE }
GdxColorMap(args.size, 1, args)
}
else {
throw UnsupportedOperationException("Unknown skybox: '$name'")
}
}
} }

View File

@@ -19,17 +19,11 @@ import net.torvald.terrarum.gameworld.GameWorld
import net.torvald.terrarum.gameworld.WorldTime import net.torvald.terrarum.gameworld.WorldTime
import net.torvald.terrarum.gameworld.WorldTime.Companion.DAY_LENGTH import net.torvald.terrarum.gameworld.WorldTime.Companion.DAY_LENGTH
import net.torvald.terrarum.RNGConsumer import net.torvald.terrarum.RNGConsumer
import net.torvald.terrarum.clut.Skybox import net.torvald.terrarum.weather.SkyboxModelHosek.elevCnt
import net.torvald.terrarum.clut.Skybox.elevCnt
import net.torvald.terrarum.utils.JsonFetcher
import net.torvald.terrarum.utils.forEachSiblings
import net.torvald.terrarum.weather.WeatherObjectCloud.Companion.ALPHA_ROLLOFF_Z import net.torvald.terrarum.weather.WeatherObjectCloud.Companion.ALPHA_ROLLOFF_Z
import net.torvald.terrarum.weather.WeatherObjectCloud.Companion.NEWBORN_GROWTH_TIME import net.torvald.terrarum.weather.WeatherObjectCloud.Companion.NEWBORN_GROWTH_TIME
import net.torvald.terrarum.worlddrawer.WorldCamera import net.torvald.terrarum.worlddrawer.WorldCamera
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
import net.torvald.util.SortedArrayList import net.torvald.util.SortedArrayList
import java.io.File
import java.io.FileFilter
import java.lang.Double.doubleToLongBits import java.lang.Double.doubleToLongBits
import java.lang.Math.toDegrees import java.lang.Math.toDegrees
import kotlin.collections.ArrayList import kotlin.collections.ArrayList
@@ -57,7 +51,7 @@ internal object WeatherMixer : RNGConsumer {
val DEFAULT_WEATHER = BaseModularWeather( val DEFAULT_WEATHER = BaseModularWeather(
"default", "default",
JsonValue(JsonValue.ValueType.`object`), JsonValue(JsonValue.ValueType.`object`),
GdxColorMap(1, 3, Color(0x55aaffff), Color(0xaaffffff.toInt()), Color.WHITE), SkyboxGradSimple(GdxColorMap(1, 2, Color(0x55aaffff), Color(0xaaffffff.toInt()))),
GdxColorMap(2, 2, Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE), GdxColorMap(2, 2, Color.WHITE, Color.WHITE, Color.WHITE, Color.WHITE),
listOf("default"), listOf("default"),
0f, 0f,
@@ -556,7 +550,7 @@ internal object WeatherMixer : RNGConsumer {
fun g(x: Double) = Math.toDegrees(atan(RECIPROCAL_OF_APPARENT_SOLAR_Y_AT_45DEG * x)) fun g(x: Double) = Math.toDegrees(atan(RECIPROCAL_OF_APPARENT_SOLAR_Y_AT_45DEG * x))
val phi = currentsolarDeg + CLOUD_SOLARDEG_OFFSET val phi = currentsolarDeg + CLOUD_SOLARDEG_OFFSET
val x = cloudY val x = cloudY
return g(x + a(phi)).bipolarClamp(Skybox.elevMax) return g(x + a(phi)).bipolarClamp(SkyboxModelHosek.elevMax)
} }
/** /**
@@ -661,7 +655,7 @@ internal object WeatherMixer : RNGConsumer {
val gradY = -(gH - App.scr.height) * ((parallax + 1f) / 2f) val gradY = -(gH - App.scr.height) * ((parallax + 1f) / 2f)
val (tex, uvs, turbTihsBlend, albThisBlend, turbOldBlend, albOldBlend) = Skybox.getUV( val (tex, uvs, turbTihsBlend, albThisBlend, turbOldBlend, albOldBlend) = SkyboxModelHosek.getUV(
solarElev, solarElev,
oldTurbidity, oldTurbidity,
oldAlbedo, oldAlbedo,
@@ -819,14 +813,14 @@ internal object WeatherMixer : RNGConsumer {
val angleX2 = (angleX1 + 1).coerceAtMost(150) val angleX2 = (angleX1 + 1).coerceAtMost(150)
val ax = solarAngleInDeg - solarAngleInDegInt val ax = solarAngleInDeg - solarAngleInDegInt
// fine-grained // fine-grained
val turbY = turbidity.coerceIn(Skybox.turbiditiesD.first(), Skybox.turbiditiesD.last()).minus(1.0) val turbY = turbidity.coerceIn(SkyboxModelHosek.turbiditiesD.first(), SkyboxModelHosek.turbiditiesD.last()).minus(1.0)
.times(Skybox.turbDivisor) .times(SkyboxModelHosek.turbDivisor)
val turbY1 = turbY.floorToInt() val turbY1 = turbY.floorToInt()
val turbY2 = (turbY1 + 1).coerceAtMost(Skybox.turbCnt - 1) val turbY2 = (turbY1 + 1).coerceAtMost(SkyboxModelHosek.turbCnt - 1)
val tx = turbY - turbY1 val tx = turbY - turbY1
// coarse-grained // coarse-grained
val albX = val albX =
albedo.coerceIn(Skybox.albedos.first(), Skybox.albedos.last()).times(5.0) // 0..5 albedo.coerceIn(SkyboxModelHosek.albedos.first(), SkyboxModelHosek.albedos.last()).times(5.0) // 0..5
val albX1 = albX.floorToInt() * elevCnt val albX1 = albX.floorToInt() * elevCnt
val albX2 = (albX + 1).floorToInt().coerceAtMost(5) * elevCnt val albX2 = (albX + 1).floorToInt().coerceAtMost(5) * elevCnt
val bx = ((albX * elevCnt) - albX1) / elevCnt val bx = ((albX * elevCnt) - albX1) / elevCnt
@@ -844,14 +838,14 @@ internal object WeatherMixer : RNGConsumer {
val a2t1b2A = colorMap.getCvec(albX2 + angleX2, turbY1) val a2t1b2A = colorMap.getCvec(albX2 + angleX2, turbY1)
val a1t2b2A = colorMap.getCvec(albX2 + angleX1, turbY2) val a1t2b2A = colorMap.getCvec(albX2 + angleX1, turbY2)
val a2t2b2A = colorMap.getCvec(albX2 + angleX2, turbY2) val a2t2b2A = colorMap.getCvec(albX2 + angleX2, turbY2)
val a1t1b1B = colorMap.getCvec(albX1 + angleX1 + Skybox.albedoCnt * elevCnt, turbY1) val a1t1b1B = colorMap.getCvec(albX1 + angleX1 + SkyboxModelHosek.albedoCnt * elevCnt, turbY1)
val a2t1b1B = colorMap.getCvec(albX1 + angleX2 + Skybox.albedoCnt * elevCnt, turbY1) val a2t1b1B = colorMap.getCvec(albX1 + angleX2 + SkyboxModelHosek.albedoCnt * elevCnt, turbY1)
val a1t2b1B = colorMap.getCvec(albX1 + angleX1 + Skybox.albedoCnt * elevCnt, turbY2) val a1t2b1B = colorMap.getCvec(albX1 + angleX1 + SkyboxModelHosek.albedoCnt * elevCnt, turbY2)
val a2t2b1B = colorMap.getCvec(albX1 + angleX2 + Skybox.albedoCnt * elevCnt, turbY2) val a2t2b1B = colorMap.getCvec(albX1 + angleX2 + SkyboxModelHosek.albedoCnt * elevCnt, turbY2)
val a1t1b2B = colorMap.getCvec(albX2 + angleX1 + Skybox.albedoCnt * elevCnt, turbY1) val a1t1b2B = colorMap.getCvec(albX2 + angleX1 + SkyboxModelHosek.albedoCnt * elevCnt, turbY1)
val a2t1b2B = colorMap.getCvec(albX2 + angleX2 + Skybox.albedoCnt * elevCnt, turbY1) val a2t1b2B = colorMap.getCvec(albX2 + angleX2 + SkyboxModelHosek.albedoCnt * elevCnt, turbY1)
val a1t2b2B = colorMap.getCvec(albX2 + angleX1 + Skybox.albedoCnt * elevCnt, turbY2) val a1t2b2B = colorMap.getCvec(albX2 + angleX1 + SkyboxModelHosek.albedoCnt * elevCnt, turbY2)
val a2t2b2B = colorMap.getCvec(albX2 + angleX2 + Skybox.albedoCnt * elevCnt, turbY2) val a2t2b2B = colorMap.getCvec(albX2 + angleX2 + SkyboxModelHosek.albedoCnt * elevCnt, turbY2)
// no srgblerp here to match the skybox shader's behaviour // no srgblerp here to match the skybox shader's behaviour