0028762: Visualization, Ray tracing - Implement depth-of-field effect
authorduv <duv@opencascade.com>
Tue, 27 Jun 2017 08:22:31 +0000 (11:22 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 13 Jul 2017 09:23:09 +0000 (12:23 +0300)
Graphic3d_RenderingParams - introduced new parameters CameraFocalPlaneDist and CameraApertureRadius managing DOF effect.
TKOpenGl - added new ray generation logic to RaytraceBase.fs.
vrenderparams command - added -focal and -aperture parameters.
OpenGl_View.hxx - function for ray generating was split into two functions (ray tracing and path tracing).
OpenGl_View_Raytrace.cxx - fixed interaction between adaptive sampling and stereo camera

src/Graphic3d/Graphic3d_RenderingParams.hxx
src/OpenGl/OpenGl_View.cxx
src/OpenGl/OpenGl_View.hxx
src/OpenGl/OpenGl_View_Raytrace.cxx
src/Shaders/RaytraceBase.fs
src/Shaders/Shaders_RaytraceBase_fs.pxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
tests/v3d/raytrace/dof_mono [new file with mode: 0644]
tests/v3d/raytrace/dof_stereo [new file with mode: 0644]

index 4175134..d5bd03a 100644 (file)
@@ -68,6 +68,8 @@ public:
     RadianceClampingValue       (30.0),
     RebuildRayTracingShaders    (Standard_False),
     NbRayTracingTiles           (16 * 16),
+    CameraApertureRadius        (0.0f),
+    CameraFocalPlaneDist        (1.0f),
     ToneMappingMethod           (Graphic3d_ToneMappingMethod_Disabled),
     Exposure                    (0.f),
     WhitePoint                  (1.f),
@@ -119,6 +121,8 @@ public:
   Standard_ShortReal                RadianceClampingValue;       //!< maximum radiance value used for clamping radiance estimation.
   Standard_Boolean                  RebuildRayTracingShaders;    //!< forces rebuilding ray tracing shaders at the next frame
   Standard_Integer                  NbRayTracingTiles;           //!< total number of screen tiles used in adaptive sampling mode (PT only)
+  Standard_ShortReal                CameraApertureRadius;        //!< aperture radius of perspective camera used for depth-of-field, 0.0 by default (no DOF) (path tracing only)
+  Standard_ShortReal                CameraFocalPlaneDist;        //!< focal  distance of perspective camera used for depth-of field, 1.0 by default (path tracing only)
 
   Graphic3d_ToneMappingMethod       ToneMappingMethod;           //!< specifies tone mapping method for path tracing, Graphic3d_ToneMappingMethod_Disabled by default
   Standard_ShortReal                Exposure;                    //!< exposure value used for tone mapping (path tracing), 0.0 by default
index 99fbd51..24de9fe 100644 (file)
@@ -94,7 +94,9 @@ OpenGl_View::OpenGl_View (const Handle(Graphic3d_StructureManager)& theMgr,
   myRaytraceSceneRadius  (0.0f),
   myRaytraceSceneEpsilon (1.0e-6f),
   myToUpdateEnvironmentMap (Standard_False),
-  myRaytraceLayerListState (0)
+  myRaytraceLayerListState (0),
+  myPrevCameraApertureRadius(0.f),
+  myPrevCameraFocalPlaneDist(0.f)
 {
   myWorkspace = new OpenGl_Workspace (this, NULL);
 
index 48da524..03f30c7 100644 (file)
@@ -645,8 +645,10 @@ protected: //! @name data types related to ray-tracing
   {
     OpenGl_RT_OutputImageLft = 0,
     OpenGl_RT_OutputImageRgh = 1,
-    OpenGl_RT_VisualErrorImage = 2,
-    OpenGl_RT_TileOffsetsImage = 3
+    OpenGl_RT_VisualErrorImageLft = 2,
+    OpenGl_RT_VisualErrorImageRgh = 3,
+    OpenGl_RT_TileOffsetsImageLft = 4,
+    OpenGl_RT_TileOffsetsImageRgh = 5
   };
 
   //! Tool class for management of shader sources.
@@ -742,6 +744,9 @@ protected: //! @name data types related to ray-tracing
     //! Number of tiles in Y dimension (in adaptive sampling mode).
     Standard_Integer NbTilesY;
     
+    //! Enables/disables depth-of-field effect (path tracing, perspective camera).
+    Standard_Boolean DepthOfField;
+
     //! Tone mapping method for path tracing.
     Graphic3d_ToneMappingMethod ToneMappingMethod;
 
@@ -758,6 +763,7 @@ protected: //! @name data types related to ray-tracing
       RadianceClampingValue  (30.0),
       NbTilesX               (16),
       NbTilesY               (16),
+      DepthOfField           (Standard_False),
       ToneMappingMethod      (Graphic3d_ToneMappingMethod_Disabled) { }
   };
 
@@ -900,6 +906,7 @@ protected: //! @name methods related to ray-tracing
                                           const Handle(OpenGl_Context)& theGlContext);
 
   //! Generates viewing rays for corners of screen quad.
+  //! (ray tracing; path tracing for orthographic camera)
   void updateCamera (const OpenGl_Mat4& theOrientation,
                      const OpenGl_Mat4& theViewMapping,
                      OpenGl_Vec3*       theOrigins,
@@ -907,6 +914,15 @@ protected: //! @name methods related to ray-tracing
                      OpenGl_Mat4&       theView,
                      OpenGl_Mat4&       theUnView);
 
+  //! Generate viewing rays (path tracing, perspective camera).
+  void updatePerspCameraPT(const OpenGl_Mat4&           theOrientation,
+                           const OpenGl_Mat4&           theViewMapping,
+                           Graphic3d_Camera::Projection theProjection,
+                           OpenGl_Mat4&                 theViewPr,
+                           OpenGl_Mat4&                 theUnview,
+                           const int                    theWinSizeX,
+                           const int                    theWinSizeY);
+
   //! Binds ray-trace textures to corresponding texture units.
   void bindRaytraceTextures (const Handle(OpenGl_Context)& theGlContext);
 
@@ -917,6 +933,7 @@ protected: //! @name methods related to ray-tracing
   Standard_Boolean setUniformState (const Standard_Integer        theProgramId,
                                     const Standard_Integer        theSizeX,
                                     const Standard_Integer        theSizeY,
+                                    Graphic3d_Camera::Projection  theProjection,
                                     const Handle(OpenGl_Context)& theGlContext);
 
   //! Runs ray-tracing shader programs.
@@ -1027,12 +1044,12 @@ protected: //! @name fields related to ray-tracing
   //! Used if adaptive screen sampling is activated.
   Handle(OpenGl_Texture) myRaytraceOutputTexture[2];
 
-  //! Texture containing per-tile visual error estimation.
+  //! Texture containing per-tile visual error estimation (2 textures are used in stereo mode).
   //! Used if adaptive screen sampling is activated.
-  Handle(OpenGl_Texture) myRaytraceVisualErrorTexture;
-  //! Texture containing offsets of sampled screen tiles.
+  Handle(OpenGl_Texture) myRaytraceVisualErrorTexture[2];
+  //! Texture containing offsets of sampled screen tiles (2 textures are used in stereo mode).
   //! Used if adaptive screen sampling is activated.
-  Handle(OpenGl_Texture) myRaytraceTileOffsetsTexture;
+  Handle(OpenGl_Texture) myRaytraceTileOffsetsTexture[2];
 
   //! Vertex buffer (VBO) for drawing dummy quad.
   OpenGl_VertexBuffer myRaytraceScreenQuad;
@@ -1070,6 +1087,27 @@ protected: //! @name fields related to ray-tracing
   //! Tool object for sampling screen tiles in PT mode.
   OpenGl_TileSampler myTileSampler;
 
+  //! Camera position used for projective mode
+  OpenGl_Vec3 myEyeOrig;
+
+  //! Camera view direction used for projective mode
+  OpenGl_Vec3 myEyeView;
+
+  //! Camera's screen vertical direction used for projective mode
+  OpenGl_Vec3 myEyeVert;
+
+  //! Camera's screen horizontal direction used for projective mode
+  OpenGl_Vec3 myEyeSide;
+
+  //! Camera's screen size used for projective mode
+  OpenGl_Vec2 myEyeSize;
+
+  //! Aperture radius of camera on previous frame used for depth-of-field (path tracing)
+  float myPrevCameraApertureRadius;
+
+  //! Focal distance of camera on previous frame used for depth-of-field (path tracing)
+  float myPrevCameraFocalPlaneDist;
+
 public:
 
   DEFINE_STANDARD_ALLOC
index aac555f..0800cf9 100644 (file)
@@ -1149,6 +1149,11 @@ TCollection_AsciiString OpenGl_View::generateShaderPrefix (const Handle(OpenGl_C
     }
   }
 
+  if (myRaytraceParameters.DepthOfField)
+  {
+    aPrefixString += TCollection_AsciiString("\n#define DEPTH_OF_FIELD");
+  }
+
   return aPrefixString;
 }
 
@@ -1411,6 +1416,13 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
       aToRebuildShaders = Standard_True;
     }
 
+    const bool toEnableDof = !myCamera->IsOrthographic() && myRaytraceParameters.GlobalIllumination;
+    if (myRaytraceParameters.DepthOfField != toEnableDof)
+    {
+      myRaytraceParameters.DepthOfField = toEnableDof;
+      aToRebuildShaders = Standard_True;
+    }
+
     if (myRenderParams.ToneMappingMethod != myRaytraceParameters.ToneMappingMethod)
     {
       myRaytraceParameters.ToneMappingMethod = myRenderParams.ToneMappingMethod;
@@ -1830,8 +1842,10 @@ void OpenGl_View::releaseRaytraceResources (const Handle(OpenGl_Context)& theGlC
     nullifyResource (theGlContext, myRaytraceOutputTexture[0]);
     nullifyResource (theGlContext, myRaytraceOutputTexture[1]);
 
-    nullifyResource (theGlContext, myRaytraceTileOffsetsTexture);
-    nullifyResource (theGlContext, myRaytraceVisualErrorTexture);
+    nullifyResource (theGlContext, myRaytraceTileOffsetsTexture[0]);
+    nullifyResource (theGlContext, myRaytraceTileOffsetsTexture[1]);
+    nullifyResource (theGlContext, myRaytraceVisualErrorTexture[0]);
+    nullifyResource (theGlContext, myRaytraceVisualErrorTexture[1]);
 
     nullifyResource (theGlContext, mySceneNodeInfoTexture);
     nullifyResource (theGlContext, mySceneMinPointTexture);
@@ -1914,13 +1928,16 @@ Standard_Boolean OpenGl_View::updateRaytraceBuffers (const Standard_Integer
 
   myTileSampler.SetSize (theSizeX, theSizeY);
 
-  if (myRaytraceTileOffsetsTexture.IsNull())
+  if (myRaytraceTileOffsetsTexture[0].IsNull()
+   || myRaytraceTileOffsetsTexture[1].IsNull())
   {
     myRaytraceOutputTexture[0] = new OpenGl_Texture();
     myRaytraceOutputTexture[1] = new OpenGl_Texture();
 
-    myRaytraceTileOffsetsTexture = new OpenGl_Texture();
-    myRaytraceVisualErrorTexture = new OpenGl_Texture();
+    myRaytraceTileOffsetsTexture[0] = new OpenGl_Texture();
+    myRaytraceTileOffsetsTexture[1] = new OpenGl_Texture();
+    myRaytraceVisualErrorTexture[0] = new OpenGl_Texture();
+    myRaytraceVisualErrorTexture[1] = new OpenGl_Texture();
   }
 
   if (myRaytraceOutputTexture[0]->SizeX() / 3 != theSizeX
@@ -1941,13 +1958,13 @@ Standard_Boolean OpenGl_View::updateRaytraceBuffers (const Standard_Integer
       theSizeX * 3, theSizeY * 2, OpenGl_TextureFormat::Create<GLfloat, 1>());
 
     // workaround for some NVIDIA drivers
-    myRaytraceVisualErrorTexture->Release (theGlContext.operator->());
-    myRaytraceTileOffsetsTexture->Release (theGlContext.operator->());
+    myRaytraceVisualErrorTexture[0]->Release (theGlContext.operator->());
+    myRaytraceTileOffsetsTexture[0]->Release (theGlContext.operator->());
 
-    myRaytraceVisualErrorTexture->Init (theGlContext,
+    myRaytraceVisualErrorTexture[0]->Init (theGlContext,
       GL_R32I, GL_RED_INTEGER, GL_INT, myTileSampler.NbTilesX(), myTileSampler.NbTilesY(), Graphic3d_TOT_2D);
 
-    myRaytraceTileOffsetsTexture->Init (theGlContext,
+    myRaytraceTileOffsetsTexture[0]->Init (theGlContext,
       GL_RG32I, GL_RG_INTEGER, GL_INT, myTileSampler.NbTilesX(), myTileSampler.NbTilesY(), Graphic3d_TOT_2D);
   }
 
@@ -1958,6 +1975,15 @@ Standard_Boolean OpenGl_View::updateRaytraceBuffers (const Standard_Integer
     {
       myRaytraceOutputTexture[1]->InitRectangle (theGlContext,
         theSizeX * 3, theSizeY * 2, OpenGl_TextureFormat::Create<GLfloat, 1>());
+
+      myRaytraceVisualErrorTexture[1]->Release (theGlContext.operator->());
+      myRaytraceTileOffsetsTexture[1]->Release (theGlContext.operator->());
+
+      myRaytraceVisualErrorTexture[1]->Init (theGlContext,
+        GL_R32I, GL_RED_INTEGER, GL_INT, myTileSampler.NbTilesX(), myTileSampler.NbTilesY(), Graphic3d_TOT_2D);
+
+      myRaytraceTileOffsetsTexture[1]->Init (theGlContext,
+        GL_RG32I, GL_RG_INTEGER, GL_INT, myTileSampler.NbTilesX(), myTileSampler.NbTilesY(), Graphic3d_TOT_2D);
     }
   }
   else
@@ -1994,7 +2020,7 @@ void OpenGl_View::updateCamera (const OpenGl_Mat4& theOrientation,
     {
       OpenGl_Vec4 aOrigin (GLfloat(aX),
                            GLfloat(aY),
-                          -1.0f,
+                           -1.0f,
                            1.0f);
 
       aOrigin = theUnview * aOrigin;
@@ -2028,6 +2054,79 @@ void OpenGl_View::updateCamera (const OpenGl_Mat4& theOrientation,
 }
 
 // =======================================================================
+// function : updatePerspCameraPT
+// purpose  : Generates viewing rays (path tracing, perspective camera)
+// =======================================================================
+void OpenGl_View::updatePerspCameraPT (const OpenGl_Mat4&           theOrientation,
+                                       const OpenGl_Mat4&           theViewMapping,
+                                       Graphic3d_Camera::Projection theProjection,
+                                       OpenGl_Mat4&                 theViewPr,
+                                       OpenGl_Mat4&                 theUnview,
+                                       const int                    theWinSizeX,
+                                       const int                    theWinSizeY)
+{
+  // compute view-projection matrix
+  theViewPr = theViewMapping * theOrientation;
+
+  // compute inverse view-projection matrix
+  theViewPr.Inverted(theUnview);
+  
+  // get camera stereo params
+  float anIOD = myCamera->GetIODType() == Graphic3d_Camera::IODType_Relative
+    ? static_cast<float> (myCamera->IOD() * myCamera->Distance())
+    : static_cast<float> (myCamera->IOD());
+
+  float aZFocus = myCamera->ZFocusType() == Graphic3d_Camera::FocusType_Relative
+    ? static_cast<float> (myCamera->ZFocus() * myCamera->Distance())
+    : static_cast<float> (myCamera->ZFocus());
+
+  // get camera view vectors
+  const gp_Pnt anOrig = myCamera->Eye();
+
+  myEyeOrig = OpenGl_Vec3 (static_cast<float> (anOrig.X()),
+                           static_cast<float> (anOrig.Y()),
+                           static_cast<float> (anOrig.Z()));
+
+  const gp_Dir aView = myCamera->Direction();
+
+  OpenGl_Vec3 anEyeViewMono = OpenGl_Vec3 (static_cast<float> (aView.X()),
+                                           static_cast<float> (aView.Y()),
+                                           static_cast<float> (aView.Z()));
+
+  const gp_Dir anUp = myCamera->Up();
+
+  myEyeVert = OpenGl_Vec3 (static_cast<float> (anUp.X()),
+                           static_cast<float> (anUp.Y()),
+                           static_cast<float> (anUp.Z()));
+
+  myEyeSide = OpenGl_Vec3::Cross (anEyeViewMono, myEyeVert);
+
+  const double aScaleY = tan (myCamera->FOVy() / 360 * M_PI);
+  const double aScaleX = theWinSizeX * aScaleY / theWinSizeY;
+  myEyeSize = OpenGl_Vec2 (static_cast<float> (aScaleX),
+                           static_cast<float> (aScaleY));
+
+  if (theProjection == Graphic3d_Camera::Projection_Perspective)
+  {
+    myEyeView = anEyeViewMono;
+  }
+  else // stereo camera
+  {
+    // compute z-focus point
+    OpenGl_Vec3 aZFocusPoint = myEyeOrig + anEyeViewMono * aZFocus;
+
+    // compute stereo camera shift
+    float aDx = theProjection == Graphic3d_Camera::Projection_MonoRightEye ? 0.5f * anIOD : -0.5f * anIOD;
+    myEyeOrig += myEyeSide.Normalized() * aDx;
+
+    // estimate new camera direction vector and correct its length
+    myEyeView = (aZFocusPoint - myEyeOrig).Normalized();
+    myEyeView *= 1.f / anEyeViewMono.Dot (myEyeView);
+  }
+}
+
+// =======================================================================
 // function : uploadRaytraceData
 // purpose  : Uploads ray-trace data to the GPU
 // =======================================================================
@@ -2463,6 +2562,7 @@ Standard_Boolean OpenGl_View::updateRaytraceLightSources (const OpenGl_Mat4& the
 Standard_Boolean OpenGl_View::setUniformState (const Standard_Integer        theProgramId,
                                                const Standard_Integer        theWinSizeX,
                                                const Standard_Integer        theWinSizeY,
+                                               Graphic3d_Camera::Projection  theProjection,
                                                const Handle(OpenGl_Context)& theGlContext)
 {
   // Get projection state
@@ -2473,12 +2573,26 @@ Standard_Boolean OpenGl_View::setUniformState (const Standard_Integer        the
   OpenGl_Vec3 aOrigins[4];
   OpenGl_Vec3 aDirects[4];
 
-  updateCamera (myCamera->OrientationMatrixF(),
-                aCntxProjectionState.Current(),
-                aOrigins,
-                aDirects,
-                aViewPrjMat,
-                anUnviewMat);
+  if (myCamera->IsOrthographic()
+   || !myRenderParams.IsGlobalIlluminationEnabled)
+  {
+    updateCamera (myCamera->OrientationMatrixF(),
+                  aCntxProjectionState.Current(),
+                  aOrigins,
+                  aDirects,
+                  aViewPrjMat,
+                  anUnviewMat);
+  }
+  else
+  {
+    updatePerspCameraPT (myCamera->OrientationMatrixF(),
+                         aCntxProjectionState.Current(),
+                         theProjection,
+                         aViewPrjMat,
+                         anUnviewMat,
+                         theWinSizeX,
+                         theWinSizeY);
+  }
 
   Handle(OpenGl_ShaderProgram)& theProgram = theProgramId == 0
                                            ? myRaytraceProgram
@@ -2488,7 +2602,16 @@ Standard_Boolean OpenGl_View::setUniformState (const Standard_Integer        the
   {
     return Standard_False;
   }
-
+  
+  theProgram->SetUniform(theGlContext, "uEyeOrig", myEyeOrig);
+  theProgram->SetUniform(theGlContext, "uEyeView", myEyeView);
+  theProgram->SetUniform(theGlContext, "uEyeVert", myEyeVert);
+  theProgram->SetUniform(theGlContext, "uEyeSide", myEyeSide);
+  theProgram->SetUniform(theGlContext, "uEyeSize", myEyeSize);
+
+  theProgram->SetUniform(theGlContext, "uApertureRadius", myRenderParams.CameraApertureRadius);
+  theProgram->SetUniform(theGlContext, "uFocalPlaneDist", myRenderParams.CameraFocalPlaneDist);
+  
   // Set camera state
   theProgram->SetUniform (theGlContext,
     myUniformLocations[theProgramId][OpenGl_RT_uOriginLB], aOrigins[0]);
@@ -2614,11 +2737,15 @@ void OpenGl_View::bindRaytraceTextures (const Handle(OpenGl_Context)& theGlConte
     theGlContext->core42->glBindImageTexture (OpenGl_RT_OutputImageRgh,
       myRaytraceOutputTexture[1]->TextureId(), 0, GL_TRUE, 0, GL_READ_WRITE, GL_R32F);
 
-    theGlContext->core42->glBindImageTexture (OpenGl_RT_VisualErrorImage,
-      myRaytraceVisualErrorTexture->TextureId(), 0, GL_TRUE, 0, GL_READ_WRITE, GL_R32I);
-    theGlContext->core42->glBindImageTexture (OpenGl_RT_TileOffsetsImage,
-      myRaytraceTileOffsetsTexture->TextureId(), 0, GL_TRUE, 0, GL_READ_ONLY, GL_RG32I);
-  #endif
+    theGlContext->core42->glBindImageTexture (OpenGl_RT_VisualErrorImageLft,
+      myRaytraceVisualErrorTexture[0]->TextureId(), 0, GL_TRUE, 0, GL_READ_WRITE, GL_R32I);
+    theGlContext->core42->glBindImageTexture (OpenGl_RT_VisualErrorImageRgh,
+      myRaytraceVisualErrorTexture[1]->TextureId(), 0, GL_TRUE, 0, GL_READ_WRITE, GL_R32I);
+    theGlContext->core42->glBindImageTexture (OpenGl_RT_TileOffsetsImageLft,
+      myRaytraceTileOffsetsTexture[0]->TextureId(), 0, GL_TRUE, 0, GL_READ_ONLY, GL_RG32I);
+    theGlContext->core42->glBindImageTexture (OpenGl_RT_TileOffsetsImageRgh,
+      myRaytraceTileOffsetsTexture[1]->TextureId(), 0, GL_TRUE, 0, GL_READ_ONLY, GL_RG32I);
+#endif
   }
 
   if (!myTextureEnv.IsNull() && myTextureEnv->IsValid())
@@ -2673,6 +2800,7 @@ Standard_Boolean OpenGl_View::runRaytraceShaders (const Standard_Integer
   aResult &= setUniformState (0,
                               theSizeX,
                               theSizeY,
+                              theProjection,
                               theGlContext);
 
   if (myRaytraceParameters.GlobalIllumination) // path tracing
@@ -2728,6 +2856,7 @@ Standard_Boolean OpenGl_View::runRaytrace (const Standard_Integer        theSize
     aResult &= setUniformState (1 /* FSAA ID */,
                                 theSizeX,
                                 theSizeY,
+                                theProjection,
                                 theGlContext);
 
     // Perform multi-pass adaptive FSAA using ping-pong technique.
@@ -2830,20 +2959,33 @@ Standard_Boolean OpenGl_View::runPathtrace (const Standard_Integer
   {
     myAccumFrames = myToUpdateEnvironmentMap = 0;
   }
+  
+  if (myRenderParams.CameraApertureRadius != myPrevCameraApertureRadius
+   || myRenderParams.CameraFocalPlaneDist != myPrevCameraFocalPlaneDist)
+  {
+
+    myPrevCameraApertureRadius = myRenderParams.CameraApertureRadius;
+    myPrevCameraFocalPlaneDist = myRenderParams.CameraFocalPlaneDist;
+
+    myAccumFrames = 0;
+  }
+
+  // Choose proper set of frame buffers for stereo rendering
+  const Standard_Integer aFBOIdx (theProjection == Graphic3d_Camera::Projection_MonoRightEye);
 
   if (myRaytraceParameters.AdaptiveScreenSampling)
   {
     if (myAccumFrames == 0)
     {
       myTileSampler.Reset(); // reset tile sampler to its initial state
-    }
 
-    // Adaptive sampling is starting at the second frame
-    myTileSampler.Upload (theGlContext,
-                          myRaytraceTileOffsetsTexture,
-                          myRaytraceParameters.NbTilesX,
-                          myRaytraceParameters.NbTilesY,
-                          myAccumFrames > 0);
+      // Adaptive sampling is starting at the second frame
+      myTileSampler.Upload (theGlContext,
+                            myRaytraceTileOffsetsTexture[aFBOIdx],
+                            myRaytraceParameters.NbTilesX,
+                            myRaytraceParameters.NbTilesY,
+                            false);
+    }
   }
 
   bindRaytraceTextures (theGlContext);
@@ -2852,13 +2994,18 @@ Standard_Boolean OpenGl_View::runPathtrace (const Standard_Integer
   Handle(OpenGl_FrameBuffer) aDepthSourceFramebuffer;
   Handle(OpenGl_FrameBuffer) anAccumImageFramebuffer;
 
-  // Choose proper set of frame buffers for stereo rendering
-  const Standard_Integer aFBOIdx (theProjection == Graphic3d_Camera::Projection_MonoRightEye);
-
   const Standard_Integer anImageId = (aFBOIdx != 0)
                                    ? OpenGl_RT_OutputImageRgh
                                    : OpenGl_RT_OutputImageLft;
 
+  const Standard_Integer anErrorId = (aFBOIdx != 0)
+                                   ? OpenGl_RT_VisualErrorImageRgh
+                                   : OpenGl_RT_VisualErrorImageLft;
+
+  const Standard_Integer anOffsetId = (aFBOIdx != 0)
+                                    ? OpenGl_RT_TileOffsetsImageRgh
+                                    : OpenGl_RT_TileOffsetsImageLft;
+
   aRenderImageFramebuffer = myAccumFrames % 2 ? myRaytraceFBO1[aFBOIdx] : myRaytraceFBO2[aFBOIdx];
   anAccumImageFramebuffer = myAccumFrames % 2 ? myRaytraceFBO2[aFBOIdx] : myRaytraceFBO1[aFBOIdx];
 
@@ -2878,12 +3025,12 @@ Standard_Boolean OpenGl_View::runPathtrace (const Standard_Integer
   if (myRaytraceParameters.AdaptiveScreenSampling)
   {
   #if !defined(GL_ES_VERSION_2_0)
-    if (myAccumFrames == 0)
+    if (myAccumFrames == 0 || (myAccumFrames == 1 && myCamera->IsStereo()))
     {
       theGlContext->core44->glClearTexImage (myRaytraceOutputTexture[aFBOIdx]->TextureId(), 0, GL_RED, GL_FLOAT, NULL);
     }
 
-    theGlContext->core44->glClearTexImage (myRaytraceVisualErrorTexture->TextureId(), 0, GL_RED_INTEGER, GL_INT, NULL);
+    theGlContext->core44->glClearTexImage (myRaytraceVisualErrorTexture[aFBOIdx]->TextureId(), 0, GL_RED_INTEGER, GL_INT, NULL);
   #endif
   }
 
@@ -2899,11 +3046,12 @@ Standard_Boolean OpenGl_View::runPathtrace (const Standard_Integer
   myRaytraceProgram->SetUniform (theGlContext,
     myUniformLocations[0][OpenGl_RT_uRenderImage], anImageId);
   myRaytraceProgram->SetUniform (theGlContext,
-    myUniformLocations[0][OpenGl_RT_uOffsetImage], OpenGl_RT_TileOffsetsImage);
+    myUniformLocations[0][OpenGl_RT_uOffsetImage], anOffsetId);
 
   glDisable (GL_DEPTH_TEST);
 
-  if (myRaytraceParameters.AdaptiveScreenSampling && myAccumFrames > 0)
+  if (myRaytraceParameters.AdaptiveScreenSampling
+   && ((myAccumFrames > 0 && !myCamera->IsStereo()) || myAccumFrames > 1))
   {
     glViewport (0,
                 0,
@@ -2914,7 +3062,8 @@ Standard_Boolean OpenGl_View::runPathtrace (const Standard_Integer
   // Generate for the given RNG seed
   theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
 
-  if (myRaytraceParameters.AdaptiveScreenSampling && myAccumFrames > 0)
+  if (myRaytraceParameters.AdaptiveScreenSampling
+   && ((myAccumFrames > 0 && !myCamera->IsStereo()) || myAccumFrames > 1))
   {
     glViewport (0,
                 0,
@@ -2930,7 +3079,7 @@ Standard_Boolean OpenGl_View::runPathtrace (const Standard_Integer
     // Set uniforms for display program
     myOutImageProgram->SetUniform (theGlContext, "uRenderImage",   anImageId);
     myOutImageProgram->SetUniform (theGlContext, "uAccumFrames",   myAccumFrames);
-    myOutImageProgram->SetUniform (theGlContext, "uVarianceImage", OpenGl_RT_VisualErrorImage);
+    myOutImageProgram->SetUniform (theGlContext, "uVarianceImage", anErrorId);
     myOutImageProgram->SetUniform (theGlContext, "uDebugAdaptive", myRenderParams.ShowSamplingTiles ?  1 : 0);
   }
 
@@ -2969,11 +3118,17 @@ Standard_Boolean OpenGl_View::runPathtrace (const Standard_Integer
 
   if (myRaytraceParameters.AdaptiveScreenSampling)
   {
-    myRaytraceVisualErrorTexture->Bind (theGlContext);
+    myRaytraceVisualErrorTexture[aFBOIdx]->Bind (theGlContext);
 
     // Download visual error map from the GPU and build
     // adjusted tile offsets for optimal image sampling
     myTileSampler.GrabVarianceMap (theGlContext);
+
+    myTileSampler.Upload (theGlContext,
+                          myRaytraceTileOffsetsTexture[aFBOIdx],
+                          myRaytraceParameters.NbTilesX,
+                          myRaytraceParameters.NbTilesY,
+                          myAccumFrames > 0);
   }
 
   unbindRaytraceTextures (theGlContext);
index 4f08b83..c9edddf 100644 (file)
@@ -108,6 +108,27 @@ uniform vec4 uBackColorTop = vec4 (0.0);
 //! Bottom color of gradient background.
 uniform vec4 uBackColorBot = vec4 (0.0);
 
+//! Aperture radius of camera used for depth-of-field
+uniform float uApertureRadius = 0.f;
+
+//! Focal distance of camera used for depth-of field
+uniform float uFocalPlaneDist = 10.f;
+
+//! Camera position used for projective mode
+uniform vec3 uEyeOrig;
+
+//! Camera view direction used for projective mode
+uniform vec3 uEyeView;
+
+//! Camera's screen vertical direction used for projective mode
+uniform vec3 uEyeVert;
+
+//! Camera's screen horizontal direction used for projective mode
+uniform vec3 uEyeSide;
+
+//! Camera's screen size used for projective mode
+uniform vec2 uEyeSize;
+
 /////////////////////////////////////////////////////////////////////////////////////////
 // Specific data types
 
@@ -271,12 +292,43 @@ vec4 BackgroundColor()
 /////////////////////////////////////////////////////////////////////////////////////////
 // Functions for compute ray-object intersection
 
+//=======================================================================
+// function : sampleUniformDisk
+// purpose  :
+//=======================================================================
+vec2 sampleUniformDisk ()
+{
+  vec2 aPoint;
+
+  float aKsi1 = 2.f * RandFloat () - 1.f;
+  float aKsi2 = 2.f * RandFloat () - 1.f;
+
+  if (aKsi1 > -aKsi2)
+  {
+    if (aKsi1 > aKsi2)
+      aPoint = vec2 (aKsi1, (M_PI / 4.f) * (0.f + aKsi2 / aKsi1));
+    else
+      aPoint = vec2 (aKsi2, (M_PI / 4.f) * (2.f - aKsi1 / aKsi2));
+  }
+  else
+  {
+    if (aKsi1 < aKsi2)
+      aPoint = vec2 (-aKsi1, (M_PI / 4.f) * (4.f + aKsi2 / aKsi1));
+    else
+      aPoint = vec2 (-aKsi2, (M_PI / 4.f) * (6.f - aKsi1 / aKsi2));
+  }
+
+  return vec2 (sin (aPoint.y), cos (aPoint.y)) * aPoint.x;
+}
+
 // =======================================================================
 // function : GenerateRay
 // purpose  :
 // =======================================================================
 SRay GenerateRay (in vec2 thePixel)
 {
+#ifndef DEPTH_OF_FIELD
+
   vec3 aP0 = mix (uOriginLB, uOriginRB, thePixel.x);
   vec3 aP1 = mix (uOriginLT, uOriginRT, thePixel.x);
 
@@ -286,6 +338,27 @@ SRay GenerateRay (in vec2 thePixel)
   vec3 aDirection = normalize (mix (aD0, aD1, thePixel.y));
 
   return SRay (mix (aP0, aP1, thePixel.y), aDirection);
+
+#else
+
+  vec2 aPixel = uEyeSize * (thePixel - vec2 (0.5f)) * 2.f;
+
+  vec2 aAperturePnt = sampleUniformDisk () * uApertureRadius;
+
+  vec3 aLocalDir = normalize (vec3 (
+    aPixel * uFocalPlaneDist - aAperturePnt, uFocalPlaneDist));
+
+  vec3 aOrigin = uEyeOrig +
+                 uEyeSide * aAperturePnt.x +
+                 uEyeVert * aAperturePnt.y;
+
+  vec3 aDirect = uEyeView * aLocalDir.z +
+                 uEyeSide * aLocalDir.x +
+                 uEyeVert * aLocalDir.y;
+
+  return SRay (aOrigin, aDirect);
+
+#endif
 }
 
 // =======================================================================
index a25d6fc..81a2ae0 100644 (file)
@@ -111,6 +111,27 @@ static const char Shaders_RaytraceBase_fs[] =
   "//! Bottom color of gradient background.\n"
   "uniform vec4 uBackColorBot = vec4 (0.0);\n"
   "\n"
+  "//! Aperture radius of camera used for depth-of-field\n"
+  "uniform float uApertureRadius = 0.f;\n"
+  "\n"
+  "//! Focal distance of camera used for depth-of field\n"
+  "uniform float uFocalPlaneDist = 10.f;\n"
+  "\n"
+  "//! Camera position used for projective mode\n"
+  "uniform vec3 uEyeOrig;\n"
+  "\n"
+  "//! Camera view direction used for projective mode\n"
+  "uniform vec3 uEyeView;\n"
+  "\n"
+  "//! Camera's screen vertical direction used for projective mode\n"
+  "uniform vec3 uEyeVert;\n"
+  "\n"
+  "//! Camera's screen horizontal direction used for projective mode\n"
+  "uniform vec3 uEyeSide;\n"
+  "\n"
+  "//! Camera's screen size used for projective mode\n"
+  "uniform vec2 uEyeSize;\n"
+  "\n"
   "/////////////////////////////////////////////////////////////////////////////////////////\n"
   "// Specific data types\n"
   "\n"
@@ -274,12 +295,43 @@ static const char Shaders_RaytraceBase_fs[] =
   "/////////////////////////////////////////////////////////////////////////////////////////\n"
   "// Functions for compute ray-object intersection\n"
   "\n"
+  "//=======================================================================\n"
+  "// function : sampleUniformDisk\n"
+  "// purpose  :\n"
+  "//=======================================================================\n"
+  "vec2 sampleUniformDisk ()\n"
+  "{\n"
+  "  vec2 aPoint;\n"
+  "\n"
+  "  float aKsi1 = 2.f * RandFloat () - 1.f;\n"
+  "  float aKsi2 = 2.f * RandFloat () - 1.f;\n"
+  "\n"
+  "  if (aKsi1 > -aKsi2)\n"
+  "  {\n"
+  "    if (aKsi1 > aKsi2)\n"
+  "      aPoint = vec2 (aKsi1, (M_PI / 4.f) * (0.f + aKsi2 / aKsi1));\n"
+  "    else\n"
+  "      aPoint = vec2 (aKsi2, (M_PI / 4.f) * (2.f - aKsi1 / aKsi2));\n"
+  "  }\n"
+  "  else\n"
+  "  {\n"
+  "    if (aKsi1 < aKsi2)\n"
+  "      aPoint = vec2 (-aKsi1, (M_PI / 4.f) * (4.f + aKsi2 / aKsi1));\n"
+  "    else\n"
+  "      aPoint = vec2 (-aKsi2, (M_PI / 4.f) * (6.f - aKsi1 / aKsi2));\n"
+  "  }\n"
+  "\n"
+  "  return vec2 (sin (aPoint.y), cos (aPoint.y)) * aPoint.x;\n"
+  "}\n"
+  "\n"
   "// =======================================================================\n"
   "// function : GenerateRay\n"
   "// purpose  :\n"
   "// =======================================================================\n"
   "SRay GenerateRay (in vec2 thePixel)\n"
   "{\n"
+  "#ifndef DEPTH_OF_FIELD\n"
+  "\n"
   "  vec3 aP0 = mix (uOriginLB, uOriginRB, thePixel.x);\n"
   "  vec3 aP1 = mix (uOriginLT, uOriginRT, thePixel.x);\n"
   "\n"
@@ -289,6 +341,27 @@ static const char Shaders_RaytraceBase_fs[] =
   "  vec3 aDirection = normalize (mix (aD0, aD1, thePixel.y));\n"
   "\n"
   "  return SRay (mix (aP0, aP1, thePixel.y), aDirection);\n"
+  "\n"
+  "#else\n"
+  "\n"
+  "  vec2 aPixel = uEyeSize * (thePixel - vec2 (0.5f)) * 2.f;\n"
+  "\n"
+  "  vec2 aAperturePnt = sampleUniformDisk () * uApertureRadius;\n"
+  "\n"
+  "  vec3 aLocalDir = normalize (vec3 (\n"
+  "    aPixel * uFocalPlaneDist - aAperturePnt, uFocalPlaneDist));\n"
+  "\n"
+  "  vec3 aOrigin = uEyeOrig +\n"
+  "                 uEyeSide * aAperturePnt.x +\n"
+  "                 uEyeVert * aAperturePnt.y;\n"
+  "\n"
+  "  vec3 aDirect = uEyeView * aLocalDir.z +\n"
+  "                 uEyeSide * aLocalDir.x +\n"
+  "                 uEyeVert * aLocalDir.y;\n"
+  "\n"
+  "  return SRay (aOrigin, aDirect);\n"
+  "\n"
+  "#endif\n"
   "}\n"
   "\n"
   "// =======================================================================\n"
index cb2ce78..82f9678 100644 (file)
@@ -9647,6 +9647,56 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
       }
       aParams.RebuildRayTracingShaders = toEnable;
     }
+    else if (aFlag == "-focal")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      TCollection_AsciiString aParam (theArgVec[anArgIter]);
+      if (aParam.IsRealValue())
+      {
+        float aFocalDist = static_cast<float> (aParam.RealValue());
+        if (aFocalDist < 0)
+        {
+          std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
+          return 1;
+        }
+        aView->ChangeRenderingParams().CameraFocalPlaneDist = aFocalDist;
+      }
+      else
+      {
+        std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
+        return 1;
+      }
+    }
+    else if (aFlag == "-aperture")
+    {
+      if (++anArgIter >= theArgNb)
+      {
+        std::cout << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      TCollection_AsciiString aParam(theArgVec[anArgIter]);
+      if (aParam.IsRealValue())
+      {
+        float aApertureSize = static_cast<float> (aParam.RealValue());
+        if (aApertureSize < 0)
+        {
+          std::cout << "Error: parameter can't be negative at argument '" << anArg << "'.\n";
+          return 1;
+        }
+        aView->ChangeRenderingParams().CameraApertureRadius = aApertureSize;
+      }
+      else
+      {
+        std::cout << "Error: wrong syntax at argument'" << anArg << "'.\n";
+        return 1;
+      }
+    }
     else if (aFlag == "-exposure")
     {
       if (++anArgIter >= theArgNb)
@@ -11205,6 +11255,8 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "\n      '-shadingModel model'       Controls shading model from enumeration"
     "\n                                  color, flat, gouraud, phong"
     "\n      '-resolution   value'       Sets a new pixels density (PPI), defines scaling factor for parameters like text size"
+    "\n      '-aperture     >= 0.0'      Aperture size  of perspective camera for depth-of-field effect (0 disables DOF)"
+    "\n      '-focal        >= 0.0'      Focal distance of perspective camera for depth-of-field effect"
     "\n      '-exposure     value'       Exposure value for tone mapping (0.0 value disables the effect)"
     "\n      '-whitepoint   value'       White point value for filmic tone mapping"
     "\n      '-tonemapping  mode'        Tone mapping mode (disabled, filmic)"
diff --git a/tests/v3d/raytrace/dof_mono b/tests/v3d/raytrace/dof_mono
new file mode 100644 (file)
index 0000000..a919850
--- /dev/null
@@ -0,0 +1,70 @@
+puts "========"
+puts "Ray Tracing - check depth-of-field"
+puts "========"
+
+pload MODELING VISUALIZATION
+
+vclear
+vinit View1
+
+vlight add positional head 0 pos 0.5 0.5 0.85
+vlight change 0 sm 0.06
+vlight change 0 int 25.0
+
+vsetdispmode 1
+vcamera -persp
+
+box b 1 1 1 
+explode b FACE 
+vdisplay -noupdate b_1 b_2 b_3 b_5 b_6
+vlocation -noupdate b_1 -setLocation  1  0  0
+vlocation -noupdate b_2 -setLocation -1  0  0
+vlocation -noupdate b_3 -setLocation  0  1  0
+vlocation -noupdate b_5 -setLocation  0  0  1
+vlocation -noupdate b_6 -setLocation  0  0 -1
+
+vsetmaterial -noupdate b_1 plastic
+vsetmaterial -noupdate b_2 plastic
+vsetmaterial -noupdate b_3 plastic
+vsetmaterial -noupdate b_5 plastic
+vsetmaterial -noupdate b_6 plastic
+vbsdf b_1 -kd 1 0.3 0.3 -ks 0
+vbsdf b_2 -kd 0.3 0.5 1 -ks 0
+vbsdf b_3 -kd 1 -ks 0
+vbsdf b_5 -kd 1 -ks 0
+vbsdf b_6 -kd 1 -ks 0
+
+vfront
+vfit
+
+psphere s 0.2
+vdisplay     -noupdate s
+vlocation    -noupdate s -setLocation 0.21 0.3 0.2
+vsetmaterial -noupdate s glass
+vbsdf s -absorpColor 0.8 0.8 1.0
+vbsdf s -absorpCoeff 6
+
+box c 0.3 0.3 0.2
+vdisplay     -noupdate c
+vlocation    -noupdate c -setLocation 0.55 0.3 0.0
+vlocation    -noupdate c -rotate 0 0 0 0 0 1 -30
+vsetmaterial -noupdate c plastic
+vbsdf c -kd 1.0 0.8 0.2 -ks 0.3 -n
+
+box g 0.15 0.15 0.3
+vdisplay     -noupdate g
+vlocation    -noupdate g -setLocation 0.7 0.25 0.2
+vlocation    -noupdate g -rotate 0 0 0 0 0 1 10
+vsetmaterial -noupdate g glass
+vbsdf g -absorpColor 0.8 1.0 0.8
+vbsdf g -absorpCoeff 6
+
+psphere r 0.1
+vdisplay -noupdate r
+vsetmaterial -noupdate r plastic
+vbsdf r -kd 0.5 0.9 0.3 -ks 0.3 -baseRoughness 0.0 -n
+vbsdf r -baseFresnel Constant 1.0
+vlocation r -setLocation 0.5 0.65 0.1
+
+vrenderparams -ray -gi -rayDepth 10 -iss
+vrenderparams -aperture 0.1 -focal 2.0
diff --git a/tests/v3d/raytrace/dof_stereo b/tests/v3d/raytrace/dof_stereo
new file mode 100644 (file)
index 0000000..ec3e094
--- /dev/null
@@ -0,0 +1,76 @@
+puts "========"
+puts "Ray Tracing - check depth-of-field"
+puts "========"
+
+pload MODELING VISUALIZATION
+
+vclear
+vinit View1
+
+vlight add positional head 0 pos 0.5 0.5 0.85
+vlight change 0 sm 0.06
+vlight change 0 int 25.0
+
+vsetdispmode 1
+vcamera -persp
+
+box b 1 1 1 
+explode b FACE 
+vdisplay -noupdate b_1 b_2 b_3 b_5 b_6
+vlocation -noupdate b_1 -setLocation  1  0  0
+vlocation -noupdate b_2 -setLocation -1  0  0
+vlocation -noupdate b_3 -setLocation  0  1  0
+vlocation -noupdate b_5 -setLocation  0  0  1
+vlocation -noupdate b_6 -setLocation  0  0 -1
+
+vsetmaterial -noupdate b_1 plastic
+vsetmaterial -noupdate b_2 plastic
+vsetmaterial -noupdate b_3 plastic
+vsetmaterial -noupdate b_5 plastic
+vsetmaterial -noupdate b_6 plastic
+vbsdf b_1 -kd 1 0.3 0.3 -ks 0
+vbsdf b_2 -kd 0.3 0.5 1 -ks 0
+vbsdf b_3 -kd 1 -ks 0
+vbsdf b_5 -kd 1 -ks 0
+vbsdf b_6 -kd 1 -ks 0
+
+vfront
+vfit
+
+psphere s 0.2
+vdisplay     -noupdate s
+vlocation    -noupdate s -setLocation 0.21 0.3 0.2
+vsetmaterial -noupdate s glass
+vbsdf s -absorpColor 0.8 0.8 1.0
+vbsdf s -absorpCoeff 6
+
+box c 0.3 0.3 0.2
+vdisplay     -noupdate c
+vlocation    -noupdate c -setLocation 0.55 0.3 0.0
+vlocation    -noupdate c -rotate 0 0 0 0 0 1 -30
+vsetmaterial -noupdate c plastic
+vbsdf c -kd 1.0 0.8 0.2 -ks 0.3 -n
+
+box g 0.15 0.15 0.3
+vdisplay     -noupdate g
+vlocation    -noupdate g -setLocation 0.7 0.25 0.2
+vlocation    -noupdate g -rotate 0 0 0 0 0 1 10
+vsetmaterial -noupdate g glass
+vbsdf g -absorpColor 0.8 1.0 0.8
+vbsdf g -absorpCoeff 6
+
+psphere r 0.1
+vdisplay -noupdate r
+vsetmaterial -noupdate r plastic
+vbsdf r -kd 0.5 0.9 0.3 -ks 0.3 -baseRoughness 0.0 -n
+vbsdf r -baseFresnel Constant 1.0
+vlocation r -setLocation 0.5 0.65 0.1
+
+vrenderparams -ray -gi -rayDepth 10 -iss
+vrenderparams -aperture 0.1 -focal 2.0
+
+# activate stereo
+vstereo on
+vstereo -mode anaglyph
+vcamera -iod 0.1
+vfit