Compositor RenderableListener problem

Problems building or running the engine, queries about how to use features etc.
Post Reply
Stickymango
Hobgoblin
Posts: 540
Joined: Wed Nov 17, 2004 4:36 pm
Location: Middlesbrough, England

Compositor RenderableListener problem

Post by Stickymango »

Hi,

I have a RenderTargetListener and RenderableListener interface setup to perform a special rendering technique, but I also need a compositor effect adding after that.

The problem is that when I enable the compositor my renderableListener doesn't get called, the RenderTargetListener does get called though, is there a reason why this doesn't work and is there a workaround?

Thanks for any help,
User avatar
sinbad
OGRE Retired Team Member
OGRE Retired Team Member
Posts: 19269
Joined: Sun Oct 06, 2002 11:19 pm
Location: Guernsey, Channel Islands
x 66
Contact:

Post by sinbad »

Hmm, having checked the code I don't see any immediate reason for this, the listener set via RenderQueue::setRenderableListener is not tampered with by compositors at all. The only thing I can think of is that you're using multiple Scenemanagers and therefore multiple render queues, and something is getting attached to the wrong one or something.
Stickymango
Hobgoblin
Posts: 540
Joined: Wed Nov 17, 2004 4:36 pm
Location: Middlesbrough, England

Post by Stickymango »

Oh, I shall make sure I'm not doing anything stupid in my code but I am literally calling CompositorInstance::setEnabled() and then my listener isn't called, I comment that line out and its fine :?

I'm using a single SceneManager.
Stickymango
Hobgoblin
Posts: 540
Joined: Wed Nov 17, 2004 4:36 pm
Location: Middlesbrough, England

Post by Stickymango »

Update:

I've narrowed the problem down a bit further but should explain exactly what I'm doing first.

What I have at the moment is a two viewports rendering different halves of the screen, on the right hand side I'm using RenderTargetListener/RenderableListener to perform a Depth render of the scene in the left hand side of the screen, pretty much the same code as used in DWORD's Dof demo. What I then need to do is apply a compositor effect to both viewports.

I load my compositor effect and call:

Code: Select all

mInst1 = mCompositorManager->addCompositor(vp1, "Effect");
mInst2 = mCompositorManager->addCompositor(vp2, "Effect");
mInst1->setEnabled(true);
mInst2->setEnabled(true);
However, its the enabling of the second instance that causes my RenderableListener to NOT be called resulting in a normal render of the scene in both viewports, I comment out the second instance enabling, and the output is what I expect ( normal scene/depth render ) but the only the left-hand viewport has the compositor...

This seems odd and possibly a bug? I've not had a problem before using the same compositor effect on two viewports but I wasn't using listeners then...

Any ideas what might be going on?
User avatar
manowar
Orc
Posts: 419
Joined: Thu Apr 07, 2005 2:11 pm
Location: UK
Contact:

Post by manowar »

Having the same issues I have done a bit of testing and found some interesting stuff when the compositors are enabled.

Consider this class (I only keep the interesting information):

Code: Select all

class MyClass : public Ogre::RenderTargetListener,
			  public Ogre::RenderQueue::RenderableListener
{
...
}
Then the 3 overriden functions:

Code: Select all

void	MyClass::preViewportUpdate(const Ogre::RenderTargetViewportEvent& evt)
{	
     RenderQueue* queue = evt.source->getCamera()->getSceneManager()->getRenderQueue();
     queue->setRenderableListener(this);
     Ogre::LogManager::getSingleton().logMessage("preViewportUpdate");
}

Code: Select all

void	MyClass::postViewportUpdate(const Ogre::RenderTargetViewportEvent& evt)
{
     Ogre::LogManager::getSingleton().logMessage("postViewportUpdate");
}

Code: Select all

bool	MyClass::renderableQueued(Renderable* rend, Ogre::uint8 groupID, Ogre::ushort priority, Technique** ppTech)
{		
	Ogre::LogManager::getSingleton().logMessage("Renderable queue");
	return true;	
}
The render target has 2 viewports and the render target listener is registered. We have also a compositor that can be applied on both viewports.

This is the call orders when compositors are disabled:
...
// First viewport
preViewportUpdate
Renderable queue
postViewportUpdate

// Second viewport
preViewportUpdate
Renderable queue
postViewportUpdate

// First viewport
preViewportUpdate
Renderable queue
postViewportUpdate

// Second viewport
preViewportUpdate
Renderable queue
postViewportUpdate
...

However when the compositors are both enabled we have:
...
// Firstviewport
preViewportUpdate
postViewportUpdate
// Second viewport
preViewportUpdate
postViewportUpdate
Renderable queue

// Firstviewport
preViewportUpdate
postViewportUpdate
// Second viewport
preViewportUpdate
postViewportUpdate
Renderable queue
...
You can see what is the problem and why the rendering for each view port can be wrong when changing settings before/after the viewport updates !

Now the question is, why is the calls order changing when enabling compositors ?

Thanks for any help

PS. This is probably the reason why the RenderableListener was not called in the previous posts.

This bit of code in postViewportUpdate to 'unregister' the RenderableListener was certainly not called at the right moment, when the compositors were enabled.

Code: Select all

RenderQueue* queue = evt.source->getCamera()->getSceneManager()->getRenderQueue();
queue->setRenderableListener(0);
jj
Halfling
Posts: 50
Joined: Thu Apr 03, 2008 1:33 am

Re: Compositor RenderableListener problem

Post by jj »

Hey,

I'm having the same problem with Ogre 1.7.2. Any solution to this?

Any help would be really appreciated!

jj
Shimayama
Halfling
Posts: 74
Joined: Sat Apr 25, 2009 2:20 pm
Location: Norway
x 1

Re: Compositor RenderableListener problem

Post by Shimayama »

I've had the same problem recently.

I found out that CompositorChain is also a RenderTarget::Listener and will add itself as a listener to the same RenderTarget as our own listener, which will cause some conflicts.

It appears to me that the actual scene is rendered in CompositorChain::preRenderTargetUpdate(), since it is rendered to a texture that will be used by the compistor later on when it renders the screen space quad used for the compositor effects.

The problem here is that any preViewportUpdate() will therefore always be invoked after the default scene has been rendered to the texture. This is definitely a bug in Ogre, since Ogre should ensure that preViewportUpdate() always happens before the viewport is updated! I can see one arguing that it actually is invoked before the last compositor quad is rendered to the final screen buffer, but I think most people would assume preViewportUpdate() to be invoked before start updating the viewport with the default scene, not just that last compositor quad.

Here are the logs from my own listener:

Red = Events of interest
Green = Stuff added to render queue, which we want to control per viewport (from preViewportUpdate).
Blue = Rendering

One can easily see in the logs below that when compositors are enabled, the scene is added to render queues and rendered (green and blue) before preViewportUpdate() (in red), which is incorrect.

Without compositors:

14:43:06: frameStarted 152
14:43:06: preRenderTargetUpdate 152 ptr = 0833FC80
14:43:06: preViewportUpdate 152 ptr = 0E856418
14:43:06: renderableQueued (a renderable was added to queue. Not yet rendered, just queued!)
... lots of them
14:43:06: renderableQueued

14:43:06: preRenderQueues (before actual rendering)
14:43:06: renderQueueStarted id = 0
14:43:06: renderQueueEnded id = 0
14:43:06: renderQueueStarted id = 5
14:43:06: renderQueueEnded id = 5
14:43:06: renderQueueStarted id = 7
14:43:06: renderQueueEnded id = 7
14:43:06: renderQueueStarted id = 9
14:43:06: renderQueueEnded id = 9
14:43:06: renderQueueStarted id = 50
14:43:06: renderQueueEnded id = 50
14:43:06: renderQueueStarted id = 95
14:43:06: renderQueueEnded id = 95
14:43:06: renderQueueStarted id = 100
14:43:06: renderQueueEnded id = 100
14:43:06: postRenderQueues (after actual rendering)

14:43:06: postViewportUpdate 152 ptr = 0E856418
14:43:06: postRenderTargetUpdate 152 ptr = 0833FC80
14:43:06: frameEnded 153



With compositors:


14:43:15: frameStarted 303
14:43:15: preRenderTargetUpdate 303 ptr = 0833FC80
(CompositorChain::preRenderTargetUpdate() is most certainly invoked here, causing the scene to render since the compositor needs to update its textures)
14:43:15: renderableQueued
... lots of them (probably the normal scene)
14:43:15: renderableQueued

14:43:15: preRenderQueues (my guess is that here starts the normal scene rendering)
14:43:15: renderQueueStarted id = 0
14:43:15: renderQueueEnded id = 0
14:43:15: renderQueueStarted id = 5
14:43:15: renderQueueEnded id = 5
14:43:15: renderQueueStarted id = 7
14:43:15: renderQueueEnded id = 7
14:43:15: renderQueueStarted id = 9
14:43:15: renderQueueEnded id = 9
14:43:15: renderQueueStarted id = 50
14:43:15: renderQueueEnded id = 50
14:43:15: renderQueueStarted id = 95
14:43:15: renderQueueEnded id = 95
14:43:15: renderQueueStarted id = 100
14:43:15: renderQueueEnded id = 100
14:43:15: postRenderQueues (normal scene rendering finished)

14:43:15: renderableQueued
... lots of them (probably the normal scene again, with compositor schemes set for g-buffer)
14:43:15: renderableQueued

14:43:15: preRenderQueues (probably full scene rendering of g-buffer containing depths and normals to be used by compositor)
14:43:15: renderQueueStarted id = 0
14:43:15: renderQueueEnded id = 0
14:43:15: renderQueueStarted id = 5
14:43:15: renderQueueEnded id = 5
14:43:15: renderQueueStarted id = 7
14:43:15: renderQueueEnded id = 7
14:43:15: renderQueueStarted id = 9
14:43:15: renderQueueEnded id = 9
14:43:15: renderQueueStarted id = 50
14:43:15: renderQueueEnded id = 50
14:43:15: renderQueueStarted id = 95
14:43:15: renderQueueEnded id = 95
14:43:15: renderQueueStarted id = 100
14:43:15: renderQueueEnded id = 100
14:43:15: postRenderQueues
14:43:15: preRenderQueues (maybe first compositor quad. Should be 4 render_quad commands for this particular compositor.)
14:43:15: renderQueueStarted id = 0
14:43:15: renderQueueStarted id = 5
14:43:15: renderQueueStarted id = 7
14:43:15: renderQueueStarted id = 9
14:43:15: renderQueueStarted id = 50
14:43:15: renderQueueStarted id = 95
14:43:15: renderQueueStarted id = 100
14:43:15: renderQueueEnded id = 100
14:43:15: postRenderQueues
14:43:15: preRenderQueues (maybe second compositor quad.)
14:43:15: renderQueueStarted id = 0
14:43:15: renderQueueStarted id = 5
14:43:15: renderQueueStarted id = 7
14:43:15: renderQueueStarted id = 9
14:43:15: renderQueueStarted id = 50
14:43:15: renderQueueStarted id = 95
14:43:15: renderQueueStarted id = 100
14:43:15: renderQueueEnded id = 100
14:43:15: postRenderQueues
14:43:15: preRenderQueues (maybe third compositor quad.)
14:43:15: renderQueueStarted id = 0
14:43:15: renderQueueStarted id = 5
14:43:15: renderQueueStarted id = 7
14:43:15: renderQueueStarted id = 9
14:43:15: renderQueueStarted id = 50
14:43:15: renderQueueStarted id = 95
14:43:15: renderQueueStarted id = 100
14:43:15: renderQueueEnded id = 100
14:43:15: postRenderQueues

14:43:15: preViewportUpdate 303 ptr = 0E856418
14:43:15: renderableQueued
14:43:15: renderableQueued
14:43:15: renderableQueued
14:43:15: renderableQueued
14:43:15: renderableQueued
14:43:15: renderableQueued
14:43:15: renderableQueued
14:43:15: renderableQueued
14:43:15: renderableQueued
14:43:15: renderableQueued
14:43:15: renderableQueued
14:43:15: renderableQueued
14:43:15: renderableQueued
14:43:15: renderableQueued
14:43:15: renderableQueued

14:43:15: preRenderQueues (probably the last 4th compositor quad, or all of them. Should be 4 render_quads in total for this particular compisitor.)
14:43:15: renderQueueStarted id = 0
14:43:15: renderQueueStarted id = 5
14:43:15: renderQueueStarted id = 7
14:43:15: renderQueueStarted id = 9
14:43:15: renderQueueStarted id = 50
14:43:15: renderQueueStarted id = 95
14:43:15: renderQueueStarted id = 100
14:43:15: renderQueueEnded id = 100
14:43:15: postRenderQueues

14:43:15: postViewportUpdate 303 ptr = 0E856418
14:43:15: postRenderTargetUpdate 303 ptr = 0833FC80
14:43:15: frameEnded 303
Post Reply