RenderQueues

Started by
2 comments, last by Jason Z 13 years, 4 months ago
I have been stumped on a design for more than a few months. Wondering if someone can give some info on how they tackle this.

I implemented the start of a simple RenderQueue. The RenderQueue as is just has Insert, Remove, and Render methods. Its purpose is to sort Renderables and call thier corresponding Render methods in the correct order. This seemed simple enough and a good assumption on how a RenderQueue works in a real engine. Tell me if I am wrong!

Obviously, I need a Renderable base class in order to put things in the queue. So, I imagined a renderable being a single entity that is going to be rendered and gave it some data including an effect to use, as well as a pointer to buffers. Additionally a Renderable is derived from a Transform, as I thought that surely anything that is rendered would have a transform! I gave Renderable an enum to tell the queue which order to render things:

enum RenderType
{
RENDERTYPE_OPAQUE = 0,
RENDERTYPE_TRANSPARENT,
RENDERTYPE_SCREEN,
RENDERTYPE_UI,
NUM_RENDER_TYPES
};

Now the problem arrises when I created a LensFlare class. A LensFlare is something that is rendered, so I want to plop it into the RenderQueue. In order to do that I should derive it from Renderable. Problem is a LensFlare really isn't a single thing to be rendered! It consists of a occlusion test (a square), a glow, and 3 flares, all of which are pretty much 2D squares with some transparency. The occlusion test is rendered at a position far back in the scene while the flares are rendered at the screen level. Furthermore, the Lensflare has more than one effect that needs to be used per frame, one for occlusion test and one for everything else. It also doesn't have a single transform, but rather just a light position.

I am not sure how to handle this. The easy choice would be to alter the RenderQueue to have a seperate method to insert LensFlares as a special case, but that feels really hacky. What happens down the road when I want to insert complex models made of parts for that matter?

Another thought was to seperate the Lensflare into components and insert them seperatly, but I am not sure how that would turn out either, especially since they would have to communicate with eachother to get the occlusion test result.

Does anyone have some design advice here that would help sort out this mess? There doesn't seem to be much out there on the internal workings of a RenderQueue in a real engine. Open source inspection really hasn't helped me much in this scenario either.





Advertisement
I think part of the problem is that you are mixing two different classes of operations. In my engine I define a single draw call as an 'Entity3D' class, which would something along the lines of your Renderable (although it also has 3D information as well). Your lense flare rendering is a sequence of the draw calls, each with varying purposes (i.e. predicated rendering, drawing, and blooming).

Since it uses more than one call, it is fundamentally different than a single object being rendered - this is exactly what you pointed out below. For more complex rendering sequences that should not be split up by the engine, I provide a 'RenderView' class that manages all of the individual sequence handling. This allows for the sequence to be defined within an object, and then you can treat the whole RenderView as a sortable object too. This is what your lens flare sounds like to me - a complex sequence of objects that need to be rendered.

Personally, I prefer to keep the views at a higher organizational level than the individual Entity3D instances (i.e. the views are using the Entity3Ds), but could do it either way.
Quote:Original post by Jason Z
I think part of the problem is that you are mixing two different classes of operations. In my engine I define a single draw call as an 'Entity3D' class, which would something along the lines of your Renderable (although it also has 3D information as well). Your lense flare rendering is a sequence of the draw calls, each with varying purposes (i.e. predicated rendering, drawing, and blooming).

Since it uses more than one call, it is fundamentally different than a single object being rendered - this is exactly what you pointed out below. For more complex rendering sequences that should not be split up by the engine, I provide a 'RenderView' class that manages all of the individual sequence handling. This allows for the sequence to be defined within an object, and then you can treat the whole RenderView as a sortable object too. This is what your lens flare sounds like to me - a complex sequence of objects that need to be rendered.

Personally, I prefer to keep the views at a higher organizational level than the individual Entity3D instances (i.e. the views are using the Entity3Ds), but could do it either way.


Yes, it sounds like you are understanding. I do think I need to make a class that contains seperate entities to be rendered at some point. I know there will be models with multiple parts for example.

However, I am still unsure whether to treat the lensflare that way. The reason being tht the entire thing except for the occlusion test is drawn at screen level...I think the occlusion test is too for that matter if I understand the XNA example I orginally wrote it from.

How does your RenderQueue and RenderView work for say a model surrounded by particle effects where the two are grouped? Say like a sword with sparklies around it ala modern mmos. They are two entities that probably have a transform multiplied by another as they are positonally related, they are probably also related in that they both need to be rendered or not, but are drawn at different times during a frame in different ways right? How does that work as far as sorting and removing?
The particle system would be an Entity3D, and would likely be attached to the sword in the spatial hierarchy. Both would be rendered as an Entity3D separately, and would be sorted based on their rendering type. I have a similar enumeration as you showed above to discern standard geometry, alpha geometry, screen space stuff, text, etc... Then each render view has the option of sorting by object type to perform rendering. This is how I do normal scene rendering too - a standard perspective rendering is encapsulated in a render view.

However, your lens flare is more like a post process than an object IMO. If you really wanted to treat it like an object, you could just add the appropriate code into its render method - although it likely wouldn't be very performant...

This topic is closed to new replies.

Advertisement