From f7dbd7995a330a5bd9cddd8435f3818a64f28b8c Mon Sep 17 00:00:00 2001 From: kjeppesen1 Date: Fri, 16 Apr 2021 15:36:51 -0700 Subject: [PATCH 1/4] LensFlare - allow inheritance (#2965) * Add LensFlarePrivate setter methods and move LensFlareCompositorListener defintion to header * Modified LensFlareCompositorListener members to follow PIMPL * Reduce line length and fix whitespace Signed-off-by: Steve Peters Co-authored-by: kbjeppes Co-authored-by: Steve Peters --- gazebo/rendering/LensFlare.cc | 575 +++++++++++++++++----------------- gazebo/rendering/LensFlare.hh | 78 ++++- 2 files changed, 368 insertions(+), 285 deletions(-) diff --git a/gazebo/rendering/LensFlare.cc b/gazebo/rendering/LensFlare.cc index 2c254c9ddb..792a501344 100644 --- a/gazebo/rendering/LensFlare.cc +++ b/gazebo/rendering/LensFlare.cc @@ -23,7 +23,6 @@ #include "gazebo/transport/Node.hh" -#include "gazebo/rendering/ogre_gazebo.h" #include "gazebo/rendering/Camera.hh" #include "gazebo/rendering/Conversions.hh" #include "gazebo/rendering/Light.hh" @@ -35,319 +34,310 @@ namespace gazebo { namespace rendering { - /// \brief We'll create an instance of this class for each camera, to be - /// used to inject lens flare uniforms in each render call. - class LensFlareCompositorListener - : public Ogre::CompositorInstance::Listener + /// \brief Private data class for LensFlareCompositorListener + class LensFlareCompositorListenerPrivate { - /// \brief Constructor - public: LensFlareCompositorListener(CameraPtr _camera, LightPtr _light) - { - this->camera = _camera; - this->SetLight(_light); - } + /// \brief Pointer to light + public: LightPtr light; - /// \brief Destructor - public: ~LensFlareCompositorListener() - { - if (this->wideAngleDummyCamera) - { - this->wideAngleDummyCamera->GetScene()->RemoveCamera( - this->wideAngleDummyCamera->Name()); - } - } + /// \brief Pointer to camera + public: CameraPtr camera; + + /// \brief Dummy camera used by wide angle camera for occlusion checking + public: CameraPtr wideAngleDummyCamera; - /// \brief Set directional light that generates lens flare - /// \param[in] _light Pointer to directional light - public: void SetLight(LightPtr _light) + /// \brief Position of light in world frame + public: ignition::math::Vector3d lightWorldPos; + + /// \brief Scale of lens flare. + public: double scale = 1.0; + + /// \brief Color of lens flare. + public: ignition::math::Vector3d color + = ignition::math::Vector3d(1.0, 1.0, 1.0); + }; + + ////////////////////////////////////////////////// + LensFlareCompositorListener::LensFlareCompositorListener(CameraPtr _camera, + LightPtr _light) + : dataPtr(new LensFlareCompositorListenerPrivate) + { + this->dataPtr->camera = _camera; + this->SetLight(_light); + } + + ////////////////////////////////////////////////// + LensFlareCompositorListener::~LensFlareCompositorListener() + { + if (this->dataPtr->wideAngleDummyCamera) { - this->light = _light; + this->dataPtr->wideAngleDummyCamera->GetScene()->RemoveCamera( + this->dataPtr->wideAngleDummyCamera->Name()); } + } + + ////////////////////////////////////////////////// + void LensFlareCompositorListener::SetLight(LightPtr _light) + { + this->dataPtr->light = _light; + } + + ////////////////////////////////////////////////// + void LensFlareCompositorListener::SetScale(const double _scale) + { + this->dataPtr->scale = _scale; + } + + ////////////////////////////////////////////////// + void LensFlareCompositorListener::SetColor( + const ignition::math::Vector3d &_color) + { + this->dataPtr->color = _color; + } - /// \brief Set the scale of lens flare. - /// \param[in] _scale Scale of lens flare - public: void SetScale(const double _scale) + ////////////////////////////////////////////////// + void LensFlareCompositorListener::notifyMaterialRender(unsigned int _passId, + Ogre::MaterialPtr &_mat) + { + if (!this->dataPtr->light) { - this->scale = _scale; + // return if this->light is not set, we may still be initializing + return; } - /// \brief Set the color of lens flare. - /// \param[in] _color Color of lens flare - public: void SetColor(const ignition::math::Vector3d &_color) + GZ_ASSERT(!_mat.isNull(), "Null OGRE material"); + // These calls are setting parameters that are declared in two places: + // 1. media/materials/scripts/gazebo.material, in + // fragment_program Gazebo/CameraLensFlareFS + // 2. media/materials/scripts/camera_lens_flare_fs.glsl + Ogre::Technique *technique = _mat->getTechnique(0); + GZ_ASSERT(technique, "Null OGRE material technique"); + Ogre::Pass *pass = technique->getPass(_passId); + GZ_ASSERT(pass, "Null OGRE material pass"); + Ogre::GpuProgramParametersSharedPtr params = + pass->getFragmentProgramParameters(); + GZ_ASSERT(!params.isNull(), "Null OGRE material GPU parameters"); + + // for adjusting aspect ratio of flare + params->setNamedConstant("viewport", + Ogre::Vector3( + static_cast(this->dataPtr->camera->ViewportWidth()), + static_cast(this->dataPtr->camera->ViewportHeight()), + 1.0)); + + // use light's world position for lens flare position + if (this->dataPtr->light->Type() == "directional") { - this->color = _color; + // Directional lights misuse position as a direction. + // The large multiplier is for occlusion testing and assumes the light + // is very far away. Larger values cause the light to disappear on + // some frames for some unknown reason. + this->dataPtr->lightWorldPos = + -(this->dataPtr->light->WorldPose().Rot() * + this->dataPtr->light->Direction()) * 100000.0; } + else + this->dataPtr->lightWorldPos = this->dataPtr->light->WorldPose().Pos(); + + ignition::math::Vector3d pos; + double lensFlareScale = 1.0; + + // wide angle camera has a different way of projecting 3d points and + // occlusion checking + auto wideAngleCam = + boost::dynamic_pointer_cast(this->dataPtr->camera); + if (wideAngleCam) + this->WideAngleCameraPosScale(wideAngleCam, pos, lensFlareScale); + else + this->CameraPosScale(this->dataPtr->camera, pos, lensFlareScale); + + params->setNamedConstant("lightPos", Conversions::Convert(pos)); + params->setNamedConstant("scale", + static_cast(lensFlareScale)); + params->setNamedConstant("color", + Ogre::Vector3(this->dataPtr->color.X(), this->dataPtr->color.Y(), + this->dataPtr->color.Z())); + } - /// \brief Callback that OGRE will invoke for us on each render call - /// \param[in] _passID OGRE material pass ID. - /// \param[in] _mat Pointer to OGRE material. - public: virtual void notifyMaterialRender(unsigned int _passId, - Ogre::MaterialPtr &_mat) + ////////////////////////////////////////////////// + void LensFlareCompositorListener::CameraPosScale(const CameraPtr &_camera, + ignition::math::Vector3d &_pos, double &_scale) + { + Ogre::Vector3 lightPos; + // project 3d world space to clip space + auto viewProj = _camera->OgreCamera()->getProjectionMatrix() * + _camera->OgreCamera()->getViewMatrix(); + auto pos = viewProj * Ogre::Vector4( + Conversions::Convert(this->dataPtr->lightWorldPos)); + // normalize x and y + // keep z for visibility test + lightPos.x = pos.x / pos.w; + lightPos.y = pos.y / pos.w; + lightPos.z = pos.z; + + double occlusionScale = 1.0; + if (lightPos.z >= 0.0) { - if (!this->light) - { - // return if this->light is not set, we may still be initializing - return; - } - - GZ_ASSERT(!_mat.isNull(), "Null OGRE material"); - // These calls are setting parameters that are declared in two places: - // 1. media/materials/scripts/gazebo.material, in - // fragment_program Gazebo/CameraLensFlareFS - // 2. media/materials/scripts/camera_lens_flare_fs.glsl - Ogre::Technique *technique = _mat->getTechnique(0); - GZ_ASSERT(technique, "Null OGRE material technique"); - Ogre::Pass *pass = technique->getPass(_passId); - GZ_ASSERT(pass, "Null OGRE material pass"); - Ogre::GpuProgramParametersSharedPtr params = - pass->getFragmentProgramParameters(); - GZ_ASSERT(!params.isNull(), "Null OGRE material GPU parameters"); - - // for adjusting aspect ratio of flare - params->setNamedConstant("viewport", - Ogre::Vector3(static_cast(this->camera->ViewportWidth()), - static_cast(this->camera->ViewportHeight()), 1.0)); - - // use light's world position for lens flare position - if (this->light->Type() == "directional") - { - // Directional lights misuse position as a direction. - // The large multiplier is for occlusion testing and assumes the light - // is very far away. Larger values cause the light to disappear on - // some frames for some unknown reason. - this->lightWorldPos = -(this->light->WorldPose().Rot() * - light->Direction()) * 100000.0; - } - else - this->lightWorldPos = this->light->WorldPose().Pos(); - - ignition::math::Vector3d pos; - double lensFlareScale = 1.0; - - // wide angle camera has a different way of projecting 3d points and - // occlusion checking - auto wideAngleCam = - boost::dynamic_pointer_cast(this->camera); - if (wideAngleCam) - this->WideAngleCameraPosScale(wideAngleCam, pos, lensFlareScale); - else - this->CameraPosScale(this->camera, pos, lensFlareScale); - - params->setNamedConstant("lightPos", Conversions::Convert(pos)); - params->setNamedConstant("scale", - static_cast(lensFlareScale)); - params->setNamedConstant("color", - Ogre::Vector3(this->color.X(), this->color.Y(), this->color.Z())); + occlusionScale = this->OcclusionScale(_camera, + Conversions::ConvertIgn(lightPos), this->dataPtr->lightWorldPos); } + _pos = Conversions::ConvertIgn(lightPos); + _scale = occlusionScale * this->dataPtr->scale; + } - /// \brief Get the lens flare position and scale for a normal camera - /// \param[in] _camera Camera which the lens flare is added to - /// \param[out] _pos lens flare position in normalized device coordinates - /// \param[out] _scale Amount to scale the lens flare by. - private: void CameraPosScale(const CameraPtr &_camera, - ignition::math::Vector3d &_pos, double &_scale) + ////////////////////////////////////////////////// + void LensFlareCompositorListener::WideAngleCameraPosScale( + const WideAngleCameraPtr &_wideAngleCam, + ignition::math::Vector3d &_pos, double &_scale) + { + Ogre::Vector3 lightPos; + // create dummy camera for occlusion checking + // Needed so we can reuse Scene::FirstContact function which expects + // a gazebo camera object + std::vector ogreEnvCameras = + _wideAngleCam->OgreEnvCameras(); + if (!this->dataPtr->wideAngleDummyCamera) { - Ogre::Vector3 lightPos; - // project 3d world space to clip space - auto viewProj = _camera->OgreCamera()->getProjectionMatrix() * - _camera->OgreCamera()->getViewMatrix(); - auto pos = viewProj * Ogre::Vector4( - Conversions::Convert(this->lightWorldPos)); - // normalize x and y - // keep z for visibility test - lightPos.x = pos.x / pos.w; - lightPos.y = pos.y / pos.w; - lightPos.z = pos.z; - - double occlusionScale = 1.0; - if (lightPos.z >= 0.0) - { - occlusionScale = this->OcclusionScale(_camera, - Conversions::ConvertIgn(lightPos), this->lightWorldPos); - } - _pos = Conversions::ConvertIgn(lightPos); - _scale = occlusionScale * this->scale; + // create camera with auto render set to false + // so it doesn't actually use up too much gpu resources + static unsigned int dummyCamId = 0; + std::string dummyCamName = + _wideAngleCam->Name() + "_lensflare_occlusion_" + + std::to_string(dummyCamId); + this->dataPtr->wideAngleDummyCamera = + _wideAngleCam->GetScene()->CreateCamera( + dummyCamName, false); + this->dataPtr->wideAngleDummyCamera->Load(); + + // set dummy camera properties based on env cam + Ogre::Camera *cam = ogreEnvCameras[0]; + this->dataPtr->wideAngleDummyCamera->SetImageWidth( + cam->getViewport()->getActualWidth()); + this->dataPtr->wideAngleDummyCamera->SetImageHeight( + cam->getViewport()->getActualHeight()); + this->dataPtr->wideAngleDummyCamera->Init(); + this->dataPtr->wideAngleDummyCamera->CreateRenderTexture( + dummyCamName + "_rtt"); + this->dataPtr->wideAngleDummyCamera->SetAspectRatio( + cam->getAspectRatio()); + // aspect ratio should be 1.0 so VFOV should equal to HFOV + this->dataPtr->wideAngleDummyCamera->SetHFOV( + ignition::math::Angle(cam->getFOVy().valueRadians())); + // reset camera orientation so we can set the exact world pose + // below when doing occlusion ray cast test + this->dataPtr->wideAngleDummyCamera->OgreCamera()->setOrientation( + Ogre::Quaternion::IDENTITY); } - /// \brief Get the lens flare position and scale for a wide angle camera - /// \param[in] _wideAngleCam Camera which the lens flare is added to - /// \param[out] _pos lens flare position in normalized device coordinates - /// \param[out] _scale Amount to scale the lens flare by. - private: void WideAngleCameraPosScale( - const WideAngleCameraPtr &_wideAngleCam, - ignition::math::Vector3d &_pos, double &_scale) + // project camera into screen space + double viewportWidth = + static_cast(_wideAngleCam->ViewportWidth()); + double viewportHeight = + static_cast(_wideAngleCam->ViewportHeight()); + auto imagePos = _wideAngleCam->Project3d(this->dataPtr->lightWorldPos); + + GZ_ASSERT(viewportWidth > 0, "Viewport width is 0"); + GZ_ASSERT(viewportHeight > 0, "Viewport height is 0"); + + // convert to normalized device coordinates (needed by shaders) + // keep z for visibility test + lightPos.x = 2.0 * (imagePos.X() / viewportWidth - 0.5); + lightPos.y = 2.0 * (1.0 - (imagePos.Y() / viewportHeight) - 0.5); + // imagePos.Z() is the distance of point from camera optical center + // if it's > 1.0 than the point is outside of camera view + // but allow some tol to avoid sharp dropoff of lens flare at + // edge of image frame. tol = 0.75 + lightPos.z = (imagePos.Z() > 1.75) ? -1 : 1; + + // check occlusion and set scale + // loop through all env cameras and find the cam that sees the light + // ray cast using that env camera to see if the distance to closest + // intersection point is less than light's world pos + double occlusionScale = 1.0; + if (lightPos.z >= 0.0) { - Ogre::Vector3 lightPos; - // create dummy camera for occlusion checking - // Needed so we can reuse Scene::FirstContact function which expects - // a gazebo camera object - std::vector ogreEnvCameras = - _wideAngleCam->OgreEnvCameras(); - if (!this->wideAngleDummyCamera) - { - // create camera with auto render set to false - // so it doesn't actually use up too much gpu resources - static unsigned int dummyCamId = 0; - std::string dummyCamName = - _wideAngleCam->Name() + "_lensflare_occlusion_" + - std::to_string(dummyCamId); - this->wideAngleDummyCamera = - _wideAngleCam->GetScene()->CreateCamera( - dummyCamName, false); - this->wideAngleDummyCamera->Load(); - - // set dummy camera properties based on env cam - Ogre::Camera *cam = ogreEnvCameras[0]; - this->wideAngleDummyCamera->SetImageWidth( - cam->getViewport()->getActualWidth()); - this->wideAngleDummyCamera->SetImageHeight( - cam->getViewport()->getActualHeight()); - this->wideAngleDummyCamera->Init(); - this->wideAngleDummyCamera->CreateRenderTexture( - dummyCamName + "_rtt"); - this->wideAngleDummyCamera->SetAspectRatio( - cam->getAspectRatio()); - // aspect ratio should be 1.0 so VFOV should equal to HFOV - this->wideAngleDummyCamera->SetHFOV( - ignition::math::Angle(cam->getFOVy().valueRadians())); - // reset camera orientation so we can set the exact world pose - // below when doing occlusion ray cast test - this->wideAngleDummyCamera->OgreCamera()->setOrientation( - Ogre::Quaternion::IDENTITY); - } - - // project camera into screen space - double viewportWidth = - static_cast(_wideAngleCam->ViewportWidth()); - double viewportHeight = - static_cast(_wideAngleCam->ViewportHeight()); - auto imagePos = _wideAngleCam->Project3d(this->lightWorldPos); - - GZ_ASSERT(viewportWidth > 0, "Viewport width is 0"); - GZ_ASSERT(viewportHeight > 0, "Viewport height is 0"); - - // convert to normalized device coordinates (needed by shaders) - // keep z for visibility test - lightPos.x = 2.0 * (imagePos.X() / viewportWidth - 0.5); - lightPos.y = 2.0 * (1.0 - (imagePos.Y() / viewportHeight) - 0.5); - // imagePos.Z() is the distance of point from camera optical center - // if it's > 1.0 than the point is outside of camera view - // but allow some tol to avoid sharp dropoff of lens flare at - // edge of image frame. tol = 0.75 - lightPos.z = (imagePos.Z() > 1.75) ? -1 : 1; - - // check occlusion and set scale - // loop through all env cameras and find the cam that sees the light - // ray cast using that env camera to see if the distance to closest - // intersection point is less than light's world pos - double occlusionScale = 1.0; - if (lightPos.z >= 0.0) + // loop through all env cameras + for (auto cam : ogreEnvCameras) { - // loop through all env cameras - for (auto cam : ogreEnvCameras) + // project light world point to camera clip space. + auto viewProj = cam->getProjectionMatrix() * cam->getViewMatrix(); + auto pos = viewProj * + Ogre::Vector4(Conversions::Convert(this->dataPtr->lightWorldPos)); + pos.x /= pos.w; + pos.y /= pos.w; + // check if light is visible + if (std::fabs(pos.x) <= 1 && std::fabs(pos.y) <= 1 && pos.z > 0) { - // project light world point to camera clip space. - auto viewProj = cam->getProjectionMatrix() * cam->getViewMatrix(); - auto pos = viewProj * - Ogre::Vector4(Conversions::Convert(this->lightWorldPos)); - pos.x /= pos.w; - pos.y /= pos.w; - // check if light is visible - if (std::fabs(pos.x) <= 1 && std::fabs(pos.y) <= 1 && pos.z > 0) - { - // check occlusion using this env camera - this->wideAngleDummyCamera->SetWorldPose(ignition::math::Pose3d( + // check occlusion using this env camera + this->dataPtr->wideAngleDummyCamera->SetWorldPose( + ignition::math::Pose3d( Conversions::ConvertIgn(cam->getDerivedPosition()), Conversions::ConvertIgn(cam->getDerivedOrientation()))); - occlusionScale = this->OcclusionScale( - this->wideAngleDummyCamera, - ignition::math::Vector3d(pos.x, pos.y, pos.z), - this->lightWorldPos); - break; - } + occlusionScale = this->OcclusionScale( + this->dataPtr->wideAngleDummyCamera, + ignition::math::Vector3d(pos.x, pos.y, pos.z), + this->dataPtr->lightWorldPos); + break; } } - _pos = Conversions::ConvertIgn(lightPos); - _scale = occlusionScale * this->scale; } + _pos = Conversions::ConvertIgn(lightPos); + _scale = occlusionScale * this->dataPtr->scale; + } - /// \brief Check to see if the lens flare is occluded and return a scaling - /// factor that is proportional to the lens flare's visibility - /// \param[in] _cam Camera used for checking occlusion - /// \param[in] _imgPos light pos in clip space - /// \param[in] _worldPos light pos in 3D world space - private: double OcclusionScale(const CameraPtr &_cam, - const ignition::math::Vector3d &_imgPos, - const ignition::math::Vector3d &_worldPos) + ////////////////////////////////////////////////// + double LensFlareCompositorListener::OcclusionScale(const CameraPtr &_cam, + const ignition::math::Vector3d &_imgPos, + const ignition::math::Vector3d &_worldPos) + { + double viewportWidth = + static_cast(_cam->ViewportWidth()); + double viewportHeight = + static_cast(_cam->ViewportHeight()); + ignition::math::Vector2i screenPos; + screenPos.X() = ((_imgPos.X() / 2.0) + 0.5) * viewportWidth; + screenPos.Y() = (1 - ((_imgPos.Y() / 2.0) + 0.5)) * viewportHeight; + + ScenePtr scene = _cam->GetScene(); + + // check center point + // if occluded than set scale to 0 + ignition::math::Vector3d position; + bool intersect = scene->FirstContact(_cam, screenPos, position); + if (intersect && (position.Length() < _worldPos.Length())) + return 0; + + unsigned int rays = 0; + unsigned int occluded = 0u; + // work in normalized device coordinates + // lens flare's halfSize is just an approximated value + double halfSize = 0.05 * this->dataPtr->scale; + double steps = 10; + double stepSize = halfSize * 2 / steps; + double cx = _imgPos.X(); + double cy = _imgPos.Y(); + double startx = cx - halfSize; + double starty = cy - halfSize; + double endx = cx + halfSize; + double endy = cy + halfSize; + // do sparse ray cast occlusion check + for (double i = starty; i < endy; i+=stepSize) { - double viewportWidth = - static_cast(_cam->ViewportWidth()); - double viewportHeight = - static_cast(_cam->ViewportHeight()); - ignition::math::Vector2i screenPos; - screenPos.X() = ((_imgPos.X() / 2.0) + 0.5) * viewportWidth; - screenPos.Y() = (1 - ((_imgPos.Y() / 2.0) + 0.5)) * viewportHeight; - - ScenePtr scene = _cam->GetScene(); - - // check center point - // if occluded than set scale to 0 - ignition::math::Vector3d position; - bool intersect = scene->FirstContact(_cam, screenPos, position); - if (intersect && (position.Length() < _worldPos.Length())) - return 0; - - unsigned int rays = 0; - unsigned int occluded = 0u; - // work in normalized device coordinates - // lens flare's halfSize is just an approximated value - double halfSize = 0.05 * this->scale; - double steps = 10; - double stepSize = halfSize * 2 / steps; - double cx = _imgPos.X(); - double cy = _imgPos.Y(); - double startx = cx - halfSize; - double starty = cy - halfSize; - double endx = cx + halfSize; - double endy = cy + halfSize; - // do sparse ray cast occlusion check - for (double i = starty; i < endy; i+=stepSize) + for (double j = startx; j < endx; j+=stepSize) { - for (double j = startx; j < endx; j+=stepSize) - { - screenPos.X() = ((j / 2.0) + 0.5) * viewportWidth; - screenPos.Y() = (1 - ((i / 2.0) + 0.5)) * viewportHeight; - intersect = scene->FirstContact(_cam, screenPos, position); - if (intersect && (position.Length() < _worldPos.Length())) - occluded++; - rays++; - } + screenPos.X() = ((j / 2.0) + 0.5) * viewportWidth; + screenPos.Y() = (1 - ((i / 2.0) + 0.5)) * viewportHeight; + intersect = scene->FirstContact(_cam, screenPos, position); + if (intersect && (position.Length() < _worldPos.Length())) + occluded++; + rays++; } - double s = static_cast(rays - occluded) / - static_cast(rays); - return s; - }; - - /// \brief Pointer to light - private: LightPtr light; - - /// \brief Pointer to camera - private: CameraPtr camera; - - /// \brief Dummy camera used by wide angle camera for occlusion checking - private: CameraPtr wideAngleDummyCamera; - - /// \brief Position of light in world frame - private: ignition::math::Vector3d lightWorldPos; - - /// \brief Scale of lens flare. - private: double scale = 1.0; - - /// \brief Color of lens flare. - private: ignition::math::Vector3d color - = ignition::math::Vector3d(1.0, 1.0, 1.0); - }; + } + double s = static_cast(rays - occluded) / + static_cast(rays); + return s; + } /// \brief Private data class for LensFlare class LensFlarePrivate @@ -532,3 +522,22 @@ void LensFlare::OnRequest(ConstRequestPtr &_msg) std::bind(&LensFlare::Update, this)); } } + +////////////////////////////////////////////////// +void LensFlare::SetCameraSensor(CameraPtr _camera) +{ + this->dataPtr->camera = _camera; +} + +////////////////////////////////////////////////// +void LensFlare::SetLensFlareCompositorListener( + std::shared_ptr _listener) +{ + this->dataPtr->lensFlareCompositorListener = _listener; +} + +////////////////////////////////////////////////// +void LensFlare::SetLensFlareInstance(Ogre::CompositorInstance *_instance) +{ + this->dataPtr->lensFlareInstance = _instance; +} diff --git a/gazebo/rendering/LensFlare.hh b/gazebo/rendering/LensFlare.hh index 773e4a6baa..6c793aff5c 100644 --- a/gazebo/rendering/LensFlare.hh +++ b/gazebo/rendering/LensFlare.hh @@ -22,6 +22,7 @@ #include "gazebo/msgs/msgs.hh" +#include "gazebo/rendering/ogre_gazebo.h" #include "gazebo/rendering/RenderTypes.hh" #include "gazebo/util/system.hh" @@ -31,7 +32,67 @@ namespace gazebo /// \brief Rendering namespace namespace rendering { - class LensFlarePrivate; + class LensFlarePrivate; + + class LensFlareCompositorListenerPrivate; + + /// \brief We'll create an instance of this class for each camera, to be + /// used to inject lens flare uniforms in each render call. + class GZ_RENDERING_VISIBLE LensFlareCompositorListener + : public Ogre::CompositorInstance::Listener + { + /// \brief Constructor + public: LensFlareCompositorListener(CameraPtr _camera, LightPtr _light); + + /// \brief Destructor + public: ~LensFlareCompositorListener(); + + /// \brief Set directional light that generates lens flare + /// \param[in] _light Pointer to directional light + public: void SetLight(LightPtr _light); + + /// \brief Set the scale of lens flare. + /// \param[in] _scale Scale of lens flare + public: void SetScale(const double _scale); + + /// \brief Set the color of lens flare. + /// \param[in] _color Color of lens flare + public: void SetColor(const ignition::math::Vector3d &_color); + + /// \brief Callback that OGRE will invoke for us on each render call + /// \param[in] _passID OGRE material pass ID. + /// \param[in] _mat Pointer to OGRE material. + public: virtual void notifyMaterialRender(unsigned int _passId, + Ogre::MaterialPtr &_mat); + + /// \brief Get the lens flare position and scale for a normal camera + /// \param[in] _camera Camera which the lens flare is added to + /// \param[out] _pos lens flare position in normalized device coordinates + /// \param[out] _scale Amount to scale the lens flare by. + private: void CameraPosScale(const CameraPtr &_camera, + ignition::math::Vector3d &_pos, double &_scale); + + /// \brief Get the lens flare position and scale for a wide angle camera + /// \param[in] _wideAngleCam Camera which the lens flare is added to + /// \param[out] _pos lens flare position in normalized device coordinates + /// \param[out] _scale Amount to scale the lens flare by. + private: void WideAngleCameraPosScale( + const WideAngleCameraPtr &_wideAngleCam, + ignition::math::Vector3d &_pos, double &_scale); + + /// \brief Check to see if the lens flare is occluded and return a scaling + /// factor that is proportional to the lens flare's visibility + /// \param[in] _cam Camera used for checking occlusion + /// \param[in] _imgPos light pos in clip space + /// \param[in] _worldPos light pos in 3D world space + private: double OcclusionScale(const CameraPtr &_cam, + const ignition::math::Vector3d &_imgPos, + const ignition::math::Vector3d &_worldPos); + + /// \internal + /// \brief Pointer to private data. + private: std::unique_ptr dataPtr; + }; /// \addtogroup gazebo_rendering Rendering /// \{ @@ -63,7 +124,20 @@ namespace gazebo public: void SetColor(const ignition::math::Vector3d &_color); /// \brief Update function to search light source - private: void Update(); + protected: void Update(); + + /// \brief Set camera stored in LensFlarePrivate + /// \param[in] _camera Camera to use in sensor. + protected: void SetCameraSensor(CameraPtr _camera); + + /// \brief Set lensFlareCompositorListener stored in LensFlarePrivate + /// \param[in] _listener Shared pointer to object to be set. + protected: void SetLensFlareCompositorListener( + std::shared_ptr _listener); + + /// \brief Set lensFlareInstance stored in LensFlarePrivate + /// \param[in] _instance CompositorInstance to set + protected: void SetLensFlareInstance(Ogre::CompositorInstance *_instance); /// \brief Request callback /// \param[in] _msg The message data. From 635a2d00fc869c08171276ad4b38e597b757891c Mon Sep 17 00:00:00 2001 From: Steve Peters Date: Mon, 19 Apr 2021 16:43:16 -0700 Subject: [PATCH 2/4] LensFlare: rename SetCameraSensor to SetCameraImpl (#2975) This is an adjustment to API added in #2965, which is allowed because the API has not yet been released. Signed-off-by: Steve Peters --- gazebo/rendering/LensFlare.cc | 2 +- gazebo/rendering/LensFlare.hh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gazebo/rendering/LensFlare.cc b/gazebo/rendering/LensFlare.cc index 792a501344..b312b01750 100644 --- a/gazebo/rendering/LensFlare.cc +++ b/gazebo/rendering/LensFlare.cc @@ -524,7 +524,7 @@ void LensFlare::OnRequest(ConstRequestPtr &_msg) } ////////////////////////////////////////////////// -void LensFlare::SetCameraSensor(CameraPtr _camera) +void LensFlare::SetCameraImpl(CameraPtr _camera) { this->dataPtr->camera = _camera; } diff --git a/gazebo/rendering/LensFlare.hh b/gazebo/rendering/LensFlare.hh index 6c793aff5c..a119ecb473 100644 --- a/gazebo/rendering/LensFlare.hh +++ b/gazebo/rendering/LensFlare.hh @@ -128,7 +128,7 @@ namespace gazebo /// \brief Set camera stored in LensFlarePrivate /// \param[in] _camera Camera to use in sensor. - protected: void SetCameraSensor(CameraPtr _camera); + protected: void SetCameraImpl(CameraPtr _camera); /// \brief Set lensFlareCompositorListener stored in LensFlarePrivate /// \param[in] _listener Shared pointer to object to be set. From 4b44af0902f7758dbcc74f4d5d4ae893ef878eed Mon Sep 17 00:00:00 2001 From: Martin Pecka Date: Fri, 16 Apr 2021 01:06:24 +0200 Subject: [PATCH 3/4] Fix size of light visual (#2947) Signed-off-by: Martin Pecka --- gazebo/rendering/Light.cc | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gazebo/rendering/Light.cc b/gazebo/rendering/Light.cc index 3f31b06341..2e1f4316d0 100644 --- a/gazebo/rendering/Light.cc +++ b/gazebo/rendering/Light.cc @@ -319,8 +319,8 @@ void Light::CreateVisual() double angles[2]; double range = 0.2; - angles[0] = range * tan(outerAngle); - angles[1] = range * tan(innerAngle); + angles[0] = range * tan(outerAngle / 2); + angles[1] = range * tan(innerAngle / 2); unsigned int i = 0; this->dataPtr->line->AddPoint(ignition::math::Vector3d(0, 0, 0)); From f04fc1592a4186d3eb7de18b9d326ac49caeffe3 Mon Sep 17 00:00:00 2001 From: Benlitz Date: Sat, 17 Apr 2021 10:07:33 +0900 Subject: [PATCH 4/4] Fix depth camera breaking shadows (#2907) * Remove modifications to the shadow technique done in the DepthCamera, this is not necessary and breaks lighting for all other cameras that will render after it in the same frame * Add call to setShadowsEnabled for the normals viewport as well Co-authored-by: Steve Peters --- gazebo/rendering/DepthCamera.cc | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/gazebo/rendering/DepthCamera.cc b/gazebo/rendering/DepthCamera.cc index 512a2a0a8e..ab82e14532 100644 --- a/gazebo/rendering/DepthCamera.cc +++ b/gazebo/rendering/DepthCamera.cc @@ -239,6 +239,7 @@ void DepthCamera::CreateDepthTexture(const std::string &_textureName) this->SetDepthTarget(this->depthTarget); this->depthViewport->setOverlaysEnabled(false); + this->depthViewport->setShadowsEnabled(false); this->depthViewport->setBackgroundColour( Ogre::ColourValue(Ogre::ColourValue(0, 0, 0))); @@ -282,6 +283,7 @@ void DepthCamera::CreateDepthTexture(const std::string &_textureName) this->dataPtr->pcdViewport->setBackgroundColour( Conversions::Convert(ignBG)); this->dataPtr->pcdViewport->setOverlaysEnabled(false); + this->dataPtr->pcdViewport->setShadowsEnabled(false); this->dataPtr->pcdViewport->setVisibilityMask( GZ_VISIBILITY_ALL & ~(GZ_VISIBILITY_GUI | GZ_VISIBILITY_SELECTABLE)); @@ -378,6 +380,7 @@ void DepthCamera::CreateNormalsTexture(const std::string &_textureName) this->dataPtr->normalsViewport->setBackgroundColour( Conversions::Convert(ignBG)); this->dataPtr->normalsViewport->setOverlaysEnabled(false); + this->dataPtr->normalsViewport->setShadowsEnabled(false); this->dataPtr->normalsViewport->setVisibilityMask( GZ_VISIBILITY_ALL & ~(GZ_VISIBILITY_GUI | GZ_VISIBILITY_SELECTABLE)); @@ -602,9 +605,6 @@ void DepthCamera::RenderImpl() { Ogre::SceneManager *sceneMgr = this->scene->OgreSceneManager(); - Ogre::ShadowTechnique shadowTech = sceneMgr->getShadowTechnique(); - - sceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_NONE); sceneMgr->_suppressRenderStateChanges(true); this->UpdateRenderTarget(this->depthTarget, @@ -614,14 +614,12 @@ void DepthCamera::RenderImpl() this->depthTarget->update(false); sceneMgr->_suppressRenderStateChanges(false); - sceneMgr->setShadowTechnique(shadowTech); // for camera image Camera::RenderImpl(); if (this->dataPtr->outputPoints) { - sceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_NONE); sceneMgr->_suppressRenderStateChanges(true); this->UpdateRenderTarget(this->dataPtr->pcdTarget, @@ -630,7 +628,6 @@ void DepthCamera::RenderImpl() this->dataPtr->pcdTarget->update(false); sceneMgr->_suppressRenderStateChanges(false); - sceneMgr->setShadowTechnique(shadowTech); } if (this->dataPtr->outputReflectance) @@ -640,7 +637,6 @@ void DepthCamera::RenderImpl() if (this->dataPtr->outputNormals) { - sceneMgr->setShadowTechnique(Ogre::SHADOWTYPE_NONE); sceneMgr->_suppressRenderStateChanges(true); this->UpdateRenderTarget(this->dataPtr->normalsTarget, @@ -649,7 +645,6 @@ void DepthCamera::RenderImpl() this->dataPtr->normalsTarget->update(false); sceneMgr->_suppressRenderStateChanges(false); - sceneMgr->setShadowTechnique(shadowTech); } }