diff --git a/.gitsubprojects b/.gitsubprojects
index 55ae42d55c2670d9d5b6846ceb94fbc721313c70..35f17644f8f44a0e49fbedef85267636e505ef92 100644
--- a/.gitsubprojects
+++ b/.gitsubprojects
@@ -3,8 +3,8 @@
 #git_subproject( Lexis https://github.com/HBPVis/Lexis.git c24dc07 )
 #git_subproject( gmrvlex git@gitlab.gmrv.es:nsviz/gmrvlex.git c20b194 )
 #git_subproject( Brion https://github.com/BlueBrain/Brion.git 073f356 )
-git_subproject( ReTo https://github.com/gmrvvis/ReTo.git ff4086c )
-git_subproject( prefr https://github.com/gmrvvis/prefr.git 05fbf11 )
+git_subproject( ReTo https://github.com/gmrvvis/ReTo.git 13f5747f )
+git_subproject( prefr https://github.com/gmrvvis/prefr.git 5b4b874a )
 git_subproject( SimIL https://github.com/gmrvvis/SimIL.git 7a1eab6 )
 git_subproject( scoop https://github.com/gmrvvis/scoop.git b3326cd )
-git_subproject( acuterecorder https://github.com/vg-lab/AcuteRecorder.git 11d66ac1 )
+git_subproject( acuterecorder https://github.com/vg-lab/AcuteRecorder.git 3ae70efa )
diff --git a/CMake/common b/CMake/common
index c295fb24d765a6d9479e4d7e4c0885e3ff0df6b0..f5651546b0d3036cebb61cea1293d2b3f1bedb2e 160000
--- a/CMake/common
+++ b/CMake/common
@@ -1 +1 @@
-Subproject commit c295fb24d765a6d9479e4d7e4c0885e3ff0df6b0
+Subproject commit f5651546b0d3036cebb61cea1293d2b3f1bedb2e
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 6e64eece307c1f423317104acec862711ff6a754..647ff5ee57918209b4fb681f18dca50ea110207b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -9,7 +9,7 @@
 cmake_minimum_required( VERSION 3.1 FATAL_ERROR )
 
 # visimpl project and version
-project( visimpl VERSION 1.5.4 )
+project( visimpl VERSION 1.6.0 )
 set( visimpl_VERSION_ABI 6 )
 
 SET( VISIMPL_LICENSE "GPL")
diff --git a/sumrice/TransferFunctionWidget.cpp b/sumrice/TransferFunctionWidget.cpp
index a6c13ba10a578315aeb0a9d7c793877825481fd5..9798809b9b4019dc96f09d0b672e2c9c1e7c1a72 100644
--- a/sumrice/TransferFunctionWidget.cpp
+++ b/sumrice/TransferFunctionWidget.cpp
@@ -81,10 +81,10 @@ void TransferFunctionWidget::InitDialog( void )
     QGradientStops stops;
 
     stops.clear( );
-    stops << qMakePair( 0.0,  QColor::fromRgbF( 0.0, 1.0, 0.0, 0.05 ))
-          << qMakePair( 0.35, QColor::fromRgbF( 1.0, 0.0, 0.0, 0.2  ))
-          << qMakePair( 0.7,  QColor::fromRgbF( 1.0, 1.0, 0.0, 0.2  ))
-          << qMakePair( 1.0,  QColor::fromRgbF( 0.0, 0.0, 1.0, 0.2  ));
+    stops << qMakePair( 0.0,  QColor::fromRgbF( 0.0, 1.0, 0.0, 0.2 ))
+          << qMakePair( 0.35, QColor::fromRgbF( 1.0, 0.0, 0.0, 0.5  ))
+          << qMakePair( 0.7,  QColor::fromRgbF( 1.0, 1.0, 0.0, 0.5  ))
+          << qMakePair( 1.0,  QColor::fromRgbF( 0.0, 0.0, 1.0, 0.5  ));
     _presets.push_back( Preset( "Default [ multi-hue]", stops ));
 
      stops.clear( );
@@ -98,23 +98,23 @@ void TransferFunctionWidget::InitDialog( void )
     _presets.push_back( Preset( "Red-green [ multi-hue]", stops ));
 
     stops.clear( );
-    stops << qMakePair( 0.0, QColor( 255, 0, 0, 50 ))
+    stops << qMakePair( 0.0, QColor( 255, 0, 0, 100 ))
           << qMakePair( 0.1, QColor( 255, 0, 0, 200 ))
           << qMakePair( 1.0, QColor( 0, 0, 0, 20 ));
     _presets.push_back( Preset( "Red [ mono-hue]", stops ));
 
     stops.clear( );
-    stops << qMakePair( 0.0, QColor( 0, 255, 0, 50 ))
+    stops << qMakePair( 0.0, QColor( 0, 255, 0, 100 ))
           << qMakePair( 1.0, QColor( 0, 0, 0, 0 ));
     _presets.push_back( Preset( "Green [ mono-hue]", stops ));
 
     stops.clear( );
-    stops << qMakePair( 0.0, QColor( 0, 0, 255, 50 ))
+    stops << qMakePair( 0.0, QColor( 0, 0, 255, 100 ))
           << qMakePair( 1.0, QColor( 0, 0, 0, 0 ));
     _presets.push_back( Preset( "Blue [ mono-hue]", stops ));
 
     stops.clear( );
-    stops << qMakePair( 0.0, QColor::fromHsv( 60, 255, 255, 50 ))
+    stops << qMakePair( 0.0, QColor::fromHsv( 60, 255, 255, 100 ))
           << qMakePair( 1.0, QColor::fromHsv( 60, 128, 128,  0 ))
           << qMakePair( 1.0, QColor::fromHsv( 60,   0,   0,  0 ));
     _presets.push_back( Preset( "Yellow [ mono-hue]", stops ));
diff --git a/visimpl/DomainManager.cpp b/visimpl/DomainManager.cpp
index 17284074b88458205441d8a9f2c4094beed1bef9..a3054137e83bada50aa29e99cedaed05150aebed 100644
--- a/visimpl/DomainManager.cpp
+++ b/visimpl/DomainManager.cpp
@@ -103,14 +103,14 @@ namespace visimpl
     _loadPaletteColors( );
   }
 
-  void DomainManager::initializeParticleSystem( void )
+  void DomainManager::initializeParticleSystem( prefr::IGLRenderProgram* program )
   {
     std::cout << "Initializing particle system..." << std::endl;
 
     _updater = new UpdaterStaticPosition( );
 
     prefr::Sorter* sorter = new prefr::Sorter( );
-    prefr::GLRenderer* renderer = new prefr::GLPickRenderer( );
+    prefr::OIGLRenderer* renderer = new prefr::OIGLRenderer( program );
 
     _particleSystem->addUpdater( _updater );
     _particleSystem->sorter( sorter );
@@ -135,10 +135,10 @@ namespace visimpl
 
 
     _modelBase = new prefr::ColorOperationModel( _decayValue, _decayValue );
-    _modelBase->color.Insert( 0.0f, ( glm::vec4(0.f, 1.f, 0.f, 0.05)));
-    _modelBase->color.Insert( 0.35f, ( glm::vec4(1, 0, 0, 0.2 )));
-    _modelBase->color.Insert( 0.7f, ( glm::vec4(1.f, 1.f, 0, 0.2 )));
-    _modelBase->color.Insert( 1.0f, ( glm::vec4(0, 0, 1.f, 0.2 )));
+    _modelBase->color.Insert( 0.0f, ( glm::vec4(0.f, 1.f, 0.f, 0.2)));
+    _modelBase->color.Insert( 0.35f, ( glm::vec4(1, 0, 0, 0.5 )));
+    _modelBase->color.Insert( 0.7f, ( glm::vec4(1.f, 1.f, 0, 0.5 )));
+    _modelBase->color.Insert( 1.0f, ( glm::vec4(0, 0, 1.f, 0.5 )));
 
     _modelBase->velocity.Insert( 0.0f, 0.0f );
 
diff --git a/visimpl/DomainManager.h b/visimpl/DomainManager.h
index f1d3ea967948ac6817c4087331fa2341ef6c14fd..b8894d0431255eef68d0efb3af8c02f1a15a0c35 100644
--- a/visimpl/DomainManager.h
+++ b/visimpl/DomainManager.h
@@ -26,6 +26,7 @@
 #include <unordered_map>
 
 #include <prefr/prefr.h>
+#include <prefr/GL/IGLRenderProgram.h>
 #include <simil/simil.h>
 #include <scoop/scoop.h>
 
@@ -59,7 +60,7 @@ namespace visimpl
 #endif
 
 
-    void initializeParticleSystem( void );
+    void initializeParticleSystem( prefr::IGLRenderProgram* program );
 
     VisualGroup* addVisualGroupFromSelection( const std::string& name,
                                               bool overrideGIDs = false );
diff --git a/visimpl/MainWindow.cpp b/visimpl/MainWindow.cpp
index c91646ab6f862c2196d1ba0ab86960fa93bee294..d114bbc1feac056ab85365c4bd84d9162326561b 100644
--- a/visimpl/MainWindow.cpp
+++ b/visimpl/MainWindow.cpp
@@ -70,13 +70,17 @@
 #include <QJsonDocument>
 #include <QJsonObject>
 #include <QJsonArray>
+#include <QMenu>
 
 #include <thread>
+#include <iterator>
 
 #include <sumrice/sumrice.h>
 
 template<class T> void ignore( const T& ) { }
 
+constexpr const char* POSITION_KEY = "positionData";
+
 namespace visimpl
 {
   enum toolIndex
@@ -168,6 +172,10 @@ namespace visimpl
 #else
     _ui->actionOpenBlueConfig->setEnabled( false );
 #endif
+
+    auto positionsMenu = new QMenu();
+    positionsMenu->setTitle("Camera positions");
+    _ui->actionCamera_Positions->setMenu(positionsMenu);
   }
 
   void MainWindow::init( const std::string& zeqUri )
@@ -242,6 +250,18 @@ namespace visimpl
     connect( _openGLWidget , SIGNAL( pickedSingle( unsigned int )) , this ,
              SLOT( updateSelectedStatsPickingSingle( unsigned int )) );
 
+    connect(_ui->actionAdd_camera_position, SIGNAL(triggered(bool)), this,
+             SLOT(addCameraPosition()));
+
+    connect(_ui->actionRemove_camera_position, SIGNAL(triggered(bool)), this,
+             SLOT(removeCameraPosition()));
+
+    connect(_ui->actionLoad_camera_positions, SIGNAL(triggered(bool)), this,
+             SLOT(loadCameraPositions()));
+
+    connect(_ui->actionSave_camera_positions, SIGNAL(triggered(bool)), this,
+             SLOT(saveCameraPositions()));
+
     QAction *actionTogglePause = new QAction( this );
     actionTogglePause->setShortcut( Qt::Key_Space );
 
@@ -510,9 +530,13 @@ namespace visimpl
     if( _recorder != nullptr )
     {
       if(action) action->setDisabled( true );
+      const bool currentlyPlaying = (_openGLWidget && _openGLWidget->player() && _openGLWidget->player()->isPlaying());
+      if(currentlyPlaying) Pause();
 
       RecorderUtils::stopAndWait(_recorder, this);
 
+      if(currentlyPlaying) Play();
+
       // Recorder will be deleted after finishing.
       _recorder = nullptr;
       return;
@@ -2356,10 +2380,10 @@ void MainWindow::clearGroups( void )
 
     const auto contents = file.readAll();
     QJsonParseError jsonError;
-    const auto  jsonDoc = QJsonDocument::fromJson(contents, &jsonError);;
+    const auto  jsonDoc = QJsonDocument::fromJson(contents, &jsonError);
     if(jsonDoc.isNull() || !jsonDoc.isObject())
     {
-      const auto message = tr("Couldn't read the contents of %1 or error at parsing.").arg(fileName);
+      const auto message = tr("Couldn't read the contents of %1 or parsing error.").arg(fileName);
 
       QMessageBox msgbox{this};
       msgbox.setWindowTitle(title);
@@ -2375,7 +2399,7 @@ void MainWindow::clearGroups( void )
     const auto jsonObj = jsonDoc.object();
     if(jsonObj.isEmpty())
     {
-      const auto message = tr("Error at parsing.").arg(fileName);
+      const auto message = tr("Error parsing the contents of %1.").arg(fileName);
 
       QMessageBox msgbox{this};
       msgbox.setWindowTitle(title);
@@ -2598,7 +2622,6 @@ void MainWindow::clearGroups( void )
     obj.insert("groups", groupsObjs);
 
     QJsonDocument doc{obj};
-    const auto temp = doc.toJson().toStdString();
     wFile.write(doc.toJson());
 
     QApplication::restoreOverrideCursor();
@@ -2702,6 +2725,295 @@ void MainWindow::clearGroups( void )
     QMainWindow::closeEvent(e);
   }
 
+  void MainWindow::loadCameraPositions()
+  {
+    const QString title = "Load camera positions";
+
+    auto actions = _ui->actionCamera_Positions->menu()->actions();
+    const auto numActions = actions.size();
+    if(numActions > 0)
+    {
+      const auto warnText = tr("Loading new camera positions will erase"
+                               " %1 existing position%2. Are you sure?").arg(numActions).arg(numActions > 1 ? "s":"");
+      if(QMessageBox::Ok != QMessageBox::warning(this, title, warnText, QMessageBox::Cancel|QMessageBox::Ok))
+        return;
+    }
+
+    const QString nameFilter = "Camera positions (*.json)";
+    QDir directory;
+
+    if(_lastOpenedNetworkFileName.isEmpty())
+      directory = QDir::home();
+    else
+      directory = QFileInfo(_lastOpenedNetworkFileName).dir();
+
+    QFileDialog fDialog(this);
+    fDialog.setWindowIcon(QIcon(":/visimpl.png"));
+    fDialog.setWindowTitle(title);
+    fDialog.setAcceptMode(QFileDialog::AcceptMode::AcceptOpen);
+    fDialog.setDefaultSuffix("json");
+    fDialog.setDirectory(directory);
+    fDialog.setOption(QFileDialog::Option::DontUseNativeDialog, true);
+    fDialog.setFileMode(QFileDialog::FileMode::ExistingFile);
+    fDialog.setNameFilters(QStringList{nameFilter});
+    fDialog.setNameFilter(nameFilter);
+
+    if(fDialog.exec() != QFileDialog::Accepted)
+      return;
+
+    if(fDialog.selectedFiles().empty()) return;
+
+    auto file = fDialog.selectedFiles().first();
+
+    QFile posFile{file};
+    if(!posFile.open(QIODevice::ReadOnly|QIODevice::Text))
+    {
+      const QString errorText = tr("Unable to open: %1").arg(file);
+      QMessageBox::critical(this, title, errorText);
+      return;
+    }
+
+    const auto contents = posFile.readAll();
+    QJsonParseError parserError;
+
+    const auto  jsonDoc = QJsonDocument::fromJson(contents, &parserError);
+    if(jsonDoc.isNull() || !jsonDoc.isObject())
+    {
+      const auto message = tr("Couldn't read the contents of %1 or parsing error.").arg(file);
+
+      QMessageBox msgbox{this};
+      msgbox.setWindowTitle(title);
+      msgbox.setIcon(QMessageBox::Icon::Critical);
+      msgbox.setText(message);
+      msgbox.setWindowIcon(QIcon(":/visimpl.png"));
+      msgbox.setStandardButtons(QMessageBox::Ok);
+      msgbox.setDetailedText(parserError.errorString());
+      msgbox.exec();
+      return;
+    }
+
+    const auto jsonObj = jsonDoc.object();
+    if(jsonObj.isEmpty())
+    {
+      const auto message = tr("Error parsing the contents of %1.").arg(file);
+
+      QMessageBox msgbox{this};
+      msgbox.setWindowTitle(title);
+      msgbox.setIcon(QMessageBox::Icon::Critical);
+      msgbox.setText(message);
+      msgbox.setWindowIcon(QIcon(":/visimpl.png"));
+      msgbox.setStandardButtons(QMessageBox::Ok);
+      msgbox.exec();
+      return;
+    }
+
+    // Clear existing actions before entering new ones.
+    for(auto action: actions)
+    {
+      _ui->actionCamera_Positions->menu()->removeAction(action);
+      delete action;
+    }
+
+    const auto jsonPositions = jsonObj.value("positions").toArray();
+
+    auto createPosition = [this](const QJsonValue &v)
+    {
+      const auto o = v.toObject();
+
+      const auto name = o.value("name").toString();
+      const auto position = o.value("position").toString();
+      const auto radius = o.value("radius").toString();
+      const auto rotation = o.value("rotation").toString();
+
+      auto action = new QAction(name);
+      action->setProperty(POSITION_KEY, position + ";" + radius + ";" + rotation);
+
+      connect(action, SIGNAL(triggered(bool)), this, SLOT(applyCameraPosition()));
+
+      _ui->actionCamera_Positions->menu()->addAction(action);
+    };
+    std::for_each(jsonPositions.constBegin(), jsonPositions.constEnd(), createPosition);
+
+    const bool positionsExist = !_ui->actionCamera_Positions->menu()->actions().isEmpty();
+    _ui->actionSave_camera_positions->setEnabled(positionsExist);
+    _ui->actionRemove_camera_position->setEnabled(positionsExist);
+    _ui->actionCamera_Positions->setEnabled(positionsExist);
+  }
+
+  void MainWindow::saveCameraPositions()
+  {
+    const QString nameFilter = "Camera positions (*.json)";
+    QDir directory;
+
+    if(_lastOpenedNetworkFileName.isEmpty())
+      directory = QDir::home();
+    else
+      directory = QFileInfo(_lastOpenedNetworkFileName).dir();
+
+    QFileDialog fDialog(this);
+    fDialog.setWindowIcon(QIcon(":/visimpl.png"));
+    fDialog.setWindowTitle("Save camera positions");
+    fDialog.setAcceptMode(QFileDialog::AcceptMode::AcceptSave);
+    fDialog.setDefaultSuffix("json");
+    fDialog.setDirectory(directory);
+    fDialog.setOption(QFileDialog::Option::DontUseNativeDialog, true);
+    fDialog.setFileMode(QFileDialog::FileMode::AnyFile);
+    fDialog.setNameFilters(QStringList{nameFilter});
+    fDialog.setNameFilter(nameFilter);
+
+    if(fDialog.exec() != QFileDialog::Accepted)
+      return;
+
+    if(fDialog.selectedFiles().empty()) return;
+
+    const auto filename = fDialog.selectedFiles().first();
+
+    QFile wFile{filename};
+    if(!wFile.open(QIODevice::WriteOnly|QIODevice::Text|QIODevice::Truncate))
+    {
+      const auto message = tr("Unable to open file %1 for writing.").arg(filename);
+
+      QMessageBox msgbox{this};
+      msgbox.setWindowTitle(tr("Save camera positions"));
+      msgbox.setIcon(QMessageBox::Icon::Critical);
+      msgbox.setText(message);
+      msgbox.setWindowIcon(QIcon(":/visimpl.png"));
+      msgbox.setDefaultButton(QMessageBox::Ok);
+      msgbox.exec();
+      return;
+    }
+
+    QApplication::setOverrideCursor(Qt::WaitCursor);
+
+    const auto actions = _ui->actionCamera_Positions->menu()->actions();
+
+    QJsonArray positionsObjs;
+
+    auto insertPosition = [&positionsObjs, this](const QAction *a)
+    {
+      if(!a) return;
+      const auto posData = a->property(POSITION_KEY).toString();
+      const auto parts = posData.split(";");
+      Q_ASSERT(parts.size() == 3);
+      const auto position = parts.first();
+      const auto radius = parts.at(1);
+      const auto rotation = parts.last();
+
+      QJsonObject positionObj;
+      positionObj.insert("name", a->text());
+      positionObj.insert("position", position);
+      positionObj.insert("radius", radius);
+      positionObj.insert("rotation", rotation);
+
+      positionsObjs << positionObj;
+    };
+    std::for_each(actions.cbegin(), actions.cend(), insertPosition);
+
+    QJsonObject obj;
+    obj.insert("positions", positionsObjs);
+
+    QJsonDocument doc{obj};
+    wFile.write(doc.toJson());
+
+    QApplication::restoreOverrideCursor();
+
+    if(wFile.error() != QFile::NoError)
+    {
+      const auto message = tr("Error saving file %1.").arg(filename);
+
+      QMessageBox msgbox{this};
+      msgbox.setWindowTitle(tr("Save camera positions"));
+      msgbox.setIcon(QMessageBox::Icon::Critical);
+      msgbox.setText(message);
+      msgbox.setDetailedText(wFile.errorString());
+      msgbox.setWindowIcon(QIcon(":/visimpl.png"));
+      msgbox.setDefaultButton(QMessageBox::Ok);
+      msgbox.exec();
+    }
+
+    wFile.flush();
+    wFile.close();
+  }
+
+  void MainWindow::addCameraPosition()
+  {
+    QStringList items;
+
+    auto actions = _ui->actionCamera_Positions->menu()->actions();
+    auto insertItemName = [&items](const QAction *a){ items << a->text(); };
+    std::for_each(actions.cbegin(), actions.cend(), insertItemName);
+
+    const QString title = tr("Add camera position");
+
+    bool ok = false;
+    QString name;
+    while(!ok || name.isEmpty())
+    {
+      name = QInputDialog::getText(this, title, tr("Position name:"), QLineEdit::Normal, tr("New position"), &ok);
+
+      if(ok && !name.isEmpty())
+      {
+        QString tempName(name);
+        int collision = 0;
+        while(items.contains(tempName, Qt::CaseInsensitive))
+        {
+          ++collision;
+          tempName = tr("%1 (%2)").arg(name).arg(collision);
+        }
+
+        name = tempName;
+      }
+    }
+
+    auto action = new QAction(name);
+
+    const auto position = _openGLWidget->cameraPosition();
+    action->setProperty(POSITION_KEY, position.toString());
+
+    connect(action, SIGNAL(triggered(bool)), this, SLOT(applyCameraPosition()));
+    _ui->actionCamera_Positions->menu()->addAction(action);
+    _ui->actionCamera_Positions->setEnabled(true);
+    _ui->actionSave_camera_positions->setEnabled(true);
+    _ui->actionRemove_camera_position->setEnabled(true);
+  }
+
+  void MainWindow::removeCameraPosition()
+  {
+    bool ok = false;
+    QStringList items;
+
+    auto actions = _ui->actionCamera_Positions->menu()->actions();
+    auto insertItemName = [&items](const QAction *a){ items << a->text(); };
+    std::for_each(actions.cbegin(), actions.cend(), insertItemName);
+
+    auto item = QInputDialog::getItem(this, tr("Remove camera position"), tr("Position name:"), items, 0, false, &ok);
+    if (ok && !item.isEmpty())
+    {
+      auto actionOfName = [&item](const QAction *a){ return a->text() == item; };
+      const auto it = std::find_if(actions.cbegin(), actions.cend(), actionOfName);
+      auto distance = std::distance(actions.cbegin(), it);
+      auto action = actions.at(distance);
+      _ui->actionCamera_Positions->menu()->removeAction(action);
+      delete action;
+
+      const auto enabled = actions.size() > 1;
+      _ui->actionRemove_camera_position->setEnabled(enabled);
+      _ui->actionSave_camera_positions->setEnabled(enabled);
+      _ui->actionCamera_Positions->setEnabled(enabled);
+    }
+  }
+
+  void MainWindow::applyCameraPosition()
+  {
+    auto action = qobject_cast<QAction *>(sender());
+    if(action)
+    {
+      auto positionString = action->property(POSITION_KEY).toString();
+      CameraPosition position(positionString);
+      _openGLWidget->setCameraPosition(position);
+    }
+  }
+
   void MainWindow::sendZeroEQPlaybackOperation(const unsigned int op)
   {
 #ifdef SIMIL_USE_ZEROEQ
diff --git a/visimpl/MainWindow.h b/visimpl/MainWindow.h
index 943f092c905ee425144b0c0373f591cb4df79c85..f15caaefe88f5acf6abfeb35188d7fdba13a1c96 100644
--- a/visimpl/MainWindow.h
+++ b/visimpl/MainWindow.h
@@ -232,8 +232,36 @@ namespace visimpl
      */
     void changeStackVizToolbarStatus(bool status);
 
+    /** \brief Updates the UI after a recording has finished.
+     *
+     */
     void finishRecording();
 
+    /** \brief Loads camera positions from a file.
+     *
+     */
+    void loadCameraPositions();
+
+    /** \brief Saves camera positions to a file on disk.
+     *
+     */
+    void saveCameraPositions();
+
+    /** \brief Stores current camera position in the positions list.
+     *
+     */
+    void addCameraPosition();
+
+    /** \brief Lets the user select a position to remove from the positions list.
+     *
+     */
+    void removeCameraPosition();
+
+    /** \brief Changes the camera position to the one specified by the user.
+     *
+     */
+    void applyCameraPosition();
+
   protected:
     void _initSimControlDock( void );
     void _initPlaybackDock( void );
diff --git a/visimpl/OpenGLWidget.cpp b/visimpl/OpenGLWidget.cpp
index 6b999cbf83c32d10d2f3d97e341c8bde13508db4..b7bc98789ceae3f98b33cf1235a0450d737342b6 100644
--- a/visimpl/OpenGLWidget.cpp
+++ b/visimpl/OpenGLWidget.cpp
@@ -49,134 +49,176 @@
 #include "prefr/ColorSource.h"
 
 #ifdef SIMIL_USE_BRION
+
 #include <brain/brain.h>
 #include <brion/brion.h>
+#include <QOpenGLDebugLogger>
+
 #endif
 
 #ifdef VISIMPL_USE_ZEROEQ
-  #include <zeroeq/zeroeq.h>
+
+#include <zeroeq/zeroeq.h>
+
 #endif
 
 constexpr float ZOOM_FACTOR = 1.3f;
 constexpr float TRANSLATION_FACTOR = 0.001f;
 constexpr float ROTATION_FACTOR = 0.01f;
+constexpr int FRAMEBUFFER_SCALE_FACTOR = 2;
+constexpr int SAMPLES = 4;
 
 namespace visimpl
 {
   const InitialConfig _initialConfigSimBlueConfig =
-      std::make_tuple( 0.5f, 20.0f, 20.0f, 1.0f );
+    std::make_tuple( 0.5f , 20.0f , 20.0f , 1.0f );
   const InitialConfig _initialConfigSimH5 =
-      std::make_tuple( 0.005f, 20.0f, 0.1f, 500.0f );
+    std::make_tuple( 0.005f , 20.0f , 0.1f , 500.0f );
   const InitialConfig _initialConfigSimCSV =
-        //std::make_tuple( 0.005f, 20.0f, 0.1f, 50000.0f );
-      std::make_tuple( 0.2f, 2.0f, 1.5f, 5.0f );
+    //std::make_tuple( 0.005f, 20.0f, 0.1f, 50000.0f );
+    std::make_tuple( 0.2f , 2.0f , 1.5f , 5.0f );
 
   const InitialConfig _initialConfigSimREST =
-        std::make_tuple( 0.005f, 20.0f, 0.1f, 500.0f );
+    std::make_tuple( 0.005f , 20.0f , 0.1f , 500.0f );
 
   constexpr float invRGBInt = 1.0f / 255;
 
-  OpenGLWidget::OpenGLWidget( QWidget* parent_,
-                              Qt::WindowFlags windowsFlags_,
+  const static std::string vertexShaderCode = R"(#version 330 core
+layout (location = 0) in vec2 aPos;
+layout (location = 1) in vec2 aTexCoords;
+
+out vec2 TexCoords;
+
+void main()
+{
+    gl_Position = vec4(aPos.x, aPos.y, 0.0, 1.0);
+    TexCoords = aTexCoords;
+}
+)";
+
+  const static std::string screenFragment = R"(#version 330 core
+out vec4 FragColor;
+
+in vec2 TexCoords;
+
+uniform sampler2D screenTexture;
+
+void main()
+{
+    FragColor = vec4(texture(screenTexture, TexCoords).rgb, 1);
+}
+)";
+
+
+  OpenGLWidget::OpenGLWidget( QWidget* parent_ ,
+                              Qt::WindowFlags windowsFlags_ ,
                               const std::string&
-  #ifdef VISIMPL_USE_ZEROEQ
+#ifdef VISIMPL_USE_ZEROEQ
                               zeqUri
-  #endif
-    )
-  : QOpenGLWidget( parent_, windowsFlags_ )
-  #ifdef VISIMPL_USE_ZEROEQ
-  , _zeqUri( zeqUri )
-  #endif
-  , _fpsLabel( nullptr )
-  , _labelCurrentTime( nullptr )
-  , _showFps( false )
-  , _showCurrentTime( true )
-  , _wireframe( false )
-  , _camera( nullptr )
-  , _lastCameraPosition( 0, 0, 0)
-  , _scaleFactor( 1.0f, 1.0f, 1.0f )
-  , _scaleFactorExternal( false )
-  , _focusOnSelection( true )
-  , _pendingSelection( false )
-  , _backtrace( false )
-  , _playbackMode( TPlaybackMode::CONTINUOUS )
-  , _frameCount( 0 )
-  , _mouseX( 0 )
-  , _mouseY( 0 )
-  , _rotation( false )
-  , _translation( false )
-  , _idleUpdate( true )
-  , _paint( false )
-  , _currentClearColor( 20, 20, 20, 255 )
-  , _particleRadiusThreshold( 0.8 )
-  , _currentShader( T_SHADER_UNDEFINED )
-  , _shaderParticlesCurrent( nullptr )
-  , _shaderParticlesDefault( nullptr )
-  , _shaderParticlesSolid( nullptr )
-  , _shaderPicking( nullptr )
-  , _shaderClippingPlanes( nullptr )
-  , _particleSystem( nullptr )
-  , _pickRenderer( nullptr )
-  , _simulationType( simil::TSimulationType::TSimNetwork )
-  , _player( nullptr )
-  , m_loader{nullptr}
-  , m_loaderDialog{nullptr}
-  , _clippingPlaneLeft( nullptr )
-  , _clippingPlaneRight( nullptr )
-  , _planeHeight( 1 )
-  , _planeWidth( 1 )
-  , _planeDistance( 20 )
-  , _rotationPlanes( false )
-  , _translationPlanes( false )
-  , _clipping( true )
-  , _paintClippingPlanes( true )
-  , _planesColor( 1.0, 1.0, 1.0, 1.0 )
-  , _deltaTime( 0.0f )
-  , _sbsTimePerStep( 5.0f )
-  , _sbsBeginTime( 0 )
-  , _sbsEndTime( 0 )
-  , _sbsCurrentTime( 0 )
-  , _sbsCurrentRenderDelta( 0 )
-  , _sbsPlaying( false )
-  , _sbsFirstStep( true )
-  , _sbsNextStep( false )
-  , _sbsPrevStep( false )
-  , _simDeltaTime( 0.125f )
-  , _timeStepsPerSecond( 2.0f )
-  , _simTimePerSecond( 0.5f )
-  , _firstFrame( true )
-  , _renderSpeed( 0.0f )
-  , _simPeriod( 0.0f )
-  , _simPeriodMicroseconds( 0.0f )
-  , _renderPeriod( 0.0f )
-  , _renderPeriodMicroseconds( 0.0f )
-  , _sliderUpdatePeriod( 0.25f )
-  , _elapsedTimeRenderAcc( 0.0f )
-  , _elapsedTimeSliderAcc( 0.0f )
-  , _elapsedTimeSimAcc( 0.0f )
-  , _alphaBlendingAccumulative( false )
-  , _showSelection( false )
-  , _flagNewData (false )
-  , _flagResetParticles( false )
-  , _flagUpdateSelection( false )
-  , _flagUpdateGroups( false )
-  , _flagUpdateAttributes( false )
-  , _flagPickingSingle( false )
-  , _flagPickingHighlighted( false )
-  , _flagChangeShader( false )
-  , _flagUpdateRender( false )
-  , _flagModeChange( false )
-  , _newMode( TMODE_UNDEFINED )
-  , _flagAttribChange( false )
-  , _newAttrib( T_TYPE_UNDEFINED )
-  , _currentAttrib( T_TYPE_MORPHO )
-  , _showActiveEvents( true )
-  , _subsetEvents( nullptr )
-  , _deltaEvents( 0.125f )
-  , _domainManager( nullptr )
-  , _selectedPickingSingle( 0 )
-  {
-    _lastCameraPosition = glm::vec3( 0, 0, 0 );
+#endif
+                            )
+    : QOpenGLWidget( parent_ , windowsFlags_ )
+#ifdef VISIMPL_USE_ZEROEQ
+    , _zeqUri( zeqUri )
+#endif
+    , _fpsLabel( nullptr )
+    , _labelCurrentTime( nullptr )
+    , _showFps( false )
+    , _showCurrentTime( true )
+    , _wireframe( false )
+    , _camera( nullptr )
+    , _lastCameraPosition( 0 , 0 , 0 )
+    , _scaleFactor( 1.0f , 1.0f , 1.0f )
+    , _scaleFactorExternal( false )
+    , _focusOnSelection( true )
+    , _pendingSelection( false )
+    , _backtrace( false )
+    , _playbackMode( TPlaybackMode::CONTINUOUS )
+    , _frameCount( 0 )
+    , _mouseX( 0 )
+    , _mouseY( 0 )
+    , _rotation( false )
+    , _translation( false )
+    , _idleUpdate( true )
+    , _paint( false )
+    , _currentClearColor( 20 , 20 , 20 , 255 )
+    , _particleRadiusThreshold( 0.8 )
+    , _currentShader( T_SHADER_UNDEFINED )
+    , _shaderParticlesCurrent( nullptr )
+    , _shaderParticlesDefault( nullptr )
+    , _shaderParticlesSolid( nullptr )
+    , _shaderPicking( nullptr )
+    , _shaderClippingPlanes( nullptr )
+    , _particleSystem( nullptr )
+    , _pickRenderer( nullptr )
+    , _simulationType( simil::TSimulationType::TSimNetwork )
+    , _player( nullptr )
+    , m_loader{ nullptr }
+    , m_loaderDialog{ nullptr }
+    , _clippingPlaneLeft( nullptr )
+    , _clippingPlaneRight( nullptr )
+    , _planeHeight( 1 )
+    , _planeWidth( 1 )
+    , _planeDistance( 20 )
+    , _rotationPlanes( false )
+    , _translationPlanes( false )
+    , _clipping( true )
+    , _paintClippingPlanes( true )
+    , _planesColor( 1.0 , 1.0 , 1.0 , 1.0 )
+    , _deltaTime( 0.0f )
+    , _sbsTimePerStep( 5.0f )
+    , _sbsBeginTime( 0 )
+    , _sbsEndTime( 0 )
+    , _sbsCurrentTime( 0 )
+    , _sbsCurrentRenderDelta( 0 )
+    , _sbsPlaying( false )
+    , _sbsFirstStep( true )
+    , _sbsNextStep( false )
+    , _sbsPrevStep( false )
+    , _simDeltaTime( 0.125f )
+    , _timeStepsPerSecond( 2.0f )
+    , _simTimePerSecond( 0.5f )
+    , _firstFrame( true )
+    , _renderSpeed( 0.0f )
+    , _simPeriod( 0.0f )
+    , _simPeriodMicroseconds( 0.0f )
+    , _renderPeriod( 0.0f )
+    , _renderPeriodMicroseconds( 0.0f )
+    , _sliderUpdatePeriod( 0.25f )
+    , _elapsedTimeRenderAcc( 0.0f )
+    , _elapsedTimeSliderAcc( 0.0f )
+    , _elapsedTimeSimAcc( 0.0f )
+    , _alphaBlendingAccumulative( false )
+    , _showSelection( false )
+    , _flagNewData( false )
+    , _flagResetParticles( false )
+    , _flagUpdateSelection( false )
+    , _flagUpdateGroups( false )
+    , _flagUpdateAttributes( false )
+    , _flagPickingSingle( false )
+    , _flagPickingHighlighted( false )
+    , _flagChangeShader( false )
+    , _flagUpdateRender( false )
+    , _flagModeChange( false )
+    , _newMode( TMODE_UNDEFINED )
+    , _flagAttribChange( false )
+    , _newAttrib( T_TYPE_UNDEFINED )
+    , _currentAttrib( T_TYPE_MORPHO )
+    , _showActiveEvents( true )
+    , _subsetEvents( nullptr )
+    , _deltaEvents( 0.125f )
+    , _domainManager( nullptr )
+    , _selectedPickingSingle( 0 )
+    , _oglFunctions{nullptr}
+    , _screenPlaneShader( nullptr )
+    , _msaaFrameBuffer( 0 )
+    , _msaaTextureColor( 0 )
+    , _msaaRBODepth( 0 )
+    , _midFrameBuffer( 0 )
+    , _midTextureColor( 0 )
+    , _midRBODepth( 0 )
+  {
+    _lastCameraPosition = glm::vec3( 0 , 0 , 0 );
 
     _maxFPS = 60.0f;
     _renderPeriod = 1.0f / _maxFPS;
@@ -196,194 +238,201 @@ namespace visimpl
       "margin: 10px;"
       " border-radius: 10px;}" );
     _fpsLabel->setVisible( _showFps );
-    _fpsLabel->setMaximumSize( 100, 50 );
+    _fpsLabel->setMaximumSize( 100 , 50 );
 
     _labelCurrentTime = new QLabel( );
     _labelCurrentTime->setStyleSheet(
-          "QLabel { background-color : #333;"
-          "color : white;"
-          "padding: 3px;"
-          "margin: 10px;"
-          " border-radius: 10px;}" );
+      "QLabel { background-color : #333;"
+      "color : white;"
+      "padding: 3px;"
+      "margin: 10px;"
+      " border-radius: 10px;}" );
     _labelCurrentTime->setVisible( _showCurrentTime );
-    _labelCurrentTime->setMaximumSize( 100, 50 );
+    _labelCurrentTime->setMaximumSize( 100 , 50 );
 
     _eventLabelsLayout = new QGridLayout( );
     _eventLabelsLayout->setAlignment( Qt::AlignTop );
     _eventLabelsLayout->setMargin( 0 );
     setLayout( _eventLabelsLayout );
-    _eventLabelsLayout->addWidget( _labelCurrentTime, 0, 0, 1, 9 );
-    _eventLabelsLayout->addWidget( _fpsLabel, 1, 0, 1, 9 );
+    _eventLabelsLayout->addWidget( _labelCurrentTime , 0 , 0 , 1 , 9 );
+    _eventLabelsLayout->addWidget( _fpsLabel , 1 , 0 , 1 , 9 );
 
     _colorPalette =
-        scoop::ColorPalette::colorBrewerQualitative(
-            scoop::ColorPalette::ColorBrewerQualitative::Set1, 9 );
+      scoop::ColorPalette::colorBrewerQualitative(
+        scoop::ColorPalette::ColorBrewerQualitative::Set1 , 9 );
 
     // This is needed to get key events
     this->setFocusPolicy( Qt::WheelFocus );
 
 #ifdef VISIMPL_USE_ZEROEQ
-    if ( !_zeqUri.empty( ) )
+    if ( !_zeqUri.empty( ))
     {
       bool failed = false;
       try
       {
-        auto &instance = ZeroEQConfig::instance();
-        if(!instance.isConnected())
+        auto& instance = ZeroEQConfig::instance( );
+        if ( !instance.isConnected( ))
         {
-          instance.connect(_zeqUri);
+          instance.connect( _zeqUri );
         }
 
-        _camera = new Camera( _zeqUri, instance.subscriber() );
+        _camera = new Camera( _zeqUri , instance.subscriber( ));
       }
-      catch(std::exception &e)
+      catch ( std::exception& e )
       {
-        std::cerr << e.what() << " " << __FILE__ << ":" << __LINE__ << std::endl;
+        std::cerr << e.what( ) << " " << __FILE__ << ":" << __LINE__
+                  << std::endl;
         failed = true;
       }
-      catch(...)
+      catch ( ... )
       {
-        std::cerr << "Unknown exception catched when initializing camera. " << __FILE__ << ":" << __LINE__ << std::endl;
+        std::cerr << "Unknown exception catched when initializing camera. "
+                  << __FILE__ << ":" << __LINE__ << std::endl;
         failed = true;
       }
 
-      if(failed)
+      if ( failed )
       {
         _camera = nullptr;
-        _zeqUri.clear();
+        _zeqUri.clear( );
       }
     }
 #endif
 
-    if(!_camera)
+    if ( !_camera )
       _camera = new Camera( );
 
-    _camera->camera()->farPlane( 100000.f );
-
-    setAutoFillBackground(true);
-    setPalette(QPalette(QPalette::Window, Qt::black));
+    setAutoFillBackground( true );
+    setPalette( QPalette( QPalette::Window , Qt::black ));
   }
 
   OpenGLWidget::~OpenGLWidget( void )
   {
-    if( _camera )
+    if ( _camera )
       delete _camera;
 
-    if( _shaderParticlesDefault )
+    if ( _shaderParticlesDefault )
       delete _shaderParticlesDefault;
 
-    if( _shaderParticlesSolid )
+    if ( _shaderParticlesSolid )
       delete _shaderParticlesSolid;
 
-    if( _shaderPicking )
+    if ( _shaderPicking )
       delete _shaderPicking;
 
-    if( _particleSystem )
+    if ( _particleSystem )
       delete _particleSystem;
 
-    if( _player )
+    if ( _player )
       delete _player;
 
     m_loader = nullptr;
-    closeLoadingDialog();
+    closeLoadingDialog( );
   }
 
-  void OpenGLWidget::loadData( const std::string& fileName,
-                               const simil::TDataType fileType,
-                               simil::TSimulationType simulationType,
-                               const std::string& report)
+  void OpenGLWidget::loadData( const std::string& fileName ,
+                               const simil::TDataType fileType ,
+                               simil::TSimulationType simulationType ,
+                               const std::string& report )
   {
     m_loader = nullptr;
-    closeLoadingDialog();
+    closeLoadingDialog( );
 
     _simulationType = simulationType;
 
-    m_loaderDialog = new LoadingDialog(this);
-    m_loaderDialog->show();
+    m_loaderDialog = new LoadingDialog( this );
+    m_loaderDialog->show( );
 
-    QApplication::processEvents();
+    QApplication::processEvents( );
 
-    m_loader = std::make_shared<LoaderThread>();
-    m_loader->setData(fileType, fileName, report);
+    m_loader = std::make_shared< LoaderThread >( );
+    m_loader->setData( fileType , fileName , report );
 
-    connect(m_loader.get(), SIGNAL(finished()),            this,           SLOT(onLoaderFinished()));
-    connect(m_loader.get(), SIGNAL(progress(int)),         m_loaderDialog, SLOT(setProgress(int)));
-    connect(m_loader.get(), SIGNAL(network(unsigned int)), m_loaderDialog, SLOT(setNetwork(unsigned int)));
-    connect(m_loader.get(), SIGNAL(spikes(unsigned int)),  m_loaderDialog, SLOT(setSpikesValue(unsigned int)));
+    connect( m_loader.get( ) , SIGNAL( finished( )) , this ,
+             SLOT( onLoaderFinished( )) );
+    connect( m_loader.get( ) , SIGNAL( progress( int )) , m_loaderDialog ,
+             SLOT( setProgress( int )) );
+    connect( m_loader.get( ) , SIGNAL( network( unsigned int )) ,
+             m_loaderDialog , SLOT( setNetwork( unsigned int )) );
+    connect( m_loader.get( ) , SIGNAL( spikes( unsigned int )) ,
+             m_loaderDialog , SLOT( setSpikesValue( unsigned int )) );
 
-    m_loader->start();
+    m_loader->start( );
   }
 
-  void OpenGLWidget::onLoaderFinished()
+  void OpenGLWidget::onLoaderFinished( )
   {
     makeCurrent( );
 
     _deltaTime = 0.5f;
 
-    if(m_loader)
+    if ( m_loader )
     {
-      const auto error = m_loader->errors();
-      if(!error.empty())
+      const auto error = m_loader->errors( );
+      if ( !error.empty( ))
       {
-        closeLoadingDialog();
-        QApplication::restoreOverrideCursor();
+        closeLoadingDialog( );
+        QApplication::restoreOverrideCursor( );
 
-        const auto message = QString::fromStdString(error);
-        QMessageBox::critical(this, tr("Error loading data"), message, QMessageBox::Ok);
+        const auto message = QString::fromStdString( error );
+        QMessageBox::critical( this , tr( "Error loading data" ) , message ,
+                               QMessageBox::Ok );
 
         m_loader = nullptr;
         return;
       }
     }
 
-    const auto dataType = m_loader->type();
+    const auto dataType = m_loader->type( );
 
-    switch(dataType)
+    switch ( dataType )
     {
       case simil::TBlueConfig:
       case simil::TCSV:
       case simil::THDF5:
-        {
-          const auto spikeData = m_loader->simulationData();
+      {
+        const auto spikeData = m_loader->simulationData( );
 
-          _player = new simil::SpikesPlayer();
-          _player->LoadData(spikeData);
+        _player = new simil::SpikesPlayer( );
+        _player->LoadData( spikeData );
 
-          m_loader = nullptr;
-        }
+        m_loader = nullptr;
+      }
         break;
       case simil::TREST:
-        {
-          const auto netData = m_loader->network();
-          const auto simData = m_loader->simulationData();
+      {
+        const auto netData = m_loader->network( );
+        const auto simData = m_loader->simulationData( );
 
-          _player = new simil::SpikesPlayer();
-          _player->LoadData(netData, simData);
+        _player = new simil::SpikesPlayer( );
+        _player->LoadData( netData , simData );
 
-          // NOTE: loader doesn't get destroyed because has a loop for getting data.
-        }
+        // NOTE: loader doesn't get destroyed because has a loop for getting data.
+      }
         break;
       case simil::TDataUndefined:
       default:
-        {
-          m_loader = nullptr;
-          closeLoadingDialog();
-          QMessageBox::critical(this, tr("Error loading data"), tr("Data type is undefined after loading"), QMessageBox::Ok);
+      {
+        m_loader = nullptr;
+        closeLoadingDialog( );
+        QMessageBox::critical( this , tr( "Error loading data" ) ,
+                               tr( "Data type is undefined after loading" ) ,
+                               QMessageBox::Ok );
 
-          return;
-        }
+        return;
+      }
         break;
     }
 
-    if(m_loaderDialog)
+    if ( m_loaderDialog )
     {
-      m_loaderDialog->setNetwork(_player->gidsSize());
-      m_loaderDialog->setSpikesValue(_player->spikesSize());
-      m_loaderDialog->repaint();
+      m_loaderDialog->setNetwork( _player->gidsSize( ));
+      m_loaderDialog->setSpikesValue( _player->spikesSize( ));
+      m_loaderDialog->repaint( );
     }
 
     InitialConfig config;
-    switch (dataType)
+    switch ( dataType )
     {
       case simil::TBlueConfig:
         config = _initialConfigSimBlueConfig;
@@ -401,10 +450,10 @@ namespace visimpl
         break;
     }
 
-    if( !_scaleFactorExternal )
+    if ( !_scaleFactorExternal )
     {
       const auto scale = std::get< T_SCALE >( config );
-      _scaleFactor = vec3( scale, scale, scale );
+      _scaleFactor = vec3( scale , scale , scale );
     }
 
     std::cout << "Using scale factor of " << _scaleFactor.x
@@ -412,42 +461,44 @@ namespace visimpl
               << ", " << _scaleFactor.z
               << std::endl;
 
-    createParticleSystem(  );
+    createParticleSystem( );
+    _initRenderToTexture( );
 
-    simulationDeltaTime( std::get< T_DELTATIME >( config ) );
-    simulationStepsPerSecond( std::get< T_STEPS_PER_SEC >( config ) );
-    changeSimulationDecayValue( std::get< T_DECAY >( config ) );
+    simulationDeltaTime( std::get< T_DELTATIME >( config ));
+    simulationStepsPerSecond( std::get< T_STEPS_PER_SEC >( config ));
+    changeSimulationDecayValue( std::get< T_DECAY >( config ));
 
 #ifdef VISIMPL_USE_ZEROEQ
-  if( !_zeqUri.empty( ))
-  {
-    try
+    if ( !_zeqUri.empty( ))
     {
-      auto &instance = ZeroEQConfig::instance();
-      if(!instance.isConnected())
+      try
       {
-        instance.connect(_zeqUri);
-      }
+        auto& instance = ZeroEQConfig::instance( );
+        if ( !instance.isConnected( ))
+        {
+          instance.connect( _zeqUri );
+        }
 
-      _player->connectZeq(instance.subscriber(), instance.publisher());
-      instance.startReceiveLoop();
-    }
-    catch(std::exception &e)
-    {
-      std::cerr << "Exception when initializing ZeroEQ. ";
-      std::cerr << e.what() << __FILE__ << ":" << __LINE__ << std::endl;
-    }
-    catch(...)
-    {
-      std::cerr << "Unknown exception when initializing ZeroEQ. " << __FILE__ << ":" << __LINE__ << std::endl;
+        _player->connectZeq( instance.subscriber( ) , instance.publisher( ));
+        instance.startReceiveLoop( );
+      }
+      catch ( std::exception& e )
+      {
+        std::cerr << "Exception when initializing ZeroEQ. ";
+        std::cerr << e.what( ) << __FILE__ << ":" << __LINE__ << std::endl;
+      }
+      catch ( ... )
+      {
+        std::cerr << "Unknown exception when initializing ZeroEQ. " << __FILE__
+                  << ":" << __LINE__ << std::endl;
+      }
     }
-  }
 #endif
 
     this->_paint = true;
     update( );
 
-    emit dataLoaded();
+    emit dataLoaded( );
   }
 
   void OpenGLWidget::initializeGL( void )
@@ -455,9 +506,9 @@ namespace visimpl
     initializeOpenGLFunctions( );
 
     glEnable( GL_DEPTH_TEST );
-    glClearColor( float( _currentClearColor.red( )) / 255.0f,
-                  float( _currentClearColor.green( )) / 255.0f,
-                  float( _currentClearColor.blue( )) / 255.0f,
+    glClearColor( float( _currentClearColor.red( )) / 255.0f ,
+                  float( _currentClearColor.green( )) / 255.0f ,
+                  float( _currentClearColor.blue( )) / 255.0f ,
                   float( _currentClearColor.alpha( )) / 255.0f );
     glPolygonMode( GL_FRONT_AND_BACK , GL_FILL );
     glEnable( GL_CULL_FACE );
@@ -470,14 +521,99 @@ namespace visimpl
     QOpenGLWidget::initializeGL( );
   }
 
+  void OpenGLWidget::_initRenderToTexture( void )
+  {
+    _oglFunctions = context( )->versionFunctions< QOpenGLFunctions_4_0_Core >( );
+    _oglFunctions->initializeOpenGLFunctions( );
+
+    _screenPlaneShader = new reto::ShaderProgram( );
+    _screenPlaneShader->loadVertexShaderFromText( vertexShaderCode );
+    _screenPlaneShader->loadFragmentShaderFromText( screenFragment );
+    _screenPlaneShader->create( );
+    _screenPlaneShader->link( );
+    _screenPlaneShader->autocatching( true );
+    _screenPlaneShader->use( );
+    _screenPlaneShader->sendUniformi( "screenTexture" , 0 );
+
+    // Generate the MSAA framebuffer
+
+    glGenFramebuffers( 1 , &_msaaFrameBuffer );
+    glBindFramebuffer( GL_FRAMEBUFFER , _msaaFrameBuffer );
+
+    glGenTextures( 1 , &_msaaTextureColor );
+    glBindTexture( GL_TEXTURE_2D_MULTISAMPLE , _msaaTextureColor );
+
+    _oglFunctions->glTexImage2DMultisample(
+      GL_TEXTURE_2D_MULTISAMPLE , SAMPLES , GL_RGB ,
+      width( ) * FRAMEBUFFER_SCALE_FACTOR ,
+      height( ) * FRAMEBUFFER_SCALE_FACTOR ,
+      GL_TRUE
+    );
+
+    glBindTexture( GL_TEXTURE_2D_MULTISAMPLE , 0 );
+
+    glFramebufferTexture2D( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 ,
+                            GL_TEXTURE_2D_MULTISAMPLE , _msaaTextureColor , 0 );
+
+
+    glGenRenderbuffers( 1 , &_msaaRBODepth );
+    glBindRenderbuffer( GL_RENDERBUFFER , _msaaRBODepth );
+    _oglFunctions->glRenderbufferStorageMultisample(
+      GL_RENDERBUFFER , SAMPLES , GL_DEPTH_COMPONENT32 ,
+      width( ) * FRAMEBUFFER_SCALE_FACTOR ,
+      height( ) * FRAMEBUFFER_SCALE_FACTOR );
+    glBindRenderbuffer( GL_RENDERBUFFER , 0 );
+
+    glFramebufferRenderbuffer( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT ,
+                               GL_RENDERBUFFER , _msaaRBODepth );
+
+    if ( glCheckFramebufferStatus( GL_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE )
+      std::cerr << "ERROR::FRAMEBUFFER:: Framebuffer is not complete!"
+                << std::endl;
+
+    // Generate the mid framebuffer.
+
+    glGenFramebuffers( 1 , &_midFrameBuffer );
+    glBindFramebuffer( GL_FRAMEBUFFER , _midFrameBuffer );
+
+    glGenTextures( 1 , &_midTextureColor );
+    glBindTexture( GL_TEXTURE_2D , _midTextureColor );
+    glTexImage2D( GL_TEXTURE_2D , 0 , GL_RGB ,
+                  width( ) * FRAMEBUFFER_SCALE_FACTOR ,
+                  height( ) * FRAMEBUFFER_SCALE_FACTOR ,
+                  0 ,
+                  GL_RGB , GL_UNSIGNED_BYTE , nullptr );
+    glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_LINEAR );
+    glTexParameteri( GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_LINEAR );
+    glBindTexture( GL_TEXTURE_2D , 0 );
+    glFramebufferTexture2D( GL_FRAMEBUFFER , GL_COLOR_ATTACHMENT0 ,
+                            GL_TEXTURE_2D , _midTextureColor , 0 );
+
+    glGenRenderbuffers( 1 , &_midRBODepth );
+    glBindRenderbuffer( GL_RENDERBUFFER , _midRBODepth );
+    glRenderbufferStorage( GL_RENDERBUFFER , GL_DEPTH_COMPONENT32 ,
+                           width( ) * FRAMEBUFFER_SCALE_FACTOR ,
+                           height( ) * FRAMEBUFFER_SCALE_FACTOR );
+    glBindRenderbuffer( GL_RENDERBUFFER , 0 );
+
+    glFramebufferRenderbuffer( GL_FRAMEBUFFER , GL_DEPTH_ATTACHMENT ,
+                               GL_RENDERBUFFER , _midRBODepth );
+
+    if ( glCheckFramebufferStatus( GL_FRAMEBUFFER ) != GL_FRAMEBUFFER_COMPLETE )
+      std::cerr << "ERROR::FRAMEBUFFER:: Mid Framebuffer is not complete!"
+                << std::endl;
+
+    glBindFramebuffer( GL_FRAMEBUFFER , defaultFramebufferObject( ));
+  }
+
   void OpenGLWidget::_configureSimulationFrame( void )
   {
-    if( !_player || !_player->isPlaying( ) || !_particleSystem->run( ))
+    if ( !_player || !_player->isPlaying( ) || !_particleSystem->run( ))
       return;
 
     const float prevTime = _player->currentTime( );
 
-    if( _backtrace )
+    if ( _backtrace )
     {
       _backtraceSimulation( );
       _backtrace = false;
@@ -487,31 +623,32 @@ namespace visimpl
 
     const float currentTime = _player->currentTime( );
 
-    _domainManager->processInput( _player->spikesNow( ), prevTime,
-                             currentTime, false );
+    _domainManager->processInput( _player->spikesNow( ) , prevTime ,
+                                  currentTime , false );
   }
 
   void OpenGLWidget::_configurePreviousStep( void )
   {
-    if( !_player || !_particleSystem->run( ))
+    if ( !_player || !_particleSystem->run( ))
       return;
 
     _sbsBeginTime = _sbsFirstStep ?
-                    _player->currentTime( ):
+                    _player->currentTime( ) :
                     _sbsPlaying ? _sbsBeginTime : _sbsEndTime;
 
-    _sbsBeginTime = std::max( static_cast<double>(_player->startTime( )),
-                              _sbsBeginTime - static_cast<double>(_player->deltaTime( )));
+    _sbsBeginTime = std::max( static_cast<double>(_player->startTime( )) ,
+                              _sbsBeginTime -
+                              static_cast<double>(_player->deltaTime( )));
 
     _sbsEndTime = _sbsBeginTime + _player->deltaTime( );
 
-    if(_sbsBeginTime < _sbsEndTime)
+    if ( _sbsBeginTime < _sbsEndTime )
     {
       _player->GoTo( _sbsBeginTime );
 
       _backtraceSimulation( );
 
-      _sbsStepSpikes = _player->spikesBetween( _sbsBeginTime, _sbsEndTime );
+      _sbsStepSpikes = _player->spikesBetween( _sbsBeginTime , _sbsEndTime );
 
       _sbsCurrentTime = _sbsBeginTime;
       _sbsCurrentSpike = _sbsStepSpikes.first;
@@ -523,21 +660,21 @@ namespace visimpl
 
   void OpenGLWidget::_configureStepByStep( void )
   {
-    if( !_player || ! _player->isPlaying( ) || !_particleSystem->run( ))
+    if ( !_player || !_player->isPlaying( ) || !_particleSystem->run( ))
       return;
 
     _sbsBeginTime = _sbsFirstStep ? _player->currentTime( ) : _sbsEndTime;
 
     _sbsEndTime = _sbsBeginTime + _player->deltaTime( );
 
-    if( _sbsPlaying )
+    if ( _sbsPlaying )
     {
       _player->GoTo( _sbsBeginTime );
 
       _backtraceSimulation( );
     }
 
-    _sbsStepSpikes = _player->spikesBetween( _sbsBeginTime, _sbsEndTime );
+    _sbsStepSpikes = _player->spikesBetween( _sbsBeginTime , _sbsEndTime );
 
     _sbsCurrentTime = _sbsBeginTime;
     _sbsCurrentSpike = _sbsStepSpikes.first;
@@ -550,7 +687,7 @@ namespace visimpl
   {
     _sbsCurrentRenderDelta = 0;
 
-    if( _sbsPlaying && _sbsCurrentTime >= _sbsEndTime )
+    if ( _sbsPlaying && _sbsCurrentTime >= _sbsEndTime )
     {
       _sbsPlaying = false;
       _player->GoTo( _sbsEndTime );
@@ -558,25 +695,29 @@ namespace visimpl
       emit stepCompleted( );
     }
 
-    if( _sbsPlaying )
+    if ( _sbsPlaying )
     {
       double diff = _sbsEndTime - _sbsCurrentTime;
-      double renderDelta  = elapsedRenderTime * _sbsInvTimePerStep * _player->deltaTime( );
-      _sbsCurrentRenderDelta = std::min( diff, renderDelta );
+      double renderDelta =
+        elapsedRenderTime * _sbsInvTimePerStep * _player->deltaTime( );
+      _sbsCurrentRenderDelta = std::min( diff , renderDelta );
 
       double nextTime = _sbsCurrentTime + _sbsCurrentRenderDelta;
 
       auto spikeIt = _sbsCurrentSpike;
-      while( spikeIt->first < nextTime  &&
-             spikeIt - _sbsStepSpikes.first < _sbsStepSpikes.second - _sbsStepSpikes.first )
+      while ( spikeIt->first < nextTime &&
+              spikeIt - _sbsStepSpikes.first <
+              _sbsStepSpikes.second - _sbsStepSpikes.first )
       {
         ++spikeIt;
       }
 
-      if( spikeIt != _sbsCurrentSpike )
+      if ( spikeIt != _sbsCurrentSpike )
       {
-        simil::SpikesCRange frameSpikes = std::make_pair( _sbsCurrentSpike, spikeIt );
-        _domainManager->processInput( frameSpikes, _sbsCurrentTime, nextTime, false );
+        simil::SpikesCRange frameSpikes = std::make_pair( _sbsCurrentSpike ,
+                                                          spikeIt );
+        _domainManager->processInput( frameSpikes , _sbsCurrentTime , nextTime ,
+                                      false );
       }
 
       _sbsCurrentTime = nextTime;
@@ -587,19 +728,19 @@ namespace visimpl
   void OpenGLWidget::_backtraceSimulation( void )
   {
     float endTime = _player->currentTime( );
-    float startTime = std::max( 0.0f, endTime - _domainManager->decay( ));
-    if(startTime < endTime)
+    float startTime = std::max( 0.0f , endTime - _domainManager->decay( ));
+    if ( startTime < endTime )
     {
-      const auto context = _player->spikesBetween( startTime, endTime );
+      const auto context = _player->spikesBetween( startTime , endTime );
 
-      if( context.first != context.second )
-        _domainManager->processInput( context, startTime, endTime, true );
+      if ( context.first != context.second )
+        _domainManager->processInput( context , startTime , endTime , true );
     }
   }
 
   void OpenGLWidget::changeShader( int shaderIndex )
   {
-    if( shaderIndex < 0 || shaderIndex >= ( int ) T_SHADER_UNDEFINED )
+    if ( shaderIndex < 0 || shaderIndex >= ( int ) T_SHADER_UNDEFINED )
       return;
 
     _currentShader = ( tShaderParticlesType ) shaderIndex;
@@ -608,20 +749,31 @@ namespace visimpl
 
   void OpenGLWidget::_setShaderParticles( void )
   {
-    if( _currentShader == T_SHADER_UNDEFINED )
+    if ( _currentShader == T_SHADER_UNDEFINED )
       return;
 
-    switch( _currentShader )
+    switch ( _currentShader )
     {
       case T_SHADER_DEFAULT:
         _shaderParticlesCurrent = _shaderParticlesDefault;
         break;
       case T_SHADER_SOLID:
         _shaderParticlesCurrent = _shaderParticlesSolid;
+        _shaderParticlesCurrent->use( );
+        _shaderParticlesCurrent->sendUniformf( "radiusThreshold" ,
+                                               _particleRadiusThreshold );
         break;
       default:
         break;
     }
+
+    auto render = _particleSystem->renderer( );
+    auto glRender = dynamic_cast<prefr::GLAbstractRenderer*>(render);
+
+    if ( glRender != nullptr )
+    {
+      glRender->setRenderProgram( _shaderParticlesCurrent );
+    }
   }
 
   void OpenGLWidget::createParticleSystem( )
@@ -631,105 +783,127 @@ namespace visimpl
 
     // For debugging purposes only
     bool success = false;
-    const auto shadersFile = std::getenv("VISIMPL_SHADERS_FILE");
-    if(shadersFile)
+    const auto shadersFile = std::getenv( "VISIMPL_SHADERS_FILE" );
+    if ( shadersFile )
     {
-      QFile sFile{QString::fromLocal8Bit(shadersFile)};
-      if(sFile.open(QIODevice::ReadOnly|QIODevice::Text))
+      QFile sFile{ QString::fromLocal8Bit( shadersFile ) };
+      if ( sFile.open( QIODevice::ReadOnly | QIODevice::Text ))
       {
-        const auto contents = sFile.readAll();
-        const auto shaders = contents.split('@');
+        const auto contents = sFile.readAll( );
+        const auto shaders = contents.split( '@' );
 
-        if(shaders.size() == 7)
+        if ( shaders.size( ) == 7 )
         {
-          bool shadersSuccess[4]{true, true, true, true};
-          auto prefrVertexShader = std::string(shaders.at(0).data(), shaders.at(0).size());
-
-          _shaderParticlesDefault = new reto::ShaderProgram( );
-          shadersSuccess[0] &= _shaderParticlesDefault->loadVertexShaderFromText( std::string(shaders.at(0).data(), shaders.at(0).size()) );
-          shadersSuccess[0] &= _shaderParticlesDefault->loadFragmentShaderFromText( std::string(shaders.at(1).data(), shaders.at(1).size()) );
-          shadersSuccess[0] &= _shaderParticlesDefault->compileAndLink( );
+          bool shadersSuccess[4]{ true , true , true , true };
+          auto prefrVertexShader = std::string( shaders.at( 0 ).data( ) ,
+                                                shaders.at( 0 ).size( ));
+
+          _shaderParticlesDefault = new prefr::RenderProgram( );
+          shadersSuccess[ 0 ] &= _shaderParticlesDefault->loadVertexShaderFromText(
+            std::string( shaders.at( 0 ).data( ) , shaders.at( 0 ).size( )));
+          shadersSuccess[ 0 ] &= _shaderParticlesDefault->loadFragmentShaderFromText(
+            std::string( shaders.at( 1 ).data( ) , shaders.at( 1 ).size( )));
+          shadersSuccess[ 0 ] &= _shaderParticlesDefault->compileAndLink( );
           _shaderParticlesDefault->autocatching( );
 
-          if(!shadersSuccess[0])
+          if ( !shadersSuccess[ 0 ] )
           {
-            std::cout << "shaders failed at _shaderParticlesDefault." << __FILE__ << ":" << __LINE__ << std::endl;
+            std::cout << "shaders failed at _shaderParticlesDefault."
+                      << __FILE__ << ":" << __LINE__ << std::endl;
           }
 
           _shaderParticlesCurrent = _shaderParticlesDefault;
           _currentShader = T_SHADER_DEFAULT;
 
-          _shaderParticlesSolid = new reto::ShaderProgram( );
-          shadersSuccess[1] &= _shaderParticlesSolid->loadVertexShaderFromText( std::string(shaders.at(0).data(), shaders.at(0).size()) );
-          shadersSuccess[1] &= _shaderParticlesSolid->loadFragmentShaderFromText( std::string(shaders.at(2).data(), shaders.at(2).size()) );
-          shadersSuccess[1] &= _shaderParticlesSolid->compileAndLink( );
+          _shaderParticlesSolid = new prefr::RenderProgram( );
+          shadersSuccess[ 1 ] &= _shaderParticlesSolid->loadVertexShaderFromText(
+            std::string( shaders.at( 0 ).data( ) , shaders.at( 0 ).size( )));
+          shadersSuccess[ 1 ] &= _shaderParticlesSolid->loadFragmentShaderFromText(
+            std::string( shaders.at( 2 ).data( ) , shaders.at( 2 ).size( )));
+          shadersSuccess[ 1 ] &= _shaderParticlesSolid->compileAndLink( );
           _shaderParticlesSolid->autocatching( );
 
-          if(!shadersSuccess[1])
+          if ( !shadersSuccess[ 1 ] )
           {
-            std::cout << "shaders failed at _shaderParticlesSolid." << __FILE__ << ":" << __LINE__ << std::endl;
+            std::cout << "shaders failed at _shaderParticlesSolid." << __FILE__
+                      << ":" << __LINE__ << std::endl;
           }
 
           _shaderPicking = new prefr::RenderProgram( );
-          shadersSuccess[2] &= _shaderPicking->loadVertexShaderFromText( std::string(shaders.at(3).data(), shaders.at(3).size()) );
-          shadersSuccess[2] &= _shaderPicking->loadFragmentShaderFromText( std::string(shaders.at(4).data(), shaders.at(4).size()) );
-          shadersSuccess[2] &= _shaderPicking->compileAndLink( );
+          shadersSuccess[ 2 ] &= _shaderPicking->loadVertexShaderFromText(
+            std::string( shaders.at( 3 ).data( ) , shaders.at( 3 ).size( )));
+          shadersSuccess[ 2 ] &= _shaderPicking->loadFragmentShaderFromText(
+            std::string( shaders.at( 4 ).data( ) , shaders.at( 4 ).size( )));
+          shadersSuccess[ 2 ] &= _shaderPicking->compileAndLink( );
 
-          if(!shadersSuccess[2])
+          if ( !shadersSuccess[ 2 ] )
           {
-            std::cout << "shaders failed at _shaderPicking." << __FILE__ << ":" << __LINE__ << std::endl;
+            std::cout << "shaders failed at _shaderPicking." << __FILE__ << ":"
+                      << __LINE__ << std::endl;
           }
 
-          _shaderClippingPlanes = new reto::ShaderProgram( );
-          shadersSuccess[3] &= _shaderClippingPlanes->loadVertexShaderFromText( std::string(shaders.at(5).data(), shaders.at(5).size()) );
-          shadersSuccess[3] &= _shaderClippingPlanes->loadFragmentShaderFromText( std::string(shaders.at(6).data(), shaders.at(6).size()) );
-          shadersSuccess[3] &= _shaderClippingPlanes->compileAndLink( );
+          _shaderClippingPlanes = new prefr::RenderProgram( );
+          shadersSuccess[ 3 ] &= _shaderClippingPlanes->loadVertexShaderFromText(
+            std::string( shaders.at( 5 ).data( ) , shaders.at( 5 ).size( )));
+          shadersSuccess[ 3 ] &= _shaderClippingPlanes->loadFragmentShaderFromText(
+            std::string( shaders.at( 6 ).data( ) , shaders.at( 6 ).size( )));
+          shadersSuccess[ 3 ] &= _shaderClippingPlanes->compileAndLink( );
           _shaderClippingPlanes->autocatching( );
 
-          if(!shadersSuccess[3])
+          if ( !shadersSuccess[ 3 ] )
           {
-            std::cout << "shaders failed at _shaderClippingPlanes." << __FILE__ << ":" << __LINE__ << std::endl;
+            std::cout << "shaders failed at _shaderClippingPlanes." << __FILE__
+                      << ":" << __LINE__ << std::endl;
           }
 
-          if(shadersSuccess[0] && shadersSuccess[1] && shadersSuccess[2] && shadersSuccess[3])
+          if ( shadersSuccess[ 0 ] && shadersSuccess[ 1 ] &&
+               shadersSuccess[ 2 ] && shadersSuccess[ 3 ] )
           {
             success = true;
-            std::cout << "Loaded shaders from: " << sFile.fileName().toStdString() << std::endl;
+            std::cout << "Loaded shaders from: "
+                      << sFile.fileName( ).toStdString( ) << std::endl;
           }
         }
       }
       else
       {
-        std::cerr << "Unable to read " << sFile.fileName().toStdString() << " reverting to default shaders.";
+        std::cerr << "Unable to read " << sFile.fileName( ).toStdString( )
+                  << " reverting to default shaders.";
       }
     }
 
-    if(!success)
+    if ( !success )
     {
       // Default shaders.
 
       // Initialize shader
-      _shaderParticlesDefault = new reto::ShaderProgram( );
-      _shaderParticlesDefault->loadVertexShaderFromText( prefr::prefrVertexShader );
-      _shaderParticlesDefault->loadFragmentShaderFromText( prefr::prefrFragmentShaderDefault );
+      _shaderParticlesDefault = new prefr::RenderProgram( );
+      _shaderParticlesDefault->loadVertexShaderFromText(
+        prefr::prefrVertexShader );
+      _shaderParticlesDefault->loadFragmentShaderFromText(
+        prefr::prefrFragmentShaderDefault );
       _shaderParticlesDefault->compileAndLink( );
       _shaderParticlesDefault->autocatching( );
 
       _shaderParticlesCurrent = _shaderParticlesDefault;
       _currentShader = T_SHADER_DEFAULT;
 
-      _shaderParticlesSolid = new reto::ShaderProgram( );
-      _shaderParticlesSolid->loadVertexShaderFromText( prefr::prefrVertexShader );
-      _shaderParticlesSolid->loadFragmentShaderFromText( prefr::prefrFragmentShaderSolid );
+      _shaderParticlesSolid = new prefr::RenderProgram( );
+      _shaderParticlesSolid->loadVertexShaderFromText(
+        prefr::prefrVertexShader );
+      _shaderParticlesSolid->loadFragmentShaderFromText(
+        prefr::prefrFragmentShaderSolid );
       _shaderParticlesSolid->compileAndLink( );
       _shaderParticlesSolid->autocatching( );
 
       _shaderPicking = new prefr::RenderProgram( );
-      _shaderPicking->loadVertexShaderFromText( prefr::prefrVertexShaderPicking );
-      _shaderPicking->loadFragmentShaderFromText( prefr::prefrFragmentShaderPicking );
+      _shaderPicking->loadVertexShaderFromText(
+        prefr::prefrVertexShaderPicking );
+      _shaderPicking->loadFragmentShaderFromText(
+        prefr::prefrFragmentShaderPicking );
       _shaderPicking->compileAndLink( );
 
-      _shaderClippingPlanes = new reto::ShaderProgram( );
+      _shaderClippingPlanes = new prefr::RenderProgram( );
       _shaderClippingPlanes->loadVertexShaderFromText( prefr::planeVertCode );
       _shaderClippingPlanes->loadFragmentShaderFromText( prefr::planeFragCode );
       _shaderClippingPlanes->compileAndLink( );
@@ -739,26 +913,29 @@ namespace visimpl
     }
 
     const unsigned int maxParticles =
-        std::max(100000u, static_cast<unsigned int>( _player->gids( ).size( )));
+      std::max( 100000u , static_cast<unsigned int>( _player->gids( ).size( )));
 
-    _updateData();
-    _particleSystem = new prefr::ParticleSystem( maxParticles, _camera );
+    _updateData( );
+    _particleSystem = new prefr::ParticleSystem( maxParticles , _camera );
     _flagResetParticles = true;
 
-    _domainManager = new DomainManager( _particleSystem, _player->gids());
+    _domainManager = new DomainManager( _particleSystem , _player->gids( ));
 #ifdef SIMIL_USE_BRION
-      _domainManager->init( _gidPositions, _player->data( )->blueConfig( ));
+    _domainManager->init( _gidPositions , _player->data( )->blueConfig( ));
 #else
-      _domainManager->init( _gidPositions );
+    _domainManager->init( _gidPositions );
 #endif
-    _domainManager->initializeParticleSystem( );
-    _domainManager->updateData( _player->gids(), _gidPositions);
+    _domainManager->initializeParticleSystem( _shaderParticlesDefault );
+    _domainManager->updateData( _player->gids( ) , _gidPositions );
 
     _pickRenderer =
-        dynamic_cast< prefr::GLPickRenderer* >( _particleSystem->renderer( ));
+      dynamic_cast< prefr::GLPickRenderer* >( _particleSystem->renderer( ));
 
-    _pickRenderer->glPickProgram( _shaderPicking );
-    _pickRenderer->setDefaultFBO( defaultFramebufferObject( ));
+    if ( _pickRenderer != nullptr )
+    {
+      _pickRenderer->glPickProgram( _shaderPicking );
+      _pickRenderer->setDefaultFBO( defaultFramebufferObject( ));
+    }
 
     _domainManager->mode( TMODE_SELECTION );
 
@@ -769,69 +946,32 @@ namespace visimpl
 
   void OpenGLWidget::_paintParticles( void )
   {
-    if( !_particleSystem )
+    if ( !_particleSystem )
       return;
 
-    glDepthMask(GL_FALSE);
-    glEnable(GL_BLEND);
-
-    glEnable(GL_DEPTH_TEST);
-    glDisable(GL_CULL_FACE);
-
-    if( _alphaBlendingAccumulative )
-      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA);
-    else
-      glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-
-
-    glFrontFace(GL_CCW);
-
-    _shaderParticlesCurrent->use();
-    unsigned int shader = _shaderParticlesCurrent->program( );
-
-    unsigned int uModelViewProjM;
-    unsigned int cameraUp;
-    unsigned int cameraRight;
-    unsigned int particleRadius;
-
-    uModelViewProjM = glGetUniformLocation( shader, "modelViewProjM" );
-    glUniformMatrix4fv( uModelViewProjM, 1, GL_FALSE,
-                       _camera->camera()->projectionViewMatrix() );
-
-    cameraUp = glGetUniformLocation( shader, "cameraUp" );
-    cameraRight = glGetUniformLocation( shader, "cameraRight" );
-    particleRadius = glGetUniformLocation( shader, "radiusThreshold" );
-
-    float* viewM = _camera->camera()->viewMatrix( );
-
-    glUniform3f( cameraUp, viewM[1], viewM[5], viewM[9] );
-    glUniform3f( cameraRight, viewM[0], viewM[4], viewM[8] );
+    _shaderParticlesCurrent->use( );
 
-    glUniform1f( particleRadius, _particleRadiusThreshold );
+    glm::vec3 cameraPosition( _camera->position( )[ 0 ] ,
+                              _camera->position( )[ 1 ] ,
+                              _camera->position( )[ 2 ] );
 
-    glm::vec3 cameraPosition ( _camera->position( )[ 0 ],
-                               _camera->position( )[ 1 ],
-                               _camera->position( )[ 2 ] );
-
-    if( _player->isPlaying( ) || _lastCameraPosition != cameraPosition || _flagUpdateRender )
+    if ( _player->isPlaying( ) || _lastCameraPosition != cameraPosition ||
+         _flagUpdateRender )
     {
-      _particleSystem->updateCameraDistances( cameraPosition );
       _lastCameraPosition = cameraPosition;
-
       _particleSystem->updateRender( );
-
       _flagUpdateRender = false;
     }
 
-    if( _clipping )
+    if ( _clipping )
     {
-      _clippingPlaneLeft->activate( _shaderParticlesCurrent, 0 );
-      _clippingPlaneRight->activate( _shaderParticlesCurrent, 1 );
+      _clippingPlaneLeft->activate( _shaderParticlesCurrent , 0 );
+      _clippingPlaneRight->activate( _shaderParticlesCurrent , 1 );
     }
 
     _particleSystem->render( );
 
-    if( _clipping )
+    if ( _clipping )
     {
       _clippingPlaneLeft->deactivate( 0 );
       _clippingPlaneRight->deactivate( 1 );
@@ -842,7 +982,7 @@ namespace visimpl
 
   void OpenGLWidget::_paintPlanes( void )
   {
-    if( _clipping && _paintClippingPlanes )
+    if ( _clipping && _paintClippingPlanes )
     {
       _planeLeft.render( _shaderClippingPlanes );
       _planeRight.render( _shaderClippingPlanes );
@@ -851,191 +991,226 @@ namespace visimpl
 
   void OpenGLWidget::_resolveFlagsOperations( void )
   {
-    if(_flagNewData)
-       _updateNewData( );
+    if ( _flagNewData )
+      _updateNewData( );
 
-    if( _flagChangeShader )
+    if ( _flagChangeShader )
       _setShaderParticles( );
 
-    if( _flagModeChange )
+    if ( _flagModeChange )
       _modeChange( );
 
-    if( _flagUpdateSelection )
+    if ( _flagUpdateSelection )
       _updateSelection( );
 
-    if( _flagUpdateGroups )
+    if ( _flagUpdateGroups )
       _updateGroupsVisibility( );
 
-    if( _flagUpdateGroups && _domainManager && _domainManager->showGroups( ))
+    if ( _flagUpdateGroups && _domainManager && _domainManager->showGroups( ))
       _updateGroups( );
 
-    if( _flagAttribChange )
+    if ( _flagAttribChange )
       _attributeChange( );
 
-    if( _flagUpdateAttributes )
+    if ( _flagUpdateAttributes )
       _updateAttributes( );
 
-    if( _flagResetParticles )
+    if ( _flagResetParticles )
     {
-      if(_domainManager) _domainManager->resetParticles( );
+      if ( _domainManager ) _domainManager->resetParticles( );
       _flagResetParticles = false;
     }
 
-    if( _particleSystem )
+    if ( _particleSystem )
       _particleSystem->update( 0.0f );
   }
 
-    void OpenGLWidget::paintGL( void )
-    {
-      std::chrono::time_point< std::chrono::system_clock > now =
-          std::chrono::system_clock::now( );
+  void OpenGLWidget::paintGL( void )
+  {
+    std::chrono::time_point< std::chrono::system_clock > now =
+      std::chrono::system_clock::now( );
 
-      const unsigned int elapsedMicroseconds =
-          std::chrono::duration_cast< std::chrono::microseconds >
-            ( now - _lastFrame ).count( );
+    const unsigned int elapsedMicroseconds =
+      std::chrono::duration_cast< std::chrono::microseconds >
+        ( now - _lastFrame ).count( );
 
-      _lastFrame = now;
+    _lastFrame = now;
 
-      _deltaTime = elapsedMicroseconds * 0.000001;
+    _deltaTime = elapsedMicroseconds * 0.000001;
 
-      if( _player && _player->isPlaying( ))
-      {
-        _elapsedTimeSimAcc += elapsedMicroseconds;
-        _elapsedTimeRenderAcc += elapsedMicroseconds;
-        _elapsedTimeSliderAcc += elapsedMicroseconds;
-      }
-      _frameCount++;
-      glDepthMask(GL_TRUE);
-      glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-      glDisable(GL_BLEND);
-      glEnable(GL_DEPTH_TEST);
-      glEnable(GL_CULL_FACE);
+    if ( _player && _player->isPlaying( ))
+    {
+      _elapsedTimeSimAcc += elapsedMicroseconds;
+      _elapsedTimeRenderAcc += elapsedMicroseconds;
+      _elapsedTimeSliderAcc += elapsedMicroseconds;
+    }
+    _frameCount++;
+    glDepthMask( GL_TRUE );
+    glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+    glDisable( GL_BLEND );
+    glEnable( GL_DEPTH_TEST );
+    glEnable( GL_CULL_FACE );
 
-      _resolveFlagsOperations( );
+    _resolveFlagsOperations( );
 
-      if ( _paint )
-      {
-        _camera->anim( );
+    if ( _paint )
+    {
+      _camera->anim( );
 
-        if( _particleSystem )
+      if ( _particleSystem )
+      {
+        if ( _player && _player->isPlaying( ))
         {
-          if( _player && _player->isPlaying( ))
+          switch ( _playbackMode )
           {
-            switch( _playbackMode )
-            {
-              // Continuous mode (Default)
-              case TPlaybackMode::CONTINUOUS:
-                if( _elapsedTimeSimAcc >= _simPeriodMicroseconds )
-                {
-                  _configureSimulationFrame( );
-                  _updateEventLabelsVisibility( );
+            // Continuous mode (Default)
+            case TPlaybackMode::CONTINUOUS:
+              if ( _elapsedTimeSimAcc >= _simPeriodMicroseconds )
+              {
+                _configureSimulationFrame( );
+                _updateEventLabelsVisibility( );
 
-                  _elapsedTimeSimAcc = 0.0f;
-                }
-                break;
+                _elapsedTimeSimAcc = 0.0f;
+              }
+              break;
               // Step by step mode
-              case TPlaybackMode::STEP_BY_STEP:
-                if( _sbsPrevStep )
-                {
-                  _configurePreviousStep( );
-                  _sbsPrevStep = false;
-                }
-                else if( _sbsNextStep )
-                {
-                  _configureStepByStep( );
-                  _sbsNextStep = false;
-                }
-                break;
-              default:
-                break;
-            }
+            case TPlaybackMode::STEP_BY_STEP:
+              if ( _sbsPrevStep )
+              {
+                _configurePreviousStep( );
+                _sbsPrevStep = false;
+              }
+              else if ( _sbsNextStep )
+              {
+                _configureStepByStep( );
+                _sbsNextStep = false;
+              }
+              break;
+            default:
+              break;
+          }
 
-            if( _elapsedTimeRenderAcc >= _renderPeriodMicroseconds )
-            {
-              double renderDelta = 0;
+          if ( _elapsedTimeRenderAcc >= _renderPeriodMicroseconds )
+          {
+            double renderDelta = 0;
 
-              switch( _playbackMode )
-              {
+            switch ( _playbackMode )
+            {
               case TPlaybackMode::CONTINUOUS:
-                renderDelta = _elapsedTimeRenderAcc * _simTimePerSecond * 0.000001;
+                renderDelta =
+                  _elapsedTimeRenderAcc * _simTimePerSecond * 0.000001;
                 break;
-              case  TPlaybackMode::STEP_BY_STEP:
+              case TPlaybackMode::STEP_BY_STEP:
                 _configureStepByStepFrame( _elapsedTimeRenderAcc * 0.000001 );
                 renderDelta = _sbsCurrentRenderDelta;
                 break;
               default:
                 renderDelta = 0;
-              }
-
-              if(std::isnan(renderDelta)) renderDelta = 0;
+            }
 
-              _updateParticles( renderDelta );
-              _elapsedTimeRenderAcc = 0.0f;
-            } // elapsed > render period
+            if ( std::isnan( renderDelta )) renderDelta = 0;
+
+            _updateParticles( renderDelta );
+            _elapsedTimeRenderAcc = 0.0f;
+          } // elapsed > render period
+
+        } // if player && player->isPlaying
+
+
+        glBindFramebuffer( GL_FRAMEBUFFER , _msaaFrameBuffer );
+        glViewport( 0 , 0 , width( ) * FRAMEBUFFER_SCALE_FACTOR ,
+                    height( ) * FRAMEBUFFER_SCALE_FACTOR );
+        glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
+        glEnable( GL_DEPTH_TEST );
+
+        _paintPlanes( );
+        _paintParticles( );
+
+        glViewport( 0 , 0 , width( ) , height( ));
+
+        // Perform MSAA
+        glBindFramebuffer( GL_READ_FRAMEBUFFER , _msaaFrameBuffer );
+        glBindFramebuffer( GL_DRAW_FRAMEBUFFER , _midFrameBuffer );
+        int w = width( ) * FRAMEBUFFER_SCALE_FACTOR;
+        int h = height( ) * FRAMEBUFFER_SCALE_FACTOR;
+        _oglFunctions->glBlitFramebuffer(
+          0 , 0 ,
+          w , h ,
+          0 , 0 ,
+          w , h ,
+          GL_COLOR_BUFFER_BIT , GL_NEAREST );
+
+        // Perform super-sampling
+        glBindFramebuffer( GL_READ_FRAMEBUFFER , _midFrameBuffer );
+        glBindFramebuffer( GL_DRAW_FRAMEBUFFER , defaultFramebufferObject( ));
+        _oglFunctions->glBlitFramebuffer(
+          0 , 0 ,
+          w , h ,
+          0 , 0 ,
+          width( ) , height( ) ,
+          GL_COLOR_BUFFER_BIT , GL_LINEAR );
+
+        if ( _flagPickingSingle )
+        {
+          _pickSingle( );
+        }
+      } // if particleSystem
 
-          } // if player && player->isPlaying
+    }
 
-          _paintPlanes( );
+    if ( _player && _elapsedTimeSliderAcc > _sliderUpdatePeriodMicroseconds )
+    {
+      _elapsedTimeSliderAcc = 0.0f;
 
-          _paintParticles( );
+#ifdef VISIMPL_USE_ZEROEQ
+      _player->sendCurrentTimestamp( );
+#endif
 
-          if( _flagPickingSingle )
-          {
-            _pickSingle( );
-          }
-        } // if particleSystem
+      emit updateSlider( _player->GetRelativeTime( ));
 
-      }
 
-      if( _player && _elapsedTimeSliderAcc > _sliderUpdatePeriodMicroseconds )
+      if ( _showCurrentTime )
       {
-        _elapsedTimeSliderAcc = 0.0f;
-
-    #ifdef VISIMPL_USE_ZEROEQ
-        _player->sendCurrentTimestamp( );
-    #endif
-
-        emit updateSlider( _player->GetRelativeTime( ));
-
-
-        if( _showCurrentTime )
-        {
-          _labelCurrentTime->setText( tr( "t=") + QString::number( _player->currentTime( )));
-        }
+        _labelCurrentTime->setText(
+          tr( "t=" ) + QString::number( _player->currentTime( )));
       }
+    }
 
-      #define FRAMES_PAINTED_TO_MEASURE_FPS 10
-      if( _showFps && _frameCount >= FRAMES_PAINTED_TO_MEASURE_FPS )
-      {
-        auto duration = std::chrono::duration_cast<std::chrono::milliseconds>( now - _then );
-        _then = now;
+#define FRAMES_PAINTED_TO_MEASURE_FPS 10
+    if ( _showFps && _frameCount >= FRAMES_PAINTED_TO_MEASURE_FPS )
+    {
+      auto duration = std::chrono::duration_cast< std::chrono::milliseconds >(
+        now - _then );
+      _then = now;
 
-        MainWindow* mainWindow = dynamic_cast< MainWindow* >( parent( ));
-        if( mainWindow )
+      MainWindow* mainWindow = dynamic_cast< MainWindow* >( parent( ));
+      if ( mainWindow )
+      {
+        const unsigned int ellapsedMiliseconds = duration.count( );
+        const auto ratioMS =
+          static_cast<float>(_frameCount) / ellapsedMiliseconds;
+        if ( !std::isnan( ratioMS ))
         {
-          const unsigned int ellapsedMiliseconds = duration.count();
-          const auto ratioMS = static_cast<float>(_frameCount) / ellapsedMiliseconds;
-          if(!std::isnan(ratioMS))
-          {
-            const unsigned int fps = roundf(1000.0f * ratioMS);
+          const unsigned int fps = roundf( 1000.0f * ratioMS );
 
-            if( _showFps)
-            {
-              _fpsLabel->setText(QString::number(fps) + QString(" FPS"));
-            }
+          if ( _showFps )
+          {
+            _fpsLabel->setText( QString::number( fps ) + QString( " FPS" ));
           }
         }
-
-        _frameCount = 0;
       }
 
-      if( _idleUpdate && _player)
-        update( );
+      _frameCount = 0;
+    }
+
+    if ( _idleUpdate && _player )
+      update( );
   }
 
-  void OpenGLWidget::setSelectedGIDs( const std::unordered_set< uint32_t >& gids )
+  void
+  OpenGLWidget::setSelectedGIDs( const std::unordered_set< uint32_t >& gids )
   {
-    if( gids.size( ) > 0 )
+    if ( gids.size( ) > 0 )
     {
       _selectedGIDs = gids;
       _pendingSelection = true;
@@ -1061,8 +1236,9 @@ namespace visimpl
 
   void OpenGLWidget::selectAttrib( int newAttrib )
   {
-    if( _domainManager && ( newAttrib < 0 || newAttrib >= ( int ) T_TYPE_UNDEFINED ||
-        _domainManager->mode( ) != TMODE_ATTRIBUTE ) )
+    if ( _domainManager &&
+         ( newAttrib < 0 || newAttrib >= ( int ) T_TYPE_UNDEFINED ||
+           _domainManager->mode( ) != TMODE_ATTRIBUTE ))
       return;
 
     _newAttrib = ( tNeuronAttributes ) newAttrib;
@@ -1071,19 +1247,19 @@ namespace visimpl
 
   void OpenGLWidget::_modeChange( void )
   {
-    if( _domainManager )
+    if ( _domainManager )
       _domainManager->mode( _newMode );
 
     _flagModeChange = false;
     _flagUpdateRender = true;
 
-    if( _domainManager && ( _domainManager->mode( ) == TMODE_ATTRIBUTE ) )
+    if ( _domainManager && ( _domainManager->mode( ) == TMODE_ATTRIBUTE ))
       emit attributeStatsComputed( );
   }
 
   void OpenGLWidget::_attributeChange( void )
   {
-    if( _domainManager )
+    if ( _domainManager )
       _domainManager->generateAttributesGroups( _newAttrib );
 
     _currentAttrib = _newAttrib;
@@ -1095,7 +1271,7 @@ namespace visimpl
 
   void OpenGLWidget::_updateSelection( void )
   {
-    if( _particleSystem /*&& _pendingSelection*/ )
+    if ( _particleSystem /*&& _pendingSelection*/ )
     {
       _particleSystem->run( false );
 
@@ -1109,19 +1285,19 @@ namespace visimpl
     }
   }
 
-  void OpenGLWidget::setGroupVisibility( unsigned int i, bool state )
+  void OpenGLWidget::setGroupVisibility( unsigned int i , bool state )
   {
-    _pendingGroupStateChanges.push( std::make_pair( i, state ));
+    _pendingGroupStateChanges.push( std::make_pair( i , state ));
     _flagUpdateGroups = true;
   }
 
   void OpenGLWidget::_updateGroupsVisibility( void )
   {
-    while( !_pendingGroupStateChanges.empty( ))
+    while ( !_pendingGroupStateChanges.empty( ))
     {
       auto state = _pendingGroupStateChanges.front( );
-      if(_domainManager)
-        _domainManager->setVisualGroupState( state.first, state.second );
+      if ( _domainManager )
+        _domainManager->setVisualGroupState( state.first , state.second );
 
       _pendingGroupStateChanges.pop( );
 
@@ -1131,7 +1307,7 @@ namespace visimpl
 
   void OpenGLWidget::_updateGroups( void )
   {
-    if( _particleSystem /*&& _pendingSelection*/ )
+    if ( _particleSystem /*&& _pendingSelection*/ )
     {
       _particleSystem->run( false );
 
@@ -1149,49 +1325,48 @@ namespace visimpl
 
   void OpenGLWidget::_updateAttributes( void )
   {
-    if( _particleSystem )
+    if ( _particleSystem )
     {
-      _particleSystem->run(false);
+      _particleSystem->run( false );
 
-      _domainManager->updateAttributes();
+      _domainManager->updateAttributes( );
 
-      updateCameraBoundingBox();
+      updateCameraBoundingBox( );
 
-      _particleSystem->run(true);
-      _particleSystem->update(0.0f);
+      _particleSystem->run( true );
+      _particleSystem->update( 0.0f );
 
       _flagUpdateAttributes = false;
       _flagUpdateRender = true;
     }
   }
 
-  void OpenGLWidget::updateData()
+  void OpenGLWidget::updateData( )
   {
     _flagNewData = true;
   }
 
-  bool OpenGLWidget::_updateData( void )
+  bool OpenGLWidget::_updateData( bool force )
   {
-    const auto &positions = _player->positions();
+    const auto& positions = _player->positions( );
 
     // assumed positions doesn't change so if equal the network didn't change.
-    if(positions.size() == _gidPositions.size()) return false;
+    if ( !force && positions.size( ) == _gidPositions.size( )) return false;
 
-    _gidPositions.clear();
-    _gidPositions.reserve(positions.size());
+    _gidPositions.clear( );
+    _gidPositions.reserve( positions.size( ));
 
-    auto gidit = _player->gids().cbegin();
-    auto insertElement = [&](const vmml::Vector3f &v)
+    auto gidit = _player->gids( ).cbegin( );
+    auto insertElement = [ & ]( const vmml::Vector3f& v )
     {
-      const vec3 position(v.x() * _scaleFactor.x,
-                          v.y() * _scaleFactor.y,
-                          v.z() * _scaleFactor.z);
+      const vec3 position( v.x( ) * _scaleFactor.x ,
+                           v.y( ) * _scaleFactor.y ,
+                           v.z( ) * _scaleFactor.z );
 
-      _gidPositions.insert(std::make_pair(*gidit, position));
+      _gidPositions.insert( std::make_pair( *gidit , position ));
       ++gidit;
     };
-    std::for_each(positions.cbegin(), positions.cend(), insertElement);
-
+    std::for_each( positions.cbegin( ) , positions.cend( ) , insertElement );
     return true;
   }
 
@@ -1199,16 +1374,16 @@ namespace visimpl
   {
     _flagNewData = false;
 
-    if(!_updateData()) return;
+    if ( !_updateData( )) return;
 
-    _domainManager->updateData(_player->gids(), _gidPositions );
+    _domainManager->updateData( _player->gids( ) , _gidPositions );
     _focusOn( _domainManager->boundingBox( ));
     _flagUpdateRender = true;
   }
 
   void OpenGLWidget::setMode( int mode )
   {
-    if( mode < 0 || ( mode >= ( int )TMODE_UNDEFINED ))
+    if ( mode < 0 || ( mode >= ( int ) TMODE_UNDEFINED ))
       return;
 
     _newMode = static_cast<tVisualMode>(mode);
@@ -1217,7 +1392,7 @@ namespace visimpl
 
   void OpenGLWidget::showInactive( bool state )
   {
-    if( _domainManager)
+    if ( _domainManager )
       _domainManager->showInactive( state );
   }
 
@@ -1234,16 +1409,20 @@ namespace visimpl
 
   void OpenGLWidget::updateCameraBoundingBox( bool setBoundingBox )
   {
-    if(_gidPositions.empty()) return;
+    if ( _gidPositions.empty( )) return;
 
     const auto boundingBox = _domainManager->boundingBox( );
 
-    const glm::vec3 MAX{std::numeric_limits<float>::max(),std::numeric_limits<float>::max(),std::numeric_limits<float>::max()};
-    const glm::vec3 MIN{std::numeric_limits<float>::min(),std::numeric_limits<float>::min(),std::numeric_limits<float>::min()};
+    const glm::vec3 MAX{ std::numeric_limits< float >::max( ) ,
+                         std::numeric_limits< float >::max( ) ,
+                         std::numeric_limits< float >::max( ) };
+    const glm::vec3 MIN{ std::numeric_limits< float >::min( ) ,
+                         std::numeric_limits< float >::min( ) ,
+                         std::numeric_limits< float >::min( ) };
 
-    if(boundingBox.first != MAX && boundingBox.second != MIN)
+    if ( boundingBox.first != MAX && boundingBox.second != MIN )
     {
-      if( setBoundingBox )
+      if ( setBoundingBox )
         _boundingBoxHome = boundingBox;
 
       _focusOn( boundingBox );
@@ -1253,10 +1432,10 @@ namespace visimpl
   void OpenGLWidget::_focusOn( const tBoundingBox& boundingBox )
   {
     const glm::vec3 center = ( boundingBox.first + boundingBox.second ) * 0.5f;
-    const float side = glm::length( boundingBox.second - center );
-    const float radius = side / std::tan( _camera->camera()->fieldOfView( ));
+    const float side = glm::length( boundingBox.second - center ) / 1.75;
+    const float radius = side / std::tan( _camera->camera( )->fieldOfView( ));
 
-    _camera->position(Eigen::Vector3f( center.x, center.y, center.z));
+    _camera->position( Eigen::Vector3f( center.x , center.y , center.z ));
     _camera->radius( radius );
   }
 
@@ -1264,16 +1443,20 @@ namespace visimpl
   {
     _shaderPicking->use( );
     unsigned int shader = _shaderPicking->program( );
-    unsigned int particleRadius = glGetUniformLocation( shader, "radiusThreshold" );
+    unsigned int particleRadius = glGetUniformLocation( shader ,
+                                                        "radiusThreshold" );
 
-    glUniform1f( particleRadius, _particleRadiusThreshold );
+    glUniform1f( particleRadius , _particleRadiusThreshold );
 
     auto result =
-        _pickRenderer->pick( _pickingPosition.x( ), _pickingPosition.y( ));
+      _pickRenderer->pick( *_particleSystem ,
+                           _pickingPosition.x( ) ,
+                           _pickingPosition.y( ));
 
     _flagPickingSingle = false;
 
-    if( result == 0 || ( result - 1 == _selectedPickingSingle && _flagPickingHighlighted ))
+    if ( result == 0 ||
+         ( result - 1 == _selectedPickingSingle && _flagPickingHighlighted ))
     {
       _domainManager->clearHighlighting( );
       _flagUpdateRender = true;
@@ -1296,12 +1479,12 @@ namespace visimpl
 
   void OpenGLWidget::showEventsActivityLabels( bool show )
   {
-    auto updateWidget = [show](visimpl::OpenGLWidget::EventLabel &container)
+    auto updateWidget = [ show ]( visimpl::OpenGLWidget::EventLabel& container )
     {
       container.upperWidget->setVisible( show );
       container.upperWidget->update( );
     };
-    std::for_each(_eventLabels.begin(), _eventLabels.end(), updateWidget);
+    std::for_each( _eventLabels.begin( ) , _eventLabels.end( ) , updateWidget );
   }
 
   void OpenGLWidget::showCurrentTimeLabel( bool show )
@@ -1310,16 +1493,16 @@ namespace visimpl
     _labelCurrentTime->update( );
   }
 
-  void OpenGLWidget::circuitScaleFactor( vec3 scale_, bool update )
+  void OpenGLWidget::circuitScaleFactor( vec3 scale_ , bool update )
   {
     _scaleFactor = scale_;
 
     _scaleFactorExternal = true;
 
-    if( update && _player )
+    if ( update && _player )
     {
-      _updateData();
-      _domainManager->updateData(_player->gids(), _gidPositions );
+      _updateData( true );
+      _domainManager->updateData( _player->gids( ) , _gidPositions );
       _focusOn( _domainManager->boundingBox( ));
     }
 
@@ -1333,7 +1516,7 @@ namespace visimpl
 
   void OpenGLWidget::_updateParticles( float renderDelta )
   {
-    if( _player->isPlaying( ) || _firstFrame )
+    if ( _player->isPlaying( ) || _firstFrame )
     {
       _particleSystem->update( renderDelta );
       _firstFrame = false;
@@ -1345,7 +1528,7 @@ namespace visimpl
     std::vector< bool > visibility = _activeEventsAt( _player->currentTime( ));
 
     unsigned int counter = 0;
-    for( auto showLabel : visibility )
+    for ( auto showLabel: visibility )
     {
       EventLabel& labelObjects = _eventLabels[ counter ];
 
@@ -1359,13 +1542,13 @@ namespace visimpl
 
   std::vector< bool > OpenGLWidget::_activeEventsAt( float time )
   {
-    std::vector< bool > result( _eventLabels.size( ), false);
+    std::vector< bool > result( _eventLabels.size( ) , false );
 
     const float totalTime = _player->endTime( ) - _player->startTime( );
     const double perc = time / totalTime;
 
     unsigned int counter = 0;
-    for( auto event : _eventsActivation )
+    for ( auto event: _eventsActivation )
     {
       unsigned int position = perc * event.size( );
       result[ counter ] = event[ position ];
@@ -1378,12 +1561,43 @@ namespace visimpl
 
   void OpenGLWidget::resizeGL( int w , int h )
   {
-    _camera->windowSize(w, h);
-    glViewport( 0, 0, w, h );
+    _camera->windowSize( w , h );
+    glViewport( 0 , 0 , w , h );
+
+    if ( _pickRenderer )
+    {
+      _pickRenderer->setWindowSize( w , h );
+    }
 
-    if( _pickRenderer )
+    if ( _oglFunctions != nullptr && _msaaTextureColor != 0 )
     {
-      _pickRenderer->setWindowSize( w, h );
+      int rw = width( ) * FRAMEBUFFER_SCALE_FACTOR;
+      int rh = height( ) * FRAMEBUFFER_SCALE_FACTOR;
+      // Resize MSAA buffers
+      glBindTexture( GL_TEXTURE_2D_MULTISAMPLE , _msaaTextureColor );
+      _oglFunctions->glTexImage2DMultisample(
+        GL_TEXTURE_2D_MULTISAMPLE , SAMPLES , GL_RGB ,
+        rw , rh , GL_TRUE );
+
+      glBindRenderbuffer( GL_RENDERBUFFER , _msaaRBODepth );
+      _oglFunctions->glRenderbufferStorageMultisample(
+        GL_RENDERBUFFER , SAMPLES , GL_DEPTH_COMPONENT32 ,
+        rw , rh );
+
+      // And mid-buffers too!
+
+      glBindTexture( GL_TEXTURE_2D , _midTextureColor );
+      glTexImage2D( GL_TEXTURE_2D , 0 , GL_RGB ,
+                    rw , rh , 0 ,
+                    GL_RGB , GL_UNSIGNED_BYTE , nullptr );
+
+      glBindRenderbuffer( GL_RENDERBUFFER , _midRBODepth );
+      glRenderbufferStorage( GL_RENDERBUFFER , GL_DEPTH_COMPONENT32 ,
+                             rw , rh );
+
+      glBindTexture( GL_TEXTURE_2D_MULTISAMPLE , 0 );
+      glBindTexture( GL_TEXTURE_2D , 0 );
+      glBindRenderbuffer( GL_RENDERBUFFER , 0 );
     }
   }
 
@@ -1392,13 +1606,13 @@ namespace visimpl
     _clippingPlaneLeft = new reto::ClippingPlane( );
     _clippingPlaneRight = new reto::ClippingPlane( );
 
-    _planePosLeft.resize( 4, Eigen::Vector3f::Zero( ));
-    _planePosRight.resize( 4, Eigen::Vector3f::Zero( ));
+    _planePosLeft.resize( 4 , Eigen::Vector3f::Zero( ));
+    _planePosRight.resize( 4 , Eigen::Vector3f::Zero( ));
 
     _planeRotation = Eigen::Matrix4f::Identity( );
 
-    _planeLeft.init( _camera->camera() );
-    _planeRight.init( _camera->camera() );
+    _planeLeft.init( _camera->camera( ));
+    _planeRight.init( _camera->camera( ));
 
     _genPlanesFromBoundingBox( );
   }
@@ -1407,11 +1621,15 @@ namespace visimpl
   {
     auto currentBoundingBox = _domainManager->boundingBox( );
 
-    _planesCenter = glmToEigen( currentBoundingBox.first + currentBoundingBox.second ) * 0.5f;
+    _planesCenter =
+      glmToEigen( currentBoundingBox.first + currentBoundingBox.second ) * 0.5f;
 
-    _planeDistance = std::abs( currentBoundingBox.second.x - currentBoundingBox.first.x ) + 1;
-    _planeHeight = std::abs( currentBoundingBox.second.y - currentBoundingBox.first.y );
-    _planeWidth = std::abs( currentBoundingBox.second.z - currentBoundingBox.first.z );
+    _planeDistance =
+      std::abs( currentBoundingBox.second.x - currentBoundingBox.first.x ) + 1;
+    _planeHeight = std::abs(
+      currentBoundingBox.second.y - currentBoundingBox.first.y );
+    _planeWidth = std::abs(
+      currentBoundingBox.second.z - currentBoundingBox.first.z );
 
     _genPlanesFromParameters( );
   }
@@ -1419,7 +1637,7 @@ namespace visimpl
   void OpenGLWidget::_genPlanesFromParameters( void )
   {
     glm::vec3 offset =
-        glm::vec3( _planeDistance, _planeHeight, _planeWidth ) * 0.5f;
+      glm::vec3( _planeDistance , _planeHeight , _planeWidth ) * 0.5f;
 
     evec3 centerLeft = _planesCenter;
     evec3 centerRight = _planesCenter;
@@ -1427,27 +1645,27 @@ namespace visimpl
     centerRight.x( ) += offset.x;
 
     _planePosLeft[ 0 ] = _planePosLeft[ 1 ] =
-        _planePosLeft[ 2 ] = _planePosLeft[ 3 ] = centerLeft;
+    _planePosLeft[ 2 ] = _planePosLeft[ 3 ] = centerLeft;
 
     _planePosRight[ 0 ] = _planePosRight[ 1 ] =
-        _planePosRight[ 2 ] = _planePosRight[ 3 ] = centerRight;
+    _planePosRight[ 2 ] = _planePosRight[ 3 ] = centerRight;
 
-    _planePosLeft[ 0 ] += Eigen::Vector3f( 0, offset.y, -offset.z );
-    _planePosLeft[ 1 ] += Eigen::Vector3f(  0, -offset.y, -offset.z );
-    _planePosLeft[ 2 ] += Eigen::Vector3f( 0, -offset.y, offset.z );
-    _planePosLeft[ 3 ] += Eigen::Vector3f( 0, offset.y, offset.z );
+    _planePosLeft[ 0 ] += Eigen::Vector3f( 0 , offset.y , -offset.z );
+    _planePosLeft[ 1 ] += Eigen::Vector3f( 0 , -offset.y , -offset.z );
+    _planePosLeft[ 2 ] += Eigen::Vector3f( 0 , -offset.y , offset.z );
+    _planePosLeft[ 3 ] += Eigen::Vector3f( 0 , offset.y , offset.z );
 
-    _planePosRight[ 0 ] += Eigen::Vector3f( 0, offset.y, -offset.z );
-    _planePosRight[ 1 ] += Eigen::Vector3f( 0, -offset.y, -offset.z);
-    _planePosRight[ 2 ] += Eigen::Vector3f( 0, -offset.y, offset.z );
-    _planePosRight[ 3 ] += Eigen::Vector3f( 0, offset.y, offset.z );
+    _planePosRight[ 0 ] += Eigen::Vector3f( 0 , offset.y , -offset.z );
+    _planePosRight[ 1 ] += Eigen::Vector3f( 0 , -offset.y , -offset.z );
+    _planePosRight[ 2 ] += Eigen::Vector3f( 0 , -offset.y , offset.z );
+    _planePosRight[ 3 ] += Eigen::Vector3f( 0 , offset.y , offset.z );
 
     _updatePlanes( );
   }
 
-  static Eigen::Vector3f transform( const Eigen::Vector3f& position,
-                             const Eigen::Vector3f& displacement,
-                             const Eigen::Matrix4f& rotation )
+  static Eigen::Vector3f transform( const Eigen::Vector3f& position ,
+                                    const Eigen::Vector3f& displacement ,
+                                    const Eigen::Matrix4f& rotation )
   {
     auto disp = vec3ToVec4( displacement );
     return vec4ToVec3(( rotation * ( vec3ToVec4( position ) - disp )) + disp );
@@ -1464,44 +1682,44 @@ namespace visimpl
 
     std::vector< Eigen::Vector3f > transformedPoints( pointsNumber * 2 );
 
-    for( unsigned int i = 0; i < pointsNumber; ++i )
+    for ( unsigned int i = 0; i < pointsNumber; ++i )
     {
       transformedPoints[ i ] =
-          transform( _planePosLeft[ i ], center, _planeRotation );
+        transform( _planePosLeft[ i ] , center , _planeRotation );
 
-      transformedPoints[ i + pointsNumber] =
-          transform( _planePosRight[ i ], center, _planeRotation );
+      transformedPoints[ i + pointsNumber ] =
+        transform( _planePosRight[ i ] , center , _planeRotation );
     }
 
-    _planeLeft.points( transformedPoints[ 0 ], transformedPoints[ 1 ],
-                   transformedPoints[ 2 ], transformedPoints[ 3 ]);
+    _planeLeft.points( transformedPoints[ 0 ] , transformedPoints[ 1 ] ,
+                       transformedPoints[ 2 ] , transformedPoints[ 3 ] );
 
-    _planeRight.points( transformedPoints[ 4 ], transformedPoints[ 5 ],
-                       transformedPoints[ 6 ], transformedPoints[ 7 ]);
+    _planeRight.points( transformedPoints[ 4 ] , transformedPoints[ 5 ] ,
+                        transformedPoints[ 6 ] , transformedPoints[ 7 ] );
 
 
     float offsetX = _planeDistance * 0.5;
     centerLeft.x( ) -= offsetX;
     centerRight.x( ) += offsetX;
 
-    center = transform( center, center, _planeRotation );
-    centerLeft = transform( centerLeft, center, _planeRotation );
-    centerRight = transform( centerRight, center, _planeRotation );
+    center = transform( center , center , _planeRotation );
+    centerLeft = transform( centerLeft , center , _planeRotation );
+    centerRight = transform( centerRight , center , _planeRotation );
 
     _planeNormalLeft = ( center - centerLeft ).normalized( );
     _planeNormalRight = ( center - centerRight ).normalized( );
 
     _clippingPlaneLeft->setEquationByPointAndNormal(
-                centerLeft, _planeNormalLeft );
+      centerLeft , _planeNormalLeft );
     _clippingPlaneRight->setEquationByPointAndNormal(
-                centerRight, _planeNormalRight );
+      centerRight , _planeNormalRight );
   }
 
   void OpenGLWidget::clippingPlanes( bool active )
   {
     _clipping = active;
 
-    if( _clipping )
+    if ( _clipping )
     {
       _updatePlanes( );
     }
@@ -1562,9 +1780,9 @@ namespace visimpl
 
   void OpenGLWidget::clippingPlanesColor( const QColor& color_ )
   {
-    _planesColor = evec4( color_.red( ) * invRGBInt,
-                          color_.green( ) * invRGBInt,
-                          color_.blue( ) * invRGBInt,
+    _planesColor = evec4( color_.red( ) * invRGBInt ,
+                          color_.green( ) * invRGBInt ,
+                          color_.blue( ) * invRGBInt ,
                           1.0 );
 
     _planeLeft.color( _planesColor );
@@ -1573,34 +1791,34 @@ namespace visimpl
 
   QColor OpenGLWidget::clippingPlanesColor( void )
   {
-    return QColor( _planesColor.x( ) * 255,
-                   _planesColor.y( ) * 255,
-                   _planesColor.z( ) * 255,
+    return QColor( _planesColor.x( ) * 255 ,
+                   _planesColor.y( ) * 255 ,
+                   _planesColor.z( ) * 255 ,
                    _planesColor.w( ) * 255 );
   }
 
-  void OpenGLWidget::_rotatePlanes( float yaw_, float pitch_ )
+  void OpenGLWidget::_rotatePlanes( float yaw_ , float pitch_ )
   {
     Eigen::Matrix4f rot;
     Eigen::Matrix4f rYaw;
     Eigen::Matrix4f rPitch;
 
-    float sinYaw, cosYaw, sinPitch, cosPitch;
+    float sinYaw , cosYaw , sinPitch , cosPitch;
 
     sinYaw = sin( yaw_ );
     cosYaw = cos( yaw_ );
     sinPitch = sin( pitch_ );
     cosPitch = cos( pitch_ );
 
-    rYaw << cosYaw, 0.0f, sinYaw, 0.0f,
-            0.0f,   1.0f, 0.0f, 0.0f,
-            -sinYaw, 0.0f, cosYaw, 0.0f,
-            0.0f, 0.0f, 0.0f, 1.0f;
+    rYaw << cosYaw , 0.0f , sinYaw , 0.0f ,
+      0.0f , 1.0f , 0.0f , 0.0f ,
+      -sinYaw , 0.0f , cosYaw , 0.0f ,
+      0.0f , 0.0f , 0.0f , 1.0f;
 
-    rPitch << 1.0f, 0.0f, 0.0f, 0.0f,
-              0.0f, cosPitch, -sinPitch, 0.0f,
-              0.0f, sinPitch, cosPitch, 0.0f,
-              0.0f, 0.0f, 0.0f, 1.0f;
+    rPitch << 1.0f , 0.0f , 0.0f , 0.0f ,
+      0.0f , cosPitch , -sinPitch , 0.0f ,
+      0.0f , sinPitch , cosPitch , 0.0f ,
+      0.0f , 0.0f , 0.0f , 1.0f;
 
     rot = rPitch * rYaw;
 
@@ -1614,7 +1832,7 @@ namespace visimpl
     GIDVec result;
 
     // Project elements
-    evec3 normal = - _planeNormalLeft;
+    evec3 normal = -_planeNormalLeft;
     normal.normalize( );
 
     auto positions = _domainManager->positions( );
@@ -1623,12 +1841,12 @@ namespace visimpl
 
     float distance = 0.0f;
 
-    for( auto neuronPos : positions )
+    for ( auto neuronPos: positions )
     {
       distance = normal.dot( _planeLeft.points( )[ 0 ] ) -
                  normal.dot( glmToEigen( neuronPos.second ));
 
-      if( distance > 0.0f && distance <= _planeDistance )
+      if ( distance > 0.0f && distance <= _planeDistance )
       {
         result.emplace_back( neuronPos.first );
       }
@@ -1643,13 +1861,13 @@ namespace visimpl
   {
     if ( event_->button( ) == Qt::LeftButton )
     {
-      if( event_->modifiers( ) == ( Qt::SHIFT | Qt::CTRL ) && _clipping )
+      if ( event_->modifiers( ) == ( Qt::SHIFT | Qt::CTRL ) && _clipping )
       {
         _translationPlanes = true;
         _mouseX = event_->x( );
         _mouseY = event_->y( );
       }
-      else if( event_->modifiers( ) == Qt::CTRL )
+      else if ( event_->modifiers( ) == Qt::CTRL )
       {
         _pickingPosition = event_->pos( );
 
@@ -1659,7 +1877,7 @@ namespace visimpl
           _mouseY = event_->y( );
         }
       }
-      else if( event_->modifiers( ) == Qt::SHIFT && _clipping )
+      else if ( event_->modifiers( ) == Qt::SHIFT && _clipping )
       {
         _rotationPlanes = true;
         _mouseX = event_->x( );
@@ -1678,11 +1896,11 @@ namespace visimpl
 
   void OpenGLWidget::mouseReleaseEvent( QMouseEvent* event_ )
   {
-    if( event_->modifiers( ) == Qt::CTRL )
+    if ( event_->modifiers( ) == Qt::CTRL )
     {
-      if( _pickingPosition == event_->pos( ))
+      if ( _pickingPosition == event_->pos( ))
       {
-        _pickingPosition.setY( height() - _pickingPosition.y( ) );
+        _pickingPosition.setY( height( ) - _pickingPosition.y( ));
 
         _flagPickingSingle = true;
       }
@@ -1691,7 +1909,7 @@ namespace visimpl
       _translationPlanes = false;
     }
 
-    if ( event_->button( ) == Qt::LeftButton)
+    if ( event_->button( ) == Qt::LeftButton )
     {
       _rotation = false;
       _rotationPlanes = false;
@@ -1702,45 +1920,47 @@ namespace visimpl
 
   void OpenGLWidget::mouseMoveEvent( QMouseEvent* event_ )
   {
-    const float diffX = event_->x() - _mouseX;
-    const float diffY = event_->y() - _mouseY;
+    const float diffX = event_->x( ) - _mouseX;
+    const float diffY = event_->y( ) - _mouseY;
 
-    auto updateLastEventCoords = [this]( const QMouseEvent *e )
+    auto updateLastEventCoords = [ this ]( const QMouseEvent* e )
     {
       _mouseX = e->x( );
       _mouseY = e->y( );
     };
 
-    if( _rotation )
+    if ( _rotation )
     {
-      _camera->rotate( Eigen::Vector3f ( diffX * ROTATION_FACTOR, diffY * ROTATION_FACTOR, 0.0f));
-      updateLastEventCoords(event_);
+      _camera->rotate(
+        Eigen::Vector3f( diffX * ROTATION_FACTOR , diffY * ROTATION_FACTOR ,
+                         0.0f ));
+      updateLastEventCoords( event_ );
     }
 
-    if( _rotationPlanes && _clipping )
+    if ( _rotationPlanes && _clipping )
     {
-      _rotatePlanes( diffX * ROTATION_FACTOR, diffY * ROTATION_FACTOR );
-      updateLastEventCoords(event_);
+      _rotatePlanes( diffX * ROTATION_FACTOR , diffY * ROTATION_FACTOR );
+      updateLastEventCoords( event_ );
     }
 
-    if( _translation )
+    if ( _translation )
     {
       const float xDis = diffX * TRANSLATION_FACTOR * _camera->radius( );
       const float yDis = diffY * TRANSLATION_FACTOR * _camera->radius( );
 
-      _camera->localTranslate( Eigen::Vector3f( -xDis, yDis, 0.0f ));
-      updateLastEventCoords(event_);
+      _camera->localTranslate( Eigen::Vector3f( -xDis , yDis , 0.0f ));
+      updateLastEventCoords( event_ );
     }
 
-    if( _translationPlanes )
+    if ( _translationPlanes )
     {
       const float xDis = diffX * TRANSLATION_FACTOR * _camera->radius( );
       const float yDis = diffY * TRANSLATION_FACTOR * _camera->radius( );
-      const evec3 displacement ( xDis, -yDis, 0 );
+      const evec3 displacement( xDis , -yDis , 0 );
 
       _planesCenter += _camera->rotation( ).transpose( ) * displacement;
 
-      updateLastEventCoords(event_);
+      updateLastEventCoords( event_ );
       _genPlanesFromParameters( );
     }
 
@@ -1751,6 +1971,7 @@ namespace visimpl
   {
     int delta = event_->angleDelta( ).y( );
 
+
     if ( delta > 0 )
       _camera->radius( _camera->radius( ) / ZOOM_FACTOR );
     else
@@ -1764,7 +1985,7 @@ namespace visimpl
     switch ( event_->key( ))
     {
       case Qt::Key_C:
-          _flagUpdateSelection = true;
+        _flagUpdateSelection = true;
         break;
       default:
         break;
@@ -1774,18 +1995,18 @@ namespace visimpl
   void OpenGLWidget::changeClearColor( void )
   {
     QColor color =
-      QColorDialog::getColor( _currentClearColor, parentWidget( ),
-                              "Choose new background color",
-                              QColorDialog::DontUseNativeDialog);
+      QColorDialog::getColor( _currentClearColor , parentWidget( ) ,
+                              "Choose new background color" ,
+                              QColorDialog::DontUseNativeDialog );
 
     if ( color.isValid( ))
     {
       _currentClearColor = color;
 
       makeCurrent( );
-      glClearColor( float( _currentClearColor.red( )) / 255.0f,
-                    float( _currentClearColor.green( )) / 255.0f,
-                    float( _currentClearColor.blue( )) / 255.0f,
+      glClearColor( float( _currentClearColor.red( )) / 255.0f ,
+                    float( _currentClearColor.green( )) / 255.0f ,
+                    float( _currentClearColor.blue( )) / 255.0f ,
                     float( _currentClearColor.alpha( )) / 255.0f );
       update( );
     }
@@ -1817,13 +2038,13 @@ namespace visimpl
     if ( _wireframe )
     {
       glEnable( GL_POLYGON_OFFSET_LINE );
-      glPolygonOffset( -1, -1 );
+      glPolygonOffset( -1 , -1 );
       glLineWidth( 1.5 );
-      glPolygonMode( GL_FRONT_AND_BACK, GL_LINE );
+      glPolygonMode( GL_FRONT_AND_BACK , GL_LINE );
     }
     else
     {
-      glPolygonMode( GL_FRONT_AND_BACK, GL_FILL );
+      glPolygonMode( GL_FRONT_AND_BACK , GL_FILL );
       glDisable( GL_POLYGON_OFFSET_LINE );
     }
 
@@ -1842,7 +2063,7 @@ namespace visimpl
 
   void OpenGLWidget::playbackMode( TPlaybackMode mode )
   {
-    if( mode != TPlaybackMode::AB_REPEAT )
+    if ( mode != TPlaybackMode::AB_REPEAT )
       _playbackMode = mode;
   }
 
@@ -1858,12 +2079,12 @@ namespace visimpl
 
   float OpenGLWidget::currentTime( void )
   {
-    switch( _playbackMode )
+    switch ( _playbackMode )
     {
-    case TPlaybackMode::STEP_BY_STEP:
-      return _sbsCurrentTime;
-    default:
-      return _player->currentTime( );
+      case TPlaybackMode::STEP_BY_STEP:
+        return _sbsCurrentTime;
+      default:
+        return _player->currentTime( );
     }
   }
 
@@ -1895,34 +2116,35 @@ namespace visimpl
   {
     const auto& eventNames = _subsetEvents->eventNames( );
 
-    if( eventNames.empty( ) )
+    if ( eventNames.empty( ))
       return;
 
-    for( auto& label : _eventLabels )
+    for ( auto& label: _eventLabels )
     {
       _eventLabelsLayout->removeWidget( label.upperWidget );
 
-      delete( label.colorLabel );
-      delete( label.label );
-      delete( label.upperWidget );
+      delete ( label.colorLabel );
+      delete ( label.label );
+      delete ( label.upperWidget );
     }
 
     _eventLabels.clear( );
     _eventsActivation.clear( );
 
     const float totalTime = _player->endTime( ) - _player->startTime( );
-    const auto &colors = _colorPalette.colors( );
+    const auto& colors = _colorPalette.colors( );
 
     unsigned int row = 0;
-    auto insertEvents = [&row, &totalTime, &colors, this](const std::string &eventName)
+    auto insertEvents = [ &row , &totalTime , &colors , this ](
+      const std::string& eventName )
     {
-      QPixmap pixmap{20,20};
-      pixmap.fill(colors[ row ].name( ));
-      auto colorLabel = new QLabel();
-      colorLabel->setPixmap(pixmap);
+      QPixmap pixmap{ 20 , 20 };
+      pixmap.fill( colors[ row ].name( ));
+      auto colorLabel = new QLabel( );
+      colorLabel->setPixmap( pixmap );
 
       QLabel* label = new QLabel( );
-      label->setMaximumSize( 100, 50 );
+      label->setMaximumSize( 100 , 50 );
       label->setTextFormat( Qt::RichText );
       label->setStyleSheet(
         "QLabel { background-color : #333;"
@@ -1931,7 +2153,7 @@ namespace visimpl
         "margin: 10px;"
         " border-radius: 10px;}" );
 
-      label->setText(QString::fromStdString(eventName));
+      label->setText( QString::fromStdString( eventName ));
 
       auto container = new QWidget( );
       auto labelLayout = new QHBoxLayout( );
@@ -1947,19 +2169,21 @@ namespace visimpl
 
       _eventLabels.push_back( eventObj );
 
-      _eventLabelsLayout->addWidget( container, row, 10, 2, 1 );
+      _eventLabelsLayout->addWidget( container , row , 10 , 2 , 1 );
 
-      const auto activity = _subsetEvents->eventActivity( eventName, _deltaEvents, totalTime );
-      _eventsActivation.push_back(activity);
+      const auto activity = _subsetEvents->eventActivity( eventName ,
+                                                          _deltaEvents ,
+                                                          totalTime );
+      _eventsActivation.push_back( activity );
 
       ++row;
     };
-    std::for_each(eventNames.cbegin(), eventNames.cend(), insertEvents);
+    std::for_each( eventNames.cbegin( ) , eventNames.cend( ) , insertEvents );
   }
 
   void OpenGLWidget::Play( void )
   {
-    if( _player )
+    if ( _player )
     {
       _player->Play( );
     }
@@ -1967,7 +2191,7 @@ namespace visimpl
 
   void OpenGLWidget::Pause( void )
   {
-    if( _player )
+    if ( _player )
     {
       _player->Pause( );
     }
@@ -1976,9 +2200,9 @@ namespace visimpl
   void OpenGLWidget::PlayPause( void )
   {
 
-    if( _player )
+    if ( _player )
     {
-      if( !_player->isPlaying( ))
+      if ( !_player->isPlaying( ))
         _player->Play( );
       else
         _player->Pause( );
@@ -1987,7 +2211,7 @@ namespace visimpl
 
   void OpenGLWidget::Stop( void )
   {
-    if( _player )
+    if ( _player )
     {
       _player->Stop( );
       _flagResetParticles = true;
@@ -1997,7 +2221,7 @@ namespace visimpl
 
   void OpenGLWidget::Repeat( bool repeat )
   {
-    if( _player )
+    if ( _player )
     {
       _player->loop( repeat );
     }
@@ -2005,7 +2229,7 @@ namespace visimpl
 
   void OpenGLWidget::PlayAt( float timePos )
   {
-    if( _player )
+    if ( _player )
     {
       _particleSystem->run( false );
       _flagResetParticles = true;
@@ -2013,18 +2237,18 @@ namespace visimpl
       _backtrace = true;
 
       std::cout << "Play at " << timePos << std::endl;
-      _player->PlayAtTime(timePos);
+      _player->PlayAtTime( timePos );
       _particleSystem->run( true );
     }
   }
 
   void OpenGLWidget::Restart( void )
   {
-    if( _player )
+    if ( _player )
     {
       const bool playing = _player->isPlaying( );
       _player->Stop( );
-      if( playing )
+      if ( playing )
         _player->Play( );
 
       _flagResetParticles = true;
@@ -2034,7 +2258,7 @@ namespace visimpl
 
   void OpenGLWidget::PreviousStep( void )
   {
-    if( _playbackMode != TPlaybackMode::STEP_BY_STEP )
+    if ( _playbackMode != TPlaybackMode::STEP_BY_STEP )
     {
       _playbackMode = TPlaybackMode::STEP_BY_STEP;
       _sbsFirstStep = true;
@@ -2046,7 +2270,7 @@ namespace visimpl
 
   void OpenGLWidget::NextStep( void )
   {
-    if( _playbackMode != TPlaybackMode::STEP_BY_STEP )
+    if ( _playbackMode != TPlaybackMode::STEP_BY_STEP )
     {
       _playbackMode = TPlaybackMode::STEP_BY_STEP;
       _sbsFirstStep = true;
@@ -2059,24 +2283,30 @@ namespace visimpl
   void OpenGLWidget::SetAlphaBlendingAccumulative( bool accumulative )
   {
     _alphaBlendingAccumulative = accumulative;
+    if ( _particleSystem != nullptr )
+    {
+      _particleSystem->renderer( )->enableAccumulativeMode(
+        _alphaBlendingAccumulative );
+    }
   }
 
-  void OpenGLWidget::changeSimulationColorMapping( const TTransferFunction& colors )
+  void
+  OpenGLWidget::changeSimulationColorMapping( const TTransferFunction& colors )
   {
 
     prefr::vectortvec4 gcolors;
 
-    for( const auto &c : colors )
+    for ( const auto& c: colors )
     {
-      glm::vec4 gColor( c.second.red( ) * invRGBInt,
-                        c.second.green( ) * invRGBInt,
-                        c.second.blue( ) * invRGBInt,
+      glm::vec4 gColor( c.second.red( ) * invRGBInt ,
+                        c.second.green( ) * invRGBInt ,
+                        c.second.blue( ) * invRGBInt ,
                         c.second.alpha( ) * invRGBInt );
 
-      gcolors.Insert( c.first, gColor );
+      gcolors.Insert( c.first , gColor );
     }
 
-    if( _domainManager )
+    if ( _domainManager )
     {
       _domainManager->modelSelectionBase( )->color = gcolors;
 
@@ -2093,14 +2323,15 @@ namespace visimpl
 
     auto timeValue = model->color.times.begin( );
 
-    auto insertColor = [&timeValue, &result](const vec4 col)
+    auto insertColor = [ &timeValue , &result ]( const vec4 col )
     {
-      const QColor color( col.r * 255, col.g * 255, col.b * 255, col.a * 255 );
-      result.push_back( std::make_pair( *timeValue, color ));
+      const QColor color( col.r * 255 , col.g * 255 , col.b * 255 ,
+                          col.a * 255 );
+      result.push_back( std::make_pair( *timeValue , color ));
 
       ++timeValue;
     };
-    std::for_each(colors.cbegin(), colors.cend(), insertColor);
+    std::for_each( colors.cbegin( ) , colors.cend( ) , insertColor );
 
     return result;
   }
@@ -2109,10 +2340,11 @@ namespace visimpl
   {
     utils::InterpolationSet< float > newSize;
 
-    auto insertSize = [&newSize](const Event &e){ newSize.Insert(e.first, e.second); };
-    std::for_each(sizes.cbegin(), sizes.cend(), insertSize);
+    auto insertSize = [ &newSize ]( const Event& e )
+    { newSize.Insert( e.first , e.second ); };
+    std::for_each( sizes.cbegin( ) , sizes.cend( ) , insertSize );
 
-    if( _domainManager )
+    if ( _domainManager )
     {
       _domainManager->modelSelectionBase( )->size = newSize;
 
@@ -2124,18 +2356,18 @@ namespace visimpl
   {
     TSizeFunction result;
 
-    if( _domainManager )
+    if ( _domainManager )
     {
       const auto model = _domainManager->modelSelectionBase( );
-      const auto &sizes = model->size.times;
+      const auto& sizes = model->size.times;
 
       auto sizeValue = model->size.values.begin( );
-      auto insertSize = [&result, &sizeValue](const float &f)
+      auto insertSize = [ &result , &sizeValue ]( const float& f )
       {
-        result.emplace_back(f, *sizeValue);
+        result.emplace_back( f , *sizeValue );
         ++sizeValue;
       };
-      std::for_each(sizes.cbegin(), sizes.cend(), insertSize);
+      std::for_each( sizes.cbegin( ) , sizes.cend( ) , insertSize );
     }
 
     return result;
@@ -2157,7 +2389,7 @@ namespace visimpl
 
   void OpenGLWidget::simulationStepsPerSecond( float value )
   {
-    if(value == 0) return;
+    if ( value == 0 ) return;
 
     _timeStepsPerSecond = value;
 
@@ -2184,7 +2416,7 @@ namespace visimpl
 
   void OpenGLWidget::changeSimulationDecayValue( float value )
   {
-    if( _domainManager )
+    if ( _domainManager )
       _domainManager->decay( value );
   }
 
@@ -2193,14 +2425,35 @@ namespace visimpl
     return _domainManager->decay( );
   }
 
-  void OpenGLWidget::closeLoadingDialog()
+  void OpenGLWidget::closeLoadingDialog( )
   {
-    if(m_loaderDialog)
+    if ( m_loaderDialog )
     {
-      m_loaderDialog->close();
+      m_loaderDialog->close( );
       delete m_loaderDialog;
       m_loaderDialog = nullptr;
     }
   }
 
+  CameraPosition OpenGLWidget::cameraPosition() const
+  {
+    CameraPosition pos;
+    pos.position = _camera->position();
+    pos.radius   = _camera->radius();
+    pos.rotation = _camera->rotation();
+
+    return pos;
+  }
+
+  void OpenGLWidget::setCameraPosition(const CameraPosition &pos)
+  {
+    if(_camera)
+    {
+      _camera->position(pos.position);
+      _camera->radius(pos.radius);
+      _camera->rotation(pos.rotation);
+      update();
+    }
+  }
+
 } // namespace visimpl
diff --git a/visimpl/OpenGLWidget.h b/visimpl/OpenGLWidget.h
index 9e040f6cd08ba60fc079913bb3ff98a7f4b8c9a7..acfe5f8c17852e7453101cd383b51660586411ef 100644
--- a/visimpl/OpenGLWidget.h
+++ b/visimpl/OpenGLWidget.h
@@ -30,6 +30,8 @@
 // Qt
 #include <QOpenGLFunctions>
 #include <QOpenGLWidget>
+#include <QOpenGLFunctions_4_0_Core>
+#include <QString>
 
 // C++
 #include <chrono>
@@ -57,13 +59,75 @@
 #include <sumrice/sumrice.h>
 #include <scoop/scoop.h>
 
+#include <sstream>
+
 class QLabel;
 class LoadingDialog;
 class LoaderThread;
 
-
 namespace visimpl
 {
+  /** \class CameraPosition
+   * \brief Implements a structure to serialize and store camera positions.
+   *
+   */
+  class CameraPosition
+  {
+    public:
+      Eigen::Vector3f position; /** position point.  */
+      Eigen::Matrix3f rotation; /** rotation matrix. */
+      float radius;             /** aperture.        */
+
+      /** \brief CameraPosition class constructor.
+       *
+       */
+      CameraPosition()
+      : position{Eigen::Vector3f()}
+      , rotation{Eigen::Matrix3f::Zero()}
+      , radius{0}
+      {};
+
+      /** \brief CameraPosition class constructor.
+       * \param[in] data Camera position serialized data.
+       *
+       */
+      CameraPosition(const QString &data)
+      {
+        const auto parts = data.split(";");
+        Q_ASSERT(parts.size() == 3);
+        const auto posData = parts.first();
+        const auto rotData = parts.last();
+        radius = parts.at(1).toFloat();
+
+        const auto posParts = posData.split(",");
+        Q_ASSERT(posParts.size() == 3);
+        const auto rotParts = rotData.split(",");
+        Q_ASSERT(rotParts.size() == 9);
+
+        position = Eigen::Vector3f(posParts[0].toFloat(), posParts[1].toFloat(), posParts[2].toFloat());
+        radius = parts.at(1).toFloat();
+        rotation.block<1,3>(0,0) = Eigen::Vector3f{rotParts[0].toFloat(), rotParts[1].toFloat(), rotParts[2].toFloat()};
+        rotation.block<1,3>(1,0) = Eigen::Vector3f{rotParts[3].toFloat(), rotParts[4].toFloat(), rotParts[5].toFloat()};
+        rotation.block<1,3>(2,0) = Eigen::Vector3f{rotParts[6].toFloat(), rotParts[7].toFloat(), rotParts[8].toFloat()};
+      }
+
+      /** \brief Returns the serialized camera position.
+       *
+       */
+      QString toString() const
+      {
+        std::stringstream stream;
+        stream << position << ";" << radius << ";"
+               << rotation(0,0) << "," << rotation(0,1) << "," << rotation(0,2) << ","
+               << rotation(1,0) << "," << rotation(1,1) << "," << rotation(1,2) << ","
+               << rotation(2,0) << "," << rotation(2,1) << "," << rotation(2,2);
+
+        auto serialization = QString::fromStdString(stream.str());
+        serialization.replace('\n',',').remove(' ');
+
+        return serialization;
+      }
+  };
 
   typedef enum
   {
@@ -141,6 +205,17 @@ namespace visimpl
 
     void closeLoadingDialog();
 
+    /** \brief Returns the current camera position.
+     *
+     */
+    CameraPosition cameraPosition() const;
+
+    /** \brief Moves the camera to the given position.
+     * \param[in] pos CameraPosition reference.
+     *
+     */
+    void setCameraPosition(const CameraPosition &pos);
+
   signals:
 
     void updateSlider( float );
@@ -249,6 +324,8 @@ namespace visimpl
 
     void _backtraceSimulation( void );
 
+    void _initRenderToTexture( void );
+
     void _configureSimulationFrame( void );
     void _configureStepByStepFrame( double elapsedRenderTimeMilliseconds );
 
@@ -264,7 +341,7 @@ namespace visimpl
     void _updateAttributes( void );
     void _updateNewData( void );
 
-    bool _updateData( void );
+    bool _updateData( bool force = false );
 
     void _createEventLabels( void );
     void _updateEventLabelsVisibility( void );
@@ -331,11 +408,11 @@ namespace visimpl
     std::chrono::time_point< std::chrono::system_clock > _lastFrame;
 
     tShaderParticlesType _currentShader;
-    reto::ShaderProgram* _shaderParticlesCurrent;
-    reto::ShaderProgram* _shaderParticlesDefault;
-    reto::ShaderProgram* _shaderParticlesSolid;
+    prefr::RenderProgram* _shaderParticlesCurrent;
+    prefr::RenderProgram* _shaderParticlesDefault;
+    prefr::RenderProgram* _shaderParticlesSolid;
     prefr::RenderProgram* _shaderPicking;
-    reto::ShaderProgram* _shaderClippingPlanes;
+    prefr::RenderProgram* _shaderClippingPlanes;
 
     prefr::ParticleSystem* _particleSystem;
     prefr::GLPickRenderer* _pickRenderer;
@@ -438,6 +515,19 @@ namespace visimpl
     unsigned int _selectedPickingSingle;
 
     tGidPosMap _gidPositions; // particle positions * scale.
+
+    QOpenGLFunctions_4_0_Core* _oglFunctions;
+
+    // Render to texture
+    reto::ShaderProgram* _screenPlaneShader;
+
+    unsigned int _msaaFrameBuffer;
+    unsigned int _msaaTextureColor;
+    unsigned int _msaaRBODepth;
+
+    unsigned int _midFrameBuffer;
+    unsigned int _midTextureColor;
+    unsigned int _midRBODepth;
   };
 } // namespace visimpl
 
diff --git a/visimpl/icons/eye.svg b/visimpl/icons/eye.svg
new file mode 100644
index 0000000000000000000000000000000000000000..e99e8d743b3f3db9178277447fe6f8ced1480a09
--- /dev/null
+++ b/visimpl/icons/eye.svg
@@ -0,0 +1,42 @@
+<?xml version="1.0" encoding="iso-8859-1"?>
+<!-- Generator: Adobe Illustrator 19.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
+<svg version="1.1" id="Capa_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+	 viewBox="0 0 488.85 488.85" style="enable-background:new 0 0 488.85 488.85;" xml:space="preserve">
+<g>
+	<path d="M244.425,98.725c-93.4,0-178.1,51.1-240.6,134.1c-5.1,6.8-5.1,16.3,0,23.1c62.5,83.1,147.2,134.2,240.6,134.2
+		s178.1-51.1,240.6-134.1c5.1-6.8,5.1-16.3,0-23.1C422.525,149.825,337.825,98.725,244.425,98.725z M251.125,347.025
+		c-62,3.9-113.2-47.2-109.3-109.3c3.2-51.2,44.7-92.7,95.9-95.9c62-3.9,113.2,47.2,109.3,109.3
+		C343.725,302.225,302.225,343.725,251.125,347.025z M248.025,299.625c-33.4,2.1-61-25.4-58.8-58.8c1.7-27.6,24.1-49.9,51.7-51.7
+		c33.4-2.1,61,25.4,58.8,58.8C297.925,275.625,275.525,297.925,248.025,299.625z"/>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+<g>
+</g>
+</svg>
diff --git a/visimpl/prefr/PrefrShaders.h b/visimpl/prefr/PrefrShaders.h
index 9d2b58b7f2c1b4756c930b81be67c24e281a8f56..8eb267c895cbf6a9f1bf3ec1ac37311c627d92d2 100644
--- a/visimpl/prefr/PrefrShaders.h
+++ b/visimpl/prefr/PrefrShaders.h
@@ -39,17 +39,19 @@ uniform vec4 plane[ 2 ];
 out float gl_ClipDistance[ 2 ];
 
 layout(location = 0) in vec3 vertexPosition;
-layout(location = 1) in vec4 particlePosition;
-layout(location = 2) in vec4 particleColor;
+layout(location = 1) in float particleSize;
+layout(location = 2) in vec3 particlePosition;
+layout(location = 3) in vec4 particleColor;
 
 out vec4 color;
 out vec2 uvCoord;
 
 void main()
 {
-  vec4 position = vec4((vertexPosition.x * particlePosition.a * cameraRight) + 
-                  (vertexPosition.y * particlePosition.a * cameraUp) + 
-                  particlePosition.rgb, 1.0); 
+  vec4 position =  vec4(
+        (vertexPosition.x * particleSize * cameraRight)
+        + (vertexPosition.y * particleSize * cameraUp)
+        + particlePosition, 1.0);
 
   gl_ClipDistance[ 0 ] = dot( position, plane[ 0 ]);
   gl_ClipDistance[ 1 ] = dot( position, plane[ 1 ]);
@@ -92,7 +94,7 @@ void main()
   if( l > radiusThreshold )
     discard;
 
-  outputColor = color;
+  outputColor = vec4(color.rgb, 1.0f);
 })";
 
 const static std::string prefrVertexShaderPicking = R"(#version 400
@@ -107,9 +109,9 @@ uniform vec4 plane[ 2 ];
 out float gl_ClipDistance[ 2 ];
 
 layout(location = 0) in vec3 vertexPosition;
-layout(location = 1) in vec4 particlePosition;
-layout(location = 2) in vec4 particleColor;
-
+layout(location = 1) in float particleSize;
+layout(location = 2) in vec3 particlePosition;
+layout(location = 3) in vec4 particleColor;
 
 out vec4 color;
 out vec2 uvCoord;
@@ -118,9 +120,10 @@ out float id;
 
 void main()
 {
-  vec4 position = vec4((vertexPosition.x * particlePosition.a * cameraRight) + 
-                  (vertexPosition.y * particlePosition.a * cameraUp) + 
-                  particlePosition.rgb, 1.0); 
+  vec4 position =  vec4(
+        (vertexPosition.x * particleSize * cameraRight)
+        + (vertexPosition.y * particleSize * cameraUp)
+        + particlePosition, 1.0);
 
   gl_ClipDistance[ 0 ] = dot( position, plane[ 0 ]);
   gl_ClipDistance[ 1 ] = dot( position, plane[ 1 ]);
@@ -146,7 +149,7 @@ out vec4 outputColor;
 
 vec3 unpackColor( float f )
 {
-  vec3 color = fract(vec3(1.0/255.0, 1.0/(255.0*255.0), 
+  vec3 color = fract(vec3(1.0/255.0, 1.0/(255.0*255.0),
     1.0/(255.0*255.0*255.0)) * f);
   color -= color.xxy * vec3(0.0, 1.0/255.0, 1.0/255.0);
 
@@ -154,7 +157,7 @@ vec3 unpackColor( float f )
 }
 
 void main( )
-{ 
+{
 
   vec2 p = -1.0 + 2.0 * uvCoord;
   float l = sqrt(dot(p,p));
diff --git a/visimpl/resources.qrc b/visimpl/resources.qrc
index c0abd46f34241dacf0323ffbf4d37e9fda2c343e..801a3f6c3ead4e3a1506d6a49837ca2404ec81b8 100644
--- a/visimpl/resources.qrc
+++ b/visimpl/resources.qrc
@@ -29,6 +29,7 @@
     <file>icons/toolconfig.svg</file>
     <file>icons/left.svg</file>
     <file>icons/right.svg</file>
+    <file>icons/eye.svg</file>
     <file>visimpl.png</file>
   </qresource>
 </RCC>
diff --git a/visimpl/visimpl.ui b/visimpl/visimpl.ui
index b05131aa5e511e4109161c767a4b711f8feade13..7342c7778aad9204f00507049abf511a2d15f8c8 100644
--- a/visimpl/visimpl.ui
+++ b/visimpl/visimpl.ui
@@ -37,6 +37,9 @@
     <addaction name="separator"/>
     <addaction name="actionOpenSubsetEventsFile"/>
     <addaction name="separator"/>
+    <addaction name="actionLoad_camera_positions"/>
+    <addaction name="actionSave_camera_positions"/>
+    <addaction name="separator"/>
     <addaction name="actionCloseData"/>
     <addaction name="separator"/>
     <addaction name="actionQuit"/>
@@ -52,6 +55,9 @@
      <string>Options</string>
     </property>
     <addaction name="actionHome"/>
+    <addaction name="actionAdd_camera_position"/>
+    <addaction name="actionRemove_camera_position"/>
+    <addaction name="actionCamera_Positions"/>
     <addaction name="actionBackgroundColor"/>
     <addaction name="separator"/>
     <addaction name="actionTogglePlaybackDock"/>
@@ -516,6 +522,56 @@
     <string>Shows/Hides the StackViz configuration panels.</string>
    </property>
   </action>
+  <action name="actionCamera_Positions">
+   <property name="enabled">
+    <bool>false</bool>
+   </property>
+   <property name="icon">
+    <iconset resource="resources.qrc">
+     <normaloff>:/icons/eye.svg</normaloff>:/icons/eye.svg</iconset>
+   </property>
+   <property name="text">
+    <string>Camera positions</string>
+   </property>
+   <property name="toolTip">
+    <string>Camera positions list.</string>
+   </property>
+  </action>
+  <action name="actionLoad_camera_positions">
+   <property name="text">
+    <string>Load camera positions...</string>
+   </property>
+   <property name="toolTip">
+    <string>Load camera positions from a file on disk.</string>
+   </property>
+  </action>
+  <action name="actionSave_camera_positions">
+   <property name="enabled">
+    <bool>false</bool>
+   </property>
+   <property name="text">
+    <string>Save camera positions...</string>
+   </property>
+   <property name="toolTip">
+    <string>Save camera positions to a file on disk.</string>
+   </property>
+  </action>
+  <action name="actionAdd_camera_position">
+   <property name="text">
+    <string>Add camera position...</string>
+   </property>
+   <property name="toolTip">
+    <string>Add camera position</string>
+   </property>
+  </action>
+  <action name="actionRemove_camera_position">
+   <property name="enabled">
+    <bool>false</bool>
+   </property>
+   <property name="text">
+    <string>Remove camera position...</string>
+   </property>
+  </action>
  </widget>
  <resources>
   <include location="resources.qrc"/>