[osg-users] Volume Rendering and Depth Buffer
Anna Osvin
annieloveowls at gmail.com
Fri Apr 12 10:20:28 PDT 2019
Hi. In a project that I'm working on I have an osgVolume::VolumeScene containing one volume model and some polygonal models. I need to do some depth buffer checks on that scene, so I've attached depth buffer to viewer camera. When I fetch osg::Image representing depth buffer content, everything is fine, except background values are not calculated properly (they should be 1, but instead it's ~0.15). And when I add osg::Depth( osg::Depth::Function::LESS, zNear, zFar ) attribute to the camera, background values are calculated correctly, but I lose all of the polygonal models data (they are no longer visible, and not presented in depth buffer).
Here is function that does depth buffer checking:
Code:
bool pickZBufferIntersection( osgViewer::View& view, bool perspectiveProjection, const osg::Vec2& point2d, osg::Vec3& pickedPoint )
{
osg::Camera* camera = view.getCamera();
if ( camera == nullptr )
{
Q_ASSERT_X( false, "bool pickZBufferIntersection( ... )", "View has no camera." );
return false;
}
const osg::Image* zImage = camera->getBufferAttachmentMap()[osg::Camera::BufferComponent::DEPTH_BUFFER]._image;
if ( zImage == nullptr )
{
Q_ASSERT_X( false, "bool pickZBufferIntersection( ... )", "ZBuffer is not attached to view camera." );
return false;
}
osg::Vec3f cameraPos;
osg::Vec3f center;
osg::Vec3f up;
camera->getViewMatrixAsLookAt( cameraPos, center, up );
osg::Matrixd prInv = osg::Matrixd::inverse( camera->getProjectionMatrix() );
osg::Matrixd viewInv = osg::Matrixd::inverse( camera->getViewMatrix() );
const osg::Viewport* viewPort = camera->getViewport();
int x = point2d.x() - viewPort->x();
int y = point2d.y() - viewPort->y();
osg::Vec3 s(0, 0, -1);
s[0] = (point2d[0] / viewPort->width()) * 2.0 - 1.0;
s[1] = (point2d[1] / viewPort->height()) * 2.0 - 1.0;
s = s * prInv * viewInv;
osg::Vec3d v = s - cameraPos;
double zNear = 1.0f;
double zFar = 10000.0f;
static uint pickNumber = 0;
double zV, z_n, z;
osg::Vec3f point;
zV = ( (float*)zImage->data( x, y ) )[ 0 ];
if( perspectiveProjection )
{
z_n = 2.0*zV - 1.0;
z = 2.0 * zNear * zFar / ( zFar + zNear - z_n * ( zFar - zNear ) );
point = cameraPos + v*z;
}
else
{
z = ( zFar - zNear )*zV;
point = s + ( center - cameraPos )*z;
}
if( z > zNear + 1e-8 && z < zFar - 1 - 1e-8 )
{
pickedPoint = point;
return true;
}
return false;
}
And here is viewer setup bit:
Code:
QWidget* createViewWidget(osgQt::GraphicsWindowQt* gw, osgVolume::VolumeScene& scene)
{
osgViewer::View* view = new osgViewer::View;
/* ... */
osg::Camera* camera = view->getCamera();
camera->setGraphicsContext(gw);
camera->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
const osg::GraphicsContext::Traits* traits = gw->getTraits();
camera->setClearColor(osgColor( SCENE3D_BACKGROUND_COLOR ));
camera->setViewport(new osg::Viewport(0, 0, traits->width, traits->height));
osg::ref_ptr<osg::Image> zImage = new osg::Image();
zImage->allocateImage(1000, 1000, 1, GL_DEPTH_COMPONENT, GL_FLOAT);
camera->attach(osg::Camera::DEPTH_BUFFER, zImage);
const int orthoRange = 120;
const float zNear = 1.0f;
const float zFar = 10000.0f;
camera->setProjectionMatrixAsOrtho(-orthoRange, orthoRange, -orthoRange, orthoRange, zNear, zFar);
//camera->getOrCreateStateSet()->setAttribute( new osg::Depth( osg::Depth::Function::LESS, zNear, zFar ), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
/* ... */
view->setSceneData(&scene);
view->addEventHandler(new osgViewer::StatsHandler);
gw->setTouchEventsEnabled(true);
return gw->getGLWidget();
}
...
Thank you!
Cheers,
Annie[/img]
------------------
Read this topic online here:
http://forum.openscenegraph.org/viewtopic.php?p=75829#75829
Attachments:
http://forum.openscenegraph.org//files/depth_buffer_depthrange_185.png
http://forum.openscenegraph.org//files/depth_buffer_154.png
More information about the osg-users
mailing list