[seems *solved*] Manual renders via renderQueueStarted/Ended

nullsquared

12-01-2008 23:17:50

I have some complicated "external" scene renders which can't work with render queues, so I render them manually after the main render.

However, this causes big problems with the GUI (big white patches, incorrect drawings, etc.). So I removed the manager from the render queue listeners and called renderQueueStarted and renderQueueEnded myself manually after my other "external" renders.

Now, this works perfectly under OpenGL. However, under Direct3D, I get this:

OGRE EXCEPTION(3:RenderingAPIException): Failed to DrawPrimitive : Invalid call in D3D9RenderSystem::_render at E:\ogrenew\RenderSystems\Direct3D9\src\OgreD3D9RenderSystem.cpp (line 2719)


I understand this seems like a completely internal Ogre bug that's not QuickGUI's fault... but it works under D3D when I put it in a render queue (and don't render my "external" stuff, obviously). So I was wondering if you knew what render queues did for D3D differently from OpenGL, such that OpenGL works fine, yet D3D fails?

Thanks a bunch in advance.

EDIT: Looks at my lower post for what seems to have fixed it for me.

kungfoomasta

13-01-2008 05:13:26

I'm not really familiar with the lower level working of how Ogre does Rendering. Maybe if you posted this in the Development forum the more knowledgable people can answer. Sorry!

nullsquared

13-01-2008 13:54:39

Heh, no problem. I bet it's just some odd initialization bug or something that the render queues do and I don't.

Either way, QuickGUI is awesome... it's just so stable and easy to use, I don't know what I'd do without it :D. Great job on it!

kungfoomasta

14-01-2008 17:49:54

nullsquared, thanks! :)

If you find any simple fixes or features please post. Complex ones are important also, but I already have a big TODO list, and time is scarce. :wink:

nullsquared

14-01-2008 21:05:15

nullsquared, thanks! :)

If you find any simple fixes or features please post. Complex ones are important also, but I already have a big TODO list, and time is scarce. :wink:


Well, I dug through Ogre's source, and saw 1 thing jump out at me: when SceneManager::_renderScene() gets ready to call _renderVisibleObjects(), it called RenderSystem::_beginFrame(). After the rendering, it called RenderSystem::_endFrame().

So now manual rendering of QuickGUI looks like so:

// on init
GUI->setRenderQueueID(GUI_RQ);
GUI->removeFromRenderQueue();

// in loop
renderSys->_beginFrame();

std::string _tempStr = "_tempStr";
bool _tempBool = false;

GUI->renderQueueStarted(GUI_RQ, _tempStr, _tempBool);
GUI->renderQueueEnded(GUI_RQ, _tempStr, _tempBool);

renderSys->_endFrame();

_tempString and _tempBool are just there since those functions "need them". Supposedly, QuickGUI doesn't use them (from a quick look at the source), so they shouldn't be of trouble. In fact, you can pass in std::string() for the _tempString since it's a const reference, but you can't pass in bool() for the 3rd param in GCC (I remember VC++'s unstandardized compiler was OK with it) since it's not a const reference.

Now, I do not guarantee any "correctness" here, but, hey, it works :D - and I don't notice any problems with performance or visuals or anything ;) I actually like doing this type of "deep digging", I got used to it when I got to use the RenderSystem directly a bunch of times for my portals. Fun stuff :D

Anyways, kungfoomasta, great job, good luck, and _thanks_!

kungfoomasta

14-01-2008 21:23:41

Interesting! From the online API docs:

virtual void _beginFrame (void)=0
Signifies the beginning of a frame, ie the start of rendering on a single viewport.

virtual void _endFrame (void)=0
Ends rendering of a frame to the current viewport.


So is all of your rendering manually done? I wonder what would happen if you called this when ogre is set to automatically render. I imagine you call begin, do all of your rendering (not only GUI), and then call end. So it might not be so useful for people who have ogre automatically render, or make use of higher level functions like "renderOneFrame".

I don't use the string or bool, I just needed to keep the same signature, since I inherit from Ogre::RenderQueueListener.

nullsquared

14-01-2008 21:41:33

Interesting! From the online API docs:

virtual void _beginFrame (void)=0
Signifies the beginning of a frame, ie the start of rendering on a single viewport.

virtual void _endFrame (void)=0
Ends rendering of a frame to the current viewport.


So is all of your rendering manually done? I wonder what would happen if you called this when ogre is set to automatically render. I imagine you call begin, do all of your rendering (not only GUI), and then call end. So it might not be so useful for people who have ogre automatically render, or make use of higher level functions like "renderOneFrame".

I don't use the string or bool, I just needed to keep the same signature, since I inherit from Ogre::RenderQueueListener.


Well, I use SceneManager::_renderScene() in most cases, and "some" manual rendering via RenderSystem::_render(). SceneManager::_renderScene() does indeed call _beginFrame()/_endFrame() before and after it renders all of the visible objects (_renderVisibleObjects()), so there's really not much to be done.

The reason stuff seemed to work perfectly before is because all of the render queues were called in between the _renderScene()'s begin/end.

If Ogre renders automatically via renderOneFrame() or startRendering() and FrameListeners, this might not be "too" useful for 1 reason: the window's buffer is already swapped. I manually swap my buffer after all of my manual rendering and GUI rendering, so that's why it works seamlessly.

Then again, I don't really see a reason to manually render the GUI if one's using renderOneFrame(). Really, the only reason I needed to do this is because I render stuff after the main scene without a render queue, so I needed the GUI to appear on top of it - which would be impossible if it was a render queue listener of the main scene.

kungfoomasta

14-01-2008 21:53:28

I noticed that before rendering the GUI I make a call to

RenderSystem::_setViewport

However I never revert it to what is was previously. I'll add this in, I don't know if it will change anything, but its good to error on the side of caution.

nullsquared

14-01-2008 21:59:09

I noticed that before rendering the GUI I make a call to

RenderSystem::_setViewport

However I never revert it to what is was previously. I'll add this in, I don't know if it will change anything, but its good to error on the side of caution.

I actually don't think that is necessary:

// from SceneManager::_renderScene()
// Set the viewport - this is deliberately after the shadow texture update
setViewport(vp);

// later on
void SceneManager::setViewport(Viewport* vp)
{
mCurrentViewport = vp;
// Set viewport in render system
mDestRenderSystem->_setViewport(vp);
// Set the active material scheme for this viewport
MaterialManager::getSingleton().setActiveScheme(vp->getMaterialScheme());
}

_renderScene already does that, and if I'm not mistakened, it's what calls all of the render queues.

kungfoomasta

14-01-2008 22:04:36

Yah, after thinking about it some more, I think that anybody who renders would probably set the viewport accordingly. No wonder I didn't see this in the other GUI library implementations. :wink: