Further work on new MultipassTechnique/VolumeScene.

This commit is contained in:
Robert Osfield
2013-12-06 19:31:12 +00:00
parent ed4deeb0fb
commit 3858acf70f
8 changed files with 574 additions and 119 deletions

View File

@@ -13,7 +13,9 @@
#include <osgVolume/VolumeScene>
#include <osg/Geometry>
#include <osg/PrimitiveSet>
#include <osg/Geode>
#include <osg/ValueObject>
#include <osg/io_utils>
#include <osgDB/ReadFile>
#include <OpenThreads/ScopedLock>
@@ -29,34 +31,12 @@ class RTTCameraCullCallback : public osg::NodeCallback
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
#if 1
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
if (cv)
{
osg::Camera* camera = cv->getCurrentCamera();
OSG_NOTICE<<"Current camera="<<camera<<", node="<<node<<std::endl;
OSG_NOTICE<<" before near ="<<cv->getCalculatedNearPlane()<<std::endl;
OSG_NOTICE<<" before far ="<<cv->getCalculatedFarPlane()<<std::endl;
}
_volumeScene->osg::Group::traverse(*nv);
if (cv)
{
OSG_NOTICE<<" after near ="<<cv->getCalculatedNearPlane()<<std::endl;
OSG_NOTICE<<" after far ="<<cv->getCalculatedFarPlane()<<std::endl;
}
#else
osg::Group* group = dynamic_cast<osg::Group*>(node);
if (group)
{
OSG_NOTICE<<"Traversing RTT subgraph, "<<group->className()<<", "<<nv->className()<<std::endl;
group->osg::Group::traverse(*nv);
}
else
{
OSG_NOTICE<<"Can't traverse RTT subgraph"<<std::endl;
}
#endif
node->setUserValue("CalculatedNearPlane",double(cv->getCalculatedNearPlane()));
node->setUserValue("CalculatedFarPlane",double(cv->getCalculatedFarPlane()));
}
protected:
@@ -64,6 +44,7 @@ class RTTCameraCullCallback : public osg::NodeCallback
virtual ~RTTCameraCullCallback() {}
osgVolume::VolumeScene* _volumeScene;
};
@@ -100,8 +81,11 @@ void VolumeScene::tileVisited(osg::NodeVisitor* nv, osgVolume::VolumeTile* tile)
if (viewData.valid())
{
OSG_NOTICE<<"tileVisited("<<tile<<")"<<std::endl;
viewData->_tiles.push_back(nv->getNodePath());
osg::ref_ptr<TileData> tileData = new TileData;
tileData->nodePath = cv->getNodePath();
tileData->projectionMatrix = cv->getProjectionMatrix();
tileData->modelviewMatrix = cv->getModelViewMatrix();
viewData->_tiles.push_back(tileData.get());
}
}
}
@@ -129,7 +113,6 @@ void VolumeScene::traverse(osg::NodeVisitor& nv)
{
OSG_NOTICE<<"Creating ViewData"<<std::endl;
unsigned textureWidth = 512;
unsigned textureHeight = 512;
@@ -187,14 +170,40 @@ void VolumeScene::traverse(osg::NodeVisitor& nv)
// create mesh for rendering the RTT textures onto the screen
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->addDrawable(osg::createTexturedQuadGeometry(osg::Vec3(-1.0f,-1.0f,-1.0f),osg::Vec3(2.0f,0.0f,-1.0f),osg::Vec3(0.0f,2.0f,-1.0f)));
geode->setCullingActive(false);
osg::ref_ptr<osg::StateSet> stateset = geode->getOrCreateStateSet();
viewData->_backdropSubgraph = geode;
//geode->addDrawable(osg::createTexturedQuadGeometry(osg::Vec3(-1.0f,-1.0f,-1.0f),osg::Vec3(2.0f,0.0f,-1.0f),osg::Vec3(0.0f,2.0f,-1.0f)));
stateset->setTextureAttributeAndModes(0, viewData->_colorTexture.get(), osg::StateAttribute::ON);
stateset->setTextureAttributeAndModes(1, viewData->_depthTexture.get(), osg::StateAttribute::ON);
stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::OFF);
viewData->_geometry = new osg::Geometry;
geode->addDrawable(viewData->_geometry.get());
viewData->_geometry->setUseDisplayList(false);
viewData->_geometry->setUseVertexBufferObjects(false);
viewData->_vertices = new osg::Vec3Array(4);
viewData->_geometry->setVertexArray(viewData->_vertices.get());
osg::ref_ptr<osg::Vec4Array> colors = new osg::Vec4Array(1);
(*colors)[0].set(1.0f,1.0f,1.0f,1.0f);
viewData->_geometry->setColorArray(colors.get(), osg::Array::BIND_OVERALL);
osg::ref_ptr<osg::Vec2Array> texcoords = new osg::Vec2Array(4);
(*texcoords)[0].set(0.0f,1.0f);
(*texcoords)[1].set(0.0f,0.0f);
(*texcoords)[2].set(1.0f,1.0f);
(*texcoords)[3].set(1.0f,0.0f);
viewData->_geometry->setTexCoordArray(0, texcoords.get(), osg::Array::BIND_PER_VERTEX);
viewData->_geometry->addPrimitiveSet(new osg::DrawArrays(GL_TRIANGLE_STRIP,0,4));
osg::ref_ptr<osg::StateSet> stateset = viewData->_geometry->getOrCreateStateSet();
stateset->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON);
stateset->setMode(GL_LIGHTING, osg::StateAttribute::OFF);
stateset->setMode(GL_BLEND, osg::StateAttribute::ON);
stateset->setRenderBinDetails(10,"DepthSortedBin");
osg::ref_ptr<osg::Program> program = new osg::Program;
stateset->setAttribute(program);
@@ -225,29 +234,37 @@ void VolumeScene::traverse(osg::NodeVisitor& nv)
program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_color_depth_frag));
}
#endif
stateset->addUniform(new osg::Uniform("colorTexture",0));
stateset->addUniform(new osg::Uniform("depthTexture",1));
viewData->_stateset = new osg::StateSet;
viewData->_stateset->addUniform(new osg::Uniform("colorTexture",0));
viewData->_stateset->addUniform(new osg::Uniform("depthTexture",1));
viewData->_postCamera = new osg::Camera;
viewData->_postCamera->setReferenceFrame(osg::Camera::ABSOLUTE_RF);
viewData->_postCamera->addChild(geode);
viewData->_stateset->setTextureAttributeAndModes(0, viewData->_colorTexture.get(), osg::StateAttribute::ON);
viewData->_stateset->setTextureAttributeAndModes(1, viewData->_depthTexture.get(), osg::StateAttribute::ON);
viewData->_viewportSizeUniform = new osg::Uniform("viewportSize",osg::Vec2(1280.0,1024.0));
viewData->_stateset->addUniform(viewData->_viewportSizeUniform.get());
geode->setStateSet(viewData->_stateset.get());
}
else
{
OSG_NOTICE<<"Reusing ViewData"<<std::endl;
// OSG_NOTICE<<"Reusing ViewData"<<std::endl;
}
osg::Matrix projectionMatrix = *(cv->getProjectionMatrix());
osg::Matrix modelviewMatrix = *(cv->getModelViewMatrix());
// new frame so need to clear last frames log of VolumeTiles
viewData->_tiles.clear();
// record the parent render stage
viewData->_parentRenderStage = cv->getCurrentRenderStage();
osg::Viewport* viewport = cv->getCurrentRenderStage()->getViewport();
if (viewport)
{
viewData->_viewportSizeUniform->set(osg::Vec2(viewport->width(),viewport->height()));
if (viewport->width() != viewData->_colorTexture->getTextureWidth() ||
viewport->height() != viewData->_colorTexture->getTextureHeight())
{
@@ -257,7 +274,6 @@ void VolumeScene::traverse(osg::NodeVisitor& nv)
viewData->_depthTexture->setTextureSize(viewport->width(), viewport->height());
viewData->_depthTexture->dirtyTextureObject();
viewData->_rttCamera->setViewport(0, 0, viewport->width(), viewport->height());
viewData->_postCamera->setViewport(0, 0, viewport->width(), viewport->height());
if (viewData->_rttCamera->getRenderingCache())
{
viewData->_rttCamera->getRenderingCache()->releaseGLObjects(0);
@@ -265,24 +281,126 @@ void VolumeScene::traverse(osg::NodeVisitor& nv)
}
}
cv->setUserValue("VolumeSceneTraversal",std::string("RenderToTexture"));
osg::Camera* parentCamera = cv->getCurrentCamera();
viewData->_rttCamera->setClearColor(parentCamera->getClearColor());
OSG_NOTICE<<"Ready to traverse RTT Camera"<<std::endl;
OSG_NOTICE<<" RTT Camera ProjectionMatrix Before "<<viewData->_rttCamera->getProjectionMatrix()<<std::endl;
//OSG_NOTICE<<"Ready to traverse RTT Camera"<<std::endl;
//OSG_NOTICE<<" RTT Camera ProjectionMatrix Before "<<viewData->_rttCamera->getProjectionMatrix()<<std::endl;
viewData->_rttCamera->accept(nv);
OSG_NOTICE<<" RTT Camera ProjectionMatrix After "<<viewData->_rttCamera->getProjectionMatrix()<<std::endl;
OSG_NOTICE<<" cv ProjectionMatrix After "<<*(cv->getProjectionMatrix())<<std::endl;
//OSG_NOTICE<<" RTT Camera ProjectionMatrix After "<<viewData->_rttCamera->getProjectionMatrix()<<std::endl;
//OSG_NOTICE<<" cv ProjectionMatrix After "<<*(cv->getProjectionMatrix())<<std::endl;
OSG_NOTICE<<" after RTT near ="<<cv->getCalculatedNearPlane()<<std::endl;
OSG_NOTICE<<" after RTT far ="<<cv->getCalculatedFarPlane()<<std::endl;
//OSG_NOTICE<<" after RTT near ="<<cv->getCalculatedNearPlane()<<std::endl;
//OSG_NOTICE<<" after RTT far ="<<cv->getCalculatedFarPlane()<<std::endl;
OSG_NOTICE<<"tileVisited()"<<viewData->_tiles.size()<<std::endl;
//OSG_NOTICE<<"tileVisited()"<<viewData->_tiles.size()<<std::endl;
OSG_NOTICE<<"Ready to traverse POST Camera"<<std::endl;
viewData->_postCamera->accept(nv);
double calculatedNearPlane = DBL_MAX;
double calculatedFarPlane = -DBL_MAX;
if (viewData->_rttCamera->getUserValue("CalculatedNearPlane",calculatedNearPlane) &&
viewData->_rttCamera->getUserValue("CalculatedFarPlane",calculatedFarPlane))
{
calculatedNearPlane *= 0.5;
calculatedFarPlane *= 2.0;
//OSG_NOTICE<<"Got from RTTCamera CalculatedNearPlane="<<calculatedNearPlane<<std::endl;
//OSG_NOTICE<<"Got from RTTCamera CalculatedFarPlane="<<calculatedFarPlane<<std::endl;
if (calculatedNearPlane < cv->getCalculatedNearPlane()) cv->setCalculatedNearPlane(calculatedNearPlane);
if (calculatedFarPlane > cv->getCalculatedFarPlane()) cv->setCalculatedFarPlane(calculatedFarPlane);
}
if (calculatedFarPlane>calculatedNearPlane)
{
cv->clampProjectionMatrix(projectionMatrix, calculatedNearPlane, calculatedFarPlane);
}
osg::Matrix inv_projectionModelViewMatrix;
inv_projectionModelViewMatrix.invert(modelviewMatrix*projectionMatrix);
double depth = 1.0;
osg::Vec3d v00 = osg::Vec3d(-1.0,-1.0,depth)*inv_projectionModelViewMatrix;
osg::Vec3d v01 = osg::Vec3d(-1.0,1.0,depth)*inv_projectionModelViewMatrix;
osg::Vec3d v10 = osg::Vec3d(1.0,-1.0,depth)*inv_projectionModelViewMatrix;
osg::Vec3d v11 = osg::Vec3d(1.0,1.0,depth)*inv_projectionModelViewMatrix;
// OSG_NOTICE<<"v00= "<<v00<<std::endl;
// OSG_NOTICE<<"v01= "<<v01<<std::endl;
// OSG_NOTICE<<"v10= "<<v10<<std::endl;
// OSG_NOTICE<<"v11= "<<v11<<std::endl;
(*(viewData->_vertices))[0] = v01;
(*(viewData->_vertices))[1] = v00;
(*(viewData->_vertices))[2] = v11;
(*(viewData->_vertices))[3] = v10;
viewData->_geometry->dirtyBound();
//OSG_NOTICE<<" new after RTT near ="<<cv->getCalculatedNearPlane()<<std::endl;
//OSG_NOTICE<<" new after RTT far ="<<cv->getCalculatedFarPlane()<<std::endl;
viewData->_backdropSubgraph->accept(*cv);
osg::NodePath nodePathPriorToTraversingSubgraph = cv->getNodePath();
cv->setUserValue("VolumeSceneTraversal",std::string("Post"));
// for each tile that needs post rendering we need to add it into current RenderStage.
Tiles& tiles = viewData->_tiles;
for(Tiles::iterator itr = tiles.begin();
itr != tiles.end();
++itr)
{
TileData* tileData = itr->get();
unsigned int numStateSetPushed = 0;
// OSG_NOTICE<<"VolumeTile to add "<<tileData->projectionMatrix.get()<<", "<<tileData->modelviewMatrix.get()<<std::endl;
osg::NodePath& nodePath = tileData->nodePath;
cv->getNodePath() = nodePath;
cv->pushProjectionMatrix(tileData->projectionMatrix.get());
cv->pushModelViewMatrix(tileData->modelviewMatrix.get(), osg::Transform::ABSOLUTE_RF_INHERIT_VIEWPOINT);
cv->pushStateSet(viewData->_stateset.get());
++numStateSetPushed;
osg::NodePath::iterator np_itr = nodePath.begin();
// skip over all nodes above VolumeScene as this will have already been traverse by CullVisitor
while(np_itr!=nodePath.end() && (*np_itr)!=viewData->_rttCamera.get()) { ++np_itr; }
if (np_itr!=nodePath.end()) ++np_itr;
// push the stateset on the nodes between this VolumeScene and the VolumeTile
for(osg::NodePath::iterator ss_itr = np_itr;
ss_itr != nodePath.end();
++ss_itr)
{
if ((*ss_itr)->getStateSet())
{
numStateSetPushed++;
cv->pushStateSet((*ss_itr)->getStateSet());
// OSG_NOTICE<<" pushing StateSet"<<std::endl;
}
}
cv->traverse(*(tileData->nodePath.back()));
// pop the StateSet's
for(unsigned int i=0; i<numStateSetPushed; ++i)
{
cv->popStateSet();
// OSG_NOTICE<<" popping StateSet"<<std::endl;
}
cv->popModelViewMatrix();
cv->popProjectionMatrix();
}
cv->getNodePath() = nodePathPriorToTraversingSubgraph;
}
else
{