From 1d026036370ca3dcfdf97e41026f37d02903fccc Mon Sep 17 00:00:00 2001 From: Moritz Zwerger Date: Thu, 26 Oct 2023 16:06:04 +0200 Subject: [PATCH] skeletal: pack normal and transform in same float, use includes --- .../entities/entities/player/PlayerEntity.kt | 4 -- .../entities/EntityRendererManager.kt | 5 +- .../entities/renderer/DummyEntityRenderer.kt | 8 +-- .../renderer/player/PlayerRenderer.kt | 53 +++++++++++++++++++ .../rendering/skeletal/mesh/SkeletalMesh.kt | 14 +++-- .../shader/includes/skeletal/buffer.glsl | 18 +++++++ .../shader/includes/skeletal/shade.glsl | 38 +++++++++++++ .../rendering/shader/skeletal/skeletal.fsh | 1 - .../rendering/shader/skeletal/skeletal.vsh | 40 +++----------- 9 files changed, 127 insertions(+), 54 deletions(-) create mode 100644 src/main/resources/assets/minosoft/rendering/shader/includes/skeletal/buffer.glsl create mode 100644 src/main/resources/assets/minosoft/rendering/shader/includes/skeletal/shade.glsl diff --git a/src/main/java/de/bixilon/minosoft/data/entities/entities/player/PlayerEntity.kt b/src/main/java/de/bixilon/minosoft/data/entities/entities/player/PlayerEntity.kt index 67da2a3f5..b08888499 100644 --- a/src/main/java/de/bixilon/minosoft/data/entities/entities/player/PlayerEntity.kt +++ b/src/main/java/de/bixilon/minosoft/data/entities/entities/player/PlayerEntity.kt @@ -36,9 +36,6 @@ import de.bixilon.minosoft.data.registries.item.items.dye.DyeableItem import de.bixilon.minosoft.data.registries.shapes.aabb.AABB import de.bixilon.minosoft.data.text.formatting.color.ChatColors import de.bixilon.minosoft.data.text.formatting.color.RGBColor -import de.bixilon.minosoft.gui.rendering.entities.EntitiesRenderer -import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer -import de.bixilon.minosoft.gui.rendering.entities.renderer.player.PlayerRenderer import de.bixilon.minosoft.gui.rendering.util.vec.vec3.Vec3dUtil.EMPTY import de.bixilon.minosoft.physics.entities.living.player.PlayerPhysics import de.bixilon.minosoft.protocol.network.connection.play.PlayConnection @@ -139,7 +136,6 @@ abstract class PlayerEntity( } override fun createPhysics(): PlayerPhysics<*> = PlayerPhysics(this) - override fun createRenderer(renderer: EntitiesRenderer): EntityRenderer<*> = PlayerRenderer(renderer, this) fun swingHand(hand: Hands) { val arm = hand.getArm(mainArm) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/EntityRendererManager.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/EntityRendererManager.kt index 4154cb748..fc7479a2b 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/EntityRendererManager.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/EntityRendererManager.kt @@ -13,12 +13,15 @@ package de.bixilon.minosoft.gui.rendering.entities +import de.bixilon.kutil.cast.CastUtil.nullCast import de.bixilon.kutil.collections.iterator.async.ConcurrentIterator import de.bixilon.kutil.collections.map.LockMap import de.bixilon.kutil.concurrent.lock.simple.SimpleLock import de.bixilon.kutil.concurrent.pool.ThreadPool import de.bixilon.kutil.observer.set.SetObserver.Companion.observeSet import de.bixilon.minosoft.data.entities.entities.Entity +import de.bixilon.minosoft.gui.rendering.entities.factory.EntityModelFactory +import de.bixilon.minosoft.gui.rendering.entities.factory.RegisteredEntityModelFactory import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer import de.bixilon.minosoft.util.logging.Log import de.bixilon.minosoft.util.logging.LogLevels @@ -46,7 +49,7 @@ class EntityRendererManager(val renderer: EntitiesRenderer) : Iterable) entity.create(this.renderer) else entity.type.modelFactory?.nullCast>()?.create(this.renderer, entity) ?: return entity.renderer?.let { onReplace(it) } this.renderers.unsafe.put(entity, renderer)?.let { onReplace(it) } } finally { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/DummyEntityRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/DummyEntityRenderer.kt index 77aec7a52..2f411ce94 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/DummyEntityRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/DummyEntityRenderer.kt @@ -15,11 +15,5 @@ package de.bixilon.minosoft.gui.rendering.entities.renderer import de.bixilon.minosoft.data.entities.entities.Entity import de.bixilon.minosoft.gui.rendering.entities.EntitiesRenderer -import de.bixilon.minosoft.gui.rendering.entities.factory.EntityModelFactory -class DummyEntityRenderer(renderer: EntitiesRenderer, entity: Entity) : EntityRenderer(renderer, entity) { - - companion object : EntityModelFactory { - override fun create(renderer: EntitiesRenderer, entity: Entity) = DummyEntityRenderer(renderer, entity) - } -} +class DummyEntityRenderer(renderer: EntitiesRenderer, entity: Entity) : EntityRenderer(renderer, entity) diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/player/PlayerRenderer.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/player/PlayerRenderer.kt index 3cf145295..1c6597bba 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/player/PlayerRenderer.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/entities/renderer/player/PlayerRenderer.kt @@ -14,15 +14,68 @@ package de.bixilon.minosoft.gui.rendering.entities.renderer.player import de.bixilon.minosoft.data.entities.entities.player.PlayerEntity +import de.bixilon.minosoft.data.entities.entities.player.properties.PlayerProperties +import de.bixilon.minosoft.data.entities.entities.player.properties.textures.metadata.SkinModel import de.bixilon.minosoft.data.registries.identified.Identified import de.bixilon.minosoft.data.registries.identified.Namespaces.minecraft import de.bixilon.minosoft.gui.rendering.entities.EntitiesRenderer import de.bixilon.minosoft.gui.rendering.entities.factory.RegisteredEntityModelFactory +import de.bixilon.minosoft.gui.rendering.entities.feature.SkeletalFeature import de.bixilon.minosoft.gui.rendering.entities.renderer.EntityRenderer import de.bixilon.minosoft.gui.rendering.models.loader.ModelLoader import de.bixilon.minosoft.gui.rendering.models.loader.SkeletalLoader.Companion.sModel +import de.bixilon.minosoft.gui.rendering.skeletal.baked.BakedSkeletalModel +import de.bixilon.minosoft.gui.rendering.system.base.texture.skin.PlayerSkin +import java.util.* open class PlayerRenderer(renderer: EntitiesRenderer, entity: E) : EntityRenderer(renderer, entity) { + private var properties: PlayerProperties? = null + private var registered = false + + + override fun update(millis: Long) { + if (registered) return + val update = updateProperties() + + val model = getModel() + + val instance = model?.createInstance(renderer.context) ?: return + this.registered = true + + this.features += SkeletalFeature(this, instance) + } + + private fun updateProperties(): Boolean { + val properties = entity.additional.properties + + if (this.properties == properties) return false + unload() + this.properties = properties + return true + } + + open fun getSkin(): PlayerSkin? { + return renderer.context.textures.skins.default[UUID.randomUUID()] // TODO + // val properties = this.properties?.textures?.skin + // if(properties == null){ + // return renderer.context.textures.skins.getSkin(entity, properties, ) + //} + } + + + open fun getModel(): BakedSkeletalModel? { + val skin = getSkin() ?: return null + val name = when (skin.model) { + SkinModel.WIDE -> WIDE + SkinModel.SLIM -> SLIM + } + return renderer.context.models.skeletal[name] + + + val properties = this.properties + val model = properties?.textures?.skin?.metadata?.model ?: SkinModel.WIDE // TODO: failover according + + } companion object : RegisteredEntityModelFactory, Identified { diff --git a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/mesh/SkeletalMesh.kt b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/mesh/SkeletalMesh.kt index c655f2250..3cbd46f86 100644 --- a/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/mesh/SkeletalMesh.kt +++ b/src/main/java/de/bixilon/minosoft/gui/rendering/skeletal/mesh/SkeletalMesh.kt @@ -25,13 +25,13 @@ import de.bixilon.minosoft.gui.rendering.util.mesh.MeshStruct class SkeletalMesh(context: RenderContext, initialCacheSize: Int) : Mesh(context, SkeletalMeshStruct, initialCacheSize = initialCacheSize), SkeletalConsumer { override val order = context.system.quadOrder - private fun addVertex(position: FaceVertexData, positionOffset: Int, uv: FaceVertexData, uvOffset: Int, transform: Float, normal: Float, textureShaderId: Float) { + private fun addVertex(position: FaceVertexData, positionOffset: Int, uv: FaceVertexData, uvOffset: Int, transformNormal: Float, textureShaderId: Float) { data.add( position[positionOffset + 0], position[positionOffset + 1], position[positionOffset + 2], uv[uvOffset + 0], uv[uvOffset + 1], - transform, normal, + transformNormal, + textureShaderId, ) - data.add(textureShaderId) } private fun encodePart(part: Float): Int { @@ -48,12 +48,11 @@ class SkeletalMesh(context: RenderContext, initialCacheSize: Int) : Mesh(context } override fun addQuad(positions: FaceVertexData, uv: FaceVertexData, transform: Int, normal: Vec3, texture: ShaderTexture) { - val transform = transform.buffer() + val transformNormal = ((transform shl 12) or encodeNormal(normal)).toFloat() val textureShaderId = texture.shaderId.buffer() - val normal = encodeNormal(normal).buffer() order.iterate { position, uvIndex -> - addVertex(positions, position * Vec3.length, uv, uvIndex * Vec2.length, transform, normal, textureShaderId) + addVertex(positions, position * Vec3.length, uv, uvIndex * Vec2.length, transformNormal, textureShaderId) } } @@ -61,8 +60,7 @@ class SkeletalMesh(context: RenderContext, initialCacheSize: Int) : Mesh(context data class SkeletalMeshStruct( val position: Vec3, val uv: Vec2, - val transform: Int, - val normal: Int, + val transformNormal: Int, val indexLayerAnimation: Int, ) { companion object : MeshStruct(SkeletalMeshStruct::class) diff --git a/src/main/resources/assets/minosoft/rendering/shader/includes/skeletal/buffer.glsl b/src/main/resources/assets/minosoft/rendering/shader/includes/skeletal/buffer.glsl new file mode 100644 index 000000000..254bb760d --- /dev/null +++ b/src/main/resources/assets/minosoft/rendering/shader/includes/skeletal/buffer.glsl @@ -0,0 +1,18 @@ +/* + * Minosoft + * Copyright (C) 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. + */ + + +layout (std140) uniform uSkeletalBuffer +{ + mat4 uSkeletalTransforms[TRANSFORMS]; +}; diff --git a/src/main/resources/assets/minosoft/rendering/shader/includes/skeletal/shade.glsl b/src/main/resources/assets/minosoft/rendering/shader/includes/skeletal/shade.glsl new file mode 100644 index 000000000..69d2161a1 --- /dev/null +++ b/src/main/resources/assets/minosoft/rendering/shader/includes/skeletal/shade.glsl @@ -0,0 +1,38 @@ +/* + * Minosoft + * Copyright (C) 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. + */ + +float decodeNormal(uint data) { + return (data / 15.0f) * 2.0f - 1.0f; +} + +vec3 decodeNormal(float normal) { + uint combined = floatBitsToUint(normal); + uint x = combined & 0x0Fu; + uint y = combined >> 8u & 0x0Fu; + uint z = combined >> 4u & 0x0Fu; + return vec3(decodeNormal(x), decodeNormal(y), decodeNormal(z)); +} + +vec3 transformNormal(vec3 normal, mat4 transform) { + // return normalize(mat3(transpose(inverse(transform))) * normal); + return mat3(transform) * normal; +} + +float getShade(vec3 normal) { + if (normal.y < -0.5f) return 0.5f; + if (normal.y > 0.5f) return 1.0f; + if (normal.x < -0.5f || normal.x > 0.5f) return 0.6f; + if (normal.z < -0.5f || normal.z > 0.5f) return 0.8f; + + return 1.0f; +} diff --git a/src/main/resources/assets/minosoft/rendering/shader/skeletal/skeletal.fsh b/src/main/resources/assets/minosoft/rendering/shader/skeletal/skeletal.fsh index e7bb06c55..10a03852e 100644 --- a/src/main/resources/assets/minosoft/rendering/shader/skeletal/skeletal.fsh +++ b/src/main/resources/assets/minosoft/rendering/shader/skeletal/skeletal.fsh @@ -30,5 +30,4 @@ out vec4 foutColor; void main() { run_animation(); - run_animation(); } diff --git a/src/main/resources/assets/minosoft/rendering/shader/skeletal/skeletal.vsh b/src/main/resources/assets/minosoft/rendering/shader/skeletal/skeletal.vsh index 3aeaf867a..59396d88a 100644 --- a/src/main/resources/assets/minosoft/rendering/shader/skeletal/skeletal.vsh +++ b/src/main/resources/assets/minosoft/rendering/shader/skeletal/skeletal.vsh @@ -15,19 +15,15 @@ layout (location = 0) in vec3 vinPosition; layout (location = 1) in vec2 vinUV; -layout (location = 2) in float vinTransform; -layout (location = 3) in float vinNormal; -layout (location = 4) in float vinIndexLayerAnimation;// texture index (0xF0000000), texture layer (0x0FFFF000), animation index (0x00000FFF) +layout (location = 2) in float vinTransformNormal; // transform (0x7F000), normal (0xFFF) +layout (location = 3) in float vinIndexLayerAnimation;// texture index (0xF0000000), texture layer (0x0FFFF000), animation index (0x00000FFF) #include "minosoft:animation/header_vertex" uniform mat4 uViewProjectionMatrix; -layout (std140) uniform uSkeletalBuffer -{ - mat4 uSkeletalTransforms[TRANSFORMS]; -}; +#include "minosoft:skeletal/buffer" uniform uint uLight; @@ -36,37 +32,15 @@ uniform uint uLight; #include "minosoft:animation/main_vertex" -float decodeNormal(uint data) { - return (data / 15.0f) * 2.0f - 1.0f; -} +#include "minosoft:skeletal/shade" -vec3 decodeNormal() { - uint combined = floatBitsToUint(vinNormal); - uint x = combined & 0x0Fu; - uint y = combined >> 8u & 0x0Fu; - uint z = combined >> 4u & 0x0Fu; - return vec3(decodeNormal(x), decodeNormal(y), decodeNormal(z)); -} - -vec3 transformNormal(vec3 normal, mat4 transform) { - // return normalize(mat3(transpose(inverse(transform))) * normal); - return mat3(transform) * normal; -} - -float getShade(vec3 normal) { - if (normal.y < -0.5f) return 0.5f; - if (normal.y > 0.5f) return 1.0f; - if (normal.x < -0.5f || normal.x > 0.5f) return 0.6f; - if (normal.z < -0.5f || normal.z > 0.5f) return 0.8f; - - return 1.0f; -} void main() { - mat4 transform = uSkeletalTransforms[floatBitsToUint(vinTransform)]; + uint transformNormal = floatBitsToInt(vinTransform); + mat4 transform = uSkeletalTransforms[(transformNormal >> 12u) & 0x7F]; vec4 position = transform * vec4(vinPosition, 1.0f); gl_Position = uViewProjectionMatrix * position; - vec3 normal = transformNormal(decodeNormal(), transform); + vec3 normal = transformNormal(decodeNormal(vinNormal & 0xFFF), transform); finTintColor = getLight(uLight & 0xFFu) * vec4(vec3(getShade(normal)), 1.0f); finFragmentPosition = position.xyz;