0025414: Visualization - Optimize ray-tracing performance
authordbp <dbp@opencascade.com>
Thu, 23 Oct 2014 14:18:24 +0000 (18:18 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 30 Oct 2014 08:44:37 +0000 (11:44 +0300)
This patch increases ray-tracing performance up to 12% in regular mode, and up to 36% in FSAA mode.

src/OpenGl/OpenGl_SceneGeometry.cxx
src/OpenGl/OpenGl_SceneGeometry.hxx
src/OpenGl/OpenGl_Workspace_Raytrace.cxx
src/Shaders/RaytraceBase.fs
src/Shaders/RaytraceSmooth.fs

index c618c29..7178229 100755 (executable)
@@ -128,6 +128,29 @@ OpenGl_RaytraceLight::OpenGl_RaytraceLight (const BVH_Vec4f& theDiffuse,
   //
 }
 
+// =======================================================================
+// function : Center
+// purpose  : Returns centroid position along the given axis
+// =======================================================================
+Standard_ShortReal OpenGl_TriangleSet::Center (
+  const Standard_Integer theIndex, const Standard_Integer theAxis) const
+{
+  // Note: Experiments show that the use of the box centroid (instead
+  // of the triangle centroid) increases render performance up to 12%
+
+  const BVH_Vec4i& aTriangle = Elements[theIndex];
+
+  const Standard_ShortReal aVertex0 =
+    BVH::VecComp<Standard_ShortReal, 3>::Get (Vertices[aTriangle.x()], theAxis);
+  const Standard_ShortReal aVertex1 =
+    BVH::VecComp<Standard_ShortReal, 3>::Get (Vertices[aTriangle.y()], theAxis);
+  const Standard_ShortReal aVertex2 =
+    BVH::VecComp<Standard_ShortReal, 3>::Get (Vertices[aTriangle.z()], theAxis);
+
+  return (Min (Min (aVertex0, aVertex1), aVertex2) +
+          Max (Max (aVertex0, aVertex1), aVertex2)) * 0.5f;
+}
+
 // =======================================================================
 // function : Box
 // purpose  : Returns AABB of primitive set
index f5c8545..dc52558 100755 (executable)
@@ -141,7 +141,7 @@ public:
 
   //! Creates new OpenGL element triangulation.
   OpenGl_TriangleSet (const Standard_Size theArrayID)
-  : BVH_Triangulation<Standard_ShortReal, 3> (),
+  : BVH_Triangulation<Standard_ShortReal, 3>(),
     myArrayID (theArrayID)
   {
     //
@@ -185,6 +185,9 @@ public:
   //! Returns AABB of primitive set.
   BVH_BoxNt Box() const;
 
+  //! Returns centroid position along the given axis.
+  Standard_ShortReal Center (const Standard_Integer theIndex, const Standard_Integer theAxis) const;
+
 public:
 
   BVH_Array3f Normals; //!< Array of vertex normals.
@@ -193,7 +196,7 @@ public:
 
 private:
 
-  Standard_Size myArrayID; //!< Id of associated primitive array.
+  Standard_Size myArrayID; //!< ID of associated primitive array.
 
 };
 
index cd02fc4..85d287b 100644 (file)
@@ -2241,38 +2241,42 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
                    1, // ID of FSAA program
                    myPostFSAAProgram);
 
-  const Standard_ShortReal aMaxOffset = 0.559017f;
-  const Standard_ShortReal aMinOffset = 0.186339f;
-
   myGlContext->core20fwd->glEnableVertexAttribArray (Graphic3d_TOA_POS);
   myGlContext->core20fwd->glVertexAttribPointer (Graphic3d_TOA_POS, 3, GL_FLOAT, GL_FALSE, 0, NULL);
 
-  // Perform multi-pass adaptive FSAA using ping-pong technique
-  // rotated grid AA always uses 4 samples
-  for (Standard_Integer anIt = 0; anIt < 4; ++anIt)
+  // Perform multi-pass adaptive FSAA using ping-pong technique.
+  // We use 'FLIPTRI' sampling pattern changing for every pixel
+  // (3 additional samples per pixel, the 1st sample is already
+  // available from initial ray-traced image).
+  for (Standard_Integer anIt = 1; anIt < 4; ++anIt)
   {
     GLfloat aOffsetX = 1.f / theSizeX;
     GLfloat aOffsetY = 1.f / theSizeY;
 
-    if (anIt < 2)
+    if (anIt == 1)
     {
-      aOffsetX *= anIt < 1 ? aMinOffset : -aMaxOffset;
-      aOffsetY *= anIt < 1 ? aMaxOffset :  aMinOffset;
+      aOffsetX *= -0.55f;
+      aOffsetY *=  0.55f;
     }
-    else
+    else if (anIt == 2)
     {
-      aOffsetX *= anIt > 2 ?  aMaxOffset : -aMinOffset;
-      aOffsetY *= anIt > 2 ? -aMinOffset : -aMaxOffset;
+      aOffsetX *=  0.00f;
+      aOffsetY *= -0.55f;
     }
-    
+    else if (anIt == 3)
+    {
+      aOffsetX *= 0.55f;
+      aOffsetY *= 0.00f;
+    }
+
     myPostFSAAProgram->SetUniform (myGlContext,
-      myUniformLocations[1][OpenGl_RT_uSamples], anIt + 2);
+      myUniformLocations[1][OpenGl_RT_uSamples], anIt + 1);
     myPostFSAAProgram->SetUniform (myGlContext,
       myUniformLocations[1][OpenGl_RT_uOffsetX], aOffsetX);
     myPostFSAAProgram->SetUniform (myGlContext,
       myUniformLocations[1][OpenGl_RT_uOffsetY], aOffsetY);
 
-    Handle(OpenGl_FrameBuffer)& aFramebuffer = anIt % 2 ? myRaytraceFBO1 : myRaytraceFBO2;
+    Handle(OpenGl_FrameBuffer)& aFramebuffer = anIt % 2 ? myRaytraceFBO2 : myRaytraceFBO1;
 
     if (anIt == 3) // disable FBO on last iteration
     {
@@ -2285,7 +2289,7 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
     {
       aFramebuffer->BindBuffer (myGlContext);
     }
-    
+
     myGlContext->core15fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
 
     if (anIt != 3) // set input for the next pass
index d0c002e..10bf8af 100644 (file)
@@ -5,6 +5,11 @@
 //! Normalized pixel coordinates.
 in vec2 vPixel;
 
+//! Sub-pixel offset in X direction for FSAA.
+uniform float uOffsetX = 0.f;
+//! Sub-pixel offset in Y direction for FSAA.
+uniform float uOffsetY = 0.f;
+
 //! Origin of viewing ray in left-top corner.
 uniform vec3 uOriginLT;
 //! Origin of viewing ray in left-bottom corner.
index f75a971..6207600 100644 (file)
@@ -4,11 +4,6 @@ uniform sampler2D uFSAAInputTexture;
 //! Number of accumulated FSAA samples.
 uniform int uSamples;
 
-//! Sub-pixel offset in X direction for FSAA.
-uniform float uOffsetX;
-//! Sub-pixel offset in Y direction for FSAA.
-uniform float uOffsetY;
-
 //! Output pixel color.
 out vec4 OutColor;
 
@@ -25,6 +20,10 @@ void main (void)
   int aPixelX = int (gl_FragCoord.x);
   int aPixelY = int (gl_FragCoord.y);
 
+  // Adjust FLIPTRI pattern used for adaptive FSAA
+  float anOffsetX = mix (uOffsetX, -uOffsetX, float (aPixelX % 2));
+  float anOffsetY = mix (uOffsetY, -uOffsetY, float (aPixelY % 2));
+
   vec4 aClr0 = texelFetch (uFSAAInputTexture, ivec2 (aPixelX + 0, aPixelY + 0), 0);
   vec4 aClr1 = texelFetch (uFSAAInputTexture, ivec2 (aPixelX + 0, aPixelY - 1), 0);
   vec4 aClr2 = texelFetch (uFSAAInputTexture, ivec2 (aPixelX + 0, aPixelY + 1), 0);
@@ -47,7 +46,7 @@ void main (void)
                  abs (aClr6.w - aClr0.w) > LUM_DIFFERENCE ||
                  abs (aClr7.w - aClr0.w) > LUM_DIFFERENCE ||
                  abs (aClr8.w - aClr0.w) > LUM_DIFFERENCE;
-  
+
   if (!aRender)
   {
     aRender = abs (dot (LUMA, aClr1.xyz) - aLum) > LUM_DIFFERENCE ||
@@ -61,19 +60,19 @@ void main (void)
   }
 
   vec4 aColor = aClr0;
-                 
+
   if (aRender)
   {
-    SRay aRay = GenerateRay (vPixel + vec2 (uOffsetX, uOffsetY));
-        
+    SRay aRay = GenerateRay (vPixel + vec2 (anOffsetX, anOffsetY));
+
     vec3 aInvDirect = 1.f / max (abs (aRay.Direct), SMALL);
-        
+
     aInvDirect = vec3 (aRay.Direct.x < 0.f ? -aInvDirect.x : aInvDirect.x,
                        aRay.Direct.y < 0.f ? -aInvDirect.y : aInvDirect.y,
                        aRay.Direct.z < 0.f ? -aInvDirect.z : aInvDirect.z);
-                           
+
     aColor = mix (aClr0, clamp (Radiance (aRay, aInvDirect), 0.f, 1.f), 1.f / uSamples);
   }
-  
+
   OutColor = aColor;
 }
\ No newline at end of file