[SOLVED] Instancing skinned meshes


photo

Recommended Posts

Dear Unigine community,

 

I have been given access to the Unigine Developer Community as an evaluator. Thanks a ton.

 

I am eagerly browsing through lots of interesting, at times bewildering stuff.

 

A bit about the indie game I am working on.

 

It is a wargame set in 18th century Europe. The easiest way to describe it is to say that I am aiming for a Rome Total War clone. Don't know if I could make it, but hey, if I didn't try, I'll never know, right?

 

My soldier characters have 4 LOD levels.

 

*LOD 0 : Highest level of detail, 1000 polygons, skinned, animated, mesh. 1024x1024 diffuse, 1024x1024 normal and 1024x1024 specular textures.

 

*LOD 1 : Medium level of detail, 400 polygons, skinned, animated, mesh.

 

*LOD 2 : Low level of detail, 100 polygons, skinned, animated, mesh.

 

*LOD 3 : Impostor object using a 2D sprite.

 

 

I need thousands and thousands of soldier models to be rendered on screen at the same time as the camera pulls back. Of course at larger distances, the LOD gets progressively less complex until at some point the character transforms into a 2D impostor.

 

Guess what I am looking for is something like the following:

http://http.develope...gems3_ch02.html

 

I have gone through the Unigine development logs and found some interesting stuff related to instanced skinned meshes.

 

For example, see: http://unigine.com/d...g/2008/11/26/52

 

I quote:

"

November 26, 2008

Recent changes:

  • Instancing of skinned and dynamic meshes

Some notes on instancing follows. There is a pool for 64 bones drawn in once, so there is a huge speedup on skinned meshes with simple skeletons. Cloned ObjectMeshDymamic are also instanced, they are drawn by 32 in a batch. Plus there are some performance improvements in instancing of static meshes."

 

 

I have a few questions and was hoping that the gurus here would give me some pointers:

 

Qn1: Would Unigine (PC version) be able to render tens of thousands of animated characters using the currently available LOD and the skinned mesh instancing technique?

 

Qn2: If answer to qn 1 is yes, are there any available test results one could look at?

 

Thanks in advance.

 

Best Regards

S

Link to post

Q1: no, but no multi-purpose engine (even high-end CryEngine) can do this. Both the game and article you memtioned use very specialized/restricted crowd animation and rendering techniques

 

Q2: there are some Unigine walking character group skinned mesh samples. You could modify the script code to increase character count to get a feeling for performance requirements (but based on your expectation of 10000+ characters most probably you will be quite disappointed...)

Link to post

Ulf, hi!

 

What if I switch to sprites pretty early during the LOD switching?

Do you think if a major portion of the 10000+ characters are sprites, that would help?

Link to post

You definitely will have low performance in case of rendering 10000+ individual objects. The instancing performance of engine is 500-1500 KSurface per second (depending on scene and CPU). So performance of 10000 individual objects with shadows are rendered in deferred rendering mode is not better than 50fps (two geometry passes) and 25 fps in forward rendering mode (four geometry passes). You should group small series of your objects into the single one (four or more characters with minimal number of bones are inside the single skinned object). And you should always keep in mind the time of game update.

Link to post

Qn2: If answer to qn 1 is yes, are there any available test results one could look at?

You can easily check it with your own models: simply export your skinned mesh from any of the supported 3D editors and add into Unigine. Check the tutorial for how-to.

 

You can also run stress test samples for skinned meshes that are included into Evaluation kit (samples -> stress -> skinned_01) . However, in these meshes the number of bones is quite high (they have 46 bones). A a rough calculation: if you will use 10 bones in your characters, the performance can be up to 4x faster. In this case, instancing be more efficient, because the lower the number of bones, the higher the number of skinned meshes that can be stored in the instance data buffer to be drawn in one draw call.

 

In addition, you can enable the deferred rendering mode for lights (less precise, but less rendering passes that redraw geometry as well) and get some performance gain from that, as Frustum advised.

Link to post

Here is a screen from NVidia SDK Whitepaper 10.5 (year 2007, for GeForce 8* series, just the same as in your link):

post-26-0-32948200-1319628613_thumb.png

 

You can find working sample and sources here, convert them to Unigine and test on your hardware:

http://developer.dow...Instancing.html

 

 

So, generally it is possible, even on GF 8800 hardware. To achieve such results in Unigine you have to:

- create perfect LODs. use only one surface per object, minimal acceptable geometry, minimal number of bones;

- make sure that distant object don't drop or receive shadows, don't use alpha blending, glow, parallax, detail materials, etc.;

- use only ambient pass for distant objects (deferred pass could be skipped too but you have to imitate scattering somehow);

- deal with spatial tree issues (there would be a CPU-based bottleneck just like in some of stress samples);

 

I also do not recommend to use impostors cause they have descent quality and should be re-rendered too frequently to imitate real object animation. However it would be wise to use some kind of sprite billboards just as in SpeedTree. Unfortunately there is no native support for such billboards in Unigine and you'll have to blend their textures manually depending on view angle.

Link to post

Manguste, hi! Thanks for the pointers.

 

Does the following example show how to do instanced skinning?

Evaluation kit (samples -> stress -> skinned_01)

 

As an evaluator can I edit the skinned_01 code to bring my own LOD meshes in?

 

Thanks a ton for all the others who replied.

 

I am going through the answers.

Link to post

As far as I know, unigine does not support skinned mesh lod

Link to post

Hah! So skinned meshes in Unigine cannot use LOD system as of today! That's good to know. At least I now know where the engine stands presently.

Unigine team, are there any plans to implement this item in the near future?

Link to post

So skinned meshes in Unigine cannot use LOD system as of today

 

They can via multi-surface approach and animation layer en-/disabling as described in the work-around

Link to post

Ulf, hi!

 

Thanks for that clarification.

 

I read the following post by the Unigine Chief Technical Officer:

 

"Number of bones in skeleton is not a big bottleneck.

 

Approximately approach is: single skeleton with all bones and several surfaces with different number of triangles for different distances.

 

Major number of bones are finger bones, there is a way to disable them:

 

Finger bones should be excluded or have zero weight on distant surfaces.

Animation of fingers can be stored into the separate .sanim file, because of hierarchical skeleton.

Layer with finger bone animation can be disabled on far distances."

 

When applied to my project this translates to:

 

*Create 3 or 4 mesh LODs for soldier model. Have identical skeletal structure for all LODs. The animations will also be the same. But for less detailed LODs some animation groups (like finger animation) will be disabled.

 

*Enable all bone influences for LOD0. As you go down in LOD, decrease the number of bones affecting the skinning.

 

1* What happens to the diffuse, normal and specular textures for the character? At LOD 0, they are all 1024 by 1024. Is there a mechanism for using smaller textures on less detailed LOD meshes?

 

2* Would I be able to test this all out (with just my evaluator license) using the scripts exposed in the evaluation kit (samples -> stress -> skinned_01)?

 

Thanks once again for your patience. I see that you routinely help out newbies like me on the forum (There is, after all, a reason for the Hero member status, I guess :) )

Link to post

1* What happens to the diffuse, normal and specular textures for the character? At LOD 0, they are all 1024 by 1024. Is there a mechanism for using smaller textures on less detailed LOD meshes?

 

You can assign different materials to each LOD specific mesh surface. Therefore it would be possible to use smaller textures for LOD's > 0 by defining multiple materials. But I don't think this would give you any benefit. Normally using single material with texture atlas with mipmaps should work fine for all LODs.

 

Texturing performance will definitely not be the bottleneck for your application. I would expect that you will be totally CPU-bound.

 

2* Would I be able to test this all out (with just my evaluator license) using the scripts exposed in the evaluation kit (samples -> stress -> skinned_01)?

 

Does the evaluation licence includes exporters for 3DS/Maya ? Initial challenge of your project would be multi-surface skinned mesh character export from one of these modelling tools. If this is possible than you should be able to test it with the evaluation SDK as there are no scripting restrictions as far as I know

Link to post
You definitely will have low performance in case of rendering 10000+ individual objects. The instancing performance of engine is 500-1500 KSurface per second (depending on scene and CPU). So performance of 10000 individual objects with shadows are rendered in deferred rendering mode is not better than 50fps (two geometry passes) and 25 fps in forward rendering mode (four geometry passes). You should group small series of your objects into the single one (four or more characters with minimal number of bones are inside the single skinned object). And you should always keep in mind the time of game update.

 

Frustum, hi!

 

You say the instancing performance of the engine is 500 to 1500 KSurfaces per second.

 

*Do I interpret this as 1500 kilo surfaces per second? Or was this a typo?

 

*If we go by 1500 surfaces max, how many triangles could each surface have? Because, per my understanding, a surface in Unigine is a mesh. My soldier mesh is a single surface and has 1000 quads (2000 triangles) at LOD 0.

 

*I am looking at the code under C:\Unigine Evaluation Kit\data\samples\stress.

In particular the file "skinned_01.cpp"

 

This is what I see:

for(int y = -size, i = 0; y <= size; y++) {

for(int x = -size; x <= size; x++, i++) {

ObjectMeshSkinned mesh = add_editor(new ObjectMeshSkinned("samples/stress/meshes/skinned_01.smesh"));

mesh.setWorldTransform(Mat4(translate(x,y,0.0f) * rotateZ(90.0f)));

mesh.setMaterial(get_mesh_material(x ^ y),"*");

mesh.setProperty("surface_base","*");

mesh.setLoop(1);

mesh.setTime(i * mesh.getNumFrames() * 0.25f);

mesh.setSpeed(25.0f);

mesh.play();

num++;

}

}

 

Is there instanced skinning code anywhere here? Or am I missing something?

Link to post
You can assign different materials to each LOD specific mesh surface. Therefore it would be possible to use smaller textures for LOD's > 0 by defining multiple materials. But I don't think this would give you any benefit. Normally using single material with texture atlas with mipmaps should work fine for all LODs. Texturing performance will definitely not be the bottleneck for your application. I would expect that you will be totally CPU-bound. Does the evaluation licence includes exporters for 3DS/Maya ? Initial challenge of your project would be multi-surface skinned mesh character export from one of these modelling tools. If this is possible than you should be able to test it with the evaluation SDK as there are no scripting restrictions as far as I know

 

I looked at my eval package. Exporters for 3DS Max are available. But I can't seem to find any skinned instancing example anywhere.

May be I am looking at the wrong spot? :)

Link to post

Yep 1500 kilo surfaces per second is a CPU bottleneck. Top GPU's able to render approximately 500 million of triangles per second. The overall performance depends on your content complexity. You shouldn't do any additional action to activate hardware instancing. Render performs the instancing automatically for the same object surfaces with the same materials.

00000.png

00001.png

00002.png

00003.png

Link to post