From 27b71e3927080981fcb4fa4d9fa8e2d0c15d0be4 Mon Sep 17 00:00:00 2001 From: Robert Osfield Date: Thu, 27 Mar 2014 12:47:44 +0000 Subject: [PATCH] Added cube and hull rendering support --- include/osgVolume/MultipassTechnique | 63 +-- include/osgVolume/VolumeTechnique | 2 +- src/osgVolume/MultipassTechnique.cpp | 367 ++++++++++++++---- src/osgVolume/Property.cpp | 4 +- .../volume_accumulateSamples_iso_frag.cpp | 2 +- .../volume_accumulateSamples_iso_tf_frag.cpp | 2 +- .../volume_accumulateSamples_lit_frag.cpp | 3 +- .../volume_accumulateSamples_lit_tf_frag.cpp | 3 +- .../volume_accumulateSamples_mip_frag.cpp | 3 +- .../volume_accumulateSamples_mip_tf_frag.cpp | 3 +- ...volume_accumulateSamples_standard_frag.cpp | 3 +- ...ume_accumulateSamples_standard_tf_frag.cpp | 4 +- .../Shaders/volume_compute_ray_color_frag.cpp | 12 +- .../volume_multipass_cube_and_hull_frag.cpp | 119 ++++++ .../Shaders/volume_multipass_cube_frag.cpp | 87 +++++ .../Shaders/volume_multipass_frag.cpp | 12 +- .../Shaders/volume_multipass_hull_frag.cpp | 94 +++++ src/osgVolume/VolumeScene.cpp | 2 +- 18 files changed, 650 insertions(+), 135 deletions(-) create mode 100644 src/osgVolume/Shaders/volume_multipass_cube_and_hull_frag.cpp create mode 100644 src/osgVolume/Shaders/volume_multipass_cube_frag.cpp create mode 100644 src/osgVolume/Shaders/volume_multipass_hull_frag.cpp diff --git a/include/osgVolume/MultipassTechnique b/include/osgVolume/MultipassTechnique index 0b383265c..8c0ee367e 100644 --- a/include/osgVolume/MultipassTechnique +++ b/include/osgVolume/MultipassTechnique @@ -19,22 +19,6 @@ 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 frontFaceDepthTexture; - osg::ref_ptr frontFaceRttCamera; - - osg::ref_ptr backFaceDepthTexture; - osg::ref_ptr backFaceRttCamera; - - osg::ref_ptr texgenUniform; -}; class OSGVOLUME_EXPORT MultipassTechnique : public VolumeTechnique @@ -61,9 +45,40 @@ class OSGVOLUME_EXPORT MultipassTechnique : public VolumeTechnique /** Traverse the terrain subgraph.*/ virtual void traverse(osg::NodeVisitor& nv); + enum RenderingMode + { + CUBE, + HULL, + CUBE_AND_HULL + }; + + RenderingMode computeRenderingMode(); + + /** Container for render to texture objects used when doing multi-pass volume rendering techniques.*/ + struct OSGVOLUME_EXPORT MultipassTileData : public TileData + { + MultipassTileData(osgUtil::CullVisitor* cv, MultipassTechnique* mpt); + + virtual void update(osgUtil::CullVisitor* cv); + + void setUp(osg::ref_ptr& camera, osg::ref_ptr& texture2D, int width, int height); + + + osg::observer_ptr multipassTechnique; + RenderingMode currentRenderingMode; + + osg::ref_ptr frontFaceDepthTexture; + osg::ref_ptr frontFaceRttCamera; + + osg::ref_ptr backFaceDepthTexture; + osg::ref_ptr backFaceRttCamera; + + osg::ref_ptr texgenUniform; + }; + /** 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); } + virtual TileData* createTileData(osgUtil::CullVisitor* cv) { return new MultipassTileData(cv, this); } protected: @@ -83,12 +98,14 @@ class OSGVOLUME_EXPORT MultipassTechnique : public VolumeTechnique enum ShaderMask { - BACK_SHADERS = 1, - STANDARD_SHADERS = 2, - LIT_SHADERS = 4, - ISO_SHADERS = 8, - MIP_SHADERS = 16, - TF_SHADERS = 32 + CUBE_SHADERS = 1, + HULL_SHADERS = 2, + CUBE_AND_HULL_SHADERS = 4, + STANDARD_SHADERS = 8, + LIT_SHADERS = 16, + ISO_SHADERS = 32, + MIP_SHADERS = 64, + TF_SHADERS = 128 }; typedef std::map > StateSetMap; diff --git a/include/osgVolume/VolumeTechnique b/include/osgVolume/VolumeTechnique index 79639eaf3..906604ef9 100644 --- a/include/osgVolume/VolumeTechnique +++ b/include/osgVolume/VolumeTechnique @@ -72,7 +72,7 @@ class OSGVOLUME_EXPORT VolumeTechnique : public osg::Object /** 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; } + virtual TileData* createTileData(osgUtil::CullVisitor* /*cv*/) { return 0; } protected: diff --git a/src/osgVolume/MultipassTechnique.cpp b/src/osgVolume/MultipassTechnique.cpp index 738c3a415..db0d92556 100644 --- a/src/osgVolume/MultipassTechnique.cpp +++ b/src/osgVolume/MultipassTechnique.cpp @@ -151,9 +151,42 @@ osg::Image* createDownsampledImage(osg::Image* sourceImage) // // MultipassTileData // -MultipassTileData::MultipassTileData(osgUtil::CullVisitor* cv): - TileData() + +class RTTCameraCullCallback : public osg::NodeCallback { + public: + + RTTCameraCullCallback(MultipassTechnique::MultipassTileData* tileData, MultipassTechnique* mt): + _tileData(tileData), + _mt(mt) {} + + virtual void operator()(osg::Node* node, osg::NodeVisitor* nv) + { + osgUtil::CullVisitor* cv = dynamic_cast(nv); + + cv->pushProjectionMatrix(_tileData->projectionMatrix.get()); + + // OSG_NOTICE<<"Traversing tile subgraph for pre-render "<<_mt->getVolumeTile()->getNumChildren()<getVolumeTile()->osg::Group::traverse(*cv); + + cv->popProjectionMatrix(); + } + + protected: + + virtual ~RTTCameraCullCallback() {} + + osg::observer_ptr _tileData; + osg::observer_ptr _mt; +}; + +MultipassTechnique::MultipassTileData::MultipassTileData(osgUtil::CullVisitor* cv, MultipassTechnique* mpt): + TileData(), + multipassTechnique(mpt) +{ + currentRenderingMode = mpt->computeRenderingMode(); + int width = 512; int height = 512; @@ -164,9 +197,60 @@ MultipassTileData::MultipassTileData(osgUtil::CullVisitor* cv): height = static_cast(viewport->height()); } - osg::ref_ptr depthTexture = new osg::Texture2D; - frontFaceDepthTexture = depthTexture; + stateset = new osg::StateSet; + switch(currentRenderingMode) + { + case(MultipassTechnique::CUBE): + { + // no need to set up RTT Cameras; + OSG_NOTICE<<"Setting up MultipassTileData for CUBE rendering"<addUniform(texgenUniform.get()); + break; + } + case(MultipassTechnique::HULL): + { + OSG_NOTICE<<"Setting up MultipassTileData for HULL rendering"<setName("frontFaceRttCamera"); + frontFaceRttCamera->setCullCallback(new RTTCameraCullCallback(this, mpt)); + frontFaceRttCamera->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); + + texgenUniform = new osg::Uniform("texgen",osg::Matrixf()); + + stateset->setTextureAttribute(2, frontFaceDepthTexture.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); + stateset->addUniform(texgenUniform.get()); + break; + } + case(MultipassTechnique::CUBE_AND_HULL): + { + OSG_NOTICE<<"Setting up MultipassTileData for CUBE_AND_HULL rendering"<setName("frontFaceRttCamera"); + frontFaceRttCamera->setCullCallback(new RTTCameraCullCallback(this, mpt)); + frontFaceRttCamera->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::BACK), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); + + setUp(backFaceRttCamera, backFaceDepthTexture, width, height); + backFaceRttCamera->setName("backFaceRttCamera"); + backFaceRttCamera->setCullCallback(new RTTCameraCullCallback(this, mpt)); + backFaceRttCamera->getOrCreateStateSet()->setAttributeAndModes(new osg::CullFace(osg::CullFace::FRONT), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); + + texgenUniform = new osg::Uniform("texgen",osg::Matrixf()); + + stateset->setTextureAttribute(2, frontFaceDepthTexture.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); + stateset->setTextureAttribute(3, backFaceDepthTexture.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); + stateset->addUniform(texgenUniform.get()); + break; + } + } + +} + +void MultipassTechnique::MultipassTileData::setUp(osg::ref_ptr& camera, osg::ref_ptr& depthTexture, int width, int height) +{ + depthTexture = new osg::Texture2D; depthTexture->setTextureSize(width, height); depthTexture->setInternalFormat(GL_DEPTH_COMPONENT); depthTexture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR); @@ -175,9 +259,7 @@ MultipassTileData::MultipassTileData(osgUtil::CullVisitor* cv): 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 camera = new osg::Camera; - frontFaceRttCamera = camera; - frontFaceRttCamera->setName("frontFaceRttCamera"); + camera = new osg::Camera; camera->attach(osg::Camera::DEPTH_BUFFER, depthTexture.get()); camera->setViewport(0, 0, width, height); @@ -193,17 +275,15 @@ MultipassTileData::MultipassTileData(osgUtil::CullVisitor* cv): 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) +void MultipassTechnique::MultipassTileData::update(osgUtil::CullVisitor* cv) { + if (currentRenderingMode != multipassTechnique->computeRenderingMode()) + { + OSG_NOTICE<<"Warning: need to re-structure MP setup."<getNodePath(); projectionMatrix = cv->getProjectionMatrix(); @@ -232,6 +312,20 @@ void MultipassTileData::update(osgUtil::CullVisitor* cv) } } } + + if (backFaceDepthTexture.valid()) + { + if (backFaceDepthTexture->getTextureWidth()!=width || backFaceDepthTexture->getTextureHeight()!=height) + { + OSG_NOTICE<<"Need to change texture size to "<setTextureSize(width, height); + backFaceRttCamera->setViewport(0, 0, width, height); + if (backFaceRttCamera->getRenderingCache()) + { + backFaceRttCamera->getRenderingCache()->releaseGLObjects(0); + } + } + } } ///////////////////////////////////////////////////////////////////////////////////////// @@ -262,6 +356,38 @@ osg::StateSet* MultipassTechnique::createStateSet(osg::StateSet* statesetPrototy return stateset.release(); } +MultipassTechnique::RenderingMode MultipassTechnique::computeRenderingMode() +{ + bool hasHull = (_volumeTile->getNumChildren()>0); + + if (!hasHull) + { + return CUBE; + } + + CollectPropertiesVisitor cpv(false); + if (_volumeTile->getLayer()->getProperty()) + { + _volumeTile->getLayer()->getProperty()->accept(cpv); + } + + double etfValue = cpv._exteriorTransparencyFactorProperty.valid() ? cpv._exteriorTransparencyFactorProperty->getValue() : 0.0; + + if (etfValue<=0.0) + { + return HULL; + } + else if (etfValue<1.0) + { + return CUBE_AND_HULL; + } + else + { + return CUBE; + } +} + + void MultipassTechnique::init() { OSG_INFO<<"MultipassTechnique::init()"< stateset = new osg::StateSet; _volumeRenderStateSet = stateset; - unsigned int volumeTextureUnit = 3; - - bool requiresRenderingOfCubeAndHull = cpv._exteriorTransparencyFactorProperty.valid() && cpv._exteriorTransparencyFactorProperty->getValue()!=0.0f; - if (requiresRenderingOfCubeAndHull) - { - OSG_NOTICE<<"******* We need to set up the rendering of the Cube and Hull, ETF = "<getValue()<addUniform(new osg::Uniform("depthTexture",1)); - stateset->addUniform(new osg::Uniform("frontFaceDepthTexture",2)); stateset->setMode(GL_ALPHA_TEST,osg::StateAttribute::ON); //stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF); @@ -536,8 +656,6 @@ void MultipassTechnique::init() tf_texture->setFilter(osg::Texture::MAG_FILTER, osg::Texture::LINEAR); tf_texture->setWrap(osg::Texture::WRAP_R,osg::Texture::CLAMP_TO_EDGE); - unsigned int transferFunctionTextureUnit = volumeTextureUnit+1; - 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("tfOffset",tfOffset)); @@ -549,8 +667,6 @@ void MultipassTechnique::init() osg::ref_ptr front_CullFace = new osg::CullFace(osg::CullFace::BACK); osg::ref_ptr back_CullFace = new osg::CullFace(osg::CullFace::FRONT); - - osg::ref_ptr main_vertexShader = osgDB::readRefShaderFile(osg::Shader::VERTEX, "shaders/volume_multipass.vert"); if (!main_vertexShader) { @@ -559,12 +675,6 @@ void MultipassTechnique::init() } - osg::ref_ptr back_main_fragmentShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_multipass.frag");; - if (!back_main_fragmentShader) - { - #include "Shaders/volume_multipass_frag.cpp" - back_main_fragmentShader = new osg::Shader(osg::Shader::FRAGMENT, volume_multipass_frag); - } osg::ref_ptr computeRayColorShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_compute_ray_color.frag"); if (!computeRayColorShader) @@ -576,17 +686,63 @@ void MultipassTechnique::init() // clear any previous settings _stateSetMap.clear(); - osg::ref_ptr back_stateset_prototype = new osg::StateSet; - osg::ref_ptr back_program_prototype = new osg::Program; - { - back_stateset_prototype->setAttributeAndModes(back_CullFace.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); - back_program_prototype->addShader(main_vertexShader.get()); - back_program_prototype->addShader(back_main_fragmentShader.get()); - back_program_prototype->addShader(computeRayColorShader.get()); + // set up the program template for rendering just the cube + osg::ref_ptr cube_main_fragmentShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_multipass_cube.frag");; + if (!cube_main_fragmentShader) + { + #include "Shaders/volume_multipass_cube_frag.cpp" + cube_main_fragmentShader = new osg::Shader(osg::Shader::FRAGMENT, volume_multipass_cube_frag); + } + osg::ref_ptr cube_stateset_prototype = new osg::StateSet; + osg::ref_ptr cube_program_prototype = new osg::Program; + { + cube_stateset_prototype->setAttributeAndModes(back_CullFace.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); + + cube_program_prototype->addShader(main_vertexShader.get()); + cube_program_prototype->addShader(cube_main_fragmentShader.get()); + cube_program_prototype->addShader(computeRayColorShader.get()); } + // set up the program template for rendering just the hull + osg::ref_ptr hull_main_fragmentShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_multipass_hull.frag");; + if (!hull_main_fragmentShader) + { + #include "Shaders/volume_multipass_hull_frag.cpp" + hull_main_fragmentShader = new osg::Shader(osg::Shader::FRAGMENT, volume_multipass_hull_frag); + } + osg::ref_ptr hull_stateset_prototype = new osg::StateSet; + osg::ref_ptr hull_program_prototype = new osg::Program; + { + hull_stateset_prototype->setAttributeAndModes(back_CullFace.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); + hull_stateset_prototype->addUniform(new osg::Uniform("frontFaceDepthTexture",2)); + + hull_program_prototype->addShader(main_vertexShader.get()); + hull_program_prototype->addShader(hull_main_fragmentShader.get()); + hull_program_prototype->addShader(computeRayColorShader.get()); + } + + + // set up the program template for rendering just the cube + osg::ref_ptr cube_and_hull_main_fragmentShader = osgDB::readRefShaderFile(osg::Shader::FRAGMENT, "shaders/volume_multipass_cube_and_hull.frag");; + if (!cube_and_hull_main_fragmentShader) + { + #include "Shaders/volume_multipass_cube_and_hull_frag.cpp" + cube_and_hull_main_fragmentShader = new osg::Shader(osg::Shader::FRAGMENT, volume_multipass_cube_and_hull_frag); + } + osg::ref_ptr cube_and_hull_stateset_prototype = new osg::StateSet; + osg::ref_ptr cube_and_hull_program_prototype = new osg::Program; + { + cube_and_hull_stateset_prototype->setAttributeAndModes(back_CullFace.get(), osg::StateAttribute::ON|osg::StateAttribute::OVERRIDE); + cube_and_hull_stateset_prototype->addUniform(new osg::Uniform("frontFaceDepthTexture",2)); + cube_and_hull_stateset_prototype->addUniform(new osg::Uniform("backFaceDepthTexture",3)); + + cube_and_hull_program_prototype->addShader(main_vertexShader.get()); + cube_and_hull_program_prototype->addShader(cube_and_hull_main_fragmentShader.get()); + cube_and_hull_program_prototype->addShader(computeRayColorShader.get()); + } + // set up the rendering of the front face { _frontFaceStateSet = new osg::StateSet; @@ -612,8 +768,9 @@ void MultipassTechnique::init() accumulateSamplesShader = new osg::Shader(osg::Shader::FRAGMENT, volume_accumulateSamples_standard_frag); } - // back - _stateSetMap[STANDARD_SHADERS|BACK_SHADERS] = createStateSet(back_stateset_prototype.get(), back_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[STANDARD_SHADERS|CUBE_SHADERS] = createStateSet(cube_stateset_prototype.get(), cube_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[STANDARD_SHADERS|HULL_SHADERS] = createStateSet(hull_stateset_prototype.get(), hull_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[STANDARD_SHADERS|CUBE_AND_HULL_SHADERS] = createStateSet(cube_and_hull_stateset_prototype.get(), cube_and_hull_program_prototype.get(), accumulateSamplesShader.get()); } // STANDARD_SHADERS with TransferFunction @@ -626,8 +783,9 @@ void MultipassTechnique::init() accumulateSamplesShader = new osg::Shader(osg::Shader::FRAGMENT, volume_accumulateSamples_standard_tf_frag); } - // back - _stateSetMap[STANDARD_SHADERS|BACK_SHADERS|TF_SHADERS] = createStateSet(back_stateset_prototype.get(), back_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[STANDARD_SHADERS|CUBE_SHADERS|TF_SHADERS] = createStateSet(cube_stateset_prototype.get(), cube_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[STANDARD_SHADERS|HULL_SHADERS|TF_SHADERS] = createStateSet(hull_stateset_prototype.get(), hull_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[STANDARD_SHADERS|CUBE_AND_HULL_SHADERS|TF_SHADERS] = createStateSet(cube_and_hull_stateset_prototype.get(), cube_and_hull_program_prototype.get(), accumulateSamplesShader.get()); } } @@ -643,8 +801,9 @@ void MultipassTechnique::init() accumulateSamplesShader = new osg::Shader(osg::Shader::FRAGMENT, volume_accumulateSamples_iso_frag); } - // back - _stateSetMap[ISO_SHADERS|BACK_SHADERS] = createStateSet(back_stateset_prototype.get(), back_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[ISO_SHADERS|CUBE_SHADERS] = createStateSet(cube_stateset_prototype.get(), cube_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[ISO_SHADERS|HULL_SHADERS] = createStateSet(hull_stateset_prototype.get(), hull_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[ISO_SHADERS|CUBE_AND_HULL_SHADERS] = createStateSet(cube_and_hull_stateset_prototype.get(), cube_and_hull_program_prototype.get(), accumulateSamplesShader.get()); } // ISO_SHADERS with TransferFunction @@ -657,8 +816,9 @@ void MultipassTechnique::init() accumulateSamplesShader = new osg::Shader(osg::Shader::FRAGMENT, volume_accumulateSamples_iso_tf_frag); } - // back - _stateSetMap[ISO_SHADERS|BACK_SHADERS|TF_SHADERS] = createStateSet(back_stateset_prototype.get(), back_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[ISO_SHADERS|CUBE_SHADERS|TF_SHADERS] = createStateSet(cube_stateset_prototype.get(), cube_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[ISO_SHADERS|HULL_SHADERS|TF_SHADERS] = createStateSet(hull_stateset_prototype.get(), hull_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[ISO_SHADERS|CUBE_AND_HULL_SHADERS|TF_SHADERS] = createStateSet(cube_and_hull_stateset_prototype.get(), cube_and_hull_program_prototype.get(), accumulateSamplesShader.get()); } } @@ -674,8 +834,9 @@ void MultipassTechnique::init() accumulateSamplesShader = new osg::Shader(osg::Shader::FRAGMENT, volume_accumulateSamples_mip_frag); } - // back - _stateSetMap[MIP_SHADERS|BACK_SHADERS] = createStateSet(back_stateset_prototype.get(), back_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[MIP_SHADERS|CUBE_SHADERS] = createStateSet(cube_stateset_prototype.get(), cube_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[MIP_SHADERS|HULL_SHADERS] = createStateSet(hull_stateset_prototype.get(), hull_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[MIP_SHADERS|CUBE_AND_HULL_SHADERS] = createStateSet(cube_and_hull_stateset_prototype.get(), cube_and_hull_program_prototype.get(), accumulateSamplesShader.get()); } // MIP_SHADERS with TransferFunction @@ -688,8 +849,9 @@ void MultipassTechnique::init() accumulateSamplesShader = new osg::Shader(osg::Shader::FRAGMENT, volume_accumulateSamples_mip_tf_frag); } - // back - _stateSetMap[MIP_SHADERS|BACK_SHADERS|TF_SHADERS] = createStateSet(back_stateset_prototype.get(), back_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[MIP_SHADERS|CUBE_SHADERS|TF_SHADERS] = createStateSet(cube_stateset_prototype.get(), cube_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[MIP_SHADERS|HULL_SHADERS|TF_SHADERS] = createStateSet(hull_stateset_prototype.get(), hull_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[MIP_SHADERS|CUBE_AND_HULL_SHADERS|TF_SHADERS] = createStateSet(cube_and_hull_stateset_prototype.get(), cube_and_hull_program_prototype.get(), accumulateSamplesShader.get()); } } @@ -705,8 +867,9 @@ void MultipassTechnique::init() accumulateSamplesShader = new osg::Shader(osg::Shader::FRAGMENT, volume_accumulateSamples_lit_frag); } - // back - _stateSetMap[LIT_SHADERS|BACK_SHADERS] = createStateSet(back_stateset_prototype.get(), back_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[LIT_SHADERS|CUBE_SHADERS] = createStateSet(cube_stateset_prototype.get(), cube_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[LIT_SHADERS|HULL_SHADERS] = createStateSet(hull_stateset_prototype.get(), hull_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[LIT_SHADERS|CUBE_AND_HULL_SHADERS] = createStateSet(cube_and_hull_stateset_prototype.get(), cube_and_hull_program_prototype.get(), accumulateSamplesShader.get()); } // MIP_SHADERS with TransferFunction @@ -719,8 +882,9 @@ void MultipassTechnique::init() accumulateSamplesShader = new osg::Shader(osg::Shader::FRAGMENT, volume_accumulateSamples_lit_tf_frag); } - // back - _stateSetMap[LIT_SHADERS|BACK_SHADERS|TF_SHADERS] = createStateSet(back_stateset_prototype.get(), back_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[LIT_SHADERS|CUBE_SHADERS|TF_SHADERS] = createStateSet(cube_stateset_prototype.get(), cube_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[LIT_SHADERS|HULL_SHADERS|TF_SHADERS] = createStateSet(hull_stateset_prototype.get(), hull_program_prototype.get(), accumulateSamplesShader.get()); + _stateSetMap[LIT_SHADERS|CUBE_AND_HULL_SHADERS|TF_SHADERS] = createStateSet(cube_and_hull_stateset_prototype.get(), cube_and_hull_program_prototype.get(), accumulateSamplesShader.get()); } } @@ -768,7 +932,7 @@ class RTTBackfaceCameraCullCallback : public osg::NodeCallback { public: - RTTBackfaceCameraCullCallback(MultipassTileData* tileData, MultipassTechnique* mt): + RTTBackfaceCameraCullCallback(MultipassTechnique::MultipassTileData* tileData, MultipassTechnique* mt): _tileData(tileData), _mt(mt) {} @@ -787,7 +951,7 @@ class RTTBackfaceCameraCullCallback : public osg::NodeCallback virtual ~RTTBackfaceCameraCullCallback() {} - osg::observer_ptr _tileData; + osg::observer_ptr _tileData; osg::observer_ptr _mt; }; @@ -806,20 +970,42 @@ void MultipassTechnique::cull(osgUtil::CullVisitor* cv) vs = dynamic_cast(*itr); } + RenderingMode renderingMode = computeRenderingMode(); + if (rttTraversal) { if (vs) { MultipassTileData* tileData = dynamic_cast(vs->tileVisited(cv, getVolumeTile())); - if (tileData && tileData->frontFaceRttCamera.valid()) + if (tileData) { - if (!(tileData->frontFaceRttCamera->getCullCallback())) + switch(renderingMode) { - tileData->frontFaceRttCamera->setCullCallback(new RTTBackfaceCameraCullCallback(tileData, this)); + case(CUBE): + { + // no work required to pre-render + break; + } + case(HULL): + { + if (tileData->frontFaceRttCamera.valid()) tileData->frontFaceRttCamera->accept(*cv); + break; + } + case(CUBE_AND_HULL): + { + // OSG_NOTICE<<"Doing pre-rendering"<frontFaceRttCamera.valid()) + { + // OSG_NOTICE<<" frontFaceRttCamera"<frontFaceRttCamera->accept(*cv); + } + if (tileData->backFaceRttCamera.valid()) + { + // OSG_NOTICE<<" backFaceRttCamera"<backFaceRttCamera->accept(*cv); + } + } } - - // traverse RTT Camera - tileData->frontFaceRttCamera->accept(*cv); } osg::BoundingBox bb; @@ -860,25 +1046,28 @@ void MultipassTechnique::cull(osgUtil::CullVisitor* cv) } } - int shaderMaskBack = shaderMask | BACK_SHADERS; - - // OSG_NOTICE<<"shaderMaskBack "<(vs->getTileData(cv, getVolumeTile())); - if (tileData) + if (tileData && tileData->texgenUniform.valid()) { 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_NOTICE<<"Updating texgen"< back_stateset = _stateSetMap[shaderMaskBack]; osg::ref_ptr moving_stateset = (_whenMovingStateSet.valid() && isMoving(cv)) ? _whenMovingStateSet : 0; if (moving_stateset.valid()) @@ -887,24 +1076,38 @@ void MultipassTechnique::cull(osgUtil::CullVisitor* cv) cv->pushStateSet(moving_stateset.get()); } - if (back_stateset.valid()) + osg::ref_ptr program_stateset = _stateSetMap[shaderMask]; + if (program_stateset.valid()) { - // OSG_NOTICE<<"Have back stateset"<pushStateSet(back_stateset.get()); + // OSG_NOTICE<<"Have program_stateset OK."<pushStateSet(program_stateset.get()); cv->pushStateSet(_volumeRenderStateSet.get()); - if (getVolumeTile()->getNumChildren()>0) + switch(renderingMode) { - getVolumeTile()->osg::Group::traverse(*cv); - } - else - { - _transform->accept(*cv); + case(CUBE): + // OSG_NOTICE<<"Travering Transform for CUBE rendering"<accept(*cv); + break; + case(HULL): + // OSG_NOTICE<<"Travering children for HULL rendering"<osg::Group::traverse(*cv); + break; + case(CUBE_AND_HULL): + // OSG_NOTICE<<"Travering Transform for CUBE_AND_HULL rendering"<accept(*cv); + //getVolumeTile()->osg::Group::traverse(*cv); + break; } cv->popStateSet(); cv->popStateSet(); } + else + { + OSG_NOTICE<<"Warning: No program available for required shader mask "<0)\n" " {\n" diff --git a/src/osgVolume/Shaders/volume_accumulateSamples_mip_tf_frag.cpp b/src/osgVolume/Shaders/volume_accumulateSamples_mip_tf_frag.cpp index 9f092a33a..3ed490820 100644 --- a/src/osgVolume/Shaders/volume_accumulateSamples_mip_tf_frag.cpp +++ b/src/osgVolume/Shaders/volume_accumulateSamples_mip_tf_frag.cpp @@ -6,10 +6,9 @@ char volume_accumulateSamples_mip_tf_frag[] = "#version 110\n" "uniform float tfScale;\n" "uniform float tfOffset;\n" "\n" - "vec4 accumulateSamples(vec3 ts, vec3 te, vec3 dt, float scale, float cutoff, int num_iterations)\n" + "vec4 accumulateSamples(vec4 fragColor, vec3 ts, vec3 te, vec3 dt, float scale, float cutoff, int num_iterations)\n" "{\n" " vec3 texcoord = te.xyz;\n" - " vec4 fragColor = vec4(0.0, 0.0, 0.0, 0.0);\n" "\n" " float max_a = 0.0;\n" " while(num_iterations>0)\n" diff --git a/src/osgVolume/Shaders/volume_accumulateSamples_standard_frag.cpp b/src/osgVolume/Shaders/volume_accumulateSamples_standard_frag.cpp index ab448e23c..9885617d0 100644 --- a/src/osgVolume/Shaders/volume_accumulateSamples_standard_frag.cpp +++ b/src/osgVolume/Shaders/volume_accumulateSamples_standard_frag.cpp @@ -4,10 +4,9 @@ char volume_accumulateSamples_standard_frag[] = "#version 110\n" "\n" "uniform float AlphaFuncValue;\n" "\n" - "vec4 accumulateSamples(vec3 ts, vec3 te, vec3 dt, float scale, float cutoff, int num_iterations)\n" + "vec4 accumulateSamples(vec4 fragColor, vec3 ts, vec3 te, vec3 dt, float scale, float cutoff, int num_iterations)\n" "{\n" " vec3 texcoord = te.xyz;\n" - " vec4 fragColor = vec4(0.0, 0.0, 0.0, 0.0);\n" "\n" " while(num_iterations>0 && fragColor.a0 && fragColor.a0) fragColor.a = 1.0;\n" + " if (fragColor.a>1.0) fragColor.a = 1.0;\n" "\n" " return fragColor;\n" "}\n" diff --git a/src/osgVolume/Shaders/volume_compute_ray_color_frag.cpp b/src/osgVolume/Shaders/volume_compute_ray_color_frag.cpp index 5c102a4db..b463e8b3f 100644 --- a/src/osgVolume/Shaders/volume_compute_ray_color_frag.cpp +++ b/src/osgVolume/Shaders/volume_compute_ray_color_frag.cpp @@ -9,9 +9,9 @@ char volume_compute_ray_color_frag[] = "#version 110\n" "varying mat4 texgen_withProjectionMatrixInverse;\n" "\n" "// forward declare, probided by volume_accumulateSamples*.frag shaders\n" - "vec4 accumulateSamples(vec3 ts, vec3 te, vec3 dt, float scale, float cutoff, int num_iterations);\n" + "vec4 accumulateSamples(vec4 fragColor, vec3 ts, vec3 te, vec3 dt, float scale, float cutoff, int num_iterations);\n" "\n" - "vec4 accumulateSegment(vec3 ts, vec3 te)\n" + "vec4 accumulateSegment(vec4 fragColor, vec3 ts, vec3 te)\n" "{\n" " const int max_iterations = 8192;\n" "\n" @@ -45,9 +45,7 @@ char volume_compute_ray_color_frag[] = "#version 110\n" "\n" " float cutoff = 1.0-1.0/256.0;\n" "\n" - " vec4 fragColor;\n" - "\n" - " fragColor = accumulateSamples(ts, te, deltaTexCoord, scale, cutoff, num_iterations);\n" + " fragColor = accumulateSamples(fragColor, ts, te, deltaTexCoord, scale, cutoff, num_iterations);\n" "\n" " fragColor *= baseColor;\n" "\n" @@ -105,7 +103,7 @@ char volume_compute_ray_color_frag[] = "#version 110\n" "}\n" "\n" "\n" - "vec4 computeRayColor(float px, float py, float depth_start, float depth_end)\n" + "vec4 computeRayColor(vec4 fragColor, float px, float py, float depth_start, float depth_end)\n" "{\n" " float viewportWidth = viewportDimensions[2];\n" " float viewportHeight = viewportDimensions[3];\n" @@ -129,6 +127,6 @@ char volume_compute_ray_color_frag[] = "#version 110\n" " vec3 clamped_start_texcoord = clampToUnitCube(end_texcoord.xyz, start_texcoord.xyz);\n" " vec3 clamped_end_texcoord = clampToUnitCube(start_texcoord.xyz, end_texcoord.xyz);\n" "\n" - " return accumulateSegment(clamped_start_texcoord, clamped_end_texcoord);\n" + " return accumulateSegment(fragColor, clamped_start_texcoord, clamped_end_texcoord);\n" "}\n" "\n"; diff --git a/src/osgVolume/Shaders/volume_multipass_cube_and_hull_frag.cpp b/src/osgVolume/Shaders/volume_multipass_cube_and_hull_frag.cpp new file mode 100644 index 000000000..e9882dcc2 --- /dev/null +++ b/src/osgVolume/Shaders/volume_multipass_cube_and_hull_frag.cpp @@ -0,0 +1,119 @@ +char volume_multipass_cube_and_hull_frag[] = "#version 110\n" + "\n" + "uniform sampler2D colorTexture;\n" + "uniform sampler2D depthTexture;\n" + "uniform sampler2D backFaceDepthTexture;\n" + "uniform sampler2D frontFaceDepthTexture;\n" + "uniform vec4 viewportDimensions;\n" + "uniform float ExteriorTransparencyFactorValue;\n" + "\n" + "\n" + "// declare function defined in volume_compute_ray_color.frag\n" + "vec4 computeRayColor(vec4 fragColor, float px, float py, float depth_start, float depth_end);\n" + "\n" + "vec4 computeSegment(vec4 fragColor, float px, float py, float depth_start, float depth_end, float transparencyFactor, vec4 scene_color, float scene_depth)\n" + "{\n" + "#if 1\n" + " //return mix(fragColor, computeRayColor(fragColor, px, py, depth_start, depth_end), transparencyFactor);\n" + " if ((depth_end=1.0) return fragColor;\n" + "\n" + " // compute rear segement color and blend with accumulated_color\n" + " return mix( fragColor, computeRayColor(fragColor, px, py, depth_start, scene_depth), transparencyFactor);\n" + " }\n" + " else\n" + " {\n" + " return mix( fragColor, computeRayColor(fragColor, px, py, depth_start, depth_end), transparencyFactor);\n" + " }\n" + "#else\n" + " if ((depth_end=1.0) return fragColor;\n" + "\n" + " // compute rear segement color and blend with accumulated_color\n" + " return computeRayColor(fragColor, px, py, depth_start, scene_depth) * transparencyFactor;\n" + " }\n" + " else\n" + " {\n" + " return computeRayColor(fragColor, px, py, depth_start, depth_end) * transparencyFactor;\n" + " }\n" + "#endif\n" + "}\n" + "\n" + "void main(void)\n" + "{\n" + " vec2 texcoord = vec2((gl_FragCoord.x-viewportDimensions[0])/viewportDimensions[2], (gl_FragCoord.y-viewportDimensions[1])/viewportDimensions[3]);\n" + " vec4 color = texture2D( colorTexture, texcoord);\n" + " float texture_depth = texture2D( depthTexture, texcoord).s;\n" + " float back_depth = texture2D( backFaceDepthTexture, texcoord).s;\n" + " float front_depth = texture2D( frontFaceDepthTexture, texcoord).s;\n" + "\n" + " //float ExteriorTransparencyFactorValue = 1.0;\n" + " vec4 fragColor = vec4(0.0, 0.0, 0.0, 0.0);\n" + "\n" + " // make sure the front_depth and back_depth values represent usable depths for later tests\n" + " if (front_depth>back_depth)\n" + " {\n" + " if (front_depth==1.0)\n" + " {\n" + " // front face likely to have been clipped out by near plane\n" + " front_depth = 0.0;\n" + " }\n" + " else\n" + " {\n" + " // front and back faces of hull are reversed so treat them as empty.\n" + " front_depth = 1.0;\n" + " back_depth = 1.0;\n" + " }\n" + " }\n" + "\n" + " if (back_depthgl_FragCoord.z)\n" + " {\n" + " fragColor = mix(color, fragColor, fragColor.a);\n" + " }\n" + "\n" + " gl_FragColor = fragColor;\n" + " gl_FragDepth = 0.0;\n" + "}\n" + "\n"; diff --git a/src/osgVolume/Shaders/volume_multipass_cube_frag.cpp b/src/osgVolume/Shaders/volume_multipass_cube_frag.cpp new file mode 100644 index 000000000..dd32aae33 --- /dev/null +++ b/src/osgVolume/Shaders/volume_multipass_cube_frag.cpp @@ -0,0 +1,87 @@ +char volume_multipass_cube_frag[] = "#version 110\n" + "\n" + "uniform sampler2D colorTexture;\n" + "uniform sampler2D depthTexture;\n" + "uniform vec4 viewportDimensions;\n" + "\n" + "// declare function defined in volume_compute_ray_color.frag\n" + "vec4 computeRayColor(vec4 fragColor, float px, float py, float depth_start, float depth_end);\n" + "\n" + "void main(void)\n" + "{\n" + " vec2 texcoord = vec2((gl_FragCoord.x-viewportDimensions[0])/viewportDimensions[2], (gl_FragCoord.y-viewportDimensions[1])/viewportDimensions[3]);\n" + " vec4 color = texture2D( colorTexture, texcoord);\n" + " float texture_depth = texture2D( depthTexture, texcoord).s;\n" + " float front_depth = 0.0;\n" + "\n" + " if (gl_FragCoord.ztexture_depth) discard;\n" + "\n" + " // gl_FragDepth = texture_depth;\n" + "\n" + " // need to blend the object color with the ray from the object depth to the eye point\n" + " vec4 ray_color = computeRayColor(vec4(0.0,0.0,0.0,0.0), gl_FragCoord.x, gl_FragCoord.y, texture_depth, front_depth);\n" + " // ray_color *= vec4(1.0,1.0,0.0,1.0);\n" + " gl_FragColor = mix(color, ray_color, ray_color.a);\n" + " }\n" + " }\n" + "\n" + "}\n" + "\n"; diff --git a/src/osgVolume/Shaders/volume_multipass_frag.cpp b/src/osgVolume/Shaders/volume_multipass_frag.cpp index 0cd1d76fa..e4c21128d 100644 --- a/src/osgVolume/Shaders/volume_multipass_frag.cpp +++ b/src/osgVolume/Shaders/volume_multipass_frag.cpp @@ -6,7 +6,7 @@ char volume_multipass_frag[] = "#version 110\n" "uniform vec4 viewportDimensions;\n" "\n" "// declare function defined in volume_compute_ray_color.frag\n" - "vec4 computeRayColor(float px, float py, float depth_start, float depth_end);\n" + "vec4 computeRayColor(vec4 fragColor, float px, float py, float depth_start, float depth_end);\n" "\n" "void main(void)\n" "{\n" @@ -26,7 +26,7 @@ char volume_multipass_frag[] = "#version 110\n" "\n" " gl_FragDepth = front_depth; // gl_FragCoord.z;\n" "\n" - " vec4 ray_color = computeRayColor(gl_FragCoord.x, gl_FragCoord.y, gl_FragCoord.z, front_depth);\n" + " vec4 ray_color = computeRayColor(vec4(0.0,0.0,0.0,0.0), gl_FragCoord.x, gl_FragCoord.y, gl_FragCoord.z, front_depth);\n" "\n" " gl_FragColor = mix(color, ray_color, ray_color.a);\n" " }\n" @@ -49,13 +49,13 @@ char volume_multipass_frag[] = "#version 110\n" "\n" " if (front_depthtexture_depth) discard;\n" + "\n" + " // gl_FragDepth = texture_depth;\n" + "\n" + " // need to blend the object color with the ray from the object depth to the eye point\n" + " vec4 ray_color = computeRayColor(vec4(0.0,0.0,0.0,0.0), gl_FragCoord.x, gl_FragCoord.y, texture_depth, front_depth);\n" + " // ray_color *= vec4(1.0,1.0,0.0,1.0);\n" + " gl_FragColor = mix(color, ray_color, ray_color.a);\n" + " }\n" + " }\n" + "\n" + "}\n" + "\n"; diff --git a/src/osgVolume/VolumeScene.cpp b/src/osgVolume/VolumeScene.cpp index 78a43748b..3fc66adc5 100644 --- a/src/osgVolume/VolumeScene.cpp +++ b/src/osgVolume/VolumeScene.cpp @@ -405,7 +405,7 @@ void VolumeScene::traverse(osg::NodeVisitor& nv) TileData* tileData = itr->second.get(); if (!tileData || !(tileData->active)) { - OSG_INFO<<"Skipping TileData that is inactive : "<