Archived

This topic is now archived and is closed to further replies.

TheJakub

Render States

Recommended Posts

I'm having a difficult time figuring out how to manage and optimize render state changes within my engine. I want to be able to only change the texture or material when its needed, not on every render call for an entity. Has someone worked with this in the past? And if so, could you let me in on some ideas as to how I should go about this. Also, would it be a good idea to seperate the world geometry from the entites when rendering. Maybe designing a routine to optimize the render states for the world geometry, before going into some kind of routine for the game elements specifically? [edited by - TheJakub on November 17, 2003 2:03:08 PM]

Share this post


Link to post
Share on other sites
I dealt with this same problem recently. To minimize state changes, you'll have to sort your renderable data by first shader (if you are using them), then material, and then texture.

Each entity in your engine should have renderable data associated with it, consisting of geometry, a texture id, material id, and shader id. What you have to do is send this data to a render queue class, which should sort the data by first shader, then material, then texture. When you go to render, render each renderable data in the order the queue has it in.

My own renderqueue is a linked list(RenderQueueNode) of linked lists(RenderList) that contains sorted CRenderableData. It looks like this (I sort only by shader):

RenderQueueNode -> RenderQueueNode -> RenderQueueNode -> etc
| | |
RenderList RenderList RenderList
| | |
*CRenderableData *CRenderableData *CRenderableData
(shaderID 0) (shaderID 1) (shaderID 2)
| | |
*CRenderableData *CRenderableData *CRenderableData
(shaderID 0) (shaderID 1) (shaderdID 2)
| | |
etc etc etc

Each RenderQueueNode contains a RenderList which is a linked list that holds pointers to CRenderableDatas with all the same properties(same shader id, same material id, same texture id; as state before, in my own engine, I sort only by shader id).

When an entity is created within the engine, it sends a pointer to its CRenderableData to the first node in the RenderQueue. The RenderQueue traverses through each node to find a node with a RenderList that contains CRenderableData with the same properties as the CRenderableData that is being sent. If the engine finds a node that meets these conditions, it adds the the pointer to the CRenderableData to its RenderList. If there are no RenderQueueNodes that contain data with the same properties, a new node is created and the CRenderableData is added to that.

This happens all at load time. During runtime, the engine traverses through each RenderQueueNode and renders everything with in the each node's RenderList, thereby minimizing state changes. Since everything is already sorted, the overhead of sorted each frame is also eliminated. Also, with this kind of set up, you should not have to worry about seperating out the render processes of the world's renderable data and of the smaller game entity's renderable data. As long as what you are rendering has renderable data with a shader, texture, or material id, it can all be sent to the RenderQueue, regardless of whether its world geometry or game entity geometry.

[edited by - GreenToad on November 17, 2003 3:11:54 PM]

Share this post


Link to post
Share on other sites
Thanks for all the help, a complete description to boot I'm gonna start implementing this into my own engine as soon as I can.

edit = speeling

[edited by - TheJakub on November 17, 2003 3:56:57 PM]

Share this post


Link to post
Share on other sites
Note that after the RenderQueue recieves quite a few CRenderableDatas it may be faster to rebuild the RenderQueue each frame from the CRenderableData associated with each visible game entity. Since not all CRenderableData in the game will be visible at one time, traversing through a huge linked list of, for example, 3000 objects, is actually slower than rebuilding and traversing through a linked list of say 200 visible objects. My own setup shows a slow down when there are 1500 nodes in my RenderQueue.

Edit: However, a more efficient approach might be to have the RenderQueue contain only the visible objects, and when a given object loses visibility, it is removed from the queue right then and there, and when it gains visibility again, it is placed back inside the queue. This way, you don't have a massive queue of thousands of unseen objects, and you don't have to resort all the visible objects each frame.

[edited by - GreenToad on November 17, 2003 7:06:19 PM]

Share this post


Link to post
Share on other sites