0025652: Visualization, TKOpenGl - RayTracing initialization failures are not properl...
[occt.git] / src / OpenGl / OpenGl_Workspace_Raytrace.cxx
index 3c408ce..71de483 100644 (file)
 
 #include <OpenGl_Workspace.hxx>
 
-#include <NCollection_Mat4.hxx>
-#include <OpenGl_ArbFBO.hxx>
+#include <Graphic3d_TextureParams.hxx>
 #include <OpenGl_FrameBuffer.hxx>
 #include <OpenGl_PrimitiveArray.hxx>
-#include <OpenGl_Texture.hxx>
 #include <OpenGl_VertexBuffer.hxx>
 #include <OpenGl_View.hxx>
 #include <OSD_File.hxx>
 #include <OSD_Protection.hxx>
-#include <Standard_Assert.hxx>
 
 using namespace OpenGl_Raytrace;
 
@@ -35,24 +32,6 @@ using namespace OpenGl_Raytrace;
   #include <OSD_Timer.hxx>
 #endif
 
-// =======================================================================
-// function : MatVecMult
-// purpose  : Multiples 4x4 matrix by 4D vector
-// =======================================================================
-template<typename T>
-BVH_Vec4f MatVecMult (const T m[16], const BVH_Vec4f& v)
-{
-  return BVH_Vec4f (
-    static_cast<float> (m[ 0] * v.x() + m[ 4] * v.y() +
-                        m[ 8] * v.z() + m[12] * v.w()),
-    static_cast<float> (m[ 1] * v.x() + m[ 5] * v.y() +
-                        m[ 9] * v.z() + m[13] * v.w()),
-    static_cast<float> (m[ 2] * v.x() + m[ 6] * v.y() +
-                        m[10] * v.z() + m[14] * v.w()),
-    static_cast<float> (m[ 3] * v.x() + m[ 7] * v.y() +
-                        m[11] * v.z() + m[15] * v.w()));
-}
-
 // =======================================================================
 // function : UpdateRaytraceGeometry
 // purpose  : Updates 3D scene geometry for ray tracing
@@ -92,18 +71,14 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceGeometry (GeomUpdateMode theMod
 
   for (OpenGl_SequenceOfLayers::Iterator anLayerIt (aList.Layers()); anLayerIt.More(); anLayerIt.Next())
   {
-    const OpenGl_PriorityList& aPriorityList = anLayerIt.Value().PriorityList();
-
-    if (aPriorityList.NbStructures() == 0)
+    const OpenGl_Layer& aLayer = anLayerIt.Value();
+    if (aLayer.NbStructures() == 0)
       continue;
 
-    const OpenGl_ArrayOfStructure& aStructArray = aPriorityList.ArrayOfStructures();
-
+    const OpenGl_ArrayOfStructure& aStructArray = aLayer.ArrayOfStructures();
     for (Standard_Integer anIndex = 0; anIndex < aStructArray.Length(); ++anIndex)
     {
-      OpenGl_SequenceOfStructure::Iterator aStructIt;
-
-      for (aStructIt.Init (aStructArray (anIndex)); aStructIt.More(); aStructIt.Next())
+      for (OpenGl_SequenceOfStructure::Iterator aStructIt (aStructArray (anIndex)); aStructIt.More(); aStructIt.Next())
       {
         const OpenGl_Structure* aStructure = aStructIt.Value();
 
@@ -113,12 +88,19 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceGeometry (GeomUpdateMode theMod
           {
             return UpdateRaytraceGeometry (OpenGl_GUM_PREPARE);
           }
-        } 
+        }
         else if (theMode == OpenGl_GUM_PREPARE)
         {
           if (!aStructure->IsRaytracable()
            || !aStructure->IsVisible())
+          {
             continue;
+          }
+          else if (!aStructure->ViewAffinity.IsNull()
+                && !aStructure->ViewAffinity->IsVisible (myViewId))
+          {
+            continue;
+          }
 
           for (OpenGl_Structure::GroupIterator aGroupIter (aStructure->DrawGroups()); aGroupIter.More(); aGroupIter.Next())
           {
@@ -134,7 +116,7 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceGeometry (GeomUpdateMode theMod
               }
             }
           }
-        } 
+        }
         else if (theMode == OpenGl_GUM_UPDATE)
         {
           if (!aStructure->IsRaytracable())
@@ -148,7 +130,7 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceGeometry (GeomUpdateMode theMod
 
   if (theMode == OpenGl_GUM_PREPARE)
   {
-    BVH_ObjectSet<Standard_ShortReal, 4>::BVH_ObjectList anUnchangedObjects;
+    BVH_ObjectSet<Standard_ShortReal, 3>::BVH_ObjectList anUnchangedObjects;
 
     // Leave only unchanged objects in myRaytraceGeometry so only their transforms and materials will be updated
     // Objects which not in myArrayToTrianglesMap will be built from scratch.
@@ -203,7 +185,7 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceGeometry (GeomUpdateMode theMod
 
     myRaytraceSceneRadius = 2.f /* scale factor */ * Max (aMinRadius, aMaxRadius);
 
-    const BVH_Vec4f aSize = myRaytraceGeometry.Box().Size();
+    const BVH_Vec3f aSize = myRaytraceGeometry.Box().Size();
 
     myRaytraceSceneEpsilon = Max (1e-6f, 1e-4f * sqrtf (
       aSize.x() * aSize.x() + aSize.y() * aSize.y() + aSize.z() * aSize.z()));
@@ -216,7 +198,7 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceGeometry (GeomUpdateMode theMod
 
 // =======================================================================
 // 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)
 {
@@ -241,54 +223,130 @@ Standard_Boolean OpenGl_Workspace::CheckRaytraceStructure (const OpenGl_Structur
   return Standard_True;
 }
 
+// =======================================================================
+// function : BuildTexTransform
+// purpose  : Constructs texture transformation matrix
+// =======================================================================
+void BuildTexTransform (const Handle(Graphic3d_TextureParams)& theParams, BVH_Mat4f& theMatrix)
+{
+  theMatrix.InitIdentity();
+
+  // Apply scaling
+  const Graphic3d_Vec2& aScale = theParams->Scale();
+
+  theMatrix.ChangeValue (0, 0) *= aScale.x();
+  theMatrix.ChangeValue (1, 0) *= aScale.x();
+  theMatrix.ChangeValue (2, 0) *= aScale.x();
+  theMatrix.ChangeValue (3, 0) *= aScale.x();
+
+  theMatrix.ChangeValue (0, 1) *= aScale.y();
+  theMatrix.ChangeValue (1, 1) *= aScale.y();
+  theMatrix.ChangeValue (2, 1) *= aScale.y();
+  theMatrix.ChangeValue (3, 1) *= aScale.y();
+
+  // Apply translation
+  const Graphic3d_Vec2 aTrans = -theParams->Translation();
+
+  theMatrix.ChangeValue (0, 3) = theMatrix.GetValue (0, 0) * aTrans.x() +
+                                 theMatrix.GetValue (0, 1) * aTrans.y();
+
+  theMatrix.ChangeValue (1, 3) = theMatrix.GetValue (1, 0) * aTrans.x() +
+                                 theMatrix.GetValue (1, 1) * aTrans.y();
+
+  theMatrix.ChangeValue (2, 3) = theMatrix.GetValue (2, 0) * aTrans.x() +
+                                 theMatrix.GetValue (2, 1) * aTrans.y();
+
+  // Apply rotation
+  const Standard_ShortReal aSin = std::sin (
+    -theParams->Rotation() * static_cast<Standard_ShortReal> (M_PI / 180.0));
+  const Standard_ShortReal aCos = std::cos (
+    -theParams->Rotation() * static_cast<Standard_ShortReal> (M_PI / 180.0));
+
+  BVH_Mat4f aRotationMat;
+  aRotationMat.SetValue (0, 0,  aCos);
+  aRotationMat.SetValue (1, 1,  aCos);
+  aRotationMat.SetValue (0, 1, -aSin);
+  aRotationMat.SetValue (1, 0,  aSin);
+
+  theMatrix = theMatrix * aRotationMat;
+}
+
 // =======================================================================
 // function : CreateMaterial
 // purpose  : Creates ray-tracing material properties
 // =======================================================================
-void CreateMaterial (const OPENGL_SURF_PROP& theProp, OpenGl_RaytraceMaterial& theMaterial)
+Standard_Boolean OpenGl_Workspace::CreateMaterial (const OpenGl_AspectFace* theAspect, OpenGl_RaytraceMaterial& theMaterial)
 {
-  const float* aSrcAmb = theProp.isphysic ? theProp.ambcol.rgb : theProp.matcol.rgb;
-  theMaterial.Ambient = BVH_Vec4f (aSrcAmb[0] * theProp.amb,
-                                   aSrcAmb[1] * theProp.amb,
-                                   aSrcAmb[2] * theProp.amb,
-                                   1.0f);
-
-  const float* aSrcDif = theProp.isphysic ? theProp.difcol.rgb : theProp.matcol.rgb;
-  theMaterial.Diffuse = BVH_Vec4f (aSrcDif[0] * theProp.diff,
-                                   aSrcDif[1] * theProp.diff,
-                                   aSrcDif[2] * theProp.diff,
-                                   1.0f);
-
-  const float aDefSpecCol[4] = {1.0f, 1.0f, 1.0f, 1.0f};
-  const float* aSrcSpe = theProp.isphysic ? theProp.speccol.rgb : aDefSpecCol;
-  theMaterial.Specular = BVH_Vec4f (aSrcSpe[0] * theProp.spec,
-                                    aSrcSpe[1] * theProp.spec,
-                                    aSrcSpe[2] * theProp.spec,
-                                    theProp.shine);
-
-  const float* aSrcEms = theProp.isphysic ? theProp.emscol.rgb : theProp.matcol.rgb;
-  theMaterial.Emission = BVH_Vec4f (aSrcEms[0] * theProp.emsv,
-                                    aSrcEms[1] * theProp.emsv,
-                                    aSrcEms[2] * theProp.emsv,
-                                    1.0f);
+  const OPENGL_SURF_PROP& aProperties = theAspect->IntFront();
+
+  const Standard_ShortReal* aSrcAmbient =
+    aProperties.isphysic ? aProperties.ambcol.rgb : aProperties.matcol.rgb;
+
+  theMaterial.Ambient = BVH_Vec4f (aSrcAmbient[0] * aProperties.amb,
+                                   aSrcAmbient[1] * aProperties.amb,
+                                   aSrcAmbient[2] * aProperties.amb,
+                                   1.f);
+
+  const Standard_ShortReal* aSrcDiffuse =
+    aProperties.isphysic ? aProperties.difcol.rgb : aProperties.matcol.rgb;
+
+  theMaterial.Diffuse = BVH_Vec4f (aSrcDiffuse[0] * aProperties.diff,
+                                   aSrcDiffuse[1] * aProperties.diff,
+                                   aSrcDiffuse[2] * aProperties.diff,
+                                   -1.f /* no texture */);
+
+  theMaterial.Specular = BVH_Vec4f (
+    (aProperties.isphysic ? aProperties.speccol.rgb[0] : 1.f) * aProperties.spec,
+    (aProperties.isphysic ? aProperties.speccol.rgb[1] : 1.f) * aProperties.spec,
+    (aProperties.isphysic ? aProperties.speccol.rgb[2] : 1.f) * aProperties.spec,
+    aProperties.shine);
+
+  const Standard_ShortReal* aSrcEmission =
+    aProperties.isphysic ? aProperties.emscol.rgb : aProperties.matcol.rgb;
+
+  theMaterial.Emission = BVH_Vec4f (aSrcEmission[0] * aProperties.emsv,
+                                    aSrcEmission[1] * aProperties.emsv,
+                                    aSrcEmission[2] * aProperties.emsv,
+                                    1.f);
 
   // Note: Here we use sub-linear transparency function
   // to produce realistic-looking transparency effect
-  theMaterial.Transparency = BVH_Vec4f (powf (theProp.trans, 0.75f),
-                                        1.f - theProp.trans,
-                                        theProp.index == 0 ? 1.f : theProp.index,
-                                        theProp.index == 0 ? 1.f : 1.f / theProp.index);
+  theMaterial.Transparency = BVH_Vec4f (powf (aProperties.trans, 0.75f),
+                                        1.f - aProperties.trans,
+                                        aProperties.index == 0 ? 1.f : aProperties.index,
+                                        aProperties.index == 0 ? 1.f : 1.f / aProperties.index);
+
+  const Standard_ShortReal aMaxRefl = Max (theMaterial.Diffuse.x() + theMaterial.Specular.x(),
+                                      Max (theMaterial.Diffuse.y() + theMaterial.Specular.y(),
+                                           theMaterial.Diffuse.z() + theMaterial.Specular.z()));
 
-  const float aMaxRefl = Max (theMaterial.Diffuse.x() + theMaterial.Specular.x(),
-                         Max (theMaterial.Diffuse.y() + theMaterial.Specular.y(),
-                              theMaterial.Diffuse.z() + theMaterial.Specular.z()));
+  const Standard_ShortReal aReflectionScale = 0.75f / aMaxRefl;
 
-  const float aReflectionScale = 0.75f / aMaxRefl;
+  theMaterial.Reflection = BVH_Vec4f (
+    aProperties.speccol.rgb[0] * aProperties.spec * aReflectionScale,
+    aProperties.speccol.rgb[1] * aProperties.spec * aReflectionScale,
+    aProperties.speccol.rgb[2] * aProperties.spec * aReflectionScale,
+    0.f);
 
-  theMaterial.Reflection = BVH_Vec4f (theProp.speccol.rgb[0] * theProp.spec * aReflectionScale,
-                                      theProp.speccol.rgb[1] * theProp.spec * aReflectionScale,
-                                      theProp.speccol.rgb[2] * theProp.spec * aReflectionScale,
-                                      0.f);
+  if (theAspect->DoTextureMap())
+  {
+    if (myGlContext->arbTexBindless != NULL)
+    {
+      BuildTexTransform (theAspect->TextureParams(), theMaterial.TextureTransform);
+      theMaterial.Diffuse.w() = static_cast<Standard_ShortReal> (
+        myRaytraceGeometry.AddTexture (theAspect->TextureRes (myGlContext)));
+    }
+    else if (!myIsRaytraceWarnTextures)
+    {
+      myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+                                GL_DEBUG_TYPE_PORTABILITY_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB,
+                                "Warning: texturing in Ray-Trace requires GL_ARB_bindless_texture extension which is missing. "
+                                "Textures will be ignored.");
+      myIsRaytraceWarnTextures = Standard_True;
+    }
+  }
+
+  return Standard_True;
 }
 
 // =======================================================================
@@ -313,7 +371,7 @@ Standard_Boolean OpenGl_Workspace::AddRaytraceStructure (const OpenGl_Structure*
     aStructMatID = static_cast<Standard_Integer> (myRaytraceGeometry.Materials.size());
 
     OpenGl_RaytraceMaterial aStructMaterial;
-    CreateMaterial (theStructure->AspectFace()->IntFront(), aStructMaterial);
+    CreateMaterial (theStructure->AspectFace(), aStructMaterial);
 
     myRaytraceGeometry.Materials.push_back (aStructMaterial);
   }
@@ -362,7 +420,7 @@ Standard_Boolean OpenGl_Workspace::AddRaytraceGroups (const OpenGl_Structure*
       aGroupMatID = static_cast<Standard_Integer> (myRaytraceGeometry.Materials.size());
 
       OpenGl_RaytraceMaterial aGroupMaterial;
-      CreateMaterial (aGroupIter.Value()->AspectFace()->IntFront(), aGroupMaterial);
+      CreateMaterial (aGroupIter.Value()->AspectFace(), aGroupMaterial);
 
       myRaytraceGeometry.Materials.push_back (aGroupMaterial);
     }
@@ -385,7 +443,7 @@ Standard_Boolean OpenGl_Workspace::AddRaytraceGroups (const OpenGl_Structure*
         aMatID = static_cast<Standard_Integer> (myRaytraceGeometry.Materials.size());
 
         OpenGl_RaytraceMaterial aMaterial;
-        CreateMaterial (anAspect->IntFront(), aMaterial);
+        CreateMaterial (anAspect, aMaterial);
 
         myRaytraceGeometry.Materials.push_back (aMaterial);
       }
@@ -400,7 +458,7 @@ Standard_Boolean OpenGl_Workspace::AddRaytraceGroups (const OpenGl_Structure*
           if (aSetIter != myArrayToTrianglesMap.end())
           {
             OpenGl_TriangleSet* aSet = aSetIter->second;
+
             BVH_Transform<Standard_ShortReal, 4>* aTransform = new BVH_Transform<Standard_ShortReal, 4>();
 
             if (theTransform != NULL)
@@ -410,14 +468,14 @@ Standard_Boolean OpenGl_Workspace::AddRaytraceGroups (const OpenGl_Structure*
           
             aSet->SetProperties (aTransform);
 
-            if (aSet->MaterialIndex() != OpenGl_TriangleSet::INVALID_MATERIAL && aSet->MaterialIndex() != aMatID )
+            if (aSet->MaterialIndex() != OpenGl_TriangleSet::INVALID_MATERIAL && aSet->MaterialIndex() != aMatID)
             {
               aSet->SetMaterialIndex (aMatID);
             }
           }
           else
           {
-            NCollection_Handle<BVH_Object<Standard_ShortReal, 4> > aSet =
+            NCollection_Handle<BVH_Object<Standard_ShortReal, 3> > aSet =
               AddRaytracePrimitiveArray (aPrimArray, aMatID, 0);
 
             if (!aSet.IsNull())
@@ -448,13 +506,17 @@ Standard_Boolean OpenGl_Workspace::AddRaytraceGroups (const OpenGl_Structure*
 // =======================================================================
 OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (const OpenGl_PrimitiveArray* theArray,
                                                                  Standard_Integer             theMatID,
-                                                                 const Standard_ShortReal*    theTransform)
+                                                                 const OpenGl_Mat4*           theTransform)
 {
   const Handle(Graphic3d_IndexBuffer)& anIndices = theArray->Indices();
   const Handle(Graphic3d_Buffer)&      anAttribs = theArray->Attributes();
   const Handle(Graphic3d_BoundBuffer)& aBounds   = theArray->Bounds();
   if (theArray->DrawMode() < GL_TRIANGLES
+  #if !defined(GL_ES_VERSION_2_0)
    || theArray->DrawMode() > GL_POLYGON
+  #else
+   || theArray->DrawMode() > GL_TRIANGLE_FAN
+  #endif
    || anAttribs.IsNull())
   {
     return NULL;
@@ -463,19 +525,33 @@ OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (const OpenGl_Pr
 #ifdef RAY_TRACE_PRINT_INFO
   switch (theArray->DrawMode())
   {
-    case GL_POLYGON:        std::cout << "\tAdding GL_POLYGON\n";        break;
     case GL_TRIANGLES:      std::cout << "\tAdding GL_TRIANGLES\n";      break;
-    case GL_QUADS:          std::cout << "\tAdding GL_QUADS\n";          break;
     case GL_TRIANGLE_FAN:   std::cout << "\tAdding GL_TRIANGLE_FAN\n";   break;
     case GL_TRIANGLE_STRIP: std::cout << "\tAdding GL_TRIANGLE_STRIP\n"; break;
+  #if !defined(GL_ES_VERSION_2_0)
+    case GL_QUADS:          std::cout << "\tAdding GL_QUADS\n";          break;
     case GL_QUAD_STRIP:     std::cout << "\tAdding GL_QUAD_STRIP\n";     break;
+    case GL_POLYGON:        std::cout << "\tAdding GL_POLYGON\n";        break;
+  #endif
   }
 #endif
 
+  OpenGl_Mat4 aNormalMatrix;
+
+  if (theTransform != NULL)
+  {
+    Standard_ASSERT_RETURN (theTransform->Inverted (aNormalMatrix),
+      "Error: Failed to compute normal transformation matrix", NULL);
+
+    aNormalMatrix.Transpose();
+  }
+
   OpenGl_TriangleSet* aSet = new OpenGl_TriangleSet (theArray->GetUID());
   {
     aSet->Vertices.reserve (anAttribs->NbElements);
     aSet->Normals .reserve (anAttribs->NbElements);
+    aSet->TexCrds .reserve (anAttribs->NbElements);
+
     const size_t aVertFrom = aSet->Vertices.size();
     for (Standard_Integer anAttribIter = 0; anAttribIter < anAttribs->NbAttributes; ++anAttribIter)
     {
@@ -488,8 +564,8 @@ OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (const OpenGl_Pr
         {
           for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
           {
-            const Graphic3d_Vec3& aVert = *reinterpret_cast<const Graphic3d_Vec3* >(anAttribs->value (aVertIter) + anOffset);
-            aSet->Vertices.push_back (BVH_Vec4f (aVert.x(), aVert.y(), aVert.z(), 1.0f));
+            aSet->Vertices.push_back (
+              *reinterpret_cast<const Graphic3d_Vec3* >(anAttribs->value (aVertIter) + anOffset));
           }
         }
         else if (anAttrib.DataType == Graphic3d_TOD_VEC2)
@@ -497,7 +573,7 @@ OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (const OpenGl_Pr
           for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
           {
             const Graphic3d_Vec2& aVert = *reinterpret_cast<const Graphic3d_Vec2* >(anAttribs->value (aVertIter) + anOffset);
-            aSet->Vertices.push_back (BVH_Vec4f (aVert.x(), aVert.y(), 0.0f, 1.0f));
+            aSet->Vertices.push_back (BVH_Vec3f (aVert.x(), aVert.y(), 0.0f));
           }
         }
       }
@@ -508,8 +584,19 @@ OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (const OpenGl_Pr
         {
           for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
           {
-            const Graphic3d_Vec3& aNorm = *reinterpret_cast<const Graphic3d_Vec3* >(anAttribs->value (aVertIter) + anOffset);
-            aSet->Normals.push_back (BVH_Vec4f (aNorm.x(), aNorm.y(), aNorm.z(), 0.0f));
+            aSet->Normals.push_back (
+              *reinterpret_cast<const Graphic3d_Vec3* >(anAttribs->value (aVertIter) + anOffset));
+          }
+        }
+      }
+      else if (anAttrib.Id == Graphic3d_TOA_UV)
+      {
+        if (anAttrib.DataType == Graphic3d_TOD_VEC2)
+        {
+          for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
+          {
+            aSet->TexCrds.push_back (
+              *reinterpret_cast<const Graphic3d_Vec2* >(anAttribs->value (aVertIter) + anOffset));
           }
         }
       }
@@ -519,39 +606,55 @@ OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (const OpenGl_Pr
     {
       for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
       {
-        aSet->Normals.push_back (BVH_Vec4f());
+        aSet->Normals.push_back (BVH_Vec3f());
       }
     }
 
-    if (theTransform)
+    if (aSet->TexCrds.size() != aSet->Vertices.size())
+    {
+      for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
+      {
+        aSet->TexCrds.push_back (BVH_Vec2f());
+      }
+    }
+
+    if (theTransform != NULL)
     {
       for (size_t aVertIter = aVertFrom; aVertIter < aSet->Vertices.size(); ++aVertIter)
       {
-        BVH_Vec4f& aVertex = aSet->Vertices[aVertIter];
-        aVertex = MatVecMult (theTransform, aVertex);
+        BVH_Vec3f& aVertex = aSet->Vertices[aVertIter];
+
+        BVH_Vec4f aTransVertex =
+          *theTransform * BVH_Vec4f (aVertex.x(), aVertex.y(), aVertex.z(), 1.f);
+
+        aVertex = BVH_Vec3f (aTransVertex.x(), aTransVertex.y(), aTransVertex.z());
       }
       for (size_t aVertIter = aVertFrom; aVertIter < aSet->Normals.size(); ++aVertIter)
       {
-        BVH_Vec4f& aNorm = aSet->Normals[aVertIter];
-        aNorm = MatVecMult (theTransform, aNorm);
+        BVH_Vec3f& aNormal = aSet->Normals[aVertIter];
+
+        BVH_Vec4f aTransNormal =
+          aNormalMatrix * BVH_Vec4f (aNormal.x(), aNormal.y(), aNormal.z(), 0.f);
+
+        aNormal = BVH_Vec3f (aTransNormal.x(), aTransNormal.y(), aTransNormal.z());
       }
     }
 
     if (!aBounds.IsNull())
     {
-  #ifdef RAY_TRACE_PRINT_INFO
+#ifdef RAY_TRACE_PRINT_INFO
       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];
 
-  #ifdef RAY_TRACE_PRINT_INFO
+#ifdef RAY_TRACE_PRINT_INFO
         std::cout << "\tAdding indices from bound " << aBound << ": " <<
                                       aBoundStart << " .. " << aVertNum << std::endl;
-  #endif
+#endif
 
         if (!AddRaytraceVertexIndices (*aSet, *theArray, aBoundStart, aVertNum, theMatID))
         {
@@ -597,11 +700,13 @@ Standard_Boolean OpenGl_Workspace::AddRaytraceVertexIndices (OpenGl_TriangleSet&
   switch (theArray.DrawMode())
   {
     case GL_TRIANGLES:      return AddRaytraceTriangleArray        (theSet, theArray.Indices(), theOffset, theCount, theMatID);
-    case GL_QUADS:          return AddRaytraceQuadrangleArray      (theSet, theArray.Indices(), theOffset, theCount, theMatID);
     case GL_TRIANGLE_FAN:   return AddRaytraceTriangleFanArray     (theSet, theArray.Indices(), theOffset, theCount, theMatID);
     case GL_TRIANGLE_STRIP: return AddRaytraceTriangleStripArray   (theSet, theArray.Indices(), theOffset, theCount, theMatID);
+  #if !defined(GL_ES_VERSION_2_0)
+    case GL_QUADS:          return AddRaytraceQuadrangleArray      (theSet, theArray.Indices(), theOffset, theCount, theMatID);
     case GL_QUAD_STRIP:     return AddRaytraceQuadrangleStripArray (theSet, theArray.Indices(), theOffset, theCount, theMatID);
     case GL_POLYGON:        return AddRaytracePolygonArray         (theSet, theArray.Indices(), theOffset, theCount, theMatID);
+  #endif
   }
   return Standard_False;
 }
@@ -856,7 +961,7 @@ Standard_Boolean OpenGl_Workspace::AddRaytracePolygonArray (OpenGl_TriangleSet&
 // function : UpdateRaytraceLightSources
 // purpose  : Updates 3D scene light sources for ray-tracing
 // =======================================================================
-Standard_Boolean OpenGl_Workspace::UpdateRaytraceLightSources (const GLdouble theInvModelView[16])
+Standard_Boolean OpenGl_Workspace::UpdateRaytraceLightSources (const OpenGl_Mat4& theInvModelView)
 {
   myRaytraceGeometry.Sources.clear();
 
@@ -894,9 +999,10 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceLightSources (const GLdouble th
     }
 
     if (aLight.IsHeadlight)
-      aPosition = MatVecMult (theInvModelView, aPosition);
+    {
+      aPosition = theInvModelView * aPosition;
+    }
 
-    
     myRaytraceGeometry.Sources.push_back (OpenGl_RaytraceLight (aDiffuse, aPosition));
   }
 
@@ -947,7 +1053,7 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceEnvironmentMap()
 
     if (!aProgram.IsNull())
     {
-      aProgram->Bind (myGlContext);
+      myGlContext->BindProgram (aProgram);
 
       if (!myView->TextureEnv().IsNull() && myView->SurfaceDetail() != Visual3d_TOD_NONE)
       {
@@ -955,20 +1061,18 @@ Standard_Boolean OpenGl_Workspace::UpdateRaytraceEnvironmentMap()
           myGlContext, GL_TEXTURE0 + OpenGl_RT_EnvironmentMapTexture);
 
         aProgram->SetUniform (myGlContext,
-          myUniformLocations[anIdx][OpenGl_RT_uEnvironmentEnable], 1);
+          myUniformLocations[anIdx][OpenGl_RT_uEnvMapEnable], 1);
       }
       else
       {
         aProgram->SetUniform (myGlContext,
-          myUniformLocations[anIdx][OpenGl_RT_uEnvironmentEnable], 0);
+          myUniformLocations[anIdx][OpenGl_RT_uEnvMapEnable], 0);
       }
     }
   }
 
-  OpenGl_ShaderProgram::Unbind (myGlContext);
-
+  myGlContext->BindProgram (NULL);
   myViewModificationStatus = myView->ModificationState();
-
   return Standard_True;
 }
 
@@ -1032,8 +1136,9 @@ Handle(OpenGl_ShaderObject) OpenGl_Workspace::LoadShader (const ShaderSource& th
 
   if (!aShader->Create (myGlContext))
   {
-    const TCollection_ExtendedString aMessage = "Error: Failed to create shader object";
-      
+    const TCollection_ExtendedString aMessage = TCollection_ExtendedString ("Error: Failed to create ") +
+      (theType == GL_VERTEX_SHADER ? "vertex" : "fragment") + " shader object";
+
     myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
       GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
 
@@ -1044,8 +1149,9 @@ Handle(OpenGl_ShaderObject) OpenGl_Workspace::LoadShader (const ShaderSource& th
 
   if (!aShader->LoadSource (myGlContext, theSource.Source()))
   {
-    const TCollection_ExtendedString aMessage = "Error: Failed to set shader source";
-      
+    const TCollection_ExtendedString aMessage = TCollection_ExtendedString ("Error: Failed to set ") +
+      (theType == GL_VERTEX_SHADER ? "vertex" : "fragment") + " shader source";
+
     myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
       GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
 
@@ -1058,37 +1164,31 @@ Handle(OpenGl_ShaderObject) OpenGl_Workspace::LoadShader (const ShaderSource& th
 
   if (!aShader->Compile (myGlContext))
   {
-    if (aShader->FetchInfoLog (myGlContext, aBuildLog))
-    {
-      const TCollection_ExtendedString aMessage =
-        TCollection_ExtendedString ("Error: Failed to compile shader object:\n") + aBuildLog;
+    aShader->FetchInfoLog (myGlContext, aBuildLog);
 
-#ifdef RAY_TRACE_PRINT_INFO
-      std::cout << aBuildLog << std::endl;
-#endif
+    const TCollection_ExtendedString aMessage = TCollection_ExtendedString ("Error: Failed to compile ") +
+      (theType == GL_VERTEX_SHADER ? "vertex" : "fragment") + " shader object:\n" + aBuildLog;
+
+    myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+      GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
 
-      myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-        GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
-    }
-    
     aShader->Release (myGlContext.operator->());
 
     return Handle(OpenGl_ShaderObject)();
   }
-
-#ifdef RAY_TRACE_PRINT_INFO
-  if (aShader->FetchInfoLog (myGlContext, aBuildLog))
+  else if (myGlContext->caps->glslWarnings)
   {
-    if (!aBuildLog.IsEmpty())
-    {
-      std::cout << aBuildLog << std::endl;
-    }
-    else
+    aShader->FetchInfoLog (myGlContext, aBuildLog);
+
+    if (!aBuildLog.IsEmpty() && !aBuildLog.IsEqual ("No errors.\n"))
     {
-      std::cout << "Info: shader build log is empty" << std::endl;
+      const TCollection_ExtendedString aMessage = TCollection_ExtendedString (theType == GL_VERTEX_SHADER ?
+        "Vertex" : "Fragment") + " shader was compiled with following warnings:\n" + aBuildLog;
+
+      myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+        GL_DEBUG_TYPE_PORTABILITY_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMessage);
     }
-  }  
-#endif
+  }
 
   return aShader;
 }
@@ -1105,16 +1205,47 @@ Standard_Boolean OpenGl_Workspace::SafeFailBack (const TCollection_ExtendedStrin
   myComputeInitStatus = OpenGl_RT_FAIL;
 
   ReleaseRaytraceResources();
-  
+
   return Standard_False;
 }
 
+// =======================================================================
+// function : GenerateShaderPrefix
+// purpose  : Generates shader prefix based on current ray-tracing options
+// =======================================================================
+TCollection_AsciiString OpenGl_Workspace::GenerateShaderPrefix()
+{
+  TCollection_AsciiString aPrefixString =
+    TCollection_AsciiString ("#define STACK_SIZE ") + TCollection_AsciiString (myRaytraceParameters.StackSize) + "\n" +
+    TCollection_AsciiString ("#define NB_BOUNCES ") + TCollection_AsciiString (myRaytraceParameters.NbBounces);
+
+  if (myRaytraceParameters.TransparentShadows)
+  {
+    aPrefixString += TCollection_AsciiString ("\n#define TRANSPARENT_SHADOWS");
+  }
+
+  // If OpenGL driver supports bindless textures
+  // activate texturing in ray-tracing mode
+  if (myGlContext->arbTexBindless != NULL)
+  {
+    aPrefixString += TCollection_AsciiString ("\n#define USE_TEXTURES") +
+      TCollection_AsciiString ("\n#define MAX_TEX_NUMBER ") + TCollection_AsciiString (OpenGl_RaytraceGeometry::MAX_TEX_NUMBER);
+  }
+
+  return aPrefixString;
+}
+
 // =======================================================================
 // function : InitRaytraceResources
 // purpose  : Initializes OpenGL/GLSL shader programs
 // =======================================================================
 Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView& theCView)
 {
+  if (myComputeInitStatus == OpenGl_RT_FAIL)
+  {
+    return Standard_False;
+  }
+
   Standard_Boolean aToRebuildShaders = Standard_False;
 
   if (myComputeInitStatus == OpenGl_RT_INIT)
@@ -1143,9 +1274,9 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
       }
     }
 
-    if (theCView.RenderParams.RaytracingDepth != myRaytraceParameters.TraceDepth)
+    if (theCView.RenderParams.RaytracingDepth != myRaytraceParameters.NbBounces)
     {
-      myRaytraceParameters.TraceDepth = theCView.RenderParams.RaytracingDepth;
+      myRaytraceParameters.NbBounces = theCView.RenderParams.RaytracingDepth;
       aToRebuildShaders = Standard_True;
     }
 
@@ -1164,14 +1295,7 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
       // Change state to force update all uniforms
       ++myViewModificationStatus;
 
-      TCollection_AsciiString aPrefixString =
-        TCollection_AsciiString ("#define STACK_SIZE ") + TCollection_AsciiString (myRaytraceParameters.StackSize) + "\n" +
-        TCollection_AsciiString ("#define TRACE_DEPTH ") + TCollection_AsciiString (myRaytraceParameters.TraceDepth);
-
-      if (myRaytraceParameters.TransparentShadows)
-      {
-        aPrefixString += TCollection_AsciiString ("\n#define TRANSPARENT_SHADOWS");
-      }
+      TCollection_AsciiString aPrefixString = GenerateShaderPrefix();
 
 #ifdef RAY_TRACE_PRINT_INFO
       std::cout << "GLSL prefix string:" << std::endl << aPrefixString << std::endl;
@@ -1183,19 +1307,21 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
       if (!myRaytraceShader->LoadSource (myGlContext, myRaytraceShaderSource.Source())
        || !myPostFSAAShader->LoadSource (myGlContext, myPostFSAAShaderSource.Source()))
       {
-        return Standard_False;
+        return SafeFailBack ("Failed to load source into ray-tracing fragment shaders");
       }
 
       if (!myRaytraceShader->Compile (myGlContext)
        || !myPostFSAAShader->Compile (myGlContext))
       {
-        return Standard_False;
+        return SafeFailBack ("Failed to compile ray-tracing fragment shaders");
       }
 
+      myRaytraceProgram->SetAttributeName (myGlContext, Graphic3d_TOA_POS, "occVertex");
+      myPostFSAAProgram->SetAttributeName (myGlContext, Graphic3d_TOA_POS, "occVertex");
       if (!myRaytraceProgram->Link (myGlContext)
        || !myPostFSAAProgram->Link (myGlContext))
       {
-        return Standard_False;
+        return SafeFailBack ("Failed to initialize vertex attributes for ray-tracing program");
       }
     }
   }
@@ -1204,26 +1330,20 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
   {
     if (!myGlContext->IsGlGreaterEqual (3, 1))
     {
-      const TCollection_ExtendedString aMessage = "Ray-tracing requires OpenGL 3.1 and higher";
-
-      myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-        GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
-
-      return Standard_False;
+      return SafeFailBack ("Ray-tracing requires OpenGL 3.1 and higher");
+    }
+    else if (!myGlContext->arbTboRGB32)
+    {
+      return SafeFailBack ("Ray-tracing requires OpenGL 4.0+ or GL_ARB_texture_buffer_object_rgb32 extension");
     }
 
-    myRaytraceParameters.TraceDepth = theCView.RenderParams.RaytracingDepth;
+    myRaytraceParameters.NbBounces = theCView.RenderParams.RaytracingDepth;
 
     TCollection_AsciiString aFolder = Graphic3d_ShaderProgram::ShadersFolder();
 
     if (aFolder.IsEmpty())
     {
-      const TCollection_ExtendedString aMessage = "Failed to locate shaders directory";
-      
-      myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
-        GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aMessage);
-      
-      return Standard_False;
+      return SafeFailBack ("Failed to locate shaders directory");
     }
 
     if (myIsRaytraceDataValid)
@@ -1232,14 +1352,7 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
         myRaytraceGeometry.HighLevelTreeDepth() + myRaytraceGeometry.BottomLevelTreeDepth());
     }
 
-    TCollection_AsciiString aPrefixString =
-      TCollection_AsciiString ("#define STACK_SIZE ") + TCollection_AsciiString (myRaytraceParameters.StackSize) + "\n" +
-      TCollection_AsciiString ("#define TRACE_DEPTH ") + TCollection_AsciiString (myRaytraceParameters.TraceDepth);
-
-    if (myRaytraceParameters.TransparentShadows)
-    {
-      aPrefixString += TCollection_AsciiString ("\n#define TRANSPARENT_SHADOWS");
-    }
+    TCollection_AsciiString aPrefixString  = GenerateShaderPrefix();
 
 #ifdef RAY_TRACE_PRINT_INFO
     std::cout << "GLSL prefix string:" << std::endl << aPrefixString << std::endl;
@@ -1251,10 +1364,11 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
 
       if (aBasicVertShader.IsNull())
       {
-        return SafeFailBack ("Failed to set vertex shader source");
+        return SafeFailBack ("Failed to initialize ray-trace vertex shader");
       }
 
-      TCollection_AsciiString aFiles[] = { aFolder + "/RaytraceBase.fs", aFolder + "/RaytraceRender.fs" };
+      TCollection_AsciiString aFiles[] = { aFolder + "/RaytraceBase.fs",
+                                           aFolder + "/RaytraceRender.fs" };
 
       myRaytraceShaderSource.Load (aFiles, 2);
 
@@ -1266,7 +1380,7 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
       {
         aBasicVertShader->Release (myGlContext.operator->());
 
-        return SafeFailBack ("Failed to set ray-trace fragment shader source");
+        return SafeFailBack ("Failed to initialize ray-trace fragment shader");
       }
 
       myRaytraceProgram = new OpenGl_ShaderProgram;
@@ -1286,18 +1400,29 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
         return SafeFailBack ("Failed to attach ray-trace shader objects");
       }
 
+      myRaytraceProgram->SetAttributeName (myGlContext, Graphic3d_TOA_POS, "occVertex");
+
+      TCollection_AsciiString aLinkLog;
+
       if (!myRaytraceProgram->Link (myGlContext))
       {
-        TCollection_AsciiString aLinkLog;
+        myRaytraceProgram->FetchInfoLog (myGlContext, aLinkLog);
+
+        return SafeFailBack (TCollection_ExtendedString (
+          "Failed to link ray-trace shader program:\n") + aLinkLog);
+      }
+      else if (myGlContext->caps->glslWarnings)
+      {
+        myRaytraceProgram->FetchInfoLog (myGlContext, aLinkLog);
 
-        if (myRaytraceProgram->FetchInfoLog (myGlContext, aLinkLog))
+        if (!aLinkLog.IsEmpty() && !aLinkLog.IsEqual ("No errors.\n"))
         {
-  #ifdef RAY_TRACE_PRINT_INFO
-          std::cout << aLinkLog << std::endl;
-  #endif
-        }
+          const TCollection_ExtendedString aMessage = TCollection_ExtendedString (
+            "Ray-trace shader program was linked with following warnings:\n") + aLinkLog;
 
-        return SafeFailBack ("Failed to link ray-trace shader program");
+          myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+            GL_DEBUG_TYPE_PORTABILITY_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMessage);
+        }
       }
     }
 
@@ -1307,10 +1432,11 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
 
       if (aBasicVertShader.IsNull())
       {
-        return SafeFailBack ("Failed to set vertex shader source");
+        return SafeFailBack ("Failed to initialize FSAA vertex shader");
       }
 
-      TCollection_AsciiString aFiles[] = { aFolder + "/RaytraceBase.fs", aFolder + "/RaytraceSmooth.fs" };
+      TCollection_AsciiString aFiles[] = { aFolder + "/RaytraceBase.fs",
+                                           aFolder + "/RaytraceSmooth.fs" };
 
       myPostFSAAShaderSource.Load (aFiles, 2);
 
@@ -1322,7 +1448,7 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
       {
         aBasicVertShader->Release (myGlContext.operator->());
 
-        return SafeFailBack ("Failed to set FSAA fragment shader source");
+        return SafeFailBack ("Failed to initialize FSAA fragment shader");
       }
 
       myPostFSAAProgram = new OpenGl_ShaderProgram;
@@ -1342,18 +1468,29 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
         return SafeFailBack ("Failed to attach FSAA shader objects");
       }
 
+      myPostFSAAProgram->SetAttributeName (myGlContext, Graphic3d_TOA_POS, "occVertex");
+
+      TCollection_AsciiString aLinkLog;
+
       if (!myPostFSAAProgram->Link (myGlContext))
       {
-        TCollection_AsciiString aLinkLog;
+        myPostFSAAProgram->FetchInfoLog (myGlContext, aLinkLog);
+      
+        return SafeFailBack (TCollection_ExtendedString (
+          "Failed to link FSAA shader program:\n") + aLinkLog);
+      }
+      else if (myGlContext->caps->glslWarnings)
+      {
+        myPostFSAAProgram->FetchInfoLog (myGlContext, aLinkLog);
 
-        if (myPostFSAAProgram->FetchInfoLog (myGlContext, aLinkLog))
+        if (!aLinkLog.IsEmpty() && !aLinkLog.IsEqual ("No errors.\n"))
         {
-  #ifdef RAY_TRACE_PRINT_INFO
-          std::cout << aLinkLog << std::endl;
-  #endif
+          const TCollection_ExtendedString aMessage = TCollection_ExtendedString (
+            "FSAA shader program was linked with following warnings:\n") + aLinkLog;
+
+          myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+            GL_DEBUG_TYPE_PORTABILITY_ARB, 0, GL_DEBUG_SEVERITY_LOW_ARB, aMessage);
         }
-      
-        return SafeFailBack ("Failed to link FSAA shader program");
       }
     }
   }
@@ -1365,7 +1502,7 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
       Handle(OpenGl_ShaderProgram)& aShaderProgram =
         (anIndex == 0) ? myRaytraceProgram : myPostFSAAProgram;
 
-      aShaderProgram->Bind (myGlContext);
+      myGlContext->BindProgram (aShaderProgram);
 
       aShaderProgram->SetSampler (myGlContext,
         "uSceneMinPointTexture", OpenGl_RT_SceneMinPointTexture);
@@ -1373,26 +1510,22 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
         "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,
         "uGeometryNormalTexture", OpenGl_RT_GeometryNormalTexture);
       aShaderProgram->SetSampler (myGlContext,
-        "uGeometryTriangTexture", OpenGl_RT_GeometryTriangTexture);
+        "uGeometryTexCrdTexture", OpenGl_RT_GeometryTexCrdTexture);
       aShaderProgram->SetSampler (myGlContext,
-        "uRaytraceMaterialTexture", OpenGl_RT_RaytraceMaterialTexture);
-      aShaderProgram->SetSampler (myGlContext,
-        "uRaytraceLightSrcTexture", OpenGl_RT_RaytraceLightSrcTexture);
+        "uGeometryTriangTexture", OpenGl_RT_GeometryTriangTexture);
       aShaderProgram->SetSampler (myGlContext, 
         "uSceneTransformTexture", OpenGl_RT_SceneTransformTexture);
       aShaderProgram->SetSampler (myGlContext,
         "uEnvironmentMapTexture", OpenGl_RT_EnvironmentMapTexture);
+      aShaderProgram->SetSampler (myGlContext,
+        "uRaytraceMaterialTexture", OpenGl_RT_RaytraceMaterialTexture);
+      aShaderProgram->SetSampler (myGlContext,
+        "uRaytraceLightSrcTexture", OpenGl_RT_RaytraceLightSrcTexture);
 
       aShaderProgram->SetSampler (myGlContext,
         "uOpenGlColorTexture", OpenGl_RT_OpenGlColorTexture);
@@ -1406,7 +1539,7 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
       }
 
       myUniformLocations[anIndex][OpenGl_RT_aPosition] =
-        aShaderProgram->GetAttributeLocation (myGlContext, "aPosition");
+        aShaderProgram->GetAttributeLocation (myGlContext, "occVertex");
 
       myUniformLocations[anIndex][OpenGl_RT_uOriginLB] =
         aShaderProgram->GetUniformLocation (myGlContext, "uOriginLB");
@@ -1424,23 +1557,17 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
         aShaderProgram->GetUniformLocation (myGlContext, "uDirectLT");
       myUniformLocations[anIndex][OpenGl_RT_uDirectRT] =
         aShaderProgram->GetUniformLocation (myGlContext, "uDirectRT");
-      myUniformLocations[anIndex][OpenGl_RT_uInvModelProj] =
-        aShaderProgram->GetUniformLocation (myGlContext, "uInvModelProj");
-
-      myUniformLocations[anIndex][OpenGl_RT_uLightCount] =
-        aShaderProgram->GetUniformLocation (myGlContext, "uLightCount");
-      myUniformLocations[anIndex][OpenGl_RT_uLightAmbnt] =
-        aShaderProgram->GetUniformLocation (myGlContext, "uGlobalAmbient");
+      myUniformLocations[anIndex][OpenGl_RT_uUnviewMat] =
+        aShaderProgram->GetUniformLocation (myGlContext, "uUnviewMat");
 
       myUniformLocations[anIndex][OpenGl_RT_uSceneRad] =
         aShaderProgram->GetUniformLocation (myGlContext, "uSceneRadius");
       myUniformLocations[anIndex][OpenGl_RT_uSceneEps] =
         aShaderProgram->GetUniformLocation (myGlContext, "uSceneEpsilon");
-
-      myUniformLocations[anIndex][OpenGl_RT_uShadEnabled] =
-        aShaderProgram->GetUniformLocation (myGlContext, "uShadowsEnable");
-      myUniformLocations[anIndex][OpenGl_RT_uReflEnabled] =
-        aShaderProgram->GetUniformLocation (myGlContext, "uReflectionsEnable");
+      myUniformLocations[anIndex][OpenGl_RT_uLightCount] =
+        aShaderProgram->GetUniformLocation (myGlContext, "uLightCount");
+      myUniformLocations[anIndex][OpenGl_RT_uLightAmbnt] =
+        aShaderProgram->GetUniformLocation (myGlContext, "uGlobalAmbient");
 
       myUniformLocations[anIndex][OpenGl_RT_uOffsetX] =
         aShaderProgram->GetUniformLocation (myGlContext, "uOffsetX");
@@ -1448,12 +1575,23 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
         aShaderProgram->GetUniformLocation (myGlContext, "uOffsetY");
       myUniformLocations[anIndex][OpenGl_RT_uSamples] =
         aShaderProgram->GetUniformLocation (myGlContext, "uSamples");
+      myUniformLocations[anIndex][OpenGl_RT_uWinSizeX] =
+        aShaderProgram->GetUniformLocation (myGlContext, "uWinSizeX");
+      myUniformLocations[anIndex][OpenGl_RT_uWinSizeY] =
+        aShaderProgram->GetUniformLocation (myGlContext, "uWinSizeY");
+
+      myUniformLocations[anIndex][OpenGl_RT_uTextures] =
+        aShaderProgram->GetUniformLocation (myGlContext, "uTextureSamplers");
 
-      myUniformLocations[anIndex][OpenGl_RT_uEnvironmentEnable] =
+      myUniformLocations[anIndex][OpenGl_RT_uShadEnabled] =
+        aShaderProgram->GetUniformLocation (myGlContext, "uShadowsEnable");
+      myUniformLocations[anIndex][OpenGl_RT_uReflEnabled] =
+        aShaderProgram->GetUniformLocation (myGlContext, "uReflectionsEnable");
+      myUniformLocations[anIndex][OpenGl_RT_uEnvMapEnable] =
         aShaderProgram->GetUniformLocation (myGlContext, "uEnvironmentEnable");
     }
 
-    OpenGl_ShaderProgram::Unbind (myGlContext);
+    myGlContext->BindProgram (NULL);
   }
 
   if (myComputeInitStatus != OpenGl_RT_NONE)
@@ -1481,7 +1619,7 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
   myRaytraceScreenQuad.Init (myGlContext, 3, 6, aVertices);
 
   myComputeInitStatus = OpenGl_RT_INIT; // initialized in normal way
-  
+
   return Standard_True;
 }
 
@@ -1519,12 +1657,9 @@ void OpenGl_Workspace::ReleaseRaytraceResources()
   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, myGeometryTriangTexture);
   NullifyResource (myGlContext, mySceneTransformTexture);
 
@@ -1550,53 +1685,54 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
   }
 
   /////////////////////////////////////////////////////////////////////////////
-  // Create OpenGL texture buffers
+  // Prepare OpenGL textures
 
-  if (mySceneNodeInfoTexture.IsNull())  // create hight-level BVH buffers
+  if (myGlContext->arbTexBindless != NULL)
   {
-    mySceneNodeInfoTexture = new OpenGl_TextureBufferArb;
-    mySceneMinPointTexture = new OpenGl_TextureBufferArb;
-    mySceneMaxPointTexture = new OpenGl_TextureBufferArb;
-    mySceneTransformTexture = new OpenGl_TextureBufferArb;
-
-    if (!mySceneNodeInfoTexture->Create (myGlContext)
-     || !mySceneMinPointTexture->Create (myGlContext)
-     || !mySceneMaxPointTexture->Create (myGlContext)
-     || !mySceneTransformTexture->Create (myGlContext))
+    // If OpenGL driver supports bindless textures we need
+    // to get unique 64- bit handles for using on the GPU
+    if (!myRaytraceGeometry.UpdateTextureHandles (myGlContext))
     {
 #ifdef RAY_TRACE_PRINT_INFO
-      std::cout << "Error: Failed to create buffers for high-level scene BVH" << std::endl;
+      std::cout << "Error: Failed to get OpenGL texture handles" << std::endl;
 #endif
       return Standard_False;
     }
   }
 
-  if (myObjectNodeInfoTexture.IsNull())  // create bottom-level BVH buffers
+  /////////////////////////////////////////////////////////////////////////////
+  // Create OpenGL BVH buffers
+
+  if (mySceneNodeInfoTexture.IsNull())  // create scene BVH buffers
   {
-    myObjectNodeInfoTexture = new OpenGl_TextureBufferArb;
-    myObjectMinPointTexture = new OpenGl_TextureBufferArb;
-    myObjectMaxPointTexture = new OpenGl_TextureBufferArb;
+    mySceneNodeInfoTexture  = new OpenGl_TextureBufferArb;
+    mySceneMinPointTexture  = new OpenGl_TextureBufferArb;
+    mySceneMaxPointTexture  = new OpenGl_TextureBufferArb;
+    mySceneTransformTexture = new OpenGl_TextureBufferArb;
 
-    if (!myObjectNodeInfoTexture->Create (myGlContext)
-      || !myObjectMinPointTexture->Create (myGlContext)
-      || !myObjectMaxPointTexture->Create (myGlContext))
+    if (!mySceneNodeInfoTexture->Create  (myGlContext)
+     || !mySceneMinPointTexture->Create  (myGlContext)
+     || !mySceneMaxPointTexture->Create  (myGlContext)
+     || !mySceneTransformTexture->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;
     }
   }
 
-  if (myGeometryVertexTexture.IsNull())  // create geometry buffers
+  if  (myGeometryVertexTexture.IsNull())  // create geometry buffers
   {
     myGeometryVertexTexture = new OpenGl_TextureBufferArb;
     myGeometryNormalTexture = new OpenGl_TextureBufferArb;
+    myGeometryTexCrdTexture = new OpenGl_TextureBufferArb;
     myGeometryTriangTexture = new OpenGl_TextureBufferArb;
 
     if (!myGeometryVertexTexture->Create (myGlContext)
-      || !myGeometryNormalTexture->Create (myGlContext)
-      || !myGeometryTriangTexture->Create (myGlContext))
+     || !myGeometryNormalTexture->Create (myGlContext)
+     || !myGeometryTexCrdTexture->Create (myGlContext)
+     || !myGeometryTriangTexture->Create (myGlContext))
     {
 #ifdef RAY_TRACE_PRINT_INFO
       std::cout << "Error: Failed to create buffers for triangulation data" << std::endl;
@@ -1605,7 +1741,7 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
     }
   }
 
-  if (myRaytraceMaterialTexture.IsNull())  // create material buffer
+  if (myRaytraceMaterialTexture.IsNull()) // create material buffer
   {
     myRaytraceMaterialTexture = new OpenGl_TextureBufferArb;
 
@@ -1617,35 +1753,13 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
       return Standard_False;
     }
   }
-
-  /////////////////////////////////////////////////////////////////////////////
-  // Write top-level BVH buffers
-
-  const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& 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, 4, GLsizei (aBVH->MinPointBuffer().size()),
-                                             reinterpret_cast<const GLfloat*> (&aBVH->MinPointBuffer().front()));
-    aResult &= mySceneMaxPointTexture->Init (myGlContext, 4, 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()];
-  BVH_Mat4f anIdentity;
+
+  bool aResult = true;
 
   for (Standard_Integer anElemIndex = 0; anElemIndex < myRaytraceGeometry.Size(); ++anElemIndex)
   {
@@ -1659,13 +1773,12 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
       "OpenGl_TriangleSet does not contain transform", Standard_False);
 
     aNodeTransforms[anElemIndex] = aTransform->Inversed();
-
   }
 
   aResult &= mySceneTransformTexture->Init (myGlContext, 4,
     myRaytraceGeometry.Size() * 4, reinterpret_cast<const GLfloat*> (aNodeTransforms));
 
-  delete[] aNodeTransforms;
+  delete [] aNodeTransforms;
 
   /////////////////////////////////////////////////////////////////////////////
   // Write geometry and bottom-level BVH buffers
@@ -1691,11 +1804,16 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
     aTotalBVHNodesNb += aTriangleSet->BVH()->NodeInfoBuffer().size();
   }
 
+  aTotalBVHNodesNb += myRaytraceGeometry.BVH()->NodeInfoBuffer().size();
+
   if (aTotalBVHNodesNb != 0)
   {
-    aResult &= myObjectNodeInfoTexture->Init (myGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast<const GLuint*>  (NULL));
-    aResult &= myObjectMinPointTexture->Init (myGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
-    aResult &= myObjectMaxPointTexture->Init (myGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
+    aResult &= mySceneNodeInfoTexture->Init (
+      myGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast<const GLuint*>  (NULL));
+    aResult &= mySceneMinPointTexture->Init (
+      myGlContext, 3, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
+    aResult &= mySceneMaxPointTexture->Init (
+      myGlContext, 3, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
   }
 
   if (!aResult)
@@ -1708,13 +1826,18 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
 
   if (aTotalElementsNb != 0)
   {
-    aResult &= myGeometryTriangTexture->Init (myGlContext, 4, GLsizei (aTotalElementsNb), static_cast<const GLuint*> (NULL));
+    aResult &= myGeometryTriangTexture->Init (
+      myGlContext, 4, GLsizei (aTotalElementsNb), static_cast<const GLuint*> (NULL));
   }
 
   if (aTotalVerticesNb != 0)
   {
-    aResult &= myGeometryVertexTexture->Init (myGlContext, 4, GLsizei (aTotalVerticesNb), static_cast<const GLfloat*> (NULL));
-    aResult &= myGeometryNormalTexture->Init (myGlContext, 4, GLsizei (aTotalVerticesNb), static_cast<const GLfloat*> (NULL));
+    aResult &= myGeometryVertexTexture->Init (
+      myGlContext, 3, GLsizei (aTotalVerticesNb), static_cast<const GLfloat*> (NULL));
+    aResult &= myGeometryNormalTexture->Init (
+      myGlContext, 3, GLsizei (aTotalVerticesNb), static_cast<const GLfloat*> (NULL));
+    aResult &= myGeometryTexCrdTexture->Init (
+      myGlContext, 2, GLsizei (aTotalVerticesNb), static_cast<const GLfloat*> (NULL));
   }
 
   if (!aResult)
@@ -1725,6 +1848,18 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
     return Standard_False;
   }
 
+  const NCollection_Handle<BVH_Tree<Standard_ShortReal, 3> >& aBVH = myRaytraceGeometry.BVH();
+  const Standard_Integer aBvhLength = aBVH->Length();
+  if (aBvhLength > 0)
+  {
+    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))
@@ -1735,20 +1870,20 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
     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);
 
-    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()));
-      aResult &= myObjectMinPointTexture->SubData (myGlContext, aBVHOffset, GLsizei (aBVHBuffserSize),
+      aResult &= mySceneMinPointTexture->SubData (myGlContext, aBVHOffset, aBvhBuffersSize,
                                                    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)
       {
@@ -1768,6 +1903,8 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
     {
       aResult &= myGeometryNormalTexture->SubData (myGlContext, aVerticesOffset, GLsizei (aTriangleSet->Normals.size()),
                                                    reinterpret_cast<const GLfloat*> (&aTriangleSet->Normals.front()));
+      aResult &= myGeometryTexCrdTexture->SubData (myGlContext, aVerticesOffset, GLsizei (aTriangleSet->TexCrds.size()),
+                                                   reinterpret_cast<const GLfloat*> (&aTriangleSet->TexCrds.front()));
       aResult &= myGeometryVertexTexture->SubData (myGlContext, aVerticesOffset, GLsizei (aTriangleSet->Vertices.size()),
                                                    reinterpret_cast<const GLfloat*> (&aTriangleSet->Vertices.front()));
     }
@@ -1792,10 +1929,14 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
     }
   }
 
+  /////////////////////////////////////////////////////////////////////////////
+  // Write material buffer
+
   if (myRaytraceGeometry.Materials.size() != 0)
   {
-    const GLfloat* aDataPtr = myRaytraceGeometry.Materials.front().Packed();
-    aResult &= myRaytraceMaterialTexture->Init (myGlContext, 4, GLsizei (myRaytraceGeometry.Materials.size() * 7), aDataPtr);
+    aResult &= myRaytraceMaterialTexture->Init (myGlContext, 4,
+      GLsizei (myRaytraceGeometry.Materials.size() * 11),  myRaytraceGeometry.Materials.front().Packed());
+
     if (!aResult)
     {
 #ifdef RAY_TRACE_PRINT_INFO
@@ -1817,26 +1958,28 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
       myRaytraceGeometry.Objects().ChangeValue (anElemIdx).operator->());
 
     aMemUsed += static_cast<Standard_ShortReal> (
-      aTriangleSet->Vertices.size() * sizeof (BVH_Vec4f));
+      aTriangleSet->Vertices.size() * sizeof (BVH_Vec3f));
     aMemUsed += static_cast<Standard_ShortReal> (
-      aTriangleSet->Normals.size() * sizeof (BVH_Vec4f));
+      aTriangleSet->Normals.size() * sizeof (BVH_Vec3f));
+    aMemUsed += static_cast<Standard_ShortReal> (
+      aTriangleSet->TexCrds.size() * sizeof (BVH_Vec2f));
     aMemUsed += static_cast<Standard_ShortReal> (
       aTriangleSet->Elements.size() * sizeof (BVH_Vec4i));
 
     aMemUsed += static_cast<Standard_ShortReal> (
       aTriangleSet->BVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i));
     aMemUsed += static_cast<Standard_ShortReal> (
-      aTriangleSet->BVH()->MinPointBuffer().size() * sizeof (BVH_Vec4f));
+      aTriangleSet->BVH()->MinPointBuffer().size() * sizeof (BVH_Vec3f));
     aMemUsed += static_cast<Standard_ShortReal> (
-      aTriangleSet->BVH()->MaxPointBuffer().size() * sizeof (BVH_Vec4f));
+      aTriangleSet->BVH()->MaxPointBuffer().size() * sizeof (BVH_Vec3f));
   }
 
   aMemUsed += static_cast<Standard_ShortReal> (
     myRaytraceGeometry.BVH()->NodeInfoBuffer().size() * sizeof (BVH_Vec4i));
   aMemUsed += static_cast<Standard_ShortReal> (
-    myRaytraceGeometry.BVH()->MinPointBuffer().size() * sizeof (BVH_Vec4f));
+    myRaytraceGeometry.BVH()->MinPointBuffer().size() * sizeof (BVH_Vec3f));
   aMemUsed += static_cast<Standard_ShortReal> (
-    myRaytraceGeometry.BVH()->MaxPointBuffer().size() * sizeof (BVH_Vec4f));
+    myRaytraceGeometry.BVH()->MaxPointBuffer().size() * sizeof (BVH_Vec3f));
 
   std::cout << "GPU Memory Used (MB): ~" << aMemUsed / 1048576 << std::endl;
 
@@ -1866,11 +2009,11 @@ Standard_Boolean OpenGl_Workspace::ResizeRaytraceBuffers (const Standard_Integer
 // function : UpdateCamera
 // purpose  : Generates viewing rays for corners of screen quad
 // =======================================================================
-void OpenGl_Workspace::UpdateCamera (const NCollection_Mat4<GLdouble>& theOrientation,
-                                     const NCollection_Mat4<GLdouble>& theViewMapping,
-                                     OpenGl_Vec3                       theOrigins[4],
-                                     OpenGl_Vec3                       theDirects[4],
-                                     NCollection_Mat4<GLdouble>&       theInvModelProj)
+void OpenGl_Workspace::UpdateCamera (const OpenGl_Mat4& theOrientation,
+                                     const OpenGl_Mat4& theViewMapping,
+                                     OpenGl_Vec3        theOrigins[4],
+                                     OpenGl_Vec3        theDirects[4],
+                                     OpenGl_Mat4&       theInvModelProj)
 {
   // compute inverse model-view-projection matrix
   (theViewMapping * theOrientation).Inverted (theInvModelProj);
@@ -1882,10 +2025,10 @@ void OpenGl_Workspace::UpdateCamera (const NCollection_Mat4<GLdouble>& theOrient
   {
     for (Standard_Integer aX = -1; aX <= 1; aX += 2)
     {
-      OpenGl_Vec4d aOrigin (GLdouble(aX),
-                            GLdouble(aY),
-                           -1.0,
-                            1.0);
+      OpenGl_Vec4 aOrigin (GLfloat(aX),
+                           GLfloat(aY),
+                          -1.0f,
+                           1.0f);
 
       aOrigin = theInvModelProj * aOrigin;
 
@@ -1893,10 +2036,10 @@ void OpenGl_Workspace::UpdateCamera (const NCollection_Mat4<GLdouble>& theOrient
       aOrigin.y() = aOrigin.y() / aOrigin.w();
       aOrigin.z() = aOrigin.z() / aOrigin.w();
 
-      OpenGl_Vec4d aDirect (GLdouble(aX),
-                            GLdouble(aY),
-                            1.0,
-                            1.0);
+      OpenGl_Vec4 aDirect (GLfloat(aX),
+                           GLfloat(aY),
+                           1.0f,
+                           1.0f);
 
       aDirect = theInvModelProj * aDirect;
 
@@ -1921,6 +2064,88 @@ void OpenGl_Workspace::UpdateCamera (const NCollection_Mat4<GLdouble>& theOrient
   }
 }
 
+// =======================================================================
+// function : SetUniformState
+// purpose  : Sets uniform state for the given ray-tracing shader program
+// =======================================================================
+Standard_Boolean OpenGl_Workspace::SetUniformState (const Graphic3d_CView&        theCView,
+                                                    const Standard_Integer        theSizeX,
+                                                    const Standard_Integer        theSizeY,
+                                                    const OpenGl_Vec3*            theOrigins,
+                                                    const OpenGl_Vec3*            theDirects,
+                                                    const OpenGl_Mat4&            theUnviewMat,
+                                                    const Standard_Integer        theProgramIndex,
+                                                    Handle(OpenGl_ShaderProgram)& theRaytraceProgram)
+{
+  if (theRaytraceProgram.IsNull())
+  {
+    return Standard_False;
+  }
+
+  Standard_Integer aLightSourceBufferSize =
+    static_cast<Standard_Integer> (myRaytraceGeometry.Sources.size());
+
+  Standard_Boolean aResult = Standard_True;
+
+  // Set camera state
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uOriginLB], theOrigins[0]);
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uOriginRB], theOrigins[1]);
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uOriginLT], theOrigins[2]);
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uOriginRT], theOrigins[3]);
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uDirectLB], theDirects[0]);
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uDirectRB], theDirects[1]);
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uDirectLT], theDirects[2]);
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uDirectRT], theDirects[3]);
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uUnviewMat], theUnviewMat);
+
+  // Set window size
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uWinSizeX], theSizeX);
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uWinSizeY], theSizeY);
+
+  // Set scene parameters
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uSceneRad], myRaytraceSceneRadius);
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uSceneEps], myRaytraceSceneEpsilon);
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uLightCount], aLightSourceBufferSize);
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uLightAmbnt], myRaytraceGeometry.Ambient);
+
+  // Set rendering options
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uShadEnabled], theCView.RenderParams.IsShadowEnabled ? 1 : 0);
+  aResult &= theRaytraceProgram->SetUniform (myGlContext,
+    myUniformLocations[theProgramIndex][OpenGl_RT_uReflEnabled], theCView.RenderParams.IsReflectionEnabled ? 1 : 0);
+
+  // Set array of 64-bit texture handles
+  if (myGlContext->arbTexBindless != NULL && myRaytraceGeometry.HasTextures())
+  {
+    aResult &= theRaytraceProgram->SetUniform (myGlContext, "uTextureSamplers",
+      static_cast<GLsizei> (myRaytraceGeometry.TextureHandles().size()), &myRaytraceGeometry.TextureHandles()[0]);
+  }
+
+  if (!aResult)
+  {
+#ifdef RAY_TRACE_PRINT_INFO
+    std::cout << "Info: Not all uniforms were detected (for program " << theProgramIndex << ")" << std::endl;
+#endif
+  }
+
+  return aResult;
+}
+
 // =======================================================================
 // function : RunRaytraceShaders
 // purpose  : Runs ray-tracing shader programs
@@ -1930,17 +2155,15 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
                                                        const Standard_Integer theSizeY,
                                                        const OpenGl_Vec3      theOrigins[4],
                                                        const OpenGl_Vec3      theDirects[4],
-                                                       const OpenGl_Matrix&   theInvModelProj,
+                                                       const OpenGl_Mat4&     theUnviewMat,
                                                        OpenGl_FrameBuffer*    theFrameBuffer)
 {
   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);
   myGeometryTriangTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTriangTexture);
   mySceneTransformTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture);
   myRaytraceMaterialTexture->BindTexture (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture);
@@ -1956,71 +2179,40 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
     glDisable (GL_BLEND);
   }
 
-  myRaytraceProgram->Bind (myGlContext);
-
-  Standard_Integer aLightSourceBufferSize =
-    static_cast<Standard_Integer> (myRaytraceGeometry.Sources.size());
+  myGlContext->BindProgram (myRaytraceProgram);
 
-  myRaytraceProgram->SetUniform (myGlContext,
-    myUniformLocations[0][OpenGl_RT_uOriginLB], theOrigins[0]);
-  myRaytraceProgram->SetUniform (myGlContext,
-    myUniformLocations[0][OpenGl_RT_uOriginRB], theOrigins[1]);
-  myRaytraceProgram->SetUniform (myGlContext,
-    myUniformLocations[0][OpenGl_RT_uOriginLT], theOrigins[2]);
-  myRaytraceProgram->SetUniform (myGlContext,
-    myUniformLocations[0][OpenGl_RT_uOriginRT], theOrigins[3]);
-  myRaytraceProgram->SetUniform (myGlContext,
-    myUniformLocations[0][OpenGl_RT_uDirectLB], theDirects[0]);
-  myRaytraceProgram->SetUniform (myGlContext,
-    myUniformLocations[0][OpenGl_RT_uDirectRB], theDirects[1]);
-  myRaytraceProgram->SetUniform (myGlContext,
-    myUniformLocations[0][OpenGl_RT_uDirectLT], theDirects[2]);
-  myRaytraceProgram->SetUniform (myGlContext,
-    myUniformLocations[0][OpenGl_RT_uDirectRT], theDirects[3]);
-  myRaytraceProgram->SetUniform (myGlContext,
-    myUniformLocations[0][OpenGl_RT_uInvModelProj], theInvModelProj);
-  myRaytraceProgram->SetUniform (myGlContext,
-    myUniformLocations[0][OpenGl_RT_uSceneRad], myRaytraceSceneRadius);
-  myRaytraceProgram->SetUniform (myGlContext,
-    myUniformLocations[0][OpenGl_RT_uSceneEps], myRaytraceSceneEpsilon);
-  myRaytraceProgram->SetUniform (myGlContext,
-    myUniformLocations[0][OpenGl_RT_uLightCount], aLightSourceBufferSize);
-  myRaytraceProgram->SetUniform (myGlContext,
-    myUniformLocations[0][OpenGl_RT_uLightAmbnt], myRaytraceGeometry.Ambient);
-  myRaytraceProgram->SetUniform (myGlContext,
-    myUniformLocations[0][OpenGl_RT_uShadEnabled], theCView.RenderParams.IsShadowEnabled ? 1 : 0);
-  myRaytraceProgram->SetUniform (myGlContext,
-    myUniformLocations[0][OpenGl_RT_uReflEnabled], theCView.RenderParams.IsReflectionEnabled ? 1 : 0);
-
-  myGlContext->core20fwd->glEnableVertexAttribArray (
-    myUniformLocations[0][OpenGl_RT_aPosition]);
-  {
-    myGlContext->core20fwd->glVertexAttribPointer (
-      myUniformLocations[0][OpenGl_RT_aPosition], 3, GL_FLOAT, GL_FALSE, 0, NULL);
+  SetUniformState (theCView,
+                   theSizeX,
+                   theSizeY,
+                   theOrigins,
+                   theDirects,
+                   theUnviewMat,
+                   0, // ID of RT program
+                   myRaytraceProgram);
 
+  myGlContext->core20fwd->glEnableVertexAttribArray (Graphic3d_TOA_POS);
+  {
+    myGlContext->core20fwd->glVertexAttribPointer (Graphic3d_TOA_POS, 3, GL_FLOAT, GL_FALSE, 0, NULL);
     myGlContext->core15fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
   }
-  myGlContext->core20fwd->glDisableVertexAttribArray (
-    myUniformLocations[0][OpenGl_RT_aPosition]);
-  
+  myGlContext->core20fwd->glDisableVertexAttribArray (Graphic3d_TOA_POS);
+
   if (!theCView.RenderParams.IsAntialiasingEnabled)
   {
-    myRaytraceProgram->Unbind (myGlContext);
+    myGlContext->BindProgram (NULL);
 
     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);
     myGeometryTriangTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTriangTexture);
+    mySceneTransformTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture);
     myRaytraceMaterialTexture->UnbindTexture   (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture);
     myRaytraceLightSrcTexture->UnbindTexture   (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceLightSrcTexture);
-    mySceneTransformTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture);
 
     myGlContext->core15fwd->glActiveTexture (GL_TEXTURE0);
 
@@ -2029,74 +2221,53 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
 
   myRaytraceFBO1->ColorTexture()->Bind (myGlContext, GL_TEXTURE0 + OpenGl_RT_FSAAInputTexture);
 
-  myPostFSAAProgram->Bind (myGlContext);
-
-  myPostFSAAProgram->SetUniform (myGlContext,
-    myUniformLocations[1][OpenGl_RT_uOriginLB], theOrigins[0]);
-  myPostFSAAProgram->SetUniform (myGlContext,
-    myUniformLocations[1][OpenGl_RT_uOriginRB], theOrigins[1]);
-  myPostFSAAProgram->SetUniform (myGlContext,
-    myUniformLocations[1][OpenGl_RT_uOriginLT], theOrigins[2]);
-  myPostFSAAProgram->SetUniform (myGlContext,
-    myUniformLocations[1][OpenGl_RT_uOriginRT], theOrigins[3]);
-  myPostFSAAProgram->SetUniform (myGlContext,
-    myUniformLocations[1][OpenGl_RT_uDirectLB], theDirects[0]);
-  myPostFSAAProgram->SetUniform (myGlContext,
-    myUniformLocations[1][OpenGl_RT_uDirectRB], theDirects[1]);
-  myPostFSAAProgram->SetUniform (myGlContext,
-    myUniformLocations[1][OpenGl_RT_uDirectLT], theDirects[2]);
-  myPostFSAAProgram->SetUniform (myGlContext,
-    myUniformLocations[1][OpenGl_RT_uDirectRT], theDirects[3]);
-  myRaytraceProgram->SetUniform (myGlContext,
-    myUniformLocations[1][OpenGl_RT_uInvModelProj], theInvModelProj);
-  myPostFSAAProgram->SetUniform (myGlContext,
-    myUniformLocations[1][OpenGl_RT_uSceneRad], myRaytraceSceneRadius);
-  myPostFSAAProgram->SetUniform (myGlContext,
-    myUniformLocations[1][OpenGl_RT_uSceneEps], myRaytraceSceneEpsilon);
-  myPostFSAAProgram->SetUniform (myGlContext,
-    myUniformLocations[1][OpenGl_RT_uLightCount], aLightSourceBufferSize);
-  myPostFSAAProgram->SetUniform (myGlContext,
-    myUniformLocations[1][OpenGl_RT_uLightAmbnt], myRaytraceGeometry.Ambient);
-  myPostFSAAProgram->SetUniform (myGlContext,
-    myUniformLocations[1][OpenGl_RT_uShadEnabled], theCView.RenderParams.IsShadowEnabled ? 1 : 0);
-  myPostFSAAProgram->SetUniform (myGlContext,
-    myUniformLocations[1][OpenGl_RT_uReflEnabled], theCView.RenderParams.IsReflectionEnabled ? 1 : 0);
-
-  const Standard_ShortReal aMaxOffset = 0.559017f;
-  const Standard_ShortReal aMinOffset = 0.186339f;
-
-  myGlContext->core20fwd->glEnableVertexAttribArray (
-    myUniformLocations[1][OpenGl_RT_aPosition]);
-  
-  myGlContext->core20fwd->glVertexAttribPointer (
-    myUniformLocations[1][OpenGl_RT_aPosition], 3, GL_FLOAT, GL_FALSE, 0, NULL);
+  myGlContext->BindProgram (myPostFSAAProgram);
+
+  SetUniformState (theCView,
+                   theSizeX,
+                   theSizeY,
+                   theOrigins,
+                   theDirects,
+                   theUnviewMat,
+                   1, // ID of FSAA program
+                   myPostFSAAProgram);
+
+  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
     {
@@ -2109,7 +2280,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
@@ -2119,25 +2290,22 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
     }
   }
 
-  myGlContext->core20fwd->glDisableVertexAttribArray (
-    myUniformLocations[1][OpenGl_RT_aPosition]);
+  myGlContext->core20fwd->glDisableVertexAttribArray (Graphic3d_TOA_POS);
 
-  myPostFSAAProgram->Unbind (myGlContext);
+  myGlContext->BindProgram (NULL);
   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);
   myGeometryTriangTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_GeometryTriangTexture);
+  mySceneTransformTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture);
   myRaytraceMaterialTexture->UnbindTexture   (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceMaterialTexture);
   myRaytraceLightSrcTexture->UnbindTexture   (myGlContext, GL_TEXTURE0 + OpenGl_RT_RaytraceLightSrcTexture);
-  mySceneTransformTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_SceneTransformTexture);
 
   myGlContext->core15fwd->glActiveTexture (GL_TEXTURE0);
 
@@ -2151,14 +2319,10 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
 Standard_Boolean OpenGl_Workspace::Raytrace (const Graphic3d_CView& theCView,
                                              const Standard_Integer theSizeX,
                                              const Standard_Integer theSizeY,
-                                             const Standard_Boolean theToSwap,
                                              const Aspect_CLayer2d& theCOverLayer,
                                              const Aspect_CLayer2d& theCUnderLayer,
                                              OpenGl_FrameBuffer*    theFrameBuffer)
 {
-  if (!InitRaytraceResources (theCView))
-    return Standard_False;
-
   if (!ResizeRaytraceBuffers (theSizeX, theSizeY))
     return Standard_False;
 
@@ -2166,24 +2330,13 @@ Standard_Boolean OpenGl_Workspace::Raytrace (const Graphic3d_CView& theCView,
     return Standard_False;
 
   // Get model-view and projection matrices
-  TColStd_Array2OfReal theOrientation (0, 3, 0, 3);
-  TColStd_Array2OfReal theViewMapping (0, 3, 0, 3);
+  OpenGl_Mat4 aOrientationMatrix;
+  OpenGl_Mat4 aViewMappingMatrix;
 
-  myView->GetMatrices (theOrientation, theViewMapping);
+  myView->GetMatrices (aOrientationMatrix,
+                       aViewMappingMatrix);
 
-  NCollection_Mat4<GLdouble> aOrientationMatrix;
-  NCollection_Mat4<GLdouble> aViewMappingMatrix;
-
-  for (Standard_Integer j = 0; j < 4; ++j)
-  {
-    for (Standard_Integer i = 0; i < 4; ++i)
-    {
-      aOrientationMatrix [4 * j + i] = theOrientation (i, j);
-      aViewMappingMatrix [4 * j + i] = theViewMapping (i, j);
-    }
-  }
-  
-  NCollection_Mat4<GLdouble> aInvOrientationMatrix;
+  OpenGl_Mat4 aInvOrientationMatrix;
   aOrientationMatrix.Inverted (aInvOrientationMatrix);
 
   if (!UpdateRaytraceLightSources (aInvOrientationMatrix))
@@ -2191,22 +2344,13 @@ Standard_Boolean OpenGl_Workspace::Raytrace (const Graphic3d_CView& theCView,
 
   OpenGl_Vec3 aOrigins[4];
   OpenGl_Vec3 aDirects[4];
-  NCollection_Mat4<GLdouble> anInvModelProj;
+  OpenGl_Mat4 anUnviewMat;
 
   UpdateCamera (aOrientationMatrix,
                 aViewMappingMatrix,
                 aOrigins,
                 aDirects,
-                anInvModelProj);
-
-  OpenGl_Matrix anInvModelProjMatrix;
-  for (Standard_Integer j = 0; j < 4; ++j)
-  {
-    for (Standard_Integer i = 0; i < 4; ++i)
-    {
-      anInvModelProjMatrix.mat[j][i] = static_cast<GLfloat>(anInvModelProj.GetValue(i,j));
-    }
-  }
+                anUnviewMat);
 
   Standard_Boolean wasBlendingEnabled = glIsEnabled (GL_BLEND);
   Standard_Boolean wasDepthTestEnabled = glIsEnabled (GL_DEPTH_TEST);
@@ -2232,34 +2376,51 @@ Standard_Boolean OpenGl_Workspace::Raytrace (const Graphic3d_CView& theCView,
 
   glClear (GL_COLOR_BUFFER_BIT);
 
-  myView->DrawBackground (*this);
+  myView->DrawBackground (this);
 
-  myView->RedrawLayer2d (myPrintContext, theCView, theCUnderLayer);
+  myView->RedrawLayer2d (myPrintContext, this, theCView, theCUnderLayer);
 
-  // Generate ray-traced image
-  glMatrixMode (GL_PROJECTION);
-  glPushMatrix();
-  glLoadIdentity();
+  myGlContext->WorldViewState.Push();
+  myGlContext->ProjectionState.Push();
+
+  myGlContext->WorldViewState.SetIdentity();
+  myGlContext->ProjectionState.SetIdentity();
 
-  glMatrixMode (GL_MODELVIEW);
-  glPushMatrix();
-  glLoadIdentity();
+  myGlContext->ApplyProjectionMatrix();
+  myGlContext->ApplyWorldViewMatrix();
 
   glEnable (GL_BLEND);
   glBlendFunc (GL_ONE, GL_SRC_ALPHA);
 
+  // Generate ray-traced image
   if (myIsRaytraceDataValid)
   {
     myRaytraceScreenQuad.Bind (myGlContext);
 
+    if (!myRaytraceGeometry.AcquireTextures (myGlContext))
+    {
+      const TCollection_ExtendedString aMessage = "Error: Failed to acquire OpenGL image textures";
+
+      myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+        GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_MEDIUM_ARB, aMessage);
+    }
+
     RunRaytraceShaders (theCView,
                         theSizeX,
                         theSizeY,
                         aOrigins,
                         aDirects,
-                        anInvModelProjMatrix,
+                        anUnviewMat,
                         theFrameBuffer);
 
+    if (!myRaytraceGeometry.ReleaseTextures (myGlContext))
+    {
+      const TCollection_ExtendedString aMessage = "Error: Failed to release OpenGL image textures";
+
+      myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+        GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_MEDIUM_ARB, aMessage);
+    }
+
     myRaytraceScreenQuad.Unbind (myGlContext);
   }
 
@@ -2269,10 +2430,10 @@ Standard_Boolean OpenGl_Workspace::Raytrace (const Graphic3d_CView& theCView,
   if (wasDepthTestEnabled)
     glEnable (GL_DEPTH_TEST);
 
-  glMatrixMode (GL_PROJECTION);
-  glPopMatrix();
-  glMatrixMode (GL_MODELVIEW);
-  glPopMatrix();
+  myGlContext->WorldViewState.Pop();
+  myGlContext->ProjectionState.Pop();
+
+  myGlContext->ApplyProjectionMatrix();
 
   // Redraw trihedron
   myView->RedrawTrihedron (this);
@@ -2280,20 +2441,8 @@ Standard_Boolean OpenGl_Workspace::Raytrace (const Graphic3d_CView& theCView,
   // Redraw overlay
   const int aMode = 0;
   DisplayCallback (theCView, (aMode | OCC_PRE_OVERLAY));
-  myView->RedrawLayer2d (myPrintContext, theCView, theCOverLayer);
+  myView->RedrawLayer2d (myPrintContext, this, theCView, theCOverLayer);
   DisplayCallback (theCView, aMode);
-
-  // Swap the buffers
-  if (theToSwap)
-  {
-    GetGlContext()->SwapBuffers();
-    myBackBufferRestored = Standard_False;
-  }
-  else
-  {
-    glFlush();
-  }
-
   return Standard_True;
 }