Hi Michael,
How would I set it up for instanced drawing?
My guess is that I would need to write a node-visitor that collects all
of the geometry -> drawables and sets them up to use the instanced call
overload instead of the default. I have tried doing this, but my
implementation has gotten pretty complex, and I want to make sure there
isn't a more simple way I have overlooked.
You've got the right idea for the general way to apply instanced
rendering for complex objects. But you can simplify usage by making your
model simpler.
Draw instanced will work really well if your model consists of a single
primitiveset. So ideally you'll have your modeler create the tree in a
single geometry with a single primitiveset. They can make a texture
atlas so that the same texture file applies to the whole geometry, and
then merge all the geometry into a single one.
If this is not possible, you can try using the osgUtil::Optimizer to do
this for you as a pre-process. Using the artist's model as input, you
would apply the SHARE_DUPLICATE_STATE, FLATTEN_STATIC_TRANSFORMS,
MERGE_GEODES, MERGE_GEOMETRY, VERTEX_PRETRANSFORM, VERTEX_POSTTRANSFORM,
INDEX_MESH and possibly TEXTURE_ATLAS_BUILDER optimizers on it. I use
this combination on all models by the way, in combination with a few
custom visitors it does wonders to cull and draw times. What these will do:
TEXTURE_ATLAS_BUILDER: Will merge many small textures into a single
larger one, adjusting texture coordinates, which can then be shared by
all those nodes. An artist-created texture atlas is better though, I've
seen cases where the texture atlas builder in OSG will create a really
large texture and use less than half the space in it, and other such
inefficiencies. A human will also be better equipped to judge of the
qualitative criteria in making some textures smaller thus fitting more
textures into a single atlas.
SHARE_DUPLICATE_STATE: Make sure identical state is shared (uses the
same pointer to the same object) instead of having multiple state
attributes with the same value throughout your model. You might have to
write a small visitor to help this optimizer a bit, essentially
normalizing all state that your modeling tool might set differently from
what you expect, but which has no effect on the final output. For
example you could force all geometry to single sided, etc. The idea is
to make sure the next steps will be able to merge as much as possible.
FLATTEN_STATIC_TRANSFORMS: Remove any transforms that are marked as
static data variance. You might have to make a small visitor that will
change the data variance to static on any transforms that you don't
really need. Modeling programs have a tendency to put lots of transforms
all over the place (in Maya for example, there are no groups, everything
is a transform, even graph leaves are a transform plus a geometry...).
Again this will make the next steps work more efficiently, because
things that are separated by a transform can't be merged together. You
might want to write another simple visitor that would remove unnecessary
Group nodes. Once again things that are separated by a Group can't be
merged together.
MERGE_GEODES, MERGE_GEOMETRY: Merge as many scene graph leaves together
as possible. Again this will make the next steps work more efficiently.
Note that the MERGE_GEODES optimizer in OSG has a pretty serious "design
flaw", it will only merge Geodes whose direct parent is a Group, and not
any Group subclass. Sure, merging the children of an LOD node or Switch
node is bad, but there are plenty of other subclass es of Group where it
makes no difference. So I just subclassed the MergeGeodesVisitor so it
checks the actual type of the parent, doesn't merge if it's certain
types of Group subclasses (like LOD or Switch) but merges in all other
cases.
VERTEX_PRETRANSFORM, VERTEX_POSTTRANSFORM, INDEX_MESH: This is a
powerful trio of optimizers that will turn DrawArrays into DrawElements
optimized for the GPU's cache, and merge all primitivesets under a
Geometry together. After this, you might want to run the MERGE_GEODES
and MERGE_GEOMETRY optimizers again, as they will be able to merge even
more things together.
So anyways, I described why you would want to use the various optimizers
for general models, but for your trees the goal is to end up with a
single Geometry which has a single primitiveset. Then your job of doing
instanced drawing of this tree becomes much easier. And again, if you
can get your artist / modeler to make the model with this in mind, all
the better. In general, if you can massage the data in order to make the
code simpler, it's normally a win in the long run.
Hope this helps,
J-S
--
______________________________________________________
Jean-Sebastien Guay jean-sebastien.g...@cm-labs.com
http://www.cm-labs.com/
http://whitestar02.dyndns-web.com/
_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org