Question on how models render

Started by
5 comments, last by Bonehed316 18 years, 10 months ago
I am going to be using a polygon model that is about 8000 faces. Of course i plan on reducing the size as much as I possibly can, but i would like to keep as much detail as i can as well. My question is about a idea i came across but I wasn't sure enough about. When directx renders a mesh does it render all the polygons (I know it doesn't normally render backfaces which is fine.) including the polygons the player cannot even see? For instance these faces would be like the polygons along the back of the character if you can only see the front. if it does, I was wondering what the best way to remove this extra information would be before it is rendered. My engine gets about 30-40 fps during times where there are about 400,000 - 800,000 polys on screen at once. Also some other ideas on how I could increase the frame rate of my game would be great. I’ve looked into using fog.. But I don't quite know how to jump on that idea. Any help would be great
Indy to Pro: Journeyhttp://phiendstudios.blogspot.com
Advertisement
The broad idea that you want to persue is "frustum culling". Basically, this is determining which objects are visible from the player's perspective. This allows us to skip the rendering of objects that will never be seen, increasing the framerate of our application. There are numerous techniques out there for doing this quickly and efficiently:

(1) Camera Frustum: Build a box that represents the player's view. Test all objects to see if they are inside.

(2) Quadtree/Octree/KDTree: Data structures that are used to organize objects into recursive trees. The quadtree is pretty simple, but yet it yields good results.

(3) Occlusion culling: Detecting, one way or another, when objects are inside the viewing frustum, but not visible. For example, let's say you have a small sphere behind a large box. If both objects are inside the viewing frustum, then the sphere will be rendered, even though it isn't visible. Occlusion culling tries to prevent this.

(4) Precomputed Visibility Sets (PVS): Split the world up into a grid of nodes. For each node, determine all of the other nodes that are visible. Store this data, then load it at runtime. Now, just look up what node you are at, and viola, you have the entire list of visible objects.

(5) Portals: Devide the world up into cells, which are separated by portals. If a portal is not scene from the current orientation, then all of the geometry behind that portal can't be seen, either.

There are many other methods out there, too - some for indoor scenes, some for outdoor. Just search Google for "frustum culling" and you will find plenty of resources [smile]
Dustin Franklin ( circlesoft :: KBase :: Mystic GD :: ApolloNL )
Speaking of which, I'm on this very topic at the moment building my own engine. I've got the renderer all set up, but before I move on any further I want to develope the method I will use to cull unneeded objects from rendering. Some problems I am having thinking through it all:

Frustrum culling seems error prone at first thought, but obviously works in games, so lets think about specifics. For instance, if you check a renderable object's center, or wherever you consider its "location" to be, to see if it falls in the frustrum, obviously this can lead to errors with large models being far off center. So you would either have to check all the vertices (which seems very slow), or devise a bounding sphere for every object and check that to see if it is in the frustrum, which again seems slow. Would it be possible to build an octree for every model to test for "collisions" with the frustrum, or would that be slower (consider an average level having 4000 renderable objects)?

Using scene nodes for levels is a very fast way to eliminate large portions of a level in just a few cpu cycles, but it requires ideas that seem abstract to me. For instance, how do you decide where to put a node? You could have a level designer divide the map into "zones", I suppose, and each zone would be a node. Infact, thinking of other engines (for instance the unreal engine), this is probably exactly how they decide this.

Speaking of scene nodes, I guess every object would have to have (or be) a scene node of some type in order to render it with a scene graph. Also, practically speaking, there probably arent very many long branches of scene nodes in a level, except for special cases, such as a player standing on something that moves, or perhaps the players weapon, and other things that get attached to objects, such as effects. Or would it be practical to check when any object moves to see if it has moved in to another zone, and then put that object under the level scene node for that zone? That might result in a lot of work, though. Or perhaps flag objects that are able to move and only checking to see if those objects have moved since the last update would be a better solution, and if they have then you could check to see if they're still in the same zone, heh.

Am I answering my own questions?
Quote:Original post by Bonehed316
Frustrum culling seems error prone at first thought, but obviously works in games, so lets think about specifics. For instance, if you check a renderable object's center, or wherever you consider its "location" to be, to see if it falls in the frustrum, obviously this can lead to errors with large models being far off center.

Yes, this is a valid point. Usually this sort of simple point-and-plane testing would be used when such inaccuracies aren't so important. Rather, it's better to do it quick and dirty for performance reasons.

Quote:Original post by Bonehed316
So you would either have to check all the vertices (which seems very slow), or devise a bounding sphere for every object and check that to see if it is in the frustrum, which again seems slow.

You don't want to be touching the individual vertices unless you absolutely have to [grin]

Bounding spheres are a very good idea, the mathematics is trivial and the results are pretty good... more on this in a second.

Quote:Original post by Bonehed316
Would it be possible to build an octree for every model to test for "collisions" with the frustrum, or would that be slower (consider an average level having 4000 renderable objects)?

It would be possible, but I'd hazard a guess that a "world" octree would still be a lot more efficient at rejecting objects quicker.

Quote:Original post by Bonehed316
For instance, how do you decide where to put a node? You could have a level designer divide the map into "zones", I suppose, and each zone would be a node. Infact, thinking of other engines (for instance the unreal engine), this is probably exactly how they decide this.

This is very domain specific, so I don't think there is a specific single answer for how to place zones/nodes.

I can't speak for the commercial engines beyond saying that I've read in a few articles that various tools allow to, at least, put hints for where nodes/zones should exist.


All of the best culling systems I've seen (and tried to implement) have been heirachical - if you think about the big "divisions" that you can draw between objects. For example, if we assume that everything that is behind the camera is invisible reject it straight off without any further checks. That could be done with a simple dot product operation.

Back to the spheres thing... you could get good results if you were to have one big sphere for the whole object. Test this single sphere against the sphere enclosing the camera (defined by eye position and look-at point) you'd know if it was even close to where we are observing from. If you accept it, maybe check it's sphere against the actual view-frustum and if it is wholly contained within the 6 planes, render the whole thing straight away. If it's partially intersecting one of the planes, maybe you could recurse down to checking smaller model parts (again, with their own bounding spheres).

Similarly, with the (quad|oct)tree algorithms, they work on the assumption that if you can reject a high level node early on, you implictly reject all of the nodes contained below it. Relatively little CPU time rejects a large number of objects.

hth
Jack

<hr align="left" width="25%" />
Jack Hoxley <small>[</small><small> Forum FAQ | Revised FAQ | MVP Profile | Developer Journal ]</small>

Hmm, thanks for the info.

I think I've a good idea of what I need to do now. Still, what about object placement in a scene graph. If objects move, wouldnt that object need to be moved to different nodes as it moves through the level? It would probably be trivial to do, since the number of objects that move is generally (and quite often significantly) a smaller proportion than those that do not move, and thus dont need to be updated.

And to the original poster, your framerate is pretty good considering the number of vertices you are rendering. If you implement any sort of culling setup, you will see those numbers rise quite a bit.
Quote:Original post by Bonehed316
I think I've a good idea of what I need to do now. Still, what about object placement in a scene graph. If objects move, wouldnt that object need to be moved to different nodes as it moves through the level? It would probably be trivial to do, since the number of objects that move is generally (and quite often significantly) a smaller proportion than those that do not move, and thus dont need to be updated.

Yea, there are a number of issues like this. For example, what if an object strattles 2 nodes? Which one does it go in? It would probably work best to have it placed in both nodes - just make sure it's only rendered once. I don't have my culling system set up to render right away - it determines which objects are visible, then adds them to a scene graph which categorizes an entity by its material.

On the topic of moving nodes, remember than an object will probably not skip over many nodes at once. So all you have to do is move up a level, test again, and then re-place. If it actually did move over a lot of area, just keep moving up.
Dustin Franklin ( circlesoft :: KBase :: Mystic GD :: ApolloNL )
Thanks.

I really havent worked out the specifics yet, which is why I've got so many questions. However, my renderer is set up to recieve geometry sorted by render state.

As for not rendering things twice, you could keep track of the last frame you rendered it on, or the time it was last rendered, which can be useful for numerous things.

This topic is closed to new replies.

Advertisement