From 45092327926bccd76cdce6aa4a467d2d4bdcc3b0 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Tue, 1 Nov 2005 15:23:03 +0000 Subject: [PATCH] Improved handling of osg::Image copying. --- src/osg/FrameBufferObject.cpp | 87 +++++++++++++++++++++-------------- src/osgUtil/RenderStage.cpp | 49 ++++++++++++++++++-- 2 files changed, 98 insertions(+), 38 deletions(-) diff --git a/src/osg/FrameBufferObject.cpp b/src/osg/FrameBufferObject.cpp index e599c11d5..4c9eeea6d 100644 --- a/src/osg/FrameBufferObject.cpp +++ b/src/osg/FrameBufferObject.cpp @@ -214,45 +214,64 @@ FrameBufferAttachment::FrameBufferAttachment(TextureRectangle* target) FrameBufferAttachment::FrameBufferAttachment(CameraNode::Attachment& attachment) { osg::Texture* texture = attachment._texture.get(); - osg::Texture1D* texture1D = dynamic_cast(texture); - if (texture1D) - { - _ximpl = new Pimpl(Pimpl::TEXTURE1D, attachment._level); - _ximpl->textureTarget = texture1D; - return; - } - osg::Texture2D* texture2D = dynamic_cast(texture); - if (texture2D) + if (texture) { - _ximpl = new Pimpl(Pimpl::TEXTURE2D, attachment._level); - _ximpl->textureTarget = texture2D; - return; + osg::Texture1D* texture1D = dynamic_cast(texture); + if (texture1D) + { + _ximpl = new Pimpl(Pimpl::TEXTURE1D, attachment._level); + _ximpl->textureTarget = texture1D; + return; + } + + osg::Texture2D* texture2D = dynamic_cast(texture); + if (texture2D) + { + _ximpl = new Pimpl(Pimpl::TEXTURE2D, attachment._level); + _ximpl->textureTarget = texture2D; + return; + } + + osg::Texture3D* texture3D = dynamic_cast(texture); + if (texture3D) + { + _ximpl = new Pimpl(Pimpl::TEXTURE3D, attachment._level); + _ximpl->textureTarget = texture3D; + _ximpl->zoffset = attachment._face; + return; + } + + osg::TextureCubeMap* textureCubeMap = dynamic_cast(texture); + if (textureCubeMap) + { + _ximpl = new Pimpl(Pimpl::TEXTURECUBE, attachment._level); + _ximpl->textureTarget = textureCubeMap; + _ximpl->cubeMapFace = attachment._face; + return; + } + + osg::TextureRectangle* textureRectangle = dynamic_cast(texture); + if (textureRectangle) + { + _ximpl = new Pimpl(Pimpl::TEXTURERECT); + _ximpl->textureTarget = textureRectangle; + return; + } } - osg::Texture3D* texture3D = dynamic_cast(texture); - if (texture3D) + osg::Image* image = attachment._image.get(); + if (image) { - _ximpl = new Pimpl(Pimpl::TEXTURE3D, attachment._level); - _ximpl->textureTarget = texture3D; - _ximpl->zoffset = attachment._face; - return; - } - - osg::TextureCubeMap* textureCubeMap = dynamic_cast(texture); - if (textureCubeMap) - { - _ximpl = new Pimpl(Pimpl::TEXTURECUBE, attachment._level); - _ximpl->textureTarget = textureCubeMap; - _ximpl->cubeMapFace = attachment._face; - return; - } - - osg::TextureRectangle* textureRectangle = dynamic_cast(texture); - if (textureRectangle) - { - _ximpl = new Pimpl(Pimpl::TEXTURERECT); - _ximpl->textureTarget = textureRectangle; + if (image->s()>0 && image->t()>0 && image->getPixelFormat()>0) + { + _ximpl = new Pimpl(Pimpl::RENDERBUFFER); + _ximpl->renderbufferTarget = new osg::RenderBuffer(image->s(), image->t(), image->getPixelFormat()); + } + else + { + osg::notify(osg::WARN)<<"Error: FrameBufferAttachment::FrameBufferAttachment(CameraNode::Attachment&) passed an empty osg::Image, image must be allocated first."<second._image.valid()) setImage(itr->second._image.get()); + // if one exist attach image to the RenderStage. + if (itr->second._image.valid()) + { + osg::Image* image = itr->second._image.get(); + GLenum pixelFormat = image->getPixelFormat(); + GLenum dataType = image->getDataType(); + + if (image->data()==0) + { + if (pixelFormat==0) pixelFormat = itr->second._internalFormat; + if (pixelFormat==0) pixelFormat = _imageReadPixelFormat; + if (pixelFormat==0) pixelFormat = GL_RGBA; + + if (dataType==0) dataType = _imageReadPixelDataType; + if (dataType==0) dataType = GL_UNSIGNED_BYTE; + + image->allocateImage(_viewport->width(), _viewport->height(), 1, pixelFormat, dataType); + + } + + _imageReadPixelFormat = pixelFormat; + _imageReadPixelDataType = dataType; + + setImage(itr->second._image.get()); + } } if (renderTargetImplemntation==osg::CameraNode::FRAME_BUFFER_OBJECT) @@ -182,7 +205,7 @@ void RenderStage::runCameraSetUp(osg::State& state) osg::notify(osg::INFO)<<"Setting up osg::CameraNode::FRAME_BUFFER_OBJECT"<first; osg::CameraNode::Attachment& attachment = itr->second; + switch(buffer) { case(osg::CameraNode::DEPTH_BUFFER): @@ -496,6 +520,8 @@ void RenderStage::drawInner(osg::State& state,RenderLeaf*& previous, bool& doCop copyTexture(state); } + state.checkGLErrors("before readPixel;"); + if (_image.valid()) { @@ -504,7 +530,17 @@ void RenderStage::drawInner(osg::State& state,RenderLeaf*& previous, bool& doCop glReadBuffer(_readBuffer); } - _image->readPixels(_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height(),_imageReadPixelFormat,_imageReadPixelDataType); + GLenum pixelFormat = _image->getPixelFormat(); + if (pixelFormat==0) pixelFormat = _imageReadPixelFormat; + if (pixelFormat==0) pixelFormat = GL_RGB; + + GLenum dataType = _image->getDataType(); + if (dataType==0) dataType = _imageReadPixelDataType; + if (dataType==0) dataType = GL_UNSIGNED_BYTE; + + _image->readPixels(_viewport->x(), _viewport->y(), + _viewport->width(), _viewport->height(), + pixelFormat, dataType); } @@ -514,6 +550,8 @@ void RenderStage::drawInner(osg::State& state,RenderLeaf*& previous, bool& doCop (*(_camera->getPostDrawCallback()))(*_camera); } + state.checkGLErrors("before glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);"); + if (fbo_supported) { // switch of the frame buffer object @@ -522,6 +560,9 @@ void RenderStage::drawInner(osg::State& state,RenderLeaf*& previous, bool& doCop doCopyTexture = true; } + state.checkGLErrors("after glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);"); + + if (fbo_supported && _camera) { // now generate mipmaps if they are required.