From 174e3b3dc387116dbc25640b134406869e72d60f Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 3 Aug 2006 15:57:39 +0000 Subject: [PATCH] Fixed RenderToTexture bug which occured when the viewport dimensions where different than the texture being written to. --- .../osgshadowtexture/CreateShadowedScene.cpp | 7 ++ include/osg/CameraNode | 21 ++++++ include/osg/Texture | 4 + include/osg/Texture1D | 4 +- include/osg/Texture2D | 7 +- include/osg/Texture3D | 9 +-- include/osg/TextureCubeMap | 7 +- include/osg/TextureRectangle | 7 +- src/osgUtil/RenderStage.cpp | 73 ++++++++++++++++--- 9 files changed, 113 insertions(+), 26 deletions(-) diff --git a/examples/osgshadowtexture/CreateShadowedScene.cpp b/examples/osgshadowtexture/CreateShadowedScene.cpp index 0da32a972..30da6043a 100644 --- a/examples/osgshadowtexture/CreateShadowedScene.cpp +++ b/examples/osgshadowtexture/CreateShadowedScene.cpp @@ -125,7 +125,14 @@ osg::Group* createShadowedScene(osg::Node* shadower,osg::Node* shadowed,const os camera->setClearColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f)); // set viewport +// Both of these methods should produce the same result, but they don't. +#if 1 + camera->setViewport(0,tex_height/2,tex_width,tex_height/2); +#else camera->setViewport(0,0,tex_width,tex_height); + osg::Viewport* vp = new osg::Viewport(0,tex_height/2,tex_width,tex_height/2); + camera->getOrCreateStateSet()->setAttribute(vp); +#endif // set the camera to render before the main camera. camera->setRenderOrder(osg::CameraNode::PRE_RENDER); diff --git a/include/osg/CameraNode b/include/osg/CameraNode index 05c0062f2..87b407dee 100644 --- a/include/osg/CameraNode +++ b/include/osg/CameraNode @@ -256,6 +256,27 @@ class OSG_EXPORT CameraNode : public Transform, public CullSettings _face(0), _mipMapGeneration(false) {} + int width() const + { + if (_texture.valid()) return _texture->getTextureWidth(); + if (_image.valid()) return _image->s(); + return 0; + }; + + int height() const + { + if (_texture.valid()) return _texture->getTextureHeight(); + if (_image.valid()) return _image->t(); + return 0; + }; + + int depth() const + { + if (_texture.valid()) return _texture->getTextureDepth(); + if (_image.valid()) return _image->r(); + return 0; + }; + GLenum _internalFormat; ref_ptr _image; ref_ptr _texture; diff --git a/include/osg/Texture b/include/osg/Texture index 99a345f47..736548143 100644 --- a/include/osg/Texture +++ b/include/osg/Texture @@ -220,6 +220,10 @@ class OSG_EXPORT Texture : public osg::StateAttribute return true; } + virtual int getTextureWidth() const { return 0; } + virtual int getTextureHeight() const { return 0; } + virtual int getTextureDepth() const { return 0; } + enum WrapParameter { WRAP_S, WRAP_T, diff --git a/include/osg/Texture1D b/include/osg/Texture1D index 6f10cd5a6..cb06d10f5 100644 --- a/include/osg/Texture1D +++ b/include/osg/Texture1D @@ -74,7 +74,9 @@ class OSG_EXPORT Texture1D : public Texture inline void setTextureWidth(int width) const { _textureWidth = width; } /** Gets the texture width. */ - inline int getTextureWidth() const { return _textureWidth; } + virtual int getTextureWidth() const { return _textureWidth; } + virtual int getTextureHeight() const { return 1; } + virtual int getTextureDepth() const { return 1; } class OSG_EXPORT SubloadCallback : public Referenced diff --git a/include/osg/Texture2D b/include/osg/Texture2D index 05a183e1a..14248497d 100644 --- a/include/osg/Texture2D +++ b/include/osg/Texture2D @@ -78,10 +78,11 @@ class OSG_EXPORT Texture2D : public Texture } void setTextureWidth(int width) { _textureWidth=width; } - int getTextureWidth() const { return _textureWidth; } - void setTextureHeight(int height) { _textureHeight=height; } - int getTextureHeight() const { return _textureHeight; } + + virtual int getTextureWidth() const { return _textureWidth; } + virtual int getTextureHeight() const { return _textureHeight; } + virtual int getTextureDepth() const { return 1; } class OSG_EXPORT SubloadCallback : public Referenced { diff --git a/include/osg/Texture3D b/include/osg/Texture3D index 5cecc6382..fbf5aa7f5 100644 --- a/include/osg/Texture3D +++ b/include/osg/Texture3D @@ -85,13 +85,12 @@ class OSG_EXPORT Texture3D : public Texture } void setTextureWidth(int width) { _textureWidth=width; } - int getTextureWidth() const { return _textureWidth; } - void setTextureHeight(int height) { _textureHeight=height; } - int getTextureHeight() const { return _textureHeight; } - void setTextureDepth(int depth) { _textureDepth=depth; } - int getTextureDepth() const { return _textureDepth; } + + virtual int getTextureWidth() const { return _textureWidth; } + virtual int getTextureHeight() const { return _textureHeight; } + virtual int getTextureDepth() const { return _textureDepth; } class OSG_EXPORT SubloadCallback : public Referenced diff --git a/include/osg/TextureCubeMap b/include/osg/TextureCubeMap index 59dee905e..6e0751796 100644 --- a/include/osg/TextureCubeMap +++ b/include/osg/TextureCubeMap @@ -86,10 +86,11 @@ class OSG_EXPORT TextureCubeMap : public Texture } void setTextureWidth(int width) { _textureWidth=width; } - int getTextureWidth() const { return _textureWidth; } - void setTextureHeight(int height) { _textureHeight=height; } - int getTextureHeight() const { return _textureHeight; } + + virtual int getTextureWidth() const { return _textureWidth; } + virtual int getTextureHeight() const { return _textureHeight; } + virtual int getTextureDepth() const { return 1; } class OSG_EXPORT SubloadCallback : public Referenced { diff --git a/include/osg/TextureRectangle b/include/osg/TextureRectangle index da7b94c08..eb3cbbde1 100644 --- a/include/osg/TextureRectangle +++ b/include/osg/TextureRectangle @@ -85,10 +85,11 @@ class OSG_EXPORT TextureRectangle : public Texture } void setTextureWidth(int width) { _textureWidth=width; } - int getTextureWidth() const { return _textureWidth; } - void setTextureHeight(int height) { _textureHeight=height; } - int getTextureHeight() const { return _textureHeight; } + + virtual int getTextureWidth() const { return _textureWidth; } + virtual int getTextureHeight() const { return _textureHeight; } + virtual int getTextureDepth() const { return 1; } class SubloadCallback : public Referenced { diff --git a/src/osgUtil/RenderStage.cpp b/src/osgUtil/RenderStage.cpp index c29edc860..4823d8739 100644 --- a/src/osgUtil/RenderStage.cpp +++ b/src/osgUtil/RenderStage.cpp @@ -195,8 +195,25 @@ void RenderStage::runCameraSetUp(osg::State& state) osg::CameraNode::BufferAttachmentMap& bufferAttachements = _camera->getBufferAttachmentMap(); + // compute the required dimensions + int width = _viewport->x() + _viewport->width(); + int height = _viewport->y() + _viewport->height(); + int depth = 1; + osg::CameraNode::BufferAttachmentMap::iterator itr; + for(itr = bufferAttachements.begin(); + itr != bufferAttachements.end(); + ++itr) + { + width = osg::maximum(width,itr->second.width()); + height = osg::maximum(height,itr->second.height()); + depth = osg::maximum(depth,itr->second.depth()); + } + + // osg::notify(osg::NOTICE)<<"RenderStage::runCameraSetUp viewport "<<_viewport->x()<<" "<<_viewport->y()<<" "<<_viewport->width()<<" "<<_viewport->height()<allocateImage(_viewport->width(), _viewport->height(), 1, pixelFormat, dataType); + image->allocateImage(width, height, 1, pixelFormat, dataType); } @@ -238,14 +255,14 @@ void RenderStage::runCameraSetUp(osg::State& state) { if (texture1D->getTextureWidth()==0) { - texture1D->setTextureWidth(_viewport->width()); + texture1D->setTextureWidth(width); } } else if (0 != (texture2D = dynamic_cast(texture))) { if (texture2D->getTextureWidth()==0 || texture2D->getTextureHeight()==0) { - texture2D->setTextureSize(_viewport->width(),_viewport->height()); + texture2D->setTextureSize(width,height); } } else if (0 != (texture3D = dynamic_cast(texture))) @@ -253,21 +270,21 @@ void RenderStage::runCameraSetUp(osg::State& state) if (texture3D->getTextureWidth()==0 || texture3D->getTextureHeight()==0 || texture3D->getTextureDepth()==0 ) { // note we dont' have the depth here, so we'll heave to assume that height and depth are the same.. - texture3D->setTextureSize(_viewport->width(),_viewport->height(),_viewport->height()); + texture3D->setTextureSize(width,height,height); } } else if (0 != (textureCubeMap = dynamic_cast(texture))) { if (textureCubeMap->getTextureWidth()==0 || textureCubeMap->getTextureHeight()==0) { - textureCubeMap->setTextureSize(_viewport->width(),_viewport->height()); + textureCubeMap->setTextureSize(width,height); } } else if (0 != (textureRectangle = dynamic_cast(texture))) { if (textureRectangle->getTextureWidth()==0 || textureRectangle->getTextureHeight()==0) { - textureRectangle->setTextureSize(_viewport->width(),_viewport->height()); + textureRectangle->setTextureSize(width,height); } } @@ -324,12 +341,12 @@ void RenderStage::runCameraSetUp(osg::State& state) if (!depthAttached) { - fbo->setAttachment(GL_DEPTH_ATTACHMENT_EXT, osg::FrameBufferAttachment(new osg::RenderBuffer(_viewport->width(), _viewport->height(), GL_DEPTH_COMPONENT24))); + fbo->setAttachment(GL_DEPTH_ATTACHMENT_EXT, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_DEPTH_COMPONENT24))); } if (!colorAttached) { - fbo->setAttachment(GL_COLOR_ATTACHMENT0_EXT, osg::FrameBufferAttachment(new osg::RenderBuffer(_viewport->width(), _viewport->height(), GL_RGB))); + fbo->setAttachment(GL_COLOR_ATTACHMENT0_EXT, osg::FrameBufferAttachment(new osg::RenderBuffer(width, height, GL_RGB))); } fbo->apply(state); @@ -396,8 +413,11 @@ void RenderStage::runCameraSetUp(osg::State& state) // set up the traits of the graphics context that we want osg::ref_ptr traits = new osg::GraphicsContext::Traits; - traits->_width = _viewport->width(); - traits->_height = _viewport->height(); + traits->_width = width; + traits->_height = height; + + // osg::notify(osg::NOTICE)<<"traits = "<_width<<" "<_height<_pbuffer = (renderTargetImplemntation==osg::CameraNode::PIXEL_BUFFER || renderTargetImplemntation==osg::CameraNode::PIXEL_BUFFER_RTT); traits->_windowDecoration = (renderTargetImplemntation==osg::CameraNode::SEPERATE_WINDOW); traits->_doubleBuffer = (renderTargetImplemntation==osg::CameraNode::SEPERATE_WINDOW); @@ -581,6 +601,36 @@ void RenderStage::copyTexture(osg::State& state) osg::TextureRectangle* textureRec = 0; osg::TextureCubeMap* textureCubeMap = 0; +#if 1 + // use TexCopySubImage with the offset of the viewport into the texture + // note, this path mirrors the pbuffer and fbo means for updating the texture. + // Robert Osfield, 3rd August 2006. + if ((texture2D = dynamic_cast(_texture.get())) != 0) + { + texture2D->copyTexSubImage2D(state,_viewport->x(),_viewport->y(), _viewport->x(),_viewport->y(),_viewport->width(),_viewport->height()); + } + else if ((textureRec = dynamic_cast(_texture.get())) != 0) + { + textureRec->copyTexSubImage2D(state,_viewport->x(),_viewport->y(), _viewport->x(),_viewport->y(),_viewport->width(),_viewport->height()); + } + else if ((texture1D = dynamic_cast(_texture.get())) != 0) + { + // need to implement + texture1D->copyTexSubImage1D(state,_viewport->x(), _viewport->x(),_viewport->y(),_viewport->width()); + } + else if ((texture3D = dynamic_cast(_texture.get())) != 0) + { + // need to implement + texture3D->copyTexSubImage3D(state, _viewport->x(), _viewport->y(), _face, _viewport->x(), _viewport->y(), _viewport->width(), _viewport->height()); + } + else if ((textureCubeMap = dynamic_cast(_texture.get())) != 0) + { + // need to implement + textureCubeMap->copyTexSubImageCubeMap(state, _face, _viewport->x(), _viewport->y(), _viewport->x(),_viewport->y(),_viewport->width(),_viewport->height()); + } +#else + // use CopySubImage with the offset set to 0,0 + // original code path. if ((texture2D = dynamic_cast(_texture.get())) != 0) { texture2D->copyTexImage2D(state,_viewport->x(),_viewport->y(),_viewport->width(),_viewport->height()); @@ -604,6 +654,7 @@ void RenderStage::copyTexture(osg::State& state) // need to implement textureCubeMap->copyTexSubImageCubeMap(state, _face, 0, 0, _viewport->x(),_viewport->y(),_viewport->width(),_viewport->height()); } +#endif } void RenderStage::drawInner(osg::State& state,RenderLeaf*& previous, bool& doCopyTexture)