Where does quickgui draw stuff?

chunky

25-04-2008 04:39:51

OK, so, I'm quite confused.

I have a framelistener that grabs an image of the entire window every frameEnded, and renders it using aalib. It's a terrible disgusting hack, but aalib has always given me the warm fuzzies

FWIW, the source is here: aaframelistener-2008-04-24.tar.gz, but basically what it does is jam a rendertexture into the system that exactly uses the camera I have for the main game.

What's strange is that everything appears in the aalib window, except for quickgui stuff. In the screenshot below you see I have the console open in the right [ogre] window, but in the left window, aalib doesn't show the console [the fps and speed at the top are currently done using an ogre overlay, we'll move them to quickgui eventually]. Any ideas what's up with that? The resolution is really weak, but you should see some manner of blob in the bottom left of the AALib window

Clicky for bigger version:


Thanks,
Gary (-;

kungfoomasta

25-04-2008 05:03:21

Thats odd. QuickGUI uses the Ogre::RenderSystem class, along with the RenderOperation and HardwareVertexBuffer to render quads. The GUIManager is a render queue listener, and it renders at the end of the OVERLAY render queue is drawn.

What happens if you take a screenshot via code, are quickgui widgets visible? If so, you can look at that and see how its done. I imagine using the hardware pixel buffer of the viewport's render target, and copying that to an ogre texture and saving it to disk.

chunky

25-04-2008 20:48:40

Yay, now I'm still confused.

twshot04252008_123546116.png

It got the GUI in it when I used RenderWindow::writeContentsToTimestampedFile.

Any more suggestions? I linked the actual source in my first post, if that would help any

Thank-you very much,
Gary (-;

kungfoomasta

25-04-2008 22:04:03

Use the source, Luke!

Here is your code:


bool TWAAFrameListener::frameEnded(const Ogre::FrameEvent& evt) {
#ifdef HAVE_AALIB
if(NULL == mAAContext) return true;

// Read pixels
// Probably could just point pbuffer at the aalib pixel buffer instead
// but that runs greater risk of an overflow
size_t size = aa_imgwidth(mAAContext) * aa_imgheight(mAAContext) * 4;
char pBuffer[size];
Ogre::PixelBox pbox(aa_imgwidth(mAAContext),aa_imgheight(mAAContext), 1, Ogre::PF_L8, pBuffer);
Ogre::HardwarePixelBufferSharedPtr hpBuffer = mTexturePtr->getBuffer(0,0);
hpBuffer->blitToMemory(pbox);

int i,j;
for(i=aa_imgwidth(mAAContext)-1; i>=0; i--) {
for(j=aa_imgheight(mAAContext)-1; j>=0; j--) {
aa_putpixel(mAAContext, i,j, pBuffer[i+j*aa_imgwidth(mAAContext)]);
}
}

aa_render(mAAContext, mAAParams, 0, 0,
aa_imgwidth(mAAContext), aa_imgheight(mAAContext));
aa_flush(mAAContext);
#endif //HAVE_AALIB

//memset(c->imagebuffer,0,aa_imgwidth(c)*aa_imgheight(c)); // Not necessary since we write all pixels

return true;
}


And here is how Ogre's Render Target writes image data to a file:


void RenderTexture::writeContentsToFile( const String & filename )
{
// copyToMemory
ImageCodec::ImageData *imgData = new ImageCodec::ImageData();

imgData->width = mWidth;
imgData->height = mHeight;
imgData->depth = 1;
imgData->format = PF_BYTE_RGBA;
size_t size = imgData->width * imgData->height * 4;

// Allocate buffer
uchar* pBuffer = new uchar[size];

// Read pixels
mBuffer->blitToMemory(
Box(0,0,mZOffset,mWidth,mHeight,mZOffset+1),
PixelBox(mWidth, mHeight, 1, imgData->format, pBuffer)
);

// Wrap buffer in a chunk
MemoryDataStreamPtr stream(new MemoryDataStream(
pBuffer, size, false));

// Get codec
size_t pos = filename.find_last_of(".");
String extension;
if( pos == String::npos )
OGRE_EXCEPT(
Exception::ERR_INVALIDPARAMS,
"Unable to determine image type for '" + filename + "' - invalid extension.",
"GLRenderTexture::writeContentsToFile" );

while( pos != filename.length() - 1 )
extension += filename[++pos];

// Get the codec
Codec * pCodec = Codec::getCodec(extension);

// Write out
Codec::CodecDataPtr codecDataPtr(imgData);
pCodec->codeToFile(stream, filename, codecDataPtr);

delete [] pBuffer;
}


I'm still learning when it comes to pixel manipulation, so I can't directly provide a solution, but all the information is here. From a quick glance I see that you're code uses Ogre::PF_L8 and Ogre uses PF_BYTE_RGBA. In the worst case you could always write the viewport contents to file, load the file as an Ogre::Texture, and iterate through its buffer that way.

chunky

28-04-2008 22:34:49

Yep, using the source is how I got this far...

The texture format doesn't make a difference. I just use 8-bits-of-luminance because that more conveniently maps onto what AAlib asks for.

I tried switching to that blitToMemory with an Ogre::Box as the first param, but it made no difference. As far as I can tell the root problem is that the manual texture I create is created in such a way that QuickGUI doesn't end up rendered on it, but I don't know how or why that would be the case.

Any suggestions?

The pertinent bit of code [I think] is this one:
mTexturePtr = Ogre::TextureManager::getSingleton().createManual("AARttTex",
Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP_NAME,
Ogre::TEX_TYPE_2D,
mWindow->getWidth(),
mWindow->getHeight(),
1,
Ogre::PF_L8,
Ogre::TU_RENDERTARGET);

mRttTex = mTexturePtr->getBuffer()->getRenderTarget();

if(NULL != mRttTex) {
Ogre::Viewport *v = mRttTex->addViewport( mCam );
v->setClearEveryFrame( true );
v->setBackgroundColour( Ogre::ColourValue::Black );
}


Thank-you very much,
Gary (-;

kungfoomasta

28-04-2008 23:59:31

Here is one way you could approach this problem, although its not the most efficient. I'm not knowledgable enough to give a better solution. :P


mViewport->writeContentsToFile(myFileName);
Ogre::TexturePtr tp = Ogre::TextureManager::getSingleton().loadImage(myFileName,Ogre::ResourceGroupManager::DEFAULT_RESOURCE_GROUP);

// Read pixels
// Probably could just point pbuffer at the aalib pixel buffer instead
// but that runs greater risk of an overflow
size_t size = aa_imgwidth(mAAContext) * aa_imgheight(mAAContext) * 4;
char pBuffer[size];
Ogre::PixelBox pbox(aa_imgwidth(mAAContext),aa_imgheight(mAAContext), 1, Ogre::PF_L8, pBuffer);
Ogre::HardwarePixelBufferSharedPtr hpBuffer = tp->getBuffer(0,0);
...


Gotta run, sorry for being incomplete!

chunky

29-04-2008 06:32:01

Ew, totally avoiding the real issue :-)

Actually, since this whole thing is most an experiment in ogre than anything else, I'd really love to figure out the "correct" way to do this for future reference :-)

Gary (-;