fix leaf block & leaf particle colors

This commit is contained in:
octarine-noise
2021-07-26 14:52:16 +02:00
parent 4c08354d74
commit b4824b77ae
12 changed files with 71 additions and 30 deletions

View File

@@ -70,6 +70,8 @@ data class Color(val alpha: Int, val red: Int, val green: Int, val blue: Int) {
)
val asInt get() = (alpha shl 24) or (red shl 16) or (green shl 8) or blue
val asHSB get() = HSB.fromColor(this)
operator fun times(f: Float) = Color(
alpha,
(f * red.toFloat()).toInt().coerceIn(0 until 256),
@@ -93,6 +95,10 @@ data class HSB(var hue: Float, var saturation: Float, var brightness: Float) {
val hsbVals = java.awt.Color.RGBtoHSB((color shr 16) and 255, (color shr 8) and 255, color and 255, null)
return HSB(hsbVals[0], hsbVals[1], hsbVals[2])
}
fun fromColor(color: Color): HSB {
val hsbVals = java.awt.Color.RGBtoHSB(color.red, color.green, color.blue, null)
return HSB(hsbVals[0], hsbVals[1], hsbVals[2])
}
}
val asInt: Int get() = java.awt.Color.HSBtoRGB(hue, saturation, brightness)
val asColor: Color get() = Color(asInt)

View File

@@ -84,20 +84,20 @@ fun crossModelsRaw(num: Int, size: Double, hOffset: Double, vOffset: Double): Li
}
}
fun crossModelSingle(base: List<Quad>, sprite: TextureAtlasSprite, tintIndex: Int,scrambleUV: Boolean) =
fun crossModelSingle(base: List<Quad>, sprite: TextureAtlasSprite, color: Color, tint: Int, scrambleUV: Boolean) =
base.map { if (scrambleUV) it.scrambleUV(random, canFlipU = true, canFlipV = true, canRotate = true) else it }
.map { it.colorIndex(tintIndex) }
.map { it.color(color).colorIndex(tint) }
.mapIndexed { idx, quad -> quad.sprite(sprite) }
.withOpposites()
.bake(false)
fun crossModelsTextured(
leafBase: Iterable<List<Quad>>,
tintIndex: Int,
color: Color, tint: Int,
scrambleUV: Boolean,
spriteGetter: (Int) -> ResourceLocation
) = leafBase.mapIndexed { idx, leaf ->
crossModelSingle(leaf, Atlas.BLOCKS[spriteGetter(idx)], tintIndex, scrambleUV)
crossModelSingle(leaf, Atlas.BLOCKS[spriteGetter(idx)], color, tint, scrambleUV)
}.toTypedArray()
fun Iterable<Quad>.withOpposites() = flatMap { listOf(it, it.flipped) }

View File

@@ -87,7 +87,7 @@ class StandardCactusModel(
crossModelsRaw(64, config.size, 0.0, 0.0)
.transform { rotateZ(randomD(-config.sizeVariation, config.sizeVariation)) }
}
crossModelsTextured(models, -1, true) { cactusCrossSprite }
crossModelsTextured(models, Color.white, -1, true) { cactusCrossSprite }
}
}
}

View File

@@ -28,19 +28,24 @@ import mods.betterfoliage.util.averageHSB
import mods.betterfoliage.util.idxOrNull
import mods.betterfoliage.util.lazy
import mods.betterfoliage.util.lazyMap
import mods.betterfoliage.util.lighten
import mods.betterfoliage.util.brighten
import mods.betterfoliage.util.logTextureColor
import mods.betterfoliage.util.randomI
import net.minecraft.client.renderer.RenderType
import net.minecraft.util.Direction.DOWN
import net.minecraft.util.Direction.UP
import net.minecraft.util.ResourceLocation
import org.apache.logging.log4j.Level.INFO
import java.util.Random
object StandardGrassDiscovery : ParametrizedModelDiscovery() {
override fun processModel(ctx: ModelDiscoveryContext, params: Map<String, String>) {
val texture = params.location("texture") ?: return
val tint = params.int("tint") ?: -1
val color = Atlas.BLOCKS.file(texture).averageHSB.lighten()
val color = Atlas.BLOCKS.file(texture).averageHSB.let {
detailLogger.logTextureColor(INFO, "grass texture \"$texture\"", it)
it.brighten().asColor
}
ctx.addReplacement(StandardGrassKey(texture, tint, color))
BetterFoliage.blockTypes.grass.add(ctx.blockState)
ctx.blockState.block.extendLayers()

View File

@@ -22,8 +22,12 @@ import mods.betterfoliage.resource.discovery.ModelDiscoveryContext
import mods.betterfoliage.resource.discovery.ParametrizedModelDiscovery
import mods.betterfoliage.resource.generated.GeneratedLeafSprite
import mods.betterfoliage.util.Atlas
import mods.betterfoliage.util.averageHSB
import mods.betterfoliage.util.lazy
import mods.betterfoliage.util.lazyMap
import mods.betterfoliage.util.logColorOverride
import mods.betterfoliage.util.brighten
import mods.betterfoliage.util.logTextureColor
import mods.betterfoliage.util.saturate
import net.minecraft.client.renderer.RenderType
import net.minecraft.util.Direction.UP
import net.minecraft.util.ResourceLocation
@@ -31,14 +35,19 @@ import org.apache.logging.log4j.Level.INFO
object StandardLeafDiscovery : ParametrizedModelDiscovery() {
override fun processModel(ctx: ModelDiscoveryContext, params: Map<String, String>) {
val leafSprite = params.location("texture-leaf") ?: return
val leafType = LeafParticleRegistry.typeMappings.getType(leafSprite) ?: "default"
val generated = GeneratedLeafSprite(leafSprite, leafType)
val texture = params.location("texture") ?: return
val tint = params.int("tint") ?: -1
val color = Atlas.BLOCKS.file(texture).averageHSB.let {
detailLogger.logTextureColor(INFO, "leaf texture \"$texture\"", it)
it.brighten().asColor
}
val leafType = LeafParticleRegistry.typeMappings.getType(texture) ?: "default"
val generated = GeneratedLeafSprite(texture, leafType)
.register(BetterFoliage.generatedPack)
.apply { ctx.sprites.add(this) }
detailLogger.log(INFO, " particle $leafType")
ctx.addReplacement(StandardLeafKey(generated, leafType, null))
ctx.addReplacement(StandardLeafKey(generated, leafType, tint, color))
BetterFoliage.blockTypes.leaf.add(ctx.blockState)
}
}
@@ -46,10 +55,9 @@ object StandardLeafDiscovery : ParametrizedModelDiscovery() {
data class StandardLeafKey(
val roundLeafTexture: ResourceLocation,
override val leafType: String,
override val overrideColor: Color?
override val tintIndex: Int,
override val avgColor: Color
) : HalfBakedWrapperKey(), LeafParticleKey {
val tintIndex: Int get() = if (overrideColor == null) 0 else -1
override fun bake(ctx: ModelBakingContext, wrapped: SpecialRenderModel): SpecialRenderModel {
return StandardLeafModel(wrapped, this)
}
@@ -78,14 +86,16 @@ class StandardLeafModel(
val leafSpritesSnowed by SpriteSetDelegate(Atlas.BLOCKS) { idx ->
ResourceLocation(BetterFoliageMod.MOD_ID, "blocks/better_leaves_snowed_$idx")
}
val leafModelsBase = BetterFoliage.modelManager.lazyMap { key: StandardLeafKey ->
val leafModelsBase by BetterFoliage.modelManager.lazy {
Config.leaves.let { crossModelsRaw(64, it.size, it.hOffset, it.vOffset) }
}
val leafModelsNormal = BetterFoliage.modelManager.lazyMap { key: StandardLeafKey ->
crossModelsTextured(leafModelsBase[key], key.tintIndex, true) { key.roundLeafTexture }
// generated leaf textures naturally carry the color of their source textures
// no need to color the quad a second time
crossModelsTextured(leafModelsBase, Color.white, key.tintIndex, true) { key.roundLeafTexture }
}
val leafModelsSnowed = BetterFoliage.modelManager.lazyMap { key: StandardLeafKey ->
crossModelsTextured(leafModelsBase[key], -1, false) { leafSpritesSnowed[it].name }
crossModelsTextured(leafModelsBase, Color.white, -1, false) { leafSpritesSnowed[it].name }
}
}
}

View File

@@ -25,7 +25,7 @@ import mods.betterfoliage.util.averageHSB
import mods.betterfoliage.util.idxOrNull
import mods.betterfoliage.util.lazy
import mods.betterfoliage.util.lazyMap
import mods.betterfoliage.util.lighten
import mods.betterfoliage.util.brighten
import mods.betterfoliage.util.randomI
import net.minecraft.client.renderer.RenderType
import net.minecraft.util.Direction
@@ -36,7 +36,7 @@ object StandardMyceliumDiscovery : ParametrizedModelDiscovery() {
override fun processModel(ctx: ModelDiscoveryContext, params: Map<String, String>) {
val texture = params.location("texture") ?: return
val tint = params.int("tint") ?: -1
val color = Atlas.BLOCKS.file(texture).averageHSB.lighten(multiplier = 1.5f)
val color = Atlas.BLOCKS.file(texture).averageHSB.brighten(multiplier = 1.5f).asColor
ctx.addReplacement(StandardMyceliumKey(texture, tint, color))
ctx.blockState.block.extendLayers()
}

View File

@@ -1,6 +1,8 @@
package mods.betterfoliage.render.particle
import com.mojang.blaze3d.vertex.IVertexBuilder
import mods.betterfoliage.model.Color
import mods.betterfoliage.model.HSB
import mods.betterfoliage.util.Double3
import net.minecraft.client.Minecraft
import net.minecraft.client.particle.SpriteTexturedParticle
@@ -92,10 +94,16 @@ abstract class AbstractParticle(world: ClientWorld, x: Double, y: Double, z: Dou
renderVertex(coords[3], sprite.u0, sprite.v1)
}
fun setColor(color: Int) {
bCol = (color and 255) / 256.0f
gCol = ((color shr 8) and 255) / 256.0f
rCol = ((color shr 16) and 255) / 256.0f
fun setColor(color: Color) {
rCol = color.red / 256.0f
gCol = color.green / 256.0f
bCol = color.blue / 256.0f
}
/**
* Set particle color to the "stronger" of the given colors, determined by higher color saturation
*/
fun setColor(color1: Color, color2: Color) =
setColor(if (color1.asHSB.saturation > color2.asHSB.saturation) color1 else color2)
}

View File

@@ -1,6 +1,7 @@
package mods.betterfoliage.render.particle
import mods.betterfoliage.config.Config
import mods.betterfoliage.model.Color
import mods.betterfoliage.util.Double3
import mods.betterfoliage.util.PI2
import mods.betterfoliage.util.minmax
@@ -44,7 +45,7 @@ class FallingLeafParticle(
yd = -Config.fallingLeaves.speed
quadSize = Config.fallingLeaves.size.toFloat() * 0.1f
setColor(leaf.overrideColor?.asInt ?: blockColor)
if (leaf.tintIndex == -1) setColor(leaf.avgColor) else setColor(leaf.avgColor, Color(blockColor))
sprite = LeafParticleRegistry[leaf.leafType][randomI(max = 1024)]
}

View File

@@ -23,7 +23,8 @@ interface LeafBlockModel {
interface LeafParticleKey {
val leafType: String
val overrideColor: Color?
val tintIndex: Int
val avgColor: Color
}
object LeafParticleRegistry : HasLogger(), VeryEarlyReloadListener {

View File

@@ -2,6 +2,7 @@
package mods.betterfoliage.util
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.model.HSB
import net.minecraft.block.BlockState
import net.minecraft.client.Minecraft
import net.minecraft.util.ResourceLocation
@@ -65,6 +66,11 @@ abstract class HasLogger {
val detailLogger = BetterFoliageMod.detailLogger(this)
}
fun Logger.logTextureColor(level: Level, description: String, avgColor: HSB) {
val rgb = avgColor.asColor
log(level, "$description average color RGB[${rgb.red},${rgb.green},${rgb.blue}], HSB[${avgColor.hue},${avgColor.saturation},${avgColor.brightness}]")
}
fun getBlockModel(state: BlockState) = Minecraft.getInstance().blockRenderer.blockModelShaper.getBlockModel(state)
/**
* Check if the Chunk containing the given [BlockPos] is loaded.

View File

@@ -16,6 +16,8 @@ import java.io.IOException
import javax.imageio.ImageIO
import kotlin.math.atan2
import kotlin.math.cos
import kotlin.math.max
import kotlin.math.min
import kotlin.math.sin
enum class Atlas(val resourceId: ResourceLocation) {
@@ -107,8 +109,10 @@ val ResourceLocation.averageHSB: HSB get() = resourceManager.loadSprite(this).le
return HSB(avgHue, sumSaturation / numOpaque.toFloat(), sumBrightness / numOpaque.toFloat())
}
fun HSB.lighten(multiplier: Float = 2.0f, ceiling: Float = 0.9f) =
copy(brightness = (brightness * multiplier).coerceAtMost(ceiling)).asColor
fun HSB.brighten(multiplier: Float = 1.5f, floor: Float = 0.1f, ceiling: Float = 0.9f) =
copy(brightness = (brightness * multiplier).coerceAtMost(max(ceiling, brightness)).coerceAtLeast(min(floor, brightness)))
fun HSB.saturate(multiplier: Float = 1.5f, floor: Float = 0.1f, ceiling: Float = 0.9f) =
copy(saturation = (saturation * multiplier).coerceAtMost(max(ceiling, saturation)).coerceAtLeast(min(floor, saturation)))
/** Weighted blend of 2 packed RGB colors */
fun blendRGB(rgb1: Int, rgb2: Int, weight1: Int, weight2: Int): Int {

View File

@@ -3,8 +3,8 @@ match block.class.extends(classOf("minecraft:oak_leaves")) setParam("type", "lea
match isParam("type", "leaf")
model.extends("minecraft:block/leaves", "minecraft:block/cube_all")
setParam("texture-leaf", model.texture("all"))
setParam("tint-leaf", model.tint("all"))
setParam("texture", model.texture("all"))
setParam("tint", model.tint("all"))
end
// Podzol