NAME
SoOffscreenRenderer -
The SoOffscreenRenderer class is used for rendering scenes in offscreen
buffers.
If you want to render to a memory buffer instead of an on-screen OpenGL
context, use this class. Rendering to a memory buffer can be used to
generate texture maps on-the-fly, or for saving snapshots of the scene
to disk files (as pixel bitmaps or as Postscript files for sending to a
Postscript-capable printer).
SYNOPSIS
#include <Inventor/SoOffscreenRenderer.h>
Public Types
enum Components { LUMINANCE = 1, LUMINANCE_TRANSPARENCY = 2, RGB =
3, RGB_TRANSPARENCY = 4 }
Public Member Functions
SoOffscreenRenderer (const SbViewportRegion &viewportregion)
SoOffscreenRenderer (SoGLRenderAction *action)
~SoOffscreenRenderer ()
void setComponents (const Components components)
Components getComponents (void) const
void setViewportRegion (const SbViewportRegion ®ion)
const SbViewportRegion & getViewportRegion (void) const
void setBackgroundColor (const SbColor &color)
const SbColor & getBackgroundColor (void) const
void setGLRenderAction (SoGLRenderAction *action)
SoGLRenderAction * getGLRenderAction (void) const
SbBool render (SoNode *scene)
SbBool render (SoPath *scene)
unsigned char * getBuffer (void) const
const void *const & getDC (void) const
SbBool writeToRGB (FILE *fp) const
SbBool writeToPostScript (FILE *fp) const
SbBool writeToPostScript (FILE *fp, const SbVec2f &printsize) const
SbBool writeToRGB (const char *filename) const
SbBool writeToPostScript (const char *filename) const
SbBool writeToPostScript (const char *filename, const SbVec2f
&printsize) const
SbBool isWriteSupported (const SbName &filetypeextension) const
int getNumWriteFiletypes (void) const
void getWriteFiletypeInfo (const int idx, SbPList &extlist, SbString
&fullname, SbString &description)
SbBool writeToFile (const SbString &filename, const SbName
&filetypeextension) const
void setPbufferEnable (SbBool enable)
SbBool getPbufferEnable (void) const
void getWriteFiletypeInfo (const int idx, SbList< SbName > &extlist,
SbString &fullname, SbString &description)
Static Public Member Functions
static float getScreenPixelsPerInch (void)
static SbVec2s getMaximumResolution (void)
Detailed Description
The SoOffscreenRenderer class is used for rendering scenes in offscreen
buffers.
If you want to render to a memory buffer instead of an on-screen OpenGL
context, use this class. Rendering to a memory buffer can be used to
generate texture maps on-the-fly, or for saving snapshots of the scene
to disk files (as pixel bitmaps or as Postscript files for sending to a
Postscript-capable printer).
Here’s a dead simple usage example, just the code directly related to
the SoOffscreenRenderer:
SoOffscreenRenderer myRenderer(vpregion);
SoNode * root = myViewer->getSceneManager()->getSceneGraph();
SbBool ok = myRenderer.render(root);
unsigned char * imgbuffer = myRenderer.getBuffer();
// [then use image buffer in a texture, or write it to file, or whatever]
And a complete, simple, stand-alone example:
#include <Inventor/SoDB.h>
#include <Inventor/SoOffscreenRenderer.h>
#include <Inventor/nodes/SoCube.h>
#include <Inventor/nodes/SoDirectionalLight.h>
#include <Inventor/nodes/SoPerspectiveCamera.h>
#include <Inventor/nodes/SoSeparator.h>
int
main(int argc, char ** argv)
{
SoDB::init();
SoPerspectiveCamera * camera = new SoPerspectiveCamera;
SoDirectionalLight * light = new SoDirectionalLight;
SoCube * cube = new SoCube;
SoSeparator * root = new SoSeparator;
root->addChild(camera);
root->addChild(light);
root->addChild(cube);
root->ref();
SbViewportRegion vpr;
vpr.setWindowSize(400, 400);
light->direction.setValue(1, -1.2, -0.5);
camera->position.setValue(-2, 2, 2);
camera->pointAt(SbVec3f(0, 0, 0));
camera->viewAll(cube, vpr);
SoOffscreenRenderer osr(vpr);
SbBool ok = osr.render(root);
if (!ok) { exit(1); }
ok = osr.writeToRGB(’test-image.rgb’);
if (!ok) { exit(1); }
(void)puts(’Image written successfully.’);
root->unref();
return 0;
}
Note that the SoOffscreenRenderer potentially allocates a fairly large
amount of resources, both OpenGL and general system resources, for each
instance. You will therefore be well adviced to try to reuse
SoOffscreenRenderer instances, instead of constructing and destructing
a new instance e.g. for each frame when generating pictures for video.
Offscreen rendering is internally done through either a GLX offscreen
context (i.e. OpenGL on X11), WGL (i.e. OpenGL on Win32), AGL (old-
style OpenGL on the Mac OS X) or CGL (new-style Mac OS X).
If the OpenGL driver supports the pbuffer extension, it is detected and
used to provide hardware-accelerated offscreen rendering.
The pixeldata is fetched from the OpenGL buffer with glReadPixels(),
with the format and type arguments set to GL_RGBA and GL_UNSIGNED_BYTE,
respectively. This means that the maximum resolution is 32 bits, 8 bits
for each of the R/G/B/A components.
One particular usage of the SoOffscreenRenderer is to make it render
frames to be used for the construction of movies. The general technique
for doing this is to iterate over the following actions:
· move camera to correct position for frame
· update the realTime global field (see explanation below)
· invoke the SoOffscreenRenderer
· dump rendered scene to file
The code would go something like the following (pseudo-code style).
First we need to stop the Coin library itself from doing any automatic
updating of the realTime field, so your application initialization for
Coin should look something like:
[...] = SoQt::init([...]); // or SoWin::init() or SoDB::init()
// ..and then immediately:
// Control realTime field ourselves, so animations within the scene
// follows ’movie-time’ and not ’wallclock-time’.
SoDB::enableRealTimeSensor(FALSE);
SoSceneManager::enableRealTimeUpdate(FALSE);
SoSFTime * realtime = SoDB::getGlobalField(’realTime’);
realtime->setValue(0.0);
Note that it is important that the realTime field is initialized to
your start-time before setting up any engines or other entities in the
system that uses the realTime field.
Then for the rendering loop, something like:
for (int i=0; i < NRFRAMES; i++) {
// [...reposition camera here, if necessary...]
// render
offscreenrend->render(root);
// dump to file
SbString framefile;
framefile.sprintf(’frame%06d.rgb’, i);
offscreenrend->writeToRGB(framefile.getString());
// advance ’current time’ by the frames-per-second value, which
// is 24 fps in this example
realtime->setValue(realtime.getValue() + 1/24.0);
}
When making movies you need to write your application control code to
take care of moving the camera along the correct trajectory yourself,
and to explicitly control the global realTime field. The latter is so
you’re able to ’step’ with appropriate time units for each render
operation (e.g. if you want a movie that has a 24 FPS refresh rate,
first render with realTime=0.0, then add 1/24s to the realTime field,
render again to a new frame, add another 1/24s to the realTime field,
render, and so on).
For further information about how to control the realTime field, see
documentation of SoDB::getGlobalField(), SoDB::enableRealTimeSensor(),
and SoSceneManager::enableRealTimeUpdate().
If you want to use this class to create snapshots of your current
viewer’s view, but want to control the size of the snapshot, you need
to modify the camera a bit while rendering to be sure that everything
you see in the current view is visible in the snapshot.
Below you’ll find some pseude-code that does this. There are probably
other ways to do this as well.
void render_offscreen(const SbVec2s size)
{
SbVec2s glsize = this->getGLSize(); // size of your normal viewer
float glar = float(glsize[0] / float(glsize[1]));
float ar = float(size[0]) / float(size[1]);
SoCamera * camera = this->getCamera(); // the camera you’re using
SoCamera::ViewportMapping oldmap = (SoCamera::ViewportMapping)
camera->viewportMapping.getValue();
float oldar = camera->aspectRatio.getValue();
camera->viewportMapping = SoCamera::LEAVE_ALONE;
camera->aspectRatio = ar;
float scaleheight = 1.0f;
if (glar > ar) {
scaleheight = glar / ar;
camera->scaleHeight(scaleheight);
}
else {
scaleheight = ar / glar;
camera->scaleHeight(scaleheight);
}
SoOffscreenRenderer * renderer = new SoOffscreenRenderer(size);
renderer->render(root);
// ... save image
// restore camera
camera->viewportMapping = oldmap;
camera->aspectRatio = oldar;
if (scaleheight != 1.0f) {
camera->scaleHeight(1.0f / scaleheight);
}
}
Member Enumeration Documentation
enum SoOffscreenRenderer::Components Enumerated values for the available
image formats.
See also:
setComponents()
Constructor & Destructor Documentation
SoOffscreenRenderer::SoOffscreenRenderer (const SbViewportRegion &
viewportregion) Constructor. Argument is the viewportregion we should
use when rendering. An internal SoGLRenderAction will be constructed.
SoOffscreenRenderer::SoOffscreenRenderer (SoGLRenderAction * action)
Constructor. Argument is the action we should apply to the scene graph
when rendering the scene. Information about the viewport is extracted
from the action.
SoOffscreenRenderer::~SoOffscreenRenderer () Destructor.
Member Function Documentation
float SoOffscreenRenderer::getScreenPixelsPerInch (void) [static] Returns
the screen pixels per inch resolution of your monitor.
SbVec2s SoOffscreenRenderer::getMaximumResolution (void) [static] Get
maximum dimensions (width, height) of the offscreen buffer.
Note that from Coin version 2 onwards, the returned value will always
be (SHRT_MAX, SHRT_MAX), where SHRT_MAX on most systems is equal to
32767.
This because the SoOffscreenRenderer can in principle generate
unlimited size offscreen canvases by tiling together multiple
renderings of the same scene.
void SoOffscreenRenderer::setComponents (const Components components) Sets
the component format of the offscreen buffer.
If set to LUMINANCE, a grayscale image is rendered,
LUMINANCE_TRANSPARENCY gives us a grayscale image with transparency,
RGB will give us a 24-bit image with 8 bits each for the red, green and
blue component, and RGB_TRANSPARENCY yields a 32-bit image (RGB plus
transparency).
The default format to render to is RGB.
This will invalidate the current buffer, if any. The buffer will not
contain valid data until another call to SoOffscreenRenderer::render()
happens.
SoOffscreenRenderer::Components SoOffscreenRenderer::getComponents (void)
const Returns the component format of the offscreen buffer.
See also:
setComponents()
void SoOffscreenRenderer::setViewportRegion (const SbViewportRegion &
region) Sets the viewport region.
This will invalidate the current buffer, if any. The buffer will not
contain valid data until another call to SoOffscreenRenderer::render()
happens.
const SbViewportRegion & SoOffscreenRenderer::getViewportRegion (void)
const Returns the viewerport region.
void SoOffscreenRenderer::setBackgroundColor (const SbColor & color) Sets
the background color. The buffer is cleared to this color before
rendering.
const SbColor & SoOffscreenRenderer::getBackgroundColor (void) const
Returns the background color.
void SoOffscreenRenderer::setGLRenderAction (SoGLRenderAction * action)
Sets the render action. Use this if you have special rendering needs.
SoGLRenderAction * SoOffscreenRenderer::getGLRenderAction (void) const
Returns the rendering action currently used.
SbBool SoOffscreenRenderer::render (SoNode * scene) Render the scenegraph
rooted at scene into our internal pixel buffer.
Important note: make sure you pass in a scene node pointer which has
both a camera and at least one lightsource below it -- otherwise you
are likely to end up with just a blank or black image buffer.
This mistake is easily made if you use an SoOffscreenRenderer on a
scenegraph from one of the standard viewer components, as you will
often just leave the addition of a camera and a headlight lightsource
to the viewer to set up. This camera and lightsource are then part of
the viewer’s private ’super-graph’ outside of the scope of the
scenegraph passed in by the application programmer. To make sure the
complete scenegraph (including the viewer’s ’private parts’
(*snicker*)) are passed to this method, you can get the scenegraph root
from the viewer’s internal SoSceneManager instance instead of from the
viewer’s own getSceneGraph() method, like this:
SoOffscreenRenderer * myRenderer = new SoOffscreenRenderer(vpregion);
SoNode * root = myViewer->getSceneManager()->getSceneGraph();
SbBool ok = myRenderer->render(root);
// [then use image buffer in a texture, or write it to file, or whatever]
If you do this and still get a blank buffer, another common problem is
to have a camera which is not actually pointing at the scene geometry
you want a snapshot of. If you suspect that could be the cause of
problems on your end, take a look at SoCamera::pointAt() and
SoCamera::viewAll() to see how you can make a camera node guaranteed to
be directed at the scene geometry.
Yet another common mistake when setting up the camera is to specify
values for the SoCamera::nearDistance and SoCamera::farDistance fields
which doesn’t not enclose the full scene. This will result in either
just the background color, or that parts at the front or the back of
the scene will not be visible in the rendering.
See also:
writeToRGB()
SbBool SoOffscreenRenderer::render (SoPath * scene) Render the scene path
into our internal memory buffer.
unsigned char * SoOffscreenRenderer::getBuffer (void) const Returns the
offscreen memory buffer.
const void *const & SoOffscreenRenderer::getDC (void) const Win32 only:
returns a direct handle to the internal DC of the offscreen context.
Useful for efficient access to the raw image under certain special
circumstances. getBuffer() might be too slow, for instance due to pixel
format conversion (Windows DCs are usually BGRA, while the 32-bit
buffers returned from getBuffer() are RGBA).
Notes:
The return value is a reference to a HDC. The HDC typedef has been
unwound to a native C++ type for multiplatform compatibility reasons.
Returned reference will contain a NULL value on other platforms.
Important limitation: if the current dimensions of the
SoOffscreenRenderer instance are larger than what can be rendered with
a single offscreen buffer, tiling will be used by the
SoOffscreenRenderer, and the returned HDC will contain only part of the
full rendered image.
See also:
getBuffer()
Since:
Coin 3.1
SbBool SoOffscreenRenderer::writeToRGB (FILE * fp) const Writes the buffer
in SGI RGB format by appending it to the already open file. Returns
FALSE if writing fails.
Important note: do not use this method when the Coin library has been
compiled as an MSWindows DLL, as passing FILE* instances back or forth
to DLLs is dangerous and will most likely cause a crash. This is an
intrinsic limitation for MSWindows DLLs.
SbBool SoOffscreenRenderer::writeToPostScript (FILE * fp) const Writes the
buffer in Postscript format by appending it to the already open file.
Returns FALSE if writing fails.
Important note: do not use this method when the Coin library has been
compiled as an MSWindows DLL, as passing FILE* instances back or forth
to DLLs is dangerous and will most likely cause a crash. This is an
intrinsic limitation for MSWindows DLLs.
SbBool SoOffscreenRenderer::writeToPostScript (FILE * fp, const SbVec2f &
printsize) const Writes the buffer to a file in Postscript format, with
printsize dimensions.
Important note: do not use this method when the Coin library has been
compiled as an MSWindows DLL, as passing FILE* instances back or forth
to DLLs is dangerous and will most likely cause a crash. This is an
intrinsic limitation for MSWindows DLLs.
SbBool SoOffscreenRenderer::writeToRGB (const char * filename) const Opens
a file with the given name and writes the offscreen buffer in SGI RGB
format to the new file. If the file already exists, it will be
overwritten (if permitted by the filesystem).
Returns TRUE if all went ok, otherwise FALSE.
SbBool SoOffscreenRenderer::writeToPostScript (const char * filename) const
Opens a file with the given name and writes the offscreen buffer in
Postscript format to the new file. If the file already exists, it will
be overwritten (if permitted by the filesystem).
Returns TRUE if all went ok, otherwise FALSE.
SbBool SoOffscreenRenderer::writeToPostScript (const char * filename, const
SbVec2f & printsize) const Opens a file with the given name and writes
the offscreen buffer in Postscript format with printsize dimensions to
the new file. If the file already exists, it will be overwritten (if
permitted by the filesystem).
Returns TRUE if all went ok, otherwise FALSE.
SbBool SoOffscreenRenderer::isWriteSupported (const SbName &
filetypeextension) const Returns TRUE if the buffer can be saved as a
file of type filetypeextension, using
SoOffscreenRenderer::writeToFile(). This function needs simage v1.1 or
newer.
Examples of possibly supported extensions are: ’jpg’, ’png’, ’tiff’,
’gif’, ’bmp’, etc. The extension match is not case sensitive.
Which formats are actually supported depends on the capabilities of
Coin’s support library for handling import and export of pixel-data
files: the simage library. If the simage library is not installed on
your system, no extension output formats will be supported.
Also, note that it is possible to build and install a simage library
that lacks support for most or all of the file formats it is capable of
supporting. This is so because the simage library depends on other,
external 3rd party libraries -- in the same manner as Coin depends on
the simage library for added file format support.
The two built-in formats that are supported through the
SoOffscreenRenderer::writeToRGB() and
SoOffscreenRenderer::writeToPostScript() methods (for SGI RGB format
and for Adobe Postscript files, respectively) are not considered by
this method, as those two formats are guaranteed to always be supported
through those functions.
So if you want to be guaranteed to be able to export a screenshot in
your wanted format, you will have to use either one of the above
mentioned method for writing SGI RGB or Adobe Postscript directly, or
make sure the Coin library has been built and is running on top of a
version of the simage library (that you have preferably built yourself)
with the file format(s) you want support for.
This method is an extension versus the original SGI Open Inventor API.
See also:
getNumWriteFiletypes(), getWriteFiletypeInfo(), writeToFile()
int SoOffscreenRenderer::getNumWriteFiletypes (void) const Returns the
number of available exporters. Detailed information about the exporters
can then be found using getWriteFiletypeInfo().
See SoOffscreenRenderer::isWriteSupported() for information about which
file formats you can expect to be present.
Note that the two built-in export formats, SGI RGB and Adobe
Postscript, are not counted.
This method is an extension versus the original SGI Open Inventor API.
See also:
getWriteFiletypeInfo()
void SoOffscreenRenderer::getWriteFiletypeInfo (const int idx, SbPList &
extlist, SbString & fullname, SbString & description) Returns
information about an image exporter. extlist is a list of filename
extensions for a file format. E.g. for JPEG it is legal to use both jpg
and jpeg. Extlist will contain const char * pointers (you need to cast
the void * pointers to const char * before using them).
fullname is the full name of the image format. description is an
optional string with more information about the file format.
See SoOffscreenRenderer::isWriteSupported() for information about which
file formats you can expect to be present.
This method is an extension versus the original SGI Open Inventor API.
Here is a stand-alone, complete code example that shows how you can
check exactly which output formats are supported:
#include <Inventor/SoDB.h>
#include <Inventor/SoOffscreenRenderer.h>
int
main(int argc, char **argv)
{
SoDB::init();
SoOffscreenRenderer * r = new SoOffscreenRenderer(*(new SbViewportRegion));
int num = r->getNumWriteFiletypes();
if (num == 0) {
(void)fprintf(stdout,
’No image formats supported by the ’
’SoOffscreenRenderer except SGI RGB and Postscript.0);
}
else {
for (int i=0; i < num; i++) {
SbPList extlist;
SbString fullname, description;
r->getWriteFiletypeInfo(i, extlist, fullname, description);
(void)fprintf(stdout, ’%s: %s (extension%s: ’,
fullname.getString(), description.getString(),
extlist.getLength() > 1 ? ’s’ : ’’);
for (int j=0; j < extlist.getLength(); j++) {
(void)fprintf(stdout, ’%s%s’, j>0 ? ’, ’ : ’’, (const char*) extlist[j]);
}
(void)fprintf(stdout, ’)0);
}
}
delete r;
return 0;
}
See also:
getNumWriteFiletypes(), writeToFile()
Since:
Coin 2.3
SbBool SoOffscreenRenderer::writeToFile (const SbString & filename, const
SbName & filetypeextension) const Saves the buffer to filename, in the
filetype specified by filetypeextensions.
Note that you must still specify the full filename for the first
argument, i.e. the second argument will not automatically be attached
to the filename -- it is only used to decide the filetype.
This method is an extension versus the orignal SGI Open Inventor API.
See also:
isWriteSupported()
void SoOffscreenRenderer::setPbufferEnable (SbBool enable) Control whether
or not SoOffscreenRenderer can use the ’pbuffer’ feature of OpenGL to
render the scenes with hardware acceleration.
This is a dummy function in Coin, provided for API compatibility
reasons, as it is really superfluous:
Coin has internal heuristics to figure out if pbuffers are available
and can be allocated and used for the SoOffscreenRenderer. The
SoOffscreenRenderer will also automatically fall back on ’soft’ buffers
if it can not use pbuffers (or any other hardware accelerated rendering
technique).
Since:
Coin 3.1
SbBool SoOffscreenRenderer::getPbufferEnable (void) const See
SoOffscreenRenderer::setPbufferEnable().
Since:
Coin 3.1
void SoOffscreenRenderer::getWriteFiletypeInfo (const int idx, SbList<
SbName > & extlist, SbString & fullname, SbString & description) Note
that if the Coin library has been built as a DLL under Microsoft
Windows and you use this method from application code, you must make
sure that both the Coin DLL and the application executable is using the
same instance of a C Run-Time (CRT) library. Otherwise, you will get
memory heap corruption upon deallocating the returned instances,
eventually leading to mysterious crashes.
To avoid this potential problem, use the overloaded
getWriteFiletypeInfo() function with an SbPList for the second argument
instead.
Author
Generated automatically by Doxygen for Coin from the source code.