Closed vpenades closed 4 years ago
Hi! I use SharpGLTF to export game character models, and implementing morphing would be a great help to me in regards to facial flexes. My current method of exporting relies on creating new meshes for each morph target, but natively support morphing would remove the need for that and allow me to bring morphs wherever they need be. While I don't technically need it, having it would be a big help and reduce the hassle of having to apply morphs by hand.
If you would like my assistance in testing, I would be glad to help. Otherwise, I hope you can figure out a good solution to this issue that doesn't cause much development stress. Thank you for reading.
Hi
It will take a while until I face the morphing issue, since I still have to figure out how to solve several problems.
One of them is how to arrange the vertex attributes; by default, sharpGLTF stores all vertex buffers in interleaved mode, so the GPU only needs to bind a single vertex buffer and a single index buffer to render the geometry. Historically this has always been the most optimized way to store a vertex buffer, although I have seen some debate about it recently. Furthermore, if you use the CreateMeshes(*)
method, it creates a single vertex and index buffer for all meshes, which helps reducing the number of GPU command calls.
Vertex Buffers with morph targets are a different story. I asked around about how actual 3D engines handle morphing at the GPU level, and I always get the answer, which is:
Morph targets are binded as vertex attributes and interpolated by the vertex shader
But that would mean that 2 or 3 morph targets would be allowed, since there's a maximum limit of 16 attributes per vertex, and that's not realistic, since gltf does not impose a maximum number of morph targets; I've been told there's gltf around with more than 100 morph targets.
So when meshes use morph targets, it seems a different kind of attribute and vertex buffers layout is required, but haven't figured out yet the optimal layout that would make most engines happy.
@BlockBuilder57 The morph targets building API is nearly finished and will be available in the next package release.
Morph targets are quite tricky to implement because MeshBuilder might split a given vertex multiple times if the vertex is used inside multiple primitives, (for example a vertex in a materials boundary).
Also, MeshBuilder is a last stage utility class and it doesn't calculate normals and tangents by itself, so if a mesh has normals and tangents, you must also provide normals and tangents for the morpth targets too!
Oh, awesome! That's exactly what I wanted to hear, actually! I have normals for each morph already queued up. I don't know if Blender actually supports per-morph normals yet, but once the API is finished I will implement it in my tool and let you how it works and report any bugs I find. Again, let me know if there's anything I can do to assist in testing.
Thanks for implementing this!
@BlockBuilder57 morph support has been added to Alpha-12 which has just been published.
Now you can add morph targets to a mesh builder, see example here.
Hi again, been working on my tool some more and just got morphs working, but so far I've been unable to find a way to add names to the morph targets. I'm guessing this something that's already in and I'm completely glossing over, so I'm just adding another comment to this to avoid another issue. If it's not, I can go ahead and make a new issue.
Hi!
As far as I know, there is no standard way of setting morph target names.
This is also being discussed here: https://github.com/KhronosGroup/glTF/issues/1036
I've been considering different options to provide morphing support for MeshBuilder... adding support for morphing targets would add a lot of complexity to the API and to the underlaying code, and I am not sure if it's worth the burden, given that morphing is a feature that is rearely used.
Also, MeshBuilder is designed to play nice with gltf, by creating strided vertex buffers from the very beginning.
But, in gltf, I think the vertex buffers layout is slightly different than standard stride when morphing is supported.
So, given these contraints, I believe the best approach would be to create a new class called MeshBuilderMorphModifier that would encapsulate static MeshBuilders, adding the extra methods for morphing.
Additionally, a CreateMorphableMeshes would be required to fill them in the destination model. this would allow to create separate vertex buffers for the geometry fragments.