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.
- 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
- [s]16-bit indices are used, so watch out if vertexCount * numInstances exceeds 65535[/s] 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

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.
Cheers
Dark Sylinc
Edit: Here's the source code of instance test (Release mode binaries included)
Update 05/06/2011:
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.
std::vector<InstancedEntity*> ents;
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[0] ) )
{
//If we get here, the instanced entity doesn't have a skeleton to share or the technique selected doesn't support skeletal animation
}
}
If it's worth mentioning, I've been using it for 2 months and no problems so far

It can't be that bad, as one user here figured out how to make it work on it's own
