skeletal: pack normal and transform in same float, use includes

This commit is contained in:
Moritz Zwerger 2023-10-26 16:06:04 +02:00
parent d574203bdf
commit 1d02603637
No known key found for this signature in database
GPG Key ID: 5CAD791931B09AC4
9 changed files with 127 additions and 54 deletions

View File

@ -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)

View File

@ -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<EntityRen
fun add(entity: Entity) {
try {
renderers.lock.lock()
val renderer = entity.createRenderer(this.renderer) ?: return
val renderer = if (entity is EntityModelFactory<*>) entity.create(this.renderer) else entity.type.modelFactory?.nullCast<RegisteredEntityModelFactory<Entity>>()?.create(this.renderer, entity) ?: return
entity.renderer?.let { onReplace(it) }
this.renderers.unsafe.put(entity, renderer)?.let { onReplace(it) }
} finally {

View File

@ -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<Entity>(renderer, entity) {
companion object : EntityModelFactory<Entity> {
override fun create(renderer: EntitiesRenderer, entity: Entity) = DummyEntityRenderer(renderer, entity)
}
}
class DummyEntityRenderer(renderer: EntitiesRenderer, entity: Entity) : EntityRenderer<Entity>(renderer, entity)

View File

@ -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<E : PlayerEntity>(renderer: EntitiesRenderer, entity: E) : EntityRenderer<E>(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<PlayerEntity>, Identified {

View File

@ -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)

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* This software is not affiliated with Mojang AB, the original developer of Minecraft.
*/
layout (std140) uniform uSkeletalBuffer
{
mat4 uSkeletalTransforms[TRANSFORMS];
};

View File

@ -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 <https://www.gnu.org/licenses/>.
*
* 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;
}

View File

@ -30,5 +30,4 @@ out vec4 foutColor;
void main() {
run_animation();
run_animation();
}

View File

@ -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;