Use framebuffer object as fallback for off-screen rendering

This commit is contained in:
wmayer 2013-06-19 17:42:28 +02:00
parent e5224f1140
commit c6b02da648
8 changed files with 111 additions and 34 deletions

View File

@ -29,6 +29,7 @@
# include <QByteArray>
# include <QDateTime>
# include <QImage>
# include <QGLFramebufferObject>
#endif
#include "Thumbnail.h"
@ -85,24 +86,17 @@ void Thumbnail::SaveDocFile (Base::Writer &writer) const
if (!this->viewer)
return;
QImage img;
try {
this->viewer->savePicture(this->size, this->size, View3DInventorViewer::Current, img);
// Alternative way of off-screen rendering
#if 0
QGLFramebufferObject fbo(this->size, this->size,QGLFramebufferObject::Depth);
fbo.bind();
glEnable(GL_DEPTH_TEST);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthRange(0.1,1.0);
glEnable(GL_LINE_SMOOTH);
SoGLRenderAction gl(SbViewportRegion(this->size,this->size));
gl.apply(this->viewer->getSceneManager()->getSceneGraph());
fbo.release();
img = fbo.toImage();
#endif
if (App::GetApplication().GetParameterGroupByPath
("User parameter:BaseApp/Preferences/Document")->GetBool("DisablePBuffers",false)) {
this->createThumbnailFromFramebuffer(img);
}
catch (...) {
return; // offscreen rendering failed
else {
try {
this->viewer->savePicture(this->size, this->size, View3DInventorViewer::Current, img);
}
catch (...) {
this->createThumbnailFromFramebuffer(img);
}
}
QPixmap px = Gui::BitmapFactory().pixmap(App::Application::Config()["AppIcon"].c_str());
@ -126,3 +120,11 @@ void Thumbnail::SaveDocFile (Base::Writer &writer) const
void Thumbnail::RestoreDocFile(Base::Reader &reader)
{
}
void Thumbnail::createThumbnailFromFramebuffer(QImage& img) const
{
// Alternative way of off-screen rendering
QGLFramebufferObject fbo(this->size, this->size,QGLFramebufferObject::Depth);
this->viewer->renderToFramebuffer(&fbo);
img = fbo.toImage();
}

View File

@ -27,6 +27,8 @@
#include <Base/Persistence.h>
#include <QUrl>
class QImage;
namespace Gui {
class View3DInventorViewer;
@ -53,6 +55,9 @@ public:
void RestoreDocFile(Base::Reader &reader);
//@}
private:
void createThumbnailFromFramebuffer(QImage&) const;
private:
QUrl uri;
View3DInventorViewer* viewer;

View File

@ -27,6 +27,7 @@
# include <QAction>
# include <QApplication>
# include <QFileInfo>
# include <QGLFramebufferObject>
# include <QKeyEvent>
# include <QEvent>
# include <QDropEvent>
@ -483,12 +484,38 @@ void View3DInventor::print(QPrinter* printer)
QImage img;
QPainter p(printer);
QRect rect = printer->pageRect();
_viewer->savePicture(rect.width(), rect.height(), View3DInventorViewer::White, img);
if (App::GetApplication().GetParameterGroupByPath
("User parameter:BaseApp/Preferences/Document")->GetBool("DisablePBuffers",false)) {
previewFromFramebuffer(rect, img);
}
else {
try {
_viewer->savePicture(rect.width(), rect.height(), View3DInventorViewer::White, img);
}
catch (...) {
previewFromFramebuffer(rect, img);
}
}
p.drawImage(0,0,img);
p.end();
#endif
}
void View3DInventor::previewFromFramebuffer(const QRect& rect, QImage& img)
{
QGLFramebufferObject fbo(rect.width(), rect.height(), QGLFramebufferObject::Depth);
const SbColor col = _viewer->getBackgroundColor();
bool on = _viewer->hasGradientBackground();
_viewer->setBackgroundColor(SbColor(1.0f,1.0f,1.0f));
_viewer->setGradientBackground(false);
_viewer->renderToFramebuffer(&fbo);
_viewer->setBackgroundColor(col);
_viewer->setGradientBackground(on);
img = fbo.toImage();
}
// **********************************************************************************
bool View3DInventor::onMsg(const char* pMsg, const char** ppReturn)

View File

@ -127,6 +127,7 @@ protected:
void focusInEvent (QFocusEvent * e);
void customEvent (QEvent * e);
void contextMenuEvent (QContextMenuEvent*e);
void previewFromFramebuffer(const QRect&, QImage&);
/// handle to the viewer parameter group
ParameterGrp::handle hGrp;

View File

@ -430,6 +430,11 @@ void View3DInventorViewer::setGradientBackground(bool on)
backgroundroot->removeChild(pcBackGround);
}
bool View3DInventorViewer::hasGradientBackground() const
{
return (backgroundroot->findChild(pcBackGround) != -1);
}
void View3DInventorViewer::setGradientBackgroundColor(const SbColor& fromColor,
const SbColor& toColor)
{
@ -577,7 +582,6 @@ void View3DInventorViewer::savePicture(const char* filename, int w, int h,
throw Base::Exception("Offscreen rendering failed");
// set matrix for miba
renderer._Matrix = camera->getViewVolume().getMatrix();
//bool ok = renderer.writeToImageFile(filename, filetypeextension);
renderer.writeToImageFile(filename, comment);
root->unref();
}
@ -941,6 +945,8 @@ void View3DInventorViewer::renderToFramebuffer(QGLFramebufferObject* fbo)
{
this->glLockNormal();
fbo->bind();
int width = fbo->size().width();
int height = fbo->size().height();
glDisable(GL_TEXTURE_2D);
glEnable(GL_LIGHTING);
@ -948,12 +954,13 @@ void View3DInventorViewer::renderToFramebuffer(QGLFramebufferObject* fbo)
glEnable(GL_LINE_SMOOTH);
const SbColor col = this->getBackgroundColor();
glClearColor(col[0], col[1], col[2], 0.0f);
glViewport(0, 0, width, height);
glClearColor(col[0], col[1], col[2], 1.0f);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
glDepthRange(0.1,1.0);
SoGLRenderAction gl(SbViewportRegion(fbo->size().width(),fbo->size().height()));
SoGLRenderAction gl(SbViewportRegion(width, height));
gl.apply(this->backgroundroot);
gl.apply(this->getSceneManager()->getSceneGraph());
gl.apply(this->foregroundroot);

View File

@ -269,6 +269,7 @@ public:
void viewSelection();
void setGradientBackground(bool b);
bool hasGradientBackground() const;
void setGradientBackgroundColor(const SbColor& fromColor,
const SbColor& toColor);
void setGradientBackgroundColor(const SbColor& fromColor,

View File

@ -26,6 +26,8 @@
#ifndef __InventorAll__
# include "InventorAll.h"
# include <sstream>
# include <QImage>
# include <QGLFramebufferObject>
#endif
@ -556,6 +558,37 @@ Py::Object View3DInventorPy::isAnimationEnabled(const Py::Tuple& args)
return Py::Boolean(ok ? true : false);
}
void View3DInventorPy::createImageFromFramebuffer(int backgroundType, int width, int height, QImage& img)
{
QGLFramebufferObject fbo(width, height, QGLFramebufferObject::Depth);
const SbColor col = _view->getViewer()->getBackgroundColor();
bool on = _view->getViewer()->hasGradientBackground();
switch(backgroundType){
case 0: // Current
break;
case 1: // Black
_view->getViewer()->setBackgroundColor(SbColor(0.0f,0.0f,0.0f));
_view->getViewer()->setGradientBackground(false);
break;
case 2: // White
_view->getViewer()->setBackgroundColor(SbColor(1.0f,1.0f,1.0f));
_view->getViewer()->setGradientBackground(false);
break;
case 3: // Transparent
_view->getViewer()->setBackgroundColor(SbColor(1.0f,1.0f,1.0f));
_view->getViewer()->setGradientBackground(false);
break;
default:
break;
}
_view->getViewer()->renderToFramebuffer(&fbo);
_view->getViewer()->setBackgroundColor(col);
_view->getViewer()->setGradientBackground(on);
img = fbo.toImage();
}
Py::Object View3DInventorPy::saveImage(const Py::Tuple& args)
{
char *cFileName,*cImageType="Current",*cComment="$MIBA";
@ -587,24 +620,23 @@ Py::Object View3DInventorPy::saveImage(const Py::Tuple& args)
else
throw Py::Exception("Parameter 4 have to be (Current|Black|White|Transparent)");
#endif
if (App::GetApplication().GetParameterGroupByPath
("User parameter:BaseApp/Preferences/Document")->GetBool("DisablePBuffers",false)) {
QImage img;
createImageFromFramebuffer(t, w, h, img);
img.save(QString::fromUtf8(cFileName));
return Py::None();
}
try {
QColor c;
_view->getViewer()->savePicture(cFileName,w,h,t,cComment);
return Py::None();
}
catch (const Base::Exception& e) {
Base::Console().Log("Try disabling the use of pbuffers, set the environment variables\n"
"COIN_GLXGLUE_NO_PBUFFERS=1\n"
"COIN_GLXGLUE_NO_GLX13_PBUFFERS=1\n"
"and re-run the application.\n");
throw Py::Exception(e.what());
}
catch (const std::exception& e) {
throw Py::Exception(e.what());
}
catch(...) {
throw Py::Exception("Unknown C++ exception");
catch (const Base::Exception&) {
QImage img;
createImageFromFramebuffer(t, w, h, img);
img.save(QString::fromUtf8(cFileName));
return Py::None();
}
}

View File

@ -28,6 +28,7 @@
#include <CXX/Extensions.hxx>
class SoEventCallback;
class QImage;
namespace Gui {
@ -102,6 +103,7 @@ private:
typedef PyObject* (*method_varargs_handler)(PyObject *_self, PyObject *_args);
static method_varargs_handler pycxx_handler;
static PyObject *method_varargs_ext_handler(PyObject *_self, PyObject *_args);
void createImageFromFramebuffer(int backgroundType, int width, int height, QImage&);
private:
std::list<PyObject*> callbacks;