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:
parent
a30ec25067
commit
1264ec736a
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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());
|
||||||
|
cv->pushStateSet(_volumeRenderStateSet.get());
|
||||||
|
|
||||||
|
if (getVolumeTile()->getNumChildren()>0)
|
||||||
|
{
|
||||||
|
getVolumeTile()->osg::Group::traverse(*cv);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
_transform->accept(*cv);
|
_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()
|
||||||
|
@ -45,7 +45,6 @@ class RTTCameraCullCallback : public osg::NodeCallback
|
|||||||
virtual ~RTTCameraCullCallback() {}
|
virtual ~RTTCameraCullCallback() {}
|
||||||
|
|
||||||
osgVolume::VolumeScene* _volumeScene;
|
osgVolume::VolumeScene* _volumeScene;
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
@ -81,10 +80,7 @@ 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);
|
|
||||||
if (cv)
|
|
||||||
{
|
{
|
||||||
osg::ref_ptr<ViewData> viewData;
|
osg::ref_ptr<ViewData> viewData;
|
||||||
|
|
||||||
@ -93,27 +89,112 @@ void VolumeScene::tileVisited(osg::NodeVisitor* nv, osgVolume::VolumeTile* tile)
|
|||||||
viewData = _viewDataMap[cv];
|
viewData = _viewDataMap[cv];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//osg::BoundingBox bb(0.0f,0.0f,0.0f,1.0f,1.0f,1.0f);
|
||||||
|
//cv->updateCalculatedNearFar(*(cv->getModelViewMatrix()),bb);
|
||||||
|
|
||||||
if (viewData.valid())
|
if (viewData.valid())
|
||||||
{
|
{
|
||||||
|
int textureWidth = 512;
|
||||||
|
int textureHeight = 512;
|
||||||
|
|
||||||
|
osg::Viewport* viewport = cv->getCurrentRenderStage()->getViewport();
|
||||||
|
if (viewport)
|
||||||
|
{
|
||||||
|
textureWidth = viewport->width();
|
||||||
|
textureHeight = viewport->height();
|
||||||
|
}
|
||||||
|
|
||||||
osg::ref_ptr<TileData>& tileData = viewData->_tiles[tile];
|
osg::ref_ptr<TileData>& tileData = viewData->_tiles[tile];
|
||||||
if (!tileData) tileData = new TileData;
|
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->active = true;
|
||||||
tileData->nodePath = cv->getNodePath();
|
tileData->nodePath = cv->getNodePath();
|
||||||
tileData->projectionMatrix = cv->getProjectionMatrix();
|
tileData->projectionMatrix = cv->getProjectionMatrix();
|
||||||
tileData->modelviewMatrix = cv->getModelViewMatrix();
|
tileData->modelviewMatrix = cv->getModelViewMatrix();
|
||||||
}
|
|
||||||
|
|
||||||
osg::BoundingBox bb(0.0f,0.0f,0.0f,1.0f,1.0f,1.0f);
|
|
||||||
cv->updateCalculatedNearFar(*(cv->getModelViewMatrix()),bb);
|
if (tileData->depthTexture.valid())
|
||||||
|
{
|
||||||
|
if (tileData->depthTexture->getTextureWidth()!=textureWidth || tileData->depthTexture->getTextureHeight()!=textureHeight)
|
||||||
|
{
|
||||||
|
OSG_NOTICE<<"Need to change texture size to "<<textureHeight<<", "<<textureWidth<<std::endl;
|
||||||
|
tileData->depthTexture->setTextureSize(textureWidth, textureHeight);
|
||||||
|
tileData->rttCamera->setViewport(0, 0, textureWidth, textureHeight);
|
||||||
|
if (tileData->rttCamera->getRenderingCache())
|
||||||
|
{
|
||||||
|
tileData->rttCamera->getRenderingCache()->releaseGLObjects(0);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return tileData.get();
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
VolumeScene::TileData* VolumeScene::getTileData(osgUtil::CullVisitor* cv, osgVolume::VolumeTile* tile)
|
||||||
|
{
|
||||||
|
osg::ref_ptr<ViewData> viewData;
|
||||||
|
{
|
||||||
|
OpenThreads::ScopedLock<OpenThreads::Mutex> lock(_viewDataMapMutex);
|
||||||
|
viewData = _viewDataMap[cv];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!viewData) return 0;
|
||||||
|
|
||||||
|
Tiles::iterator itr = viewData->_tiles.find(tile);
|
||||||
|
return (itr != viewData->_tiles.end()) ? itr->second.get() : 0;
|
||||||
|
}
|
||||||
|
|
||||||
void VolumeScene::traverse(osg::NodeVisitor& nv)
|
void VolumeScene::traverse(osg::NodeVisitor& nv)
|
||||||
{
|
{
|
||||||
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
|
osgUtil::CullVisitor* cv = dynamic_cast<osgUtil::CullVisitor*>(&nv);
|
||||||
if (cv)
|
if (!cv)
|
||||||
{
|
{
|
||||||
|
Group::traverse(nv);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save current cull settings
|
||||||
|
osg::CullSettings saved_cull_settings(*cv);
|
||||||
|
|
||||||
|
// cv->setComputeNearFarMode(osg::CullSettings::DO_NOT_COMPUTE_NEAR_FAR);
|
||||||
|
|
||||||
osg::ref_ptr<ViewData> viewData;
|
osg::ref_ptr<ViewData> viewData;
|
||||||
bool initializeViewData = false;
|
bool initializeViewData = false;
|
||||||
{
|
{
|
||||||
@ -374,11 +455,9 @@ void VolumeScene::traverse(osg::NodeVisitor& nv)
|
|||||||
TileData* tileData = itr->second.get();
|
TileData* tileData = itr->second.get();
|
||||||
if (!tileData || !(tileData->active))
|
if (!tileData || !(tileData->active))
|
||||||
{
|
{
|
||||||
OSG_NOTICE<<"Skipping TileData that is inactive : "<<tileData<<std::endl;
|
OSG_INFO<<"Skipping TileData that is inactive : "<<tileData<<std::endl;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
OSG_NOTICE<<"Handling TileData that is active : "<<tileData<<std::endl;
|
|
||||||
|
|
||||||
|
|
||||||
unsigned int numStateSetPushed = 0;
|
unsigned int numStateSetPushed = 0;
|
||||||
|
|
||||||
@ -395,6 +474,8 @@ void VolumeScene::traverse(osg::NodeVisitor& nv)
|
|||||||
cv->pushStateSet(viewData->_stateset.get());
|
cv->pushStateSet(viewData->_stateset.get());
|
||||||
++numStateSetPushed;
|
++numStateSetPushed;
|
||||||
|
|
||||||
|
cv->pushStateSet(tileData->stateset.get());
|
||||||
|
++numStateSetPushed;
|
||||||
|
|
||||||
osg::NodePath::iterator np_itr = nodePath.begin();
|
osg::NodePath::iterator np_itr = nodePath.begin();
|
||||||
|
|
||||||
@ -427,10 +508,14 @@ void VolumeScene::traverse(osg::NodeVisitor& nv)
|
|||||||
cv->popProjectionMatrix();
|
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;
|
cv->getNodePath() = nodePathPriorToTraversingSubgraph;
|
||||||
}
|
|
||||||
else
|
// restore the previous cull settings
|
||||||
{
|
cv->setCullSettings(saved_cull_settings);
|
||||||
Group::traverse(nv);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user