Hi everyone,

I am trying to store the Z-Buffer of a subgraph of my scene in an osg::Image for later processing, but the values I obtain are not as expected in the range [0,1] but appear to be integer values starting at 0 and going up to about 200. I am writing the depth buffer to the osg::Image by using image->readPixels(0, 0, width, height, GL_DEPTH_COMPONENT, GL_FLOAT);
The osg code which is executed is:

void Image::readPixels(int x,int y,int width,int height,GLenum format,GLenum type)
   {
       allocateImage(width,height,1,format,type);

       glPixelStorei(GL_PACK_ALIGNMENT,_packing);

       glReadPixels(x,y,width,height,format,type,_data);
   }

And according to the OpenGL reference manual (http://www.opengl.org/sdk/docs/man/xhtml/glReadPixels.xml) the values written to the buffer "_data" should be of type float and in the range [0,1] which they are not for me.

I am wondering if I am doing something wrong.
In the following I posted a short version of my implementation, which is based on the osgprerender example.

First I set up a render to texture pass:
   ...
   // texture to render to
   osg::Texture* texture = 0;
   osg::Texture2D* texture2D = new osg::Texture2D;
   texture2D->setTextureSize(tex_width, tex_height);
   texture2D->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
   texture2D->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
   // set up texture for z-buffer values
   texture2D->setInternalFormat(GL_DEPTH_COMPONENT);
   texture = texture2D;

   // attach an image to the texture.
// this allows us to modify the image data before it is being rendered to the quad
   osg::Image* image = new osg::Image;
   texture2D->setImage(image);
   ...

Then I create a second camera as copy of the main camera which renders to the above texture.

   ...
   // obtain main camera
   osg::Camera* pCamera = ...
   osg::Camera* pCamCopy = new osg::Camera;
// set update callback to update the copied camera's view and projection matrix pCamCopy->setPreDrawCallback(new UpdateCamCallback(pCamera)); // just keeps the copied and the main camera aligned // set the clear mask. -> just the depth buffer is cleared.
   pCamCopy->setClearMask(GL_DEPTH_BUFFER_BIT);
// set the color mask. -> since we do not want any color information to be written we can set all bits to zero.
   pCamCopy->setColorMask(new osg::ColorMask(0,0,0,0));
// set up projection.
   pCamCopy->setProjectionMatrix(pCamera->getProjectionMatrix());
   // set view
   pCamCopy->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
   pCamCopy->setViewMatrix(pCamera->getViewMatrix());
   // set viewport
   pCamCopy->setViewport(0,0,tex_width,tex_height);

   // set the camera to render before the main camera.
   pCamCopy->setRenderOrder(osg::Camera::PRE_RENDER);
   // tell the camera to use OpenGL frame buffer object where supported.
pCamCopy->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
   // attach the texture and use it as the depth buffer
   pCamCopy->attach(osg::Camera::DEPTH_BUFFER, texture);

   // add sub graph to camera for rendering
   pCamCopy->addChild(subGraph);
   // add camera to scene
   pRoot->addChild(pCamCopy)

Finally I set a post draw callback to the copied camera, where the post processing of the depth buffer should be performed. There I call osg::Image::readPixels(...) to copy the depth buffer data from the gpu to the image but the obtained data does not seem to be correct. // set post processing callback pCamCopy->setPostDrawCallback(new FilterImageCallback(image, tex_width, tex_height));

The Code for the callback is as follows:

struct FilterImageCallback : osg::Camera::DrawCallback
{
   FilterImageCallback(osg::Image* pImage, int width, int height)
       :   m_pImage(pImage),
           m_width(width),
           m_height(height)
   {}
void operator () (osg::RenderInfo& renderInfo) const
   {
m_pImage->readPixels(0, 0, m_width, m_height, GL_DEPTH_COMPONENT, GL_FLOAT);

       // apply post processing here:

       // test: obtain first pixel's z value and convert to float.
       float z = (float) (m_pImage->data())[0];
// Problem: z-value is not in range [0, 1] but appears to be 0,1,2, etc. It is 0 for areas where the z-buffer is clear, i.e. z-value corresponds to "infinity".
   }

private:
   osg::Image* m_pImage;
   int m_width;
   int m_height;
};

I can't find the mistake.
Any help is much appreciated!

Cheers and Thank you
Daniel




_______________________________________________
osg-users mailing list
osg-users@lists.openscenegraph.org
http://lists.openscenegraph.org/listinfo.cgi/osg-users-openscenegraph.org

Reply via email to