From d21f1d0e467896c818bd1b645ee759fbb92ff26c Mon Sep 17 00:00:00 2001 From: Moritz Zwerger Date: Thu, 29 Feb 2024 21:18:29 +0100 Subject: [PATCH] fog flags, improve and refactor fog FogFlags are way cleaner and allow further extension of the fog system (e.g. custom behavior for versions, change shape of shader, ...) This fixe the invisible block glitch when being e.g. in a debugger/profiler while joining (the fog settings were messed up because the interpolation sucked) --- .../registries/effects/vision/VisionEffect.kt | 5 +- .../data/registries/fluid/fluids/LavaFluid.kt | 13 +- .../registries/fluid/fluids/WaterFluid.kt | 12 +- .../minosoft/gui/rendering/camera/Camera.kt | 3 +- .../gui/rendering/camera/FogManager.kt | 176 ------------------ .../gui/rendering/camera/fog/FogFlags.kt | 32 ++++ .../camera/fog/FogInterpolationStart.kt | 23 +++ .../gui/rendering/camera/fog/FogManager.kt | 152 +++++++++++++++ .../gui/rendering/camera/fog/FogOptions.kt | 22 +++ .../gui/rendering/camera/fog/FogState.kt | 38 ++++ .../gui/rendering/camera/fog/FoggedFluid.kt | 22 +++ .../chunk/border/WorldBorderShader.kt | 4 +- .../gui/rendering/chunk/shader/ChunkShader.kt | 4 +- .../entities/feature/block/BlockShader.kt | 4 +- .../feature/text/BillboardTextShader.kt | 4 +- .../gui/rendering/shader/types/FogShader.kt | 4 +- .../skeletal/shader/BaseSkeletalShader.kt | 4 +- .../gui/rendering/sky/clouds/CloudShader.kt | 4 +- .../rendering/shader/includes/animation.glsl | 2 +- .../rendering/shader/includes/fog.glsl | 74 +++++--- .../rendering/shader/sky/clouds/clouds.fsh | 2 +- 21 files changed, 374 insertions(+), 230 deletions(-) delete mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/camera/FogManager.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogFlags.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogInterpolationStart.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogManager.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogOptions.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogState.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FoggedFluid.kt diff --git a/src/main/java/de/bixilon/minosoft/data/registries/effects/vision/VisionEffect.kt b/src/main/java/de/bixilon/minosoft/data/registries/effects/vision/VisionEffect.kt index 239cb2d82..2ec63c6e1 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/effects/vision/VisionEffect.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/effects/vision/VisionEffect.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 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. * @@ -18,8 +18,10 @@ import de.bixilon.minosoft.data.registries.effects.properties.categories.Benefic import de.bixilon.minosoft.data.registries.effects.properties.categories.HarmfulEffect import de.bixilon.minosoft.data.registries.identified.Identified import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft +import de.bixilon.minosoft.data.text.formatting.color.ChatColors import de.bixilon.minosoft.data.text.formatting.color.Colored import de.bixilon.minosoft.data.text.formatting.color.RGBColor.Companion.asRGBColor +import de.bixilon.minosoft.gui.rendering.camera.fog.FogOptions interface VisionEffect { @@ -32,6 +34,7 @@ interface VisionEffect { object Blindness : StatusEffectType(), VisionEffect, Identified, Colored, HarmfulEffect { override val identifier = minecraft("blindness") override val color = 0x1F1F23.asRGBColor() + val FOG_OPTIONS = FogOptions(start = 3.0f, end = 5.0f, color = ChatColors.BLACK) } object NightVision : StatusEffectType(), VisionEffect, Identified, Colored, BeneficalEffect { diff --git a/src/main/java/de/bixilon/minosoft/data/registries/fluid/fluids/LavaFluid.kt b/src/main/java/de/bixilon/minosoft/data/registries/fluid/fluids/LavaFluid.kt index 89dacd96f..9662528c3 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/fluid/fluids/LavaFluid.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/fluid/fluids/LavaFluid.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 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. * @@ -27,11 +27,16 @@ import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft import de.bixilon.minosoft.data.registries.identified.ResourceLocation import de.bixilon.minosoft.data.registries.particle.ParticleType import de.bixilon.minosoft.data.registries.registries.Registries +import de.bixilon.minosoft.data.text.formatting.color.RGBColor +import de.bixilon.minosoft.data.world.World +import de.bixilon.minosoft.gui.rendering.camera.fog.FogOptions +import de.bixilon.minosoft.gui.rendering.camera.fog.FoggedFluid import de.bixilon.minosoft.gui.rendering.models.fluid.fluids.LavaFluidModel import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.lava.LavaParticle import de.bixilon.minosoft.gui.rendering.util.VecUtil.horizontal import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3d +import de.bixilon.minosoft.physics.EntityPositionInfo import de.bixilon.minosoft.physics.entities.EntityPhysics import de.bixilon.minosoft.physics.entities.living.LivingEntityPhysics import de.bixilon.minosoft.physics.input.MovementInput @@ -39,7 +44,7 @@ import de.bixilon.minosoft.physics.parts.input.InputPhysics.applyMovementInput import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import java.util.* -open class LavaFluid(identifier: ResourceLocation = Companion.identifier) : Fluid(identifier), FluidCollisionHandler { +open class LavaFluid(identifier: ResourceLocation = Companion.identifier) : Fluid(identifier), FluidCollisionHandler, FoggedFluid { private val lavaParticleType: ParticleType = unsafeNull() override val priority: Int get() = 1 @@ -75,7 +80,6 @@ open class LavaFluid(identifier: ResourceLocation = Companion.identifier) : Flui return other is LavaFluid } - override fun randomTick(connection: PlayConnection, blockState: BlockState, blockPosition: Vec3i, random: Random) { super.randomTick(connection, blockState, blockPosition, random) val particle = connection.world.particle ?: return @@ -103,9 +107,12 @@ open class LavaFluid(identifier: ResourceLocation = Companion.identifier) : Flui return LavaFluidModel() } + override fun getFogOptions(world: World, position: EntityPositionInfo) = FOG_OPTIONS + companion object : FluidFactory, AliasedIdentified { override val identifier = minecraft("lava") override val identifiers = setOf(minecraft("flowing_lava")) + private val FOG_OPTIONS = FogOptions(start = 0.2f, end = 1.0f, color = RGBColor(0.6f, 0.1f, 0.0f)) const val FRICTION = 0.5 override fun build(resourceLocation: ResourceLocation, registries: Registries) = LavaFluid() diff --git a/src/main/java/de/bixilon/minosoft/data/registries/fluid/fluids/WaterFluid.kt b/src/main/java/de/bixilon/minosoft/data/registries/fluid/fluids/WaterFluid.kt index 41d07fbf5..8604bfc00 100644 --- a/src/main/java/de/bixilon/minosoft/data/registries/fluid/fluids/WaterFluid.kt +++ b/src/main/java/de/bixilon/minosoft/data/registries/fluid/fluids/WaterFluid.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 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. * @@ -32,12 +32,16 @@ import de.bixilon.minosoft.data.registries.identified.AliasedIdentified import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft import de.bixilon.minosoft.data.registries.identified.ResourceLocation import de.bixilon.minosoft.data.registries.registries.Registries +import de.bixilon.minosoft.data.world.World +import de.bixilon.minosoft.gui.rendering.camera.fog.FogOptions +import de.bixilon.minosoft.gui.rendering.camera.fog.FoggedFluid import de.bixilon.minosoft.gui.rendering.models.fluid.fluids.WaterFluidModel import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.water.UnderwaterParticle import de.bixilon.minosoft.gui.rendering.tint.TintedBlock import de.bixilon.minosoft.gui.rendering.tint.tints.fluid.WaterTintProvider import de.bixilon.minosoft.gui.rendering.util.VecUtil.plus import de.bixilon.minosoft.gui.rendering.util.VecUtil.toVec3d +import de.bixilon.minosoft.physics.EntityPositionInfo import de.bixilon.minosoft.physics.entities.EntityPhysics import de.bixilon.minosoft.physics.entities.living.LivingEntityPhysics import de.bixilon.minosoft.physics.input.MovementInput @@ -47,7 +51,7 @@ import de.bixilon.minosoft.physics.parts.input.InputPhysics.applyMovementInput import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection import java.util.* -class WaterFluid(resourceLocation: ResourceLocation = identifier) : Fluid(resourceLocation), FluidEnterHandler, FluidCollisionHandler, TintedBlock { +class WaterFluid(resourceLocation: ResourceLocation = identifier) : Fluid(resourceLocation), FluidEnterHandler, FluidCollisionHandler, TintedBlock, FoggedFluid { override val priority: Int get() = 0 override val tintProvider get() = WaterTintProvider @@ -136,6 +140,10 @@ class WaterFluid(resourceLocation: ResourceLocation = identifier) : Fluid(resour onCollision(physics, height) } + override fun getFogOptions(world: World, position: EntityPositionInfo): FogOptions { + return FogOptions(start = 5.0f, end = 10.0f, color = position.biome?.waterFogColor) + } + companion object : FluidFactory, AliasedIdentified { override val identifier = minecraft("water") override val identifiers = setOf(minecraft("flowing_water")) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/Camera.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/Camera.kt index 311ec247c..eb70f78a2 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/Camera.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/Camera.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 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. * @@ -19,6 +19,7 @@ import de.bixilon.kutil.time.TimeUtil.millis import de.bixilon.minosoft.data.entities.entities.player.local.LocalPlayerEntity import de.bixilon.minosoft.gui.rendering.RenderContext import de.bixilon.minosoft.gui.rendering.RenderUtil.runAsync +import de.bixilon.minosoft.gui.rendering.camera.fog.FogManager import de.bixilon.minosoft.gui.rendering.camera.view.ViewManager import de.bixilon.minosoft.gui.rendering.camera.visibility.WorldVisibilityGraph diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/FogManager.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/FogManager.kt deleted file mode 100644 index d82b54673..000000000 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/FogManager.kt +++ /dev/null @@ -1,176 +0,0 @@ -/* - * Minosoft - * Copyright (C) 2020-2023 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 . - * - * This software is not affiliated with Mojang AB, the original developer of Minecraft. - */ - -package de.bixilon.minosoft.gui.rendering.camera - -import de.bixilon.kutil.math.interpolation.FloatInterpolation.interpolateLinear -import de.bixilon.kutil.time.TimeUtil.millis -import de.bixilon.minosoft.data.registries.effects.vision.VisionEffect -import de.bixilon.minosoft.data.registries.fluid.fluids.LavaFluid -import de.bixilon.minosoft.data.registries.fluid.fluids.WaterFluid -import de.bixilon.minosoft.data.text.formatting.color.ChatColors -import de.bixilon.minosoft.data.text.formatting.color.ColorInterpolation.interpolateSine -import de.bixilon.minosoft.data.text.formatting.color.Colors -import de.bixilon.minosoft.data.text.formatting.color.RGBColor -import de.bixilon.minosoft.gui.rendering.RenderContext -import de.bixilon.minosoft.gui.rendering.shader.types.FogShader -import de.bixilon.minosoft.gui.rendering.system.base.shader.NativeShader -import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition - -class FogManager( - private val context: RenderContext, -) { - private val player = context.connection.player - - private var fogChange = -1L - - private var _fogStart = 0.0f - private var _fogEnd = 0.0f - private var _fogColor: RGBColor? = null - - private var fogStart = 0.0f - private var fogEnd = 0.0f - private var fogColor: RGBColor? = null - - - var interpolatedFogStart = 0.0f - private set - var interpolatedFogEnd = 0.0f - private set - var interpolatedFogColor: RGBColor? = null - private set - var interpolatedRevision = 0L - private set - - - private var shaderRevision = -1L - - fun draw() { - if (!calculateFog()) { - updateValues() - } - updateShaders() - } - - private fun calculateFog(): Boolean { - val sky = context.connection.world.dimension.effects - var fogStart = if (!context.connection.profiles.rendering.fog.enabled || !sky.fog) { - Float.MAX_VALUE - } else { - (context.connection.world.view.viewDistance - 2.0f) * ProtocolDefinition.SECTION_WIDTH_X // could be improved? basically view distance in blocks and then the center of that chunk - } - var fogEnd = fogStart + 15.0f - var color: RGBColor? = null - - val submergedFluid = player.physics.submersion.eye - - if (submergedFluid is LavaFluid) { - color = LAVA_FOG_COLOR - fogStart = 0.2f - fogEnd = 1.0f - } else if (submergedFluid is WaterFluid) { - color = player.physics.positionInfo.biome?.waterFogColor - fogStart = 5.0f - fogEnd = 10.0f - } else if (player.effects[VisionEffect.Blindness] != null) { - color = ChatColors.BLACK - fogStart = 3.0f - fogEnd = 5.0f - } - - if (fogStart == this.fogStart && fogEnd == this.fogEnd && color == this.fogColor) { - return false - } - - saveFog() - this.fogStart = fogStart - this.fogEnd = fogEnd - this.fogColor = color - return true - } - - private fun saveFog() { - val time = millis() - updateValues(time) - fogChange = time - _fogStart = interpolatedFogStart - _fogEnd = interpolatedFogEnd - _fogColor = interpolatedFogColor - } - - private fun updateValues(time: Long = millis()) { - val delta = time - fogChange - if (delta > FOG_INTERPOLATION_TIME) { - // already up to date - return - } - val progress = delta / FOG_INTERPOLATION_TIME.toFloat() - this.interpolatedFogStart = interpolateLinear(progress, _fogStart, fogStart) - this.interpolatedFogEnd = interpolateLinear(progress, _fogEnd, fogEnd) - var color: RGBColor? = interpolateSine(progress, _fogColor ?: Colors.TRANSPARENT, fogColor ?: Colors.TRANSPARENT) - if (color == Colors.TRANSPARENT) { - color = null - } - this.interpolatedFogColor = color - - this.interpolatedRevision++ - } - - - private fun updateShaders() { - val revision = interpolatedRevision - - if (revision == this.shaderRevision) { - return - } - - val start = interpolatedFogStart * interpolatedFogStart - val end = interpolatedFogEnd * interpolatedFogEnd - val color = interpolatedFogColor - val distance = end - start - - for (shader in context.system.shaders) { - if (shader !is FogShader || shader.fog != this) { - continue - } - use(shader.native, start, end, color, distance) - } - this.shaderRevision = revision - } - - fun use(shader: NativeShader) { - use(shader, interpolatedFogStart * interpolatedFogStart, interpolatedFogEnd * interpolatedFogEnd, interpolatedFogColor) - } - - fun use(shader: NativeShader, start: Float, end: Float, color: RGBColor?, distance: Float = end - start) { - shader.use() - - shader["uFogStart"] = start - shader["uFogEnd"] = end - shader["uFogDistance"] = distance - if (color == null) { - shader[USE_FOG_COLOR] = false - } else { - shader[FOG_COLOR] = color - shader[USE_FOG_COLOR] = true - } - } - - companion object { - private val LAVA_FOG_COLOR = RGBColor(0.6f, 0.1f, 0.0f) - private const val FOG_INTERPOLATION_TIME = 300 - - private const val FOG_COLOR = "uFogColor" - private const val USE_FOG_COLOR = "uUseFogColor" - } -} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogFlags.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogFlags.kt new file mode 100644 index 000000000..1325aca50 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogFlags.kt @@ -0,0 +1,32 @@ +/* + * Minosoft + * Copyright (C) 2020-2024 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.camera.fog + +import de.bixilon.kutil.enums.ValuesEnum +import de.bixilon.kutil.enums.ValuesEnum.Companion.names + +enum class FogFlags { + ENABLE, + USE_COLOR, + ; + + + val mask = 0x01 shl ordinal + + + companion object : ValuesEnum { + override val VALUES = values() + override val NAME_MAP = names() + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogInterpolationStart.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogInterpolationStart.kt new file mode 100644 index 000000000..0fa75bcd9 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogInterpolationStart.kt @@ -0,0 +1,23 @@ +/* + * Minosoft + * Copyright (C) 2020-2024 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.camera.fog + +import de.bixilon.minosoft.data.text.formatting.color.RGBColor + +class FogInterpolationStart { + var start: Float = 0.0f + var end: Float = 0.0f + var color: RGBColor? = null + var change = -1L +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogManager.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogManager.kt new file mode 100644 index 000000000..281bcdef6 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogManager.kt @@ -0,0 +1,152 @@ +/* + * Minosoft + * Copyright (C) 2020-2024 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.camera.fog + +import de.bixilon.kutil.math.interpolation.FloatInterpolation.interpolateLinear +import de.bixilon.kutil.time.TimeUtil.millis +import de.bixilon.minosoft.data.registries.effects.vision.VisionEffect +import de.bixilon.minosoft.data.text.formatting.color.ColorInterpolation.interpolateSine +import de.bixilon.minosoft.data.text.formatting.color.Colors +import de.bixilon.minosoft.data.text.formatting.color.RGBColor +import de.bixilon.minosoft.gui.rendering.RenderContext +import de.bixilon.minosoft.gui.rendering.shader.types.FogShader +import de.bixilon.minosoft.gui.rendering.system.base.shader.NativeShader +import de.bixilon.minosoft.protocol.protocol.ProtocolDefinition + +class FogManager( + private val context: RenderContext, +) { + private val player = context.connection.player + + private var interpolation = FogInterpolationStart() + private val state = FogState() + private var options = FogOptions() + + + private var shaderRevision = -1 + + fun draw() { + update() + if (interpolation.change >= 0L) { + interpolate() + } + updateShaders() + } + + private fun getOptions(): FogOptions { + val fluid = player.physics.submersion.eye + + return when { + fluid is FoggedFluid -> fluid.getFogOptions(context.connection.world, player.physics.positionInfo) + player.effects[VisionEffect.Blindness] != null -> VisionEffect.Blindness.FOG_OPTIONS + else -> { + val fogStart = (context.connection.world.view.viewDistance - 2.0f) * ProtocolDefinition.SECTION_WIDTH_X // could be improved? basically view distance in blocks and then the center of that chunk + FogOptions(fogStart, fogStart + 15.0f, null) + } + } + } + + private fun update() { + val sky = context.connection.world.dimension.effects + val enabled = sky.fog && context.connection.profiles.rendering.fog.enabled + if (state.enabled != enabled) { + state.revision++ + } + if (!state.enabled) return + + val options = getOptions() + if (this.options == options) { + return + } + + save() + this.options = options + state.revision++ + } + + private fun save() { + val time = millis() + interpolate(time) + interpolation.change = time + interpolation.start = state.start + interpolation.end = state.end + interpolation.color = state.color + } + + private fun interpolate(time: Long = millis()) { + val delta = time - interpolation.change + val progress = delta / INTERPOLATE_DURATION.toFloat() + state.start = interpolateLinear(progress, interpolation.start, options.start) + state.end = interpolateLinear(progress, interpolation.end, options.end) + var color: RGBColor? = interpolateSine(progress, interpolation.color ?: Colors.TRANSPARENT, options.color ?: Colors.TRANSPARENT) + if (color == Colors.TRANSPARENT) { + color = null + } + state.color = color + if (progress >= 1.0f) { + interpolation.change = 1L // this avoid further interpolations with the same data + } + + state.revision++ + } + + + private fun updateShaders() { + val revision = state.revision + + if (revision == this.shaderRevision) { + return + } + + val start = state.start * state.start + val end = state.end * state.end + val distance = end - start + val color = state.color + val flags = state.flags() + + for (shader in context.system.shaders) { + if (shader !is FogShader || shader.fog != this) { + continue + } + shader.native.update(start, end, distance, color, flags) + } + this.shaderRevision = revision + } + + fun use(shader: NativeShader) { + val start = state.start * state.start + val end = state.end * state.end + val distance = end - start + val color = state.color + val flags = state.flags() + + shader.update(start, end, distance, color, flags) + } + + private fun NativeShader.update(start: Float, end: Float, distance: Float, color: RGBColor?, flags: Int) { + use() + + this["uFogStart"] = start + this["uFogEnd"] = end + this["uFogDistance"] = distance + + color?.let { this["uFogColor"] = it } + this.setUInt("uFogFlags", flags) + } + + + companion object { + private const val INTERPOLATE_DURATION = 300 + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogOptions.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogOptions.kt new file mode 100644 index 000000000..9d7b8a896 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogOptions.kt @@ -0,0 +1,22 @@ +/* + * Minosoft + * Copyright (C) 2020-2024 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.camera.fog + +import de.bixilon.minosoft.data.text.formatting.color.RGBColor + +data class FogOptions( + val start: Float = 0.0f, + val end: Float = 0.0f, + val color: RGBColor? = null, +) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogState.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogState.kt new file mode 100644 index 000000000..c765a339e --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FogState.kt @@ -0,0 +1,38 @@ +/* + * Minosoft + * Copyright (C) 2020-2024 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.camera.fog + +import de.bixilon.minosoft.data.text.formatting.color.RGBColor + +data class FogState( + var enabled: Boolean = true, + var start: Float = 0.0f, + var end: Float = 0.0f, + var color: RGBColor? = null, +) { + var revision = -1 + + + fun flags(): Int { + var flags = 0 + if (enabled) { + flags = flags or FogFlags.ENABLE.mask + } + if (color != null) { + flags = flags or FogFlags.USE_COLOR.mask + } + + return flags + } +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FoggedFluid.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FoggedFluid.kt new file mode 100644 index 000000000..6efcf8ced --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/camera/fog/FoggedFluid.kt @@ -0,0 +1,22 @@ +/* + * Minosoft + * Copyright (C) 2020-2024 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 . + * + * This software is not affiliated with Mojang AB, the original developer of Minecraft. + */ + +package de.bixilon.minosoft.gui.rendering.camera.fog + +import de.bixilon.minosoft.data.world.World +import de.bixilon.minosoft.physics.EntityPositionInfo + +interface FoggedFluid { + + fun getFogOptions(world: World, position: EntityPositionInfo): FogOptions +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/border/WorldBorderShader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/border/WorldBorderShader.kt index 921cb912e..2a8a02512 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/border/WorldBorderShader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/border/WorldBorderShader.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 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. * @@ -16,7 +16,7 @@ package de.bixilon.minosoft.gui.rendering.chunk.border import de.bixilon.kotlinglm.mat4x4.Mat4 import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.minosoft.data.text.formatting.color.ChatColors -import de.bixilon.minosoft.gui.rendering.camera.FogManager +import de.bixilon.minosoft.gui.rendering.camera.fog.FogManager import de.bixilon.minosoft.gui.rendering.shader.Shader import de.bixilon.minosoft.gui.rendering.shader.types.* import de.bixilon.minosoft.gui.rendering.system.base.shader.NativeShader diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/shader/ChunkShader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/shader/ChunkShader.kt index 8545870b3..1934ed112 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/shader/ChunkShader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/chunk/shader/ChunkShader.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 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. * @@ -15,7 +15,7 @@ package de.bixilon.minosoft.gui.rendering.chunk.shader import de.bixilon.kotlinglm.mat4x4.Mat4 import de.bixilon.kotlinglm.vec3.Vec3 -import de.bixilon.minosoft.gui.rendering.camera.FogManager +import de.bixilon.minosoft.gui.rendering.camera.fog.FogManager import de.bixilon.minosoft.gui.rendering.light.LightmapBuffer import de.bixilon.minosoft.gui.rendering.shader.Shader import de.bixilon.minosoft.gui.rendering.shader.types.* diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/feature/block/BlockShader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/feature/block/BlockShader.kt index a2324347b..9a1cd9b67 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/feature/block/BlockShader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/feature/block/BlockShader.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 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. * @@ -16,7 +16,7 @@ package de.bixilon.minosoft.gui.rendering.entities.feature.block import de.bixilon.kotlinglm.mat4x4.Mat4 import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.minosoft.data.text.formatting.color.ChatColors -import de.bixilon.minosoft.gui.rendering.camera.FogManager +import de.bixilon.minosoft.gui.rendering.camera.fog.FogManager import de.bixilon.minosoft.gui.rendering.shader.Shader import de.bixilon.minosoft.gui.rendering.shader.types.FogShader import de.bixilon.minosoft.gui.rendering.shader.types.TextureShader diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/feature/text/BillboardTextShader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/feature/text/BillboardTextShader.kt index 33a3a5416..175a5ef8f 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/feature/text/BillboardTextShader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/feature/text/BillboardTextShader.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 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. * @@ -16,7 +16,7 @@ package de.bixilon.minosoft.gui.rendering.entities.feature.text import de.bixilon.kotlinglm.mat4x4.Mat4 import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.minosoft.data.text.formatting.color.ChatColors -import de.bixilon.minosoft.gui.rendering.camera.FogManager +import de.bixilon.minosoft.gui.rendering.camera.fog.FogManager import de.bixilon.minosoft.gui.rendering.shader.Shader import de.bixilon.minosoft.gui.rendering.shader.types.FogShader import de.bixilon.minosoft.gui.rendering.shader.types.TextureShader diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/shader/types/FogShader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/shader/types/FogShader.kt index 37c6a7974..be9b61e7c 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/shader/types/FogShader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/shader/types/FogShader.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2022 Moritz Zwerger + * Copyright (C) 2020-2024 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. * @@ -13,7 +13,7 @@ package de.bixilon.minosoft.gui.rendering.shader.types -import de.bixilon.minosoft.gui.rendering.camera.FogManager +import de.bixilon.minosoft.gui.rendering.camera.fog.FogManager import de.bixilon.minosoft.gui.rendering.shader.AbstractShader import de.bixilon.minosoft.gui.rendering.shader.uniform.ShaderUniform diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/shader/BaseSkeletalShader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/shader/BaseSkeletalShader.kt index 21f598015..e65708fbc 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/shader/BaseSkeletalShader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/shader/BaseSkeletalShader.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 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. * @@ -15,7 +15,7 @@ package de.bixilon.minosoft.gui.rendering.skeletal.shader import de.bixilon.kotlinglm.mat4x4.Mat4 import de.bixilon.kotlinglm.vec3.Vec3 -import de.bixilon.minosoft.gui.rendering.camera.FogManager +import de.bixilon.minosoft.gui.rendering.camera.fog.FogManager import de.bixilon.minosoft.gui.rendering.shader.Shader import de.bixilon.minosoft.gui.rendering.shader.types.FogShader import de.bixilon.minosoft.gui.rendering.shader.types.TextureShader diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudShader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudShader.kt index 0d831ccf2..f9d3c46a1 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudShader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/sky/clouds/CloudShader.kt @@ -1,6 +1,6 @@ /* * Minosoft - * Copyright (C) 2020-2023 Moritz Zwerger + * Copyright (C) 2020-2024 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. * @@ -15,7 +15,7 @@ package de.bixilon.minosoft.gui.rendering.sky.clouds import de.bixilon.kotlinglm.mat4x4.Mat4 import de.bixilon.kotlinglm.vec3.Vec3 -import de.bixilon.minosoft.gui.rendering.camera.FogManager +import de.bixilon.minosoft.gui.rendering.camera.fog.FogManager import de.bixilon.minosoft.gui.rendering.shader.Shader import de.bixilon.minosoft.gui.rendering.shader.types.FogShader import de.bixilon.minosoft.gui.rendering.shader.types.ViewProjectionShader diff --git a/src/main/resources/assets/minosoft/rendering/shader/includes/animation.glsl b/src/main/resources/assets/minosoft/rendering/shader/includes/animation.glsl index 1c1cd5b71..c4ffc04c4 100644 --- a/src/main/resources/assets/minosoft/rendering/shader/includes/animation.glsl +++ b/src/main/resources/assets/minosoft/rendering/shader/includes/animation.glsl @@ -81,7 +81,7 @@ void applyTexel() { foutColor = texel; #ifdef FOG - set_fog(); + fog_set(); #endif } diff --git a/src/main/resources/assets/minosoft/rendering/shader/includes/fog.glsl b/src/main/resources/assets/minosoft/rendering/shader/includes/fog.glsl index 9d9430154..06ca9a47e 100644 --- a/src/main/resources/assets/minosoft/rendering/shader/includes/fog.glsl +++ b/src/main/resources/assets/minosoft/rendering/shader/includes/fog.glsl @@ -21,46 +21,58 @@ uniform float uFogStart = 60.0f * 60.0f; uniform float uFogEnd = 75.0f * 75.0f; uniform float uFogDistance = 15.0f * 15.0f; uniform vec4 uFogColor; -uniform bool uUseFogColor = false; +uniform uint uFogFlags = 0u; + + +#define FOG_ENABLE 0x01u << 0u +#define FOG_USE_COLOR 0x01u << 1u #ifndef DISTANCE_MULTIPLIER - #define DISTANCE_MULTIPLIER 1.0f +#define DISTANCE_MULTIPLIER 1.0f #endif -float calulate_fog_alpha(float distance2) { - if (distance2 < uFogStart) { - return 1.0f; - } - if (distance2 > uFogEnd) { - return 0.0f; - } +float fog_alpha_from_distance(float distance2) { + if (distance2 < uFogStart) return 1.0f; + if (distance2 > uFogEnd) return 0.0f; - return pow(1.0f - (distance2 - uFogStart) / uFogDistance, 2); + float alpha = 1.0f - (distance2 - uFogStart) / uFogDistance; + + return alpha * alpha; } -float calculate_fog() { - if (uFogStart > 10000.0f) { - return 1.0f; - }; - #ifdef FOG_SPHERE - vec3 distance_vec3 = finFragmentPosition.xyz - uCameraPosition.xyz; - float distance = dot(distance_vec3, distance_vec3); - #else - vec2 distance_vec2 = finFragmentPosition.xz - uCameraPosition.xz; - float distance = dot(distance_vec2, distance_vec2); - #endif - return calulate_fog_alpha(distance * DISTANCE_MULTIPLIER); +float fog_calculate_distance() { + vec3 distance = finFragmentPosition.xyz - uCameraPosition.xyz; + distance.y /= 2.0f;// increase possible distance on y axis + return dot(distance, distance); } -void set_fog() { - float alpha = calculate_fog(); - if (uUseFogColor) { - foutColor.rgb = mix(uFogColor.rgb, foutColor.rgb, foutColor.a * alpha); - foutColor.a = 1.0f; + +float fog_calculate_alpha() { + if (uFogStart > 10000.0f) return 1.0f; + + float distance = fog_calculate_distance(); + return fog_alpha_from_distance(distance * DISTANCE_MULTIPLIER); +} + +void fog_mix_alpha(float alpha) { + if (alpha <= 0.0f) discard; + foutColor.a = foutColor.a * alpha; +} + +void fog_mix_color(float alpha) { + foutColor.rgb = mix(uFogColor.rgb, foutColor.rgb, foutColor.a * alpha); + foutColor.a = 1.0f; +} + +void fog_set() { + if ((uFogFlags & FOG_ENABLE) == 0u) return; + + float alpha = fog_calculate_alpha(); + + + if ((uFogFlags & FOG_USE_COLOR) != 0u) { + fog_mix_color(alpha); } else { - if (alpha <= 0.0f) { - discard; - } - foutColor.a = foutColor.a * alpha; + fog_mix_alpha(alpha); } } diff --git a/src/main/resources/assets/minosoft/rendering/shader/sky/clouds/clouds.fsh b/src/main/resources/assets/minosoft/rendering/shader/sky/clouds/clouds.fsh index e1a19dd69..8e1ca2ea7 100644 --- a/src/main/resources/assets/minosoft/rendering/shader/sky/clouds/clouds.fsh +++ b/src/main/resources/assets/minosoft/rendering/shader/sky/clouds/clouds.fsh @@ -27,5 +27,5 @@ flat in float finBrightness; void main() { foutColor = vec4(uCloudsColor, 1.0f); foutColor.rgb *= finBrightness; - set_fog(); + fog_set(); }