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();
}
};
Role of the renderer
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.
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.
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:
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.
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.
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!
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.
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.
This topic is closed to new replies.
Advertisement
Popular Topics
Advertisement