[2.1] Morph animations on Linux

Discussion area about developing with Ogre-Next (2.1, 2.2 and beyond)


Post Reply
xissburg
Halfling
Posts: 83
Joined: Sun Feb 21, 2010 4:58 pm
x 28

[2.1] Morph animations on Linux

Post by xissburg »

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
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: [2.1] Morph animations on Linux

Post by dark_sylinc »

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.
xissburg
Halfling
Posts: 83
Joined: Sun Feb 21, 2010 4:58 pm
x 28

Re: [2.1] Morph animations on Linux

Post by xissburg »

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.
xissburg
Halfling
Posts: 83
Joined: Sun Feb 21, 2010 4:58 pm
x 28

Re: [2.1] Morph animations on Linux

Post by xissburg »

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.
User avatar
Ybalrid
Halfling
Posts: 89
Joined: Thu Jul 10, 2014 6:52 pm
Location: France
x 31
Contact:

Re: [2.1] Morph animations on Linux

Post by Ybalrid »

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.
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/
xissburg
Halfling
Posts: 83
Joined: Sun Feb 21, 2010 4:58 pm
x 28

Re: [2.1] Morph animations on Linux

Post by xissburg »

@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.
User avatar
Ybalrid
Halfling
Posts: 89
Joined: Thu Jul 10, 2014 6:52 pm
Location: France
x 31
Contact:

Re: [2.1] Morph animations on Linux

Post by Ybalrid »

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?
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/
xissburg
Halfling
Posts: 83
Joined: Sun Feb 21, 2010 4:58 pm
x 28

Re: [2.1] Morph animations on Linux

Post by xissburg »

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
User avatar
Ybalrid
Halfling
Posts: 89
Joined: Thu Jul 10, 2014 6:52 pm
Location: France
x 31
Contact:

Re: [2.1] Morph animations on Linux

Post by Ybalrid »

xissburg 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
Just make sure that I can also give this data to a v2 submesh without constructing a v1 mesh first ;-)
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/
xissburg
Halfling
Posts: 83
Joined: Sun Feb 21, 2010 4:58 pm
x 28

Re: [2.1] Morph animations on Linux

Post by xissburg »

Ybalrid wrote: ↑Sat May 25, 2019 10:04 pm Just make sure that I can also give this data to a v2 submesh without constructing a v1 mesh first ;-)
What would be the ideal interface for you? How are the buffers obtained from glTF?
User avatar
Ybalrid
Halfling
Posts: 89
Joined: Thu Jul 10, 2014 6:52 pm
Location: France
x 31
Contact:

Re: [2.1] Morph animations on Linux

Post by Ybalrid »

xissburg wrote: ↑Sun May 26, 2019 4:47 pm
Ybalrid wrote: ↑Sat May 25, 2019 10:04 pm Just make sure that I can also give this data to a v2 submesh without constructing a v1 mesh first ;-)
What would be the ideal interface for you? How are the buffers obtained from glTF?
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/
xissburg
Halfling
Posts: 83
Joined: Sun Feb 21, 2010 4:58 pm
x 28

Re: [2.1] Morph animations on Linux

Post by xissburg »

Ybalrid wrote: ↑Sun May 26, 2019 8:42 pm 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.
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?
User avatar
Ybalrid
Halfling
Posts: 89
Joined: Thu Jul 10, 2014 6:52 pm
Location: France
x 31
Contact:

Re: [2.1] Morph animations on Linux

Post by Ybalrid »

xissburg wrote: ↑Sun Jun 02, 2019 1:25 am
Ybalrid wrote: ↑Sun May 26, 2019 8:42 pm 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.
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?
They are separate arrays, but they can be interleaved, it doesn't really matter.

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/
xissburg
Halfling
Posts: 83
Joined: Sun Feb 21, 2010 4:58 pm
x 28

Re: [2.1] Morph animations on Linux

Post by xissburg »

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 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.
User avatar
Ybalrid
Halfling
Posts: 89
Joined: Thu Jul 10, 2014 6:52 pm
Location: France
x 31
Contact:

Re: [2.1] Morph animations on Linux

Post by Ybalrid »

xissburg wrote: ↑Sun Jun 09, 2019 5:28 am
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 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.
No way!! This is super awesome! :shock: :D

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/
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: [2.1] Morph animations on Linux

Post by dark_sylinc »

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
xissburg
Halfling
Posts: 83
Joined: Sun Feb 21, 2010 4:58 pm
x 28

Re: [2.1] Morph animations on Linux

Post by xissburg »

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
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.
xissburg
Halfling
Posts: 83
Joined: Sun Feb 21, 2010 4:58 pm
x 28

Re: [2.1] Morph animations on Linux

Post by xissburg »

dark_sylinc wrote: ↑Sat Sep 14, 2019 10:54 pm Is there any update in regards to morph targets in 2.2?
@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?

Thanks
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: [2.1] Morph animations on Linux

Post by dark_sylinc »

It could be done in several ways, but the most simple and compatible way is an algorithm that would be somewhat like this:

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
}
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):

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] );
}
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 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
xissburg wrote: ↑Thu Sep 19, 2019 3:45 pmDo 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?
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.
  1. AabbCalcultor_piece_cs.any is ran and calculates an AABB
  2. AabbWorldSpace_piece_cs.any uses that AABB and transforms it to world space
  3. Voxelizer_piece_cs.any performs the main task, using the transformed AABBs as an optimization to skip voxels
Note that OgreVctVoxelizer.cpp takes an Item, downloads its vertex and index buffers to the CPU and uploads them again to the GPU. Actually the index buffer is copied GPU -> GPU.
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.
User avatar
dark_sylinc
OGRE Team Member
OGRE Team Member
Posts: 5296
Joined: Sat Jul 21, 2007 4:55 pm
Location: Buenos Aires, Argentina
x 1278
Contact:

Re: [2.1] Morph animations on Linux

Post by dark_sylinc »

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.
User avatar
Ybalrid
Halfling
Posts: 89
Joined: Thu Jul 10, 2014 6:52 pm
Location: France
x 31
Contact:

Re: [2.1] Morph animations on Linux

Post by Ybalrid »

Morph targets now merged in 2.2??! I think I should start dusting Ogre_glTF and bring it to 2.2! :D
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/
Post Reply