rendering: wip: biome blending

This commit is contained in:
Bixilon 2021-04-06 16:14:34 +02:00
parent d9b48cc8af
commit 130e0f2ed5
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
10 changed files with 112 additions and 24 deletions

View File

@ -15,9 +15,10 @@ package de.bixilon.minosoft.config.config.game
import de.bixilon.minosoft.config.config.game.controls.ControlsGameConfig import de.bixilon.minosoft.config.config.game.controls.ControlsGameConfig
import de.bixilon.minosoft.config.config.game.elements.ElementsGameConfig import de.bixilon.minosoft.config.config.game.elements.ElementsGameConfig
import de.bixilon.minosoft.config.config.game.graphics.GraphicsGameConfig
data class GameConfig( data class GameConfig(
var animations: AnimationsGameConfig = AnimationsGameConfig(), var graphics: GraphicsGameConfig = GraphicsGameConfig(),
var other: OtherGameConfig = OtherGameConfig(), var other: OtherGameConfig = OtherGameConfig(),
var hud: HUDGameConfig = HUDGameConfig(), var hud: HUDGameConfig = HUDGameConfig(),
var controls: ControlsGameConfig = ControlsGameConfig(), var controls: ControlsGameConfig = ControlsGameConfig(),

View File

@ -11,7 +11,7 @@
* This software is not affiliated with Mojang AB, the original developer of Minecraft. * This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/ */
package de.bixilon.minosoft.config.config.game package de.bixilon.minosoft.config.config.game.graphics
data class AnimationsGameConfig( data class AnimationsGameConfig(
var textures: Boolean = true, var textures: Boolean = true,

View File

@ -0,0 +1,21 @@
/*
* Minosoft
* Copyright (C) 2021 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.config.config.game.graphics
import com.squareup.moshi.Json
data class GraphicsGameConfig(
var animations: AnimationsGameConfig = AnimationsGameConfig(),
@Json(name = "biome_blend_radius") var biomeBlendRadius: Int = 3,
)

View File

@ -55,7 +55,8 @@ data class Block(
hasDynamicShape = data["has_dynamic_shape"]?.asBoolean ?: false, hasDynamicShape = data["has_dynamic_shape"]?.asBoolean ?: false,
tintColor = data["tint_color"]?.asInt?.let { TintColorCalculator.getJsonColor(it) }, tintColor = data["tint_color"]?.asInt?.let { TintColorCalculator.getJsonColor(it) },
itemId = data["item"]?.asInt ?: 0, itemId = data["item"]?.asInt ?: 0,
tint = data["tint"]?.asString?.let { ResourceLocation(it) }) tint = data["tint"]?.asString?.let { ResourceLocation(it) },
)
// block states // block states

View File

@ -121,4 +121,21 @@ class World : BiomeAccessor {
override fun getBiome(blockPosition: Vec3i): Biome? { override fun getBiome(blockPosition: Vec3i): Biome? {
return biomeAccessor.getBiome(blockPosition) return biomeAccessor.getBiome(blockPosition)
} }
fun getBlocks(start: Vec3i, end: Vec3i): Map<Vec3i, BlockState> {
val blocks: MutableMap<Vec3i, BlockState> = mutableMapOf()
for (z in start.z until end.z) {
for (y in start.y until end.y) {
for (x in start.x until end.x) {
val blockPosition = Vec3i(x, y, z)
getBlockState(blockPosition)?.let {
blocks[blockPosition] = it
}
}
}
}
return blocks.toMap()
}
} }

View File

@ -25,18 +25,18 @@ class IndirectPalette(
private val connection = buffer.connection private val connection = buffer.connection
private var palette = buffer.readVarIntArray() private var palette = buffer.readVarIntArray()
override fun blockById(blockId: Int): BlockState? { override fun blockById(id: Int): BlockState? {
var realBlockId = blockId var blockId = id
if (realBlockId < palette.size) { if (blockId < palette.size) {
realBlockId = palette[realBlockId] blockId = palette[blockId]
} }
val block = connection.mapping.getBlockState(realBlockId) val block = connection.mapping.getBlockState(blockId)
if (StaticConfiguration.DEBUG_MODE && block == null && realBlockId != ProtocolDefinition.NULL_BLOCK_ID) { if (StaticConfiguration.DEBUG_MODE && block == null && blockId != ProtocolDefinition.NULL_BLOCK_ID) {
val blockName: String = if (connection.version.isFlattened()) { val blockName: String = if (connection.version.isFlattened()) {
realBlockId.toString() blockId.toString()
} else { } else {
"(${realBlockId shr 4}:${realBlockId and 0x0F}" "(${blockId shr 4}:${blockId and 0x0F}"
} }
Log.warn("Server sent unknown block: $blockName") Log.warn("Server sent unknown block: $blockName")
} }

View File

@ -71,7 +71,7 @@ class RenderWindow(
private var mouseCatch = !StaticConfiguration.DEBUG_MODE private var mouseCatch = !StaticConfiguration.DEBUG_MODE
private val screenshotTaker = ScreenshotTaker(this) private val screenshotTaker = ScreenshotTaker(this)
val tintColorCalculator = TintColorCalculator() val tintColorCalculator = TintColorCalculator(connection.world)
val font = Font() val font = Font()
val textures = TextureArray(mutableListOf()) val textures = TextureArray(mutableListOf())

View File

@ -13,17 +13,19 @@
package de.bixilon.minosoft.gui.rendering package de.bixilon.minosoft.gui.rendering
import de.bixilon.minosoft.Minosoft
import de.bixilon.minosoft.config.StaticConfiguration import de.bixilon.minosoft.config.StaticConfiguration
import de.bixilon.minosoft.data.assets.MinecraftAssetsManager import de.bixilon.minosoft.data.assets.MinecraftAssetsManager
import de.bixilon.minosoft.data.mappings.ResourceLocation import de.bixilon.minosoft.data.mappings.ResourceLocation
import de.bixilon.minosoft.data.mappings.biomes.Biome import de.bixilon.minosoft.data.mappings.biomes.Biome
import de.bixilon.minosoft.data.mappings.blocks.BlockState import de.bixilon.minosoft.data.mappings.blocks.BlockState
import de.bixilon.minosoft.data.text.RGBColor import de.bixilon.minosoft.data.text.RGBColor
import de.bixilon.minosoft.data.world.World
import de.bixilon.minosoft.gui.rendering.textures.Texture import de.bixilon.minosoft.gui.rendering.textures.Texture
import glm_.vec3.Vec3i import glm_.vec3.Vec3i
class TintColorCalculator { class TintColorCalculator(val world: World) {
private lateinit var grassColorMap: Array<RGBColor> private lateinit var grassColorMap: Array<RGBColor>
private lateinit var foliageColorMap: Array<RGBColor> private lateinit var foliageColorMap: Array<RGBColor>
@ -32,7 +34,47 @@ class TintColorCalculator {
foliageColorMap = assetsManager.readPixelArrayAsset(Texture.getResourceTextureIdentifier(textureName = "colormap/foliage.png")) foliageColorMap = assetsManager.readPixelArrayAsset(Texture.getResourceTextureIdentifier(textureName = "colormap/foliage.png"))
} }
fun getTint(biome: Biome?, blockState: BlockState, blockPosition: Vec3i): RGBColor? { fun getAverageTint(biome: Biome?, blockState: BlockState, blockPosition: Vec3i): RGBColor? {
val biomeBlendRadius = Minosoft.getConfig().config.game.graphics.biomeBlendRadius
val selfTint = getTint(biome, blockState, blockPosition)
if (selfTint == null || biomeBlendRadius == 0) {
return selfTint
}
val blendStart = Vec3i(blockPosition.x - biomeBlendRadius, blockPosition.y, blockPosition.z - biomeBlendRadius)
val blendEnd = Vec3i(blockPosition.x + biomeBlendRadius, blockPosition.y + 1, blockPosition.z + biomeBlendRadius)
var totalRed = 0L
var totalGreen = 0L
var totalBlue = 0L
var count = 0
for (z in blendStart.z until blendEnd.z) {
for (y in blendStart.y until blendEnd.y) {
for (x in blendStart.x until blendEnd.x) {
val blendBlockPosition = Vec3i(x, y, z)
getTint(world.getBiome(blendBlockPosition), blockState, blendBlockPosition)?.let {
totalRed += it.red
totalGreen += it.green
totalBlue += it.blue
count++
}
}
}
}
if ((totalRed == 0L && totalGreen == 0L && totalBlue == 0L) || count == 0) {
return null
}
return RGBColor((totalRed / count).toInt(), (totalGreen / count).toInt(), (totalBlue / count).toInt())
}
private fun getTint(biome: Biome?, blockState: BlockState, blockPosition: Vec3i): RGBColor? {
return when { return when {
biome == null -> null biome == null -> null
StaticConfiguration.BIOME_DEBUG_MODE -> RGBColor(biome.hashCode()) StaticConfiguration.BIOME_DEBUG_MODE -> RGBColor(biome.hashCode())
@ -42,11 +84,10 @@ class TintColorCalculator {
} }
} }
fun calculateTint(tint: ResourceLocation, biome: Biome, blockPosition: Vec3i): RGBColor? { private fun calculateTint(tint: ResourceLocation, biome: Biome, blockPosition: Vec3i): RGBColor? {
return when (tint) { return when (tint) {
ResourceLocation("water_tint") -> biome.waterColor WATER_TINT_RESOURCE_LOCATION -> biome.waterColor
ResourceLocation("grass_tint"), ResourceLocation("sugar_cane_tint"), ResourceLocation("shearing_double_plant_tint") -> { GRASS_TINT_RESOURCE_LOCATION, SUGAR_CANE_TINT_RESOURCE_LOCATION, SHEARING_DOUBLE_PLANT_TINT_RESOURCE_LOCATION -> {
// ToDo: color overrider in < 1.16
biome.grassColorOverride?.let { return it } biome.grassColorOverride?.let { return it }
val colorMapPixelIndex = biome.downfallColorMapCoordinate shl 8 or biome.temperatureColorMapCoordinate val colorMapPixelIndex = biome.downfallColorMapCoordinate shl 8 or biome.temperatureColorMapCoordinate
@ -60,18 +101,25 @@ class TintColorCalculator {
} }
biome.grassColorModifier.modifier.invoke(color) biome.grassColorModifier.modifier.invoke(color)
} }
ResourceLocation("foliage_tint") -> { FOLIAGE_TINT_RESOURCE_LOCATION -> {
biome.foliageColorOverride?.let { return it } biome.foliageColorOverride?.let { return it }
// ToDo: color overrider in < 1.16
foliageColorMap[biome.downfallColorMapCoordinate shl 8 or biome.getClampedTemperature(blockPosition.y)] foliageColorMap[biome.downfallColorMapCoordinate shl 8 or biome.getClampedTemperature(blockPosition.y)]
} }
ResourceLocation("lily_pad_tint") -> RenderConstants.LILY_PAD_BLOCK_COLOR LILY_PAD_TINT_RESOURCE_LOCATION -> RenderConstants.LILY_PAD_BLOCK_COLOR
else -> null else -> null
} }
} }
companion object { companion object {
private val WATER_TINT_RESOURCE_LOCATION = ResourceLocation("water_tint")
private val GRASS_TINT_RESOURCE_LOCATION = ResourceLocation("grass_tint")
private val SUGAR_CANE_TINT_RESOURCE_LOCATION = ResourceLocation("sugar_cane_tint")
private val SHEARING_DOUBLE_PLANT_TINT_RESOURCE_LOCATION = ResourceLocation("shearing_double_plant_tint")
private val FOLIAGE_TINT_RESOURCE_LOCATION = ResourceLocation("foliage_tint")
private val LILY_PAD_TINT_RESOURCE_LOCATION = ResourceLocation("lily_pad_tint")
fun getJsonColor(color: Int): RGBColor? { fun getJsonColor(color: Int): RGBColor? {
if (color == 0) { if (color == 0) {
return null return null

View File

@ -78,11 +78,11 @@ class WorldRenderer(
val biome = world.getBiome(blockPosition) val biome = world.getBiome(blockPosition)
val tintColor = renderWindow.tintColorCalculator.getTint(biome, blockState, blockPosition) val tintColor = renderWindow.tintColorCalculator.getAverageTint(biome, blockState, blockPosition)
if (blockState.properties[BlockProperties.WATERLOGGED] == true) { if (blockState.properties[BlockProperties.WATERLOGGED] == true) {
val waterTintColor = renderWindow.tintColorCalculator.getTint(biome, WATER_BLOCK_STATE, blockPosition) val waterTintColor = renderWindow.tintColorCalculator.getAverageTint(biome, WATER_BLOCK_STATE, blockPosition)
BlockState.SPECIAL_RENDERERS["water"]?.render(blockState, world.worldLightAccessor, waterTintColor, blockPosition, meshCollection, neighborBlocks, world) BlockState.SPECIAL_RENDERERS["water"]?.render(blockState, world.worldLightAccessor, waterTintColor, blockPosition, meshCollection, neighborBlocks, world)
} }

View File

@ -178,7 +178,7 @@ class TextureArray(val allTextures: MutableList<Texture>) {
if (!initialized) { if (!initialized) {
return return
} }
if (!Minosoft.getConfig().config.game.animations.textures) { if (!Minosoft.getConfig().config.game.graphics.animations.textures) {
return return
} }