ppovb5fc7/gazebo/plugins/AmbientOcclusionVisualPlugi...

251 lines
7.9 KiB
C++

/*
* Copyright (C) 2018 Open Source Robotics Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include <gazebo/rendering/Camera.hh>
#include <gazebo/rendering/RenderTypes.hh>
#include <gazebo/rendering/Scene.hh>
#include <gazebo/rendering/UserCamera.hh>
#include <gazebo/rendering/Visual.hh>
#include <gazebo/rendering/ogre_gazebo.h>
#include "AmbientOcclusionVisualPlugin.hh"
namespace gazebo
{
/// \brief Helper class to assign the GBuffer material to compositors that
/// need them
class SsaoGBufferSchemeHandler : public Ogre::MaterialManager::Listener
{
/// \brief Constructor
public: SsaoGBufferSchemeHandler()
{
this->gBufRefMat =
Ogre::MaterialManager::getSingleton().getByName("SSAO/GBuffer");
if (this->gBufRefMat.isNull())
{
gzerr << "Unable to find 'SSAO/GBuffer' material, SSAO will not work"
<< std::endl;
}
}
/// \brief Destructor
public: ~SsaoGBufferSchemeHandler()
{
this->gBufRefMat.setNull();
}
/// \brief Ogre callback for assigning the GBuffer material to compositors
/// \param[in] _schemeIndex Index of scheme requested
/// \param[in] _schemeName Name of scheme requested
/// \param[in] _originalMaterial Orignal material that does not contain
/// the requested scheme
/// \param[in] _lodIndex The material level-of-detail
/// \param[in] _rend Pointer to the Ogre::Renderable object requesting
/// the use of the techinique
/// \return The Ogre material technique to use when scheme is not found.
public: virtual Ogre::Technique *handleSchemeNotFound(
uint16_t /*_schemeIndex*/, const Ogre::String& _schemeName,
Ogre::Material *_originalMaterial, uint16_t /*_lodIndex*/,
const Ogre::Renderable */*_rend*/)
{
// ignore transparent / semi-tranparent materials with alpha rejection set
Ogre::Technique *origTech = _originalMaterial->getTechnique(0);
if (origTech)
{
for (unsigned int i = 0; i < origTech->getNumPasses(); ++i)
{
Ogre::Pass *origPass = origTech->getPass(i);
if (origPass && origPass->getAlphaRejectFunction() !=
Ogre::CMPF_ALWAYS_PASS)
return nullptr;
}
}
// set to use gbuffer
Ogre::Technique *gBufferTech = _originalMaterial->createTechnique();
gBufferTech->setSchemeName(_schemeName);
Ogre::Pass *gbufPass = gBufferTech->createPass();
if (!this->gBufRefMat.isNull())
*gbufPass = *this->gBufRefMat->getTechnique(0)->getPass(0);
return gBufferTech;
}
/// \brief GBuffer material
private: Ogre::MaterialPtr gBufRefMat;
};
/// \brief Private data for the AmbientOcclusionVisualPlugin class.
class AmbientOcclusionVisualPluginPrivate
{
/// \brief Destructor
public: ~AmbientOcclusionVisualPluginPrivate();
/// \brief Ambient occlusion compositor name
public: std::string compositorName;
/// \brief Post filter compositor name
public: std::string postFilterName;
/// \brief GBuffer material scheme handler
public: SsaoGBufferSchemeHandler *gBufSchemeHandler = nullptr;
/// \brief Apply ambient occlusion to the viewport of the input camera
/// \param[in] _cam Pointer to a camera
public: void AddSsao(rendering::CameraPtr _cam);
};
}
using namespace gazebo;
GZ_REGISTER_VISUAL_PLUGIN(AmbientOcclusionVisualPlugin)
/////////////////////////////////////////////////
AmbientOcclusionVisualPluginPrivate::~AmbientOcclusionVisualPluginPrivate()
{
Ogre::MaterialManager::getSingleton().removeListener(
this->gBufSchemeHandler, "GBuffer");
delete this->gBufSchemeHandler;
this->gBufSchemeHandler = nullptr;
}
/////////////////////////////////////////////////
AmbientOcclusionVisualPlugin::AmbientOcclusionVisualPlugin()
: dataPtr(new AmbientOcclusionVisualPluginPrivate)
{
}
/////////////////////////////////////////////////
AmbientOcclusionVisualPlugin::~AmbientOcclusionVisualPlugin()
{
}
/////////////////////////////////////////////////
void AmbientOcclusionVisualPlugin::Load(rendering::VisualPtr _visual,
sdf::ElementPtr _sdf)
{
if (!_visual || !_sdf)
{
gzerr << "No visual or SDF element specified. Plugin won't load." <<
std::endl;
return;
}
// Use Crease Shading. There are others but this one is fast
// and gives reasonably nice looking results
this->dataPtr->compositorName = "SSAO/CreaseShading";
this->dataPtr->postFilterName = "SSAO/Post/NoFilter";
rendering::ScenePtr scene = _visual->GetScene();
if (!scene)
{
gzerr << "Scene is null. Ambient Occlusion will not be enabled"
<< std::endl;
return;
}
// apply to all cameras
for (unsigned int i = 0; i < scene->CameraCount(); ++i)
{
this->dataPtr->AddSsao(scene->GetCamera(i));
}
for (unsigned int i = 0; i < scene->UserCameraCount(); ++i)
{
rendering::CameraPtr cam =
boost::dynamic_pointer_cast<rendering::Camera>(
scene->GetUserCamera(i));
this->dataPtr->AddSsao(cam);
}
this->dataPtr->gBufSchemeHandler = new SsaoGBufferSchemeHandler();
Ogre::MaterialManager::getSingleton().addListener(
this->dataPtr->gBufSchemeHandler, "GBuffer");
}
/////////////////////////////////////////////////
void AmbientOcclusionVisualPluginPrivate::AddSsao(rendering::CameraPtr _cam)
{
Ogre::Viewport *ogreViewport = _cam->OgreCamera()->getViewport();
if (!ogreViewport)
{
gzerr << "Viewport is null. Ambient Occlusion will not be enabled"
<< std::endl;
return;
}
// GBuffer
Ogre::CompositorInstance *gBufCompInstance =
Ogre::CompositorManager::getSingleton().addCompositor(
ogreViewport, "SSAO/GBuffer");
if (gBufCompInstance)
{
gBufCompInstance->setEnabled(true);
// the GBuffer compositor should have 2 passes,
// see gazebo/media/materials/scripts/CreaseShading.compositor
if (gBufCompInstance->getTechnique()->getNumTargetPasses() > 1)
{
// set a visibility mask so that the ssao effect does not apply to
// gui visuals
gBufCompInstance->getTechnique()->getTargetPass(1)->setVisibilityMask(
GZ_VISIBILITY_ALL & ~(GZ_VISIBILITY_GUI | GZ_VISIBILITY_SELECTABLE));
}
}
else
{
gzerr << "Failed to add GBuffer compositor" << std::endl;
}
// SSAO - Crease Shading
if (Ogre::CompositorManager::getSingleton().addCompositor(
ogreViewport, this->compositorName))
{
Ogre::CompositorManager::getSingleton().setCompositorEnabled(
ogreViewport, compositorName, true);
}
else
{
gzerr << "Failed to add compositor: " << this->compositorName
<< std::endl;
}
// SSAO post filter
if (Ogre::CompositorManager::getSingleton().addCompositor(
ogreViewport, this->postFilterName))
{
Ogre::CompositorManager::getSingleton().setCompositorEnabled(
ogreViewport, this->postFilterName, true);
}
else
{
gzerr << "Failed to add " << this->postFilterName << " compositor"
<< std::endl;
}
// modulate with existing scene
std::string postModulateFilterName = "SSAO/Post/Modulate";
if (Ogre::CompositorManager::getSingleton().addCompositor(
ogreViewport, postModulateFilterName))
{
Ogre::CompositorManager::getSingleton().setCompositorEnabled(
ogreViewport, postModulateFilterName, true);
}
else
{
gzerr << "Failed to add " << postModulateFilterName << " compositor"
<< std::endl;
}
}