[WIP] major rewrite, grass and leaves working already

This commit is contained in:
octarine-noise
2021-05-06 22:40:32 +02:00
parent 09ccb83e8b
commit f44d2a7a50
96 changed files with 2348 additions and 3531 deletions

View File

@@ -0,0 +1,65 @@
package mods.betterfoliage.render.block.vanilla
import mods.betterfoliage.Client
import mods.betterfoliage.config.Config
import mods.betterfoliage.render.ISpecialRenderModel
import mods.betterfoliage.render.old.HalfBakedSpecialWrapper
import mods.betterfoliage.render.old.HalfBakedWrapKey
import mods.betterfoliage.render.pipeline.RenderCtxBase
import mods.betterfoliage.resource.discovery.ModelBakeKey
import mods.betterfoliage.resource.discovery.ModelReplacer
import mods.betterfoliage.util.offset
import net.minecraft.block.BlockState
import net.minecraft.block.Blocks
import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.RenderTypeLookup
import net.minecraft.client.renderer.model.BlockModel
import net.minecraft.client.renderer.model.ModelBakery
import net.minecraft.util.Direction.UP
import net.minecraft.util.ResourceLocation
object StandardDirtDiscovery : ModelReplacer() {
val dirtBlocks = listOf(Blocks.DIRT, Blocks.COARSE_DIRT, Blocks.PODZOL)
override fun processModel(
bakery: ModelBakery,
state: BlockState,
location: ResourceLocation,
sprites: MutableSet<ResourceLocation>,
replacements: MutableMap<ResourceLocation, ModelBakeKey>
): Boolean {
val model = bakery.getUnbakedModel(location)
if (model is BlockModel && state.block in dirtBlocks) {
Client.blockTypes.dirt.add(state)
replacements[location] = StandardDirtKey
RenderTypeLookup.setRenderLayer(state.block, RenderType.getCutout())
return true
}
return super.processModel(bakery, state, location, sprites, replacements)
}
}
object StandardDirtKey : HalfBakedWrapKey() {
override fun replace(wrapped: ISpecialRenderModel) = StandardDirtModel(wrapped)
}
class StandardDirtModel(
wrapped: ISpecialRenderModel
) : HalfBakedSpecialWrapper(wrapped) {
override fun render(ctx: RenderCtxBase, noDecorations: Boolean) {
if (!Config.enabled || noDecorations) return super.render(ctx, false)
val stateUp = ctx.offset(UP).state
val isConnectedGrass = Config.connectedGrass.enabled && stateUp in Client.blockTypes.grass
if (isConnectedGrass) {
(ctx.blockModelShapes.getModel(stateUp) as? ISpecialRenderModel)?.let { grassModel ->
ctx.renderMasquerade(UP.offset) {
grassModel.render(ctx, true)
}
return
}
return super.render(ctx, false)
}
super.render(ctx, false)
}
}

View File

@@ -0,0 +1,123 @@
package mods.betterfoliage.render.block.vanilla
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.Client
import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.config.Config
import mods.betterfoliage.config.ConfigurableBlockMatcher
import mods.betterfoliage.config.ModelTextureList
import mods.betterfoliage.render.ISpecialRenderModel
import mods.betterfoliage.render.lighting.LightingPreferredFace
import mods.betterfoliage.render.old.Color
import mods.betterfoliage.render.old.HalfBakedSpecialWrapper
import mods.betterfoliage.render.old.HalfBakedWrapKey
import mods.betterfoliage.render.pipeline.RenderCtxBase
import mods.betterfoliage.render.pipeline.RenderCtxVanilla
import mods.betterfoliage.resource.discovery.BakeWrapperManager
import mods.betterfoliage.resource.discovery.ConfigurableModelReplacer
import mods.betterfoliage.resource.discovery.ModelBakeKey
import mods.betterfoliage.resource.model.SpriteSetDelegate
import mods.betterfoliage.resource.model.buildTufts
import mods.betterfoliage.resource.model.fullCubeTextured
import mods.betterfoliage.resource.model.fullCubeTinted
import mods.betterfoliage.resource.model.tuftModelSet
import mods.betterfoliage.resource.model.tuftShapeSet
import mods.betterfoliage.util.Atlas
import mods.betterfoliage.util.LazyInvalidatable
import mods.betterfoliage.util.LazyMapInvalidatable
import mods.betterfoliage.util.get
import mods.betterfoliage.util.isSnow
import mods.betterfoliage.util.randomI
import net.minecraft.block.BlockState
import net.minecraft.block.Blocks
import net.minecraft.client.renderer.RenderType
import net.minecraft.client.renderer.RenderTypeLookup
import net.minecraft.util.Direction.DOWN
import net.minecraft.util.Direction.UP
import net.minecraft.util.ResourceLocation
object StandardGrassDiscovery : ConfigurableModelReplacer() {
override val matchClasses: ConfigurableBlockMatcher get() = BlockConfig.grassBlocks
override val modelTextures: List<ModelTextureList> get() = BlockConfig.grassModels.modelList
override fun processModel(
state: BlockState,
location: ResourceLocation,
textureMatch: List<ResourceLocation>,
sprites: MutableSet<ResourceLocation>,
replacements: MutableMap<ResourceLocation, ModelBakeKey>
): Boolean {
replacements[location] = StandardGrassKey(textureMatch[0])
Client.blockTypes.grass.add(state)
RenderTypeLookup.setRenderLayer(state.block, RenderType.getCutout())
return true
}
}
data class StandardGrassKey(
val grassLocation: ResourceLocation
) : HalfBakedWrapKey() {
override fun replace(wrapped: ISpecialRenderModel): ISpecialRenderModel {
Atlas.BLOCKS[grassLocation].logColorOverride(detailLogger, Config.shortGrass.saturationThreshold)
return StandardGrassModel(wrapped, this)
}
}
class StandardGrassModel(
wrapped: ISpecialRenderModel,
key: StandardGrassKey
) : HalfBakedSpecialWrapper(wrapped) {
val tuftNormal by grassTuftMeshesNormal.delegate(key)
val tuftSnowed by grassTuftMeshesSnowed.delegate(key)
val fullBlock by grassFullBlockMeshes.delegate(key)
val upNormal = arrayOf(0.0f, 1.0f, 0.0f, 0.0f).toFloatArray()
val vanillaTuftLighting = LightingPreferredFace(UP)
override fun render(ctx: RenderCtxBase, noDecorations: Boolean) {
if (!Config.enabled || noDecorations) return super.render(ctx, noDecorations)
val stateBelow = ctx.state(DOWN)
val stateAbove = ctx.state(UP)
val isSnowed = stateAbove.isSnow
val connected = Config.connectedGrass.enabled &&
(!isSnowed || Config.connectedGrass.snowEnabled) &&
Client.blockTypes.run { stateBelow in grass || stateBelow in dirt }
if (connected) {
ctx.render(if (isSnowed) snowFullBlockMeshes[ctx.random] else fullBlock[ctx.random])
} else {
super.render(ctx, noDecorations)
}
if (Config.shortGrass.enabled(ctx.random) && !ctx.isNeighborSolid(UP)) {
(ctx as? RenderCtxVanilla)?.let { it.vertexLighter = vanillaTuftLighting }
ctx.render(if (isSnowed) tuftSnowed[ctx.random] else tuftNormal[ctx.random])
}
}
companion object {
val grassTuftSprites by SpriteSetDelegate(Atlas.BLOCKS) { idx ->
ResourceLocation(BetterFoliageMod.MOD_ID, "blocks/better_grass_long_$idx")
}
val grassTuftShapes by LazyInvalidatable(BakeWrapperManager) {
Config.shortGrass.let { tuftShapeSet(it.size, it.heightMin, it.heightMax, it.hOffset) }
}
val grassTuftMeshesNormal = LazyMapInvalidatable(BakeWrapperManager) { key: StandardGrassKey ->
val overrideColor = Atlas.BLOCKS[key.grassLocation].getColorOverride(Config.shortGrass.saturationThreshold)
tuftModelSet(grassTuftShapes, overrideColor) { idx -> grassTuftSprites[randomI()] }.buildTufts()
}
val grassTuftMeshesSnowed = LazyMapInvalidatable(BakeWrapperManager) { key: StandardGrassKey ->
tuftModelSet(grassTuftShapes, Color.white) { idx -> grassTuftSprites[randomI()] }.buildTufts()
}
val grassFullBlockMeshes = LazyMapInvalidatable(BakeWrapperManager) { key: StandardGrassKey ->
Array(64) { fullCubeTinted(key.grassLocation, Config.shortGrass.saturationThreshold) }
}
val snowFullBlockMeshes by LazyInvalidatable(BakeWrapperManager) {
Array(64) { fullCubeTextured(ResourceLocation("block/snow"), Color.white) }
}
}
}

View File

@@ -0,0 +1,112 @@
package mods.betterfoliage.render.block.vanilla
import mods.betterfoliage.BetterFoliageMod
import mods.betterfoliage.Client
import mods.betterfoliage.config.BlockConfig
import mods.betterfoliage.config.Config
import mods.betterfoliage.config.ConfigurableBlockMatcher
import mods.betterfoliage.config.ModelTextureList
import mods.betterfoliage.render.ISpecialRenderModel
import mods.betterfoliage.render.lighting.RoundLeafLighting
import mods.betterfoliage.render.old.Color
import mods.betterfoliage.render.old.HalfBakedSpecialWrapper
import mods.betterfoliage.render.old.HalfBakedWrapKey
import mods.betterfoliage.render.pipeline.RenderCtxBase
import mods.betterfoliage.render.pipeline.RenderCtxVanilla
import mods.betterfoliage.resource.discovery.BakeWrapperManager
import mods.betterfoliage.resource.discovery.ConfigurableModelReplacer
import mods.betterfoliage.resource.discovery.ModelBakeKey
import mods.betterfoliage.resource.generated.GeneratedLeaf
import mods.betterfoliage.resource.model.SpriteSetDelegate
import mods.betterfoliage.resource.model.crossModelsRaw
import mods.betterfoliage.resource.model.crossModelsTextured
import mods.betterfoliage.resource.model.crossModelsTinted
import mods.betterfoliage.texture.LeafParticleRegistry
import mods.betterfoliage.util.Atlas
import mods.betterfoliage.util.LazyMapInvalidatable
import mods.betterfoliage.util.averageColor
import mods.betterfoliage.util.isSnow
import net.minecraft.block.BlockState
import net.minecraft.client.renderer.texture.TextureAtlasSprite
import net.minecraft.util.Direction.UP
import net.minecraft.util.ResourceLocation
import org.apache.logging.log4j.Level.INFO
import org.apache.logging.log4j.Logger
object StandardLeafDiscovery : ConfigurableModelReplacer() {
override val matchClasses: ConfigurableBlockMatcher get() = BlockConfig.leafBlocks
override val modelTextures: List<ModelTextureList> get() = BlockConfig.leafModels.modelList
override fun processModel(
state: BlockState,
location: ResourceLocation,
textureMatch: List<ResourceLocation>,
sprites: MutableSet<ResourceLocation>,
replacements: MutableMap<ResourceLocation, ModelBakeKey>
): Boolean {
val leafType = LeafParticleRegistry.typeMappings.getType(textureMatch[0]) ?: "default"
val generated = GeneratedLeaf(textureMatch[0], leafType)
.register(Client.asyncPack)
.apply { sprites.add(this) }
detailLogger.log(INFO, " particle $leafType")
replacements[location] = StandardLeafKey(generated, leafType)
return true
}
}
fun TextureAtlasSprite.logColorOverride(logger: Logger, threshold: Double) {
val hsb = averageColor
return if (hsb.saturation >= threshold) {
logger.log(INFO, " brightness ${hsb.brightness}")
logger.log(INFO, " saturation ${hsb.saturation} >= ${threshold}, will use texture color")
} else {
logger.log(INFO, " saturation ${hsb.saturation} < ${threshold}, will use block color")
}
}
fun TextureAtlasSprite.getColorOverride(threshold: Double) = averageColor.let {
if (it.saturation < threshold) null else it.copy(brightness = (it.brightness * 2.0f).coerceAtMost(0.9f))
}?.asColor?.let { Color(it) }
data class StandardLeafKey(
val roundLeafTexture: ResourceLocation,
val leafType: String
) : HalfBakedWrapKey() {
override fun replace(wrapped: ISpecialRenderModel): ISpecialRenderModel {
Atlas.BLOCKS[roundLeafTexture].logColorOverride(BetterFoliageMod.detailLogger(this), 0.1)
return StandardLeafModel(wrapped, this)
}
}
class StandardLeafModel(
model: ISpecialRenderModel,
key: StandardLeafKey
) : HalfBakedSpecialWrapper(model) {
val leafNormal by leafModelsNormal.delegate(key)
val leafSnowed by leafModelsSnowed.delegate(key)
override fun render(ctx: RenderCtxBase, noDecorations: Boolean) {
super.render(ctx, noDecorations)
if (!Config.enabled || !Config.leaves.enabled || noDecorations) return
(ctx as? RenderCtxVanilla)?.let { it.vertexLighter = RoundLeafLighting }
ctx.render(leafNormal[ctx.random.nextInt(64)])
if (ctx.state(UP).isSnow) ctx.render(leafSnowed[ctx.random.nextInt(64)])
}
companion object {
val leafSpritesSnowed by SpriteSetDelegate(Atlas.BLOCKS) { idx ->
ResourceLocation(BetterFoliageMod.MOD_ID, "blocks/better_leaves_snowed_$idx")
}
val leafModelsBase = LazyMapInvalidatable(BakeWrapperManager) { key: StandardLeafKey ->
Config.leaves.let { crossModelsRaw(64, it.size, it.hOffset, it.vOffset) }
}
val leafModelsNormal = LazyMapInvalidatable(BakeWrapperManager) { key: StandardLeafKey ->
crossModelsTinted(leafModelsBase[key], Config.shortGrass.saturationThreshold) { key.roundLeafTexture }
}
val leafModelsSnowed = LazyMapInvalidatable(BakeWrapperManager) { key: StandardLeafKey ->
crossModelsTextured(leafModelsBase[key], Color.white, false) { leafSpritesSnowed[it].name }
}
}
}

View File

@@ -0,0 +1,13 @@
package mods.betterfoliage.render.block.vanilla
import mods.betterfoliage.render.column.ColumnBlockKey
import mods.betterfoliage.resource.discovery.ModelBakeKey
import net.minecraft.util.Direction
import net.minecraft.util.ResourceLocation
data class RoundLogKey(
override val axis: Direction.Axis?,
val barkSprite: ResourceLocation,
val endSprite: ResourceLocation
) : ColumnBlockKey, ModelBakeKey {
}