Render overlay on top of cegui window

For help with general CEGUI usage:
- Questions about the usage of CEGUI and its features, if not explained in the documentation.
- Problems with the CMAKE configuration or problems occuring during the build process/compilation.
- Errors or unexpected behaviour.

Moderators: CEGUI MVP, CEGUI Team

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Re: Render overlay on top of cegui window

Postby CrazyEddie » Mon Mar 01, 2010 16:56

Just to update on this: I did not get the multiple VP support done yet (yeah, yeah, I know! I said the weekend! :oops:). I'm looking at it right now, though. It may even get done today, otherwise, probably Wednesday; I'm having to fit CEGUI work in around a bunch of other stuff at the moment :P

To add to the woes, I'm having serious connectivity issues, so am not able to work in as efficient manner as I'd like :(

CE.

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Re: Render overlay on top of cegui window

Postby CrazyEddie » Mon Mar 01, 2010 19:36

Ok. I have the basic issues resolved. Here's a video:


I just have to test this on Windows for the D3D support, and I'll commit the changes and post back with the details about how it needs to be done along with a bit of a caveat / condition regarding the successful use of this (or in other words, this is still a bit of a hack, so you have to do something to ensure it works correctly).

Watch this space...

CE.

ianstangoe
Quite a regular
Quite a regular
Posts: 79
Joined: Wed Jan 09, 2008 11:06

Re: Render overlay on top of cegui window

Postby ianstangoe » Mon Mar 01, 2010 22:34

Excellent work, eagerly awaiting news :wink:

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Re: Render overlay on top of cegui window

Postby CrazyEddie » Tue Mar 02, 2010 10:35

Ok. I have just committed the mods required to get this support working, most of the rest of this post will deal with the app side of what must be done. Before I get on to that I must mention that I've spotted a graphical glitch when rendering using the D3D render system in Ogre - GL is fine, and plain old D3D is fine, but D3D under Ogre currently exhibits a minor issue with clipping - so if you see some single pixel gaps and/or alignment issues, then this is now a known issue and I'll investigate and fix ASAP.

Ok. On to the goodies...

First the caveat. In the current code we use scissoring to perform clipping when rendering window content. The problem is that the scissor region is not affected by the set viewport (it's always screen space). In order to work around this, when using the following multi-viewport hack, you need to ensure that all your top-level windows have the AutoRenderingSurface property enabled; this way content is cached to texture correctly clipped and the Right Thing is done when drawing back into multiple viewports. It may be possible to work around this issue in the future by using the viewport and projection to perform the scissoring instead (we already do that in Irrlicht, which does not expose scissoring facilities), but for now this limitation exists.

Now, the first thing you need to do is disable CEGUI's use of the _beginFrame and _endFrame calls in Ogre::RenderSystem, you can do this like so:

Code: Select all

// disable calls to _beginFrame and _endFrame, which also disables
// default rendering: we will use a custom rendering method.
myOgreRenderer->setFrameControlExecutionEnabled(false);

As noted in the comment above, this call will automatically disable the usual rendering done by the CEGUI::OgreRenderer, so after making this call, nothing will be drawn.

Now you have to hook back into the rendering process, and we'll do that by way of a Ogre::RenderQueueListener, which is set up in the usual manner, such as:

Code: Select all

myRenderQueueListener = new CEGUIRQListener(myOgreRenderer, Ogre::RENDER_QUEUE_OVERLAY, true);
mySceneManager->addRenderQueueListener(myRenderQueueListener);


Finally, we have the rewritten CEGUIRQListener class, which looks like this:

Code: Select all

//! RenderQueueListener based class used to hook into the ogre rendering system
class CEGUIRQListener : public Ogre::RenderQueueListener
{
public:
   CEGUIRQListener(CEGUI::OgreRenderer* renderer, Ogre::uint8 queue_id, bool post_queue) :
        d_renderer(renderer),
        d_queue_id(queue_id),
        d_post_queue(post_queue)
   {
   }

    void renderQueueStarted(Ogre::uint8 id, const Ogre::String& invocation, bool& skipThisQueue)
    {
        if (!d_post_queue && d_queue_id == id)
            CEGUI::System::getSingleton().renderGUI();
    }

    void renderQueueEnded(Ogre::uint8 id, const Ogre::String& invocation, bool& repeatThisQueue)
    {
        if (!d_post_queue || d_queue_id != id)
            return;

        // need to reset Ogre renderer viewport here for whichever vp is being drawn.
        Ogre::Viewport* vp = Ogre::Root::getSingleton().getRenderSystem()->_getViewport();

        int left, top, width, height;
        vp->getActualDimensions(left, top, width, height);

        const CEGUI::Rect vp_area(left, top, left + width, top + height);
        dynamic_cast<CEGUI::OgreRenderTarget&>(
            d_renderer->getDefaultRenderingRoot().getRenderTarget()).
                setOgreViewportDimensions(vp_area);

        CEGUI::System::getSingleton().renderGUI();
    }

    // methods for adjusting target queue settings
    void setTargetRenderQueue(Ogre::uint8 queue_id)
    {
        d_queue_id = queue_id;
    }

    void setPostRenderQueue(bool post_queue)
    {
        d_post_queue = post_queue;
    }


The above example only has the code that 'does the business' in the renderQueueEnded member function, if you want the same thing in renderQueueStarted, you can either duplicate the code or refactor a bit. I'll just overview on what's going on in there.

Basically, because that function is called for each view port, we have to query the active view port from the Ogre render system, and pass the viewport size to the CEGUI::RenderTarget by way of the setOgreViewportDimensions function.

Hope this is useful ;) You'll have to bear with me on the clipping glitch mentioned at the top of the post, I'll get it fixed soon :)

CE.

ianstangoe
Quite a regular
Quite a regular
Posts: 79
Joined: Wed Jan 09, 2008 11:06

Re: Render overlay on top of cegui window

Postby ianstangoe » Tue Mar 02, 2010 12:06

Hey CE,

That works great! :D

The only issue is the 'AutoRenderingSurface for Top-level windows', what exactly constitutes a top-level window? We use a lot of layouts in one of our apps, so I'd like to automate that property somehow, would it be enough to tag the window returned from loadWindowLayout()? Or is it going to be more involved then that?

Thanks.

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Re: Render overlay on top of cegui window

Postby CrazyEddie » Tue Mar 02, 2010 13:13

In this context, we can define a top level window like this:
The root window or any window that is drawn directly onto either the root window or other full-screen window attached to the root window


For example, in Demo7 that comes with CEGUI there is a full screen root window, a full screen static image, and three frame windows. The AutoRenderingSurface is enabled on the frame windows only, and they are what we consider the top-level windows in that example.

Enabling the AutoRenderingSurface also enables the texture caching (which is the whole point), so which approach is 'best' will also depend largely on your usage. It can be set in the looknfeel for certain window types, or manually on the windows returned from loadWindowLayout as you suggest, or in the layout itself if it's only needed for certain instances of a window type. As an example, caching the entire sheet would be wasteful of resources if you only have a single button displayed - in cases like that, cache the button.

One thing you could do is enable it for the root windows as suggested, and see how things go - you can always go in and tune it later.

CE.

User avatar
wizzler
Just popping in
Just popping in
Posts: 10
Joined: Sat Jan 30, 2010 15:28

Re: Render overlay on top of cegui window

Postby wizzler » Wed Mar 03, 2010 10:45

hehe. nice discussion here. No worries. It's always fun to follow interesting discussions.

I haven't had time to try out the solution yet.

I'll come back with the results this week. ;)

ianstangoe
Quite a regular
Quite a regular
Posts: 79
Joined: Wed Jan 09, 2008 11:06

Re: Render overlay on top of cegui window

Postby ianstangoe » Wed Mar 03, 2010 22:58

Hi wizzler,

sorry for hijacking but this update should solve your request also, it now allows the old style implementation so you can render your gui in any Ogre::RenderQueue, apart from the clipping issue highlighted and the inclusion of the AutoRenderSurface flag it should work fine. :)

drfranz
Just popping in
Just popping in
Posts: 2
Joined: Thu Apr 01, 2010 21:30

Re: Render overlay on top of cegui window

Postby drfranz » Thu Apr 01, 2010 21:36

Greetings,
I'm a noob at Ogre and CEGUI and have been porting my project to Ogre 1.7 and CEGUI 0.7 (current stable svn version) and I'm having the same problem as wizzler. Previously I created a bunch of CEGUI-rtt objects like this: http://www.ogre3d.org/wiki/index.php/Ba ... to_Texture
And on top of them I added an Ogre::OverlayContainer over each rtt.

Now if I create an CEGUIRQListener with post_queue = false all my hud/overlay-objects (including ogre fps/logo etc) disappear and only one or no overlay is visible.
Any tips on how to modify the CEGUIRQListener to get the old behaviour back?

User avatar
CrazyEddie
CEGUI Project Lead
Posts: 6760
Joined: Wed Jan 12, 2005 12:06
Location: England
Contact:

Re: Render overlay on top of cegui window

Postby CrazyEddie » Wed Apr 07, 2010 08:38

You must ALWAYS SPECIFY THE EXACT VERSION OF CEGUI YOU ARE USING. The easiest way to do this is to POST THE SECTION INDICATED IN THE CEGUI LOG FILE. Why do we have to keep reiterating this time and time again?

The CEGUI code is very fluid. The 0.7.1 code differs greatly from the 0.7.0 code, just as the current v0-7 subversion code - or a snapshot - will differ greatly from the released 0.7.1 code. There are things we could advise you to do that will only work with the v0-7 / snapshot code, so unless we know you're using that (or not) no advice can be given, because otherwise we get you guys coming back saying "a, b or c does not work".

All of this said, as far as I recall from my tests, the code above works fine - as in, restores the 0.6.2 behaviour exactly - when used with the v0-7 branch code. It will not work correctly with the 0.7.1 release, as discussed above.

CE

1337
Just popping in
Just popping in
Posts: 9
Joined: Tue Nov 04, 2008 22:54

Re: Render overlay on top of cegui window

Postby 1337 » Tue Apr 26, 2011 05:14

I'm re-hijacking this thread to elaborate on problems related to the original question :wink:

So, the problem we have in our game is that our console hasn't yet moved to CEGUI but uses Ogre Overlays instead. Hence CEGUI needs to be drawn prior to Overlays. For that I've implemented CE's proposed solution based on how CEGUI 0.6.2 works in order to also support CEGUI 0.7.x (most probably >= 0.7.5 because Ubuntu and Debian haven't yet moved to 0.7, Arch uses 0.7.5 and we have our own dependencies for Mac and Windows, both using 0.7.5).

Now it seems like this solution might not work anymore for CEGUI 0.7.5, which is what I'm using right now. Overlays simply stay behind, even if I set the RenderQueue to RENDER_QUEUE_SKIES_LATE, which comes before RENDER_QUEUE_OVERLAY. And I checked that CEGUI::System::renderGUI() is only called from my RQListener.

I know this doens't help much solving the problem at hand. So I have a tiny hint: If I cklick on a button, but unpress the mouse outside that button (so it gets the focus), the Ogre Overlay is then drawn on top of that button. Interestingly it only affects that 'highlighted' Button and nothing else. I can do it with any button but haven't tried it with any other element.
And I've checked: this doesn't happen without the RQListener fix.

Any ideas?

User avatar
Kulik
CEGUI Team
Posts: 1382
Joined: Mon Jul 26, 2010 18:47
Location: Czech Republic
Contact:

Re: Render overlay on top of cegui window

Postby Kulik » Wed Apr 27, 2011 12:52

I remember CE saying something about disabling the automatic rendering and calling renderGUI yourself exactly when you want. I don't know the details off the top of my head though. HTH at least a little bit ;-)

1337
Just popping in
Just popping in
Posts: 9
Joined: Tue Nov 04, 2008 22:54

Re: Render overlay on top of cegui window

Postby 1337 » Wed Apr 27, 2011 12:58

Kulik wrote:I remember CE saying something about disabling the automatic rendering and calling renderGUI yourself exactly when you want. I don't know the details off the top of my head though. HTH at least a little bit ;-)


I suppose you are referring to this line to disable automatic rendering:

Code: Select all

myOgreRenderer->setFrameControlExecutionEnabled(false);


and this line to do the rendering manually in the RQListener:

Code: Select all

    void renderQueueStarted(Ogre::uint8 id, const Ogre::String& invocation, bool& skipThisQueue)
    {
        if (!d_post_queue && d_queue_id == id)
            CEGUI::System::getSingleton().renderGUI();
    }


that's of course implemented.
As I mentioned, it seems to work, at least for that button ^^

User avatar
Jabberwocky
Quite a regular
Quite a regular
Posts: 86
Joined: Wed Oct 31, 2007 18:16
Location: Canada
Contact:

Re: Render overlay on top of cegui window

Postby Jabberwocky » Wed Apr 27, 2011 22:44

Have a look at this:
http://www.ogre3d.org/forums/viewtopic. ... 04&start=0
That is a very old thread, but it might still be relevant. Or might not be. That thread was written back when CEGUI used the old OgreCEGUIRenderer. It now uses the completely rewritten CEGUIOgreRenderer. Still, have a look at the post that discusses resetting the view and projection matrix, that might be your problem.

Also, I should point out an issue (and solution) I found with this code (which was posted earlier on this thread):
void renderQueueStarted(Ogre::uint8 id, const Ogre::String& invocation, bool& skipThisQueue)
{
if (!d_post_queue && d_queue_id == id)
CEGUI::System::getSingleton().renderGUI();
}


I found that I also needed to check the invocation string like this:
void renderQueueStarted(Ogre::uint8 id, const Ogre::String& invocation, bool& skipThisQueue)
{
if (!d_post_queue && d_queue_id == id && invocation == "" )
CEGUI::System::getSingleton().renderGUI();
}


Otherwise I ended up rendering the GUI multiple times per frame, as renderQueueStarted can be called multiple times for the same id - for example if texture shadows are enabled. The additional renderQueueStarted calls for texture shadows all have a different invocation string, so the above check fixes the problem.

The same change needs to be made to renderQueueEnded
The Salvation Prophecy
Space Combat. Planet Exploration. Strategic Domination.

1337
Just popping in
Just popping in
Posts: 9
Joined: Tue Nov 04, 2008 22:54

Re: Render overlay on top of cegui window

Postby 1337 » Thu Apr 28, 2011 00:34

Thank you for digging up some information.

But I'm afraid neither the hack from the Ogre forum nor the invocation string check has made any difference.
I guess I'm going to have to go about it the hard way: compare the new and the old version of the Ogre GUI renderer..


Return to “Help”

Who is online

Users browsing this forum: No registered users and 12 guests