Restructured the handling of TileData to make it more extensible and flexible.
This commit is contained in:
parent
d7944b6ca9
commit
2f8b0f7a70
@ -19,6 +19,24 @@
|
|||||||
|
|
||||||
namespace osgVolume {
|
namespace osgVolume {
|
||||||
|
|
||||||
|
/** Container for render to texture objects used when doing multi-pass volume rendering techniques.*/
|
||||||
|
struct OSGVOLUME_EXPORT MultipassTileData : public TileData
|
||||||
|
{
|
||||||
|
MultipassTileData(osgUtil::CullVisitor* cv);
|
||||||
|
|
||||||
|
virtual void update(osgUtil::CullVisitor* cv);
|
||||||
|
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Texture2D> frontFaceDepthTexture;
|
||||||
|
osg::ref_ptr<osg::Camera> frontFaceRttCamera;
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Texture2D> backFaceDepthTexture;
|
||||||
|
osg::ref_ptr<osg::Camera> backFaceRttCamera;
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Uniform> texgenUniform;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class OSGVOLUME_EXPORT MultipassTechnique : public VolumeTechnique
|
class OSGVOLUME_EXPORT MultipassTechnique : public VolumeTechnique
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -43,6 +61,10 @@ class OSGVOLUME_EXPORT MultipassTechnique : public VolumeTechnique
|
|||||||
/** Traverse the terrain subgraph.*/
|
/** Traverse the terrain subgraph.*/
|
||||||
virtual void traverse(osg::NodeVisitor& nv);
|
virtual void traverse(osg::NodeVisitor& nv);
|
||||||
|
|
||||||
|
/** Called from VolumeScene to create the TileData container when a multi-pass technique is being used.
|
||||||
|
* The TileData container caches any render to texture objects that are required. */
|
||||||
|
virtual TileData* createTileData(osgUtil::CullVisitor* cv) { return new MultipassTileData(cv); }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
virtual ~MultipassTechnique();
|
virtual ~MultipassTechnique();
|
||||||
|
@ -36,24 +36,8 @@ class OSGVOLUME_EXPORT VolumeScene : public osg::Group
|
|||||||
|
|
||||||
virtual void traverse(osg::NodeVisitor& nv);
|
virtual void traverse(osg::NodeVisitor& nv);
|
||||||
|
|
||||||
struct TileData : public osg::Referenced
|
TileData* tileVisited(osgUtil::CullVisitor* cv, VolumeTile* tile);
|
||||||
{
|
TileData* getTileData(osgUtil::CullVisitor* cv, VolumeTile* tile);
|
||||||
TileData() : active(false) {}
|
|
||||||
|
|
||||||
bool active;
|
|
||||||
|
|
||||||
osg::NodePath nodePath;
|
|
||||||
osg::ref_ptr<osg::RefMatrix> projectionMatrix;
|
|
||||||
osg::ref_ptr<osg::RefMatrix> modelviewMatrix;
|
|
||||||
|
|
||||||
osg::ref_ptr<osg::Texture2D> depthTexture;
|
|
||||||
osg::ref_ptr<osg::Camera> rttCamera;
|
|
||||||
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:
|
protected:
|
||||||
|
|
||||||
|
@ -25,6 +25,23 @@ namespace osgVolume {
|
|||||||
|
|
||||||
class VolumeTile;
|
class VolumeTile;
|
||||||
|
|
||||||
|
/** Container for render to texture objects used when doing multi-pass volume rendering techniques.*/
|
||||||
|
struct TileData : public osg::Referenced
|
||||||
|
{
|
||||||
|
TileData() : active(false) {}
|
||||||
|
|
||||||
|
virtual void update(osgUtil::CullVisitor* cv) = 0;
|
||||||
|
|
||||||
|
bool active;
|
||||||
|
|
||||||
|
osg::NodePath nodePath;
|
||||||
|
osg::ref_ptr<osg::RefMatrix> projectionMatrix;
|
||||||
|
osg::ref_ptr<osg::RefMatrix> modelviewMatrix;
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::StateSet> stateset;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
class OSGVOLUME_EXPORT VolumeTechnique : public osg::Object
|
class OSGVOLUME_EXPORT VolumeTechnique : public osg::Object
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
@ -53,6 +70,10 @@ class OSGVOLUME_EXPORT VolumeTechnique : public osg::Object
|
|||||||
/** Traverse the terrain subgraph.*/
|
/** Traverse the terrain subgraph.*/
|
||||||
virtual void traverse(osg::NodeVisitor& nv);
|
virtual void traverse(osg::NodeVisitor& nv);
|
||||||
|
|
||||||
|
/** Called from VolumeScene to create the TileData container when a multi-pass technique is being used.
|
||||||
|
* The TileData container caches any render to texture objects that are required. */
|
||||||
|
virtual TileData* createTileData(osgUtil::CullVisitor* cv) { return 0; }
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|
||||||
void setDirty(bool dirty);
|
void setDirty(bool dirty);
|
||||||
|
@ -147,7 +147,97 @@ osg::Image* createDownsampledImage(osg::Image* sourceImage)
|
|||||||
return targetImage.release();
|
return targetImage.release();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// MultipassTileData
|
||||||
|
//
|
||||||
|
MultipassTileData::MultipassTileData(osgUtil::CullVisitor* cv):
|
||||||
|
TileData()
|
||||||
|
{
|
||||||
|
int width = 512;
|
||||||
|
int height = 512;
|
||||||
|
|
||||||
|
osg::Viewport* viewport = cv->getCurrentRenderStage()->getViewport();
|
||||||
|
if (viewport)
|
||||||
|
{
|
||||||
|
width = static_cast<int>(viewport->width());
|
||||||
|
height = static_cast<int>(viewport->height());
|
||||||
|
}
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Texture2D> depthTexture = new osg::Texture2D;
|
||||||
|
frontFaceDepthTexture = depthTexture;
|
||||||
|
|
||||||
|
depthTexture->setTextureSize(width, height);
|
||||||
|
depthTexture->setInternalFormat(GL_DEPTH_COMPONENT);
|
||||||
|
depthTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
|
||||||
|
depthTexture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
|
||||||
|
depthTexture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
|
||||||
|
depthTexture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
|
||||||
|
depthTexture->setBorderColor(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
|
||||||
|
|
||||||
|
osg::ref_ptr<osg::Camera> camera = new osg::Camera;
|
||||||
|
frontFaceRttCamera = camera;
|
||||||
|
frontFaceRttCamera->setName("frontFaceRttCamera");
|
||||||
|
camera->attach(osg::Camera::DEPTH_BUFFER, depthTexture.get());
|
||||||
|
camera->setViewport(0, 0, width, height);
|
||||||
|
|
||||||
|
// clear the depth and colour bufferson each clear.
|
||||||
|
camera->setClearMask(GL_DEPTH_BUFFER_BIT);
|
||||||
|
|
||||||
|
// set the camera to render before the main camera.
|
||||||
|
camera->setRenderOrder(osg::Camera::PRE_RENDER);
|
||||||
|
|
||||||
|
// tell the camera to use OpenGL frame buffer object where supported.
|
||||||
|
camera->setRenderTargetImplementation(osg::Camera::FRAME_BUFFER_OBJECT);
|
||||||
|
|
||||||
|
camera->setReferenceFrame(osg::Transform::RELATIVE_RF);
|
||||||
|
camera->setProjectionMatrix(osg::Matrixd::identity());
|
||||||
|
camera->setViewMatrix(osg::Matrixd::identity());
|
||||||
|
|
||||||
|
stateset = new osg::StateSet;
|
||||||
|
stateset->setTextureAttribute(2, depthTexture.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
||||||
|
|
||||||
|
texgenUniform = new osg::Uniform("texgen",osg::Matrixf());
|
||||||
|
|
||||||
|
stateset->addUniform(texgenUniform.get());
|
||||||
|
}
|
||||||
|
|
||||||
|
void MultipassTileData::update(osgUtil::CullVisitor* cv)
|
||||||
|
{
|
||||||
|
active = true;
|
||||||
|
nodePath = cv->getNodePath();
|
||||||
|
projectionMatrix = cv->getProjectionMatrix();
|
||||||
|
modelviewMatrix = cv->getModelViewMatrix();
|
||||||
|
|
||||||
|
int width = 512;
|
||||||
|
int height = 512;
|
||||||
|
|
||||||
|
osg::Viewport* viewport = cv->getCurrentRenderStage()->getViewport();
|
||||||
|
if (viewport)
|
||||||
|
{
|
||||||
|
width = static_cast<int>(viewport->width());
|
||||||
|
height = static_cast<int>(viewport->height());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (frontFaceDepthTexture.valid())
|
||||||
|
{
|
||||||
|
if (frontFaceDepthTexture->getTextureWidth()!=width || frontFaceDepthTexture->getTextureHeight()!=height)
|
||||||
|
{
|
||||||
|
OSG_NOTICE<<"Need to change texture size to "<<width<<", "<<height<<std::endl;
|
||||||
|
frontFaceDepthTexture->setTextureSize(width, height);
|
||||||
|
frontFaceRttCamera->setViewport(0, 0, width, height);
|
||||||
|
if (frontFaceRttCamera->getRenderingCache())
|
||||||
|
{
|
||||||
|
frontFaceRttCamera->getRenderingCache()->releaseGLObjects(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// MultipassTechnique
|
||||||
|
//
|
||||||
MultipassTechnique::MultipassTechnique()
|
MultipassTechnique::MultipassTechnique()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -678,7 +768,7 @@ class RTTBackfaceCameraCullCallback : public osg::NodeCallback
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
RTTBackfaceCameraCullCallback(VolumeScene::TileData* tileData, MultipassTechnique* mt):
|
RTTBackfaceCameraCullCallback(MultipassTileData* tileData, MultipassTechnique* mt):
|
||||||
_tileData(tileData),
|
_tileData(tileData),
|
||||||
_mt(mt) {}
|
_mt(mt) {}
|
||||||
|
|
||||||
@ -697,7 +787,7 @@ class RTTBackfaceCameraCullCallback : public osg::NodeCallback
|
|||||||
|
|
||||||
virtual ~RTTBackfaceCameraCullCallback() {}
|
virtual ~RTTBackfaceCameraCullCallback() {}
|
||||||
|
|
||||||
osg::observer_ptr<osgVolume::VolumeScene::TileData> _tileData;
|
osg::observer_ptr<osgVolume::MultipassTileData> _tileData;
|
||||||
osg::observer_ptr<osgVolume::MultipassTechnique> _mt;
|
osg::observer_ptr<osgVolume::MultipassTechnique> _mt;
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -720,16 +810,16 @@ void MultipassTechnique::cull(osgUtil::CullVisitor* cv)
|
|||||||
{
|
{
|
||||||
if (vs)
|
if (vs)
|
||||||
{
|
{
|
||||||
VolumeScene::TileData* tileData = vs->tileVisited(cv, getVolumeTile());
|
MultipassTileData* tileData = dynamic_cast<MultipassTileData*>(vs->tileVisited(cv, getVolumeTile()));
|
||||||
if (tileData->rttCamera.valid())
|
if (tileData && tileData->frontFaceRttCamera.valid())
|
||||||
{
|
{
|
||||||
if (!(tileData->rttCamera->getCullCallback()))
|
if (!(tileData->frontFaceRttCamera->getCullCallback()))
|
||||||
{
|
{
|
||||||
tileData->rttCamera->setCullCallback(new RTTBackfaceCameraCullCallback(tileData, this));
|
tileData->frontFaceRttCamera->setCullCallback(new RTTBackfaceCameraCullCallback(tileData, this));
|
||||||
}
|
}
|
||||||
|
|
||||||
// traverse RTT Camera
|
// traverse RTT Camera
|
||||||
tileData->rttCamera->accept(*cv);
|
tileData->frontFaceRttCamera->accept(*cv);
|
||||||
}
|
}
|
||||||
|
|
||||||
osg::BoundingBox bb;
|
osg::BoundingBox bb;
|
||||||
@ -776,7 +866,7 @@ void MultipassTechnique::cull(osgUtil::CullVisitor* cv)
|
|||||||
|
|
||||||
if (vs)
|
if (vs)
|
||||||
{
|
{
|
||||||
VolumeScene::TileData* tileData = vs->getTileData(cv, getVolumeTile());
|
MultipassTileData* tileData = dynamic_cast<MultipassTileData*>(vs->getTileData(cv, getVolumeTile()));
|
||||||
if (tileData)
|
if (tileData)
|
||||||
{
|
{
|
||||||
Locator* layerLocator = _volumeTile->getLayer()->getLocator();
|
Locator* layerLocator = _volumeTile->getLayer()->getLocator();
|
||||||
|
@ -49,6 +49,10 @@ class RTTCameraCullCallback : public osg::NodeCallback
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// VolumeScene::ViewData
|
||||||
|
//
|
||||||
VolumeScene::ViewData::ViewData()
|
VolumeScene::ViewData::ViewData()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -67,6 +71,10 @@ void VolumeScene::ViewData::visitTile(VolumeTile* tile)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
////////////////////////////////////////////////////////////////////////
|
||||||
|
//
|
||||||
|
// VolumeScene
|
||||||
|
//
|
||||||
VolumeScene::VolumeScene()
|
VolumeScene::VolumeScene()
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -81,7 +89,7 @@ VolumeScene::~VolumeScene()
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
VolumeScene::TileData* VolumeScene::tileVisited(osgUtil::CullVisitor* cv, osgVolume::VolumeTile* tile)
|
TileData* VolumeScene::tileVisited(osgUtil::CullVisitor* cv, osgVolume::VolumeTile* tile)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<ViewData> viewData;
|
osg::ref_ptr<ViewData> viewData;
|
||||||
|
|
||||||
@ -95,73 +103,15 @@ VolumeScene::TileData* VolumeScene::tileVisited(osgUtil::CullVisitor* cv, osgVol
|
|||||||
|
|
||||||
if (viewData.valid())
|
if (viewData.valid())
|
||||||
{
|
{
|
||||||
int textureWidth = 512;
|
|
||||||
int textureHeight = 512;
|
|
||||||
|
|
||||||
osg::Viewport* viewport = cv->getCurrentRenderStage()->getViewport();
|
|
||||||
if (viewport)
|
|
||||||
{
|
|
||||||
textureWidth = static_cast<int>(viewport->width());
|
|
||||||
textureHeight = static_cast<int>(viewport->height());
|
|
||||||
}
|
|
||||||
|
|
||||||
osg::ref_ptr<TileData>& tileData = viewData->_tiles[tile];
|
osg::ref_ptr<TileData>& tileData = viewData->_tiles[tile];
|
||||||
if (!tileData)
|
if (!tileData)
|
||||||
{
|
{
|
||||||
tileData = new TileData;
|
tileData = tile->getVolumeTechnique() ? tile->getVolumeTechnique()->createTileData(cv) : 0;
|
||||||
|
|
||||||
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->setName("tileData->rttCamera");
|
|
||||||
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(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE);
|
|
||||||
|
|
||||||
tileData->texgenUniform = new osg::Uniform("texgen",osg::Matrixf());
|
|
||||||
tileData->stateset->addUniform(tileData->texgenUniform.get());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
tileData->active = true;
|
if (tileData)
|
||||||
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)
|
tileData->update(cv);
|
||||||
{
|
|
||||||
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 tileData.get();
|
||||||
@ -169,7 +119,7 @@ VolumeScene::TileData* VolumeScene::tileVisited(osgUtil::CullVisitor* cv, osgVol
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
VolumeScene::TileData* VolumeScene::getTileData(osgUtil::CullVisitor* cv, osgVolume::VolumeTile* tile)
|
TileData* VolumeScene::getTileData(osgUtil::CullVisitor* cv, osgVolume::VolumeTile* tile)
|
||||||
{
|
{
|
||||||
osg::ref_ptr<ViewData> viewData;
|
osg::ref_ptr<ViewData> viewData;
|
||||||
{
|
{
|
||||||
@ -479,7 +429,7 @@ void VolumeScene::traverse(osg::NodeVisitor& nv)
|
|||||||
|
|
||||||
osg::NodePath::iterator np_itr = nodePath.begin();
|
osg::NodePath::iterator np_itr = nodePath.begin();
|
||||||
|
|
||||||
// skip over all nodes above VolumeScene as this will have already been traverse by CullVisitor
|
// skip over all nodes above VolumeScene as this will have already been traversed by CullVisitor
|
||||||
while(np_itr!=nodePath.end() && (*np_itr)!=viewData->_rttCamera.get()) { ++np_itr; }
|
while(np_itr!=nodePath.end() && (*np_itr)!=viewData->_rttCamera.get()) { ++np_itr; }
|
||||||
if (np_itr!=nodePath.end()) ++np_itr;
|
if (np_itr!=nodePath.end()) ++np_itr;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user