]> OCCT Git - occt-copy.git/commitdiff
0028129: Visualization, Path Tracing - Improve interactivity in "steady" rendering...
authordbp <dbp@opencascade.com>
Thu, 26 Jan 2017 09:56:13 +0000 (12:56 +0300)
committerkgv <kgv@opencascade.com>
Sat, 17 Mar 2018 09:50:08 +0000 (12:50 +0300)
Re-basing the patch on current master.

13 files changed:
src/Graphic3d/Graphic3d_RenderingParams.hxx
src/OpenGl/OpenGl_TileSampler.cxx
src/OpenGl/OpenGl_TileSampler.hxx
src/OpenGl/OpenGl_View.hxx
src/OpenGl/OpenGl_View_Raytrace.cxx
src/Shaders/Display.fs
src/Shaders/PathtraceBase.fs
src/Shaders/RaytraceRender.fs
src/Shaders/Shaders_Display_fs.pxx
src/Shaders/Shaders_PathtraceBase_fs.pxx
src/Shaders/Shaders_RaytraceRender_fs.pxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
tests/v3d/raytrace/sample_ball_iss [new file with mode: 0644]

index b264d443610f1da222c85e5f0f99e18db9340aaf..33ca9e3ea372c379d1cfc0ca5ce2452c4ec61fe5 100644 (file)
@@ -62,6 +62,7 @@ public:
     TwoSidedBsdfModels          (Standard_False),
     RadianceClampingValue       (30.0),
     RebuildRayTracingShaders    (Standard_False),
+    NbRayTracingTiles           (16 * 16),
     // stereoscopic parameters
     StereoMode (Graphic3d_StereoMode_QuadBuffer),
     AnaglyphFilter (Anaglyph_RedCyan_Optimized),
@@ -105,6 +106,7 @@ public:
   Standard_Boolean        TwoSidedBsdfModels;          //!< forces path tracing to use two-sided versions of original one-sided scattering models
   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)
 
   Graphic3d_StereoMode    StereoMode;                  //!< stereoscopic output mode, Graphic3d_StereoMode_QuadBuffer by default
   Anaglyph                AnaglyphFilter;              //!< filter for anaglyph output, Anaglyph_RedCyan_Optimized by default
index 6e8a1dc39388a0c45ff35f7a9548b31a86d1cc16..c9b9b88e0f50b4ce199d0c16ae07032631458012 100644 (file)
@@ -150,36 +150,45 @@ void OpenGl_TileSampler::SetSize (const int theSizeX,
 //=======================================================================
 void OpenGl_TileSampler::Upload (const Handle(OpenGl_Context)& theContext,
                                  const Handle(OpenGl_Texture)& theTexture,
-                                 bool theAdaptive)
+                                 const int                     theNbTilesX,
+                                 const int                     theNbTilesY,
+                                 const bool                    theAdaptive)
 {
   if (theTexture.IsNull())
   {
     return;
   }
 
-  std::vector<GLint> aData (myTilesX * myTilesY * 2);
-  for (int aX = 0; aX < myTilesX; ++aX)
+  const int aNbTilesX = theAdaptive ? theNbTilesX : myTilesX;
+  const int aNbTilesY = theAdaptive ? theNbTilesY : myTilesY;
+
+  Standard_ASSERT_RAISE (aNbTilesX * aNbTilesY > 0,
+    "Error! Number of sampling tiles should be positive");
+
+  std::vector<GLint> aData (aNbTilesX * aNbTilesY * 2);
+
+  for (int aX = 0; aX < aNbTilesX; ++aX)
   {
-    for (int aY = 0; aY < myTilesY; ++aY)
+    for (int aY = 0; aY < aNbTilesY; ++aY)
     {
       if (!theAdaptive)
       {
-        aData[(aY * myTilesX + aX) * 2 + 0] = aX * TileSize();
-        aData[(aY * myTilesX + aX) * 2 + 1] = aY * TileSize();
+        aData[(aY * aNbTilesX + aX) * 2 + 0] = aX * TileSize();
+        aData[(aY * aNbTilesX + aX) * 2 + 1] = aY * TileSize();
       }
       else
       {
-        Sample (aData[(aY * myTilesX + aX) * 2 + 0],
-                aData[(aY * myTilesX + aX) * 2 + 1]);
+        Sample (aData[(aY * aNbTilesX + aX) * 2 + 0],
+                aData[(aY * aNbTilesX + aX) * 2 + 1]);
       }
     }
   }
 
   theTexture->Bind (theContext);
 
-  theContext->core11fwd->glTexImage2D (GL_TEXTURE_2D, 0, GL_RG32I, myTilesX, myTilesY, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, &aData.front());
-  const GLenum anErr = theContext->core11fwd->glGetError();
-  if (anErr != GL_NO_ERROR)
+  theContext->core11fwd->glTexImage2D (GL_TEXTURE_2D, 0, GL_RG32I, aNbTilesX, aNbTilesY, 0, GL_RG_INTEGER, GL_UNSIGNED_INT, &aData.front());
+
+  if (theContext->core11fwd->glGetError() != GL_NO_ERROR)
   {
     theContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_MEDIUM,
                              "Error! Failed to upload tile offset map on the GPU");
index 4f272930b0b5ead02be716bc75155dfbdedc51c3..9fc975358d438f073dd455a4057ca5810886e785 100644 (file)
 #include <vector>
 
 //! Tool object used for sampling screen tiles according to estimated pixel variance (used in path tracing engine).
-//! To improve GPU thread coherency, render window is split into pixel blocks or tiles.
+//! To improve GPU thread coherency, rendering window is split into pixel blocks or tiles. The important feature of
+//! this approach is that it is possible to keep the same number of tiles for any screen resolution (e.g. 256 tiles
+//! can be used for both 512 x 512 window and 1920 x 1080 window). So, a smaller number of tiles allows to increase
+//! interactivity (FPS), but at the cost of higher per-frame variance ('noise'). On the contrary a larger number of
+//! tiles decrease interactivity, but leads to lower per-frame variance. Note that the total time needed to produce
+//! final final image is the same for both cases.
 class OpenGl_TileSampler
 {
 public:
@@ -76,7 +81,9 @@ public:
   //! Uploads offsets of sampled tiles to the given OpenGL texture.
   Standard_EXPORT void Upload (const Handle(OpenGl_Context)& theContext,
                                const Handle(OpenGl_Texture)& theTexture,
-                               bool theAdaptive);
+                               const int                     theNbTilesX,
+                               const int                     theNbTilesY,
+                               const bool                    theAdaptive);
 
 protected:
 
index 45f44cc5fe85b8cb74f5a89c1ec8ed65727e272b..7eaadd2b67cff3742fdd4794b806a58241105d06 100644 (file)
@@ -711,6 +711,12 @@ protected: //! @name data types related to ray-tracing
     //! Maximum radiance value used for clamping radiance estimation.
     Standard_ShortReal RadianceClampingValue;
 
+    //! Number of tiles in X dimension (in adaptive sampling mode).
+    Standard_Integer NbTilesX;
+    
+    //! Number of tiles in Y dimension (in adaptive sampling mode).
+    Standard_Integer NbTilesY;
+
     //! Creates default compile-time ray-tracing parameters.
     RaytracingParams()
     : StackSize              (THE_DEFAULT_STACK_SIZE),
@@ -721,7 +727,9 @@ protected: //! @name data types related to ray-tracing
       TwoSidedBsdfModels     (Standard_False),
       AdaptiveScreenSampling (Standard_False),
       UseEnvMapForBackground (Standard_False),
-      RadianceClampingValue  (30.0)            { }
+      RadianceClampingValue  (30.0),
+      NbTilesX               (16),
+      NbTilesY               (16) { }
   };
 
   //! Describes state of OpenGL structure.
@@ -897,9 +905,11 @@ protected: //! @name methods related to ray-tracing
                                 const Handle(OpenGl_Context)& theGlContext);
 
   //! Runs path tracing (global illumination) kernel.
-  Standard_Boolean runPathtrace (const Graphic3d_Camera::Projection theProjection,
-                                 OpenGl_FrameBuffer*                theReadDrawFbo,
-                                 const Handle(OpenGl_Context)&      theGlContext);
+  Standard_Boolean runPathtrace (const Standard_Integer        theSizeX,
+                                 const Standard_Integer        theSizeY,
+                                 Graphic3d_Camera::Projection  theProjection,
+                                 OpenGl_FrameBuffer*           theReadDrawFbo,
+                                 const Handle(OpenGl_Context)& theGlContext);
 
   //! Redraws the window using OpenGL/GLSL ray-tracing or path tracing.
   Standard_Boolean raytrace (const Standard_Integer        theSizeX,
index 54494ef0d11562baeb8534cf588262a5d698f09e..c078c546d543830a025ad320c3d4b87a6bfbea05 100644 (file)
@@ -1359,11 +1359,21 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
       }
     }
 
+    Standard_Integer aNbTilesX = 8;
+    Standard_Integer aNbTilesY = 8;
+
+    for (Standard_Integer anIdx = 0; aNbTilesX * aNbTilesY < myRenderParams.NbRayTracingTiles; ++anIdx)
+    {
+      (anIdx % 2 == 0 ? aNbTilesX : aNbTilesY) <<= 1;
+    }
+
     if (myRenderParams.RaytracingDepth             != myRaytraceParameters.NbBounces
      || myRenderParams.IsTransparentShadowEnabled  != myRaytraceParameters.TransparentShadows
      || myRenderParams.IsGlobalIlluminationEnabled != myRaytraceParameters.GlobalIllumination
      || myRenderParams.TwoSidedBsdfModels          != myRaytraceParameters.TwoSidedBsdfModels
-     || myRaytraceGeometry.HasTextures()           != myRaytraceParameters.UseBindlessTextures)
+     || myRaytraceGeometry.HasTextures()           != myRaytraceParameters.UseBindlessTextures
+     || aNbTilesX                                  != myRaytraceParameters.NbTilesX
+     || aNbTilesY                                  != myRaytraceParameters.NbTilesY)
     {
       myRaytraceParameters.NbBounces           = myRenderParams.RaytracingDepth;
       myRaytraceParameters.TransparentShadows  = myRenderParams.IsTransparentShadowEnabled;
@@ -1371,6 +1381,18 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
       myRaytraceParameters.TwoSidedBsdfModels  = myRenderParams.TwoSidedBsdfModels;
       myRaytraceParameters.UseBindlessTextures = myRaytraceGeometry.HasTextures();
 
+#ifdef RAY_TRACE_PRINT_INFO
+      if (aNbTilesX != myRaytraceParameters.NbTilesX
+       || aNbTilesY != myRaytraceParameters.NbTilesY)
+      {
+        std::cout << "Number of tiles X: " << aNbTilesX << "\n";
+        std::cout << "Number of tiles Y: " << aNbTilesY << "\n";
+      }
+#endif
+
+      myRaytraceParameters.NbTilesX = aNbTilesX;
+      myRaytraceParameters.NbTilesY = aNbTilesY;
+
       aToRebuildShaders = Standard_True;
     }
 
@@ -1848,25 +1870,42 @@ Standard_Boolean OpenGl_View::updateRaytraceBuffers (const Standard_Integer
     return Standard_True;
   }
 
-  if (myRaytraceFBO1[0]->GetSizeX() != theSizeX
-   || myRaytraceFBO1[0]->GetSizeY() != theSizeY)
+  if (myRaytraceParameters.AdaptiveScreenSampling)
   {
-    myAccumFrames = 0;
-  }
+    const Standard_Integer aSizeX = std::max (myRaytraceParameters.NbTilesX * 64, theSizeX);
+    const Standard_Integer aSizeY = std::max (myRaytraceParameters.NbTilesY * 64, theSizeY);
 
-  myRaytraceFBO1[0]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
-  myRaytraceFBO2[0]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
+    myRaytraceFBO1[0]->InitLazy (theGlContext, aSizeX, aSizeY, GL_RGBA32F, myFboDepthFormat);
+    myRaytraceFBO2[0]->InitLazy (theGlContext, aSizeX, aSizeY, GL_RGBA32F, myFboDepthFormat);
 
-  // Init second set of buffers for stereographic rendering.
-  if (myCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
-  {
-    myRaytraceFBO1[1]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
-    myRaytraceFBO2[1]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
+    if (myRaytraceFBO1[1]->IsValid()) // second FBO not needed
+    {
+      myRaytraceFBO1[1]->Release (theGlContext.operator->());
+      myRaytraceFBO2[1]->Release (theGlContext.operator->());
+    }
   }
-  else
+  else // non-adaptive mode
   {
-    myRaytraceFBO1[1]->Release (theGlContext.operator->());
-    myRaytraceFBO2[1]->Release (theGlContext.operator->());
+    if (myRaytraceFBO1[0]->GetSizeX() != theSizeX
+     || myRaytraceFBO1[0]->GetSizeY() != theSizeY)
+    {
+      myAccumFrames = 0; // accumulation should be restarted
+    }
+
+    myRaytraceFBO1[0]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
+    myRaytraceFBO2[0]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
+
+    // Init second set of buffers for stereographic rendering
+    if (myCamera->ProjectionType() == Graphic3d_Camera::Projection_Stereo)
+    {
+      myRaytraceFBO1[1]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
+      myRaytraceFBO2[1]->InitLazy (theGlContext, theSizeX, theSizeY, GL_RGBA32F, myFboDepthFormat);
+    }
+    else if (myRaytraceFBO1[1]->IsValid()) // second FBO not needed
+    {
+      myRaytraceFBO1[1]->Release (theGlContext.operator->());
+      myRaytraceFBO2[1]->Release (theGlContext.operator->());
+    }
   }
 
   myTileSampler.SetSize (theSizeX, theSizeY);
@@ -1883,6 +1922,8 @@ Standard_Boolean OpenGl_View::updateRaytraceBuffers (const Standard_Integer
   if (myRaytraceOutputTexture[0]->SizeX() / 3 != theSizeX
    || myRaytraceOutputTexture[0]->SizeY() / 2 != theSizeY)
   {
+    myAccumFrames = 0;
+
     // Due to limitations of OpenGL image load-store extension
     // atomic operations are supported only for single-channel
     // images, so we define GL_R32F image. It is used as array
@@ -2634,7 +2675,7 @@ Standard_Boolean OpenGl_View::runRaytraceShaders (const Standard_Integer
 
   if (myRaytraceParameters.GlobalIllumination) // path tracing
   {
-    aResult &= runPathtrace (theProjection, theReadDrawFbo, theGlContext);
+    aResult &= runPathtrace (theSizeX, theSizeY, theProjection, theReadDrawFbo, theGlContext);
   }
   else // Whitted-style ray-tracing
   {
@@ -2775,7 +2816,9 @@ Standard_Boolean OpenGl_View::runRaytrace (const Standard_Integer        theSize
 // function : runPathtrace
 // purpose  : Runs path tracing shader
 // =======================================================================
-Standard_Boolean OpenGl_View::runPathtrace (const Graphic3d_Camera::Projection  theProjection,
+Standard_Boolean OpenGl_View::runPathtrace (const Standard_Integer              theSizeX,
+                                            const Standard_Integer              theSizeY,
+                                            const Graphic3d_Camera::Projection  theProjection,
                                             OpenGl_FrameBuffer*                 theReadDrawFbo,
                                             const Handle(OpenGl_Context)&       theGlContext)
 {
@@ -2793,13 +2836,12 @@ Standard_Boolean OpenGl_View::runPathtrace (const Graphic3d_Camera::Projection
       myTileSampler.Reset(); // reset tile sampler to its initial state
     }
 
-    // We upload tile offset texture each 4 frames in order
-    // to minimize overhead of additional memory bandwidth.
-    // Adaptive sampling is starting after first 30 frames.
-    if (myAccumFrames % 4 == 0)
-    {
-      myTileSampler.Upload (theGlContext, myRaytraceTileOffsetsTexture, myAccumFrames > 30);
-    }
+    // Adaptive sampling is starting at the second frame
+    myTileSampler.Upload (theGlContext,
+                          myRaytraceTileOffsetsTexture,
+                          myRaytraceParameters.NbTilesX,
+                          myRaytraceParameters.NbTilesY,
+                          myAccumFrames > 0);
   }
 
   bindRaytraceTextures (theGlContext);
@@ -2859,9 +2901,25 @@ Standard_Boolean OpenGl_View::runPathtrace (const Graphic3d_Camera::Projection
 
   glDisable (GL_DEPTH_TEST);
 
+  if (myRaytraceParameters.AdaptiveScreenSampling && myAccumFrames > 0)
+  {
+    glViewport (0,
+                0,
+                myTileSampler.TileSize() * myRaytraceParameters.NbTilesX,
+                myTileSampler.TileSize() * myRaytraceParameters.NbTilesY);
+  }
+
   // Generate for the given RNG seed
   theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
 
+  if (myRaytraceParameters.AdaptiveScreenSampling && myAccumFrames > 0)
+  {
+    glViewport (0,
+                0,
+                theSizeX,
+                theSizeY);
+  }
+
   // Output accumulated path traced image
   theGlContext->BindProgram (myOutImageProgram);
 
index c4f9faa175c8c57cd377b5678bab5a22a705cc60..6aff9c13316aa95b7f73eed251cae077d119088a 100644 (file)
@@ -2,6 +2,8 @@
 
   #extension GL_ARB_shader_image_load_store : require
 
+  #extension GL_ARB_shader_image_size : enable
+
   //! OpenGL image used for accumulating rendering result.
   volatile restrict layout(size1x32) uniform image2D uRenderImage;
 
@@ -87,8 +89,9 @@ void main (void)
   // calculate visual error
   float anError = (aAverRad - aHalfRad) * (aAverRad - aHalfRad);
 
-  // accumulate visual error to current block
-  imageAtomicAdd (uVarianceImage, ivec2 (aPixel / vec2 (BLOCK_SIZE)), int (anError * SCALE_FACTOR));
+  // accumulate visual error to current block; estimated error is written only
+  // after the first 40 samples and path length has reached 10 bounces or more
+  imageAtomicAdd (uVarianceImage, ivec2 (aPixel / vec2 (BLOCK_SIZE)), int (mix (SCALE_FACTOR, anError * SCALE_FACTOR, aColor.w > 40.f)));
 
   if (uDebugAdaptive == 0) // normal rendering
   {
@@ -96,7 +99,13 @@ void main (void)
   }
   else // showing number of samples
   {
-    aColor = vec4 (0.5f * aColor.rgb * aSampleWeight + vec3 (0.f, aColor.w / uAccumFrames * 0.35f, 0.f), 1.0);
+    vec2 aRatio = vec2 (1.f, 1.f);
+
+#ifdef GL_ARB_shader_image_size
+    aRatio = vec2 (imageSize (uRenderImage)) / vec2 (3.f * 512.f, 2.f * 512.f);
+#endif
+
+    aColor = vec4 (0.5f * aColor.rgb * aSampleWeight + vec3 (0.f, sqrt (aRatio.x * aRatio.y) * aColor.w / uAccumFrames * 0.35f, 0.f), 1.0);
   }
 
 #endif // ADAPTIVE_SAMPLING
index 76b44e86f9593c5fafca94110e71c2062a8e5058..7088826599cf7bc9e0a06b5252cf75c7d6113ec0 100644 (file)
@@ -12,9 +12,6 @@
 
 #ifdef PATH_TRACING
 
-//! Number of previously rendered frames.
-uniform int uAccumSamples;
-
 ///////////////////////////////////////////////////////////////////////////////////////
 // Specific data types
 
@@ -700,17 +697,26 @@ vec3 IntersectLight (in SRay theRay, in int theDepth, in float theHitDistance, o
 #define MATERIAL_FRESNEL(index) (18 * index + 16)
 #define MATERIAL_ABSORPT(index) (18 * index + 17)
 
-// Enables expiremental russian roulette sampling
+//! Enables experimental russian roulette sampling path termination.
+//! In most cases, it provides faster image convergence with minimal
+//! bias, so it is enabled by default.
 #define RUSSIAN_ROULETTE
 
-//! Frame step to increase number of bounces
-#define FRAME_STEP 5
+//! Frame step to increase number of bounces. This mode is used
+//! for interaction with the model, when path length is limited
+//! for the first samples, and gradually increasing when camera
+//! is stabilizing.
+#ifdef ADAPTIVE_SAMPLING
+  #define FRAME_STEP 4
+#else
+  #define FRAME_STEP 5
+#endif
 
 //=======================================================================
 // function : PathTrace
 // purpose  : Calculates radiance along the given ray
 //=======================================================================
-vec4 PathTrace (in SRay theRay, in vec3 theInverse)
+vec4 PathTrace (in SRay theRay, in vec3 theInverse, in int theNbSamples)
 {
   float aRaytraceDepth = MAXFLOAT;
 
@@ -867,7 +873,8 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse)
     aSurvive = aDepth < 3 ? 1.f : min (dot (LUMA, aThroughput), 0.95f);
 #endif
 
-    if (RandFloat() > aSurvive || all (lessThan (aThroughput, MIN_THROUGHPUT)) || aDepth >= uAccumSamples / FRAME_STEP + step (1.f / M_PI, aImpPDF))
+    // here, we additionally increase path length for non-diffuse bounces
+    if (RandFloat() > aSurvive || all (lessThan (aThroughput, MIN_THROUGHPUT)) || aDepth >= theNbSamples / FRAME_STEP + step (1.f / M_PI, aImpPDF))
     {
       aDepth = INVALID_BOUNCES; // terminate path
     }
index 15ed8d8f50d5460de8b4f832fa50e1cedc7e62cb..e3937ff992e235e06e195024b4231632c0d4802f 100644 (file)
@@ -8,6 +8,9 @@ uniform int uFrameRndSeed;
 //! become structured. Can be used fo final rendering.
 uniform int uBlockedRngEnabled;
 
+//! Number of previously rendered frames (used in non-ISS mode).
+uniform int uAccumSamples;
+
 #ifndef ADAPTIVE_SAMPLING
   //! Input image with previously accumulated samples.
   uniform sampler2D uAccumTexture;
@@ -57,7 +60,18 @@ void main (void)
 
 #ifdef PATH_TRACING
 
-  vec4 aColor = PathTrace (aRay, aInvDirect);
+#ifndef ADAPTIVE_SAMPLING
+
+  vec4 aColor = PathTrace (aRay, aInvDirect, uAccumSamples);
+
+#else
+
+  float aNbSamples = imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 0,
+                                                          2 * aFragCoord.y + 1), 1.0);
+
+  vec4 aColor = PathTrace (aRay, aInvDirect, int (aNbSamples));
+
+#endif
 
   if (any (isnan (aColor.rgb)))
   {
@@ -78,18 +92,12 @@ void main (void)
   imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 2,
                                        2 * aFragCoord.y + 1), aColor.w);
 
-  // accumulate number of samples
-  float aNbSamples = imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 0,
-                                                          2 * aFragCoord.y + 1), 1.0);
-
   if (int (aNbSamples) % 2 == 0) // accumulate luminance for even samples only
   {
     imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 2,
                                          2 * aFragCoord.y + 0), dot (LUMA, aColor.rgb));
   }
 
-  discard; // fragment should not be written to frame buffer
-
 #else
 
   if (uAccumSamples == 0)
index 2685179e4a9ed4647b93b19b1916d26e6f3f96b1..80e1cba1c8317133719f9d923ced239d32815312 100644 (file)
@@ -5,6 +5,8 @@ static const char Shaders_Display_fs[] =
   "\n"
   "  #extension GL_ARB_shader_image_load_store : require\n"
   "\n"
+  "  #extension GL_ARB_shader_image_size : enable\n"
+  "\n"
   "  //! OpenGL image used for accumulating rendering result.\n"
   "  volatile restrict layout(size1x32) uniform image2D uRenderImage;\n"
   "\n"
@@ -90,8 +92,9 @@ static const char Shaders_Display_fs[] =
   "  // calculate visual error\n"
   "  float anError = (aAverRad - aHalfRad) * (aAverRad - aHalfRad);\n"
   "\n"
-  "  // accumulate visual error to current block\n"
-  "  imageAtomicAdd (uVarianceImage, ivec2 (aPixel / vec2 (BLOCK_SIZE)), int (anError * SCALE_FACTOR));\n"
+  "  // accumulate visual error to current block; estimated error is written only\n"
+  "  // after the first 40 samples and path length has reached 10 bounces or more\n"
+  "  imageAtomicAdd (uVarianceImage, ivec2 (aPixel / vec2 (BLOCK_SIZE)), int (mix (SCALE_FACTOR, anError * SCALE_FACTOR, aColor.w > 40.f)));\n"
   "\n"
   "  if (uDebugAdaptive == 0) // normal rendering\n"
   "  {\n"
@@ -99,7 +102,13 @@ static const char Shaders_Display_fs[] =
   "  }\n"
   "  else // showing number of samples\n"
   "  {\n"
-  "    aColor = vec4 (0.5f * aColor.rgb * aSampleWeight + vec3 (0.f, aColor.w / uAccumFrames * 0.35f, 0.f), 1.0);\n"
+  "    vec2 aRatio = vec2 (1.f, 1.f);\n"
+  "\n"
+  "#ifdef GL_ARB_shader_image_size\n"
+  "    aRatio = vec2 (imageSize (uRenderImage)) / vec2 (3.f * 512.f, 2.f * 512.f);\n"
+  "#endif\n"
+  "\n"
+  "    aColor = vec4 (0.5f * aColor.rgb * aSampleWeight + vec3 (0.f, sqrt (aRatio.x * aRatio.y) * aColor.w / uAccumFrames * 0.35f, 0.f), 1.0);\n"
   "  }\n"
   "\n"
   "#endif // ADAPTIVE_SAMPLING\n"
index fb1746cff04df84f93b477083b3d113e1095aabf..04cd95aa08976e2fac2174794e5f699085454048 100644 (file)
@@ -15,9 +15,6 @@ static const char Shaders_PathtraceBase_fs[] =
   "\n"
   "#ifdef PATH_TRACING\n"
   "\n"
-  "//! Number of previously rendered frames.\n"
-  "uniform int uAccumSamples;\n"
-  "\n"
   "///////////////////////////////////////////////////////////////////////////////////////\n"
   "// Specific data types\n"
   "\n"
@@ -703,17 +700,26 @@ static const char Shaders_PathtraceBase_fs[] =
   "#define MATERIAL_FRESNEL(index) (18 * index + 16)\n"
   "#define MATERIAL_ABSORPT(index) (18 * index + 17)\n"
   "\n"
-  "// Enables expiremental russian roulette sampling\n"
+  "//! Enables experimental russian roulette sampling path termination.\n"
+  "//! In most cases, it provides faster image convergence with minimal\n"
+  "//! bias, so it is enabled by default.\n"
   "#define RUSSIAN_ROULETTE\n"
   "\n"
-  "//! Frame step to increase number of bounces\n"
-  "#define FRAME_STEP 5\n"
+  "//! Frame step to increase number of bounces. This mode is used\n"
+  "//! for interaction with the model, when path length is limited\n"
+  "//! for the first samples, and gradually increasing when camera\n"
+  "//! is stabilizing.\n"
+  "#ifdef ADAPTIVE_SAMPLING\n"
+  "  #define FRAME_STEP 4\n"
+  "#else\n"
+  "  #define FRAME_STEP 5\n"
+  "#endif\n"
   "\n"
   "//=======================================================================\n"
   "// function : PathTrace\n"
   "// purpose  : Calculates radiance along the given ray\n"
   "//=======================================================================\n"
-  "vec4 PathTrace (in SRay theRay, in vec3 theInverse)\n"
+  "vec4 PathTrace (in SRay theRay, in vec3 theInverse, in int theNbSamples)\n"
   "{\n"
   "  float aRaytraceDepth = MAXFLOAT;\n"
   "\n"
@@ -870,7 +876,8 @@ static const char Shaders_PathtraceBase_fs[] =
   "    aSurvive = aDepth < 3 ? 1.f : min (dot (LUMA, aThroughput), 0.95f);\n"
   "#endif\n"
   "\n"
-  "    if (RandFloat() > aSurvive || all (lessThan (aThroughput, MIN_THROUGHPUT)) || aDepth >= uAccumSamples / FRAME_STEP + step (1.f / M_PI, aImpPDF))\n"
+  "    // here, we additionally increase path length for non-diffuse bounces\n"
+  "    if (RandFloat() > aSurvive || all (lessThan (aThroughput, MIN_THROUGHPUT)) || aDepth >= theNbSamples / FRAME_STEP + step (1.f / M_PI, aImpPDF))\n"
   "    {\n"
   "      aDepth = INVALID_BOUNCES; // terminate path\n"
   "    }\n"
index 46afbe073168d74244683dc8035306e969488606..1d6e5bda15ac5f5fb8de91d72fa26eb4717bb07c 100644 (file)
@@ -11,6 +11,9 @@ static const char Shaders_RaytraceRender_fs[] =
   "//! become structured. Can be used fo final rendering.\n"
   "uniform int uBlockedRngEnabled;\n"
   "\n"
+  "//! Number of previously rendered frames (used in non-ISS mode).\n"
+  "uniform int uAccumSamples;\n"
+  "\n"
   "#ifndef ADAPTIVE_SAMPLING\n"
   "  //! Input image with previously accumulated samples.\n"
   "  uniform sampler2D uAccumTexture;\n"
@@ -60,7 +63,18 @@ static const char Shaders_RaytraceRender_fs[] =
   "\n"
   "#ifdef PATH_TRACING\n"
   "\n"
-  "  vec4 aColor = PathTrace (aRay, aInvDirect);\n"
+  "#ifndef ADAPTIVE_SAMPLING\n"
+  "\n"
+  "  vec4 aColor = PathTrace (aRay, aInvDirect, uAccumSamples);\n"
+  "\n"
+  "#else\n"
+  "\n"
+  "  float aNbSamples = imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 0,\n"
+  "                                                          2 * aFragCoord.y + 1), 1.0);\n"
+  "\n"
+  "  vec4 aColor = PathTrace (aRay, aInvDirect, int (aNbSamples));\n"
+  "\n"
+  "#endif\n"
   "\n"
   "  if (any (isnan (aColor.rgb)))\n"
   "  {\n"
@@ -81,18 +95,12 @@ static const char Shaders_RaytraceRender_fs[] =
   "  imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 2,\n"
   "                                       2 * aFragCoord.y + 1), aColor.w);\n"
   "\n"
-  "  // accumulate number of samples\n"
-  "  float aNbSamples = imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 0,\n"
-  "                                                          2 * aFragCoord.y + 1), 1.0);\n"
-  "\n"
   "  if (int (aNbSamples) % 2 == 0) // accumulate luminance for even samples only\n"
   "  {\n"
   "    imageAtomicAdd (uRenderImage, ivec2 (3 * aFragCoord.x + 2,\n"
   "                                         2 * aFragCoord.y + 0), dot (LUMA, aColor.rgb));\n"
   "  }\n"
   "\n"
-  "  discard; // fragment should not be written to frame buffer\n"
-  "\n"
   "#else\n"
   "\n"
   "  if (uAccumSamples == 0)\n"
index 9d34d9b0fbd7cb1e0146bb26e19add47a318f8be..4d7841799b59409e6eaf0653582507608a5e91eb 100644 (file)
@@ -9076,6 +9076,7 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
     theDI << "iss debug:      " << (aParams.ShowSamplingTiles           ? "on" : "off") << "\n";
     theDI << "two-sided BSDF: " << (aParams.TwoSidedBsdfModels          ? "on" : "off") << "\n";
     theDI << "max radiance:   " <<  aParams.RadianceClampingValue                       << "\n";
+    theDI << "nb tiles (iss): " <<  aParams.NbRayTracingTiles                           << "\n";
     theDI << "shadingModel: ";
     switch (aView->ShadingModel())
     {
@@ -9364,6 +9365,32 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
       }
       aParams.ShowSamplingTiles = toEnable;
     }
+    else if (aFlag == "-nbtiles")
+    {
+      if (toPrint)
+      {
+        theDI << aParams.NbRayTracingTiles << " ";
+        continue;
+      }
+      else if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      const Standard_Integer aNbTiles = Draw::Atoi (theArgVec[anArgIter]);
+
+      if (aNbTiles < 64)
+      {
+        std::cerr << "Error: invalid number of ISS tiles " << aNbTiles << ".\n";
+        std::cerr << "Specify value in range [64, 1024].\n";
+        return 1;
+      }
+      else
+      {
+        aParams.NbRayTracingTiles = aNbTiles;
+      }
+    }
     else if (aFlag == "-env")
     {
       if (toPrint)
@@ -10924,25 +10951,26 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     __FILE__, VRenderParams, group);
   theCommands.Add("vrenderparams",
     "\n    Manages rendering parameters: "
-    "\n      '-raster'               Disables GPU ray-tracing"
-    "\n      '-msaa         0..4'    Specifies number of samples for MSAA"
-    "\n      '-rayTrace'             Enables  GPU ray-tracing"
-    "\n      '-rayDepth     0..10'   Defines maximum ray-tracing depth"
-    "\n      '-shadows      on|off'  Enables/disables shadows rendering"
-    "\n      '-reflections  on|off'  Enables/disables specular reflections"
-    "\n      '-fsaa         on|off'  Enables/disables adaptive anti-aliasing"
-    "\n      '-gleam        on|off'  Enables/disables transparency shadow effects"
-    "\n      '-gi           on|off'  Enables/disables global illumination effects"
-    "\n      '-brng         on|off'  Enables/disables blocked RNG (fast coherent PT)"
-    "\n      '-env          on|off'  Enables/disables environment map background"
-    "\n      '-twoside      on|off'  Enables/disables two-sided BSDF models (PT mode)"
-    "\n      '-iss          on|off'  Enables/disables adaptive screen sampling (PT mode)"
-    "\n      '-issd         on|off'  Shows screen sampling distribution in ISS mode"
-    "\n      '-maxrad       > 0.0'   Value used for clamping radiance estimation (PT mode)"
-    "\n      '-rebuildGlsl  on|off'  Rebuild Ray-Tracing GLSL programs (for debugging)"
-    "\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      '-raster'                Disables GPU ray-tracing"
+    "\n      '-msaa         0..4'     Specifies number of samples for MSAA"
+    "\n      '-rayTrace'              Enables  GPU ray-tracing"
+    "\n      '-rayDepth     0..10'    Defines maximum ray-tracing depth"
+    "\n      '-shadows      on|off'   Enables/disables shadows rendering"
+    "\n      '-reflections  on|off'   Enables/disables specular reflections"
+    "\n      '-fsaa         on|off'   Enables/disables adaptive anti-aliasing"
+    "\n      '-gleam        on|off'   Enables/disables transparency shadow effects"
+    "\n      '-gi           on|off'   Enables/disables global illumination effects"
+    "\n      '-brng         on|off'   Enables/disables blocked RNG (fast coherent PT)"
+    "\n      '-env          on|off'   Enables/disables environment map background"
+    "\n      '-twoside      on|off'   Enables/disables two-sided BSDF models (PT mode)"
+    "\n      '-iss          on|off'   Enables/disables adaptive screen sampling (PT mode)"
+    "\n      '-issd         on|off'   Shows screen sampling distribution in ISS mode"
+    "\n      '-maxrad       > 0.0'    Value used for clamping radiance estimation (PT mode)"
+    "\n      '-nbtiles      64..1024' Specifies number of screen tiles in ISS mode"
+    "\n      '-rebuildGlsl  on|off'   Rebuild Ray-Tracing GLSL programs (for debugging)"
+    "\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    Unlike vcaps, these parameters dramatically change visual properties."
     "\n    Command is intended to control presentation quality depending on"
     "\n    hardware capabilities and performance.",
diff --git a/tests/v3d/raytrace/sample_ball_iss b/tests/v3d/raytrace/sample_ball_iss
new file mode 100644 (file)
index 0000000..32b9d31
--- /dev/null
@@ -0,0 +1,20 @@
+puts "============"
+puts "Visualization - Path Tracing, Ball sample (ISS mode)"
+puts "============"
+puts ""
+
+cpulimit 1000
+
+source $env(CSF_OCCTSamplesPath)/tcl/pathtrace_ball.tcl
+
+vrenderparams -iss -nbtiles 64
+vfps 1024
+vdump $imagedir/${casename}_iss_64.png
+
+vrenderparams -iss -nbtiles 256
+vfps 256
+vdump $imagedir/${casename}_iss_256.png
+
+vrenderparams -iss -nbtiles 1024
+vfps 64
+vdump $imagedir/${casename}_iss_1024.png