Themes
Report article RSS Feed Fast object instancing

When I was testing out character shadows on Hale's Riverhurst level, the framerate was not as smooth as I would like it to be. To remedy this, I'm taking a few days to make the engine handle complex scenes more efficiently.

Posted by jeffr on Dec 8th, 2009

When I was testing out character shadows on Hale's Riverhurst level, the framerate was not as smooth as I would like it to be. To remedy this, I'm taking a few days to make the engine handle complex scenes more efficiently.

My first step was to create a system for fast object instancing (copy-drawing). Because of our modular plants and buildings, most Overgrowth levels consist of many instances (copies) of relatively few unique models, so this is an important feature to optimize. As an example, Riverhurst contains about 4000 instances of the same wooden plank model.

Trees are also very good candidates for fast instancing. Here is one of the trees in Overgrowth:


As you can see in the bottom-left of the screenshot, the framerate is very smooth: 90 frames per second. However, if I create a few dozen more trees, the framerate drops down to 14 -- unacceptably low.


This is because the renderer is not taking advantage of the fact that the trees are using the same model. The rendering algorithm looks much like this:

code:
for each object in scene {  
  setup rendering state  
  setup shader  
  setup texture  
  setup vertex arrays  
  setup transform  
  draw  
}

This is a problem, because for simple models like this tree, the setup code takes much more time than the actual drawing. This is compounded by the fact that the tree is actually a collection of even simpler objects!


I decided to restructure the rendering loop to look more like this:

code:
for each object-type in scene {  
  setup rendering state
  setup shader  
  setup texture  
  setup vertex arrays  
  for each object in object-type {
    setup transform  
    draw  
  }  
}

The drawing itself is already as fast as possible, since it's just drawing a vertex buffer object with one line of code, but I further optimized the "setup transform" step by encoding the transformation matrix in the texture coordinates (aka GLSL pseudo-instancing).

Now we can draw that same group of trees at 90 frames per second!


It's still possible to slow the framerate down, but it takes many more trees than before:


Shadows are disabled in these pictures because I'm currently working on efficient texture atlases for shadow maps.

This kind of optimization may seem premature, but I think it's necessary so that we can see what level designs are technologically possible. When planning out the story and gameplay, it's important to know whether or not dense forest scenes and complex town scenes can be rendered smoothly.

Do you have any ideas about further optimizations I could do, or any questions about how the object instancing works?(permalink)



Track us
on ModDB (visit our page)

Please join us here too:
Facebook icon ModDB icon Steam icon Twitter icon YouTube icon

Post comment Comments
Varsity
Varsity Dec 8 2009, 10:26am says:

Doesn't this mean that all the instances will have identical lighting?

+1 vote     reply to comment
jeffr
jeffr Dec 8 2009, 1:23pm replied:

Not with efficient texture atlases for shadow maps

+2 votes     reply to comment
Ichiman94
Ichiman94 Dec 8 2009, 11:00am says:

awesome, but the lighting on objects is same?

+2 votes     reply to comment
pfannkuchen_gesicht
pfannkuchen_gesicht Dec 8 2009, 12:05pm replied:

no, but I don't know why/how to explain

Wiki: En.wikipedia.org

+2 votes     reply to comment
SneakySoft
SneakySoft Dec 8 2009, 11:44am says:

So is it possible with this technique to give every model a different scale and rotation? I would think so, but I still want to know for sure :)

I don't really like the tree model btw...

+2 votes     reply to comment
geostigma
geostigma Dec 8 2009, 12:47pm replied:

Yes you can have a different scale, rotation and lighting. Think of it like inheritance, you can have the same method called once but all the objects are scattered in an array list and individually being instanced with certain data such as position

+3 votes     reply to comment
Elementalist
Elementalist Dec 8 2009, 12:55pm says:

Haha, I like this approach. Instead of telling your mapper to make a better optimized map, you just optimize the entire engine. Nice. :P

+4 votes     reply to comment
vessedeloup
vessedeloup Dec 8 2009, 12:57pm says:

Nice!
I follow your posts with great interest and I look forward to playing the completed game.

Your tree doesn't seem too healthy though.

I understand you may want this tundra look with only a few branches, so a good way to make it look WAY better without lowering the frame rate too much would be to complexify the model for the trunk.

Otherwise it just looks like a big branch/stick planted in the ground.

+3 votes     reply to comment
Croco15
Croco15 Dec 8 2009, 4:41pm says:

Cool.

+1 vote     reply to comment
Dra6o0n
Dra6o0n Dec 9 2009, 1:08am says:

Isn't it possible to mirror all the models (not including shadows, which is applied separately) so that all the trees are actually redirected from 1 source and is like a "illusion" of a tree?

In reality, if you take a tree and put a mirror next to it, you get to see two trees that's mirrored and reflected.

Then to apply that to the game, you'd have to somehow grab the model and put it in that area, and have it not eat away the fps.

Since it's a "mirrored" object, it should only take up resources for the mirror itself...

And here I am going on into things I don't understand, as the more sense I try to make of what I say the more complex it gets...

+1 vote     reply to comment
liqid
liqid Dec 9 2009, 5:26am replied:

The idea is good. There is something along that way. Not a mirror, but it's called impostors and is used to render clouds and volumetrics for example [1].
How it works is, you basically render a complex object onto a texture and put that texture onto a sprite. As you get closer, you only update the sprite every now and then, saving render time. Getting closer still, you'll have to substitute it for a real model, though. This way rendering objects (particularly trees) which are far way can be sped up a lot.

[1] Markmark.net

+2 votes     reply to comment
Jonu
Jonu Dec 10 2009, 2:13am says:

Could you make Level of detail model for trees farther away consisting of one plane that is always facing you? The old trick that they used back in the days.

+1 vote     reply to comment
AlekZanDer
AlekZanDer Dec 13 2009, 10:06am says:

Nice.

+1 vote     reply to comment
Post a Comment
click to sign in

You are not logged in, your comment will be anonymous unless you join the community today (totally free - or sign in with your social account on the right) which we encourage all contributors to do.

2000 characters limit; HTML formatting and smileys are not supported - text only

News
Browse
News
Report Abuse
Report article
Related Games
Overgrowth
Overgrowth Indie Single & Multiplayer Adventure
Related Engines
Custom Built
Custom Built Commercial Released Sep 1, 2007
Related Groups
Wolfire Games
Wolfire Games Developer & Publisher with 3 members