Jump to content
  • Advertisement
Sign in to follow this  
Endar

Role of the renderer

This topic is 4828 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

Perhaps this should have been re-named "Implementation of the renderer". So far, in the things that I've programmed, I've had the objects rendering themselves, but it has occured to me that maybe this isn't the best way to do it. I was thinking while watching "House" last week (great show), and I jotted down some code for a renderer where the object registers its vertices to be rendered, and the renderer keeps pointers to these vertices and has that in whatever data structure it needs.
class COGLRenderer
{
public:
	/**
	 * An object to be rendered
	 */
	struct RenderObject{
		char* name;			///< The name of the object
		float* vertex;		///< The vertices of the object (model should be in triangles)
		float* normal;		///< Normals for the vertices
		float* color;		///< Colors for the vertices
		int num_vertex;		///< (num_vertex*3) = sizeof(vertex)
	};

private:
	std::vector<RenderObject> rlist;	///< A list of all the objects to be rendered

public:

	/**
	 * Register an object for rendering
	 * \param r A refernce to a RenderObject object
	 * \return True if the item was added properly, else false
	 */
	bool Register(RenderObject& r)
	{
		// Search for identical name in the rlist
		// If found, return false
		for(int i=0; i < rlist.size(); i++)
			if( strcmp(rlist.name, r.name) == 0 )
				return false;

		// add the object to the list
		rlist.push_back( r );
		return true;
	}

	/**
	 * Render the object connected with a RenderObject
	 * \param r A const refernce to the RenderObject to render.
	 */
	void Render(const RenderObject& r)
	{
		char	flag = 0;
		char	vertex_flag = 0x1,
				normal_flag = 0x10,
				color_flag  = 0x100;

		if( r.vertex )	// if there is an array attatched to the pointer
			flag |= vertex_flag;
		if( r.normal )  // if there is an array attatched to the pointer
			flag |= normal_flag;
		if( r.color )  // if there is an array attatched to the pointer
			flag |= color_flag;

		glBegin(GL_TRIANGLES);
			for(int i=0; i < num_vertex*3 ; i++ ){
				if( flag & color_flag )
					glColor3fPointer( &r.color );
				if( flag & normal_flag )
					glNormalPointer( &r.normal );
				if( flag & vertex_flag )
					glVertex3fPointer( &r.vertex );
			}//for
		glEnd();
	}
};

I was thinking about something along these lines, but perhaps with a pointer to the object inside the RenderObject struct. I'm looking for ideas, critisism, constructive, or a good definition and explanation of the actual implementation of a renderer.

Share this post


Link to post
Share on other sites
Advertisement
It looks like you search information on designing a SceneGraph. You should try to google for "scenegraph tutorials". There's a lot of articles describing how to implement such a thing.

Basically, I use a tree, made of abstracts "SceneNode". Each SceneNode can be:
- Material (derivative: RenderState of TextureStage)
- Transformation (derivative: Position, Scalar, Rotation, Camera)
- Mesh (derivative: GUIElement, 3DObject)

I use a structure like this:


+ RootNode
+ Camera
+ WoodTexture (Material)
+ TreePosition1 (Position)
+ Mesh (3DObject)
+ TreePosition2
+ Mesh
+ TreePosition3
+ Mesh


Each object "renders" it's sub elements. Actually rendering a material is setting everything in the engine to show the selected material (textures states, and so on).

Each Material, Texture and Mesh are loaded from a static class, which handles IO, loading, saving, and data managment.

Share this post


Link to post
Share on other sites
You seem to be going down much the same path as I was ^_^ I created a scene graph at first that had each object rendering itself, and while that worked nicely it ended up mixing a lot of Render API code with teh game logic, which I didn't like at all... (Neither did the other programmers on the team!)

So I've been working on a generic render system that let's you pass in some of the basic elements of a scene (Verticies, Textures, Shaders, etc.) and then code out all the exact render functions within a nicely encapsulated class.

Ah, what the heck. Let's post some code!


class aQRenderWorld
{
public:
aQRenderWorld( void );
~aQRenderWorld( void );

virtual int Create( HWND hWnd, aQViewParams *params ) = 0;
virtual int Destroy( void ) = 0;

virtual void Begin( void ) = 0;
virtual void End( void ) = 0;

//Handle the processing and rendering of the scene graph.
virtual void Render( aQNode *scene ) = 0;

//Flips the back buffer to the front.
//This is seperate from End() to allow the GPU to process
//the scene while other game logic is preformed.
virtual void Flip( void ) = 0;

virtual void SetMatrix( dword matID, aQMat4 *matrix ) = 0;

//Geometry Handeling
virtual void CreateVertBuffer( dword flags, uint elements, uint* buffer ) = 0;
virtual void CreateIndexBuffer( uint elements, uint* buffer ) = 0;

virtual void FreeBuffer( uint buffer ) = 0;

virtual void SetVertBuffer( uint buffer ) = 0;
virtual void SetIndexBuffer( uint buffer ) = 0;

virtual void FillVertBuffer( void* data ) = 0;
virtual void FillIndexBuffer( uint* data ) = 0;

//Push (or Render) the currently set Vertex and Index Buffers.
virtual void PushStream( dword flags ) = 0;

//Texture/Material Handeling
virtual void LoadTexture( aQString path, uint* texture ) = 0;
virtual void FreeTexture( uint texture ) = 0;
virtual void SetTexture( uint texture ) = 0;

//Text Printing
virtual void Print( int x, int y, char *str, ... ) = 0;

protected:
bool loaded;

//Copy of the view parameters used to create this window.
aQViewParams viewParams;
};



This is ripped straight from my current game code. You can take from it what you want with the understanding that it's still a work in progress, but a few things to point out: Everyting is virtual here, so the actual implementation is compeletely seperate from the structure. In this case, I have an inherited class called aQRenderWorldGL that controld the OpenGL implementation, but it could just as easily be Direct X. Also, just about every graphics resource here is controlled by simple unsigned int handles. This fit's well with the OpenGL design anyways, but it also greatly simplifies data management.

The great thing is, though, that the game code simply passes in a few high level commands and moves on, and how you handle that is up to you. For example, the Push() function could render immediately, but in my implementation it actually sorts the render command onto a stack to be rendered later. The game code never has to know though.

Share this post


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

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!