From b33696058fc29c8728d42c1cbb12f8672e3d646d Mon Sep 17 00:00:00 2001 From: Moritz Zwerger Date: Thu, 2 Nov 2023 10:10:51 +0100 Subject: [PATCH] entity renderer: damage --- build.gradle.kts | 2 +- .../data/entities/entities/LivingEntity.kt | 9 +++++++- .../event/events/damage/DamageEvent.kt | 2 +- .../event/events/damage/DamageListener.kt | 19 +++++++++++++++++ .../data/text/formatting/color/ColorUtil.kt | 4 +++- .../entities/feature/SkeletalFeature.kt | 3 ++- .../entities/hitbox/HitboxFeature.kt | 1 - .../entities/model/human/PlayerModel.kt | 2 +- .../entities/renderer/EntityRenderer.kt | 13 +++++++++++- .../renderer/living/player/PlayerShader.kt | 5 +++-- .../rendering/shader/types/TintedShader.kt | 21 +++++++++++++++++++ .../skeletal/instance/SkeletalInstance.kt | 4 ++-- .../skeletal/shader/SkeletalShader.kt | 5 +++-- .../shader/entities/player/player.vsh | 4 ++-- .../shader/skeletal/normal/normal.vsh | 4 ++-- 15 files changed, 80 insertions(+), 18 deletions(-) create mode 100644 src/main/java/de/bixilon/minosoft/data/entities/event/events/damage/DamageListener.kt create mode 100644 src/main/java/de/bixilon/minosoft/gui/rendering/shader/types/TintedShader.kt diff --git a/build.gradle.kts b/build.gradle.kts index 5a42593fa..3681bab5e 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -229,7 +229,7 @@ testing { val options = this as TestNGOptions options.preserveOrder = true // options.excludeGroups("models", "mesher", "chunk", "input", "font", "command", "registry", "biome", "version", "fluid", "world", "raycasting", "pixlyzer", "item", "block", "physics", "light", "packet", "container", "item_stack", "signature", "private_key", "interaction", "item_digging", "chunk_renderer", "rendering", "texture", "atlas", "gui") - options.excludeGroups("models", "mesher", "chunk", "input", "font", "command", "registry", "biome", "version", "fluid", "world", "raycasting", "pixlyzer", "item", "block", "physics", "light", "packet", "container", "item_stack", "signature", "private_key", "interaction", "item_digging", "chunk_renderer", "texture", "atlas", "gui") + options.excludeGroups("models", "chunk", "input", "font", "command", "registry", "biome", "version", "fluid", "world", "raycasting", "pixlyzer", "item", "physics", "light", "packet", "container", "item_stack", "signature", "private_key", "interaction", "item_digging", "chunk_renderer", "texture", "atlas", "gui") } } } diff --git a/src/main/java/de/bixilon/minosoft/data/entities/entities/LivingEntity.kt b/src/main/java/de/bixilon/minosoft/data/entities/entities/LivingEntity.kt index 2fc94bb62..ac54811be 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/entities/LivingEntity.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/entities/LivingEntity.kt @@ -14,6 +14,7 @@ package de.bixilon.minosoft.data.entities.entities import de.bixilon.kotlinglm.vec3.Vec3d import de.bixilon.kotlinglm.vec3.Vec3i +import de.bixilon.kutil.cast.CastUtil.nullCast import de.bixilon.kutil.cast.CastUtil.unsafeCast import de.bixilon.minosoft.data.container.equipment.EntityEquipment import de.bixilon.minosoft.data.entities.EntityRotation @@ -22,6 +23,8 @@ import de.bixilon.minosoft.data.entities.data.EntityData import de.bixilon.minosoft.data.entities.data.EntityDataField import de.bixilon.minosoft.data.entities.entities.player.Hands import de.bixilon.minosoft.data.entities.entities.properties.StatusEffectProperty +import de.bixilon.minosoft.data.entities.event.events.damage.DamageEvent +import de.bixilon.minosoft.data.entities.event.events.damage.DamageListener import de.bixilon.minosoft.data.registries.effects.attributes.EntityAttributes import de.bixilon.minosoft.data.registries.effects.attributes.MinecraftAttributes import de.bixilon.minosoft.data.registries.entities.EntityType @@ -33,7 +36,7 @@ import de.bixilon.minosoft.gui.rendering.particle.types.render.texture.simple.sp import de.bixilon.minosoft.physics.entities.living.LivingEntityPhysics import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection -abstract class LivingEntity(connection: PlayConnection, entityType: EntityType, data: EntityData, position: Vec3d, rotation: EntityRotation) : Entity(connection, entityType, data, position, rotation) { +abstract class LivingEntity(connection: PlayConnection, entityType: EntityType, data: EntityData, position: Vec3d, rotation: EntityRotation) : Entity(connection, entityType, data, position, rotation), DamageListener { private val entityEffectParticle = connection.registries.particleType[EntityEffectParticle] private val ambientEntityEffectParticle = connection.registries.particleType[AmbientEntityEffectParticle] @@ -109,6 +112,10 @@ abstract class LivingEntity(connection: PlayConnection, entityType: EntityType, override fun physics(): LivingEntityPhysics<*> = super.physics().unsafeCast() + override fun onDamage(type: DamageEvent) { + this.renderer?.nullCast()?.onDamage(type) + } + companion object { private val FLAGS_DATA = EntityDataField("LIVING_ENTITY_FLAGS") private val HEALTH_DATA = EntityDataField("LIVING_ENTITY_HEALTH") diff --git a/src/main/java/de/bixilon/minosoft/data/entities/event/events/damage/DamageEvent.kt b/src/main/java/de/bixilon/minosoft/data/entities/event/events/damage/DamageEvent.kt index fdc8fd0c4..43b0b93d8 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/event/events/damage/DamageEvent.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/event/events/damage/DamageEvent.kt @@ -19,6 +19,6 @@ import de.bixilon.minosoft.data.entities.event.EntityEvent interface DamageEvent : EntityEvent { override fun handle(entity: LivingEntity) { - // TODO + entity.onDamage(this) } } diff --git a/src/main/java/de/bixilon/minosoft/data/entities/event/events/damage/DamageListener.kt b/src/main/java/de/bixilon/minosoft/data/entities/event/events/damage/DamageListener.kt new file mode 100644 index 000000000..ca16cf5b2 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/data/entities/event/events/damage/DamageListener.kt @@ -0,0 +1,19 @@ +/* + * 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.data.entities.event.events.damage + +fun interface DamageListener { + + fun onDamage(type: DamageEvent) // TODO: DamageType +} diff --git a/src/main/java/de/bixilon/minosoft/data/text/formatting/color/ColorUtil.kt b/src/main/java/de/bixilon/minosoft/data/text/formatting/color/ColorUtil.kt index a28b4d92d..335a83e25 100644 --- a/src/main/java/de/bixilon/minosoft/data/text/formatting/color/ColorUtil.kt +++ b/src/main/java/de/bixilon/minosoft/data/text/formatting/color/ColorUtil.kt @@ -13,6 +13,8 @@ package de.bixilon.minosoft.data.text.formatting.color +import de.bixilon.kutil.math.interpolation.FloatInterpolation + object ColorUtil { fun mixColors(vararg colors: Int): Int { @@ -38,7 +40,7 @@ object ColorUtil { return (start.toFloat() + delta * (end.toFloat() - start.toFloat())).toInt() } - fun interpolateRGB(delta: Float, start: RGBColor, end: RGBColor): RGBColor { + fun interpolateRGB(delta: Float, start: RGBColor, end: RGBColor, component: (Float, Float, Float) -> Float = FloatInterpolation::interpolateLinear): RGBColor { if (delta <= 0.0f) return start if (delta >= 1.0f) return end diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/feature/SkeletalFeature.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/feature/SkeletalFeature.kt index 12093fe30..7de5fdab3 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/feature/SkeletalFeature.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/feature/SkeletalFeature.kt @@ -64,7 +64,8 @@ open class SkeletalFeature( } override fun draw() { - instance.draw(renderer.light.value) + val tint = renderer.light.value.mix(renderer.damage.value) + instance.draw(tint) } override fun reset() { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/hitbox/HitboxFeature.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/hitbox/HitboxFeature.kt index efc8b7f97..ccabd00ab 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/hitbox/HitboxFeature.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/hitbox/HitboxFeature.kt @@ -48,7 +48,6 @@ class HitboxFeature(renderer: EntityRenderer<*>) : EntityRenderFeature(renderer) override fun update(millis: Long, delta: Float) { if (!manager.enabled) return unload() if (!enabled) return unload() - if (!manager.profile.showInvisible && renderer.entity.isInvisible) return unload() if (!visible) return val offset = renderer.renderer.context.camera.offset.offset diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/model/human/PlayerModel.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/model/human/PlayerModel.kt index 1ea75ad5c..e773e0dba 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/model/human/PlayerModel.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/model/human/PlayerModel.kt @@ -37,7 +37,7 @@ open class PlayerModel( shader.use() shader.texture = renderer.skin?.shaderId ?: renderer.renderer.context.textures.debugTexture.shaderId - shader.light = renderer.light.value + shader.tint = renderer.light.value.mix(renderer.damage.value) shader.skinParts = this.skinParts diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/EntityRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/EntityRenderer.kt index be98cb4bf..3a4f8d2ad 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/EntityRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/EntityRenderer.kt @@ -16,6 +16,8 @@ package de.bixilon.minosoft.gui.rendering.entities.renderer import de.bixilon.kotlinglm.mat4x4.Mat4 import de.bixilon.kotlinglm.vec3.Vec3 import de.bixilon.minosoft.data.entities.entities.Entity +import de.bixilon.minosoft.data.entities.event.events.damage.DamageEvent +import de.bixilon.minosoft.data.entities.event.events.damage.DamageListener import de.bixilon.minosoft.data.text.formatting.color.ChatColors import de.bixilon.minosoft.data.text.formatting.color.ColorUtil import de.bixilon.minosoft.gui.rendering.entities.EntitiesRenderer @@ -31,13 +33,14 @@ import de.bixilon.minosoft.util.interpolate.Interpolator abstract class EntityRenderer( val renderer: EntitiesRenderer, val entity: E, -) { +) : DamageListener { private var update = 0L val features = FeatureManager(this) val info = entity.renderInfo val hitbox = HitboxFeature(this).register() val light = Interpolator(ChatColors.WHITE, ColorUtil::interpolateRGB) + val damage = Interpolator(ChatColors.WHITE, ColorUtil::interpolateRGB) // TODO delta^2 val matrix = Mat4() var visible = true protected set @@ -62,6 +65,10 @@ abstract class EntityRenderer( open fun update(millis: Long) { val delta = if (this.update <= 0L) 0.0f else ((millis - update) / 1000.0f) updateLight(delta) + if (damage.delta > 1.0f) { + damage.push(ChatColors.WHITE) + } + damage.add(delta, 0.05f) entity.draw(millis) updateMatrix(delta) features.update(millis, delta) @@ -96,4 +103,8 @@ abstract class EntityRenderer( this.visible = visible && !entity.isInvisible features.updateVisibility(occluded) } + + override fun onDamage(type: DamageEvent) { + damage.push(ChatColors.RED) + } } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/living/player/PlayerShader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/living/player/PlayerShader.kt index 1bc7768ee..df1ec2645 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/living/player/PlayerShader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/living/player/PlayerShader.kt @@ -14,12 +14,13 @@ package de.bixilon.minosoft.gui.rendering.entities.renderer.living.player import de.bixilon.minosoft.data.text.formatting.color.ChatColors +import de.bixilon.minosoft.gui.rendering.shader.types.TintedShader import de.bixilon.minosoft.gui.rendering.skeletal.shader.BaseSkeletalShader import de.bixilon.minosoft.gui.rendering.system.base.buffer.uniform.FloatUniformBuffer import de.bixilon.minosoft.gui.rendering.system.base.shader.NativeShader -class PlayerShader(native: NativeShader, buffer: FloatUniformBuffer) : BaseSkeletalShader(native, buffer) { +class PlayerShader(native: NativeShader, buffer: FloatUniformBuffer) : BaseSkeletalShader(native, buffer), TintedShader { var texture by uniform("uIndexLayer", 0x00, NativeShader::setUInt) - var light by uniform("uLight", ChatColors.WHITE) { shader, name, value -> shader.setUInt(name, value.rgb) } + override var tint by uniform("uTintColor", ChatColors.WHITE) { shader, name, value -> shader.setUInt(name, value.rgb) } var skinParts by uniform("uSkinParts", 0xFF, NativeShader::setUInt) } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/shader/types/TintedShader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/shader/types/TintedShader.kt new file mode 100644 index 000000000..29500e022 --- /dev/null +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/shader/types/TintedShader.kt @@ -0,0 +1,21 @@ +/* + * 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.shader.types + +import de.bixilon.minosoft.data.text.formatting.color.RGBColor +import de.bixilon.minosoft.gui.rendering.shader.AbstractShader + +interface TintedShader : AbstractShader { + var tint: RGBColor +} diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/SkeletalInstance.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/SkeletalInstance.kt index 4660f5dc3..39076ac24 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/SkeletalInstance.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/instance/SkeletalInstance.kt @@ -41,11 +41,11 @@ class SkeletalInstance( draw(shader) } - fun draw(light: RGBColor) { + fun draw(tint: RGBColor) { context.system.reset(faceCulling = false) val shader = context.skeletal.shader shader.use() - shader.light = light + shader.tint = tint draw(shader) } diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/shader/SkeletalShader.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/shader/SkeletalShader.kt index 9abd310ca..a1d2b3a40 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/shader/SkeletalShader.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/shader/SkeletalShader.kt @@ -15,9 +15,10 @@ package de.bixilon.minosoft.gui.rendering.skeletal.shader import de.bixilon.minosoft.data.text.formatting.color.ChatColors import de.bixilon.minosoft.gui.rendering.shader.types.AnimatedShader +import de.bixilon.minosoft.gui.rendering.shader.types.TintedShader import de.bixilon.minosoft.gui.rendering.system.base.buffer.uniform.FloatUniformBuffer import de.bixilon.minosoft.gui.rendering.system.base.shader.NativeShader -class SkeletalShader(native: NativeShader, buffer: FloatUniformBuffer) : BaseSkeletalShader(native, buffer), AnimatedShader { - var light by uniform("uLight", ChatColors.WHITE) { shader, name, value -> shader.setUInt(name, value.rgb) } +class SkeletalShader(native: NativeShader, buffer: FloatUniformBuffer) : BaseSkeletalShader(native, buffer), AnimatedShader, TintedShader { + override var tint by uniform("uTintColor", ChatColors.WHITE) { shader, name, value -> shader.setUInt(name, value.rgb) } } diff --git a/src/main/resources/assets/minosoft/rendering/shader/entities/player/player.vsh b/src/main/resources/assets/minosoft/rendering/shader/entities/player/player.vsh index 553530d51..f6ffd9dfa 100644 --- a/src/main/resources/assets/minosoft/rendering/shader/entities/player/player.vsh +++ b/src/main/resources/assets/minosoft/rendering/shader/entities/player/player.vsh @@ -21,7 +21,7 @@ out vec3 finFragmentPosition; uniform uint uIndexLayer; -uniform uint uLight; +uniform uint uTintColor; uniform uint uSkinParts; flat out uint finAllowTransparency; @@ -45,7 +45,7 @@ void main() { } finAllowTransparency = skinPart; run_skeletal(partTransformNormal, vinPosition); - vec4 light = getRGBColor(uLight & 0xFFFFFFu); + vec4 light = getRGBColor(uTintColor & 0xFFFFFFu); finTintColor *= light; finTextureIndex = uIndexLayer >> 28u; diff --git a/src/main/resources/assets/minosoft/rendering/shader/skeletal/normal/normal.vsh b/src/main/resources/assets/minosoft/rendering/shader/skeletal/normal/normal.vsh index 4eb4f26b3..e312773b6 100644 --- a/src/main/resources/assets/minosoft/rendering/shader/skeletal/normal/normal.vsh +++ b/src/main/resources/assets/minosoft/rendering/shader/skeletal/normal/normal.vsh @@ -28,12 +28,12 @@ layout (location = 3) in float vinIndexLayerAnimation;// texture index (0xF00000 #include "minosoft:color" -uniform uint uLight; +uniform uint uTintColor; void main() { run_skeletal(floatBitsToUint(vinTransformNormal), vinPosition); run_animation(); - finTintColor *= getRGBColor(uLight & 0xFFFFFFu); + finTintColor *= getRGBColor(uTintColor & 0xFFFFFFu); }