diff --git a/examples/osgprerender/osgprerender.cpp b/examples/osgprerender/osgprerender.cpp index 863eb8c8c..a72d70194 100644 --- a/examples/osgprerender/osgprerender.cpp +++ b/examples/osgprerender/osgprerender.cpp @@ -4,6 +4,7 @@ #include #include #include +#include #include #include #include @@ -107,7 +108,52 @@ class MyGeometryCallback : }; -osg::Node* createPreRenderSubGraph(osg::Node* subgraph, unsigned tex_width, unsigned tex_height, osg::CameraNode::RenderTargetImplementation renderImplementation) +struct MyCameraPostDrawCallback : public osg::CameraNode::DrawCallback +{ + MyCameraPostDrawCallback(osg::Image* image): + _image(image) + { + } + + virtual void operator () (const osg::CameraNode& /*camera*/) const + { + if (_image && _image->getPixelFormat()==GL_RGBA && _image->getDataType()==GL_UNSIGNED_BYTE) + { + + // we'll pick out the center 1/2 of the whole image, + int column_start = _image->s()/4; + int column_end = 3*column_start; + + int row_start = _image->t()/4; + int row_end = 3*row_start; + + + // and then invert these pixels + for(int r=row_start; rdata(column_start, r); + for(int c=column_start; cdirty(); + } + + } + + osg::Image* _image; +}; + + +osg::Node* createPreRenderSubGraph(osg::Node* subgraph, unsigned tex_width, unsigned tex_height, osg::CameraNode::RenderTargetImplementation renderImplementation, bool useImage, bool useTextureRectangle) { if (!subgraph) return 0; @@ -115,11 +161,27 @@ osg::Node* createPreRenderSubGraph(osg::Node* subgraph, unsigned tex_width, unsi osg::Group* parent = new osg::Group; // texture to render to and to use for rendering of flag. - osg::Texture2D* texture = new osg::Texture2D; - texture->setTextureSize(tex_width, tex_height); - texture->setInternalFormat(GL_RGBA); - texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); - texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); + osg::Texture* texture = 0; + if (useTextureRectangle) + { + osg::TextureRectangle* textureRect = new osg::TextureRectangle; + textureRect->setTextureSize(tex_width, tex_height); + textureRect->setInternalFormat(GL_RGBA); + textureRect->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); + textureRect->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); + + texture = textureRect; + } + else + { + osg::Texture2D* texture2D = new osg::Texture2D; + texture2D->setTextureSize(tex_width, tex_height); + texture2D->setInternalFormat(GL_RGBA); + texture2D->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); + texture2D->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR); + + texture = texture2D; + } // first create the geometry of the flag of which to view. { @@ -142,9 +204,11 @@ osg::Node* createPreRenderSubGraph(osg::Node* subgraph, unsigned tex_width, unsi osg::Vec3 dv = xAxis*(width/((float)(noSteps-1))); osg::Vec2Array* texcoords = new osg::Vec2Array; + + // note, when we use TextureRectangle we have to scale the tex coords up to compensate. osg::Vec2 bottom_texcoord(0.0f,0.0f); - osg::Vec2 top_texcoord(0.0f,1.0f); - osg::Vec2 dv_texcoord(1.0f/(float)(noSteps-1),0.0f); + osg::Vec2 top_texcoord(0.0f, useTextureRectangle ? tex_height : 1.0f); + osg::Vec2 dv_texcoord((useTextureRectangle ? tex_width : 1.0f)/(float)(noSteps-1),0.0f); for(int i=0;isetRenderTargetImplementation(renderImplementation); - // attach the texture and use it as the color buffer. - camera->attach(osg::CameraNode::COLOR_BUFFER, texture); + + if (useImage) + { + osg::Image* image = new osg::Image; + image->allocateImage(tex_width, tex_height, 1, GL_RGBA, GL_UNSIGNED_BYTE); + + // attach the image so its copied on each frame. + camera->attach(osg::CameraNode::COLOR_BUFFER, image); + + camera->setPostDrawCallback(new MyCameraPostDrawCallback(image)); + + // Rather than attach the texture directly to illustrate the texture's ability to + // detect an image update and to subload the image onto the texture. You needn't + // do this when using an Image for copying to, as a seperate camera->attach(..) + // would suffice as well, but we'll do it the long way round here just for demonstation + // purposes (long way round meaning we'll need to copy image to main memory, then + // copy it back to the graphics card to the texture in one frame). + // The long way round allows us to mannually modify the copied image via the callback + // and then let this modified image by reloaded back. + texture->setImage(0, image); + } + else + { + // attach the texture and use it as the color buffer. + camera->attach(osg::CameraNode::COLOR_BUFFER, texture); + } + // add subgraph to render camera->addChild(subgraph); @@ -289,6 +378,12 @@ int main( int argc, char **argv ) while (arguments.read("--fb")) { renderImplementation = osg::CameraNode::FRAME_BUFFER; } while (arguments.read("--window")) { renderImplementation = osg::CameraNode::SEPERATE_WINDOW; } + bool useImage = false; + while (arguments.read("--image")) { useImage = true; } + + bool useTextureRectangle = false; + while (arguments.read("--texture-rectangle")) { useTextureRectangle = true; } + // any option left unread are converted into errors to write out later. arguments.reportRemainingOptionsAsUnrecognized(); @@ -322,7 +417,7 @@ int main( int argc, char **argv ) loadedModelTransform->setUpdateCallback(nc); osg::Group* rootNode = new osg::Group(); - rootNode->addChild(createPreRenderSubGraph(loadedModelTransform,tex_width,tex_height, renderImplementation)); + rootNode->addChild(createPreRenderSubGraph(loadedModelTransform,tex_width,tex_height, renderImplementation, useImage, useTextureRectangle)); // add model to the viewer.