void SceneRendererPipeline::doRenderStandard(dp::sg::ui::ViewStateSharedPtr const& viewState, dp::ui::RenderTargetSharedPtr const& renderTarget)
{
  // Call the current scene renderer and render the whole scene into the main render target (tonemapFBO).
  DP_ASSERT( viewState->getTraversalMask() == ~0 );

  // This renders only one eye even if the renderTarget is stereoscopic.
  // Important: The m_sceneRenderer holds a NOP StereoViewStateProvider to use the already adjusted stereo ViewState camera!
  m_sceneRenderer->render(viewState, renderTarget, renderTarget->getStereoTarget());
}
void SceneRendererPipeline::doRenderTonemap(dp::sg::ui::ViewStateSharedPtr const& viewState, dp::ui::RenderTargetSharedPtr const& renderTarget)
{
  dp::gl::RenderTargetSharedPtr const & renderTargetGL = renderTarget.inplaceCast<dp::gl::RenderTarget>();
  dp::gl::TargetBufferMask clearMask = renderTargetGL->getClearMask();

  // Match the size of the tonemapFBO to the destination renderTarget.
  unsigned int width;
  unsigned int height;
  renderTarget->getSize(width, height);
  m_tonemapFBO->setSize(width, height);

  // Call the current scene renderer and render the whole scene into the main render target (tonemapFBO).
  DP_ASSERT( viewState->getTraversalMask() == ~0 );

  // This renders only one eye even if the renderTarget is stereoscopic.
  // Important: The m_sceneRenderer holds a NOP StereoViewStateProvider to use the already adjusted stereo ViewState camera!
  m_sceneRenderer->render(viewState, m_tonemapFBO, renderTarget->getStereoTarget());

  if ( m_tonemapperValuesChanged )
  {
    // Set the tonemapper parameters:
    const dp::sg::core::ParameterGroupDataSharedPtr& parameterGroupData = m_tonemapperData->findParameterGroupData( std::string( "tonemapParameters" ) );
    DP_ASSERT( parameterGroupData );

    DP_VERIFY( parameterGroupData->setParameter( "invGamma", 1.0f / m_tonemapperValues.gamma ) );
    DP_VERIFY( parameterGroupData->setParameter( "invWhitePoint", m_tonemapperValues.brightness / m_tonemapperValues.whitePoint) );
    DP_VERIFY( parameterGroupData->setParameter( "saturation", m_tonemapperValues.saturation ) );
    DP_VERIFY( parameterGroupData->setParameter( "crushBlacks", m_tonemapperValues.crushBlacks + m_tonemapperValues.crushBlacks + 1.0f) ); // Note, the default if the shader variable crushBlacks is 1.0!
    DP_VERIFY( parameterGroupData->setParameter( "burnHighlights", m_tonemapperValues.burnHighlights ) );

    m_tonemapperValuesChanged = false;
  }

  // No need to clear anything. This tonemapping pass just copies pixels and ignores depth.
  renderTargetGL->setClearMask( 0 );
  m_tonemapper->render();
  renderTargetGL->setClearMask( clearMask );
}
void SceneRendererPipeline::doRenderHighlight(dp::sg::ui::ViewStateSharedPtr const& viewState, dp::ui::RenderTargetSharedPtr const& renderTarget)
{
  // only call this if objects need to be rendered highlighted
  DP_ASSERT(m_highlighting);

  // Highlight pass:
  // Match the size of the highlightFBO to the destination renderTarget.
  unsigned int width;
  unsigned int height;
  renderTarget->getSize(width, height);
  m_highlightFBO->setSize(width, height);

  unsigned int originalTraversalMask = viewState->getTraversalMask();
  viewState->setTraversalMask(2); // Render only the highlighted objects.

  glPushAttrib( GL_STENCIL_BUFFER_BIT );

  // If an object is highlighted, render the highlighted object into the stencil buffer of the FBO.

  // Setup the proper stencil state.
  // Write a 1 for every rendered fragment into the stencil buffer
  glStencilFunc(GL_NEVER, 1, ~0);
  glStencilOp(GL_REPLACE, GL_KEEP, GL_KEEP);
  glEnable(GL_STENCIL_TEST);

  // This is always using a SceneRendererGL2 to render the highlighted objects.
  m_highlightFBO->setClearMask( dp::gl::TBM_COLOR_BUFFER
                              | dp::gl::TBM_DEPTH_BUFFER
                              | dp::gl::TBM_STENCIL_BUFFER); // Clear all.

  // A SceneRenderer always uses the scene background color to clear. Temporarily change it to black here.
  dp::math::Vec4f backgroundColor = viewState->getScene()->getBackColor();
  viewState->getScene()->setBackColor( dp::math::Vec4f(0.0f, 0.0f, 0.0f, 0.0f) );

  m_sceneRendererHighlight->render(viewState, m_highlightFBO);

  viewState->getScene()->setBackColor(backgroundColor);

  viewState->setTraversalMask(originalTraversalMask); // Reset the traversal mask.

  // Highlight post-processing:
  // Migrate the stencil bit contents as white color into the texture rectangle.
  m_highlightFBO->setClearMask( dp::gl::TBM_COLOR_BUFFER ); // Do not clear the stencil! Don't care for depth.

  // set the stencil as needed for the stencil to color pass
  glStencilFunc( GL_EQUAL, 1, ~0 );
  glStencilOp( GL_KEEP, GL_KEEP, GL_KEEP );

  m_rendererStencilToColor->render();

  glPopAttrib();

  // Render the outline around the highlighted object onto the main renderTarget (framebuffer).
  dp::gl::RenderTargetSharedPtr const & renderTargetGL = renderTarget.inplaceCast<dp::gl::RenderTarget>();
  dp::gl::TargetBufferMask clearMask = renderTargetGL->getClearMask();

  // keep the following render call from clearing the previous rendered content
  renderTargetGL->setClearMask( 0 );
  m_rendererHighlight->render();
  // restore the clear mask
  renderTargetGL->setClearMask( clearMask );
}