• Advertisement
Sign in to follow this  

Dilemma

This topic is 3455 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

I have two classes in my engine: class Scene { public: Scene() {} void AddModel(Model Mod); private: std::vector<Model> m_Models; }; AND class Renderer { public: Renderer() {} }; Now I would like to draw the scene with my renderer. Would the best way to do this is to let the scene draw itself ( for example: pScene->draw() in a function of the renderer ) or let the renderer explicitly draw the scene? If you think logically, it's the renderer that would have to take the scene as a parameter and then draw the contents of it. But then the renderer would have to know quite a lot about the internals of the scene class. So I'm stuck with a dilemma here: it's easier to draw the scene from within the Scene class, but the organization isn't the most logical. (a scene can't "draw itself") Also, if I let the scene draw itself, there's going to be some rendering API code in the Scene class. Something I think is a bad design. Can you point me in the right direction here? Thanks, Jeroen

Share this post


Link to post
Share on other sites
Advertisement
Well as I see it you're missing quiet a few things. It's going to be hard to you to efficiently cull the scene since you don't have any spatial relationship like a scenegraph you can use to quickly cull whole branches without even visiting them. Of cause I don't know how the actual implementation looks but that's just one of the things that I notice right away.

The way I would prolly go about this comon problem is to have a culling object run through the scenegraph (or in your case model list). Possibly using some sort of double dispatch. The culling object can then when it returns deliver the collected geometry nodes to the renderer. Or even better sort the geoemetry before rendering it.

You're quiet right when you're saying you don't want the scene to be able to render itself. You don't what the scene to ever know how it's processed. If you want some more indepth information other than my very brief walkthrough you should look into getting this book. Game Engine Design by David H. Eberly.

Share this post


Link to post
Share on other sites
Well, to be honest, I have never used a "scenegraph" before. I don't see what the fuzz is all about. In my real engine, the scene class actually contains an octree structure that itself contains nodes with the appropriate geometry. This octree is my version of a scenegraph I guess. I use it for graphics and collision culling. Anyway, it doens't change much about the problem. Instead of models, with a scenegraph, I would now have to draw geometry nodes.

So basically, you advise me not to use the first method, but pass the "geometry nodes" as a parameter to the renderer, am I right? If I do this, I would have to iterate over all the models and objects in the nodes manually and render them one by one. Wouldn't this introduce a very tight coupling between the Scene and geometry classes and the Renderer class? I mean, the renderer would have to know exactly how as scene is implemented to be able to draw it. For example, when you're drawing you need direct access to all sorts of buffers. (vertex buffers,...) Using these directly seems ugly. Maybe I should give the renderer only access to a limited interface to the scene, with functions to get some of the higher level building blocks?

Or am I tackling this problem entirely the wrong way? Maybe it's perfectly fine to access the geometry directly from within the renderer?

Jeroen

Share this post


Link to post
Share on other sites
Well I think that octtree is a very good basis for a scene graph. It allows you to perform frustum culling efficiently. I believe you can benefit in the future from having some sort of spatial relationship between the nodes. Something like that a node will inherit transformation from its parent.

In this way when you want to add a car with headlights to your scene, you just add the car node and two light nodes that will be children of the car node. Then whenever you want to move the car, you move only the car. The lights move along automagically too and you don't have to worry about them yourself.



And for the "scene renders itself" vs. "renderer renders the scene" problem... Why not have some sort of object (or maybe just a function) that will traverse the scene graph and render it itself.

In my engine I have (well, I'm planning to have, it's in the design phase actually) an object that traverses the scene graph (using the visitor pattern) and builds a list of all visible renderable nodes. This list is then sorted by pixel/vertex shaders, textures and other states to minimize state changes during rendering.

Every scene node that can be rendered then implements Renderable interface. This interface is used to retreive shaders, shader constants, buffers, textures and states that are needed to render this node.

Share this post


Link to post
Share on other sites
Hey godmodder. As I also mentioned in my reply I had no idea on how you actually implemented the scene class and my reply was directed at the source you provided. Like most problems this can be solved in a lot of ways, an octree is indeed a valid one.

You might have missed a subtle point of my reply. I'm not proposing that you let the renderer know of the scene nor the scene know of the renderer. I'm proposing you let your culling system know of the scene it's suppose to generate a list of drawable objects from. And the part of the system that's responsible of issueing the culling operation know both the culling system, scene and the renderer. As Silicon Dude also proposed you want to let your geoemetry implement some sort of IRenderable interface to decouple the renderer from the geometry. But at some point, as you also pointed out yourself, the D3D device (or whatever you're using) has to know about the raw data from the buffers so you'll have to have atleast some coupling there.

Feel free to correct me or ask if stuff is still unclear!

edit:
Silicon Dude also proposed the Vistor as an double dispatch method. This is also a very valid / typesafe choice to collect the data.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement