far improved lightmap updater

This commit is contained in:
Bixilon 2022-11-10 19:51:51 +01:00
parent 33d9804581
commit 2085878cf3
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
3 changed files with 159 additions and 3 deletions

View File

@ -245,7 +245,7 @@ class SkyboxRenderer(
return RGBColor(red / count, green / count, blue / count)
}
private fun calculateLightingStrike(original: Vec3): Vec3 {
fun calculateLightingStrike(original: Vec3): Vec3 {
val duration = this.strikeDuration
val delta = millis() - lastStrike
if (delta > duration) {

View File

@ -35,8 +35,8 @@ class Lightmap(private val light: RenderLight) {
private lateinit var defaultUpdater: LightmapUpdater
fun init() {
// defaultUpdater = NormalLightmapUpdater(light.renderWindow.connection, light.renderWindow.renderer[SkyRenderer])
defaultUpdater = LegacyLightmapUpdater(light.renderWindow.connection)
defaultUpdater = NormalLightmapUpdater(light.renderWindow.connection, light.renderWindow.renderer[SkyRenderer])
// defaultUpdater = LegacyLightmapUpdater(light.renderWindow.connection)
buffer.init()
profile.light::fullbright.profileWatch(this, profile = profile) { setLightmapUpdater() }
setLightmapUpdater()

View File

@ -0,0 +1,156 @@
/*
* Minosoft
* Copyright (C) 2020-2022 Moritz Zwerger
*
* This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with this program. If not, see <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
package de.bixilon.minosoft.gui.rendering.world.light.updater.normal
import de.bixilon.kotlinglm.vec3.Vec3
import de.bixilon.kutil.watcher.DataWatcher.Companion.observe
import de.bixilon.minosoft.data.registries.dimension.DimensionProperties
import de.bixilon.minosoft.data.world.time.DayPhases
import de.bixilon.minosoft.data.world.time.WorldTime
import de.bixilon.minosoft.data.world.weather.WorldWeather
import de.bixilon.minosoft.gui.rendering.sky.SkyRenderer
import de.bixilon.minosoft.gui.rendering.util.VecUtil.clamp
import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3Util.interpolateLinear
import de.bixilon.minosoft.gui.rendering.world.light.LightmapBuffer
import de.bixilon.minosoft.gui.rendering.world.light.updater.LightmapUpdater
import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection
import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition
import kotlin.math.abs
class NormalLightmapUpdater(
private val connection: PlayConnection,
private val skyRenderer: SkyRenderer?,
) : LightmapUpdater {
private val profile = connection.profiles.rendering.light
private var force = true
init {
connection.world::dimension.observe(this) { force = true }
}
override fun update(force: Boolean, buffer: LightmapBuffer) {
val dimension = connection.world.dimension ?: return
val skylight = dimension.hasSkyLight && dimension.effects.daylightCycle
if (!force || !this.force) {
if (!skylight) {
// do not recalculate if skylight does not change (e.g. nether or end)
return
}
}
if (skylight) {
updateBlockSky(dimension, buffer)
} else {
updateBlock(dimension, buffer)
}
this.force = false
}
private fun updateBlock(dimension: DimensionProperties, buffer: LightmapBuffer) {
for (block in 0 until ProtocolDefinition.LIGHT_LEVELS) {
buffer[0, block] = calculateBlock(dimension.brightness[block])
}
}
private fun updateBlockSky(dimension: DimensionProperties, buffer: LightmapBuffer) {
val time = connection.world.time
val weather = connection.world.weather
val skyColors = Array(ProtocolDefinition.LIGHT_LEVELS.toInt()) { calculateSky(dimension.brightness[it], weather, time) }
val blockColors = Array(ProtocolDefinition.LIGHT_LEVELS.toInt()) { calculateBlock(dimension.brightness[it]) }
for (sky in 0 until ProtocolDefinition.LIGHT_LEVELS) {
for (block in 0 until ProtocolDefinition.LIGHT_LEVELS) {
buffer[sky, block] = combine(skyColors[sky], blockColors[block])
}
}
}
private fun calculateBlock(brightness: Float): Vec3 {
val base = Vec3(brightness, brightness * ((brightness * 0.6f + 0.4f) * 0.6f + 0.4f), brightness * (brightness * brightness * 0.6f + 0.4f))
return base
}
private fun calculateDayBase(brightness: Float, progress: Float): Vec3 {
val base = Vec3(0.98f)
return interpolateLinear((abs(progress - 0.5f) * 2.0f), base, base * 0.9f) * brightness
}
private fun calculateSunset(brightness: Float, progress: Float, time: WorldTime): Vec3 {
val day = calculateDayBase(brightness, 1.0f)
val night = calculateNightBase(brightness, 0.0f, time)
return interpolateLinear(progress, day, night)
}
private fun calculateNightBase(brightness: Float, progress: Float, time: WorldTime): Vec3 {
val max = Vec3(0.10f, 0.10f, 0.30f)
return interpolateLinear((abs(progress - 0.6f) + 0.4f), max * 0.1f, max) * brightness * time.moonPhase.light
}
private fun calculateSunrise(brightness: Float, progress: Float, time: WorldTime): Vec3 {
val night = calculateNightBase(brightness, 1.0f, time)
val day = calculateDayBase(brightness, 0.0f)
return interpolateLinear(progress, night, day)
}
private fun calculateThunder(base: Vec3, brightness: Float, thunder: Float): Vec3 {
val baseBrightness = base.length()
var color = interpolateLinear(baseBrightness, Vec3(0.55f, 0.35f, 0.58f), Vec3(0.65f, 0.4f, 0.7f)) * baseBrightness * brightness * 0.3f
skyRenderer?.let { color = interpolateLinear(brightness * 5.0f + 0.5f, color, it.box.calculateLightingStrike(color)) }
return interpolateLinear(thunder, base, color)
}
private fun calculateRain(base: Vec3, brightness: Float, rain: Float): Vec3 {
val baseBrightness = base.length()
val color = interpolateLinear(baseBrightness, Vec3(0.4f, 0.4f, 0.8f), Vec3(0.5f, 0.5f, 0.9f)) * baseBrightness * brightness * 0.4f
return interpolateLinear(rain, base, color)
}
private fun calculateSky(brightness: Float, weather: WorldWeather, time: WorldTime): Vec3 {
var color = when (time.phase) {
DayPhases.DAY -> calculateDayBase(brightness, time.progress)
DayPhases.NIGHT -> calculateNightBase(brightness, time.progress, time)
DayPhases.SUNRISE -> calculateSunrise(brightness, time.progress, time)
DayPhases.SUNSET -> calculateSunset(brightness, time.progress, time)
}
if (weather.thunder > 0.0f) {
color = calculateThunder(color, brightness, weather.thunder)
} else if (weather.rain > 0.0f) {
color = calculateRain(color, brightness, weather.rain)
}
return color.brighten(0.05f)
}
private fun combine(sky: Vec3, block: Vec3): Vec3 {
var color = sky + block
color = color.clamp(0.0f, 1.0f)
return color
}
private fun Vec3.brighten(value: Float): Vec3 {
return this * (1.0f - value) + value
}
}