Page 1 of 1

Rendering custom opengl-windows.

Posted: Thu May 07, 2009 07:49
by nesqi
I'm looking for a way to render 3D-graphics within the gui. Creating a CEGUI::Window that renders OpenGL graphics within the gui. Since this seems like something pretty standard I'm a bit confused that I can't find an easy way to do this. I have only found one solution and my question is therefore, is there an easier way?

My idea is this.

Create a custom renderer that has a method for rendering all graphics drawn by the gui so far. My custom 3D-CEGUI::Window will call this from Window::drawSelf and then render its own graphics using a viewport ontop of the underlaying prerendered graphics. Then the rest of the gui windows will continue rendering ontop of this window. This approach requires that the gui renders its components from back to front. I assume this is a fixed design choice since alpha-blending will be hard otherwise.

The custom renderer will not use the zbuffer for layering the gui-graphics, instead it will use rendering order. Is this safe?

I guess i could just render all grapthics onto a texture and insert it into the standard opengl-renderer but I'm afraid this will hit performance.

Surely others have done this before my questing is just how did you do it?

Re: Rendering custom opengl-windows.

Posted: Thu May 07, 2009 19:23
by Jamarr
I needed RTT support for offscreen rendering anyway, so I just added RTT support to CEGUI v0.6.2 so I could also display dynamic scenes /textures in the GUI layer. But my textures do not have to be updated every frame, so the performance hit is minimal. I suspect that if you need to render a constantly changing scene the performance hit could be great.

I don't have any experience with writing custom-renderers, but from what I understand in v0.6.2 there is only 1 global renderer that handles /all/ of the low-level rendering. From what I /think/ I know, the rendering process goes something like this:
  1. some window state is changed; ex, the window is made visible
  2. window::drawSelf is called
  3. if the window needs to be updated, it tells the WindowRenderer to render itself; this is typically some Falagard class
  4. funny enough, the WindowRenderer doesn't actually render anything; it just determines the final rect, ordering, clipping, colors, etc.
  5. the WindowRenderer then stores the image and all of this information into the window's RenderCache
  6. then, back inside drawSelf, we tell the RenderCache to render itself
  7. this goes through the cache and tells all of the images to draw themselves using the associated information
  8. each image then calls addQuad() on the global Render object; this basically pushes the same information into a new Quad cache, but nothing is actually rendered yet
  9. somewhere down the line System::renderGUI() gets called, which tells the global Renderer to render itself;
  10. so the global Renderer goes through and renders all of the quads
  11. it should also be noted that basically anytime a window has to be updated, the entire render/quad cache is re-created

As you can tell most of this process is mis-labled and has some inefficiencies. I think that /only/ creating a custom-renderer would not be enough; the only thing the actual Renderer does is draw some obscure set of quads. The quads are not actually drawn/rendered when drawSelf() is called, and you cannot deduce what quad belongs to what window when renderGUI() is called because that information is not stored in the Quad struct. So if you try to render to the screen when drawSelf() is called, you are going to run into render-ordering problems if you have overlapping windows. Now I am not an expert on this so this may not be entierly accurate, but CE is on break so unless someone else is more familiar with it you'll just have to go through it yourself if you want to know for sure.

Now this is all in v0.6.2. If you use the development v0.7.x (trunk) version of CEGUI, I believe you can create and use custom renderers on a per-window basis as it sounds like you are wanting to do; but I can't say how stable / bug-free this version is as I don't think it has been tested much, and is still actively under development.

Re: Rendering custom opengl-windows.

Posted: Fri May 08, 2009 06:46
by nesqi
Thank you for your very elaborate answer!

After some rethinking I agree with your view on how the renderer works and I still think my Idea is a possible solution if it's adjusted. Here is what I'm thinking.

First of all a create a new renderer. This renderer has a new method called

addGraphics(GraphicsGenerator *g) that is similar to addQuad

from Window::drawSelf or Window::render i add a new GraphicsGenerator that will act just as the Quads do but it can render what ever OpenGL-stuff i want. This GraphicsGenerator will then be called from my virtual Renderer::doRender in the right order mixed with rendering of gui-quads.

This might be how it's working in 0.7 though. I should certainly have a look at the latest devel-version to se if it solves my problems instead of reinventing the wheel.

And again, thank you for your answer.

Re: Rendering custom opengl-windows.

Posted: Tue May 12, 2009 07:02
by nesqi
Hm.. I'm not sure if version 0.7 helps me much.

In the window class I need to register a new WindowRenderer or implement populateGeometryBuffer. Both these populate a GeometryBuffer stored by the Window class with graphics. This means I would have to render my open-gl stuff through the GeometryBuffer interface (most likely not a good idea) or write my own GeometryBuffer that can render the content of my window using my old gl-code.

This is over-complicated for no reason. In my opinion the API is missing a way to render custom graphics in windows. All that is needed is a viewport to render it in. Reimplementing a whole GeometryBuffer is not the way.