Post news Report RSS 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 on

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 - - 1,044 comments

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

Reply Good karma Bad karma+1 vote
jeffr Author
jeffr - - 383 comments

Not with efficient texture atlases for shadow maps

Reply Good karma+2 votes
Ichiman94
Ichiman94 - - 522 comments

awesome, but the lighting on objects is same?

Reply Good karma Bad karma+2 votes
pfannkuchen_gesicht
pfannkuchen_gesicht - - 520 comments

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

Wiki: En.wikipedia.org

Reply Good karma Bad karma+2 votes
SneakySoft
SneakySoft - - 340 comments

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...

Reply Good karma Bad karma+2 votes
geostigma
geostigma - - 30 comments

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

Reply Good karma Bad karma+3 votes
Elementalist
Elementalist - - 732 comments

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

Reply Good karma Bad karma+4 votes
vessedeloup
vessedeloup - - 72 comments

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.

Reply Good karma Bad karma+3 votes
Croco15
Croco15 - - 1,240 comments

Cool.

Reply Good karma Bad karma+1 vote
Dra6o0n
Dra6o0n - - 534 comments

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...

Reply Good karma Bad karma+1 vote
liqid
liqid - - 13 comments

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

Reply Good karma Bad karma+2 votes
Jonu
Jonu - - 26 comments

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.

Reply Good karma Bad karma+1 vote
AlekZanDer
AlekZanDer - - 2,695 comments

Nice.

Reply Good karma Bad karma+1 vote
Post a comment

Your comment will be anonymous unless you join the community. Or sign in with your social account: