1
votes

I trying to render an OSG scene into a image in my Qt program. Refer to the example of SnapImageDrawCallback(https://www.mail-archive.com/[email protected]/msg45360.html).

class SnapImageDrawCallback : public osg::CameraNode::DrawCallback { 
public:
        SnapImageDrawCallback()
        {
                _snapImageOnNextFrame = false;
        }

        void setFileName(const std::string& filename) { _filename = filename; }
        const std::string& getFileName() const { return _filename; }

        void setSnapImageOnNextFrame(bool flag) { _snapImageOnNextFrame = flag;}
        bool getSnapImageOnNextFrame() const { return _snapImageOnNextFrame; }

        virtual void operator () (const osg::CameraNode& camera) const
        {
                if (!_snapImageOnNextFrame) return;

                int x,y,width,height;
                x = camera.getViewport()->x();
                y = camera.getViewport()->y();
                width = camera.getViewport()->width();
                height = camera.getViewport()->height();

                osg::ref_ptr<osg::Image> image = new osg::Image;
                image->readPixels(x,y,width,height,GL_RGB,GL_UNSIGNED_BYTE);

                if (osgDB::writeImageFile(*image,_filename))
                {
                        std::cout  << "Saved screen image to  `"<<_filename
                         <<"`"<< std::endl;
                }

                _snapImageOnNextFrame = false;
        }

protected:

        std::string _filename;
        mutable bool        _snapImageOnNextFrame;


};

I set this as a the osg::Viewer's camera's FinalDrawCallback, but I failed with a blank image, and get this warning "Warning: detected OpenGL error 'invalid operation' at start of State::apply()" when invoke image->readPixels, My osgViewer::Viewer in embedded in QQuickFramebufferObject. Can any one give some suggestions?

2

2 Answers

2
votes

Not sure to give you the right pointer, you should provide more details about your setup and what you're after.

As a general note, if you're trying to render with OSG into a QtQuick widget the best approach is to have osg to render to an FBO in a separate shared GL context, and copy the FBO contents back the qtquick widget. I had tested this approach some times ago, see code here: https://github.com/rickyviking/qmlosg

Another similar project here: https://github.com/podsvirov/osgqtquick

0
votes

you can use pbo

ext->glGenBuffers(1, &pbo);
ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, pbo);
ext->glBufferData(GL_PIXEL_PACK_BUFFER_ARB, _width*_height*4, 0, GL_STREAM_READ);

glReadPixels(0, 0, _width, _height, _pixelFormat, _type, 0);

GLubyte* src = (GLubyte*)ext->glMapBuffer(GL_PIXEL_PACK_BUFFER_ARB,
                                              GL_READ_ONLY_ARB);
    if(src)
    {
        memcpy(image->data(), src, _width*_height*4);

        ext->glUnmapBuffer(GL_PIXEL_PACK_BUFFER_ARB);
    }
    ext->glBindBuffer(GL_PIXEL_PACK_BUFFER_ARB, 0);