diff --git a/assets/clut/skybox.png b/assets/clut/skybox.png index 8e0d6fce9..32ec50324 100644 --- a/assets/clut/skybox.png +++ b/assets/clut/skybox.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:8e2222c513b927754c4ea04554677c4649c51e255763096026547a4c00d4fadf -size 488682 +oid sha256:4c2b1edd3d64d619d97b29caef0fef718aa75a29f65ff5ad90624cab62088135 +size 2094774 diff --git a/assets/mods/basegame/locales/en/calendar.json b/assets/mods/basegame/locales/en/calendar.json new file mode 100644 index 000000000..15a254cfe --- /dev/null +++ b/assets/mods/basegame/locales/en/calendar.json @@ -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" +} \ No newline at end of file diff --git a/assets/mods/basegame/locales/koKR/calendar.json b/assets/mods/basegame/locales/koKR/calendar.json new file mode 100644 index 000000000..a0694d855 --- /dev/null +++ b/assets/mods/basegame/locales/koKR/calendar.json @@ -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": "겨울" +} \ No newline at end of file diff --git a/src/net/torvald/terrarum/clut/GenerateSkyboxTextureAtlas.kt b/src/net/torvald/terrarum/clut/GenerateSkyboxTextureAtlas.kt index 51d97cc6a..1b1f10ecb 100644 --- a/src/net/torvald/terrarum/clut/GenerateSkyboxTextureAtlas.kt +++ b/src/net/torvald/terrarum/clut/GenerateSkyboxTextureAtlas.kt @@ -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]] + } } } } diff --git a/src/net/torvald/terrarum/clut/Skybox.kt b/src/net/torvald/terrarum/clut/Skybox.kt index c39f2c478..7cb721279 100644 --- a/src/net/torvald/terrarum/clut/Skybox.kt +++ b/src/net/torvald/terrarum/clut/Skybox.kt @@ -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 { 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 diff --git a/src/net/torvald/terrarum/weather/WeatherMixer.kt b/src/net/torvald/terrarum/weather/WeatherMixer.kt index 5c54a67d6..86e5d679c 100644 --- a/src/net/torvald/terrarum/weather/WeatherMixer.kt +++ b/src/net/torvald/terrarum/weather/WeatherMixer.kt @@ -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 diff --git a/src/shaders/blendSkyboxStars.frag b/src/shaders/blendSkyboxStars.frag index bc67f4d80..a4aae766b 100644 --- a/src/shaders/blendSkyboxStars.frag +++ b/src/shaders/blendSkyboxStars.frag @@ -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;