"Sorting out" render order

Started by
31 comments, last by cozzie 11 years, 2 months ago

Hi,

I'm at the point of implementing alpha blending (shader) to be able to use transparant/translucent textures, grass etc.

For now I didn't use any object/ mesh sorting because I didn't see the advantage yet.

But.. when using alpha blending, I've learned that I have to render objects (or better triangles?) from back to front for the expected result.

A few questions I'd like to hear your opinion on;

- is it worthwhile to render meshes/ objects based on world positition Z (initial worldpos vector * actual world matrix)?

(by the CPU, finding an efficient way of looping through objects, materials, effects, entities)

- what would you suggest to sort objects on when it comes to alpha blending?

The direction I'm following now is:

- update worldmatrix of each mesh each frame

- multiply by initial worldpos, resulting in a vector with 'Z' value

- use Z value to render 'regular' objects, front to back (increase performance on rasterization/ pixel shader)

- use Z value to render 'blended' objects, back to front

Any hints or pointers are really appreciated.

Will also be quite a challenge too find the best way to combine the 'loops' (materials, effects, effects, subobjecs/entities).

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Advertisement

I think the way your currently going about it is fine and fairly common. So your just adding all visible transparent objects to a list then sorting that list based on world distance from the camera. One thing to consider however, using the world position to camera may not be the best metric because consider two objects being close together, and the one at the back being much larger than the one in front. In this case you should probably render the object at the back first. So instead maybe calculate the distance from the camera to the objects bounding box.

Thanks Nyssa, I can easily do that by using my radius value for each mesh, in combination with the world position (based on current camera position).

Good to hear that I'm on the right way.


Sorting 'regular' meshes (cpu usage) for rendering isn't that usefull (yet/ for now).

In the end I might need to merge vertex and indexbuffers to save renderstates etc..

I know loop through all effects, then materials, then meshes, the entities. This is potentially not perfect, because I switch meshes (index/ vertexbuffer) more then once for each entity. I find this a difficult choice, it's more setting of vars for the materials (in the effect/shader) versus setting more matrices and index/vertexbuffers. Don't know what's worse.

I might go for index table to prevent loops (for static objects that is, now 90% of the scene), but also then I would need to do switches on the meshes or materials. When I think of it now, probably switching materials is quicker then meshes:

- material select:

=> 2 SetFloatArray calls (amb and diff)

=> 1 TexTure call (or more when multitexturing or so)

- mesh select:

=> SetMatrix (World)

=> SetMatrix (WorldInvTransp, for normals/ lighting)

=> SetStreamSource

=> SetIndices

But then again going through all meshes and then materials, means selecting the materials again for other meshes.

Dilemma's dilemma's .... huh.png

Any advice on this?

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

as an addition, I do have a table (unsorted), with for each entity/ sub object:

- entity nr of mesh

- mesh ID

- material ID

- effect/ shader ID

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

@Nyssa (and others :))

I've been studying my renderframe and found some flaws (I believe). To illustrate.

Sample scene:

15 meshes

5 entities for each mesh

7 unique materials

Assume that I do the following one time for Opaque meshes with Opaque technique and another time for blended meshes with Blending technique (already have 2 mesh index int lists in use):

loop through effects/shaders

{

begin effect

set technique (blended or opaque)

set viewprojection matrix of camera

loop through passes of technique

{

loop through materials

{

select material (setfloatarray 2x, settexture)

loop through meshes; if mesh.mEffect = current effect

{

if mesh in frustum

{

setstream vertices, setindices

set worldmatrix

commitchanges

loop through entities; if entity.material = current material

{

if in frustum

{

draw

}

}

}

}

}

}

}

This means I do:

- 7 material switches (2 float arrays, texture)

- 105 mesh switches (setstreamsource, indices and world matrix)

- 105 commitchanges

- 105x check effectindex for mesh

- 525x check material index for entity

I figure if I turn it around and go through meshes and then materials:

- 15 mesh switches

- 105 material switches

- 105 commitchanges

- 15x check effectindex for mesh

- 525x chec material index for entity

Room for improvement?

- what would take more performance, switching a mesh versus switching a material?

- bringing back the if loops for effect and material ID checking, I can do with index lists (int array's)

- what other improvements should I look for?

(I'm not yet ready to go for merged meshes into one vertex or index buffer, which might bring other possibilities)

Any advice is really appreciated.

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Switching material implies switching shaders and switching shaders is basically the most costly thing to do on the GPU, as such you pretty much always want to reduce that to the smallest amount you can by sorting by material and, if you can, using instancing.

The other problem you have, however, if you over all algorithm as while it gets the job done it simply does too much work and too much redundant work at that.

The way many engines do it is to generate a list of objects which need to be rendered and then sort them using a sort key into material order, after which they simply walk through the list from top to bottom rendering each object as it comes. There will be some logic to reduce redundant shader changes (which can be as simple as keeping a track of the current material and shaders in it and only calling the 'set' functions if the new object requires something different) but over all once you have a sorted list it is simple to do.

http://realtimecollisiondetection.net/blog/?p=86 covers some more details,

Hi Phantom,

Thanks, this clears things up. The article covers recognizable stuff, that's the good thing :)

I thought about making indices of entities (with corresponding mesh ID) who share the same material.

This way I could batch up and reduce the material changes to the number of materials in the scene.

Thinking about it, with what your saying, this saves a lot of state changes.

Assuming that I don't need to 'CommitChanges' when setting another streamsource and indexbuffer, is this correct?

If so, this will be my first step.

Maybe later on bundle the streams/indexbuffer to improve further.

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

@Phantom; just remembered that this probably wont help/ work, because when changes the streamsource/vertexbuffer (mesh) I also need to set the mesh's world and worldinvtranspose matrix. Which probably means I need to commitchanges anyway...

Crealysm game & engine development: http://www.crealysm.com

Looking for a passionate, disciplined and structured producer? PM me

Yeah Phantom is spot on, your doing alot of redundant searching there.

The way I currently do it is via render "buckets". So as you loop over your scene objects, after you have determined an objects visible, you determine if its solid or transparent (you might have a boolean in your material for this) then add that object to the solid or transparent list. Each Object also has a key based on its render state (this can include its rasteriser state, blend state, texture ids, etc...) and each list is sorted using that key. So objects with similar states will be next to each other thus state changes should be kept to a minimum. Then you just render each object in those lists, setting world matrix values as you go.

Keep in mind that all this sorting needs to be done in an efficient way else it ends up being faster to simply do all the state changes anyway! You could also add to the above method a way of altering these lists only when an object moves in/out of the viewing frustum. That way they don't need to be rebuilt each frame!

I should add...I'm currently working in c++, but the same theory should translate in to c# smile.png

Maybe rendering alpha-blended meshes after opaque meshes would be enough.
(two phases without meshes positions analysis).

This topic is closed to new replies.

Advertisement