]> OCCT Git - occt-copy.git/commitdiff
0026432: Improving Path Tracing functionality
authorisk <isk@opencascade.com>
Wed, 10 Feb 2016 08:39:18 +0000 (11:39 +0300)
committerduv <duv@opencascade.com>
Fri, 25 Mar 2016 09:44:57 +0000 (12:44 +0300)
Samples per pixel parameter added. Simple filtering added. Lights fixed. Max radiance parameter.

src/Graphic3d/Graphic3d_RenderingParams.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/ViewerTest/ViewerTest_ViewerCommands.cxx
tests/v3d/raytrace/2_light_box [new file with mode: 0644]
tests/v3d/raytrace/2_light_sphere [new file with mode: 0644]

index 8e0f2313325da91c2932bf79348c03e1f0f9941b..17483ba2ff58cb9bfbec0e1d347c9d7fa96d4f0a 100644 (file)
@@ -61,6 +61,9 @@ public:
     IsTransparentShadowEnabled  (Standard_False),
     UseEnvironmentMapBackground (Standard_False),
     CoherentPathTracingMode     (Standard_False),
+    IsGIFilteringEnabled        (Standard_False),
+    RadianceClampValue          (10.0),
+
     // stereoscopic parameters
     StereoMode (Graphic3d_StereoMode_QuadBuffer),
     AnaglyphFilter (Anaglyph_RedCyan_Optimized),
@@ -99,6 +102,8 @@ public:
   Standard_Boolean        IsTransparentShadowEnabled;  //!< enables/disables light propagation through transparent media, False by default
   Standard_Boolean        UseEnvironmentMapBackground; //!< enables/disables environment map background
   Standard_Boolean        CoherentPathTracingMode;     //!< enables/disables 'coherent' tracing mode (single RNG seed within 16x16 image blocks)
+  Standard_Boolean        IsGIFilteringEnabled;        //!< enables/disables post-processing of GI rendering results
+  Standard_Real           RadianceClampValue;          //!< maximum radiance value which will not be clamped.
 
   Graphic3d_StereoMode    StereoMode;                  //!< stereoscopic output mode, Graphic3d_StereoMode_QuadBuffer by default
   Anaglyph                AnaglyphFilter;              //!< filter for anaglyph output, Anaglyph_RedCyan_Optimized by default
index eff171c3ef94176ceb73f6dc5dc6b81299bbc671..6bc13a248851bf28c16e83ca9f94228cd846e3af 100644 (file)
@@ -673,10 +673,12 @@ protected: //! @name data types related to ray-tracing
     OpenGl_RT_uSphereMapForBack,
     OpenGl_RT_uTexSamplersArray,
     OpenGl_RT_uBlockedRngEnabled,
+    OpenGl_RT_uMaxRadiance,
 
     // sampled frame params
     OpenGl_RT_uSampleWeight,
     OpenGl_RT_uFrameRndSeed,
+    OpenGl_RT_uBilateralEnabled,
 
     // adaptive FSAA params
     OpenGl_RT_uOffsetX,
index ecc26ac7bed6da666eca97e78c474c0a9e860d35..5875738817652edf66327ee09b448c519b1d070c 100644 (file)
@@ -1553,6 +1553,8 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
         aShaderProgram->GetUniformLocation (theGlContext, "uSampleWeight");
       myUniformLocations[anIndex][OpenGl_RT_uFrameRndSeed] =
         aShaderProgram->GetUniformLocation (theGlContext, "uFrameRndSeed");
+      myUniformLocations[anIndex][OpenGl_RT_uMaxRadiance] =
+        aShaderProgram->GetUniformLocation (theGlContext, "uMaxRadiance");
 
       myUniformLocations[anIndex][OpenGl_RT_uBackColorTop] =
         aShaderProgram->GetUniformLocation (theGlContext, "uBackColorTop");
@@ -1562,6 +1564,9 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Handle(OpenGl_Context
 
     theGlContext->BindProgram (myOutImageProgram);
 
+    myUniformLocations[0][OpenGl_RT_uBilateralEnabled] =
+      myOutImageProgram->GetUniformLocation (theGlContext, "uBilateralEnabled");
+
     myOutImageProgram->SetSampler (theGlContext,
       "uInputTexture", OpenGl_RT_PrevAccumTexture);
 
@@ -2398,14 +2403,53 @@ Standard_Boolean OpenGl_View::runRaytraceShaders (const Standard_Integer
 
     // Set frame accumulation weight
     myRaytraceProgram->SetUniform (theGlContext,
-      myUniformLocations[0][OpenGl_RT_uSampleWeight], 1.f / (myAccumFrames + 1));
+      myUniformLocations[0][OpenGl_RT_uMaxRadiance], static_cast<Standard_ShortReal> (theCView.RenderParams.RadianceClampValue));
 
     // Set random number generator seed
     myRaytraceProgram->SetUniform (theGlContext,
       myUniformLocations[0][OpenGl_RT_uFrameRndSeed], static_cast<Standard_Integer> (myRNG.NextInt() >> 2));
-  }
 
-  theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
+    Standard_Integer aSamplesPerPixel = theCView.RenderParams.SamplesPerPixel;
+
+    if (aSamplesPerPixel == 0)
+    {
+      // Set frame accumulation weight
+      myRaytraceProgram->SetUniform (theGlContext,
+        myUniformLocations[0][OpenGl_RT_uSampleWeight], 1.f / (myAccumFrames + 1));
+
+      theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
+    }
+    else
+    {
+      for (int aPassIndex = 0; aPassIndex < aSamplesPerPixel; ++aPassIndex)
+      {
+        aRenderFramebuffer = myAccumFrames % 2 ? myRaytraceFBO1 : myRaytraceFBO2;
+        anAccumFramebuffer = myAccumFrames % 2 ? myRaytraceFBO2 : myRaytraceFBO1;
+
+        aRenderFramebuffer->BindBuffer (theGlContext);
+
+        anAccumFramebuffer->ColorTexture()->Bind (
+          theGlContext, GL_TEXTURE0 + OpenGl_RT_PrevAccumTexture);
+
+        // Set frame accumulation weight
+        myRaytraceProgram->SetUniform (theGlContext,
+          myUniformLocations[0][OpenGl_RT_uSampleWeight], 1.f / (myAccumFrames + 1));
+
+        // Set random number generator seed
+        myRaytraceProgram->SetUniform (theGlContext,
+          myUniformLocations[0][OpenGl_RT_uFrameRndSeed], static_cast<Standard_Integer> (myRNG.NextInt() >> 2));
+
+        theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
+        ++myAccumFrames;
+        glFinish();
+      }
+    }
+  }
+  else
+  {
+    theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
+    ++myAccumFrames;
+  }
 
   if (myRaytraceParameters.GlobalIllumination)
   {
@@ -2427,6 +2471,9 @@ Standard_Boolean OpenGl_View::runRaytraceShaders (const Standard_Integer
     aRenderFramebuffer->DepthStencilTexture()->Bind (
       theGlContext, GL_TEXTURE0 + OpenGl_RT_DepthTexture);
 
+    myOutImageProgram->SetUniform (theGlContext,
+      myUniformLocations[0][OpenGl_RT_uBilateralEnabled], theCView.RenderParams.IsGIFilteringEnabled ? 1 : 0);
+
     theGlContext->core20fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
 
     aRenderFramebuffer->DepthStencilTexture()->Unbind (
index 85ebec20e0e4672f65aa66370b1276777fbb47f2..66b71181da83a06bb0d909725eb456cf6e113470 100644 (file)
@@ -4,16 +4,59 @@ uniform sampler2D uInputTexture;
 //! Ray tracing depth image.
 uniform sampler2D uDepthTexture;
 
+uniform int uBilateralEnabled;
+
 //! Output pixel color.
 out vec4 OutColor;
 
+const float rI = 0.270 * 1.0f;  // The intensity radius (in pixels).
+const float rL = 1.71 * 0.5f;   // The geometric radius (in pixels).
+const int WindowSize = 8;       // The window size (in pixels).
+
+float gaussian (float theL, float theR)
+{
+  return exp (-theL * theL / (2.0f * theR * theR));
+}
+
+vec4 bilateral()
+{
+  // Get the sizes
+  int aWindow   = WindowSize / 2;
+  vec4 anOutCol = vec4 (0.f, 0.f, 0.f, 0.f);
+  vec4 aRefCol  = texelFetch (uInputTexture, ivec2 (gl_FragCoord.xy), 0);
+  float aNorm   = 0.f;
+
+  // Compute the kernel
+  for (int i = -aWindow; i <= aWindow; i++)
+  {
+    for (int j = -aWindow; j <= aWindow; j++)
+    {
+      vec4 aCol = texelFetch (uInputTexture, ivec2 (gl_FragCoord.xy) + ivec2 (j, i), 0);
+      float A = gaussian (distance (aCol, aRefCol), rI);
+      float B = gaussian (length (vec2(j, i)), rL);
+      anOutCol += aCol * A * B;
+      aNorm += A * B;
+    }
+  }
+  return anOutCol * (1.f / aNorm);
+}
+
 void main (void)
 {
-  vec4 aColor = texelFetch (uInputTexture, ivec2 (gl_FragCoord.xy), 0);
+  vec4 aColor;
+
+  if (bool (uBilateralEnabled))
+  {
+    aColor = bilateral();
+  }
+  else
+  {
+    aColor = texelFetch (uInputTexture, ivec2 (gl_FragCoord.xy), 0);
+  }
 
   float aDepth = texelFetch (uDepthTexture, ivec2 (gl_FragCoord.xy), 0).r;
   gl_FragDepth = aDepth;
 
   // apply gamma correction (we use gamma = 2)
   OutColor = vec4 (sqrt (aColor.rgb), aColor.a);
-}
+}
\ No newline at end of file
index a9c2e10931d82ab824f480d1ca865d18fe740bca..276b8d384dd07a73063cb57bd78d0918631ab496 100644 (file)
@@ -473,7 +473,7 @@ void sampleMaterial (in SMaterial theMaterial,
 
     theBounce = SPEC_REFLECT_BOUNCE; // specular bounce
   }
-  else //  specular transmission
+  else if (aKsi < aReflection) //  specular transmission\r
   {
     theWeight *= theMaterial.Kt.rgb * (aReflection / aPt) *
       sampleSpecularTransmission (theOutput, theInput, theBounce, theWeight, theMaterial.Fresnel);
@@ -493,12 +493,12 @@ void sampleMaterial (in SMaterial theMaterial,
 //=======================================================================
 float handlePointLight (in vec3 theInput, in vec3 theToLight, in float theRadius, in float theDistance)
 {
-  float aDistance = dot (theToLight, theToLight);
+  float aSquareLightDist = dot (theToLight, theToLight);\r
 
-  float aCosMax = inversesqrt (1.f + theRadius * theRadius / aDistance);
+  float aCosMax = inversesqrt (1.f + theRadius * theRadius / aSquareLightDist);\r
 
-  return float (aDistance < theDistance * theDistance) *
-    step (aCosMax, dot (theToLight, theInput) * inversesqrt (aDistance));
+  return float (aSquareLightDist < theDistance * theDistance) *\r
+    step (aCosMax, dot (theToLight, theInput) * inversesqrt (aSquareLightDist));\r
 }
 
 //=======================================================================
@@ -514,13 +514,12 @@ float handleDirectLight (in vec3 theInput, in vec3 theToLight, in float theCosMa
 // function : sampleLight
 // purpose  : general sampling function for directional and point lights
 //=======================================================================
-vec3 sampleLight (in vec3 theToLight, in bool isDirectional, in float theSmoothness, inout float thePDF)
+vec3 sampleLight (in vec3 theToLight, in float theDistance, in bool isDirectional, in float theSmoothness, inout float thePDF)\r
 {
   SLocalSpace aSpace = LocalSpace (theToLight);
 
   // for point lights smoothness defines radius
-  float aCosMax = isDirectional ? theSmoothness :
-    inversesqrt (1.f + theSmoothness * theSmoothness / dot (theToLight, theToLight));
+  float aCosMax = inversesqrt (1.f + theSmoothness * theSmoothness / (theDistance * theDistance));\r
 
   float aKsi1 = RandFloat();
   float aKsi2 = RandFloat();
@@ -593,8 +592,8 @@ vec3 intersectLight (in SRay theRay, in bool isViewRay, in int theBounce, in flo
   return aRadiance;
 }
 
-#define MIN_THROUGHPUT   vec3 (0.02f)
-#define MIN_CONTRIBUTION vec3 (0.01f)
+#define MIN_THROUGHPUT   vec3 (2.0e-2f)\r
+#define MIN_CONTRIBUTION vec3 (0.5e-2f)\r
 
 #define MATERIAL_KD(index)      (18 * index + 11)
 #define MATERIAL_KR(index)      (18 * index + 12)
@@ -732,7 +731,7 @@ vec4 PathTrace (in SRay theRay, in vec3 theInverse)
 
       float aPDF = 1.f / uLightCount, aDistance = length (aLight.xyz);
 
-      aLight.xyz = sampleLight (aLight.xyz * (1.f / aDistance),
+      aLight.xyz = sampleLight (aLight.xyz * (1.f / aDistance), aDistance,\r
         aLight.w == 0.f /* is infinite */, aParam.w /* angle cosine */, aPDF);
 
       vec3 aContrib = (1.f / aPDF) * aParam.rgb /* Le */ * handleMaterial (
index 25c9bbec19950100f02f22b97bcd3f5364dd9108..a8ce317863d224781c8bf318c832543f0ff52ddc 100644 (file)
@@ -13,7 +13,8 @@ uniform sampler2D uAccumTexture;
 //! Increases performance up to 4 times, but noise becomes structured.
 uniform int uBlockedRngEnabled;
 
-#define MAX_RADIANCE vec3 (10.f)
+//! Maximum value for radiance clamping.
+uniform float uMaxRadiance;
 
 // =======================================================================
 // function : main
@@ -46,7 +47,7 @@ void main (void)
     aColor.rgb = ZERO;
   }
 
-  aColor.rgb = min (aColor.rgb, MAX_RADIANCE);
+  aColor.rgb = min (aColor.rgb, vec3 (uMaxRadiance));
 
   OutColor = mix (texture2D (uAccumTexture, vPixel), aColor, uSampleWeight);
 #else
index f882441b8006982d2c6fadf5689c33936a8948c2..ceeefb855831ddb2aa4ffc2d6b28295681ac1e00 100644 (file)
@@ -8301,6 +8301,8 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
     theDI << "reflections:  " << (aParams.IsReflectionEnabled         ? "on" : "off") << "\n";
     theDI << "gleam:        " << (aParams.IsTransparentShadowEnabled  ? "on" : "off") << "\n";
     theDI << "GI:           " << (aParams.IsGlobalIlluminationEnabled ? "on" : "off") << "\n";
+    theDI << "samples:      " <<  aParams.SamplesPerPixel                             << "\n";
+    theDI << "filtering:    " << (aParams.IsGIFilteringEnabled        ? "on" : "off") << "\n";
     theDI << "blocked RNG:  " << (aParams.CoherentPathTracingMode     ? "on" : "off") << "\n";
     theDI << "shadingModel: ";
     switch (aView->ShadingModel())
@@ -8424,6 +8426,48 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
         aParams.RaytracingDepth = aDepth;
       }
     }
+    else if (aFlag == "-maxrad"
+          || aFlag == "-rclamp")
+    {
+      if (toPrint)
+      {
+        theDI << aParams.RadianceClampValue << " ";
+        continue;
+      }
+      else if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      aParams.RadianceClampValue = Draw::Atoi (theArgVec[anArgIter]);
+    }
+    else if (aFlag == "-samples"
+          || aFlag == "-spp")
+    {
+      if (toPrint)
+      {
+        theDI << aParams.SamplesPerPixel << " ";
+        continue;
+      }
+      else if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+
+      const Standard_Integer aSamples = Draw::Atoi (theArgVec[anArgIter]);
+
+      if (aSamples < 0)
+      {
+        std::cerr << "Error: invalid ray-tracing samples per pixel " << aSamples << ". SPP should be a positive number.\n";
+        return 1;
+      }
+      else
+      {
+        aParams.SamplesPerPixel = aSamples;
+      }
+    }
     else if (aFlag == "-shad"
           || aFlag == "-shadows")
     {
@@ -8510,6 +8554,22 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
         aParams.RaytracingDepth = Min (aParams.RaytracingDepth, 10);
       }
     }
+    else if (aFlag == "-filter" || aFlag == "-pp" )
+    {
+      if (toPrint)
+      {
+        theDI << (aParams.IsGIFilteringEnabled ? "on" : "off") << " ";
+        continue;
+      }
+
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !parseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aParams.IsGIFilteringEnabled = toEnable;
+    }
     else if (aFlag == "-blockedrng"
           || aFlag == "-brng")
     {
diff --git a/tests/v3d/raytrace/2_light_box b/tests/v3d/raytrace/2_light_box
new file mode 100644 (file)
index 0000000..71f5ce8
--- /dev/null
@@ -0,0 +1,40 @@
+puts "========"
+puts "Ray Tracing - check PT lights correctness"
+puts "========"
+
+pload ALL
+vinit
+vsetdispmode 1
+vvbo 0
+
+box b 500 500 1
+box b1 2 50 20
+
+vdisplay b
+vdisplay b1
+
+vsetlocation b -250 -250 0
+vsetlocation b1 -1 -25 0
+
+vlight del 0
+vlight del 0
+
+vlight add positional head 0 pos -10 0 20
+vlight change 0 sm 5.0
+
+vrenderparams -ray -gi
+vsetmaterial b plaster
+vsetmaterial b1 plaster
+
+vviewparams -scale 23.40302443511418 -proj 3.1690307533723025e-006 -0.053740375441171516 0.99855494192227556 -up 0.00011815109169240122 0.99855493498157033 0.05374037461975216 -at -0.039728087058276865 17.658749465576971 0.40052090530867673 -eye -0.038141096586915293 -9.2534108729671232 500.45788900604856 
+
+vlight change 0 int 20
+
+psphere s 5.0
+vdisplay s
+vsetlocation s 10 0 20
+
+vbsdf s -Kd 0.0 -Ks 0.0 -Kr 0.0 -Kt 0.0
+vbsdf s -Le 20.0
+
+vfps 500
diff --git a/tests/v3d/raytrace/2_light_sphere b/tests/v3d/raytrace/2_light_sphere
new file mode 100644 (file)
index 0000000..9eca3a2
--- /dev/null
@@ -0,0 +1,37 @@
+puts "========"
+puts "Ray Tracing - check PT lights correctness"
+puts "========"
+
+pload ALL
+vinit
+vsetdispmode 1
+vvbo 0
+
+box b 500 500 1
+psphere s 6.0
+
+vdisplay b
+vdisplay s
+
+vsetlocation b -250 -250 0
+vsetlocation s 0.0 0.0 7.0
+
+vlight del 0
+vlight del 0
+
+vlight add positional head 0 pos -15 0 20 sm 4.0 int 20
+
+vrenderparams -ray -gi -rayDepth 12
+vsetmaterial b plaster
+vsetmaterial s glass
+
+psphere ls 4.0
+vdisplay ls
+vsetlocation ls 15 0 20
+
+vbsdf ls -Kd 0.0 -Ks 0.0 -Kr 0.0 -Kt 0.0
+vbsdf ls -Le 20.0
+
+vviewparams -scale 23.40302443511418 -proj 3.1690307533720754e-006 -0.053740375441171412 0.99855494192227556 -up 0.00011815108764545944 0.99855493500381731 0.053740374206389462 -at 0.062905867278332972 2.1147318213590474 -0.43602962811169049 -eye 0.064492857749694432 -24.79742851718504 499.62133847262908 
+
+vfps 400