Sign in to follow this  
Specchum

A rendering dilemma

Recommended Posts

I've been looking to improve my rendering pipeline, which currently looks like this: 1) Register all objects that need to be rendered. This simply puts all objects into a render-list, nothing more. 2) When RenderAll is called, 2 for loops are initiated:
for (loop through the material list)
{
 for (loop through all the meshes)
 {
   if (this mesh in the view frustum)
   {
     if (this mesh has this material id)
       render mesh;
   }
 }
}

3) Render all alpha blended meshes in back to front order. Thus this is not a by-material render but a view-order render. I'm sure there are a hundred better ways to do the above but I'd like something that's not horribly complicated and which doesn't involve scene-graph (I'm not ready for it yet) but will resolve my following dilemmas: 1) If I were to render the non-alpha objects in front-to-back order, wouldn't I have to forego by-material rendering (and thus take a hit with state changes)? 2) I've heard that pushing a giant vertex buffer is more efficient than multiple vertex buffer pushes. But again, how I would I go about that while still maintaining frustum culling and sort orders?

Share this post


Link to post
Share on other sites
Answering both your questions first:

1) Rendering opaque things in front-to-back order is mostly a saving for the GPU at the pixel processing level (pixel shader, frame buffer blend, final write, Z buffer write) when using a hardware Z buffer.

If your application is GPU bound, and pixel processing bound in particular, then rendering in front-to-back order can be a saving.

You are correct in saying that sorting your draw calls into perfect front-to-back order will break your batching by material - so might mean potentially more texture uploads/changes, potentially more shader constant changes, potentially more render state changes - all of which could result in a much greater performance hit than the benefits you'd get from the Z buffer.

However, the sort order doesn't need to be 'perfect'. Sorting front-to-back is a "if you can do it without harming anything else, then do it, but don't break your neck trying" types of optimisations.

I'd advise sorting by material first, then sort the meshes using each material in front-to-back order - so the material order is still preserved, but you get a little extra help from the Z buffer for the meshes using that material.


2) Changing vertex buffer means changing device state, any changes in state have a performance overhead - changing buffer less means less state changes.

Using an index buffer/indexed primitives and the 'range' parameters exposed by common 3D APIs lets you select which meshes within the big vertex buffer to render, just as you would with a separate vertex buffer per mesh.

Usually the biggest cost on PC is the number of individual draw calls though - that's one of the first things you should target.


Now some alterations to the pipeline you posted:


1) Register all objects that need to be rendered. Pointers to the objects are put into a render-list. The bounding volume of each is tested against the frustum to determine whether or not it should be inserted into the list. If the scene has any sort of hierarchy such as a scene graph, OBBtree, quadtree, etc, groups of objects are tested against the frustum first.


2) The render list is sorted by material (or multiple render lists are used, one per material). This is as simple as an std::sort.


3) When RenderAll is called:

CurrentMaterial = renderList[0].Material
for (loop through the render list)
{
if (renderList[n].Material != CurrentMaterial)
{
change material;
}

render mesh;
}



There are still lots of potential variations and optimisations to this main loop.


4) Render alpha blended geometry as usual.

Share this post


Link to post
Share on other sites
Also, if you're limited by high pixel shader costs, and this is why you'd want to be rendering front to back, you can do a depth only (/depth + ambient) pass first. This will fill the depth buffer and allow depth tests to discard potentially expensive pixels before their shaders are invoked. If you have high overdraw, or you're already doing multiple passes (say 1 per light for instance), the hierarchical early depth culling can reject regions of pixels per cycle as well, which should help if you're fill rate limited.

Share this post


Link to post
Share on other sites
Hmm...this is interesting. I have a few questions along these lines as well:

1) Is it really that much better to sort your render que by material (texture)? How often will you find two meshes that use the exact same material anyway?

2) What do you do if you want to use multitexturing (as most modern commercial titles use)?

3) Should the rendering engine take care of sorting by material/alpha/etc. or should the main game logic (well, not really the logic, but rather part of the game tha isn't the 3-D engine) take care of that? And the same for frustrum-checking too. Should the rendering engine check to see if the object is in the viewing frustrum, or should the other app stuff do that?

Share this post


Link to post
Share on other sites
S1CA, that's exactly the sort of detailed info I required and now I know what to do. Thanks very much.

c_20, I'm not using shaders at the moment but since I do plan to go with shaders at some point, your points will be worth keeping in mind since I'm indeed GPU bound and specifically by pixel fill rate presently.

ouraqt, in fact I'm heavily using multiple meshes per texture (ie many meshes share the same texture)so state switching is of prime importance to me. Currently my engine is doing state management as well as sorting and culling objects. I'm however thinking of adding a flag that can be set by the user to control culling and perhaps other stuff as well. I'll have to sort out the render pipeline first before I get to that.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this