Some of you may remember a thread where I started going off topic with a new instancing system.
Well, here is the first (WIP) patch!
The system is not complete, but these are the major advantages over the current InstanceGeometry system:
- Individual instances are controlled through "InstancedEntity", which, from the outside, behave almost like a regular Entity. They're MovableObjects, so they're supposed to work with SceneNodes.
- Dynamic bounding box calculation. Takes into account which instances are currently in the scene (i.e. 1 out of 100 instances is attached to a scene node, shrink the bbox to enclose only that instance).
- Dynamic bbox calculation hides the whole batch if no entity is visible, even though all of them combined would appear to Ogre as if it were visible. This saves render calls (i.e. the camera is looking between A & B, a combined bbox would think there's something in the middle that should be visible. InstanceManager takes care of this situation)
- When using hardware skeletal animation (in the case of ShaderBased technique) the same vertex shader can be used for instanced and non-instanced entities! This makes possible switching between systems flawlessly.
- No need to worry about the 80 (or less) entities-per-batch-or-else-your-system-crashes problem. InstanceManager takes care automatically this for you.
- Setup the InstanceManager given a base Mesh once, then start requesting as many InstancedEntity(s) as you want, the system automatically handles creating and organizing more batches for you.
- Extensible system: By deriving from "InstanceBatch", other instancing systems can be supported. Currently there's only one implementaion (ShaderBased) which is the same InstancedGeometry uses.
- Less GPU VRAM usage since batches share the same vertex & index buffers.
There are a couple of known issues of course:
- Other techniques (including HW instancing) are planned, but not yet implemented
- Only the first sub mesh from the given base mesh is considered.
- Weird/rarely used features from meshes can cause the build process to fail (i.e. submeshes using "shared" vertex buffers from the mesh)
- No LOD support. Although this is somewhat useless because if you're using instancing, this means you have a CPU bottleneck, and LOD aims at GPU bottlenecks
- 16-bit indices are used, so watch out if vertexCount * numInstances exceeds 65535 FIXED
Differences between Entity and InstancedEntity:
- Setting RenderQueueGroup and other Renderable stuff works at InstanceBatch level, not InstancedEntity. This is obviously a limitation from instancing in general, not this particular implementation
I am uploading the patch and a very simple test application which I've been using. So be patient if you don't see any link within the first 10 minutes this post was made
The test shows 10000 robot.mesh staying still in a scene with a very minimal shader, the ratio is 10 fps vs 20 fps (yahoo!!) and 540 fps for the VTF technique. I'll make a much more mind blowing sample (for inclusiong with the Sample tests) when the system is more mature. Besides the test will show the different instancing techniques, but so far only one is supported.
Edit: Here's the source code of instance test (Release mode binaries included)
Ok, this was supposed to be experimental; but I haven't had more time to spend on it, and surprisingly it's working great. I post it here because there's a lot of people asking for this feature.
The code below shows how to create instance a mesh that contains multiple submeshes. Beware, it needs creating multiple instance managers, and it may be harmful for instancing if you don't understand the effects of having multiple submeshes.
The following technique has the advantage of consuming less RAM & resources than just creating the instance managers alone:
Code: Select all
//I load the mesh now to get the number of submeshes.
MeshPtr mesh = Ogre::MeshManager::getSingleton().load( "myMesh.mesh", Ogre::ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME )
//Create one instance mgr per submesh, managerNames contains unique random names
for( int i=0; i<mesh->getNumSubMeshes(); ++i )
InstanceManager mgr = mSceneMgr->createInstanceManager( managerNames[i], "myMesh.mesh", ResourceGroupManager::AUTODETECT_RESOURCE_GROUP_NAME, technique, numInstancesPerBatch, IM_USEALL, i );
SceneNode *sceneNode; //I assume it's valid, create only ONE.
ents.reserve( mesh->getNumSubMeshes() );
//materialNames contains the names of the instancing materials for each sub mesh.
for( size_t j=0; j<mesh->getNumSubMeshes(); ++j )
InstancedEntity *instEnt = mSceneMgr->createInstancedEntity( materialNames[j], managerNames[j] );
sceneNode->attachObject( instEnt );
ents.push_back( instEnt );
//This function will tell the other entities to use the resources from the first entity. Saves RAM & CPU
if( j != 0 )
if( !ents[j]->shareTransformWith( ents ) )
//If we get here, the instanced entity doesn't have a skeleton to share or the technique selected doesn't support skeletal animation
Not really pretty, I know; but it's the best I've got. Take in mind this is experimental, that's why I didn't even make a sample showing how to do it. It may not fully work.
If it's worth mentioning, I've been using it for 2 months and no problems so far (well, a few of them arose, but they were fixed).
It can't be that bad, as one user here figured out how to make it work on it's own