E. Wing
2007-01-10 04:54:27 UTC
I'm trying to render to an image which I can do things with. My most
immediate desire is to throw the image at a printer (or Apple's
built-in PDF writer though I intend to reuse the code to do other
things that require an image capture.)
To do this, I got it in my head that the best way to do this is to use
a Framebuffer Object. It seemed this is the OpenGL
standard/cross-platform way to do things and it also allows me to
render the scene at an optimal size that is not necessarily tied to
the onscreen window size (good if I need to adjust sizes for printing
to paper or whatever).
So being new to FBO's, I took heavily from the osgprerender example
(which does work). But unlike the osgprerender example, I want to
render to an osg::Image and don't need to reuse the image in a texture
within the scene. But so far, I am only getting a blank osg::Image
when I try. I probably misunderstand how to setup everything.
Can anybody tell me where I'm going wrong? Below is an excerpt of my code.
Thanks,
Eric
// In my draw routine
{
osg::Camera* the_camera = simpleViewer->getCamera();
the_camera->setRenderOrder(osg::Camera::PRE_RENDER);
the_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
osg::ref_ptr<osg::Image> osg_image = new osg::Image;
osg_image->allocateImage(viewport_width, viewport_height, 1,
GL_RGBA, GL_UNSIGNED_BYTE);
// attach the image so its copied on each frame.
the_camera->attach(osg::Camera::COLOR_BUFFER, osg_image.get());
// I tried with a callback and without, same result
the_camera->setPostDrawCallback(new
MyCameraPostDrawCallback(osg_image.get()));
simpleViewer->frame();
[[self openGLContext] flushBuffer];
// Need to block to make sure image gets rendered so I can use it?
glFinish();
// write the image here
osgDB::writeImageFile(*osg_image, "/tmp/MyWriteInDraw.png");
// Restore normal rendering
the_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER);
the_camera->detach(osg::Camera::COLOR_BUFFER);
}
// My Callback
class MyCameraPostDrawCallback : public osg::Camera::DrawCallback
{
public:
MyCameraPostDrawCallback(osg::Image* image):
_image(image)
{
}
virtual void operator () (const osg::Camera& /*camera*/) const
{
if (_image && _image->getPixelFormat()==GL_RGBA &&
_image->getDataType()==GL_UNSIGNED_BYTE)
{
osgDB::writeImageFile(*_image, "/tmp/MyWriteImageInCallback.png");
}
}
osg::Image* _image;
};
immediate desire is to throw the image at a printer (or Apple's
built-in PDF writer though I intend to reuse the code to do other
things that require an image capture.)
To do this, I got it in my head that the best way to do this is to use
a Framebuffer Object. It seemed this is the OpenGL
standard/cross-platform way to do things and it also allows me to
render the scene at an optimal size that is not necessarily tied to
the onscreen window size (good if I need to adjust sizes for printing
to paper or whatever).
So being new to FBO's, I took heavily from the osgprerender example
(which does work). But unlike the osgprerender example, I want to
render to an osg::Image and don't need to reuse the image in a texture
within the scene. But so far, I am only getting a blank osg::Image
when I try. I probably misunderstand how to setup everything.
Can anybody tell me where I'm going wrong? Below is an excerpt of my code.
Thanks,
Eric
// In my draw routine
{
osg::Camera* the_camera = simpleViewer->getCamera();
the_camera->setRenderOrder(osg::Camera::PRE_RENDER);
the_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
osg::ref_ptr<osg::Image> osg_image = new osg::Image;
osg_image->allocateImage(viewport_width, viewport_height, 1,
GL_RGBA, GL_UNSIGNED_BYTE);
// attach the image so its copied on each frame.
the_camera->attach(osg::Camera::COLOR_BUFFER, osg_image.get());
// I tried with a callback and without, same result
the_camera->setPostDrawCallback(new
MyCameraPostDrawCallback(osg_image.get()));
simpleViewer->frame();
[[self openGLContext] flushBuffer];
// Need to block to make sure image gets rendered so I can use it?
glFinish();
// write the image here
osgDB::writeImageFile(*osg_image, "/tmp/MyWriteInDraw.png");
// Restore normal rendering
the_camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER);
the_camera->detach(osg::Camera::COLOR_BUFFER);
}
// My Callback
class MyCameraPostDrawCallback : public osg::Camera::DrawCallback
{
public:
MyCameraPostDrawCallback(osg::Image* image):
_image(image)
{
}
virtual void operator () (const osg::Camera& /*camera*/) const
{
if (_image && _image->getPixelFormat()==GL_RGBA &&
_image->getDataType()==GL_UNSIGNED_BYTE)
{
osgDB::writeImageFile(*_image, "/tmp/MyWriteImageInCallback.png");
}
}
osg::Image* _image;
};