1
\$\begingroup\$

[Edit: I found an answer - see below]

I have a 3D game world on an iPhone (limited graphics speed), and I'm already regulating whether I draw each shape on the screen based on it's size and distance from the camera. Something like...

if (how_big_it_looks_from_the_camera > constant) then draw

What I want to do now is also take into account how many shapes are being drawn, so that in busier areas of the game world I can draw less than I otherwise would.

I tried to do this by dividing how_big_it_looks by the number of shapes that were drawn last frame (well, the square root of this but I'm simplifying - the problem is the same).

if (how_big_it_looks / shapes_drawn > constant2) then draw

But the check happens at the level of objects which represent many drawn shapes, and if an object containing many shapes is switched on, it increases shapes_drawn lots and switches itself back off the next frame. It flickers on and off.

I tried keeping a kind of weighted average of previous values, by each frame doing something like shapes_drawn_recently = 0.9 * shapes_drawn_recently + 0.1 * shapes_just_drawn, but of course it only slows the flickering down because of the nature of the feedback loop.

Is there a good way of solving this?

My project is in Objective-C, but a general algorithm or pseudo-code is good too.

Thanks.

Edit: Please, I'm not asking for general advice on rendering performance. I need an answer to the specific question of how to take the shapes drawn in previous frames into account without getting flickering.

\$\endgroup\$

3 Answers 3

0
\$\begingroup\$

That's what Z buffering is for. Once you cull outside your frustum, and apply LoD to further-away objects, then you draw closest first. This will ensure that the graphics hardware can easily reject pixels that it doesn't need to draw.

Ultimately, if the shapes are part of your scene, then you can't not draw them and still get a correct image. You may try decomposing the resulting frames and see how many you actually needed.

\$\endgroup\$
3
  • \$\begingroup\$ If I only drew depending on distance and not size, tiny objects will get drawn when huge but slightly further away ones don't - it just doesn't work. I certainly can't draw everything, or slow devices run at about 1fps because they're drawing small far-away things that really don't matter and are little more than dots. \$\endgroup\$ Jun 25, 2011 at 14:54
  • \$\begingroup\$ To avoid this problem with huge objects create an extremely low LOD version and use a 2nd render loop with a deeper distance to pick out these important objects outside the smaller render distance for everyone else. \$\endgroup\$ Jun 25, 2011 at 17:30
  • \$\begingroup\$ @Mike Howard: You draw on distance and size. Size first. \$\endgroup\$
    – DeadMG
    Jun 27, 2011 at 19:51
0
\$\begingroup\$

First order of business is that you've discovered that it's best to measure before optimizing =) So now you know that it's object count that's killing your speed and not screen real estate.

Measure how many drawn objects your rendering can handle at the needed speed.

Now we need to test drawing distance, create a maximum distance at which you will draw objects and stress test your environment at different distance settings by running around and catching object counts. From this you will come up with a good distance to clip objects being drawn.

Now your basic render loop becomes one of throwing away any object that's farther away than that distance.

At this point most studios will pass that information along to the artists and designers so that they can make their data fit within the drawing parameters you've laid down.

Tip 1 is do do distance in units squared, this will avoid a sqrt() on every object every frame.

\$\endgroup\$
3
  • \$\begingroup\$ I already did all that to come up with what I'm already doing, but now I need to expand on this because some areas are more densely populated with shapes than others. Re tip 1; I do the square root only once per frame, every object reads the result. \$\endgroup\$ Jun 25, 2011 at 18:00
  • \$\begingroup\$ Sort the objects to render by distance. Start with the nearest, count how many and stop when you reach your limit? \$\endgroup\$ Jun 25, 2011 at 21:48
  • \$\begingroup\$ It's OK, I found the answer :) \$\endgroup\$ Jun 25, 2011 at 23:54
0
\$\begingroup\$

Make each object remember whether it was drawn or not the previous frame.

It it was, be more lenient with it when deciding whether it should be drawn this frame than you would be if it hadn't been drawn the last frame. So...

if (how_big_it_looks * (1.2 if drawn last frame, 1.0 if not) / shapes_drawn > constant2) then draw

Voila, no flicker. Can't believe I didn't think of this sooner.

\$\endgroup\$

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .