Sign in to follow this  
ChristianPena

Responsibilities

Recommended Posts

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?

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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
-> ExplosionRenderer

Entity
-> 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

Share this post


Link to post
Share on other sites
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 shaders
sort 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.

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this