[2.1] Morph animations on Linux
-
- Halfling
- Posts: 83
- Joined: Sun Feb 21, 2010 4:58 pm
- x 28
[2.1] Morph animations on Linux
I am in the process of preparing a PR to merge my morph animations implementation on the v2-1 branch so I am testing it on Linux and then will write the HLSL shaders in Windows (and clean up the PR because the previous one had unrelated stuff included). However I'm facing a problem. On Linux the vertex ids seem to be messed up somehow. The way the morph animations work is that I create a tex buffer containing the vertex data for each pose (up to 4). Then in the vertex shader I use gl_VertexID to find the morphed position of the current vertex. It works correctly on macOS (which is where I originally developed this) but now on Linux, after much debugging, it seems that gl_VertexID is not what I expected it to be. Using RenderDoc I could verify that the vertex ids of the mesh are really weird, like, big numbers such as something between 7000 and 8000 for a mesh with a bit over 800 vertices and I believe this must be the source of the problem. Why's that? I guess only dark_sylinc could possibly help me on this!
Btw I'm also on different machine, completely different hardware.
Thanks
Btw I'm also on different machine, completely different hardware.
Thanks
- dark_sylinc
- OGRE Team Member
- Posts: 5299
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1279
- Contact:
Re: [2.1] Morph animations on Linux
Hi!
I'm away so I'll be quick. HLSL & GLSL have a small divergence that explains this behavior:
SV_VertexID always starts from 0.
gl_VertexID starts from baseVertex value which we pass to glDraw* calls. This value is often out of your control
macOS uses an old OpenGL version which doesn't use baseVertex (thus rendering is slower), but as a side effect, your code works.
I had this problem in Colibri and fixed it by sending baseVertex in worldMaterialIdx (shader section, C++ section) and subtract it.
This should be provided by Ogre, but well, it's not an often used feature yet.
The value in stock Ogre can be seen in RenderQueue's firstVertexIndex.
I'm away so I'll be quick. HLSL & GLSL have a small divergence that explains this behavior:
SV_VertexID always starts from 0.
gl_VertexID starts from baseVertex value which we pass to glDraw* calls. This value is often out of your control
macOS uses an old OpenGL version which doesn't use baseVertex (thus rendering is slower), but as a side effect, your code works.
I had this problem in Colibri and fixed it by sending baseVertex in worldMaterialIdx (shader section, C++ section) and subtract it.
This should be provided by Ogre, but well, it's not an often used feature yet.
The value in stock Ogre can be seen in RenderQueue's firstVertexIndex.
-
- Halfling
- Posts: 83
- Joined: Sun Feb 21, 2010 4:58 pm
- x 28
Re: [2.1] Morph animations on Linux
Thank you so much! Subtracting the baseVertex from the gl_VertexID fixes the problem. However I can't use worldMaterialIdx.w because that's where the pose weights are stored. I am testing it with the z component for now but z is used by hlms_fine_light_mask which I'm not really familiar with. Since we are limited to only this vector to pass per-instance data I have no idea what I could do differently here.
-
- Halfling
- Posts: 83
- Joined: Sun Feb 21, 2010 4:58 pm
- x 28
Re: [2.1] Morph animations on Linux
So I have found this older post where you shared some ideas viewtopic.php?f=25&t=93695&p=539587#p539585
I am gonna read that over again and study the code and figure out other way to send the morph data into the GPU. I like the idea of using the worldMatBuf. I need to store the vertex count, base vertex id, and weights. In this case I can store more than 4 weights with full precision. Will post updates on my progress later.
I am gonna read that over again and study the code and figure out other way to send the morph data into the GPU. I like the idea of using the worldMatBuf. I need to store the vertex count, base vertex id, and weights. In this case I can store more than 4 weights with full precision. Will post updates on my progress later.
- Ybalrid
- Halfling
- Posts: 89
- Joined: Thu Jul 10, 2014 6:52 pm
- Location: France
- x 31
- Contact:
Re: [2.1] Morph animations on Linux
I'm happy to see that work is being done to support morph targets on v2 objects!
xissburg, I saw that you had a PR up for a while on bitbucket. I'm really interested by this. Morph target are the only missing feature to be able to fully load everything defined in a glTF asset while only working with Ogre::Item.
Once you submit your branch again, I'll be glad to help to find any issue, and start integrating it in Ogre_glTF.
xissburg, I saw that you had a PR up for a while on bitbucket. I'm really interested by this. Morph target are the only missing feature to be able to fully load everything defined in a glTF asset while only working with Ogre::Item.
Once you submit your branch again, I'll be glad to help to find any issue, and start integrating it in Ogre_glTF.
Ogre_glTF Ogre v2-1 GLTF2 loader : topic link github repo
BtOgre21 Fork of btOgre, for Ogre v2-1 : topic link github repo
OIS Current maintainer : Official repository
Annwvyn VR focused game engine using Ogre : https://github.com/Ybalrid/Annwvyn https://annwvyn.org/
BtOgre21 Fork of btOgre, for Ogre v2-1 : topic link github repo
OIS Current maintainer : Official repository
Annwvyn VR focused game engine using Ogre : https://github.com/Ybalrid/Annwvyn https://annwvyn.org/
-
- Halfling
- Posts: 83
- Joined: Sun Feb 21, 2010 4:58 pm
- x 28
Re: [2.1] Morph animations on Linux
@Ybalrid I'm currently working on this. I got to figure out the hard part I guess, now I just gotta write the remaining shaders (HLSL, Metal needs to be updated, GLSL ES) and create a clean PR. I'm hoping to wrap this up this weekend.
I'm also interested in glTF and saw your work on the importer but I still haven't tried it. I'll be more than happy to help incorporate this into it.
I'm also interested in glTF and saw your work on the importer but I still haven't tried it. I'll be more than happy to help incorporate this into it.
- Ybalrid
- Halfling
- Posts: 89
- Joined: Thu Jul 10, 2014 6:52 pm
- Location: France
- x 31
- Contact:
Re: [2.1] Morph animations on Linux
morph targets are pretty simple in glTF, they are stored as delta from the base mesh for each vertex as their position/normal/tangent, and node as a series of weights.
Weights can be animated as a "scalar" animation channel.
The API just needs to expose a way to be able to, by hand either after, or while loading the vertex data, specify the arrays of vectors described above, and to store modifications of weighs through animations.
The rest should be pretty easy to do.
glTF specs specify that a compliant client should support at minimum:
- 8 targets containing only positions
- 4 targets containing positions and normals
- 2 targets containing position, normals, and tangents.
(more of this can be done, but probably require doing the blending in "software", meaning on the CPU because it's start to be too much data to send to a vertex shader... )
Of course, we can be relaxed on this. When you say you can have up to 4 morph target, and the data is stored in a texture buffer, what do you have exactly there? vertex positions only? with normal vectors? more?
Weights can be animated as a "scalar" animation channel.
The API just needs to expose a way to be able to, by hand either after, or while loading the vertex data, specify the arrays of vectors described above, and to store modifications of weighs through animations.
The rest should be pretty easy to do.
glTF specs specify that a compliant client should support at minimum:
- 8 targets containing only positions
- 4 targets containing positions and normals
- 2 targets containing position, normals, and tangents.
(more of this can be done, but probably require doing the blending in "software", meaning on the CPU because it's start to be too much data to send to a vertex shader... )
Of course, we can be relaxed on this. When you say you can have up to 4 morph target, and the data is stored in a texture buffer, what do you have exactly there? vertex positions only? with normal vectors? more?
Ogre_glTF Ogre v2-1 GLTF2 loader : topic link github repo
BtOgre21 Fork of btOgre, for Ogre v2-1 : topic link github repo
OIS Current maintainer : Official repository
Annwvyn VR focused game engine using Ogre : https://github.com/Ybalrid/Annwvyn https://annwvyn.org/
BtOgre21 Fork of btOgre, for Ogre v2-1 : topic link github repo
OIS Current maintainer : Official repository
Annwvyn VR focused game engine using Ogre : https://github.com/Ybalrid/Annwvyn https://annwvyn.org/
-
- Halfling
- Posts: 83
- Joined: Sun Feb 21, 2010 4:58 pm
- x 28
Re: [2.1] Morph animations on Linux
This is where the poses are imported from a V1 mesh https://bitbucket.org/xissburg/ogre/src ... #lines-626
Currently it only imports vertex positions, well, actually they're offsets/delta from the original vertex positions. I'll have to extend it to support normals later. All vertex offsets of all poses are stored in a single tex buffer. This is a static buffer. Later that buffer is bound to slot #4 https://bitbucket.org/xissburg/ogre/src ... lines-2381
The dynamic data for the pose animation such as weights is passed inside the worldMatBuf, right after the skeletal animation matrices if any. Currently it only supports 4 poses because I'm passing a single float4, but it's entirely possible to increase that number indefinitely.
Pose weights are set on the Renderable https://bitbucket.org/xissburg/ogre/src ... #lines-150
On a SubItem you can set the weight by name https://bitbucket.org/xissburg/ogre/src ... #lines-107
Currently it only imports vertex positions, well, actually they're offsets/delta from the original vertex positions. I'll have to extend it to support normals later. All vertex offsets of all poses are stored in a single tex buffer. This is a static buffer. Later that buffer is bound to slot #4 https://bitbucket.org/xissburg/ogre/src ... lines-2381
The dynamic data for the pose animation such as weights is passed inside the worldMatBuf, right after the skeletal animation matrices if any. Currently it only supports 4 poses because I'm passing a single float4, but it's entirely possible to increase that number indefinitely.
Pose weights are set on the Renderable https://bitbucket.org/xissburg/ogre/src ... #lines-150
On a SubItem you can set the weight by name https://bitbucket.org/xissburg/ogre/src ... #lines-107
- Ybalrid
- Halfling
- Posts: 89
- Joined: Thu Jul 10, 2014 6:52 pm
- Location: France
- x 31
- Contact:
Re: [2.1] Morph animations on Linux
Just make sure that I can also give this data to a v2 submesh without constructing a v1 mesh firstxissburg wrote: βSat May 25, 2019 9:31 pm This is where the poses are imported from a V1 mesh https://bitbucket.org/xissburg/ogre/src ... #lines-626
Ogre_glTF Ogre v2-1 GLTF2 loader : topic link github repo
BtOgre21 Fork of btOgre, for Ogre v2-1 : topic link github repo
OIS Current maintainer : Official repository
Annwvyn VR focused game engine using Ogre : https://github.com/Ybalrid/Annwvyn https://annwvyn.org/
BtOgre21 Fork of btOgre, for Ogre v2-1 : topic link github repo
OIS Current maintainer : Official repository
Annwvyn VR focused game engine using Ogre : https://github.com/Ybalrid/Annwvyn https://annwvyn.org/
-
- Halfling
- Posts: 83
- Joined: Sun Feb 21, 2010 4:58 pm
- x 28
- Ybalrid
- Halfling
- Posts: 89
- Joined: Thu Jul 10, 2014 6:52 pm
- Location: France
- x 31
- Contact:
Re: [2.1] Morph animations on Linux
Exactly in the same way the vertex buffer are obtained. But you know, any interface where I can give you an array of 3D vectors (or just like an array of floats, with 3* the number of vertices) per blend shape is good.
Ogre_glTF Ogre v2-1 GLTF2 loader : topic link github repo
BtOgre21 Fork of btOgre, for Ogre v2-1 : topic link github repo
OIS Current maintainer : Official repository
Annwvyn VR focused game engine using Ogre : https://github.com/Ybalrid/Annwvyn https://annwvyn.org/
BtOgre21 Fork of btOgre, for Ogre v2-1 : topic link github repo
OIS Current maintainer : Official repository
Annwvyn VR focused game engine using Ogre : https://github.com/Ybalrid/Annwvyn https://annwvyn.org/
-
- Halfling
- Posts: 83
- Joined: Sun Feb 21, 2010 4:58 pm
- x 28
Re: [2.1] Morph animations on Linux
I have finished the implementation of morph animations and submitted a pull request. I am still not sure what would be the ideal interface for your glTF importer. Can you show me some code? Where in your project you'd make the invocation? What data do you have exactly? Are positions and normals separate or interleaved?
- Ybalrid
- Halfling
- Posts: 89
- Joined: Thu Jul 10, 2014 6:52 pm
- Location: France
- x 31
- Contact:
Re: [2.1] Morph animations on Linux
They are separate arrays, but they can be interleaved, it doesn't really matter.xissburg wrote: βSun Jun 02, 2019 1:25 amI have finished the implementation of morph animations and submitted a pull request. I am still not sure what would be the ideal interface for your glTF importer. Can you show me some code? Where in your project you'd make the invocation? What data do you have exactly? Are positions and normals separate or interleaved?
https://github.com/Ybalrid/Ogre_glTF/bl ... er.cpp#L61
The above link it the function that actuall load the mesh data, morph target are similar-ish to that. I'm rebuilding the arrays by hand for the vertex positions/normals/uv coordinates/bone index/blend weights.
Each "primitive" in a glTF asset can contains an array of "targets". Each target is composed of arrays of vector 3 that represent the morph target's delta (intended to be added to the base mesh, scaled by a weight between 0.0 and 1.1). These delta are obviously relative to the mesh original data. At minimum a morph target is composed of the vertex positions, but can also contains vertex normal and vertex tangents arrays.
The interface you exposes isn't really important, I can adapt to anything, at it's core for me a target is just vectors of floats that are intended to be grouped by 3. Just make sure there's a some way of adding morph targets to a submesh and that will be good
Ogre_glTF Ogre v2-1 GLTF2 loader : topic link github repo
BtOgre21 Fork of btOgre, for Ogre v2-1 : topic link github repo
OIS Current maintainer : Official repository
Annwvyn VR focused game engine using Ogre : https://github.com/Ybalrid/Annwvyn https://annwvyn.org/
BtOgre21 Fork of btOgre, for Ogre v2-1 : topic link github repo
OIS Current maintainer : Official repository
Annwvyn VR focused game engine using Ogre : https://github.com/Ybalrid/Annwvyn https://annwvyn.org/
-
- Halfling
- Posts: 83
- Joined: Sun Feb 21, 2010 4:58 pm
- x 28
Re: [2.1] Morph animations on Linux
I have forked your repo and wrote the morph animation support and a demo (https://github.com/xissburg/Ogre_glTF/tree/morph). It's not gonna work with the official 2.1 because my pull request has not been merged yet so you'd need my fork to make it run (https://bitbucket.org/xissburg/ogre/src/v2-1-morph/). I will continue to make changes and fixing bugs over the next few days because I want to use glTF in my project.Ybalrid wrote: βMon Jun 03, 2019 10:09 pm The interface you exposes isn't really important, I can adapt to anything, at it's core for me a target is just vectors of floats that are intended to be grouped by 3. Just make sure there's a some way of adding morph targets to a submesh and that will be good
- Ybalrid
- Halfling
- Posts: 89
- Joined: Thu Jul 10, 2014 6:52 pm
- Location: France
- x 31
- Contact:
Re: [2.1] Morph animations on Linux
No way!! This is super awesome!xissburg wrote: βSun Jun 09, 2019 5:28 amI have forked your repo and wrote the morph animation support and a demo (https://github.com/xissburg/Ogre_glTF/tree/morph). It's not gonna work with the official 2.1 because my pull request has not been merged yet so you'd need my fork to make it run (https://bitbucket.org/xissburg/ogre/src/v2-1-morph/). I will continue to make changes and fixing bugs over the next few days because I want to use glTF in my project.Ybalrid wrote: βMon Jun 03, 2019 10:09 pm The interface you exposes isn't really important, I can adapt to anything, at it's core for me a target is just vectors of floats that are intended to be grouped by 3. Just make sure there's a some way of adding morph targets to a submesh and that will be good
I'm going to check that out later! Thanks a lot! You, and this whole community, are absolutely amazing!
Edit: I'm okay with optional support for the v2-1 fork and maintaining that available with a compilation switch. Once things gets a bit more stable, I'll try to find the best way to actually integrate that. Probably by adding CMake option...
Ogre_glTF Ogre v2-1 GLTF2 loader : topic link github repo
BtOgre21 Fork of btOgre, for Ogre v2-1 : topic link github repo
OIS Current maintainer : Official repository
Annwvyn VR focused game engine using Ogre : https://github.com/Ybalrid/Annwvyn https://annwvyn.org/
BtOgre21 Fork of btOgre, for Ogre v2-1 : topic link github repo
OIS Current maintainer : Official repository
Annwvyn VR focused game engine using Ogre : https://github.com/Ybalrid/Annwvyn https://annwvyn.org/
- dark_sylinc
- OGRE Team Member
- Posts: 5299
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1279
- Contact:
Re: [2.1] Morph animations on Linux
Is there any update in regards to morph targets in 2.2?
I don't want 2.1 and 2.2 to diverge too much; thus I may end up porting 2.1's morph code to 2.2; compute version can come later
I don't want 2.1 and 2.2 to diverge too much; thus I may end up porting 2.1's morph code to 2.2; compute version can come later
-
- Halfling
- Posts: 83
- Joined: Sun Feb 21, 2010 4:58 pm
- x 28
Re: [2.1] Morph animations on Linux
I haven't looked into that yet and I don't think I will be doing that any soon since I haven't ported my code to 2.2 yet. Though I am still interested in implementing the compute-based morph. Sorry but no ETA on that.dark_sylinc wrote: βSat Sep 14, 2019 10:54 pm Is there any update in regards to morph targets in 2.2?
I don't want 2.1 and 2.2 to diverge too much; thus I may end up porting 2.1's morph code to 2.2; compute version can come later
-
- Halfling
- Posts: 83
- Joined: Sun Feb 21, 2010 4:58 pm
- x 28
Re: [2.1] Morph animations on Linux
@dark_sylinc By the way, I'm still wondering what it'd be like to implement this using compute shaders... I guess the concept is to have an array of all non-zero displacements and a corresponding array of vertex indices and then have a compute shader take that plus the vertex buffer as input, apply the displacements onto the vertex positions (normals, tangents...) and then we have to use that output as the input vertex buffer when rendering. Do you have any idea how that'd be done in Ogre? Which facilities would be involved? I'm specially curious about the last step: how to use the output from the compute shader as the vertex buffer for the draw call?dark_sylinc wrote: βSat Sep 14, 2019 10:54 pm Is there any update in regards to morph targets in 2.2?
Thanks
- dark_sylinc
- OGRE Team Member
- Posts: 5299
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1279
- Contact:
Re: [2.1] Morph animations on Linux
It could be done in several ways, but the most simple and compatible way is an algorithm that would be somewhat like this:
Alternatively it may be more efficient to do something like this (because previous algorithm requires one dispatch per active morph animation, an that means the GPU has micro stalls):
There may be smart ways to avoid the atomic_add, but there will always be trade offs.
Obviously it would be even more efficient to output the final vertex buffer in Compute Shader, so that the vertex shader just consumes it, instead of generating outDisplacement, for the vertex shader to add vertex[vertexId] + outDisplacement[vertexId]; however this adds a ton of complexity:
Ogre allows you to bind an UavBufferPacked directly (UAVs are always read/write) to the vertex shader, or to reinterpret it as a TexBufferPacked (i.e. read only) via UavBufferPacked::getAsTexBufferView.
You can take a look at OgreVctVoxelizer.cpp and OgreVctLighting.cpp which use the compute shaders Voxelizer_piece_cs.any and LightVctBounceInject_piece_cs.any respectively.
OgreVctVoxelizer.cpp actually has multiple steps where the output of step0 is used as input of step1.
It does that due to the reasons I mentioned (we can't read VertexBufferPacked nor IndexBufferPacked* directly, dealing with arbitrary vertex formats is insane, so we decompress everything to floats).
(*) We can't because Ogre doesn't currently support doing that.
You don't really need to do that, because what I'm asking doesn't really need to read vertex nor index buffers. It just needs to read an input of morph targets (one entry per displacement, each morph animation can have its own length), and outputs a single array of displacements (one entry per vertex), you can keep everything as float3 (or half3 or whatever). You're in full control of that data.
This scheme wastes GPU resources if only one morph animation is active at all times, but it should be a win when lots of animations are active concurrently.
Code: Select all
float3 outDisplacement[vertex_count]; //Initialized to zero
float3 displacements[morph_count];
uint16 *affectedIndices[morph_count]; //or uint32
void main( uint threadId )
{
affectedIdx = affectedIndices[threadId];
outDisplacement[idx] += displacements[threadId];
//outDisplacement will be used by the vertex shader
}
Code: Select all
const int num_morph_count = morph_count0 + morph_count1 + ... + morph_countN;
float3 outDisplacement[vertex_count]; //Initialized to zero
float3 displacements[num_morph_count];
uint16 *affectedIndices[num_morph_count]; //or uint32
void main( uint threadId )
{
affectedIdx = affectedIndices[threadId];
//Multiple threads may write to the same outDisplacement[idx]
atomic_add( outDisplacement[idx], displacements[threadId] );
}
Obviously it would be even more efficient to output the final vertex buffer in Compute Shader, so that the vertex shader just consumes it, instead of generating outDisplacement, for the vertex shader to add vertex[vertexId] + outDisplacement[vertexId]; however this adds a ton of complexity:
- Ogre right now doesn't allow reinterpretting UAVs as vertex buffer (IIRC it is possible, but there are some API woes to solve/workaround)
- The compute shader would have to know how to decode a vertex declaration: It needs to know how to handle float3, half3, short3, etc and vertex stride. This makes things complex
Compute Shaders output values to UAVs. You'll need an UavBufferPacked. For example 'outDisplacement' would actually be an UavBufferPacked.
Ogre allows you to bind an UavBufferPacked directly (UAVs are always read/write) to the vertex shader, or to reinterpret it as a TexBufferPacked (i.e. read only) via UavBufferPacked::getAsTexBufferView.
You can take a look at OgreVctVoxelizer.cpp and OgreVctLighting.cpp which use the compute shaders Voxelizer_piece_cs.any and LightVctBounceInject_piece_cs.any respectively.
OgreVctVoxelizer.cpp actually has multiple steps where the output of step0 is used as input of step1.
- AabbCalcultor_piece_cs.any is ran and calculates an AABB
- AabbWorldSpace_piece_cs.any uses that AABB and transforms it to world space
- Voxelizer_piece_cs.any performs the main task, using the transformed AABBs as an optimization to skip voxels
It does that due to the reasons I mentioned (we can't read VertexBufferPacked nor IndexBufferPacked* directly, dealing with arbitrary vertex formats is insane, so we decompress everything to floats).
(*) We can't because Ogre doesn't currently support doing that.
You don't really need to do that, because what I'm asking doesn't really need to read vertex nor index buffers. It just needs to read an input of morph targets (one entry per displacement, each morph animation can have its own length), and outputs a single array of displacements (one entry per vertex), you can keep everything as float3 (or half3 or whatever). You're in full control of that data.
This scheme wastes GPU resources if only one morph animation is active at all times, but it should be a win when lots of animations are active concurrently.
- dark_sylinc
- OGRE Team Member
- Posts: 5299
- Joined: Sat Jul 21, 2007 4:55 pm
- Location: Buenos Aires, Argentina
- x 1279
- Contact:
Re: [2.1] Morph animations on Linux
I finally merged 2.1 into 2.2; thus pose animations were ported to 2.2
It was MUCH easier than I thought. I thought it would take a lot of time, but it was done in no time.
I tested GL, Linux and D3D11 Windows. I haven't tested Metal yet.
It was MUCH easier than I thought. I thought it would take a lot of time, but it was done in no time.
I tested GL, Linux and D3D11 Windows. I haven't tested Metal yet.
- Ybalrid
- Halfling
- Posts: 89
- Joined: Thu Jul 10, 2014 6:52 pm
- Location: France
- x 31
- Contact:
Re: [2.1] Morph animations on Linux
Morph targets now merged in 2.2??! I think I should start dusting Ogre_glTF and bring it to 2.2!
Ogre_glTF Ogre v2-1 GLTF2 loader : topic link github repo
BtOgre21 Fork of btOgre, for Ogre v2-1 : topic link github repo
OIS Current maintainer : Official repository
Annwvyn VR focused game engine using Ogre : https://github.com/Ybalrid/Annwvyn https://annwvyn.org/
BtOgre21 Fork of btOgre, for Ogre v2-1 : topic link github repo
OIS Current maintainer : Official repository
Annwvyn VR focused game engine using Ogre : https://github.com/Ybalrid/Annwvyn https://annwvyn.org/