Sign in to follow this  

Managing instancing

This topic is 1350 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

Hi,
 
Currently my engine only supports instancing in a few limited cases, and I'm trying to fix that by implementing a more generic system.
 
When do engines usually find objects that can be instanced? Dynamically every frame after culling? Or at a "higher-level" by keeping a list of objects that use the same model?
 
Currently my scene struct looks like this:
 

struct Scene
{
    uint             num_actors;
    InstanceData*    actors_instance_data;
    uint*            actors_node_handles; //handles of actors' scene graph node(used to get world matrix)
    Model**          actors_models;
    BoundingSphere** bounding_spheres;
};

I could do it every frame after culling, by sorting the actors by model and if two actors a and use the same model (actors_models[a] == actors_models[b]) then they can be instanced by copying actors_instance_data[a] and actors_instance_data[b] to a constant buffer.

 

Does this seem reasonable or should I go with a "higher level" option?

 

Thanks.

Share this post


Link to post
Share on other sites
I was going to do what LS is suggesting -- sort my draws (and filter redundant states) then merge consecutive draws and dynamically build the instance buffer.

But I ended up doing what you're describing in the OP - after culling, sort model instances by model asset (and material), then submit the submeshes of each asset to the render queue once (for each material).
Each high level drawing system (such as this ModelRenderer) has to come up with its own logic to make use of it.

I may still try out the other version eventually, but I went with this way to begin with so I could make no assumptions at the lowest level about what kinds of per-instance data the user might want - such as from vertex buffer streams, cbuffers with VertexId, both at once, etc... The lowest level of my renderer is supposed to be a general purpose GPU API, like D3D/GL, without much magic.

Share this post


Link to post
Share on other sites

Battlefield 3 way is to use instancing for everything. Just pack every draw call related data to single tbuffer. Then each instanced draw call needs just start index and instance size. Then shader can manually fetch up needed data and everything is simple and clean.

Share this post


Link to post
Share on other sites

We do everything at level build time based on the assets used in that level. The artists pick from different mesh assets from a database, and place instances of them in the level. Then when we build the level we figure out which mesh assets are used, and where the instances are located. Then we build dedicated data structures for each mesh that are optimized for submitted a list of currently visible instances at runtime.

Share this post


Link to post
Share on other sites
Sign in to follow this