Commit 1d08be22 authored by Sreekanth Arikatla's avatar Sreekanth Arikatla
Browse files

Merge branch 'Andrew_ssao_shadow' into 'master'

ENH: Adds SSAO

See merge request iMSTK/iMSTK!599
parents 0ca88a6f 48bbc39e
......@@ -121,8 +121,6 @@ main()
imstkNew<DirectionalLight> dirLight("DirLight");
dirLight->setIntensity(4);
dirLight->setColor(Color(1.0, 0.95, 0.8));
dirLight->setCastsShadow(true);
dirLight->setShadowRange(1.5);
scene->addLight(dirLight);
{
......
......@@ -49,6 +49,7 @@ main()
// Write log to stdout and file
Logger::startLogger();
double sceneSize;
imstkNew<Scene> scene("Rendering");
{
// Add IBL Probe
......@@ -83,17 +84,10 @@ main()
// Lights
imstkNew<DirectionalLight> dirLight("DirectionalLight");
dirLight->setIntensity(4.0);
dirLight->setIntensity(10.0);
dirLight->setColor(Color(1.0, 0.95, 0.8));
dirLight->setCastsShadow(true);
dirLight->setShadowRange(1.5);
scene->addLight(dirLight);
imstkNew<PointLight> pointLight("PointLight");
pointLight->setIntensity(0.1);
pointLight->setPosition(0.1, 0.2, 0.5);
scene->addLight(pointLight);
// Plane
auto planeObj = apiutils::createVisualAnalyticalSceneObject("Plane", scene, "VisualPlane", Vec3d(10.0, 10.0, 10.0));
imstkNew<RenderMaterial> planeMaterial;
......@@ -129,6 +123,20 @@ main()
viewer->addControl(keyControl);
}
// Enable SSAO
Vec3d l, u;
scene->computeBoundingBox(l, u);
sceneSize = (u - l).norm();
auto rendConfig = std::make_shared<RendererConfig>();
rendConfig->m_ssaoConfig.m_enableSSAO = true;
rendConfig->m_ssaoConfig.m_SSAOBlur = true;
rendConfig->m_ssaoConfig.m_SSAORadius = 1.0 * sceneSize;
rendConfig->m_ssaoConfig.m_SSAOBias = 0.001 * sceneSize;
rendConfig->m_ssaoConfig.m_KernelSize = 128;
viewer->getActiveRenderer()->setConfig(rendConfig);
driver->start();
}
......
......@@ -210,26 +210,6 @@ RenderMaterial::removeTexture(Texture::Type type)
}
}
void
RenderMaterial::setReceivesShadows(const bool receivesShadows)
{
if (m_receivesShadows != receivesShadows)
{
m_receivesShadows = receivesShadows;
postModified();
}
}
void
RenderMaterial::setCastsShadows(const bool castsShadows)
{
if (m_castsShadows != castsShadows)
{
m_castsShadows = castsShadows;
postModified();
}
}
void
RenderMaterial::setBlendMode(const RenderMaterial::BlendMode blendMode)
{
......
......@@ -198,18 +198,6 @@ public:
void removeTexture(Texture::Type type);
std::shared_ptr<Texture> getTexture(Texture::Type type);
///
/// \brief Get/Set shadow receiving ability
///
void setReceivesShadows(const bool receivesShadows);
bool getReceivesShadows() const { return m_receivesShadows; }
///
/// \brief Get/Set shadow cast status
///
void setCastsShadows(const bool castsShadows);
bool getCastsShadows() const { return m_castsShadows; }
///
/// \brief Get/Set edge visibility
///
......@@ -316,10 +304,6 @@ protected:
///---------------------Global states------------------------
bool m_imageBasedLighting = false;
// Shadows
bool m_receivesShadows = true; ///< \note not implemented
bool m_castsShadows = true; ///< \note not implemented
bool m_backfaceCulling = true; ///< For performance, uncommon for this to be false
DisplayMode m_displayMode = DisplayMode::Surface;
......
......@@ -155,6 +155,6 @@ VTKPolyDataRenderDelegate::updateRenderProperties()
break;
}
m_actor->SetVisibility(m_visualModel->isVisible());
m_actor->SetVisibility(m_visualModel->isVisible() ? 1 : 0);
}
}
\ No newline at end of file
......@@ -70,6 +70,6 @@ VTKVolumeRenderDelegate::updateRenderProperties()
}
}
m_actor->SetVisibility(m_visualModel->isVisible());
m_actor->SetVisibility(m_visualModel->isVisible() ? 1 : 0);
}
}
\ No newline at end of file
......@@ -46,15 +46,25 @@
#include <vtkTable.h>
#include <vtkTextProperty.h>
#include <vtkOpenVRRenderer.h>
#include <vtkCameraPass.h>
#include <vtkOpenVRCamera.h>
#include <vtkOpenVRRenderer.h>
#include <vtkRenderPassCollection.h>
#include <vtkRenderStepsPass.h>
#include <vtkSequencePass.h>
#include <vtkSSAOPass.h>
#include <vtkProperty.h>
namespace imstk
{
VTKRenderer::VTKRenderer(std::shared_ptr<Scene> scene, const bool enableVR) :
m_scene(scene), m_textureManager(std::make_shared<TextureManager<VTKTextureDelegate>>())
m_scene(scene),
m_textureManager(std::make_shared<TextureManager<VTKTextureDelegate>>()),
m_ssaoPass(vtkSmartPointer<vtkSSAOPass>::New()),
m_renderStepsPass(vtkSmartPointer<vtkRenderStepsPass>::New())
{
// create m_vtkRenderer depending on enableVR
m_VrEnabled = enableVR;
if (!enableVR)
{
m_vtkRenderer = vtkSmartPointer<vtkRenderer>::New();
......@@ -152,21 +162,19 @@ VTKRenderer::VTKRenderer(std::shared_ptr<Scene> scene, const bool enableVR) :
// Camera and camera actor
if (!enableVR)
{
m_Camera = vtkSmartPointer<vtkCamera>::New();
m_camera = vtkSmartPointer<vtkCamera>::New();
}
else
{
m_Camera = vtkSmartPointer<vtkOpenVRCamera>::New();
m_camera = vtkSmartPointer<vtkOpenVRCamera>::New();
}
updateCamera();
vtkNew<vtkCameraActor> camActor;
camActor->SetCamera(m_Camera);
camActor->SetCamera(m_camera);
m_debugVtkActors.push_back(camActor);
///TODO : based on scene properties
// Customize background colors
m_vtkRenderer->SetBackground(m_config->m_BGColor1.r, m_config->m_BGColor1.g, m_config->m_BGColor1.b);
m_vtkRenderer->SetBackground2(m_config->m_BGColor2.r, m_config->m_BGColor2.g, m_config->m_BGColor2.b);
......@@ -226,6 +234,11 @@ VTKRenderer::VTKRenderer(std::shared_ptr<Scene> scene, const bool enableVR) :
axisY->SetGridVisible(false);
axisY->SetCustomTickPositions(xIndices, labels);
}
// Prepare screen space ambient occlusion effect
m_ssaoPass->SetDelegatePass(m_renderStepsPass);
this->setConfig(this->m_config);
}
void
......@@ -275,7 +288,7 @@ VTKRenderer::setMode(const Renderer::Mode mode, const bool enableVR)
}
// Reset the camera
m_Camera = vtkSmartPointer<vtkCamera>::New();
m_camera = vtkSmartPointer<vtkCamera>::New();
Renderer::setMode(mode, enableVR);
}
......@@ -386,7 +399,7 @@ void
VTKRenderer::updateCamera()
{
std::shared_ptr<Camera> cam = m_scene->getActiveCamera();
getVtkRenderer()->SetActiveCamera(m_Camera);
getVtkRenderer()->SetActiveCamera(m_camera);
// Update the camera to obtain corrected view/proj matrices
cam->update();
......@@ -397,11 +410,13 @@ VTKRenderer::updateCamera()
const double eyePos[3] = { invView(0, 3), invView(1, 3), invView(2, 3) };
const double forward[3] = { invView(0, 2), invView(1, 2), invView(2, 2) };
const double up[3] = { invView(0, 1), invView(1, 1), invView(2, 1) };
m_Camera->SetPosition(eyePos);
m_Camera->SetFocalPoint(eyePos[0] - forward[0], eyePos[1] - forward[1], eyePos[2] - forward[2]);
m_Camera->SetViewUp(up[0], up[1], up[2]);
m_Camera->SetViewAngle(cam->getFieldOfView());
m_Camera->SetClippingRange(cam->getNearZ(), cam->getFarZ());
m_camera->SetPosition(eyePos);
m_camera->SetFocalPoint(eyePos[0] - forward[0], eyePos[1] - forward[1], eyePos[2] - forward[2]);
m_camera->SetViewUp(up[0], up[1], up[2]);
m_camera->SetViewAngle(cam->getFieldOfView());
m_camera->SetClippingRange(cam->getNearZ(), cam->getFarZ());
m_camera->SetClippingRange(cam->getNearZ(), cam->getFarZ());
}
void
......@@ -610,4 +625,40 @@ VTKRenderer::updateBackground(const Vec3d backgroundOne, const Vec3d backgroundT
m_vtkRenderer->GradientBackgroundOff();
}
}
void
VTKRenderer::setConfig(std::shared_ptr<RendererConfig> config)
{
m_config = config;
// update SSAO if enabled
if (m_config->m_ssaoConfig.m_enableSSAO)
{
m_config->m_ssaoConfig.m_SSAOBlur ? m_ssaoPass->BlurOn() : m_ssaoPass->BlurOff(); // Blur on/off
m_ssaoPass->SetRadius(m_config->m_ssaoConfig.m_SSAORadius); // comparison radius
m_ssaoPass->SetBias(m_config->m_ssaoConfig.m_SSAOBias); // comparison bias
m_ssaoPass->SetKernelSize(m_config->m_ssaoConfig.m_KernelSize); // number of samples used
m_ssaoPass->SetDelegatePass(m_renderStepsPass);
m_vtkRenderer->SetPass(m_ssaoPass);
}
else
{
m_vtkRenderer->SetPass(nullptr);
}
// update background colors
m_vtkRenderer->SetBackground(m_config->m_BGColor1.r, m_config->m_BGColor1.g, m_config->m_BGColor1.b);
m_vtkRenderer->SetBackground2(m_config->m_BGColor2.r, m_config->m_BGColor2.g, m_config->m_BGColor2.b);
}
void
VTKRenderer::setDebugActorsVisible(const bool debugActorsVisible)
{
m_debugActorsVisible = debugActorsVisible;
for (auto debugActors : m_debugVtkActors)
{
debugActors->SetVisibility(debugActorsVisible);
}
}
} // imstk
......@@ -32,6 +32,7 @@
class vtkAxesActor;
class vtkCamera;
class vtkCameraPass;
class vtkChartXY;
class vtkContextActor;
class vtkLight;
......@@ -39,6 +40,8 @@ class vtkOpenVRCamera;
class vtkPlotBar;
class vtkProp;
class vtkRenderer;
class vtkRenderStepsPass;
class vtkSSAOPass;
class vtkTable;
namespace imstk
......@@ -127,6 +130,9 @@ public:
///
void updateBackground(const Vec3d color1, const Vec3d color2 = Vec3d::Zero(), const bool gradientBackground = false);
void setDebugActorsVisible(const bool debugActorsVisible);
bool getDebugActorsVisible() const { return m_debugActorsVisible; }
protected:
///
/// \brief Remove actors (also called props) from the scene
......@@ -138,6 +144,11 @@ protected:
///
void addActors(const std::vector<vtkSmartPointer<vtkProp>>& actorList);
///
/// \brief Apply configuration changes
///
void setConfig(std::shared_ptr<RendererConfig> config) override;
protected:
///
/// \brief Adds a SceneObject to be rendered
......@@ -173,7 +184,7 @@ protected:
void sceneObjectModified(Event* e);
///
/// \brief Function call for proccessing diffs on a SceneObject
/// \brief Function call for processing diffs on a SceneObject
///
void sceneObjectModified(std::shared_ptr<SceneObject> sceneObject);
......@@ -181,7 +192,7 @@ protected:
vtkSmartPointer<vtkRenderer> m_vtkRenderer;
// Camera
vtkSmartPointer<vtkCamera> m_Camera;
vtkSmartPointer<vtkCamera> m_camera;
// lights
std::vector<vtkSmartPointer<vtkLight>> m_vtkLights;
......@@ -205,10 +216,17 @@ protected:
// TextureManager is used to share textures among differing delegates
std::shared_ptr<TextureManager<VTKTextureDelegate>> m_textureManager;
// Performance chart overlay
vtkSmartPointer<vtkChartXY> m_timeTableChart;
vtkSmartPointer<vtkContextActor> m_timeTableChartActor;
vtkSmartPointer<vtkTable> m_timeTable;
vtkPlotBar* m_timeTablePlot;
int m_timeTableIter = 0;
// SSAO Effect
vtkSmartPointer<vtkSSAOPass> m_ssaoPass;
vtkSmartPointer<vtkRenderStepsPass> m_renderStepsPass;
bool m_debugActorsVisible;
};
}
......@@ -27,12 +27,23 @@
namespace imstk
{
struct rendererConfig
struct SSAOConfig
{
bool m_enableVR = false;
bool m_enableSSAO = false;
bool m_SSAOBlur = false; // blur occlusion
double m_SSAORadius = 0.1; // comparison radius
double m_SSAOBias = 0.001; // comparison bias
unsigned int m_KernelSize = 128; // number of samples used
};
struct RendererConfig
{
// Blue background
Color m_BGColor1 = Color(0.3285, 0.3285, 0.6525);
Color m_BGColor2 = Color(0.13836, 0.13836, 0.2748);
// ScreenSpace Ambient Occlusion
SSAOConfig m_ssaoConfig;
};
///
......@@ -53,7 +64,7 @@ public:
Simulation
};
Renderer() : m_config(std::make_shared<rendererConfig>()) { }
Renderer() : m_config(std::make_shared<RendererConfig>()) { }
virtual ~Renderer() = default;
public:
......@@ -76,10 +87,20 @@ public:
///
virtual void updateBackground(const Vec3d color1, const Vec3d color2 = Vec3d::Zero(), const bool gradientBackground = false) = 0;
///
/// \brief Get the render config
///
std::shared_ptr<RendererConfig> getRenderConfig() const { return m_config; }
///
/// \brief Sets the configuration and updates the render pipeline accordingly
///
virtual void setConfig(std::shared_ptr<RendererConfig> config) = 0;
protected:
bool m_VrEnabled = false;
Renderer::Mode m_currentMode = Renderer::Mode::Simulation;
std::shared_ptr<rendererConfig> m_config;
std::shared_ptr<RendererConfig> m_config;
};
}
......@@ -50,11 +50,11 @@ Scene::Scene(const std::string& name, std::shared_ptr<SceneConfig> config) :
m_taskGraph(std::make_shared<TaskGraph>("Scene_" + name + "_Source", "Scene_" + name + "_Sink")),
m_computeTimesLock(std::make_shared<ParallelUtils::SpinLock>())
{
std::shared_ptr<Camera> defaultCam = std::make_shared<Camera>();
auto defaultCam = std::make_shared<Camera>();
defaultCam->setPosition(0.0, 2.0, -15.0);
defaultCam->setFocalPoint(0.0, 0.0, 0.0);
std::shared_ptr<Camera> debugCam = std::make_shared<Camera>();
auto debugCam = std::make_shared<Camera>();
debugCam->setPosition(0.0, 4.0, -30.0);
debugCam->setFocalPoint(0.0, 0.0, 0.0);
......@@ -78,35 +78,47 @@ Scene::initialize()
// Opportunity for user configuration
this->postEvent(Event(Scene::configureTaskGraph()));
// Then init
// Initialize the task graph
initTaskGraph();
// Init the debug camera to the bounding box of the visual geometries
if (m_config->debugCamBoundingBox)
{
Vec3d globalMin = Vec3d(IMSTK_DOUBLE_MAX, IMSTK_DOUBLE_MAX, IMSTK_DOUBLE_MAX);
Vec3d globalMax = Vec3d(IMSTK_DOUBLE_MIN, IMSTK_DOUBLE_MIN, IMSTK_DOUBLE_MIN);
for (const auto& obj : m_sceneObjects)
{
for (auto visualModels : obj->getVisualModels())
{
Vec3d min = Vec3d(IMSTK_DOUBLE_MAX, IMSTK_DOUBLE_MAX, IMSTK_DOUBLE_MAX);
Vec3d max = Vec3d(IMSTK_DOUBLE_MIN, IMSTK_DOUBLE_MIN, IMSTK_DOUBLE_MIN);
visualModels->getGeometry()->computeBoundingBox(min, max);
globalMin = globalMin.cwiseMin(min);
globalMax = globalMax.cwiseMax(max);
}
}
const Vec3d center = (globalMin + globalMax) * 0.5;
const Vec3d size = globalMax - globalMin;
Vec3d globalMin, globalMax;
Scene::computeBoundingBox(globalMin, globalMax);
const Vec3d center = (globalMin + globalMax) * 0.5;
const double size = (globalMax - globalMin).norm();
m_cameras["debug"]->setFocalPoint(center);
m_cameras["debug"]->setPosition(center + Vec3d(0.0, 1.0, 1.0).normalized() * size.norm());
m_cameras["debug"]->setPosition(center + Vec3d(0.0, 1.0, 1.0).normalized() * size);
}
LOG(INFO) << "Scene '" << this->getName() << "' initialized!";
return true;
}
void
Scene::computeBoundingBox(Vec3d& lowerCorner, Vec3d& upperCorner, const double paddingPercent)
{
lowerCorner = Vec3d(IMSTK_DOUBLE_MAX, IMSTK_DOUBLE_MAX, IMSTK_DOUBLE_MAX);
upperCorner = Vec3d(IMSTK_DOUBLE_MIN, IMSTK_DOUBLE_MIN, IMSTK_DOUBLE_MIN);
for (const auto& obj : m_sceneObjects)
{
for (auto visualModels : obj->getVisualModels())
{
Vec3d min = Vec3d(IMSTK_DOUBLE_MAX, IMSTK_DOUBLE_MAX, IMSTK_DOUBLE_MAX);
Vec3d max = Vec3d(IMSTK_DOUBLE_MIN, IMSTK_DOUBLE_MIN, IMSTK_DOUBLE_MIN);
visualModels->getGeometry()->computeBoundingBox(min, max);
lowerCorner = lowerCorner.cwiseMin(min);
upperCorner = upperCorner.cwiseMax(max);
}
}
const Vec3d range = upperCorner - lowerCorner;
lowerCorner = lowerCorner - range * (paddingPercent / 100.0);
upperCorner = upperCorner + range * (paddingPercent / 100.0);
}
void
Scene::buildTaskGraph()
{
......@@ -213,7 +225,7 @@ Scene::initTaskGraph()
}
void
Scene::setEnableTaskTiming(bool enabled)
Scene::setEnableTaskTiming(const bool enabled)
{
m_config->taskTimingEnabled = enabled;
// If user wants to benchmark, tell all the nodes to time themselves
......@@ -282,7 +294,7 @@ Scene::addDebugVisualModel(std::shared_ptr<VisualModel> dbgRenderModel)
if (m_DebugRenderModelMap.find(name) != m_DebugRenderModelMap.end())
{
LOG(WARNING) << "Can not add debug render mdoel: '" << name
LOG(WARNING) << "Can not add debug render model: '" << name
<< "' is already registered in this scene.";
return;
}
......@@ -386,6 +398,45 @@ Scene::removeLight(const std::string& lightName)
LOG(INFO) << lightName << " light removed from " << m_name;
}
std::string
Scene::getCameraName(const std::shared_ptr<Camera> cam) const
{
auto i = std::find_if(m_cameras.begin(), m_cameras.end(),
[&cam](const NamedMap<Camera>::value_type& j) { return j.second == cam; });
if (i != m_cameras.end())
{
return i->first;
}
else
{
return "";
}
}
std::shared_ptr<imstk::Camera>
Scene::getCamera(const std::string name) const
{
auto i = m_cameras.find(name);
if (i != m_cameras.end())
{
return i->second;
}
else
{
return nullptr;
}
}
void
Scene::setActiveCamera(const std::string name)
{
auto i = m_cameras.find(name);
if (i != m_cameras.end())
{
m_activeCamera = m_cameras[name];
}
}
void
Scene::addController(std::shared_ptr<TrackingDeviceControl> controller)
{
......@@ -469,7 +520,7 @@ Scene::advance(const double dt)
m_resetRequested = false;
}
// FPS of physics is given by the measured time, not the given timestep dt
// FPS of physics is given by the measured time, not the given time step dt
const double elapsedTime = wwt.getTimeElapsed(StopWatch::TimeUnitType::seconds);
m_fps = 1.0 / elapsedTime;
......
......@@ -22,6 +22,7 @@
#pragma once
#include "imstkEventObject.h"
#include "imstkMath.h"
#include <atomic>
#include <string>
......@@ -109,13 +110,18 @@ public:
///
virtual bool initialize();
///
/// \brief Compute the bounding box of the scene as an union of bounding boxes of its objects
///
void computeBoundingBox(Vec3d& lowerCorner, Vec3d& upperCorner, const double paddingPercent = 0.0);
///
/// \brief Setup the task graph, this completely rebuilds the graph
///
void buildTaskGraph();
///
/// \brief Intializes the graph after its in a built state
/// \brief Initializes the graph after its in a built state
///
void initTaskGraph();
......@@ -135,7 +141,7 @@ public:
virtual void advance(const double dt);
///
/// \brief Update visuals of all sceneobjects
/// \brief Update visuals of all scene objects
///
virtual void updateVisuals();
......@@ -143,7 +149,7 @@ public:
/// \brief If true, tasks will be time and a table produced
/// every scene advance of the times
///
void setEnableTaskTiming(bool enabled);
void setEnableTaskTiming(const bool enabled);
///
/// \brief Return the SceneObjects of the scene
......@@ -197,7 +203,7 @@ public:
void addDebugVisualModel(std::shared_ptr<VisualModel> dbgRenderModel);
///
/// \brief
/// \brief Returns true if the light (checked against name) is registered to the scene, else false.
///
bool isLightRegistered(const std::string& lightName) const;
......@@ -211,18 +217,29 @@ public:
///
std::shared_ptr<Light> getLight(const std::string& lightName) const;
///
/// \brief
///
const NamedMap<Camera>& getCameras() const { return m_camer