Need Critique On Rendering Data Structures

Started by
11 comments, last by RealMarkP 14 years, 11 months ago
I'm having a hard time trying to manage my rendering. I looked into Scene graphs, and determined they might be a bit too complex for my task. I decided on a small transform graph and Octree combo. Take a look at my uml diagram and tell me what you think. Some notes: - Transform graph handles static objects as well as dynamic models with bones. - Renderables contain instances of Vertex and Index Buffers. - A renderable is passed in a shader which it sets it up for it's own rendering process (User controlled). - The renderer has a list of renderables which it iterates through (no sorting, atm). - The Octree is passed in a Frustum, AABB, Sphere, or ray and spits out a list of 'hit' objects. This can be used for rendering or picking alike. My questions are: - Are there any problems that jump out at you? - What's the best way to incorporate sorting into this architecture (By shader, texture, or other)? - How could a state sorting (or push/pop) render graph be incorporated? Be as meticulous as you want. What I'm looking for is constructive feed back and not 'OMG this sucks' comments. Thanks to everyone that replies!!
------------Anything prior to 9am should be illegal.
Advertisement
Quote:Original post by RealMarkP
- What's the best way to incorporate sorting into this architecture (By shader, texture, or other)?


Typically this is done with a render queue. When the renderable graph is queried and iterated, the renderables are pushed into some kind of render queue container. This container is either sorted on insert, or passed off to another thread and sorted as a whole.

Sorting usually goes by:

1.) Render target
2.) Opaque/Transparent
3.) Shader
4.) Texture

And i'm always curious where vertex buffer fits in. Sometimes i think it should be before the shader sort, and sometimes i think it's after texture, it depends on how you store stuff in the vbo. if the VB is all of one material then sorting it with material is pretty much the same as sorting by the material.

So a sorted list may look like this:

Rt1 - Opaque  - Shader 1   *obj1   *obj2  - Shader 2   *obj3 - Transparent  - Shader 3   *obj4   *obj5Rt2 - Opaque  - Shader 1   *obj 6 - Transparent  - Shader 3   *obj 7   *obj 8



//There are fancy bit hacking tricks to make this a single integer compare.
bool DrawCall::operator < (const DrawCall &right) const
{
return (RTID < right.RTID)
|| (Opaque && !right.Opaque)
|| (ShaderID < right.ShaderID)
|| (Opaque == Depth < right.Depth);
}

Quote:Original post by RealMarkP
- How could a state sorting (or push/pop) render graph be incorporated?


Your states could be appended to the sort list i provided. You'd just give each property a particular sort order and include that in your operator < (). My renderer has one function SetRenderState(RenderState, bool) which is the only point of access for the renderstates. Inside here you could check if the state was already set (if it's a particularly expensive state to set). Although i think the api takes care of this for you now days. At least with the late model d3ds.
Quote:Sorting usually goes by:

1.) Render target
2.) Opaque/Transparent
3.) Shader
4.) Texture

Good to know. I would never have though to sorting by Rendering Target. A side not one the Opaque/Transparent step. Figuring out Back to Front rendering might get a bit hairy in the Transparency section. I would think that when Items are added and they are transparent, it would get put into a sorted list of some sort. Data structure wise this might be easier then I previously thought.

Quote:And i'm always curious where vertex buffer fits in. Sometimes i think it should be before the shader sort, and sometimes i think it's after texture, it depends on how you store stuff in the vbo. if the VB is all of one material then sorting it with material is pretty much the same as sorting by the material.

I would think a vertex buffer would be dead last, after the texture sort. Even then, they don't have to be sorted, just rendered when the above 4 steps have been sorted.

EDIT: New uml diagram.

[Edited by - RealMarkP on April 30, 2009 1:52:57 PM]
------------Anything prior to 9am should be illegal.
It just depends, what's going to take longer, copying a huge vertex buffer over and over, or switching materials over and over, it may come out benefitial to switch materials more often than VBs, only profiling would tell.

Also, even if they're at the end, they should be sorted, to minimize needless switching.

Ultimately (it's most intuitive), i put the VB at the end of the list.

If the depth is encoded in each drawcall when it's added then they can be sorted later with the main sorting routine. In my example I sorted opaque objects front to back while transparent objects are sorted back to to front.

[Edited by - bzroom on April 30, 2009 3:19:50 PM]
Thanks for the comments, they were very helpful.

Using my new design, I have decided to manage the scene in the following manner:

1. User populates scene with a bunch of objects, some static, some dynamic. The system plugs it into an Octree for culling and into a Transformation Graph for logical arrangement. It also puts an entry into the RenderingChain which sorts it by Rendering Target, Shaders, Opacity, and Textures.

2. When an object is transformed form one location to another, the first thing to kick in is the Transform Graph, which updates the locations of all child objects. Secodnly, the Octree is updated when those objects move, to put them into the correct spatial node.

3. The Octree kicks in and culls the objects based on collision with a Frustum. Turns a 'Visible' flag on when objects are inside the frustum.

4. The renderer runs through all objects in the scene (already sorted) and only renders the ones that are visible.

Comments?
------------Anything prior to 9am should be illegal.
Quick 2p: I found the 'Renderstate change costs' article here helpful when I was looking at designing something similar.
How do you handle meshes with multiple textures? Multiple VBs per mesh or something else?
Quote:Original post by stupid_programmer
How do you handle meshes with multiple textures? Multiple VBs per mesh or something else?

Each renderable has a pointer to a shader, which it knows how to set up. Therefore if the shader does multitextureing, the renderable derivation will know how to plug multiple textures into it. Same goes for multiple vertex buffers. But you raise a good question, how does one sort textures when multiple textures are involved?

------------Anything prior to 9am should be illegal.
Heh...I ask because I am curious myself. My current engine I got around it by just requiring that every game model only have one texture on it.

The way I thought about it is to have each texture assigned to a material that has render settings and needed shaders. Then all the tris assigned to that material go in their own VB. And a 'mesh' is just a collection of VBs. This way I think you could have multiple textures and have each piece go through the sorting.
In your new UML diagram, I don't think a Model 'is a' SceneObject? It's not really a 'scene object' or 'cullable' until it's in the scene graph?
Shouldn't your concrete object 'have a' model instead? That works better in my mind...

For the rendering question raised by stupid, I've been thinking about this myself recently: when an object 'draws' itself it sends off its polys to a central renderer which stores them by pertinent hashed 'material' state (and can e.g. sort blended polys) then draws everything in this sorted state, minimising state changes and allowing separate materials (and :. textures) on a single mesh. Maybe put each material in a VB at this stage.

The only thing stopping me doing this so far is the lack of mechanism to flag my 3d model assets with per-poly materials in a satisfactory way (using Blender, which lacks nice user data specification).

This topic is closed to new replies.

Advertisement