Added support for controlling the extents of the volume rendering by nesting the hull underneath VolumeTile. Currently only supported by the new osgVolume::MultipassTechnique

This commit is contained in:
Robert Osfield 2014-01-16 16:08:43 +00:00
parent a30ec25067
commit 1264ec736a
4 changed files with 544 additions and 349 deletions

View File

@ -33,7 +33,9 @@ class OSGVOLUME_EXPORT MultipassTechnique : public VolumeTechnique
virtual void update(osgUtil::UpdateVisitor* nv); virtual void update(osgUtil::UpdateVisitor* nv);
virtual void cull(osgUtil::CullVisitor* nv); virtual void backfaceSubgraphCullTraversal(osgUtil::CullVisitor* cv);
virtual void cull(osgUtil::CullVisitor* cv);
/** Clean scene graph from any terrain technique specific nodes.*/ /** Clean scene graph from any terrain technique specific nodes.*/
virtual void cleanSceneGraph(); virtual void cleanSceneGraph();
@ -53,6 +55,7 @@ class OSGVOLUME_EXPORT MultipassTechnique : public VolumeTechnique
ModelViewMatrixMap _modelViewMatrixMap; ModelViewMatrixMap _modelViewMatrixMap;
osg::ref_ptr<osg::StateSet> _whenMovingStateSet; osg::ref_ptr<osg::StateSet> _whenMovingStateSet;
osg::ref_ptr<osg::StateSet> _volumeRenderStateSet;
osg::StateSet* createStateSet(osg::StateSet* statesetPrototype, osg::Program* programPrototype, osg::Shader* shaderToAdd1=0, osg::Shader* shaderToAdd2=0); osg::StateSet* createStateSet(osg::StateSet* statesetPrototype, osg::Program* programPrototype, osg::Shader* shaderToAdd1=0, osg::Shader* shaderToAdd2=0);
@ -69,6 +72,8 @@ class OSGVOLUME_EXPORT MultipassTechnique : public VolumeTechnique
typedef std::map<int, osg::ref_ptr<osg::StateSet> > StateSetMap; typedef std::map<int, osg::ref_ptr<osg::StateSet> > StateSetMap;
StateSetMap _stateSetMap; StateSetMap _stateSetMap;
osg::ref_ptr<osg::StateSet> _frontFaceStateSet;
}; };
} }

View File

@ -36,12 +36,6 @@ class OSGVOLUME_EXPORT VolumeScene : public osg::Group
virtual void traverse(osg::NodeVisitor& nv); virtual void traverse(osg::NodeVisitor& nv);
void tileVisited(osg::NodeVisitor* nv, osgVolume::VolumeTile* tile);
protected:
virtual ~VolumeScene();
struct TileData : public osg::Referenced struct TileData : public osg::Referenced
{ {
TileData() : active(false) {} TileData() : active(false) {}
@ -54,8 +48,17 @@ class OSGVOLUME_EXPORT VolumeScene : public osg::Group
osg::ref_ptr<osg::Texture2D> depthTexture; osg::ref_ptr<osg::Texture2D> depthTexture;
osg::ref_ptr<osg::Camera> rttCamera; osg::ref_ptr<osg::Camera> rttCamera;
osg::ref_ptr<osg::Camera> stateset; osg::ref_ptr<osg::StateSet> stateset;
osg::ref_ptr<osg::Uniform> texgenUniform;
}; };
TileData* tileVisited(osgUtil::CullVisitor* cv, osgVolume::VolumeTile* tile);
TileData* getTileData(osgUtil::CullVisitor* cv, osgVolume::VolumeTile* tile);
protected:
virtual ~VolumeScene();
typedef std::map< VolumeTile*, osg::ref_ptr<TileData> > Tiles; typedef std::map< VolumeTile*, osg::ref_ptr<TileData> > Tiles;
class ViewData : public osg::Referenced class ViewData : public osg::Referenced

View File

@ -295,15 +295,17 @@ void MultipassTechnique::init()
OSG_NOTICE<<"MultipassTechnique::init() : geometryMatrix = "<<geometryMatrix<<std::endl; OSG_NOTICE<<"MultipassTechnique::init() : geometryMatrix = "<<geometryMatrix<<std::endl;
OSG_NOTICE<<"MultipassTechnique::init() : imageMatrix = "<<imageMatrix<<std::endl; OSG_NOTICE<<"MultipassTechnique::init() : imageMatrix = "<<imageMatrix<<std::endl;
osg::ref_ptr<osg::StateSet> stateset = _transform->getOrCreateStateSet(); osg::ref_ptr<osg::StateSet> stateset = new osg::StateSet;
_volumeRenderStateSet = stateset;
unsigned int texgenTextureUnit = 0; unsigned int texgenTextureUnit = 0;
unsigned int volumeTextureUnit = 2; unsigned int volumeTextureUnit = 3;
// set up uniforms // set up uniforms
{ {
stateset->addUniform(new osg::Uniform("colorTexture",0)); stateset->addUniform(new osg::Uniform("colorTexture",0));
stateset->addUniform(new osg::Uniform("depthTexture",1)); stateset->addUniform(new osg::Uniform("depthTexture",1));
stateset->addUniform(new osg::Uniform("frontFaceDepthTexture",2));
stateset->setMode(GL_ALPHA_TEST,osg::StateAttribute::ON); stateset->setMode(GL_ALPHA_TEST,osg::StateAttribute::ON);
@ -355,7 +357,7 @@ void MultipassTechnique::init()
} }
} }
stateset->setTextureAttributeAndModes(texgenTextureUnit, texgen.get(), osg::StateAttribute::ON); stateset->setTextureAttributeAndModes(texgenTextureUnit, texgen.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE );
} }
@ -407,7 +409,7 @@ void MultipassTechnique::init()
} }
texture3D->setImage(image_3d); texture3D->setImage(image_3d);
stateset->setTextureAttributeAndModes(volumeTextureUnit, texture3D, osg::StateAttribute::ON); stateset->setTextureAttributeAndModes(volumeTextureUnit, texture3D, osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
osg::ref_ptr<osg::Uniform> baseTextureSampler = new osg::Uniform("volumeTexture", int(volumeTextureUnit)); osg::ref_ptr<osg::Uniform> baseTextureSampler = new osg::Uniform("volumeTexture", int(volumeTextureUnit));
stateset->addUniform(baseTextureSampler.get()); stateset->addUniform(baseTextureSampler.get());
@ -446,7 +448,7 @@ void MultipassTechnique::init()
unsigned int transferFunctionTextureUnit = volumeTextureUnit+1; unsigned int transferFunctionTextureUnit = volumeTextureUnit+1;
stateset->setTextureAttributeAndModes(transferFunctionTextureUnit, tf_texture.get(), osg::StateAttribute::ON); stateset->setTextureAttributeAndModes(transferFunctionTextureUnit, tf_texture.get(), osg::StateAttribute::ON | osg::StateAttribute::OVERRIDE);
stateset->addUniform(new osg::Uniform("tfTexture",int(transferFunctionTextureUnit))); stateset->addUniform(new osg::Uniform("tfTexture",int(transferFunctionTextureUnit)));
stateset->addUniform(new osg::Uniform("tfOffset",tfOffset)); stateset->addUniform(new osg::Uniform("tfOffset",tfOffset));
stateset->addUniform(new osg::Uniform("tfScale",tfScale)); stateset->addUniform(new osg::Uniform("tfScale",tfScale));
@ -487,12 +489,13 @@ void MultipassTechnique::init()
#endif #endif
osg::ref_ptr<osg::Shader> back_main_fragmentShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_multipass_back.frag"); osg::ref_ptr<osg::Shader> back_main_fragmentShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_multipass_back_with_front_depthtexture.frag");;
//osg::ref_ptr<osg::Shader> back_main_fragmentShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_multipass_back.frag");
#if 0 #if 0
if (!back_main_fragmentShader) if (!back_main_fragmentShader)
{ {
#include "Shaders/volume_multipass_back_frag.cpp" #include "Shaders/shaders/volume_multipass_back_with_front_depthtexture_frag.cpp"
back_main_fragmentShader = new osg::Shader(osg::Shader::VERTEX, volume_multipass_back_frag)); back_main_fragmentShader = new osg::Shader(osg::Shader::VERTEX, volume_multipass_back_with_front_depthtexture_frag));
} }
#endif #endif
@ -502,7 +505,7 @@ void MultipassTechnique::init()
osg::ref_ptr<osg::StateSet> front_stateset_prototype = new osg::StateSet; osg::ref_ptr<osg::StateSet> front_stateset_prototype = new osg::StateSet;
osg::ref_ptr<osg::Program> front_program_prototype = new osg::Program; osg::ref_ptr<osg::Program> front_program_prototype = new osg::Program;
{ {
front_stateset_prototype->setAttributeAndModes(front_CullFace.get(), osg::StateAttribute::ON); front_stateset_prototype->setAttributeAndModes(front_CullFace.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
front_program_prototype->addShader(main_vertexShader.get()); front_program_prototype->addShader(main_vertexShader.get());
front_program_prototype->addShader(front_main_fragmentShader.get()); front_program_prototype->addShader(front_main_fragmentShader.get());
@ -512,13 +515,28 @@ void MultipassTechnique::init()
osg::ref_ptr<osg::StateSet> back_stateset_prototype = new osg::StateSet; osg::ref_ptr<osg::StateSet> back_stateset_prototype = new osg::StateSet;
osg::ref_ptr<osg::Program> back_program_prototype = new osg::Program; osg::ref_ptr<osg::Program> back_program_prototype = new osg::Program;
{ {
back_stateset_prototype->setAttributeAndModes(back_CullFace.get(), osg::StateAttribute::ON); back_stateset_prototype->setAttributeAndModes(back_CullFace.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
back_program_prototype->addShader(main_vertexShader.get()); back_program_prototype->addShader(main_vertexShader.get());
back_program_prototype->addShader(back_main_fragmentShader.get()); back_program_prototype->addShader(back_main_fragmentShader.get());
back_program_prototype->addShader(computeRayColorShader.get()); back_program_prototype->addShader(computeRayColorShader.get());
} }
// set up the rendering of the front face
{
_frontFaceStateSet = new osg::StateSet;
// cull only the bac faces so we write only the front
_frontFaceStateSet->setAttributeAndModes(front_CullFace.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
// set up the front falce
osg::ref_ptr<osg::Program> program = new osg::Program;
program->addShader(main_vertexShader.get());
_frontFaceStateSet->setAttribute(program.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
}
// STANDARD_SHADERS // STANDARD_SHADERS
{ {
// STANDARD_SHADERS without TransferFunction // STANDARD_SHADERS without TransferFunction
@ -690,7 +708,6 @@ void MultipassTechnique::init()
if (cpv._sampleRatioWhenMovingProperty.valid()) if (cpv._sampleRatioWhenMovingProperty.valid())
{ {
_whenMovingStateSet = new osg::StateSet; _whenMovingStateSet = new osg::StateSet;
//_whenMovingStateSet->setTextureAttributeAndModes(volumeTextureUnit, new osg::TexEnvFilter(1.0));
_whenMovingStateSet->addUniform(cpv._sampleRatioWhenMovingProperty->getUniform(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON); _whenMovingStateSet->addUniform(cpv._sampleRatioWhenMovingProperty->getUniform(), osg::StateAttribute::OVERRIDE | osg::StateAttribute::ON);
} }
@ -701,14 +718,89 @@ void MultipassTechnique::update(osgUtil::UpdateVisitor* /*uv*/)
// OSG_NOTICE<<"MultipassTechnique:update(osgUtil::UpdateVisitor* nv):"<<std::endl; // OSG_NOTICE<<"MultipassTechnique:update(osgUtil::UpdateVisitor* nv):"<<std::endl;
} }
void MultipassTechnique::backfaceSubgraphCullTraversal(osgUtil::CullVisitor* cv)
{
if (!cv) return;
cv->pushStateSet(_frontFaceStateSet.get());
if (getVolumeTile()->getNumChildren()>0)
{
getVolumeTile()->osg::Group::traverse(*cv);
}
else
{
_transform->accept(*cv);
}
cv->popStateSet();
}
class RTTBackfaceCameraCullCallback : public osg::NodeCallback
{
public:
RTTBackfaceCameraCullCallback(VolumeScene::TileData* tileData, MultipassTechnique* mt):
_tileData(tileData),
_mt(mt) {}
virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
{
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv);
cv->pushProjectionMatrix(_tileData->projectionMatrix);
_mt->backfaceSubgraphCullTraversal(cv);
cv->popProjectionMatrix();
}
protected:
virtual ~RTTBackfaceCameraCullCallback() {}
osg::observer_ptr<osgVolume::VolumeScene::TileData> _tileData;
osg::observer_ptr<osgVolume::MultipassTechnique> _mt;
};
void MultipassTechnique::cull(osgUtil::CullVisitor* cv) void MultipassTechnique::cull(osgUtil::CullVisitor* cv)
{ {
std::string traversalPass; std::string traversalPass;
bool postTraversal = cv->getUserValue("VolumeSceneTraversal", traversalPass) && traversalPass=="Post"; bool rttTraversal = cv->getUserValue("VolumeSceneTraversal", traversalPass) && traversalPass=="RenderToTexture";
// OSG_NOTICE<<"MultipassTechnique::cull() traversalPass="<<traversalPass<<std::endl; // OSG_NOTICE<<"MultipassTechnique::cull() traversalPass="<<traversalPass<<std::endl;
osgVolume::VolumeScene* vs = 0;
osg::NodePath& nodePath = cv->getNodePath();
for(osg::NodePath::reverse_iterator itr = nodePath.rbegin();
(itr != nodePath.rend()) && (vs == 0);
++itr)
{
vs = dynamic_cast<osgVolume::VolumeScene*>(*itr);
}
if (postTraversal) if (rttTraversal)
{
if (vs)
{
VolumeScene::TileData* tileData = vs->tileVisited(cv, getVolumeTile());
if (tileData->rttCamera.valid())
{
if (!(tileData->rttCamera->getCullCallback()))
{
tileData->rttCamera->setCullCallback(new RTTBackfaceCameraCullCallback(tileData, this));
}
// traverse RTT Camera
tileData->rttCamera->accept(*cv);
}
osg::BoundingBox bb;
if (_transform.valid()) bb.expandBy(_transform->getBound());
if (getVolumeTile()->getNumChildren()>0) bb.expandBy(getVolumeTile()->getBound());
cv->updateCalculatedNearFar(*(cv->getModelViewMatrix()),bb);
}
}
else
{ {
int shaderMask = 0; int shaderMask = 0;
@ -740,14 +832,27 @@ void MultipassTechnique::cull(osgUtil::CullVisitor* cv)
} }
} }
int shaderMaskFront = shaderMask | FRONT_SHADERS; //int shaderMaskFront = shaderMask | FRONT_SHADERS;
int shaderMaskBack = shaderMask | BACK_SHADERS; int shaderMaskBack = shaderMask | BACK_SHADERS;
// OSG_NOTICE<<"shaderMaskFront "<<shaderMaskFront<<std::endl; // OSG_NOTICE<<"shaderMaskFront "<<shaderMaskFront<<std::endl;
// OSG_NOTICE<<"shaderMaskBack "<<shaderMaskBack<<std::endl; // OSG_NOTICE<<"shaderMaskBack "<<shaderMaskBack<<std::endl;
if (vs)
{
VolumeScene::TileData* tileData = vs->getTileData(cv, getVolumeTile());
if (tileData)
{
Locator* layerLocator = _volumeTile->getLayer()->getLocator();
osg::Matrix imv = layerLocator->getTransform() * (*(cv->getModelViewMatrix()));
osg::Matrix inverse_imv;
inverse_imv.invert(imv);
tileData->texgenUniform->set(osg::Matrixf(inverse_imv));
}
}
osg::ref_ptr<osg::StateSet> front_stateset = _stateSetMap[shaderMaskFront];
//osg::ref_ptr<osg::StateSet> front_stateset = _stateSetMap[shaderMaskFront];
osg::ref_ptr<osg::StateSet> back_stateset = _stateSetMap[shaderMaskBack]; osg::ref_ptr<osg::StateSet> back_stateset = _stateSetMap[shaderMaskBack];
osg::ref_ptr<osg::StateSet> moving_stateset = (_whenMovingStateSet.valid() && isMoving(cv)) ? _whenMovingStateSet : 0; osg::ref_ptr<osg::StateSet> moving_stateset = (_whenMovingStateSet.valid() && isMoving(cv)) ? _whenMovingStateSet : 0;
@ -757,6 +862,7 @@ void MultipassTechnique::cull(osgUtil::CullVisitor* cv)
cv->pushStateSet(moving_stateset.get()); cv->pushStateSet(moving_stateset.get());
} }
#if 0
if (front_stateset.valid()) if (front_stateset.valid())
{ {
// OSG_NOTICE<<"Have front stateset"<<std::endl; // OSG_NOTICE<<"Have front stateset"<<std::endl;
@ -764,12 +870,23 @@ void MultipassTechnique::cull(osgUtil::CullVisitor* cv)
_transform->accept(*cv); _transform->accept(*cv);
cv->popStateSet(); cv->popStateSet();
} }
#endif
if (back_stateset.valid()) if (back_stateset.valid())
{ {
// OSG_NOTICE<<"Have back stateset"<<std::endl; // OSG_NOTICE<<"Have back stateset"<<std::endl;
cv->pushStateSet(back_stateset.get()); cv->pushStateSet(back_stateset.get());
_transform->accept(*cv); cv->pushStateSet(_volumeRenderStateSet.get());
if (getVolumeTile()->getNumChildren()>0)
{
getVolumeTile()->osg::Group::traverse(*cv);
}
else
{
_transform->accept(*cv);
}
cv->popStateSet();
cv->popStateSet(); cv->popStateSet();
} }
@ -779,21 +896,6 @@ void MultipassTechnique::cull(osgUtil::CullVisitor* cv)
cv->popStateSet(); cv->popStateSet();
} }
} }
else
{
osg::NodePath& nodePath = cv->getNodePath();
for(osg::NodePath::reverse_iterator itr = nodePath.rbegin();
itr != nodePath.rend();
++itr)
{
osgVolume::VolumeScene* vs = dynamic_cast<osgVolume::VolumeScene*>(*itr);
if (vs)
{
vs->tileVisited(cv, getVolumeTile());
break;
}
}
}
} }
void MultipassTechnique::cleanSceneGraph() void MultipassTechnique::cleanSceneGraph()

View File

@ -45,7 +45,6 @@ class RTTCameraCullCallback : public osg::NodeCallback
virtual ~RTTCameraCullCallback() {} virtual ~RTTCameraCullCallback() {}
osgVolume::VolumeScene* _volumeScene; osgVolume::VolumeScene* _volumeScene;
}; };
@ -81,356 +80,442 @@ VolumeScene::~VolumeScene()
{ {
} }
void VolumeScene::tileVisited(osg::NodeVisitor* nv, osgVolume::VolumeTile* tile) VolumeScene::TileData* VolumeScene::tileVisited(osgUtil::CullVisitor* cv, osgVolume::VolumeTile* tile)
{ {
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(nv); osg::ref_ptr<ViewData> viewData;
if (cv)
{ {
osg::ref_ptr<ViewData> viewData; OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
viewData = _viewDataMap[cv];
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
viewData = _viewDataMap[cv];
}
if (viewData.valid())
{
osg::ref_ptr<TileData>& tileData = viewData->_tiles[tile];
if (!tileData) tileData = new TileData;
tileData->active = true;
tileData->nodePath = cv->getNodePath();
tileData->projectionMatrix = cv->getProjectionMatrix();
tileData->modelviewMatrix = cv->getModelViewMatrix();
}
osg::BoundingBox bb(0.0f,0.0f,0.0f,1.0f,1.0f,1.0f);
cv->updateCalculatedNearFar(*(cv->getModelViewMatrix()),bb);
} }
}
//osg::BoundingBox bb(0.0f,0.0f,0.0f,1.0f,1.0f,1.0f);
//cv->updateCalculatedNearFar(*(cv->getModelViewMatrix()),bb);
void VolumeScene::traverse(osg::NodeVisitor& nv) if (viewData.valid())
{
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
if (cv)
{ {
osg::ref_ptr<ViewData> viewData; int textureWidth = 512;
bool initializeViewData = false; int textureHeight = 512;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
if (!_viewDataMap[cv])
{
_viewDataMap[cv] = new ViewData;
initializeViewData = true;
}
viewData = _viewDataMap[cv];
}
if (initializeViewData)
{
OSG_NOTICE<<"Creating ViewData"<<std::endl;
unsigned textureWidth = 512;
unsigned textureHeight = 512;
osg::Viewport* viewport = cv->getCurrentRenderStage()->getViewport();
if (viewport)
{
textureWidth = viewport->width();
textureHeight = viewport->height();
}
// set up depth texture
viewData->_depthTexture = new osg::Texture2D;
viewData->_depthTexture->setTextureSize(textureWidth, textureHeight);
viewData->_depthTexture->setInternalFormat(GL_DEPTH_COMPONENT);
viewData->_depthTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
viewData->_depthTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
viewData->_depthTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
viewData->_depthTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
viewData->_depthTexture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
// set up color texture
viewData->_colorTexture = new osg::Texture2D;
viewData->_colorTexture->setTextureSize(textureWidth, textureHeight);
viewData->_colorTexture->setInternalFormat(GL_RGBA);
viewData->_colorTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
viewData->_colorTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
viewData->_colorTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_EDGE);
viewData->_colorTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_EDGE);
// set up the RTT Camera to capture the main scene to a color and depth texture that can be used in post processing
viewData->_rttCamera = new osg::Camera;
viewData->_rttCamera->attach(osg::Camera::DEPTH_BUFFER, viewData->_depthTexture.get());
viewData->_rttCamera->attach(osg::Camera::COLOR_BUFFER, viewData->_colorTexture.get());
viewData->_rttCamera->setCullCallback(new RTTCameraCullCallback(this));
viewData->_rttCamera->setViewport(0,0,textureWidth,textureHeight);
// clear the depth and colour bufferson each clear.
viewData->_rttCamera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
// set the camera to render before the main camera.
viewData->_rttCamera->setRenderOrder(osg::Camera::PRE_RENDER);
// tell the camera to use OpenGL frame buffer object where supported.
viewData->_rttCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
viewData->_rttCamera->setReferenceFrame(osg::Transform::RELATIVE_RF);
viewData->_rttCamera->setProjectionMatrix(osg::Matrixd::identity());
viewData->_rttCamera->setViewMatrix(osg::Matrixd::identity());
// create mesh for rendering the RTT textures onto the screen
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->setCullingActive(false);
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)));
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);
// get vertex shaders from source
osg::ref_ptr<osg::Shader> vertexShader = osgDB::readRefShaderFile(osg::Shader::VERTEX, "shaders/volume_color_depth.vert");
if (vertexShader.valid())
{
program->addShader(vertexShader.get());
}
#if 0
else
{
#include "Shaders/volume_color_depth_vert.cpp"
program->addShader(new osg::Shader(osg::Shader::VERTEX, volume_color_depth_vert));
}
#endif
// get fragment shaders from source
osg::ref_ptr<osg::Shader> fragmentShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_color_depth.frag");
if (fragmentShader.valid())
{
program->addShader(fragmentShader.get());
}
#if 0
else
{
#include "Shaders/volume_color_depth_frag.cpp"
program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_color_depth_frag));
}
#endif
viewData->_stateset = new osg::StateSet;
viewData->_stateset->addUniform(new osg::Uniform("colorTexture",0));
viewData->_stateset->addUniform(new osg::Uniform("depthTexture",1));
viewData->_stateset->setTextureAttributeAndModes(0, viewData->_colorTexture.get(), osg::StateAttribute::ON);
viewData->_stateset->setTextureAttributeAndModes(1, viewData->_depthTexture.get(), osg::StateAttribute::ON);
viewData->_viewportDimensionsUniform = new osg::Uniform("viewportDimensions",osg::Vec4(0.0,0.0,1280.0,1024.0));
viewData->_stateset->addUniform(viewData->_viewportDimensionsUniform.get());
geode->setStateSet(viewData->_stateset.get());
}
else
{
// 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->clearTiles();
osg::Viewport* viewport = cv->getCurrentRenderStage()->getViewport(); osg::Viewport* viewport = cv->getCurrentRenderStage()->getViewport();
if (viewport) if (viewport)
{ {
viewData->_viewportDimensionsUniform->set(osg::Vec4(viewport->x(), viewport->y(), viewport->width(),viewport->height())); textureWidth = viewport->width();
textureHeight = viewport->height();
}
if (viewport->width() != viewData->_colorTexture->getTextureWidth() || osg::ref_ptr<TileData>& tileData = viewData->_tiles[tile];
viewport->height() != viewData->_colorTexture->getTextureHeight()) if (!tileData)
{
tileData = new TileData;
tileData->depthTexture = new osg::Texture2D;
tileData->depthTexture->setTextureSize(textureWidth, textureHeight);
tileData->depthTexture->setInternalFormat(GL_DEPTH_COMPONENT);
tileData->depthTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
tileData->depthTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
tileData->depthTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
tileData->depthTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
tileData->depthTexture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
tileData->rttCamera = new osg::Camera;
tileData->rttCamera->attach(osg::Camera::DEPTH_BUFFER, tileData->depthTexture.get());
tileData->rttCamera->setViewport(0,0,textureWidth,textureHeight);
// clear the depth and colour bufferson each clear.
tileData->rttCamera->setClearMask(GL_DEPTH_BUFFER_BIT);
// set the camera to render before the main camera.
tileData->rttCamera->setRenderOrder(osg::Camera::PRE_RENDER);
// tell the camera to use OpenGL frame buffer object where supported.
tileData->rttCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
tileData->rttCamera->setReferenceFrame(osg::Transform::RELATIVE_RF);
tileData->rttCamera->setProjectionMatrix(osg::Matrixd::identity());
tileData->rttCamera->setViewMatrix(osg::Matrixd::identity());
tileData->stateset = new osg::StateSet;
tileData->stateset->setTextureAttribute(2, tileData->depthTexture.get());
tileData->texgenUniform = new osg::Uniform("texgen2",osg::Matrixf());
tileData->stateset->addUniform(tileData->texgenUniform);
}
tileData->active = true;
tileData->nodePath = cv->getNodePath();
tileData->projectionMatrix = cv->getProjectionMatrix();
tileData->modelviewMatrix = cv->getModelViewMatrix();
if (tileData->depthTexture.valid())
{
if (tileData->depthTexture->getTextureWidth()!=textureWidth || tileData->depthTexture->getTextureHeight()!=textureHeight)
{ {
OSG_NOTICE<<"Need to change texture size to "<<viewport->width()<<", "<< viewport->height()<<std::endl; OSG_NOTICE<<"Need to change texture size to "<<textureHeight<<", "<<textureWidth<<std::endl;
viewData->_colorTexture->setTextureSize(viewport->width(), viewport->height()); tileData->depthTexture->setTextureSize(textureWidth, textureHeight);
viewData->_colorTexture->dirtyTextureObject(); tileData->rttCamera->setViewport(0, 0, textureWidth, textureHeight);
viewData->_depthTexture->setTextureSize(viewport->width(), viewport->height()); if (tileData->rttCamera->getRenderingCache())
viewData->_depthTexture->dirtyTextureObject();
viewData->_rttCamera->setViewport(0, 0, viewport->width(), viewport->height());
if (viewData->_rttCamera->getRenderingCache())
{ {
viewData->_rttCamera->getRenderingCache()->releaseGLObjects(0); tileData->rttCamera->getRenderingCache()->releaseGLObjects(0);
} }
} }
} }
cv->setUserValue("VolumeSceneTraversal",std::string("RenderToTexture")); return tileData.get();
}
return 0;
}
osg::Camera* parentCamera = cv->getCurrentCamera(); VolumeScene::TileData* VolumeScene::getTileData(osgUtil::CullVisitor* cv, osgVolume::VolumeTile* tile)
viewData->_rttCamera->setClearColor(parentCamera->getClearColor()); {
osg::ref_ptr<ViewData> viewData;
{
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
viewData = _viewDataMap[cv];
}
//OSG_NOTICE<<"Ready to traverse RTT Camera"<<std::endl; if (!viewData) return 0;
//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; Tiles::iterator itr = viewData->_tiles.find(tile);
//OSG_NOTICE<<" cv ProjectionMatrix After "<<*(cv->getProjectionMatrix())<<std::endl; return (itr != viewData->_tiles.end()) ? itr->second.get() : 0;
}
//OSG_NOTICE<<" after RTT near ="<<cv->getCalculatedNearPlane()<<std::endl; void VolumeScene::traverse(osg::NodeVisitor& nv)
//OSG_NOTICE<<" after RTT far ="<<cv->getCalculatedFarPlane()<<std::endl; {
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
if (!cv)
{
Group::traverse(nv);
return;
}
//OSG_NOTICE<<"tileVisited()"<<viewData->_tiles.size()<<std::endl; // Save current cull settings
osg::CullSettings saved_cull_settings(*cv);
// cv->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
typedef osgUtil::CullVisitor::value_type NearFarValueType; osg::ref_ptr<ViewData> viewData;
NearFarValueType calculatedNearPlane = std::numeric_limits<NearFarValueType>::max(); bool initializeViewData = false;
NearFarValueType calculatedFarPlane = -std::numeric_limits<NearFarValueType>::max(); {
if (viewData->_rttCamera->getUserValue("CalculatedNearPlane",calculatedNearPlane) && OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
viewData->_rttCamera->getUserValue("CalculatedFarPlane",calculatedFarPlane)) if (!_viewDataMap[cv])
{ {
calculatedNearPlane *= 0.5; _viewDataMap[cv] = new ViewData;
calculatedFarPlane *= 2.0; initializeViewData = true;
//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) viewData = _viewDataMap[cv];
}
if (initializeViewData)
{
OSG_NOTICE<<"Creating ViewData"<<std::endl;
unsigned textureWidth = 512;
unsigned textureHeight = 512;
osg::Viewport* viewport = cv->getCurrentRenderStage()->getViewport();
if (viewport)
{ {
cv->clampProjectionMatrix(projectionMatrix, calculatedNearPlane, calculatedFarPlane); textureWidth = viewport->width();
textureHeight = viewport->height();
} }
osg::Matrix inv_projectionModelViewMatrix; // set up depth texture
inv_projectionModelViewMatrix.invert(modelviewMatrix*projectionMatrix); viewData->_depthTexture = new osg::Texture2D;
double depth = 1.0; viewData->_depthTexture->setTextureSize(textureWidth, textureHeight);
osg::Vec3d v00 = osg::Vec3d(-1.0,-1.0,depth)*inv_projectionModelViewMatrix; viewData->_depthTexture->setInternalFormat(GL_DEPTH_COMPONENT);
osg::Vec3d v01 = osg::Vec3d(-1.0,1.0,depth)*inv_projectionModelViewMatrix; viewData->_depthTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
osg::Vec3d v10 = osg::Vec3d(1.0,-1.0,depth)*inv_projectionModelViewMatrix; viewData->_depthTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
osg::Vec3d v11 = osg::Vec3d(1.0,1.0,depth)*inv_projectionModelViewMatrix;
// OSG_NOTICE<<"v00= "<<v00<<std::endl; viewData->_depthTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
// OSG_NOTICE<<"v01= "<<v01<<std::endl; viewData->_depthTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
// OSG_NOTICE<<"v10= "<<v10<<std::endl; viewData->_depthTexture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
// OSG_NOTICE<<"v11= "<<v11<<std::endl;
(*(viewData->_vertices))[0] = v01; // set up color texture
(*(viewData->_vertices))[1] = v00; viewData->_colorTexture = new osg::Texture2D;
(*(viewData->_vertices))[2] = v11;
(*(viewData->_vertices))[3] = v10;
viewData->_geometry->dirtyBound();
//OSG_NOTICE<<" new after RTT near ="<<cv->getCalculatedNearPlane()<<std::endl; viewData->_colorTexture->setTextureSize(textureWidth, textureHeight);
//OSG_NOTICE<<" new after RTT far ="<<cv->getCalculatedFarPlane()<<std::endl; viewData->_colorTexture->setInternalFormat(GL_RGBA);
viewData->_colorTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
viewData->_colorTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
viewData->_backdropSubgraph->accept(*cv); viewData->_colorTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_EDGE);
viewData->_colorTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_EDGE);
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. // set up the RTT Camera to capture the main scene to a color and depth texture that can be used in post processing
Tiles& tiles = viewData->_tiles; viewData->_rttCamera = new osg::Camera;
for(Tiles::iterator itr = tiles.begin(); viewData->_rttCamera->attach(osg::Camera::DEPTH_BUFFER, viewData->_depthTexture.get());
itr != tiles.end(); viewData->_rttCamera->attach(osg::Camera::COLOR_BUFFER, viewData->_colorTexture.get());
++itr) viewData->_rttCamera->setCullCallback(new RTTCameraCullCallback(this));
viewData->_rttCamera->setViewport(0,0,textureWidth,textureHeight);
// clear the depth and colour bufferson each clear.
viewData->_rttCamera->setClearMask(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT);
// set the camera to render before the main camera.
viewData->_rttCamera->setRenderOrder(osg::Camera::PRE_RENDER);
// tell the camera to use OpenGL frame buffer object where supported.
viewData->_rttCamera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
viewData->_rttCamera->setReferenceFrame(osg::Transform::RELATIVE_RF);
viewData->_rttCamera->setProjectionMatrix(osg::Matrixd::identity());
viewData->_rttCamera->setViewMatrix(osg::Matrixd::identity());
// create mesh for rendering the RTT textures onto the screen
osg::ref_ptr<osg::Geode> geode = new osg::Geode;
geode->setCullingActive(false);
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)));
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);
// get vertex shaders from source
osg::ref_ptr<osg::Shader> vertexShader = osgDB::readRefShaderFile(osg::Shader::VERTEX, "shaders/volume_color_depth.vert");
if (vertexShader.valid())
{ {
TileData* tileData = itr->second.get(); program->addShader(vertexShader.get());
if (!tileData || !(tileData->active))
{
OSG_NOTICE<<"Skipping TileData that is inactive : "<<tileData<<std::endl;
continue;
}
OSG_NOTICE<<"Handling TileData that is active : "<<tileData<<std::endl;
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();
} }
#if 0
else
{
#include "Shaders/volume_color_depth_vert.cpp"
program->addShader(new osg::Shader(osg::Shader::VERTEX, volume_color_depth_vert));
}
#endif
// get fragment shaders from source
osg::ref_ptr<osg::Shader> fragmentShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_color_depth.frag");
if (fragmentShader.valid())
{
program->addShader(fragmentShader.get());
}
#if 0
else
{
#include "Shaders/volume_color_depth_frag.cpp"
program->addShader(new osg::Shader(osg::Shader::FRAGMENT, volume_color_depth_frag));
}
#endif
viewData->_stateset = new osg::StateSet;
viewData->_stateset->addUniform(new osg::Uniform("colorTexture",0));
viewData->_stateset->addUniform(new osg::Uniform("depthTexture",1));
viewData->_stateset->setTextureAttributeAndModes(0, viewData->_colorTexture.get(), osg::StateAttribute::ON);
viewData->_stateset->setTextureAttributeAndModes(1, viewData->_depthTexture.get(), osg::StateAttribute::ON);
viewData->_viewportDimensionsUniform = new osg::Uniform("viewportDimensions",osg::Vec4(0.0,0.0,1280.0,1024.0));
viewData->_stateset->addUniform(viewData->_viewportDimensionsUniform.get());
geode->setStateSet(viewData->_stateset.get());
cv->getNodePath() = nodePathPriorToTraversingSubgraph;
} }
else else
{ {
Group::traverse(nv); // 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->clearTiles();
osg::Viewport* viewport = cv->getCurrentRenderStage()->getViewport();
if (viewport)
{
viewData->_viewportDimensionsUniform->set(osg::Vec4(viewport->x(), viewport->y(), viewport->width(),viewport->height()));
if (viewport->width() != viewData->_colorTexture->getTextureWidth() ||
viewport->height() != viewData->_colorTexture->getTextureHeight())
{
OSG_NOTICE<<"Need to change texture size to "<<viewport->width()<<", "<< viewport->height()<<std::endl;
viewData->_colorTexture->setTextureSize(viewport->width(), viewport->height());
viewData->_colorTexture->dirtyTextureObject();
viewData->_depthTexture->setTextureSize(viewport->width(), viewport->height());
viewData->_depthTexture->dirtyTextureObject();
viewData->_rttCamera->setViewport(0, 0, viewport->width(), viewport->height());
if (viewData->_rttCamera->getRenderingCache())
{
viewData->_rttCamera->getRenderingCache()->releaseGLObjects(0);
}
}
}
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;
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<<" after RTT near ="<<cv->getCalculatedNearPlane()<<std::endl;
//OSG_NOTICE<<" after RTT far ="<<cv->getCalculatedFarPlane()<<std::endl;
//OSG_NOTICE<<"tileVisited()"<<viewData->_tiles.size()<<std::endl;
typedef osgUtil::CullVisitor::value_type NearFarValueType;
NearFarValueType calculatedNearPlane = std::numeric_limits<NearFarValueType>::max();
NearFarValueType calculatedFarPlane = -std::numeric_limits<NearFarValueType>::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->second.get();
if (!tileData || !(tileData->active))
{
OSG_INFO<<"Skipping TileData that is inactive : "<<tileData<<std::endl;
continue;
}
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;
cv->pushStateSet(tileData->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();
}
// need to synchronize projection matrices:
// current CV projection matrix
// main scene RTT Camera projection matrix
// each tile RTT Camera
// each tile final render.
cv->getNodePath() = nodePathPriorToTraversingSubgraph;
// restore the previous cull settings
cv->setCullSettings(saved_cull_settings);
} }