Responsibilities

Started by
5 comments, last by ChristianPena 18 years, 6 months ago
Where do you put the responsibility of rendering? Say you have a class, Renderer, that interfaces with DirectX or OpenGL or whatever and you have some Entity class that represents a renderable object. Do you design your objects as Entity.Render() or Renderer.Render(Entity)? I am inclined to use the second method and have the Entity class be a mostly data container based object. Any thoughts?
Advertisement
I'd say let the entity object handle the actual draw calls, while the renderer sets up the state (i.e. sets shaders, constants, textures etc). This allows the entity to represent it's data how it wants, and allows the entity to encapsulate the data (otherwise you're gonna have stuff like GetVertexData functions). So in psuedo-code you'd have something like this:

for every renderable object    SetupState(object)    object.render( )


You will of course want to order the objects based on state to minimise things like texture and shader changes.
Personally, I would split the entity up into two or more classes. One that will deal with the simulation/game-mechanics aspect, and one that will deal with the rendering aspect. The reason being that you don't want a single renderer class that knows how to render all the different types of object, and at the same time, you don't want to give one class the two responsibilities of dealing with gameplay mechanics, and also rendering.
If you ever want to split the rendering code out from the game mechanics code (for example, to be able to use a fixed physics timestep, or to write a multiplayer mode), then you certainly won't want a single class having both responsibilities (drawing and simulation).

You may end up having a hierarchy like this:
Renderer-> TerrainRenderer-> ModelRenderer-> EffectRenderer  -> TrailRenderer  -> ExplosionRendererEntity-> WorldEntity-> PropEntity  -> TreeEntity  -> TableEntity  -> VaseEntity-> ActiveEntity  -> PlayerEntity  -> GruntEntity  -> BossEntity  -> ProjectileEntity    -> RocketEntity


Props and active entities may share the same renderer (ModelRenderer), and some entities (RocketEntity) may require multiple renderers (ModelRenderer and TrailRenderer)

Having said all that - there is no "correct" way of organising your code. As long as you pick one way of organising the code, and you understand that way, and you stick to it, then you shouldn't do too badly. When the project is done, there will be plenty of things about the code that you won't like, but that's fine, just learn from it, so that next time you make different mistakes.

John B
The best thing about the internet is the way people with no experience or qualifications can pretend to be completely superior to other people who have no experience or qualifications.
I concur with Mr Small.
Quote:Original post by Telastyn
I concur with Mr Small.

Not that it matters, but Small isn't my surname (hence signing off with John B, not John S). No problem though :)

John B
The best thing about the internet is the way people with no experience or qualifications can pretend to be completely superior to other people who have no experience or qualifications.
Hi,

I would do it like that :

// first pass (visibility pass) :for each node:   if node is visible:      node->render()    // this doesn't actually render. It just pass itself to the renderder// second pass. Where in the renderer here :sort entities by shaderssort entities by textures// ...for each entity:   render entity


When it comes to rendering, it all boils down to some buffers, shaders, textures, etc.
So, each node of the scenegraph (whatever their type) has pointers to such resources, and in the render function (or another name like "register()") it simply send those pointers to the renderer.

Then, it's the RENDERER which will actually issue the DIP call, the settextures, etc. Because then, the renderer has all the infos about the visible entities, so it can sort them to minimize state changes. It can also sort them front to back, etc.
Paic,

It seems like you favor the idea of having the renderable object containing the data and a seperate renderer class (one class) doing the rendering. I am for this approach as well. I just wanted to see what others thought of it.

John B:

I like your idea, but how do you relate the specialized renderers with their data components? Does each instance of a specific object have a pointer to the renderer that knows how to deal with it? Or do you use some sort of RTTI to establish which renderer to use?

This topic is closed to new replies.

Advertisement