[WIP] major rewrite, grass and leaves working already
This commit is contained in:
@@ -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)
|
||||
}
|
||||
}
|
||||
123
src/main/kotlin/mods/betterfoliage/render/block/vanilla/Grass.kt
Normal file
123
src/main/kotlin/mods/betterfoliage/render/block/vanilla/Grass.kt
Normal 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) }
|
||||
}
|
||||
}
|
||||
}
|
||||
112
src/main/kotlin/mods/betterfoliage/render/block/vanilla/Leaf.kt
Normal file
112
src/main/kotlin/mods/betterfoliage/render/block/vanilla/Leaf.kt
Normal 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 }
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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 {
|
||||
}
|
||||
Reference in New Issue
Block a user