0025703: Visualization - Decrease number of samplers used in ray-tracing mode
authordbp <dbp@opencascade.com>
Wed, 14 Jan 2015 08:04:27 +0000 (11:04 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 22 Jan 2015 13:47:52 +0000 (16:47 +0300)
This patch eliminates 3 samplers used in ray-tracing mode:

//! Texture buffer of data records of bottom-level BVH nodes.
Handle(OpenGl_TextureBufferArb) myObjectNodeInfoTexture;
//! Texture buffer of minimum points of bottom-level BVH nodes.
Handle(OpenGl_TextureBufferArb) myObjectMinPointTexture;
//! Texture buffer of maximum points of bottom-level BVH nodes.
Handle(OpenGl_TextureBufferArb) myObjectMaxPointTexture;

Serialized data contained in corresponding texture buffers were added to global scene buffers:

//! Texture buffer of data records of high-level BVH nodes.
Handle(OpenGl_TextureBufferArb) mySceneNodeInfoTexture;
 //! Texture buffer of minimum points of high-level BVH nodes.
Handle(OpenGl_TextureBufferArb) mySceneMinPointTexture;
//! Texture buffer of maximum points of high-level BVH nodes.
Handle(OpenGl_TextureBufferArb) mySceneMaxPointTexture;

This modifications leads also to small performance improvement (~2%) due to higher texture cache efficiency. Some modifications in traversal function (GLSL code) also improve performance (~3%).

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

index 7178229..512bb22 100755 (executable)
@@ -305,7 +305,7 @@ Standard_Boolean OpenGl_RaytraceGeometry::ProcessAcceleration()
 
   Standard_Integer aVerticesOffset = 0;
   Standard_Integer aElementsOffset = 0;
 
   Standard_Integer aVerticesOffset = 0;
   Standard_Integer aElementsOffset = 0;
-  Standard_Integer aBVHNodesOffset = 0;
+  Standard_Integer aBVHNodesOffset = BVH()->Length();
 
   for (Standard_Integer aNodeIdx = 0; aNodeIdx < aBVH->Length(); ++aNodeIdx)
   {
 
   for (Standard_Integer aNodeIdx = 0; aNodeIdx < aBVH->Length(); ++aNodeIdx)
   {
index 5064235..5450975 100644 (file)
@@ -328,30 +328,25 @@ protected:
   //! Defines texture samplers.
   enum ShaderSamplerNames
   {
   //! Defines texture samplers.
   enum ShaderSamplerNames
   {
-    OpenGl_RT_SceneNodeInfoTexture = 0,
-    OpenGl_RT_SceneMinPointTexture = 1,
-    OpenGl_RT_SceneMaxPointTexture = 2,
+    OpenGl_RT_SceneNodeInfoTexture  = 0,
+    OpenGl_RT_SceneMinPointTexture  = 1,
+    OpenGl_RT_SceneMaxPointTexture  = 2,
+    OpenGl_RT_SceneTransformTexture = 3,
 
 
-    OpenGl_RT_ObjectNodeInfoTexture = 3,
-    OpenGl_RT_ObjectMinPointTexture = 4,
-    OpenGl_RT_ObjectMaxPointTexture = 5,
+    OpenGl_RT_GeometryVertexTexture = 4,
+    OpenGl_RT_GeometryNormalTexture = 5,
+    OpenGl_RT_GeometryTexCrdTexture = 6,
+    OpenGl_RT_GeometryTriangTexture = 7,
 
 
-    OpenGl_RT_GeometryVertexTexture = 6,
-    OpenGl_RT_GeometryNormalTexture = 7,
-    OpenGl_RT_GeometryTexCrdTexture = 8,
-    OpenGl_RT_GeometryTriangTexture = 9,
+    OpenGl_RT_EnvironmentMapTexture = 8,
 
 
-    OpenGl_RT_EnvironmentMapTexture = 10,
+    OpenGl_RT_RaytraceMaterialTexture = 9,
+    OpenGl_RT_RaytraceLightSrcTexture = 10,
 
 
-    OpenGl_RT_RaytraceMaterialTexture = 11,
-    OpenGl_RT_RaytraceLightSrcTexture = 12,
+    OpenGl_RT_FSAAInputTexture = 11,
 
 
-    OpenGl_RT_FSAAInputTexture = 13,
-
-    OpenGl_RT_SceneTransformTexture = 14,
-
-    OpenGl_RT_OpenGlColorTexture = 15,
-    OpenGl_RT_OpenGlDepthTexture = 16
+    OpenGl_RT_OpenGlColorTexture = 12,
+    OpenGl_RT_OpenGlDepthTexture = 13
   };
 
   //! Tool class for management of shader sources.
   };
 
   //! Tool class for management of shader sources.
@@ -598,22 +593,15 @@ protected: //! @name fields related to ray-tracing
   //! OpenGL/GLSL adaptive-AA shader program.
   Handle(OpenGl_ShaderProgram) myPostFSAAProgram;
 
   //! OpenGL/GLSL adaptive-AA shader program.
   Handle(OpenGl_ShaderProgram) myPostFSAAProgram;
 
-  //! Texture buffer of data records of high-level BVH nodes.
+  //! Texture buffer of data records of bottom-level BVH nodes.
   Handle(OpenGl_TextureBufferArb) mySceneNodeInfoTexture;
   Handle(OpenGl_TextureBufferArb) mySceneNodeInfoTexture;
-  //! Texture buffer of minimum points of high-level BVH nodes.
+  //! Texture buffer of minimum points of bottom-level BVH nodes.
   Handle(OpenGl_TextureBufferArb) mySceneMinPointTexture;
   Handle(OpenGl_TextureBufferArb) mySceneMinPointTexture;
-  //! Texture buffer of maximum points of high-level BVH nodes.
+  //! Texture buffer of maximum points of bottom-level BVH nodes.
   Handle(OpenGl_TextureBufferArb) mySceneMaxPointTexture;
   //! Texture buffer of transformations of high-level BVH nodes.
   Handle(OpenGl_TextureBufferArb) mySceneTransformTexture;
 
   Handle(OpenGl_TextureBufferArb) mySceneMaxPointTexture;
   //! Texture buffer of transformations of high-level BVH nodes.
   Handle(OpenGl_TextureBufferArb) mySceneTransformTexture;
 
-  //! Texture buffer of data records of bottom-level BVH nodes.
-  Handle(OpenGl_TextureBufferArb) myObjectNodeInfoTexture;
-  //! Texture buffer of minimum points of bottom-level BVH nodes.
-  Handle(OpenGl_TextureBufferArb) myObjectMinPointTexture;
-  //! Texture buffer of maximum points of bottom-level BVH nodes.
-  Handle(OpenGl_TextureBufferArb) myObjectMaxPointTexture;
-
   //! Texture buffer of vertex coords.
   Handle(OpenGl_TextureBufferArb) myGeometryVertexTexture;
   //! Texture buffer of vertex normals.
   //! Texture buffer of vertex coords.
   Handle(OpenGl_TextureBufferArb) myGeometryVertexTexture;
   //! Texture buffer of vertex normals.
index 543663b..9f4e4fb 100644 (file)
@@ -92,7 +92,7 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceGeometry (GeomUpdateMode theMod
           {
             return UpdateRaytraceGeometry (OpenGl_GUM_PREPARE);
           }
           {
             return UpdateRaytraceGeometry (OpenGl_GUM_PREPARE);
           }
-        } 
+        }
         else if (theMode == OpenGl_GUM_PREPARE)
         {
           if (!aStructure->IsRaytracable()
         else if (theMode == OpenGl_GUM_PREPARE)
         {
           if (!aStructure->IsRaytracable()
@@ -113,7 +113,7 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceGeometry (GeomUpdateMode theMod
               }
             }
           }
               }
             }
           }
-        } 
+        }
         else if (theMode == OpenGl_GUM_UPDATE)
         {
           if (!aStructure->IsRaytracable())
         else if (theMode == OpenGl_GUM_UPDATE)
         {
           if (!aStructure->IsRaytracable())
@@ -195,7 +195,7 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceGeometry (GeomUpdateMode theMod
 
 // =======================================================================
 // function : CheckRaytraceStructure
 
 // =======================================================================
 // function : CheckRaytraceStructure
-// purpose  :  Checks to see if the structure is modified
+// purpose  : Checks to see if the structure is modified
 // =======================================================================
 Standard_Boolean OpenGl_Workspace::CheckRaytraceStructure (const OpenGl_Structure* theStructure)
 {
 // =======================================================================
 Standard_Boolean OpenGl_Workspace::CheckRaytraceStructure (const OpenGl_Structure* theStructure)
 {
@@ -639,19 +639,19 @@ OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (const OpenGl_Pr
 
     if (!aBounds.IsNull())
     {
 
     if (!aBounds.IsNull())
     {
-  #ifdef RAY_TRACE_PRINT_INFO
+#ifdef RAY_TRACE_PRINT_INFO
       std::cout << "\tNumber of bounds = " << aBounds->NbBounds << std::endl;
       std::cout << "\tNumber of bounds = " << aBounds->NbBounds << std::endl;
-  #endif
+#endif
 
       Standard_Integer aBoundStart = 0;
       for (Standard_Integer aBound = 0; aBound < aBounds->NbBounds; ++aBound)
       {
         const Standard_Integer aVertNum = aBounds->Bounds[aBound];
 
 
       Standard_Integer aBoundStart = 0;
       for (Standard_Integer aBound = 0; aBound < aBounds->NbBounds; ++aBound)
       {
         const Standard_Integer aVertNum = aBounds->Bounds[aBound];
 
-  #ifdef RAY_TRACE_PRINT_INFO
+#ifdef RAY_TRACE_PRINT_INFO
         std::cout << "\tAdding indices from bound " << aBound << ": " <<
                                       aBoundStart << " .. " << aVertNum << std::endl;
         std::cout << "\tAdding indices from bound " << aBound << ": " <<
                                       aBoundStart << " .. " << aVertNum << std::endl;
-  #endif
+#endif
 
         if (!AddRaytraceVertexIndices (*aSet, *theArray, aBoundStart, aVertNum, theMatID))
         {
 
         if (!AddRaytraceVertexIndices (*aSet, *theArray, aBoundStart, aVertNum, theMatID))
         {
@@ -1495,12 +1495,6 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
         "uSceneMaxPointTexture", OpenGl_RT_SceneMaxPointTexture);
       aShaderProgram->SetSampler (myGlContext,
         "uSceneNodeInfoTexture", OpenGl_RT_SceneNodeInfoTexture);
         "uSceneMaxPointTexture", OpenGl_RT_SceneMaxPointTexture);
       aShaderProgram->SetSampler (myGlContext,
         "uSceneNodeInfoTexture", OpenGl_RT_SceneNodeInfoTexture);
-      aShaderProgram->SetSampler (myGlContext,
-        "uObjectMinPointTexture", OpenGl_RT_ObjectMinPointTexture);
-      aShaderProgram->SetSampler (myGlContext,
-        "uObjectMaxPointTexture", OpenGl_RT_ObjectMaxPointTexture);
-      aShaderProgram->SetSampler (myGlContext,
-        "uObjectNodeInfoTexture", OpenGl_RT_ObjectNodeInfoTexture);
       aShaderProgram->SetSampler (myGlContext,
         "uGeometryVertexTexture", OpenGl_RT_GeometryVertexTexture);
       aShaderProgram->SetSampler (myGlContext,
       aShaderProgram->SetSampler (myGlContext,
         "uGeometryVertexTexture", OpenGl_RT_GeometryVertexTexture);
       aShaderProgram->SetSampler (myGlContext,
@@ -1648,10 +1642,6 @@ void OpenGl_Workspace::ReleaseRaytraceResources()
   NullifyResource (myGlContext, mySceneMinPointTexture);
   NullifyResource (myGlContext, mySceneMaxPointTexture);
 
   NullifyResource (myGlContext, mySceneMinPointTexture);
   NullifyResource (myGlContext, mySceneMaxPointTexture);
 
-  NullifyResource (myGlContext, myObjectNodeInfoTexture);
-  NullifyResource (myGlContext, myObjectMinPointTexture);
-  NullifyResource (myGlContext, myObjectMaxPointTexture);
-
   NullifyResource (myGlContext, myGeometryVertexTexture);
   NullifyResource (myGlContext, myGeometryNormalTexture);
   NullifyResource (myGlContext, myGeometryTexCrdTexture);
   NullifyResource (myGlContext, myGeometryVertexTexture);
   NullifyResource (myGlContext, myGeometryNormalTexture);
   NullifyResource (myGlContext, myGeometryTexCrdTexture);
@@ -1696,45 +1686,28 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
   }
 
   /////////////////////////////////////////////////////////////////////////////
   }
 
   /////////////////////////////////////////////////////////////////////////////
-  // Create OpenGL texture buffers
+  // Create OpenGL BVH buffers
 
 
-  if (mySceneNodeInfoTexture.IsNull())  // create hight-level BVH buffers
+  if (mySceneNodeInfoTexture.IsNull())  // create scene BVH buffers
   {
   {
-    mySceneNodeInfoTexture = new OpenGl_TextureBufferArb;
-    mySceneMinPointTexture = new OpenGl_TextureBufferArb;
-    mySceneMaxPointTexture = new OpenGl_TextureBufferArb;
+    mySceneNodeInfoTexture  = new OpenGl_TextureBufferArb;
+    mySceneMinPointTexture  = new OpenGl_TextureBufferArb;
+    mySceneMaxPointTexture  = new OpenGl_TextureBufferArb;
     mySceneTransformTexture = new OpenGl_TextureBufferArb;
 
     mySceneTransformTexture = new OpenGl_TextureBufferArb;
 
-    if (!mySceneNodeInfoTexture->Create (myGlContext)
-     || !mySceneMinPointTexture->Create (myGlContext)
-     || !mySceneMaxPointTexture->Create (myGlContext)
+    if (!mySceneNodeInfoTexture->Create  (myGlContext)
+     || !mySceneMinPointTexture->Create  (myGlContext)
+     || !mySceneMaxPointTexture->Create  (myGlContext)
      || !mySceneTransformTexture->Create (myGlContext))
     {
 #ifdef RAY_TRACE_PRINT_INFO
      || !mySceneTransformTexture->Create (myGlContext))
     {
 #ifdef RAY_TRACE_PRINT_INFO
-      std::cout << "Error: Failed to create buffers for high-level scene BVH" << std::endl;
-#endif
-      return Standard_False;
-    }
-  }
-
-  if (myObjectNodeInfoTexture.IsNull())  // create bottom-level BVH buffers
-  {
-    myObjectNodeInfoTexture = new OpenGl_TextureBufferArb;
-    myObjectMinPointTexture = new OpenGl_TextureBufferArb;
-    myObjectMaxPointTexture = new OpenGl_TextureBufferArb;
-
-    if (!myObjectNodeInfoTexture->Create (myGlContext)
-     || !myObjectMinPointTexture->Create (myGlContext)
-     || !myObjectMaxPointTexture->Create (myGlContext))
-    {
-#ifdef RAY_TRACE_PRINT_INFO
-      std::cout << "Error: Failed to create buffers for bottom-level scene BVH" << std::endl;
+      std::cout << "Error: Failed to create scene BVH buffers" << std::endl;
 #endif
       return Standard_False;
     }
   }
 
 #endif
       return Standard_False;
     }
   }
 
-  if (myGeometryVertexTexture.IsNull())  // create geometry buffers
+  if  (myGeometryVertexTexture.IsNull())  // create geometry buffers
   {
     myGeometryVertexTexture = new OpenGl_TextureBufferArb;
     myGeometryNormalTexture = new OpenGl_TextureBufferArb;
   {
     myGeometryVertexTexture = new OpenGl_TextureBufferArb;
     myGeometryNormalTexture = new OpenGl_TextureBufferArb;
@@ -1753,7 +1726,7 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
     }
   }
 
     }
   }
 
-  if (myRaytraceMaterialTexture.IsNull())  // create material buffer
+  if (myRaytraceMaterialTexture.IsNull()) // create material buffer
   {
     myRaytraceMaterialTexture = new OpenGl_TextureBufferArb;
 
   {
     myRaytraceMaterialTexture = new OpenGl_TextureBufferArb;
 
@@ -1765,35 +1738,14 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
       return Standard_False;
     }
   }
       return Standard_False;
     }
   }
-
-  /////////////////////////////////////////////////////////////////////////////
-  // Write top-level BVH buffers
-
-  const NCollection_Handle<BVH_Tree<Standard_ShortReal, 3> >& aBVH = myRaytraceGeometry.BVH();
-
-  bool aResult = true;
-  if (!aBVH->NodeInfoBuffer().empty())
-  {
-    aResult &= mySceneNodeInfoTexture->Init (myGlContext, 4, GLsizei (aBVH->NodeInfoBuffer().size()),
-                                             reinterpret_cast<const GLuint*> (&aBVH->NodeInfoBuffer().front()));
-    aResult &= mySceneMinPointTexture->Init (myGlContext, 3, GLsizei (aBVH->MinPointBuffer().size()),
-                                             reinterpret_cast<const GLfloat*> (&aBVH->MinPointBuffer().front()));
-    aResult &= mySceneMaxPointTexture->Init (myGlContext, 3, GLsizei (aBVH->MaxPointBuffer().size()),
-                                             reinterpret_cast<const GLfloat*> (&aBVH->MaxPointBuffer().front()));
-  }
-  if (!aResult)
-  {
-#ifdef RAY_TRACE_PRINT_INFO
-    std::cout << "Error: Failed to upload buffers for high-level scene BVH" << std::endl;
-#endif
-    return Standard_False;
-  }
-
+  
   /////////////////////////////////////////////////////////////////////////////
   // Write transform buffer
 
   BVH_Mat4f* aNodeTransforms = new BVH_Mat4f[myRaytraceGeometry.Size()];
 
   /////////////////////////////////////////////////////////////////////////////
   // Write transform buffer
 
   BVH_Mat4f* aNodeTransforms = new BVH_Mat4f[myRaytraceGeometry.Size()];
 
+  bool aResult = true;
+
   for (Standard_Integer anElemIndex = 0; anElemIndex < myRaytraceGeometry.Size(); ++anElemIndex)
   {
     OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
   for (Standard_Integer anElemIndex = 0; anElemIndex < myRaytraceGeometry.Size(); ++anElemIndex)
   {
     OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
@@ -1837,13 +1789,15 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
     aTotalBVHNodesNb += aTriangleSet->BVH()->NodeInfoBuffer().size();
   }
 
     aTotalBVHNodesNb += aTriangleSet->BVH()->NodeInfoBuffer().size();
   }
 
+  aTotalBVHNodesNb += myRaytraceGeometry.BVH()->NodeInfoBuffer().size();
+
   if (aTotalBVHNodesNb != 0)
   {
   if (aTotalBVHNodesNb != 0)
   {
-    aResult &= myObjectNodeInfoTexture->Init (
+    aResult &= mySceneNodeInfoTexture->Init (
       myGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast<const GLuint*>  (NULL));
       myGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast<const GLuint*>  (NULL));
-    aResult &= myObjectMinPointTexture->Init (
+    aResult &= mySceneMinPointTexture->Init (
       myGlContext, 3, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
       myGlContext, 3, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
-    aResult &= myObjectMaxPointTexture->Init (
+    aResult &= mySceneMaxPointTexture->Init (
       myGlContext, 3, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
   }
 
       myGlContext, 3, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
   }
 
@@ -1879,6 +1833,15 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
     return Standard_False;
   }
 
     return Standard_False;
   }
 
+  const NCollection_Handle<BVH_Tree<Standard_ShortReal, 3> >& aBVH = myRaytraceGeometry.BVH();
+
+  aResult &= mySceneNodeInfoTexture->SubData (myGlContext, 0, aBVH->Length(),
+    reinterpret_cast<const GLuint*> (&aBVH->NodeInfoBuffer().front()));
+  aResult &= mySceneMinPointTexture->SubData (myGlContext, 0, aBVH->Length(),
+    reinterpret_cast<const GLfloat*> (&aBVH->MinPointBuffer().front()));
+  aResult &= mySceneMaxPointTexture->SubData (myGlContext, 0, aBVH->Length(),
+    reinterpret_cast<const GLfloat*> (&aBVH->MaxPointBuffer().front()));
+
   for (Standard_Integer aNodeIdx = 0; aNodeIdx < aBVH->Length(); ++aNodeIdx)
   {
     if (!aBVH->IsOuter (aNodeIdx))
   for (Standard_Integer aNodeIdx = 0; aNodeIdx < aBVH->Length(); ++aNodeIdx)
   {
     if (!aBVH->IsOuter (aNodeIdx))
@@ -1889,20 +1852,20 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
     Standard_ASSERT_RETURN (aTriangleSet != NULL,
       "Error: Failed to get triangulation of OpenGL element", Standard_False);
 
     Standard_ASSERT_RETURN (aTriangleSet != NULL,
       "Error: Failed to get triangulation of OpenGL element", Standard_False);
 
-    const Standard_Integer aBVHOffset = myRaytraceGeometry.AccelerationOffset (aNodeIdx);
+    Standard_Integer aBVHOffset = myRaytraceGeometry.AccelerationOffset (aNodeIdx);
 
     Standard_ASSERT_RETURN (aBVHOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
       "Error: Failed to get offset for bottom-level BVH", Standard_False);
 
 
     Standard_ASSERT_RETURN (aBVHOffset != OpenGl_RaytraceGeometry::INVALID_OFFSET,
       "Error: Failed to get offset for bottom-level BVH", Standard_False);
 
-    const size_t aBVHBuffserSize = aTriangleSet->BVH()->NodeInfoBuffer().size();
+    const Standard_Integer aBvhBuffersSize = aTriangleSet->BVH()->Length();
 
 
-    if (aBVHBuffserSize != 0)
+    if (aBvhBuffersSize != 0)
     {
     {
-      aResult &= myObjectNodeInfoTexture->SubData (myGlContext, aBVHOffset, GLsizei (aBVHBuffserSize),
+      aResult &= mySceneNodeInfoTexture->SubData (myGlContext, aBVHOffset, aBvhBuffersSize,
                                                    reinterpret_cast<const GLuint*> (&aTriangleSet->BVH()->NodeInfoBuffer().front()));
                                                    reinterpret_cast<const GLuint*> (&aTriangleSet->BVH()->NodeInfoBuffer().front()));
-      aResult &= myObjectMinPointTexture->SubData (myGlContext, aBVHOffset, GLsizei (aBVHBuffserSize),
+      aResult &= mySceneMinPointTexture->SubData (myGlContext, aBVHOffset, aBvhBuffersSize,
                                                    reinterpret_cast<const GLfloat*> (&aTriangleSet->BVH()->MinPointBuffer().front()));
                                                    reinterpret_cast<const GLfloat*> (&aTriangleSet->BVH()->MinPointBuffer().front()));
-      aResult &= myObjectMaxPointTexture->SubData (myGlContext, aBVHOffset, GLsizei (aBVHBuffserSize),
+      aResult &= mySceneMaxPointTexture->SubData (myGlContext, aBVHOffset, aBvhBuffersSize,
                                                    reinterpret_cast<const GLfloat*> (&aTriangleSet->BVH()->MaxPointBuffer().front()));
       if (!aResult)
       {
                                                    reinterpret_cast<const GLfloat*> (&aTriangleSet->BVH()->MaxPointBuffer().front()));
       if (!aResult)
       {
@@ -2180,9 +2143,6 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
   mySceneMinPointTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMinPointTexture);
   mySceneMaxPointTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMaxPointTexture);
   mySceneNodeInfoTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneNodeInfoTexture);
   mySceneMinPointTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMinPointTexture);
   mySceneMaxPointTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMaxPointTexture);
   mySceneNodeInfoTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneNodeInfoTexture);
-  myObjectMinPointTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectMinPointTexture);
-  myObjectMaxPointTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectMaxPointTexture);
-  myObjectNodeInfoTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectNodeInfoTexture);
   myGeometryVertexTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture);
   myGeometryNormalTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture);
   myGeometryTexCrdTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTexCrdTexture);
   myGeometryVertexTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture);
   myGeometryNormalTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture);
   myGeometryTexCrdTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTexCrdTexture);
@@ -2225,12 +2185,9 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
 
     myOpenGlFBO->ColorTexture()->Unbind        (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlColorTexture);
     myOpenGlFBO->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlDepthTexture);
 
     myOpenGlFBO->ColorTexture()->Unbind        (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlColorTexture);
     myOpenGlFBO->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlDepthTexture);
-    mySceneMinPointTexture->UnbindTexture      (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMinPointTexture);
-    mySceneMaxPointTexture->UnbindTexture      (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMaxPointTexture);
-    mySceneNodeInfoTexture->UnbindTexture      (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneNodeInfoTexture);
-    myObjectMinPointTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectMinPointTexture);
-    myObjectMaxPointTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectMaxPointTexture);
-    myObjectNodeInfoTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectNodeInfoTexture);
+    mySceneMinPointTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMinPointTexture);
+    mySceneMaxPointTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMaxPointTexture);
+    mySceneNodeInfoTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneNodeInfoTexture);
     myGeometryVertexTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture);
     myGeometryNormalTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture);
     myGeometryTexCrdTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTexCrdTexture);
     myGeometryVertexTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture);
     myGeometryNormalTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture);
     myGeometryTexCrdTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTexCrdTexture);
@@ -2321,12 +2278,9 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
   myRaytraceFBO1->ColorTexture()->Unbind     (myGlContext, GL_TEXTURE0 + OpenGl_RT_FSAAInputTexture);
   myOpenGlFBO->ColorTexture()->Unbind        (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlColorTexture);
   myOpenGlFBO->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlDepthTexture);
   myRaytraceFBO1->ColorTexture()->Unbind     (myGlContext, GL_TEXTURE0 + OpenGl_RT_FSAAInputTexture);
   myOpenGlFBO->ColorTexture()->Unbind        (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlColorTexture);
   myOpenGlFBO->DepthStencilTexture()->Unbind (myGlContext, GL_TEXTURE0 + OpenGl_RT_OpenGlDepthTexture);
-  mySceneMinPointTexture->UnbindTexture      (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMinPointTexture);
-  mySceneMaxPointTexture->UnbindTexture      (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMaxPointTexture);
-  mySceneNodeInfoTexture->UnbindTexture      (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneNodeInfoTexture);
-  myObjectMinPointTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectMinPointTexture);
-  myObjectMaxPointTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectMaxPointTexture);
-  myObjectNodeInfoTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectNodeInfoTexture);
+  mySceneMinPointTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMinPointTexture);
+  mySceneMaxPointTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneMaxPointTexture);
+  mySceneNodeInfoTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneNodeInfoTexture);
   myGeometryVertexTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture);
   myGeometryNormalTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture);
   myGeometryTexCrdTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTexCrdTexture);
   myGeometryVertexTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryVertexTexture);
   myGeometryNormalTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryNormalTexture);
   myGeometryTexCrdTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTexCrdTexture);
index cff32f8..a300273 100644 (file)
@@ -36,22 +36,15 @@ uniform vec3 uDirectRB;
 //! Inverse model-view-projection matrix.
 uniform mat4 uUnviewMat;
 
 //! Inverse model-view-projection matrix.
 uniform mat4 uUnviewMat;
 
-//! Texture buffer of data records of high-level BVH nodes.
+//! Texture buffer of data records of bottom-level BVH nodes.
 uniform isamplerBuffer uSceneNodeInfoTexture;
 uniform isamplerBuffer uSceneNodeInfoTexture;
-//! Texture buffer of minimum points of high-level BVH nodes.
+//! Texture buffer of minimum points of bottom-level BVH nodes.
 uniform samplerBuffer uSceneMinPointTexture;
 uniform samplerBuffer uSceneMinPointTexture;
-//! Texture buffer of maximum points of high-level BVH nodes.
+//! Texture buffer of maximum points of bottom-level BVH nodes.
 uniform samplerBuffer uSceneMaxPointTexture;
 //! Texture buffer of transformations of high-level BVH nodes.
 uniform samplerBuffer uSceneTransformTexture;
 
 uniform samplerBuffer uSceneMaxPointTexture;
 //! Texture buffer of transformations of high-level BVH nodes.
 uniform samplerBuffer uSceneTransformTexture;
 
-//! Texture buffer of data records of bottom-level BVH nodes.
-uniform isamplerBuffer uObjectNodeInfoTexture;
-//! Texture buffer of minimum points of bottom-level BVH nodes.
-uniform samplerBuffer uObjectMinPointTexture;
-//! Texture buffer of maximum points of bottom-level BVH nodes.
-uniform samplerBuffer uObjectMaxPointTexture;
-
 //! Texture buffer of vertex coords.
 uniform samplerBuffer uGeometryVertexTexture;
 //! Texture buffer of vertex normals.
 //! Texture buffer of vertex coords.
 uniform samplerBuffer uGeometryVertexTexture;
 //! Texture buffer of vertex normals.
@@ -279,16 +272,16 @@ float IntersectSphere (in SRay theRay, in float theRadius)
   float aDdotD = dot (theRay.Direct, theRay.Direct);
   float aDdotO = dot (theRay.Direct, theRay.Origin);
   float aOdotO = dot (theRay.Origin, theRay.Origin);
   float aDdotD = dot (theRay.Direct, theRay.Direct);
   float aDdotO = dot (theRay.Direct, theRay.Origin);
   float aOdotO = dot (theRay.Origin, theRay.Origin);
-  
+
   float aD = aDdotO * aDdotO - aDdotD * (aOdotO - theRadius * theRadius);
   float aD = aDdotO * aDdotO - aDdotD * (aOdotO - theRadius * theRadius);
-  
+
   if (aD > 0.0f)
   {
     float aTime = (sqrt (aD) - aDdotO) * (1.0f / aDdotD);
     
     return aTime > 0.0f ? aTime : MAXFLOAT;
   }
   if (aD > 0.0f)
   {
     float aTime = (sqrt (aD) - aDdotO) * (1.0f / aDdotD);
     
     return aTime > 0.0f ? aTime : MAXFLOAT;
   }
-  
+
   return MAXFLOAT;
 }
 
   return MAXFLOAT;
 }
 
@@ -305,18 +298,18 @@ float IntersectTriangle (in SRay theRay,
 {
   vec3 aEdge0 = thePnt1 - thePnt0;
   vec3 aEdge1 = thePnt0 - thePnt2;
 {
   vec3 aEdge0 = thePnt1 - thePnt0;
   vec3 aEdge1 = thePnt0 - thePnt2;
-  
+
   theNorm = cross (aEdge1, aEdge0);
 
   vec3 aEdge2 = (1.0f / dot (theNorm, theRay.Direct)) * (thePnt0 - theRay.Origin);
   theNorm = cross (aEdge1, aEdge0);
 
   vec3 aEdge2 = (1.0f / dot (theNorm, theRay.Direct)) * (thePnt0 - theRay.Origin);
-  
+
   float aTime = dot (theNorm, aEdge2);
 
   vec3 theVec = cross (theRay.Direct, aEdge2);
   float aTime = dot (theNorm, aEdge2);
 
   vec3 theVec = cross (theRay.Direct, aEdge2);
-  
+
   theUV.x = dot (theVec, aEdge1);
   theUV.y = dot (theVec, aEdge0);
   theUV.x = dot (theVec, aEdge1);
   theUV.y = dot (theVec, aEdge0);
-  
+
   return bool (int(aTime >= 0.0f) &
                int(theUV.x >= 0.0f) &
                int(theUV.y >= 0.0f) &
   return bool (int(aTime >= 0.0f) &
                int(theUV.x >= 0.0f) &
                int(theUV.y >= 0.0f) &
@@ -341,33 +334,35 @@ ivec4 ObjectNearestHit (in int theBVHOffset, in int theVrtOffset, in int theTrgO
 
   ivec4 aTriIndex = INALID_HIT;
 
 
   ivec4 aTriIndex = INALID_HIT;
 
-  while (true)
+  bool toContinue = true;
+
+  while (toContinue)
   {
   {
-    ivec3 aData = texelFetch (uObjectNodeInfoTexture, aNode).xyz;
+    ivec3 aData = texelFetch (uSceneNodeInfoTexture, aNode).xyz;
 
     if (aData.x == 0) // if inner node
     {
       float aTimeOut;
       float aTimeLft;
       float aTimeRgh;
 
     if (aData.x == 0) // if inner node
     {
       float aTimeOut;
       float aTimeLft;
       float aTimeRgh;
-      
+
       aData.y += theBVHOffset;
       aData.z += theBVHOffset;
       aData.y += theBVHOffset;
       aData.z += theBVHOffset;
-  
-      vec3 aNodeMinLft = texelFetch (uObjectMinPointTexture, aData.y).xyz;
-      vec3 aNodeMaxLft = texelFetch (uObjectMaxPointTexture, aData.y).xyz;
-      vec3 aNodeMinRgh = texelFetch (uObjectMinPointTexture, aData.z).xyz;
-      vec3 aNodeMaxRgh = texelFetch (uObjectMaxPointTexture, aData.z).xyz;
+
+      vec3 aNodeMinLft = texelFetch (uSceneMinPointTexture, aData.y).xyz;
+      vec3 aNodeMinRgh = texelFetch (uSceneMinPointTexture, aData.z).xyz;
+      vec3 aNodeMaxLft = texelFetch (uSceneMaxPointTexture, aData.y).xyz;
+      vec3 aNodeMaxRgh = texelFetch (uSceneMaxPointTexture, aData.z).xyz;
 
       vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
       vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
 
       vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
       vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
-      
+
       vec3 aTimeMax = max (aTime0, aTime1);
       vec3 aTimeMin = min (aTime0, aTime1);
 
       aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
       aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
       vec3 aTimeMax = max (aTime0, aTime1);
       vec3 aTimeMin = min (aTime0, aTime1);
 
       aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
       aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
-      
+
       aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
       aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
 
       aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
       aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
 
@@ -384,7 +379,7 @@ ivec4 ObjectNearestHit (in int theBVHOffset, in int theVrtOffset, in int theTrgO
       if (bool(aHitLft & aHitRgh))
       {
         aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
       if (bool(aHitLft & aHitRgh))
       {
         aNode = (aTimeLft < aTimeRgh) ? aData.y : aData.z;
-        
+
         Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
       }
       else
         Stack[++aHead] = (aTimeLft < aTimeRgh) ? aData.z : aData.y;
       }
       else
@@ -395,10 +390,10 @@ ivec4 ObjectNearestHit (in int theBVHOffset, in int theVrtOffset, in int theTrgO
         }
         else
         {
         }
         else
         {
-          if (aHead == theSentinel)
-            return aTriIndex;
+          toContinue = (aHead != theSentinel);
 
 
-          aNode = Stack[aHead--];
+          if (toContinue)
+            aNode = Stack[aHead--];
         }
       }
     }
         }
       }
     }
@@ -421,7 +416,7 @@ ivec4 ObjectNearestHit (in int theBVHOffset, in int theVrtOffset, in int theTrgO
                                          aPoint2,
                                          aParams,
                                          aNormal);
                                          aPoint2,
                                          aParams,
                                          aNormal);
-                                         
+
         if (aTime < theHit.Time)
         {
           aTriIndex = aTriangle;
         if (aTime < theHit.Time)
         {
           aTriIndex = aTriangle;
@@ -429,11 +424,11 @@ ivec4 ObjectNearestHit (in int theBVHOffset, in int theVrtOffset, in int theTrgO
           theHit = SIntersect (aTime, aParams, aNormal);
         }
       }
           theHit = SIntersect (aTime, aParams, aNormal);
         }
       }
-      
-      if (aHead == theSentinel)
-        return aTriIndex;
 
 
-      aNode = Stack[aHead--];
+      toContinue = (aHead != theSentinel);
+
+      if (toContinue)
+        aNode = Stack[aHead--];
     }
   }
 
     }
   }
 
@@ -467,7 +462,7 @@ float ObjectAnyHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffse
 
   while (true)
   {
 
   while (true)
   {
-    ivec4 aData = texelFetch (uObjectNodeInfoTexture, aNode);
+    ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);
 
     if (aData.x == 0) // if inner node
     {
 
     if (aData.x == 0) // if inner node
     {
@@ -477,11 +472,11 @@ float ObjectAnyHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffse
 
       aData.y += theBVHOffset;
       aData.z += theBVHOffset;
 
       aData.y += theBVHOffset;
       aData.z += theBVHOffset;
-  
-      vec3 aNodeMinLft = texelFetch (uObjectMinPointTexture, aData.y).xyz;
-      vec3 aNodeMaxLft = texelFetch (uObjectMaxPointTexture, aData.y).xyz;
-      vec3 aNodeMinRgh = texelFetch (uObjectMinPointTexture, aData.z).xyz;
-      vec3 aNodeMaxRgh = texelFetch (uObjectMaxPointTexture, aData.z).xyz;
+
+      vec3 aNodeMinLft = texelFetch (uSceneMinPointTexture, aData.y).xyz;
+      vec3 aNodeMaxLft = texelFetch (uSceneMaxPointTexture, aData.y).xyz;
+      vec3 aNodeMinRgh = texelFetch (uSceneMinPointTexture, aData.z).xyz;
+      vec3 aNodeMaxRgh = texelFetch (uSceneMaxPointTexture, aData.z).xyz;
 
       vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
       vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
 
       vec3 aTime0 = (aNodeMinLft - theRay.Origin) * theInverse;
       vec3 aTime1 = (aNodeMaxLft - theRay.Origin) * theInverse;
@@ -491,7 +486,7 @@ float ObjectAnyHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffse
 
       aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
       aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
 
       aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
       aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
-      
+
       aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
       aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
 
       aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
       aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
 
@@ -622,9 +617,7 @@ ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theH
 
         vec3 aTrsfInverse = 1.0f / max (abs (aTrsfRay.Direct), SMALL);
 
 
         vec3 aTrsfInverse = 1.0f / max (abs (aTrsfRay.Direct), SMALL);
 
-        aTrsfInverse.x = aTrsfRay.Direct.x < 0.f ? -aTrsfInverse.x : aTrsfInverse.x;
-        aTrsfInverse.y = aTrsfRay.Direct.y < 0.f ? -aTrsfInverse.y : aTrsfInverse.y;
-        aTrsfInverse.z = aTrsfRay.Direct.z < 0.f ? -aTrsfInverse.z : aTrsfInverse.z;
+        aTrsfInverse = mix (-aTrsfInverse, aTrsfInverse, step (ZERO, aTrsfRay.Direct));
 
         ivec4 aTriIndex = ObjectNearestHit (
           aData.y, aData.z, aData.w, aTrsfRay, aTrsfInverse, theHit, aHead);
 
         ivec4 aTriIndex = ObjectNearestHit (
           aData.y, aData.z, aData.w, aTrsfRay, aTrsfInverse, theHit, aHead);
@@ -639,7 +632,7 @@ ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theH
           theObjectId = anObjectId;
         }
       }
           theObjectId = anObjectId;
         }
       }
-      
+
       if (aHead < 0)
         return aHitObject;
 
       if (aHead < 0)
         return aHitObject;
 
@@ -666,7 +659,7 @@ ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theH
       aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
 
       int aHitLft = int(aTimeLft <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeLft <= theHit.Time);
       aTimeLft = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
 
       int aHitLft = int(aTimeLft <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeLft <= theHit.Time);
-      
+
       aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
       aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
 
       aTime0 = (aNodeMinRgh - theRay.Origin) * theInverse;
       aTime1 = (aNodeMaxRgh - theRay.Origin) * theInverse;
 
@@ -675,7 +668,7 @@ ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theH
 
       aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
       aTimeRgh = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
 
       aTimeOut = min (aTimeMax.x, min (aTimeMax.y, aTimeMax.z));
       aTimeRgh = max (aTimeMin.x, max (aTimeMin.y, aTimeMin.z));
-      
+
       int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeRgh <= theHit.Time);
 
       if (bool(aHitLft & aHitRgh))
       int aHitRgh = int(aTimeRgh <= aTimeOut) & int(aTimeOut >= 0.0f) & int(aTimeRgh <= theHit.Time);
 
       if (bool(aHitLft & aHitRgh))
@@ -700,7 +693,7 @@ ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theH
       }
     }
   }
       }
     }
   }
-  
+
   return aHitObject;
 }
 
   return aHitObject;
 }
 
@@ -737,9 +730,7 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)
 
       vec3 aTrsfInverse = 1.0f / max (abs (aTrsfRay.Direct), SMALL);
 
 
       vec3 aTrsfInverse = 1.0f / max (abs (aTrsfRay.Direct), SMALL);
 
-      aTrsfInverse.x = aTrsfRay.Direct.x < 0.0f ? -aTrsfInverse.x : aTrsfInverse.x;
-      aTrsfInverse.y = aTrsfRay.Direct.y < 0.0f ? -aTrsfInverse.y : aTrsfInverse.y;
-      aTrsfInverse.z = aTrsfRay.Direct.z < 0.0f ? -aTrsfInverse.z : aTrsfInverse.z;
+      aTrsfInverse = mix (-aTrsfInverse, aTrsfInverse, step (ZERO, aTrsfRay.Direct));
 
 #ifdef TRANSPARENT_SHADOWS
       aFactor *= ObjectAnyHit (
 
 #ifdef TRANSPARENT_SHADOWS
       aFactor *= ObjectAnyHit (
@@ -1012,34 +1003,31 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse)
     {
       vec4 aLight = texelFetch (
         uRaytraceLightSrcTexture, LIGHT_POS (aLightIdx));
     {
       vec4 aLight = texelFetch (
         uRaytraceLightSrcTexture, LIGHT_POS (aLightIdx));
-      
+
       float aDistance = MAXFLOAT;
       float aDistance = MAXFLOAT;
-      
+
       if (aLight.w != 0.0f) // point light source
       {
         aDistance = length (aLight.xyz -= aPoint);
       if (aLight.w != 0.0f) // point light source
       {
         aDistance = length (aLight.xyz -= aPoint);
-        
+
         aLight.xyz *= 1.0f / aDistance;
       }
 
       SRay aShadow = SRay (aPoint + aLight.xyz * uSceneEpsilon, aLight.xyz);
         aLight.xyz *= 1.0f / aDistance;
       }
 
       SRay aShadow = SRay (aPoint + aLight.xyz * uSceneEpsilon, aLight.xyz);
-      
+
       aShadow.Origin += aHit.Normal * uSceneEpsilon *
         (dot (aHit.Normal, aLight.xyz) >= 0.0f ? 1.0f : -1.0f);
       aShadow.Origin += aHit.Normal * uSceneEpsilon *
         (dot (aHit.Normal, aLight.xyz) >= 0.0f ? 1.0f : -1.0f);
-      
+
       float aVisibility = 1.0f;
       float aVisibility = 1.0f;
-     
+
       if (bool(uShadowsEnable))
       {
         vec3 aInverse = 1.0f / max (abs (aLight.xyz), SMALL);
 
       if (bool(uShadowsEnable))
       {
         vec3 aInverse = 1.0f / max (abs (aLight.xyz), SMALL);
 
-        aInverse.x = aLight.x < 0.0f ? -aInverse.x : aInverse.x;
-        aInverse.y = aLight.y < 0.0f ? -aInverse.y : aInverse.y;
-        aInverse.z = aLight.z < 0.0f ? -aInverse.z : aInverse.z;
-
-        aVisibility = SceneAnyHit (aShadow, aInverse, aDistance);
+        aVisibility = SceneAnyHit (
+          aShadow, mix (-aInverse, aInverse, step (ZERO, aLight.xyz)), aDistance);
       }
       }
-      
+
       if (aVisibility > 0.0f)
       {
         vec3 aIntensity = vec3 (texelFetch (
       if (aVisibility > 0.0f)
       {
         vec3 aIntensity = vec3 (texelFetch (
@@ -1073,9 +1061,7 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse)
 
         theInverse = 1.0f / max (abs (theRay.Direct), SMALL);
 
 
         theInverse = 1.0f / max (abs (theRay.Direct), SMALL);
 
-        theInverse.x = theRay.Direct.x < 0.0f ? -theInverse.x : theInverse.x;
-        theInverse.y = theRay.Direct.y < 0.0f ? -theInverse.y : theInverse.y;
-        theInverse.z = theRay.Direct.z < 0.0f ? -theInverse.z : theInverse.z;
+        theInverse = mix (-theInverse, theInverse, step (ZERO, theRay.Direct));
 
         aPoint += aHit.Normal * (dot (aHit.Normal, theRay.Direct) >= 0.0f ? uSceneEpsilon : -uSceneEpsilon);
 
 
         aPoint += aHit.Normal * (dot (aHit.Normal, theRay.Direct) >= 0.0f ? uSceneEpsilon : -uSceneEpsilon);
 
@@ -1101,9 +1087,7 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse)
 
       theInverse = 1.0f / max (abs (theRay.Direct), SMALL);
 
 
       theInverse = 1.0f / max (abs (theRay.Direct), SMALL);
 
-      theInverse.x = theRay.Direct.x < 0.0f ? -theInverse.x : theInverse.x;
-      theInverse.y = theRay.Direct.y < 0.0f ? -theInverse.y : theInverse.y;
-      theInverse.z = theRay.Direct.z < 0.0f ? -theInverse.z : theInverse.z;
+      theInverse = mix (-theInverse, theInverse, step (ZERO, theRay.Direct));
 
       aPoint += aHit.Normal * (dot (aHit.Normal, theRay.Direct) >= 0.0f ? uSceneEpsilon : -uSceneEpsilon);
 
 
       aPoint += aHit.Normal * (dot (aHit.Normal, theRay.Direct) >= 0.0f ? uSceneEpsilon : -uSceneEpsilon);