mirror of
https://github.com/curioustorvald/Terrarum.git
synced 2026-03-07 12:21:52 +09:00
skybox: two different setup for AM/PN
This commit is contained in:
BIN
assets/clut/skybox.png
LFS
BIN
assets/clut/skybox.png
LFS
Binary file not shown.
31
assets/mods/basegame/locales/en/calendar.json
Normal file
31
assets/mods/basegame/locales/en/calendar.json
Normal file
@@ -0,0 +1,31 @@
|
||||
{
|
||||
"GAME_ITEM_CALENDAR": "Calendar",
|
||||
"MENU_CALENDAR_CALENDAR": "Calendar",
|
||||
"MENU_CALENDAR_EVENTS": "Events",
|
||||
"MENU_CALENDAR_ADD_NEW_EVENT": "Add New Event…",
|
||||
"CONTEXT_CALENDAR_SEASON_SPRING": "Spring",
|
||||
"CONTEXT_CALENDAR_SEASON_SUMMER": "Summer",
|
||||
"CONTEXT_CALENDAR_SEASON_AUTUMN": "Autumn",
|
||||
"CONTEXT_CALENDAR_SEASON_WINTER": "Winter",
|
||||
"CONTEXT_CALENDAR_SEASON_SPRI": "Spri",
|
||||
"CONTEXT_CALENDAR_SEASON_SUMM": "Summ",
|
||||
"CONTEXT_CALENDAR_SEASON_AUTM": "Autm",
|
||||
"CONTEXT_CALENDAR_SEASON_WINT": "Wint",
|
||||
|
||||
"CONTEXT_CALENDAR_DAY_MONDAG_DNT": "Mondag",
|
||||
"CONTEXT_CALENDAR_DAY_TYSDAG_DNT": "Tysdag",
|
||||
"CONTEXT_CALENDAR_DAY_MIDTVEKE_DNT": "Midtveke",
|
||||
"CONTEXT_CALENDAR_DAY_TORSDAG_DNT": "Torsdag",
|
||||
"CONTEXT_CALENDAR_DAY_FREDAG_DNT": "Fredag",
|
||||
"CONTEXT_CALENDAR_DAY_LAURDAG_DNT": "Laurdag",
|
||||
"CONTEXT_CALENDAR_DAY_SUNDAG_DNT": "Sundag",
|
||||
"CONTEXT_CALENDAR_DAY_VERDDAG_DNT": "Verddag",
|
||||
"CONTEXT_CALENDAR_DAY_MON_DNT": "Mon",
|
||||
"CONTEXT_CALENDAR_DAY_TYS_DNT": "Tys",
|
||||
"CONTEXT_CALENDAR_DAY_MID_DNT": "Mid",
|
||||
"CONTEXT_CALENDAR_DAY_TOR_DNT": "Tor",
|
||||
"CONTEXT_CALENDAR_DAY_FRE_DNT": "Fre",
|
||||
"CONTEXT_CALENDAR_DAY_LAU_DNT": "Lau",
|
||||
"CONTEXT_CALENDAR_DAY_SUN_DNT": "Sun",
|
||||
"CONTEXT_CALENDAR_DAY_VER_DNT": "Ver"
|
||||
}
|
||||
14
assets/mods/basegame/locales/koKR/calendar.json
Normal file
14
assets/mods/basegame/locales/koKR/calendar.json
Normal file
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"GAME_ITEM_CALENDAR": "달력",
|
||||
"MENU_CALENDAR_CALENDAR": "달력",
|
||||
"MENU_CALENDAR_EVENTS": "일정",
|
||||
"MENU_CALENDAR_ADD_NEW_EVENT": "새 일정 추가…",
|
||||
"CONTEXT_CALENDAR_SEASON_SPRING": "봄",
|
||||
"CONTEXT_CALENDAR_SEASON_SUMMER": "여름",
|
||||
"CONTEXT_CALENDAR_SEASON_AUTUMN": "가을",
|
||||
"CONTEXT_CALENDAR_SEASON_WINTER": "겨울",
|
||||
"CONTEXT_CALENDAR_SEASON_SPRI": "봄",
|
||||
"CONTEXT_CALENDAR_SEASON_SUMM": "여름",
|
||||
"CONTEXT_CALENDAR_SEASON_AUTM": "가을",
|
||||
"CONTEXT_CALENDAR_SEASON_WINT": "겨울"
|
||||
}
|
||||
@@ -19,7 +19,7 @@ fun main() {
|
||||
// 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])
|
||||
val texh = Skybox.gradSize * Skybox.turbCnt
|
||||
val texw = Skybox.elevCnt * Skybox.albedoCnt
|
||||
val texw = Skybox.elevCnt * Skybox.albedoCnt * 2
|
||||
val TGA_HEADER_SIZE = 18
|
||||
|
||||
val bytes = ByteArray(TGA_HEADER_SIZE + texw * texh * 4 + 26)
|
||||
@@ -44,47 +44,50 @@ fun main() {
|
||||
println("Generating texture atlas ($texw x $texh)...")
|
||||
|
||||
// write pixels
|
||||
for (albedo0 in 0 until Skybox.albedoCnt) {
|
||||
val albedo = Skybox.albedos[albedo0]
|
||||
println("Albedo=$albedo")
|
||||
for (turb0 in 0 until Skybox.turbCnt) {
|
||||
val turbidity = Skybox.turbiditiesD[turb0]
|
||||
println("....... Turbidity=$turbidity")
|
||||
for (elev0 in 0 until Skybox.elevCnt) {
|
||||
val elevationDeg = Skybox.elevationsD[elev0]
|
||||
val elevationRad = Math.toRadians(elevationDeg)
|
||||
for (gammaPair in 0..1) {
|
||||
for (albedo0 in 0 until Skybox.albedoCnt) {
|
||||
val albedo = Skybox.albedos[albedo0]
|
||||
println("Albedo=$albedo")
|
||||
for (turb0 in 0 until Skybox.turbCnt) {
|
||||
val turbidity = Skybox.turbiditiesD[turb0]
|
||||
println("....... Turbidity=$turbidity")
|
||||
for (elev0 in 0 until Skybox.elevCnt) {
|
||||
val elevationDeg = Skybox.elevationsD[elev0]
|
||||
val elevationRad = Math.toRadians(elevationDeg)
|
||||
// println("... Elevation: $elevationDeg")
|
||||
|
||||
val state = ArHosekSkyModel.arhosek_xyz_skymodelstate_alloc_init(turbidity, albedo, elevationRad.abs())
|
||||
val state =
|
||||
ArHosekSkyModel.arhosek_xyz_skymodelstate_alloc_init(turbidity, albedo, elevationRad.abs())
|
||||
|
||||
for (yp in 0 until Skybox.gradSize) {
|
||||
val yi = yp - 3
|
||||
val xf = -elevationDeg / 90.0
|
||||
var yf = (yi / 58.0).coerceIn(0.0, 1.0).mapCircle().coerceInSmoothly(0.0, 0.95)
|
||||
for (yp in 0 until Skybox.gradSize) {
|
||||
val yi = yp - 3
|
||||
val xf = -elevationDeg / 90.0
|
||||
var yf = (yi / 58.0).coerceIn(0.0, 1.0).mapCircle().coerceInSmoothly(0.0, 0.95)
|
||||
|
||||
// experiments visualisation: https://www.desmos.com/calculator/5crifaekwa
|
||||
// experiments visualisation: https://www.desmos.com/calculator/5crifaekwa
|
||||
// if (elevationDeg < 0) yf *= 1.0 - pow(xf, 0.333)
|
||||
// if (elevationDeg < 0) yf *= -2.0 * asin(xf - 1.0) / PI
|
||||
if (elevationDeg < 0) yf *= Skybox.superellipsoidDecay(1.0 / 3.0, xf)
|
||||
val theta = yf * HALF_PI
|
||||
// vertical angle, where 0 is zenith, ±90 is ground (which is odd)
|
||||
if (elevationDeg < 0) yf *= Skybox.superellipsoidDecay(1.0 / 3.0, xf)
|
||||
val theta = yf * HALF_PI
|
||||
// vertical angle, where 0 is zenith, ±90 is ground (which is odd)
|
||||
|
||||
// println("$yp\t$theta")
|
||||
|
||||
val xyz = CIEXYZ(
|
||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, HALF_PI, 0).toFloat(),
|
||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, HALF_PI, 1).toFloat(),
|
||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, HALF_PI, 2).toFloat()
|
||||
)
|
||||
val xyz2 = xyz.scaleToFit(elevationDeg)
|
||||
val rgb = xyz2.toRGB().toColor()
|
||||
val colour = rgb.toIntBits().toLittle()
|
||||
val xyz = CIEXYZ(
|
||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, (gammaPair * 2f + 1f) * HALF_PI, 0).toFloat(),
|
||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, (gammaPair * 2f + 1f) * HALF_PI, 1).toFloat(),
|
||||
ArHosekSkyModel.arhosek_tristim_skymodel_radiance(state, theta, (gammaPair * 2f + 1f) * HALF_PI, 2).toFloat()
|
||||
)
|
||||
val xyz2 = xyz.scaleToFit(elevationDeg)
|
||||
val rgb = xyz2.toRGB().toColor()
|
||||
val colour = rgb.toIntBits().toLittle()
|
||||
|
||||
val imgOffX = (albedo0 * Skybox.elevCnt + elev0)
|
||||
val imgOffY = texh - 1 - (Skybox.gradSize * turb0 + yp)
|
||||
val fileOffset = TGA_HEADER_SIZE + 4 * (imgOffY * texw + imgOffX)
|
||||
for (i in 0..3) {
|
||||
bytes[fileOffset + i] = colour[bytesLut[i]]
|
||||
val imgOffX = albedo0 * Skybox.elevCnt + elev0 + Skybox.elevCnt * Skybox.albedoCnt * gammaPair
|
||||
val imgOffY = texh - 1 - (Skybox.gradSize * turb0 + yp)
|
||||
val fileOffset = TGA_HEADER_SIZE + 4 * (imgOffY * texw + imgOffX)
|
||||
for (i in 0..3) {
|
||||
bytes[fileOffset + i] = colour[bytesLut[i]]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ import net.torvald.parametricsky.ArHosekSkyModel
|
||||
import net.torvald.terrarum.App
|
||||
import net.torvald.terrarum.App.printdbg
|
||||
import net.torvald.terrarum.abs
|
||||
import net.torvald.terrarum.toInt
|
||||
import net.torvald.terrarumsansbitmap.gdx.TextureRegionPack
|
||||
import kotlin.math.*
|
||||
|
||||
@@ -50,28 +51,24 @@ object Skybox : Disposable {
|
||||
}*/
|
||||
|
||||
// use external LUT
|
||||
operator fun get(elevationDeg: Double, turbidity: Double, albedo: Double): TextureRegion {
|
||||
val elev = elevationDeg.coerceIn(-elevMax, elevMax).roundToInt().plus(elevMax).roundToInt()
|
||||
val turb = turbidity.coerceIn(1.0, 10.0).minus(1.0).times(turbDivisor).roundToInt()
|
||||
val alb = albedo.coerceIn(0.1, 0.9).minus(0.1).times(turbDivisor).roundToInt()
|
||||
//printdbg(this, "elev $elevationDeg->$elev; turb $turbidity->$turb; alb $albedo->$alb")
|
||||
return texRegions.get(alb * elevCnt + elev, turb)
|
||||
operator fun get(elevationDeg: Double, turbidity: Double, albedo: Double, isAfternoon: Boolean): TextureRegion {
|
||||
TODO()
|
||||
}
|
||||
|
||||
fun getUV(elevationDeg: Double, turbidity: Double, albedo: Double): Pair<Texture, FloatArray> {
|
||||
val turb = turbidity.coerceIn(1.0, 10.0).minus(1.0).times(turbDivisor).roundToInt()
|
||||
val alb = albedo.coerceIn(0.1, 0.9).minus(0.1).times(turbDivisor).roundToInt()
|
||||
val region = texStripRegions.get(alb, turb)
|
||||
val alb = albedo.coerceIn(0.0, 1.0).times(turbDivisor).roundToInt()
|
||||
val region1 = texStripRegions.get(alb + albedoCnt * 0, turb) // left half of the sheet
|
||||
val region2 = texStripRegions.get(alb + albedoCnt * 1, turb) // right half of the sheet
|
||||
|
||||
val elev = elevationDeg.coerceIn(-elevMax, elevMax).plus(elevMax).div(elevations.last.toDouble()).div(albedoCnt).times((elevCnt - 1.0) / elevCnt)
|
||||
val elev = elevationDeg.coerceIn(-elevMax, elevMax).plus(elevMax).div(elevations.last.toDouble()).div(albedoCnt * 2).times((elevCnt - 1.0) / elevCnt)
|
||||
|
||||
val u = region.u + (0.5f / tex.width) + elev.toFloat() // because of the nature of bilinear interpolation, half pixels from the edges must be discarded
|
||||
val uA = region1.u + (0.5f / tex.width) + elev.toFloat() // because of the nature of bilinear interpolation, half pixels from the edges must be discarded
|
||||
val uB = region2.u + (0.5f / tex.width) + elev.toFloat() // because of the nature of bilinear interpolation, half pixels from the edges must be discarded
|
||||
|
||||
return tex to floatArrayOf(
|
||||
u,
|
||||
region.v,
|
||||
u,
|
||||
region.v2
|
||||
uA, region1.v, uA, region1.v2,
|
||||
uB, region2.v, uB, region2.v2,
|
||||
)
|
||||
}
|
||||
|
||||
@@ -113,7 +110,7 @@ object Skybox : Disposable {
|
||||
val turbidities = (0..45) // 1, 1.2, 1.4, 1.6, ..., 10.0
|
||||
val turbDivisor = 5.0
|
||||
val turbiditiesD = turbidities.map { 1.0 + it / turbDivisor }
|
||||
val albedos = arrayOf(0.1, 0.3, 0.5, 0.7, 0.9)
|
||||
val albedos = arrayOf(0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0)
|
||||
val elevCnt = elevations.count()
|
||||
val turbCnt = turbidities.count()
|
||||
val albedoCnt = albedos.size
|
||||
|
||||
@@ -208,8 +208,10 @@ internal object WeatherMixer : RNGConsumer {
|
||||
|
||||
// TODO trilinear with (deg, turb, alb)
|
||||
val gradY = -(gH - App.scr.height) * ((parallax + 1f) / 2f)
|
||||
|
||||
val (tex, uvs) = Skybox.getUV(solarElev, thisTurbidity, 0.3)
|
||||
|
||||
val texBlend = (1f/4000f * (timeNow - 43200) + 0.5f).coerceIn(0f, 1f) // 0.0 at T41200; 0.5 at T43200; 1.0 at T45200;
|
||||
|
||||
starmapTex.texture.bind(1)
|
||||
Gdx.gl.glActiveTexture(GL20.GL_TEXTURE0) // so that batch that comes next will bind any tex to it
|
||||
@@ -220,20 +222,20 @@ internal object WeatherMixer : RNGConsumer {
|
||||
batch.inUse {
|
||||
batch.shader = shaderBlendMax
|
||||
shaderBlendMax.setUniformi("tex1", 1)
|
||||
shaderBlendMax.setUniformf("drawOffset", 0f, gradY)
|
||||
shaderBlendMax.setUniformf("drawOffsetSize", App.scr.wf, gH)
|
||||
shaderBlendMax.setUniform2fv("skyboxUV1", uvs, 0, 2)
|
||||
shaderBlendMax.setUniform2fv("skyboxUV2", uvs, 2, 2)
|
||||
shaderBlendMax.setUniformf("drawOffsetSize", 0f, gradY, App.scr.wf, gH)
|
||||
shaderBlendMax.setUniform4fv("skyboxUV1", uvs, 0, 4)
|
||||
shaderBlendMax.setUniform4fv("skyboxUV2", uvs, 4, 4)
|
||||
shaderBlendMax.setUniformf("texBlend", texBlend)
|
||||
shaderBlendMax.setUniformf("astrumScroll", astrumOffX + astrumX, astrumOffY + astrumY)
|
||||
shaderBlendMax.setUniformf("randomNumber",
|
||||
// (world.worldTime.TIME_T.plus(31L) xor 1453L + 31L).and(1023).toFloat(),
|
||||
// (world.worldTime.TIME_T.plus(37L) xor 862L + 31L).and(1023).toFloat(),
|
||||
// (world.worldTime.TIME_T.plus(23L) xor 1639L + 29L).and(1023).toFloat(),
|
||||
// (world.worldTime.TIME_T.plus(29L) xor 2971L + 41L).and(1023).toFloat(),
|
||||
world.worldTime.TIME_T.div(+12.1f).plus(31L),
|
||||
world.worldTime.TIME_T.div(-11.8f).plus(37L),
|
||||
world.worldTime.TIME_T.div(+11.9f).plus(23L),
|
||||
world.worldTime.TIME_T.div(-12.3f).plus(29L),
|
||||
world.worldTime.TIME_T.div(+14.1f).plus(31L),
|
||||
world.worldTime.TIME_T.div(-13.8f).plus(37L),
|
||||
world.worldTime.TIME_T.div(+13.9f).plus(23L),
|
||||
world.worldTime.TIME_T.div(-14.3f).plus(29L),
|
||||
)
|
||||
|
||||
batch.color = Color.WHITE
|
||||
|
||||
@@ -13,10 +13,10 @@ out vec4 fragColor;
|
||||
|
||||
const vec2 boolean = vec2(0.0, 1.0);
|
||||
|
||||
uniform vec2 drawOffset; // value of the 'gradY'
|
||||
uniform vec2 drawOffsetSize; // value of the 'gradH'
|
||||
uniform vec2 skyboxUV1; // (u, v) for the skybox drawing
|
||||
uniform vec2 skyboxUV2; // (u2, v2) for the skybox drawing
|
||||
uniform vec4 drawOffsetSize; // (gradX, gradY, gradW, gradH)
|
||||
uniform vec4 skyboxUV1; // (u, v, u2, v2) for the skybox drawing (morning)
|
||||
uniform vec4 skyboxUV2; // (u, v, u2, v2) for the skybox drawing (afternoon)
|
||||
uniform float texBlend;
|
||||
uniform vec2 tex1Size = vec2(4096.0);
|
||||
uniform vec2 astrumScroll = vec2(0.0);
|
||||
uniform vec4 randomNumber = vec4(1.0, -2.0, 3.0, -4.0);
|
||||
@@ -112,13 +112,17 @@ vec4 random(vec2 p) {
|
||||
|
||||
// draw call to this function must use UV coord of (0,0,1,1)!
|
||||
void main(void) {
|
||||
vec2 skyboxTexCoord = mix(skyboxUV1, skyboxUV2, v_texCoords);
|
||||
vec2 astrumTexCoord = (v_texCoords * drawOffsetSize + drawOffset + astrumScroll) / tex1Size;
|
||||
vec2 skyboxTexCoordMorning = mix(skyboxUV1.xy, skyboxUV1.zw, v_texCoords);
|
||||
vec2 skyboxTexCoordAfternoon = mix(skyboxUV2.xy, skyboxUV2.zw, v_texCoords);
|
||||
|
||||
vec2 astrumTexCoord = (v_texCoords * drawOffsetSize.zw + drawOffsetSize.xy + astrumScroll) / tex1Size;
|
||||
|
||||
vec4 randomness = snoise4((gl_FragCoord.xy - astrumScroll) * 0.16) * 2.0; // multiply by 2 so that the "density" of the stars would be same as the non-random version
|
||||
|
||||
|
||||
vec4 colorTex0 = texture(u_texture, skyboxTexCoord);
|
||||
vec4 colorTex0Morining = texture(u_texture, skyboxTexCoordMorning);
|
||||
vec4 colorTex0Afternoon = texture(u_texture, skyboxTexCoordAfternoon);
|
||||
vec4 colorTex0 = mix(colorTex0Morining, colorTex0Afternoon, texBlend);
|
||||
vec4 colorTex1 = texture(tex1, astrumTexCoord) * randomness;
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user