Shader Based Scene Graph

Started by
16 comments, last by elevator2 17 years, 10 months ago
It only took me a few minutes to get a fixed function scene graph operating, but I want to avoid fixed function as much as possible. Does anyone have any suggestions on implementing a shader based scene graph? Here's what my fixed function scene graph looked like:

-RootNode
   -TransformNode
      -MeshNode
That worked great. The root node would call its children's render function. The transform node's render function set the world matrix and then rendered all its children. The mesh node simply used the ID3DXMesh::DrawSubset() function to render itself. Everything worked fine, but to do shader based, I'm not sure how it'll work. Any ideas? [Edited by - NickGravelyn on June 9, 2006 3:45:54 AM]
Advertisement
There are a few methods.
One could be to create a "shader node". It sets the shader, its parameter, then render all the childrens, and close the shader.
A second one is to move the rendering code outside the scenegraph. Create a renderer class, and in the Render() method of the scenegraph's nodes, you only send to the renderer all the informations needed to render the node (VB, IB, textures, etc.) This way you can create 2 pathes in the renderer. One which render using the FFP, and the other which render using shaders.

I'm currently using the seconde solution and am quite happy with it ^^
I think that second idea is a great idea. That will allow me to send what I need to the function. Cool. I did create a shader node and gave it the mesh node as a child, but this clearly would mean that I could have only one mesh per shader as the shader has no way of using multiple world matrices. Your idea sounds perfect. Thanks.
Interesting topic.
The way i handle it is that all scenenodes are processed into rendering queues within the SceneGraph which basically are lists sorted by material/shader.
The rendering occurs separately in a render manager which keeps the scene management and rendering management separate.
I also use a SceneGraph with childnodes etc, but i setup rendering lists internally for the node->mesh->submeshes based on their material/shader.

That way, if you have a shader node with a mesh that uses a shader, render it, and then traverse down the childnodes an find a node which does not use a shader but instead a simple material (say a single texture) you wouldnt have to switch states before rendering it as often if you had these material changes optimized in lists.
Or perhaps youre not allowed to add non-shader nodes to a shader node in your system?

Correct me if im wrong, cuz i might just be rambling about something ive missunderstood here :)
Quote:Original post by paic
There are a few methods.
One could be to create a "shader node". It sets the shader, its parameter, then render all the childrens, and close the shader.
A second one is to move the rendering code outside the scenegraph. Create a renderer class, and in the Render() method of the scenegraph's nodes, you only send to the renderer all the informations needed to render the node (VB, IB, textures, etc.) This way you can create 2 pathes in the renderer. One which render using the FFP, and the other which render using shaders.

I'm currently using the seconde solution and am quite happy with it ^^


Can you post either actual code or some pseudo code to help explain the second point? I understand it pretty well, but I'm not sure how to actually implement it.
Quote:Original post by NickGravelyn
Quote:Original post by paic
There are a few methods.
One could be to create a "shader node". It sets the shader, its parameter, then render all the childrens, and close the shader.
A second one is to move the rendering code outside the scenegraph. Create a renderer class, and in the Render() method of the scenegraph's nodes, you only send to the renderer all the informations needed to render the node (VB, IB, textures, etc.) This way you can create 2 pathes in the renderer. One which render using the FFP, and the other which render using shaders.

I'm currently using the seconde solution and am quite happy with it ^^


Can you post either actual code or some pseudo code to help explain the second point? I understand it pretty well, but I'm not sure how to actually implement it.

I believe what he is talking about is something along the lines of this. Using the other device states in a scene graph (shader constants, render states, textures, ect) can greatly improve performance, since it reduces the number of useless state changes you make.
Dustin Franklin ( circlesoft :: KBase :: Mystic GD :: ApolloNL )
What is the advantage of having shader information in your scene graph? Why not having shader information per model/object/entity/whatever, and having only spatial relationships in your scenegraph? Just get the visible objects from the scenegraph, sort them (by shader/texture/etc), render them. Probably I'm missing something obvious.
I believe it's really so obvious.
Suppose, as you say, to have shader info per-node and sort nodes per-shader. Then, since this is not going to change, you save the order somewhere. No matter where, you have somewhat modified the scene graph to account for shader information.

Previously "Krohm"

Quote:Original post by roel
What is the advantage of having shader information in your scene graph? Why not having shader information per model/object/entity/whatever, and having only spatial relationships in your scenegraph? Just get the visible objects from the scenegraph, sort them (by shader/texture/etc), render them. Probably I'm missing something obvious.


Agreed. Unless we're missing something obvious, that last article oversimplifies the issue - the second approach described there does not deal with visibility culling at all, does it?
Quote:Original post by roel
What is the advantage of having shader information in your scene graph? Why not having shader information per model/object/entity/whatever, and having only spatial relationships in your scenegraph? Just get the visible objects from the scenegraph, sort them (by shader/texture/etc), render them. Probably I'm missing something obvious.


You are correct. Most people try to make a scene graph into something it isn't. Scene graphs shouldn't, and don't care about shaders. They only care about the relationship between the objects in the scene. A shader node isn't a good idea in my opinion. If I were doing this, I would prefer a form of the second option.

I would have all my "models" retain any information involving textures, shaders, lighting, etc. I would then have a scene graph constructed of transform node, geometry nodes, and whatever other nodes that would be needed. When a geometry node is inserted into the scene graph, it gets associated with a model, the node doesn't care about anything specifics about the model, just that it is associated with that model. Now, as you travel down the tree, updating the transformations and so forth and you get to the model, you would then send that model and the current transformation to the renderer. The renderer would then set any shader constants (such as the current transformation matrix), textures, and any other data contained within the model. It would then set the active shader as the shader the model uses and render.

Quote:Original post by lightbringer
Agreed. Unless we're missing something obvious, that last article oversimplifies the issue - the second approach described there does not deal with visibility culling at all, does it?


A scene graph doesn't have to do visibility culling at all, it is just that most people use it to.

I'm no expert at scene graphs, but from my understanding of them, this is a decent way to do it, and how I would implement it. Hope this helps.

This topic is closed to new replies.

Advertisement