025306: Visualization, TKOpenGl - support texturing within RayTracing
authordbp <dbp@opencascade.com>
Thu, 23 Oct 2014 10:09:23 +0000 (14:09 +0400)
committerbugmaster <bugmaster@opencascade.com>
Thu, 23 Oct 2014 12:20:36 +0000 (16:20 +0400)
Fix bug with overlay OpenGL text.

21 files changed:
src/OpenGl/FILES
src/OpenGl/Handle_OpenGl_Sampler.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_ArbTexBindless.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_GlFunctions.hxx
src/OpenGl/OpenGl_Sampler.cxx [new file with mode: 0644]
src/OpenGl/OpenGl_Sampler.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_SceneGeometry.cxx
src/OpenGl/OpenGl_SceneGeometry.hxx
src/OpenGl/OpenGl_ShaderProgram.cxx
src/OpenGl/OpenGl_ShaderProgram.hxx
src/OpenGl/OpenGl_Text.cxx
src/OpenGl/OpenGl_TextureBufferArb.cxx
src/OpenGl/OpenGl_View.cxx
src/OpenGl/OpenGl_View.hxx
src/OpenGl/OpenGl_Workspace.cxx
src/OpenGl/OpenGl_Workspace.hxx
src/OpenGl/OpenGl_Workspace_Raytrace.cxx
src/Shaders/RaytraceBase.fs
tests/v3d/raytrace/textures [new file with mode: 0644]

index c68daee..2afea24 100755 (executable)
@@ -153,3 +153,7 @@ OpenGl_BVHTreeSelector.hxx
 OpenGl_BVHTreeSelector.cxx
 OpenGl_BVHClipPrimitiveSet.cxx
 OpenGl_BVHClipPrimitiveSet.hxx
+OpenGl_ArbTexBindless.hxx
+Handle_OpenGl_Sampler.hxx
+OpenGl_Sampler.hxx
+OpenGl_Sampler.cxx
diff --git a/src/OpenGl/Handle_OpenGl_Sampler.hxx b/src/OpenGl/Handle_OpenGl_Sampler.hxx
new file mode 100644 (file)
index 0000000..623ae56
--- /dev/null
@@ -0,0 +1,24 @@
+// Created on: 2014-10-17
+// Created by: Denis BOGOLEPOV
+// Copyright (c) 2013-2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _Handle_OpenGl_Sampler_HeaderFile
+#define _Handle_OpenGl_Sampler_HeaderFile
+
+#include <OpenGl_Resource.hxx>
+
+class OpenGl_Sampler;
+DEFINE_STANDARD_HANDLE(OpenGl_Sampler, OpenGl_Resource)
+
+#endif
diff --git a/src/OpenGl/OpenGl_ArbTexBindless.hxx b/src/OpenGl/OpenGl_ArbTexBindless.hxx
new file mode 100644 (file)
index 0000000..482acaf
--- /dev/null
@@ -0,0 +1,47 @@
+// Created on: 2014-10-07
+// Created by: Denis BOGOLEPOV
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef _OpenGl_ArbTexBindless_H__
+#define _OpenGl_ArbTexBindless_H__
+
+#include <OpenGl_GlFunctions.hxx>
+
+//! Provides bindless textures.
+//! This extension allows OpenGL applications to access texture objects in
+//! shaders without first binding each texture to one of a limited number of
+//! texture image units.
+struct OpenGl_ArbTexBindless : protected OpenGl_GlFunctions
+{
+#if !defined(GL_ES_VERSION_2_0)
+  using OpenGl_GlFunctions::glGetTextureHandleARB;
+  using OpenGl_GlFunctions::glGetTextureSamplerHandleARB;
+  using OpenGl_GlFunctions::glMakeTextureHandleResidentARB;
+  using OpenGl_GlFunctions::glMakeTextureHandleNonResidentARB;
+  using OpenGl_GlFunctions::glGetImageHandleARB;
+  using OpenGl_GlFunctions::glMakeImageHandleResidentARB;
+  using OpenGl_GlFunctions::glMakeImageHandleNonResidentARB;
+  using OpenGl_GlFunctions::glUniformHandleui64ARB;
+  using OpenGl_GlFunctions::glUniformHandleui64vARB;
+  using OpenGl_GlFunctions::glProgramUniformHandleui64ARB;
+  using OpenGl_GlFunctions::glProgramUniformHandleui64vARB;
+  using OpenGl_GlFunctions::glIsTextureHandleResidentARB;
+  using OpenGl_GlFunctions::glIsImageHandleResidentARB;
+  using OpenGl_GlFunctions::glVertexAttribL1ui64ARB;
+  using OpenGl_GlFunctions::glVertexAttribL1ui64vARB;
+  using OpenGl_GlFunctions::glGetVertexAttribLui64vARB;
+#endif
+};
+
+#endif // _OpenGl_ArbTexBindless_H__
index 02e402a..c9602a7 100644 (file)
@@ -24,7 +24,9 @@
 #include <OpenGl_ArbDbg.hxx>
 #include <OpenGl_ArbFBO.hxx>
 #include <OpenGl_ExtGS.hxx>
+#include <OpenGl_ArbTexBindless.hxx>
 #include <OpenGl_GlCore20.hxx>
+#include <OpenGl_Sampler.hxx>
 #include <OpenGl_ShaderManager.hxx>
 
 #include <Message_Messenger.hxx>
@@ -79,6 +81,8 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   core20fwd  (NULL),
   core32     (NULL),
   core32back (NULL),
+  core33     (NULL),
+  core33back (NULL),
   core41     (NULL),
   core41back (NULL),
   core42     (NULL),
@@ -95,8 +99,11 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   hasHighp   (Standard_True),
   hasTexRGBA8(Standard_True),
 #endif
-  arbNPTW(Standard_False),
+  arbNPTW  (Standard_False),
+  arbTexRG (Standard_False),
+  arbTexBindless (NULL),
   arbTBO (NULL),
+  arbTboRGB32 (Standard_False),
   arbIns (NULL),
   arbDbg (NULL),
   arbFBO (NULL),
@@ -170,6 +177,12 @@ OpenGl_Context::~OpenGl_Context()
   mySharedResources.Nullify();
   myDelayed.Nullify();
 
+  // release sampler object
+  if (!myTexSampler.IsNull())
+  {
+    myTexSampler->Release (this);
+  }
+
 #if !defined(GL_ES_VERSION_2_0)
   if (arbDbg != NULL
    && caps->contextDebug
@@ -844,6 +857,8 @@ void OpenGl_Context::init()
   core20fwd  = NULL;
   core32     = NULL;
   core32back = NULL;
+  core33     = NULL;
+  core33back = NULL;
   core41     = NULL;
   core41back = NULL;
   core42     = NULL;
@@ -853,6 +868,7 @@ void OpenGl_Context::init()
   core44     = NULL;
   core44back = NULL;
   arbTBO     = NULL;
+  arbTboRGB32 = Standard_False;
   arbIns     = NULL;
   arbDbg     = NULL;
   arbFBO     = NULL;
@@ -1723,6 +1739,7 @@ void OpenGl_Context::init()
   {
     arbTBO = (OpenGl_ArbTBO* )(&(*myFuncs));
   }
+  arbTboRGB32 = CheckExtension ("GL_ARB_texture_buffer_object_rgb32");
 
   // initialize hardware instancing extension (ARB)
   if (!has31
@@ -1747,6 +1764,28 @@ void OpenGl_Context::init()
     extGS = (OpenGl_ExtGS* )(&(*myFuncs));
   }
 
+  // initialize bindless texture extension (ARB)
+  if (CheckExtension ("GL_ARB_bindless_texture")
+   && FindProcShort (glGetTextureHandleARB)
+   && FindProcShort (glGetTextureSamplerHandleARB)
+   && FindProcShort (glMakeTextureHandleResidentARB)
+   && FindProcShort (glMakeTextureHandleNonResidentARB)
+   && FindProcShort (glGetImageHandleARB)
+   && FindProcShort (glMakeImageHandleResidentARB)
+   && FindProcShort (glMakeImageHandleNonResidentARB)
+   && FindProcShort (glUniformHandleui64ARB)
+   && FindProcShort (glUniformHandleui64vARB)
+   && FindProcShort (glProgramUniformHandleui64ARB)
+   && FindProcShort (glProgramUniformHandleui64vARB)
+   && FindProcShort (glIsTextureHandleResidentARB)
+   && FindProcShort (glIsImageHandleResidentARB)
+   && FindProcShort (glVertexAttribL1ui64ARB)
+   && FindProcShort (glVertexAttribL1ui64vARB)
+   && FindProcShort (glGetVertexAttribLui64vARB))
+  {
+    arbTexBindless = (OpenGl_ArbTexBindless* )(&(*myFuncs));
+  }
+
   if (!has12)
   {
     myGlVerMajor = 1;
@@ -1822,6 +1861,12 @@ void OpenGl_Context::init()
     myGlVerMinor = 2;
     return;
   }
+  core33     = (OpenGl_GlCore33*     )(&(*myFuncs));
+  core33back = (OpenGl_GlCore33Back* )(&(*myFuncs));
+
+  // initialize sampler object
+  myTexSampler = new OpenGl_Sampler();
+  myTexSampler->Init (*this);
 
   if (!has40)
   {
@@ -1829,6 +1874,7 @@ void OpenGl_Context::init()
     myGlVerMinor = 3;
     return;
   }
+  arbTboRGB32 = Standard_True; // in core since OpenGL 4.0
 
   if (!has41)
   {
index c41298a..c5140b7 100644 (file)
@@ -21,6 +21,7 @@
 #include <Aspect_Display.hxx>
 #include <Aspect_RenderingContext.hxx>
 #include <Handle_OpenGl_Context.hxx>
+#include <Handle_OpenGl_Sampler.hxx>
 #include <Handle_OpenGl_ShaderManager.hxx>
 #include <Handle_OpenGl_ShaderProgram.hxx>
 #include <NCollection_DataMap.hxx>
@@ -44,6 +45,7 @@ struct OpenGl_ArbIns;
 struct OpenGl_ArbDbg;
 struct OpenGl_ArbFBO;
 struct OpenGl_ExtGS;
+struct OpenGl_ArbTexBindless;
 
 template<typename theBaseClass_t> struct OpenGl_TmplCore12;
 typedef OpenGl_TmplCore12<OpenGl_GlCore11>     OpenGl_GlCore12;
@@ -441,6 +443,12 @@ public: //! @name methods to alter or retrieve current state
     return myActiveProgram;
   }
 
+  //! @return OpenGL sampler object used to override default texture parameters
+  const Handle(OpenGl_Sampler)& TextureSampler()
+  {
+    return myTexSampler;
+  }
+
   //! Bind specified program to current context,
   //! or unbind previous one when NULL specified.
   //! @return true if some program is bound to context
@@ -473,6 +481,8 @@ public: //! @name core profiles
   OpenGl_GlCore20Fwd*  core20fwd;  //!< OpenGL 2.0 without deprecated entry points
   OpenGl_GlCore32*     core32;     //!< OpenGL 3.2 core profile
   OpenGl_GlCore32Back* core32back; //!< OpenGL 3.2 backward compatibility profile
+  OpenGl_GlCore33*     core33;     //!< OpenGL 3.3 core profile
+  OpenGl_GlCore33Back* core33back; //!< OpenGL 3.3 backward compatibility profile
   OpenGl_GlCore41*     core41;     //!< OpenGL 4.1 core profile
   OpenGl_GlCore41Back* core41back; //!< OpenGL 4.1 backward compatibility profile
   OpenGl_GlCore42*     core42;     //!< OpenGL 4.2 core profile
@@ -486,20 +496,22 @@ public: //! @name core profiles
 
 public: //! @name extensions
 
-  Standard_Boolean hasHighp;    //!< highp in GLSL ES fragment shader is supported
-  Standard_Boolean hasTexRGBA8; //!< always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_rgb8_rgba8
-  Standard_Boolean arbNPTW;     //!< GL_ARB_texture_non_power_of_two
-  Standard_Boolean arbTexRG;    //!< GL_ARB_texture_rg
-  OpenGl_ArbTBO*   arbTBO;      //!< GL_ARB_texture_buffer_object
-  OpenGl_ArbIns*   arbIns;      //!< GL_ARB_draw_instanced
-  OpenGl_ArbDbg*   arbDbg;      //!< GL_ARB_debug_output
-  OpenGl_ArbFBO*   arbFBO;      //!< GL_ARB_framebuffer_object
-  OpenGl_ExtGS*    extGS;       //!< GL_EXT_geometry_shader4
-  Standard_Boolean extBgra;     //!< GL_EXT_bgra or GL_EXT_texture_format_BGRA8888 on OpenGL ES
-  Standard_Boolean extAnis;     //!< GL_EXT_texture_filter_anisotropic
-  Standard_Boolean extPDS;      //!< GL_EXT_packed_depth_stencil
-  Standard_Boolean atiMem;      //!< GL_ATI_meminfo
-  Standard_Boolean nvxMem;      //!< GL_NVX_gpu_memory_info
+  Standard_Boolean       hasHighp;       //!< highp in GLSL ES fragment shader is supported
+  Standard_Boolean       hasTexRGBA8;    //!< always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_rgb8_rgba8
+  Standard_Boolean       arbNPTW;        //!< GL_ARB_texture_non_power_of_two
+  Standard_Boolean       arbTexRG;       //!< GL_ARB_texture_rg
+  OpenGl_ArbTexBindless* arbTexBindless; //!< GL_ARB_bindless_texture
+  OpenGl_ArbTBO*         arbTBO;         //!< GL_ARB_texture_buffer_object
+  Standard_Boolean       arbTboRGB32;    //!< GL_ARB_texture_buffer_object_rgb32 (3-component TBO), in core since 4.0
+  OpenGl_ArbIns*         arbIns;         //!< GL_ARB_draw_instanced
+  OpenGl_ArbDbg*         arbDbg;         //!< GL_ARB_debug_output
+  OpenGl_ArbFBO*         arbFBO;         //!< GL_ARB_framebuffer_object
+  OpenGl_ExtGS*          extGS;          //!< GL_EXT_geometry_shader4
+  Standard_Boolean       extBgra;        //!< GL_EXT_bgra or GL_EXT_texture_format_BGRA8888 on OpenGL ES
+  Standard_Boolean       extAnis;        //!< GL_EXT_texture_filter_anisotropic
+  Standard_Boolean       extPDS;         //!< GL_EXT_packed_depth_stencil
+  Standard_Boolean       atiMem;         //!< GL_ATI_meminfo
+  Standard_Boolean       nvxMem;         //!< GL_NVX_gpu_memory_info
 
 private: // system-dependent fields
 
@@ -553,6 +565,7 @@ private: // context info
 private: //! @name fields tracking current state
 
   Handle(OpenGl_ShaderProgram) myActiveProgram; //!< currently active GLSL program
+  Handle(OpenGl_Sampler)       myTexSampler;    //!< currently active sampler object
   Standard_Integer             myRenderMode;    //!< value for active rendering mode
   Standard_Integer             myDrawBuffer;    //!< current draw buffer
 
index 080c3e0..60e9866 100644 (file)
@@ -46,6 +46,7 @@
 
   typedef double GLdouble;
   typedef double GLclampd;
+  typedef uint64_t GLuint64;
   #define GL_NONE 0
 
   // OpenGL ES 3.0+ or GL_OES_element_index_uint extension
@@ -1384,6 +1385,25 @@ public: //! @name GL_EXT_geometry_shader4
 
   PFNGLPROGRAMPARAMETERIEXTPROC glProgramParameteriEXT;
 
+public: //! @name GL_ARB_bindless_texture
+
+  PFNGLGETTEXTUREHANDLEARBPROC             glGetTextureHandleARB;
+  PFNGLGETTEXTURESAMPLERHANDLEARBPROC      glGetTextureSamplerHandleARB;
+  PFNGLMAKETEXTUREHANDLERESIDENTARBPROC    glMakeTextureHandleResidentARB;
+  PFNGLMAKETEXTUREHANDLENONRESIDENTARBPROC glMakeTextureHandleNonResidentARB;
+  PFNGLGETIMAGEHANDLEARBPROC               glGetImageHandleARB;
+  PFNGLMAKEIMAGEHANDLERESIDENTARBPROC      glMakeImageHandleResidentARB;
+  PFNGLMAKEIMAGEHANDLENONRESIDENTARBPROC   glMakeImageHandleNonResidentARB;
+  PFNGLUNIFORMHANDLEUI64ARBPROC            glUniformHandleui64ARB;
+  PFNGLUNIFORMHANDLEUI64VARBPROC           glUniformHandleui64vARB;
+  PFNGLPROGRAMUNIFORMHANDLEUI64ARBPROC     glProgramUniformHandleui64ARB;
+  PFNGLPROGRAMUNIFORMHANDLEUI64VARBPROC    glProgramUniformHandleui64vARB;
+  PFNGLISTEXTUREHANDLERESIDENTARBPROC      glIsTextureHandleResidentARB;
+  PFNGLISIMAGEHANDLERESIDENTARBPROC        glIsImageHandleResidentARB;
+  PFNGLVERTEXATTRIBL1UI64ARBPROC           glVertexAttribL1ui64ARB;
+  PFNGLVERTEXATTRIBL1UI64VARBPROC          glVertexAttribL1ui64vARB;
+  PFNGLGETVERTEXATTRIBLUI64VARBPROC        glGetVertexAttribLui64vARB;
+
 #if defined(_WIN32)
 public: //! @name wgl extensions
 
diff --git a/src/OpenGl/OpenGl_Sampler.cxx b/src/OpenGl/OpenGl_Sampler.cxx
new file mode 100644 (file)
index 0000000..0196a39
--- /dev/null
@@ -0,0 +1,133 @@
+// Created on: 2014-10-08
+// Created by: Denis BOGOLEPOV
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <OpenGl_Sampler.hxx>
+#include <OpenGl_GlCore33.hxx>
+#include <Standard_Assert.hxx>
+
+IMPLEMENT_STANDARD_HANDLE (OpenGl_Sampler, OpenGl_Resource)
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_Sampler, OpenGl_Resource)
+
+// =======================================================================
+// function : OpenGl_Sampler
+// purpose  :
+// =======================================================================
+OpenGl_Sampler::OpenGl_Sampler()
+: mySamplerID (NO_SAMPLER)
+{
+  //
+}
+
+// =======================================================================
+// function : ~OpenGl_Sampler
+// purpose  :
+// =======================================================================
+OpenGl_Sampler::~OpenGl_Sampler()
+{
+  Release (NULL);
+}
+
+// =======================================================================
+// function : Release
+// purpose  :
+// =======================================================================
+void OpenGl_Sampler::Release (OpenGl_Context* theContext)
+{
+  if (isValidSampler())
+  {
+    // application can not handle this case by exception - this is bug in code
+    Standard_ASSERT_RETURN (theContext != NULL,
+      "OpenGl_Sampler destroyed without GL context! Possible GPU memory leakage...",);
+
+    if (theContext->IsValid())
+    {
+    #if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0)
+      theContext->core33->glDeleteSamplers (1, &mySamplerID);
+    #endif
+    }
+
+    mySamplerID = NO_SAMPLER;
+  }
+}
+
+// =======================================================================
+// function : Init
+// purpose  : Initializes sampler object
+// =======================================================================
+Standard_Boolean OpenGl_Sampler::Init (OpenGl_Context& theContext)
+{
+  if (theContext.core33 == NULL)
+  {
+    return Standard_False;
+  }
+
+  if (isValidSampler())
+  {
+    Release (&theContext);
+  }
+
+#if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0)
+  theContext.core33->glGenSamplers (1, &mySamplerID);
+  return Standard_True;
+#else
+  return Standard_False;
+#endif
+}
+
+// =======================================================================
+// function : Bind
+// purpose  : Binds sampler object to the given texture unit
+// =======================================================================
+void OpenGl_Sampler::Bind (OpenGl_Context& theContext,
+                           const GLuint    theUnit)
+{
+  if (isValidSampler())
+  {
+  #if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0)
+    theContext.core33->glBindSampler (theUnit, mySamplerID);
+  #endif
+  }
+}
+
+// =======================================================================
+// function : Unbind
+// purpose  : Unbinds sampler object from the given texture unit
+// =======================================================================
+void OpenGl_Sampler::Unbind (OpenGl_Context& theContext,
+                             const GLuint    theUnit)
+{
+  if (isValidSampler())
+  {
+  #if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0)
+    theContext.core33->glBindSampler (theUnit, NO_SAMPLER);
+  #endif
+  }
+}
+
+// =======================================================================
+// function : SetParameter
+// purpose  : Sets sampler parameters
+// =======================================================================
+void OpenGl_Sampler::SetParameter (OpenGl_Context& theContext,
+                                   const GLenum    theParam,
+                                   const GLint     theValue)
+{
+  if (isValidSampler())
+  {
+  #if !defined(GL_ES_VERSION_2_0) || defined(GL_ES_VERSION_3_0)
+    theContext.core33->glSamplerParameteri (mySamplerID, theParam, theValue);
+  #endif
+  }
+}
diff --git a/src/OpenGl/OpenGl_Sampler.hxx b/src/OpenGl/OpenGl_Sampler.hxx
new file mode 100644 (file)
index 0000000..dda1e3a
--- /dev/null
@@ -0,0 +1,84 @@
+// Created on: 2014-10-08
+// Created by: Denis BOGOLEPOV
+// Copyright (c) 2014 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#ifndef OPENGL_SAMPLER_H
+#define OPENGL_SAMPLER_H
+
+#include <OpenGl_Context.hxx>
+#include <Handle_OpenGl_Sampler.hxx>
+
+//! Class implements OpenGL sampler object resource that
+//! stores the sampling parameters for a texture access.
+class OpenGl_Sampler : public OpenGl_Resource
+{
+public:
+
+  //! Helpful constant defining invalid sampler identifier
+  static const GLuint NO_SAMPLER = 0;
+
+public:
+
+  //! Creates new sampler object.
+  Standard_EXPORT OpenGl_Sampler();
+
+  //! Releases resources of sampler object.
+  Standard_EXPORT virtual ~OpenGl_Sampler();
+
+  //! Destroys object - will release GPU memory if any.
+  Standard_EXPORT virtual void Release (OpenGl_Context* theContext);
+
+  //! Initializes sampler object.
+  Standard_EXPORT Standard_Boolean Init (OpenGl_Context& theContext);
+
+  //! Returns true if current object was initialized.
+  Standard_Boolean IsValid() const
+  {
+    return isValidSampler();
+  }
+
+  //! Binds sampler object to the given texture unit.
+  Standard_EXPORT void Bind (OpenGl_Context& theContext, const GLuint theUnit = 0);
+
+  //! Unbinds sampler object from the given texture unit.
+  Standard_EXPORT void Unbind (OpenGl_Context& theContext, const GLuint theUnit = 0);
+
+  //! Sets specific sampler parameter.
+  Standard_EXPORT void SetParameter (OpenGl_Context& theContext, const GLenum theParam, const GLint theValue);
+
+  //! Returns OpenGL sampler ID.
+  GLuint SamplerID() const
+  {
+    return mySamplerID;
+  }
+
+protected:
+
+  //! Checks if sampler object is valid.
+  Standard_Boolean isValidSampler() const
+  {
+    return mySamplerID != NO_SAMPLER;
+  }
+
+protected:
+
+  GLuint mySamplerID; //!< OpenGL sampler object ID
+
+public:
+
+  DEFINE_STANDARD_RTTI(OpenGl_Sampler)
+
+};
+
+#endif // OPENGL_SAMPLER_H
index 0dcbb8a..c618c29 100755 (executable)
@@ -13,8 +13,6 @@
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <Standard_Assert.hxx>
-
 #ifdef HAVE_TBB
   // On Windows, function TryEnterCriticalSection has appeared in Windows NT
   // and is surrounded by #ifdef in MS VC++ 7.1 headers.
 
 #include <OpenGl_SceneGeometry.hxx>
 
+#include <OpenGl_ArbTexBindless.hxx>
 #include <OpenGl_PrimitiveArray.hxx>
 #include <OpenGl_Structure.hxx>
+#include <OSD_Timer.hxx>
+#include <Standard_Assert.hxx>
 
 //! Use this macro to output BVH profiling info
-//#define BVH_PRINT_INFO
-
-#ifdef BVH_PRINT_INFO
-  #include <OSD_Timer.hxx>
-#endif
+// #define RAY_TRACE_PRINT_INFO
 
 namespace
 {
   //! Useful constant for null floating-point 4D vector.
   static const BVH_Vec4f ZERO_VEC_4F;
-};
+}
 
 // =======================================================================
 // function : OpenGl_RaytraceMaterial
@@ -131,13 +128,51 @@ OpenGl_RaytraceLight::OpenGl_RaytraceLight (const BVH_Vec4f& theDiffuse,
   //
 }
 
+// =======================================================================
+// function : Box
+// purpose  : Returns AABB of primitive set
+// =======================================================================
+OpenGl_TriangleSet::BVH_BoxNt OpenGl_TriangleSet::Box() const
+{
+  const BVH_Transform<Standard_ShortReal, 4>* aTransform =
+    dynamic_cast<const BVH_Transform<Standard_ShortReal, 4>* > (Properties().operator->());
+
+  BVH_BoxNt aBox = BVH_PrimitiveSet<Standard_ShortReal, 3>::Box();
+
+  if (aTransform != NULL)
+  {
+    BVH_BoxNt aTransformedBox;
+
+    for (Standard_Integer aX = 0; aX <= 1; ++aX)
+    {
+      for (Standard_Integer aY = 0; aY <= 1; ++aY)
+      {
+        for (Standard_Integer aZ = 0; aZ <= 1; ++aZ)
+        {
+          BVH_Vec4f aCorner = aTransform->Transform() * BVH_Vec4f (
+            aX == 0 ? aBox.CornerMin().x() : aBox.CornerMax().x(),
+            aY == 0 ? aBox.CornerMin().y() : aBox.CornerMax().y(),
+            aZ == 0 ? aBox.CornerMin().z() : aBox.CornerMax().z(),
+            1.f);
+
+          aTransformedBox.Add (reinterpret_cast<BVH_Vec3f&> (aCorner));
+        }
+      }
+    }
+
+    return aTransformedBox;
+  }
+
+  return aBox;
+}
+
 // =======================================================================
 // function : Clear
 // purpose  : Clears ray-tracing geometry
 // =======================================================================
 void OpenGl_RaytraceGeometry::Clear()
 {
-  BVH_Geometry<Standard_ShortReal, 4>::BVH_Geometry::Clear();
+  BVH_Geometry<Standard_ShortReal, 3>::BVH_Geometry::Clear();
 
   std::vector<OpenGl_RaytraceLight,
     NCollection_StdAllocator<OpenGl_RaytraceLight> > anEmptySources;
@@ -154,9 +189,9 @@ void OpenGl_RaytraceGeometry::Clear()
 
 struct OpenGL_BVHParallelBuilder
 {
-  BVH_ObjectSet<Standard_ShortReal, 4>* Set;
+  BVH_ObjectSet<Standard_ShortReal, 3>* Set;
 
-  OpenGL_BVHParallelBuilder (BVH_ObjectSet<Standard_ShortReal, 4>* theSet)
+  OpenGL_BVHParallelBuilder (BVH_ObjectSet<Standard_ShortReal, 3>* theSet)
     : Set (theSet)
   {
     //
@@ -185,13 +220,13 @@ struct OpenGL_BVHParallelBuilder
 // =======================================================================
 Standard_Boolean OpenGl_RaytraceGeometry::ProcessAcceleration()
 {
-#ifdef BVH_PRINT_INFO
+#ifdef RAY_TRACE_PRINT_INFO
     OSD_Timer aTimer;
 #endif
 
   MarkDirty(); // force BVH rebuilding
 
-#ifdef BVH_PRINT_INFO
+#ifdef RAY_TRACE_PRINT_INFO
   aTimer.Reset();
   aTimer.Start();
 #endif
@@ -219,21 +254,21 @@ Standard_Boolean OpenGl_RaytraceGeometry::ProcessAcceleration()
     myBottomLevelTreeDepth = Max (myBottomLevelTreeDepth, aTriangleSet->BVH()->Depth());
   }
 
-#ifdef BVH_PRINT_INFO
+#ifdef RAY_TRACE_PRINT_INFO
   aTimer.Stop();
 
   std::cout << "Updating bottom-level BVHs (sec): " <<
     aTimer.ElapsedTime() << std::endl;
 #endif
 
-#ifdef BVH_PRINT_INFO
+#ifdef RAY_TRACE_PRINT_INFO
   aTimer.Reset();
   aTimer.Start();
 #endif
 
-  NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> > aBVH = BVH();
+  NCollection_Handle<BVH_Tree<Standard_ShortReal, 3> > aBVH = BVH();
 
-#ifdef BVH_PRINT_INFO
+#ifdef RAY_TRACE_PRINT_INFO
   aTimer.Stop();
 
   std::cout << "Updating high-level BVH (sec): " <<
@@ -285,7 +320,7 @@ Standard_Boolean OpenGl_RaytraceGeometry::ProcessAcceleration()
 // =======================================================================
 Standard_Integer OpenGl_RaytraceGeometry::AccelerationOffset (Standard_Integer theNodeIdx)
 {
-  const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = BVH();
+  const NCollection_Handle<BVH_Tree<Standard_ShortReal, 3> >& aBVH = BVH();
 
   if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx))
     return INVALID_OFFSET;
@@ -299,7 +334,7 @@ Standard_Integer OpenGl_RaytraceGeometry::AccelerationOffset (Standard_Integer t
 // =======================================================================
 Standard_Integer OpenGl_RaytraceGeometry::VerticesOffset (Standard_Integer theNodeIdx)
 {
-  const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = BVH();
+  const NCollection_Handle<BVH_Tree<Standard_ShortReal, 3> >& aBVH = BVH();
 
   if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx))
     return INVALID_OFFSET;
@@ -313,7 +348,7 @@ Standard_Integer OpenGl_RaytraceGeometry::VerticesOffset (Standard_Integer theNo
 // =======================================================================
 Standard_Integer OpenGl_RaytraceGeometry::ElementsOffset (Standard_Integer theNodeIdx)
 {
-  const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = BVH();
+  const NCollection_Handle<BVH_Tree<Standard_ShortReal, 3> >& aBVH = BVH();
 
   if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx))
     return INVALID_OFFSET;
@@ -327,7 +362,7 @@ Standard_Integer OpenGl_RaytraceGeometry::ElementsOffset (Standard_Integer theNo
 // =======================================================================
 OpenGl_TriangleSet* OpenGl_RaytraceGeometry::TriangleSet (Standard_Integer theNodeIdx)
 {
-  const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = BVH();
+  const NCollection_Handle<BVH_Tree<Standard_ShortReal, 3> >& aBVH = BVH();
 
   if (theNodeIdx >= aBVH->Length() || !aBVH->IsOuter (theNodeIdx))
     return NULL;
@@ -339,6 +374,120 @@ OpenGl_TriangleSet* OpenGl_RaytraceGeometry::TriangleSet (Standard_Integer theNo
     aBVH->NodeInfoBuffer().at (theNodeIdx).x() - 1).operator->());
 }
 
+// =======================================================================
+// function : AcquireTextures
+// purpose  : Makes the OpenGL texture handles resident
+// =======================================================================
+Standard_Boolean OpenGl_RaytraceGeometry::AcquireTextures (const Handle(OpenGl_Context)& theContext) const
+{
+  if (theContext->arbTexBindless == NULL)
+  {
+    return Standard_True;
+  }
+
+#if !defined(GL_ES_VERSION_2_0)
+  for (Standard_Integer anIdx = 0; anIdx < myTextures.Size(); ++anIdx)
+  {
+    theContext->arbTexBindless->glMakeTextureHandleResidentARB (myTextureHandles[anIdx]);
+
+    if (glGetError() != GL_NO_ERROR)
+    {
+#ifdef RAY_TRACE_PRINT_INFO
+      std::cout << "Error: Failed to make OpenGL texture resident" << std::endl;
+#endif
+      return Standard_False;
+    }
+  }
+#endif
+
+  return Standard_True;
+}
+
+// =======================================================================
+// function : ReleaseTextures
+// purpose  : Makes the OpenGL texture handles non-resident
+// =======================================================================
+Standard_Boolean OpenGl_RaytraceGeometry::ReleaseTextures (const Handle(OpenGl_Context)& theContext) const
+{
+  if (theContext->arbTexBindless == NULL)
+  {
+    return Standard_True;
+  }
+
+#if !defined(GL_ES_VERSION_2_0)
+  for (Standard_Integer anIdx = 0; anIdx < myTextures.Size(); ++anIdx)
+  {
+    theContext->arbTexBindless->glMakeTextureHandleNonResidentARB (myTextureHandles[anIdx]);
+
+    if (glGetError() != GL_NO_ERROR)
+    {
+#ifdef RAY_TRACE_PRINT_INFO
+      std::cout << "Error: Failed to make OpenGL texture non-resident" << std::endl;
+#endif
+      return Standard_False;
+    }
+  }
+#endif
+
+  return Standard_True;
+}
+
+// =======================================================================
+// function : AddTexture
+// purpose  : Adds new OpenGL texture to the scene and returns its index
+// =======================================================================
+Standard_Integer OpenGl_RaytraceGeometry::AddTexture (const Handle(OpenGl_Texture)& theTexture)
+{
+  NCollection_Vector<Handle (OpenGl_Texture)>::iterator anIter =
+    std::find (myTextures.begin(), myTextures.end(), theTexture);
+
+  if (anIter == myTextures.end())
+  {
+    if (myTextures.Size() >= MAX_TEX_NUMBER)
+    {
+      return -1;
+    }
+
+    myTextures.Append (theTexture);
+  }
+
+  return static_cast<Standard_Integer> (anIter - myTextures.begin());
+}
+
+// =======================================================================
+// function : UpdateTextureHandles
+// purpose  : Updates unique 64-bit texture handles to use in shaders
+// =======================================================================
+Standard_Boolean OpenGl_RaytraceGeometry::UpdateTextureHandles (const Handle(OpenGl_Context)& theContext)
+{
+  if (theContext->arbTexBindless == NULL)
+  {
+    return Standard_False;
+  }
+
+  myTextureHandles.clear();
+
+#if !defined(GL_ES_VERSION_2_0)
+  for (Standard_Integer anIdx = 0; anIdx < myTextures.Size(); ++anIdx)
+  {
+    const GLuint64 aHandle = theContext->arbTexBindless->glGetTextureHandleARB (
+      myTextures.Value (anIdx)->TextureId());
+
+    if (glGetError() != GL_NO_ERROR)
+    {
+#ifdef RAY_TRACE_PRINT_INFO
+      std::cout << "Error: Failed to get 64-bit handle of OpenGL texture" << std::endl;
+#endif
+      return Standard_False;
+    }
+
+    myTextureHandles.push_back (aHandle);
+  }
+#endif
+
+  return Standard_True;
+}
+
 namespace OpenGl_Raytrace
 {
   // =======================================================================
@@ -347,7 +496,7 @@ namespace OpenGl_Raytrace
   // =======================================================================
   Standard_Boolean IsRaytracedElement (const OpenGl_ElementNode* theNode)
   {
-    OpenGl_PrimitiveArray* anArray = dynamic_cast< OpenGl_PrimitiveArray* > (theNode->elem);
+    OpenGl_PrimitiveArray* anArray = dynamic_cast<OpenGl_PrimitiveArray*> (theNode->elem);
     return anArray != NULL
         && anArray->DrawMode() >= GL_TRIANGLES;
   }
index 97390a7..241e681 100755 (executable)
@@ -19,6 +19,8 @@
 #include <BVH_Geometry.hxx>
 #include <BVH_Triangulation.hxx>
 #include <NCollection_StdAllocator.hxx>
+#include <OpenGl_TextureBufferArb.hxx>
+#include <OpenGl_Texture.hxx>
 
 class  OpenGl_Element;
 struct OpenGl_ElementNode;
@@ -67,6 +69,9 @@ public:
   //! Material transparency.
   BVH_Vec4f Transparency;
 
+  //! Texture transformation matrix.
+  BVH_Mat4f TextureTransform;
+
 public:
 
   //! Creates new default material.
@@ -125,7 +130,7 @@ public:
 };
 
 //! Triangulation of single OpenGL primitive array.
-class OpenGl_TriangleSet : public BVH_Triangulation<Standard_ShortReal, 4>
+class OpenGl_TriangleSet : public BVH_Triangulation<Standard_ShortReal, 3>
 {
 public:
 
@@ -136,11 +141,11 @@ public:
 
   //! Creates new OpenGL element triangulation.
   OpenGl_TriangleSet (const Standard_Size theArrayID)
-  : BVH_Triangulation<Standard_ShortReal, 4>(),
+  : BVH_Triangulation<Standard_ShortReal, 3> (),
     myArrayID (theArrayID)
-   {
-     //
-   }
+  {
+    //
+  }
 
   //! Releases resources of OpenGL element triangulation.
   ~OpenGl_TriangleSet()
@@ -158,38 +163,31 @@ public:
   Standard_Integer MaterialIndex() const
   {
     if (Elements.size() == 0)
+    {
       return INVALID_MATERIAL;
+    }
 
     return Elements.front().w();
   }
 
   //! Sets material index for entire triangle set.
-  void SetMaterialIndex (Standard_Integer aMatID)
+  void SetMaterialIndex (Standard_Integer theMatID)
   {
     for (Standard_Size anIdx = 0; anIdx < Elements.size(); ++anIdx)
-      Elements[anIdx].w() = aMatID;
-  }
-
-  //! Returns AABB of primitive set.
-  BVH_BoxNt Box() const
-  {
-    const BVH_Transform<Standard_ShortReal, 4>* aTransform = 
-      dynamic_cast<const BVH_Transform<Standard_ShortReal, 4>* > (Properties().operator->());
-    BVH_BoxNt aBox = BVH_PrimitiveSet<Standard_ShortReal, 4>::Box(); 
-    if (aTransform)
     {
-      return aTransform->Apply (aBox);
+      Elements[anIdx].w() = theMatID;
     }
-    return aBox;
   }
 
+  //! Returns AABB of primitive set.
+  BVH_BoxNt Box() const;
+
 public:
 
-  BVH_Array4f Normals; //!< Array of vertex normals.
+  BVH_Array3f Normals; //!< Array of vertex normals.
+
+  BVH_Array2f TexCrds; //!< Array of vertex UV coords.
+
 private:
 
   Standard_Size myArrayID; //!< Id of associated primitive array.
@@ -197,13 +195,19 @@ private:
 };
 
 //! Stores geometry of ray-tracing scene.
-class OpenGl_RaytraceGeometry : public BVH_Geometry<Standard_ShortReal, 4>
+class OpenGl_RaytraceGeometry : public BVH_Geometry<Standard_ShortReal, 3>
 {
 public:
 
   //! Value of invalid offset to return in case of errors.
   static const Standard_Integer INVALID_OFFSET = -1;
 
+  //! Maximum number of textures used in ray-tracing shaders.
+  //! This is not restriction of the solution implemented, but
+  //! rather the reasonable limit of the number of textures in
+  //! various applications (can be increased if needed).
+  static const Standard_Integer MAX_TEX_NUMBER = 32;
+
 public:
 
   //! Array of properties of light sources.
@@ -221,7 +225,7 @@ public:
 
   //! Creates uninitialized ray-tracing geometry.
   OpenGl_RaytraceGeometry()
-  : BVH_Geometry<Standard_ShortReal, 4>(),
+  : BVH_Geometry<Standard_ShortReal, 3>(),
     myHighLevelTreeDepth (0),
     myBottomLevelTreeDepth (0)
   {
@@ -234,19 +238,21 @@ public:
     //
   }
 
-  //! Clears ray-tracing geometry.
-  void Clear();
-
   //! Clears only ray-tracing materials.
   void ClearMaterials()
   {
     std::vector<OpenGl_RaytraceMaterial,
       NCollection_StdAllocator<OpenGl_RaytraceMaterial> > anEmptyMaterials;
+
     Materials.swap (anEmptyMaterials);
+
+    myTextures.Clear();
   }
 
-public:
+  //! Clears ray-tracing geometry.
+  void Clear();
+
+public: //! @name methods related to acceleration structure
 
   //! Performs post-processing of high-level scene BVH.
   Standard_Boolean ProcessAcceleration();
@@ -271,6 +277,34 @@ public:
   //! @note Can be used after processing acceleration structure.
   OpenGl_TriangleSet* TriangleSet (Standard_Integer theNodeIdx);
 
+public: //! @name methods related to texture management
+
+  //! Adds new OpenGL texture to the scene and returns its index.
+  Standard_Integer AddTexture (const Handle(OpenGl_Texture)& theTexture);
+
+  //! Updates unique 64-bit texture handles to use in shaders.
+  Standard_Boolean UpdateTextureHandles (const Handle(OpenGl_Context)& theContext);
+
+  //! Makes the OpenGL texture handles resident (must be called before using).
+  Standard_Boolean AcquireTextures (const Handle(OpenGl_Context)& theContext) const;
+
+  //! Makes the OpenGL texture handles non-resident (must be called after using).
+  Standard_Boolean ReleaseTextures (const Handle(OpenGl_Context)& theContext) const;
+
+  //! Returns array of texture handles.
+  const std::vector<GLuint64>& TextureHandles() const
+  {
+    return myTextureHandles;
+  }
+
+  //! Checks if scene contains textured objects.
+  Standard_Integer HasTextures() const
+  {
+    return !myTextures.IsEmpty();
+  }
+
+public: //! @name auxiliary methods
+
   //! Returns depth of high-level scene BVH from last build.
   Standard_Integer HighLevelTreeDepth() const
   {
@@ -285,8 +319,10 @@ public:
 
 protected:
 
-  Standard_Integer myHighLevelTreeDepth;   //!< Depth of high-level scene BVH from last build
-  Standard_Integer myBottomLevelTreeDepth; //!< Maximum depth of bottom-level scene BVHs from last build
+  NCollection_Vector<Handle(OpenGl_Texture)> myTextures;             //!< Array of texture maps shared between rendered objects
+  std::vector<GLuint64>                      myTextureHandles;       //!< Array of unique 64-bit texture handles obtained from OpenGL
+  Standard_Integer                           myHighLevelTreeDepth;   //!< Depth of high-level scene BVH from last build
+  Standard_Integer                           myBottomLevelTreeDepth; //!< Maximum depth of bottom-level scene BVHs from last build
 
 };
 
index a0e027e..61cfaee 100755 (executable)
@@ -24,6 +24,7 @@
 #include <OpenGl_Context.hxx>
 #include <OpenGl_ShaderProgram.hxx>
 #include <OpenGl_ShaderManager.hxx>
+#include <OpenGl_ArbTexBindless.hxx>
 
 IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderProgram, OpenGl_Resource)
 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_Resource)
@@ -784,6 +785,70 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
   return Standard_True;
 }
 
+// =======================================================================
+// function : SetUniform
+// purpose  : Specifies the value of the 64-bit unsigned uniform variable
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   const GLchar*                 theName,
+                                                   GLuint64                      theValue)
+{
+  return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue);
+}
+
+// =======================================================================
+// function : SetUniform
+// purpose  : Specifies the value of the 64-bit unsigned uniform variable
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   GLint                         theLocation,
+                                                   GLuint64                      theValue)
+{
+  if (theCtx->arbTexBindless == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
+  {
+    return Standard_False;
+  }
+
+#if !defined(GL_ES_VERSION_2_0)
+  theCtx->arbTexBindless->glUniformHandleui64ARB (theLocation, theValue);
+#endif
+
+  return Standard_True;
+}
+
+// =======================================================================
+// function : SetUniform
+// purpose  : Specifies the value of the 64-bit unsigned uniform array
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   const GLchar*                 theName,
+                                                   const GLsizei                 theCount,
+                                                   const GLuint64*               theValue)
+{
+  return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theCount, theValue);
+}
+
+// =======================================================================
+// function : SetUniform
+// purpose  : Specifies the value of the 64-bit unsigned uniform array
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   GLint                         theLocation,
+                                                   const GLsizei                 theCount,
+                                                   const GLuint64*               theValue)
+{
+  if (theCtx->arbTexBindless == NULL || myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
+  {
+    return Standard_False;
+  }
+
+#if !defined(GL_ES_VERSION_2_0)
+  theCtx->arbTexBindless->glUniformHandleui64vARB (theLocation, theCount, theValue);
+#endif
+
+  return Standard_True;
+}
+
 // =======================================================================
 // function : SetUniform
 // purpose  : Specifies the value of the floating-point uniform variable
@@ -980,6 +1045,36 @@ Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)&
   return Standard_True;
 }
 
+// =======================================================================
+// function : SetUniform
+// purpose  : Specifies the value of the floating-point uniform 4x4 matrix
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   const GLchar*                 theName,
+                                                   const OpenGl_Mat4&            theValue,
+                                                   GLboolean                     theTranspose)
+{
+  return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theValue, theTranspose);
+}
+
+// =======================================================================
+// function : SetUniform
+// purpose  : Specifies the value of the floating-point uniform 4x4 matrix
+// =======================================================================
+Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                                   GLint                         theLocation,
+                                                   const OpenGl_Mat4&            theValue,
+                                                   GLboolean                     theTranspose)
+{
+  if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
+  {
+    return Standard_False;
+  }
+
+  theCtx->core20->glUniformMatrix4fv (theLocation, 1, theTranspose, theValue);
+  return Standard_True;
+}
+
 // =======================================================================
 // function : SetUniform
 // purpose  : Specifies the value of the floating-point uniform 4x4 matrix
index c65124c..b26cabb 100755 (executable)
@@ -350,6 +350,30 @@ public:
                                                GLint                         theLocation,
                                                const OpenGl_Vec4i&           theValue);
 
+public:
+
+  //! Specifies the value of the 64-bit unsigned integer uniform variable.
+  Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                               const GLchar*                 theName,
+                                               GLuint64                      theValue);
+
+  //! Specifies the value of the 64-bit unsigned integer uniform variable.
+  Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                               GLint                         theLocation,
+                                               GLuint64                      theValue);
+
+  //! Specifies the value of the 64-bit unsigned integer uniform array.
+  Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                               const GLchar*                 theName,
+                                               const GLsizei                 theCount,
+                                               const GLuint64*               theValue);
+
+  //! Specifies the value of the 64-bit unsigned integer uniform array.
+  Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                               GLint                         theLocation,
+                                               const GLsizei                 theCount,
+                                               const GLuint64*               theValue);
+
 public:
 
   //! Specifies the value of the float uniform variable.
@@ -394,6 +418,18 @@ public:
 
 public:
 
+  //! Specifies the value of the float uniform 4x4 matrix.
+  Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                               const GLchar*                 theName,
+                                               const OpenGl_Mat4&            theValue,
+                                               GLboolean                     theTranspose = GL_FALSE);
+
+  //! Specifies the value of the float uniform 4x4 matrix.
+  Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx,
+                                               GLint                         theLocation,
+                                               const OpenGl_Mat4&            theValue,
+                                               GLboolean                     theTranspose = GL_FALSE);
+
   //! Specifies the value of the float uniform 4x4 matrix.
   Standard_EXPORT Standard_Boolean SetUniform (const Handle(OpenGl_Context)& theCtx,
                                                const GLchar*                 theName,
index d991609..d4db2ce 100755 (executable)
@@ -19,6 +19,7 @@
 #include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_ShaderProgram.hxx>
 #include <OpenGl_ShaderStates.hxx>
+#include <OpenGl_Sampler.hxx>
 #include <OpenGl_Text.hxx>
 #include <OpenGl_Workspace.hxx>
 
@@ -377,10 +378,14 @@ void OpenGl_Text::StringSize (const Handle(OpenGl_Context)& theCtx,
 // =======================================================================
 void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
 {
-  const OpenGl_AspectText* aTextAspect = theWorkspace->AspectText (Standard_True);
-  const Handle(OpenGl_Texture) aPrevTexture = theWorkspace->DisableTexture();
-
-  const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
+  const OpenGl_AspectText*      aTextAspect  = theWorkspace->AspectText (Standard_True);
+  const Handle(OpenGl_Texture)  aPrevTexture = theWorkspace->DisableTexture();
+  const Handle(OpenGl_Context)& aCtx         = theWorkspace->GetGlContext();
+  const Handle(OpenGl_Sampler)& aSampler     = aCtx->TextureSampler();
+  if (!aSampler.IsNull())
+  {
+    aSampler->Unbind (*aCtx);
+  }
 
   if (aCtx->IsGlGreaterEqual (2, 0))
   {
@@ -418,6 +423,10 @@ void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const
   }
 
   // restore aspects
+  if (!aSampler.IsNull())
+  {
+    aSampler->Bind (*aCtx);
+  }
   if (!aPrevTexture.IsNull())
   {
     theWorkspace->EnableTexture (aPrevTexture);
@@ -722,6 +731,13 @@ void OpenGl_Text::render (const Handle(OpenGl_PrinterContext)& thePrintCtx,
     theCtx->core15fwd->glActiveTexture (GL_TEXTURE0);
   }
 
+  // unbind current OpenGL sampler
+  const Handle(OpenGl_Sampler)& aSampler = theCtx->TextureSampler();
+  if (!aSampler.IsNull() && aSampler->IsValid())
+  {
+    aSampler->Unbind (*theCtx);
+  }
+
   // extra drawings
   switch (theTextAspect.DisplayType())
   {
@@ -808,5 +824,11 @@ void OpenGl_Text::render (const Handle(OpenGl_PrinterContext)& thePrintCtx,
   // revert OpenGL state
   glPopAttrib(); // enable bit
   glPopMatrix(); // model view matrix was modified
+
+  // revert custom OpenGL sampler
+  if (!aSampler.IsNull() && aSampler->IsValid())
+  {
+    aSampler->Bind (*theCtx);
+  }
 #endif
 }
index f1d5aca..af41da1 100644 (file)
@@ -99,13 +99,17 @@ bool OpenGl_TextureBufferArb::Init (const Handle(OpenGl_Context)& theGlCtx,
                                     const GLfloat* theData)
 {
 #if !defined(GL_ES_VERSION_2_0)
-  if (theComponentsNb != 1
-   && theComponentsNb != 2
-   && theComponentsNb != 4)
+  if (theComponentsNb < 1
+   || theComponentsNb > 4)
   {
     // unsupported format
     return false;
   }
+  else if (theComponentsNb == 3
+       && !theGlCtx->arbTboRGB32)
+  {
+    return false;
+  }
   else if (!Create (theGlCtx)
         || !OpenGl_VertexBuffer::Init (theGlCtx, theComponentsNb, theElemsNb, theData))
   {
@@ -116,7 +120,7 @@ bool OpenGl_TextureBufferArb::Init (const Handle(OpenGl_Context)& theGlCtx,
   {
     case 1: myTexFormat = GL_R32F;    break;
     case 2: myTexFormat = GL_RG32F;   break;
-    //case 3: myTexFormat = GL_RGB32F;  break; // GL_ARB_texture_buffer_object_rgb32
+    case 3: myTexFormat = GL_RGB32F;  break; // GL_ARB_texture_buffer_object_rgb32
     case 4: myTexFormat = GL_RGBA32F; break;
   }
 
@@ -141,14 +145,17 @@ bool OpenGl_TextureBufferArb::Init (const Handle(OpenGl_Context)& theGlCtx,
                                     const GLuint*  theData)
 {
 #if !defined(GL_ES_VERSION_2_0)
-  if (theComponentsNb != 1
-   && theComponentsNb != 2
-   && theComponentsNb != 3
-   && theComponentsNb != 4)
+  if (theComponentsNb < 1
+   || theComponentsNb > 4)
   {
     // unsupported format
     return false;
   }
+  else if (theComponentsNb == 3
+       && !theGlCtx->arbTboRGB32)
+  {
+    return false;
+  }
   else if (!Create (theGlCtx)
         || !OpenGl_VertexBuffer::Init (theGlCtx, theComponentsNb, theElemsNb, theData))
   {
index 56725e9..8762c5b 100644 (file)
@@ -438,19 +438,10 @@ const TEL_TRANSFORM_PERSISTENCE* OpenGl_View::BeginTransformPersistence (const H
 
 /*----------------------------------------------------------------------*/
 
-void OpenGl_View::GetMatrices (TColStd_Array2OfReal&  theMatOrient,
-                               TColStd_Array2OfReal&  theMatMapping) const
+void OpenGl_View::GetMatrices (OpenGl_Mat4& theOrientation,
+                               OpenGl_Mat4& theViewMapping) const
 {
-  const Graphic3d_Mat4d& aProj   = myCamera->ProjectionMatrix();
-  const Graphic3d_Mat4d& aOrient = myCamera->OrientationMatrix();
-
-  for (Standard_Integer aRow = 0; aRow < 4; ++aRow)
-  {
-    for (Standard_Integer aCol = 0; aCol < 4; ++aCol)
-    {
-      theMatOrient  (aRow, aCol) = aOrient.GetValue (aRow, aCol);
-      theMatMapping (aRow, aCol) = aProj  .GetValue (aRow, aCol);
-    }
-  }
+  theViewMapping = myCamera->ProjectionMatrixF();
+  theOrientation = myCamera->OrientationMatrixF();
 }
 /*----------------------------------------------------------------------*/
index bbb90ca..35c0eef 100644 (file)
@@ -204,8 +204,9 @@ class OpenGl_View : public MMgt_TShared
   //! marks primitive set for rebuild.
   void InvalidateBVHData (const Standard_Integer theLayerId);
 
-  void GetMatrices (TColStd_Array2OfReal&  theMatOrient,
-                    TColStd_Array2OfReal&  theMatMapping) const;
+  //! Returns view-mapping and orientation matrices.
+  void GetMatrices (OpenGl_Mat4& theOrientation,
+                    OpenGl_Mat4& theViewMapping) const;
 
   //! Returns list of immediate structures rendered on top of main presentation
   const OpenGl_SequenceOfStructure& ImmediateStructures() const
index 67799e2..bf715d8 100644 (file)
@@ -25,6 +25,7 @@
 #include <OpenGl_Element.hxx>
 #include <OpenGl_FrameBuffer.hxx>
 #include <OpenGl_Structure.hxx>
+#include <OpenGl_Sampler.hxx>
 #include <OpenGl_Texture.hxx>
 #include <OpenGl_View.hxx>
 #include <OpenGl_Workspace.hxx>
@@ -144,6 +145,7 @@ OpenGl_Workspace::OpenGl_Workspace (const Handle(OpenGl_GraphicDriver)& theDrive
   //
   myComputeInitStatus (OpenGl_RT_NONE),
   myIsRaytraceDataValid (Standard_False),
+  myIsRaytraceWarnTextures (Standard_False),
   myViewModificationStatus (0),
   myLayersModificationStatus (0),
   //
@@ -435,6 +437,9 @@ void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)&
   }
 #endif
 
+  // get active sampler object to override default texture parameters
+  const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
+
   // setup texture filtering and wrapping
   //if (theTexture->GetParams() != theParams)
   const GLenum aFilter   = (aParams->Filter() == Graphic3d_TOTF_NEAREST) ? GL_NEAREST : GL_LINEAR;
@@ -444,9 +449,19 @@ void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)&
   #if !defined(GL_ES_VERSION_2_0)
     case GL_TEXTURE_1D:
     {
-      glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
-      glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
-      glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     aWrapMode);
+      if (aSampler.IsNull() || !aSampler->IsValid())
+      {
+        glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MAG_FILTER, aFilter);
+        glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_MIN_FILTER, aFilter);
+        glTexParameteri (GL_TEXTURE_1D, GL_TEXTURE_WRAP_S,     aWrapMode);
+      }
+      else
+      {
+        aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
+        aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilter);
+        aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
+      }
+
       break;
     }
   #endif
@@ -469,37 +484,58 @@ void OpenGl_Workspace::setTextureParams (Handle(OpenGl_Texture)&
         {
           // setup degree of anisotropy filter
           const GLint aMaxDegree = myGlContext->MaxDegreeOfAnisotropy();
+          GLint aDegree;
           switch (aParams->AnisoFilter())
           {
             case Graphic3d_LOTA_QUALITY:
             {
-              glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aMaxDegree);
+              aDegree = aMaxDegree;
               break;
             }
             case Graphic3d_LOTA_MIDDLE:
             {
-
-              glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2));
+              aDegree = (aMaxDegree <= 4) ? 2 : (aMaxDegree / 2);
               break;
             }
             case Graphic3d_LOTA_FAST:
             {
-              glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 2);
+              aDegree = 2;
               break;
             }
             case Graphic3d_LOTA_OFF:
             default:
             {
-              glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, 1);
+              aDegree = 1;
               break;
             }
           }
+
+          if (aSampler.IsNull() || !aSampler->IsValid())
+          {
+            glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
+          }
+          else
+          {
+            aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAX_ANISOTROPY_EXT, aDegree);
+          }
         }
       }
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
-      glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
+
+      if (aSampler.IsNull() || !aSampler->IsValid())
+      {
+        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, aFilterMin);
+        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, aFilter);
+        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_S,     aWrapMode);
+        glTexParameteri (GL_TEXTURE_2D, GL_TEXTURE_WRAP_T,     aWrapMode);
+      }
+      else
+      {
+        aSampler->SetParameter (*myGlContext, GL_TEXTURE_MIN_FILTER, aFilterMin);
+        aSampler->SetParameter (*myGlContext, GL_TEXTURE_MAG_FILTER, aFilter);
+        aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_S,     aWrapMode);
+        aSampler->SetParameter (*myGlContext, GL_TEXTURE_WRAP_T,     aWrapMode);
+      }
+
       break;
     }
     default: break;
@@ -563,6 +599,15 @@ Handle(OpenGl_Texture) OpenGl_Workspace::EnableTexture (const Handle(OpenGl_Text
   myTextureBound->Bind (myGlContext);
   setTextureParams (myTextureBound, theParams);
 
+  // If custom sampler object is available it will be
+  // used for overriding default texture parameters
+  const Handle(OpenGl_Sampler)& aSampler = myGlContext->TextureSampler();
+
+  if (!aSampler.IsNull() && aSampler->IsValid())
+  {
+    aSampler->Bind (*myGlContext);
+  }
+
   return aPrevTexture;
 }
 
index c43f1de..805d577 100644 (file)
@@ -95,7 +95,7 @@ struct OpenGl_Material
 
 DEFINE_STANDARD_HANDLE (OpenGl_RaytraceFilter, OpenGl_RenderFilter)
 
-//! Graphical raytracing filter.
+//! Graphical ray-tracing filter.
 //! Filters out all raytracable structures.
 class OpenGl_RaytraceFilter : public OpenGl_RenderFilter
 {
@@ -307,29 +307,26 @@ protected:
     OpenGl_RT_uOriginLB,
     OpenGl_RT_uOriginRT,
     OpenGl_RT_uOriginRB,
-
     OpenGl_RT_uDirectLT,
     OpenGl_RT_uDirectLB,
     OpenGl_RT_uDirectRT,
     OpenGl_RT_uDirectRB,
-    OpenGl_RT_uInvModelProj,
-    
+    OpenGl_RT_uUnviewMat,
+
     OpenGl_RT_uSceneRad,
     OpenGl_RT_uSceneEps,
-
     OpenGl_RT_uLightAmbnt,
     OpenGl_RT_uLightCount,
 
     OpenGl_RT_uShadEnabled,
     OpenGl_RT_uReflEnabled,
-    
-    OpenGl_RT_uInputTexture,
+    OpenGl_RT_uEnvMapEnable,
 
     OpenGl_RT_uOffsetX,
     OpenGl_RT_uOffsetY,
     OpenGl_RT_uSamples,
 
-    OpenGl_RT_uEnvironmentEnable,
+    OpenGl_RT_uTextures,
 
     OpenGl_RT_NbVariables // special field
   };
@@ -347,19 +344,20 @@ protected:
 
     OpenGl_RT_GeometryVertexTexture = 6,
     OpenGl_RT_GeometryNormalTexture = 7,
-    OpenGl_RT_GeometryTriangTexture = 8,
+    OpenGl_RT_GeometryTexCrdTexture = 8,
+    OpenGl_RT_GeometryTriangTexture = 9,
 
-    OpenGl_RT_EnvironmentMapTexture = 9,
+    OpenGl_RT_EnvironmentMapTexture = 10,
 
-    OpenGl_RT_RaytraceMaterialTexture = 10,
-    OpenGl_RT_RaytraceLightSrcTexture = 11,
+    OpenGl_RT_RaytraceMaterialTexture = 11,
+    OpenGl_RT_RaytraceLightSrcTexture = 12,
 
-    OpenGl_RT_FSAAInputTexture = 12,
+    OpenGl_RT_FSAAInputTexture = 13,
 
-    OpenGl_RT_SceneTransformTexture = 13,
+    OpenGl_RT_SceneTransformTexture = 14,
 
-    OpenGl_RT_OpenGlColorTexture = 14,
-    OpenGl_RT_OpenGlDepthTexture = 15
+    OpenGl_RT_OpenGlColorTexture = 15,
+    OpenGl_RT_OpenGlDepthTexture = 16
   };
 
   //! Tool class for management of shader sources.
@@ -407,7 +405,7 @@ protected:
   };
 
   //! Default ray-tracing depth.
-  static const Standard_Integer THE_DEFAULT_RAY_DEPTH = 3;
+  static const Standard_Integer THE_DEFAULT_NB_BOUNCES = 3;
 
   //! Default size of traversal stack.
   static const Standard_Integer THE_DEFAULT_STACK_SIZE = 24;
@@ -419,7 +417,7 @@ protected:
     Standard_Integer StackSize;
 
     //! Actual ray-tracing depth (number of ray bounces).
-    Standard_Integer TraceDepth;
+    Standard_Integer NbBounces;
 
     //! Sets light propagation through transparent media.
     Standard_Boolean TransparentShadows;
@@ -427,7 +425,7 @@ protected:
     //! Creates default compile-time ray-tracing parameters.
     RaytracingParams()
     : StackSize (THE_DEFAULT_STACK_SIZE),
-      TraceDepth (THE_DEFAULT_RAY_DEPTH),
+      NbBounces (THE_DEFAULT_NB_BOUNCES),
       TransparentShadows (Standard_False)
     {
       //
@@ -442,8 +440,11 @@ protected: //! @name methods related to ray-tracing
   //! Checks to see if the structure is modified.
   Standard_Boolean CheckRaytraceStructure (const OpenGl_Structure* theStructure);
 
+  //! Creates ray-tracing material properties.
+  Standard_Boolean CreateMaterial (const OpenGl_AspectFace* theAspect, OpenGl_RaytraceMaterial& theMaterial);
+
   //! Updates 3D scene light sources for ray-tracing.
-  Standard_Boolean UpdateRaytraceLightSources (const GLdouble theInvModelView[16]);
+  Standard_Boolean UpdateRaytraceLightSources (const OpenGl_Mat4& theInvModelView);
 
   //! Updates environment map for ray-tracing.
   Standard_Boolean UpdateRaytraceEnvironmentMap();
@@ -458,7 +459,7 @@ protected: //! @name methods related to ray-tracing
 
   //! Adds OpenGL primitive array to ray-traced scene geometry.
   OpenGl_TriangleSet* AddRaytracePrimitiveArray (
-    const OpenGl_PrimitiveArray* theArray, int theMatID, const Standard_ShortReal* theTrans);
+    const OpenGl_PrimitiveArray* theArray, int theMatID, const OpenGl_Mat4* theTrans);
 
   //! Adds vertex indices from OpenGL primitive array to ray-traced scene geometry.
   Standard_Boolean AddRaytraceVertexIndices (OpenGl_TriangleSet&          theSet,
@@ -515,6 +516,9 @@ protected: //! @name methods related to ray-tracing
   //! Performs safe exit when shaders initialization fails.
   Standard_Boolean SafeFailBack (const TCollection_ExtendedString& theMessage);
 
+  //! Generates shader prefix based on current ray-tracing options.
+  TCollection_AsciiString GenerateShaderPrefix();
+
   //! Initializes OpenGL/GLSL shader programs.
   Standard_Boolean InitRaytraceResources (const Graphic3d_CView& theCView);
 
@@ -529,11 +533,19 @@ protected: //! @name methods related to ray-tracing
                                           const Standard_Integer theSizeY);
 
   //! Generates viewing rays for corners of screen quad.
-  void UpdateCamera (const NCollection_Mat4<GLdouble>& theOrientation,
-                     const NCollection_Mat4<GLdouble>& theViewMapping,
-                     OpenGl_Vec3                       theOrigins[4],
-                     OpenGl_Vec3                       theDirects[4],
-                     NCollection_Mat4<GLdouble>&       theInvModelProj);
+  void UpdateCamera (const OpenGl_Mat4& theOrientation,
+                     const OpenGl_Mat4& theViewMapping,
+                     OpenGl_Vec3        theOrigins[4],
+                     OpenGl_Vec3        theDirects[4],
+                     OpenGl_Mat4&       theInvModelProj);
+
+  //! Sets uniform state for the given ray-tracing shader program.
+  Standard_Boolean SetUniformState (const Graphic3d_CView&        theCView,
+                                    const OpenGl_Vec3*            theOrigins,
+                                    const OpenGl_Vec3*            theDirects,
+                                    const OpenGl_Mat4&            theUnviewMat,
+                                    const Standard_Integer        theProgramIndex,
+                                    Handle(OpenGl_ShaderProgram)& theRaytraceProgram);
 
   //! Runs ray-tracing shader programs.
   Standard_Boolean RunRaytraceShaders (const Graphic3d_CView& theCView,
@@ -541,7 +553,7 @@ protected: //! @name methods related to ray-tracing
                                        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);
 
   //! Redraws the window using OpenGL/GLSL ray-tracing.
@@ -561,6 +573,9 @@ protected: //! @name fields related to ray-tracing
   //! Is geometry data valid?
   Standard_Boolean myIsRaytraceDataValid;
 
+  //! Warning about missing extension GL_ARB_bindless_texture has been displayed?
+  Standard_Boolean myIsRaytraceWarnTextures;
+
   //! 3D scene geometry data for ray-tracing.
   OpenGl_RaytraceGeometry myRaytraceGeometry;
 
@@ -607,9 +622,11 @@ protected: //! @name fields related to ray-tracing
   Handle(OpenGl_TextureBufferArb) myGeometryVertexTexture;
   //! Texture buffer of vertex normals.
   Handle(OpenGl_TextureBufferArb) myGeometryNormalTexture;
+  //! Texture buffer of vertex UV coords.
+  Handle(OpenGl_TextureBufferArb) myGeometryTexCrdTexture;
   //! Texture buffer of triangle indices.
   Handle(OpenGl_TextureBufferArb) myGeometryTriangTexture;
-  
+
   //! Texture buffer of material properties.
   Handle(OpenGl_TextureBufferArb) myRaytraceMaterialTexture;
   //! Texture buffer of light source properties.
@@ -639,10 +656,10 @@ protected: //! @name fields related to ray-tracing
   //! Cached locations of frequently used uniform variables.
   Standard_Integer myUniformLocations[2][OpenGl_RT_NbVariables];
 
-  //! Graphical raytracing filter to filter out all raytracable structures.
+  //! Graphical ray-tracing filter to filter out all raytracable structures.
   Handle(OpenGl_RaytraceFilter) myRaytraceFilter;
 
-  //! Redraw the scene using OpenGL rasterization or raytracing?
+  //! Redraw the scene using OpenGL rasterization or ray-tracing?
   Standard_Boolean myToRedrawGL;
 
 protected: //! @name protected fields
index 9fc7898..cd02fc4 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
@@ -148,7 +127,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 +182,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()));
@@ -241,54 +220,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 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 aMaxRefl = Max (theMaterial.Diffuse.x() + theMaterial.Specular.x(),
+                                      Max (theMaterial.Diffuse.y() + theMaterial.Specular.y(),
+                                           theMaterial.Diffuse.z() + theMaterial.Specular.z()));
 
-  const float aReflectionScale = 0.75f / aMaxRefl;
+  const Standard_ShortReal 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);
+
+  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;
+    }
+  }
 
-  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);
+  return Standard_True;
 }
 
 // =======================================================================
@@ -313,7 +368,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 +417,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 +440,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 +455,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 +465,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,7 +503,7 @@ 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();
@@ -478,10 +533,22 @@ OpenGl_TriangleSet* OpenGl_Workspace::AddRaytracePrimitiveArray (const OpenGl_Pr
   }
 #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)
     {
@@ -494,8 +561,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)
@@ -503,7 +570,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));
           }
         }
       }
@@ -514,8 +581,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));
           }
         }
       }
@@ -525,21 +603,37 @@ 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 (aSet->TexCrds.size() != aSet->Vertices.size())
+    {
+      for (Standard_Integer aVertIter = 0; aVertIter < anAttribs->NbElements; ++aVertIter)
+      {
+        aSet->TexCrds.push_back (BVH_Vec2f());
       }
     }
 
-    if (theTransform)
+    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());
       }
     }
 
@@ -864,7 +958,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();
 
@@ -902,9 +996,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));
   }
 
@@ -963,12 +1058,12 @@ 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);
       }
     }
   }
@@ -1115,6 +1210,32 @@ Standard_Boolean OpenGl_Workspace::SafeFailBack (const TCollection_ExtendedStrin
   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
@@ -1149,9 +1270,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;
     }
 
@@ -1170,14 +1291,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;
@@ -1212,15 +1326,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);
-
+                                GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB,
+                                "Ray-tracing requires OpenGL 3.1 and higher");
+      return Standard_False;
+    }
+    else if (!myGlContext->arbTboRGB32)
+    {
+      myGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
+                                GL_DEBUG_TYPE_ERROR_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB,
+                                "Ray-tracing requires OpenGL 4.0+ or GL_ARB_texture_buffer_object_rgb32 extension");
       return Standard_False;
     }
 
-    myRaytraceParameters.TraceDepth = theCView.RenderParams.RaytracingDepth;
+    myRaytraceParameters.NbBounces = theCView.RenderParams.RaytracingDepth;
 
     TCollection_AsciiString aFolder = Graphic3d_ShaderProgram::ShadersFolder();
 
@@ -1240,14 +1359,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;
@@ -1394,15 +1506,17 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
       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);
@@ -1434,23 +1548,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");
@@ -1459,7 +1567,14 @@ Standard_Boolean OpenGl_Workspace::InitRaytraceResources (const Graphic3d_CView&
       myUniformLocations[anIndex][OpenGl_RT_uSamples] =
         aShaderProgram->GetUniformLocation (myGlContext, "uSamples");
 
-      myUniformLocations[anIndex][OpenGl_RT_uEnvironmentEnable] =
+      myUniformLocations[anIndex][OpenGl_RT_uTextures] =
+        aShaderProgram->GetUniformLocation (myGlContext, "uTextureSamplers");
+
+      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");
     }
 
@@ -1535,6 +1650,7 @@ void OpenGl_Workspace::ReleaseRaytraceResources()
 
   NullifyResource (myGlContext, myGeometryVertexTexture);
   NullifyResource (myGlContext, myGeometryNormalTexture);
+  NullifyResource (myGlContext, myGeometryTexCrdTexture);
   NullifyResource (myGlContext, myGeometryTriangTexture);
   NullifyResource (myGlContext, mySceneTransformTexture);
 
@@ -1559,6 +1675,22 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
     return Standard_False;
   }
 
+  /////////////////////////////////////////////////////////////////////////////
+  // Prepare OpenGL textures
+
+  if (myGlContext->arbTexBindless != NULL)
+  {
+    // 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 get OpenGL texture handles" << std::endl;
+#endif
+      return Standard_False;
+    }
+  }
+
   /////////////////////////////////////////////////////////////////////////////
   // Create OpenGL texture buffers
 
@@ -1588,8 +1720,8 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
     myObjectMaxPointTexture = new OpenGl_TextureBufferArb;
 
     if (!myObjectNodeInfoTexture->Create (myGlContext)
-      || !myObjectMinPointTexture->Create (myGlContext)
-      || !myObjectMaxPointTexture->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;
@@ -1602,11 +1734,13 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
   {
     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;
@@ -1631,16 +1765,16 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
   /////////////////////////////////////////////////////////////////////////////
   // Write top-level BVH buffers
 
-  const NCollection_Handle<BVH_Tree<Standard_ShortReal, 4> >& aBVH = myRaytraceGeometry.BVH();
+  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, 4, GLsizei (aBVH->MinPointBuffer().size()),
+    aResult &= mySceneMinPointTexture->Init (myGlContext, 3, GLsizei (aBVH->MinPointBuffer().size()),
                                              reinterpret_cast<const GLfloat*> (&aBVH->MinPointBuffer().front()));
-    aResult &= mySceneMaxPointTexture->Init (myGlContext, 4, GLsizei (aBVH->MaxPointBuffer().size()),
+    aResult &= mySceneMaxPointTexture->Init (myGlContext, 3, GLsizei (aBVH->MaxPointBuffer().size()),
                                              reinterpret_cast<const GLfloat*> (&aBVH->MaxPointBuffer().front()));
   }
   if (!aResult)
@@ -1655,7 +1789,6 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
   // Write transform buffer
 
   BVH_Mat4f* aNodeTransforms = new BVH_Mat4f[myRaytraceGeometry.Size()];
-  BVH_Mat4f anIdentity;
 
   for (Standard_Integer anElemIndex = 0; anElemIndex < myRaytraceGeometry.Size(); ++anElemIndex)
   {
@@ -1669,13 +1802,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
@@ -1703,9 +1835,12 @@ Standard_Boolean OpenGl_Workspace::UploadRaytraceData()
 
   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 &= myObjectNodeInfoTexture->Init (
+      myGlContext, 4, GLsizei (aTotalBVHNodesNb), static_cast<const GLuint*>  (NULL));
+    aResult &= myObjectMinPointTexture->Init (
+      myGlContext, 3, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
+    aResult &= myObjectMaxPointTexture->Init (
+      myGlContext, 3, GLsizei (aTotalBVHNodesNb), static_cast<const GLfloat*> (NULL));
   }
 
   if (!aResult)
@@ -1718,13 +1853,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)
@@ -1778,6 +1918,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()));
     }
@@ -1802,10 +1944,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
@@ -1827,26 +1973,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;
 
@@ -1876,11 +2024,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);
@@ -1892,10 +2040,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;
 
@@ -1903,10 +2051,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;
 
@@ -1931,6 +2079,80 @@ 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 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 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 << "Error: Failed to set uniform state for ray-tracing program" << theProgramIndex << std::endl;
+#endif
+  }
+
+  return aResult;
+}
+
 // =======================================================================
 // function : RunRaytraceShaders
 // purpose  : Runs ray-tracing shader programs
@@ -1940,7 +2162,7 @@ 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);
@@ -1951,6 +2173,7 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
   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);
@@ -1968,39 +2191,12 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
 
   myGlContext->BindProgram (myRaytraceProgram);
 
-  Standard_Integer aLightSourceBufferSize =
-    static_cast<Standard_Integer> (myRaytraceGeometry.Sources.size());
-
-  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);
+  SetUniformState (theCView,
+                   theOrigins,
+                   theDirects,
+                   theUnviewMat,
+                   0, // ID of RT program
+                   myRaytraceProgram);
 
   myGlContext->core20fwd->glEnableVertexAttribArray (Graphic3d_TOA_POS);
   {
@@ -2008,7 +2204,7 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
     myGlContext->core15fwd->glDrawArrays (GL_TRIANGLES, 0, 6);
   }
   myGlContext->core20fwd->glDisableVertexAttribArray (Graphic3d_TOA_POS);
-  
+
   if (!theCView.RenderParams.IsAntialiasingEnabled)
   {
     myGlContext->BindProgram (NULL);
@@ -2023,10 +2219,11 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
     myObjectNodeInfoTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectNodeInfoTexture);
     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);
 
@@ -2037,36 +2234,12 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
 
   myGlContext->BindProgram (myPostFSAAProgram);
 
-  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);
+  SetUniformState (theCView,
+                   theOrigins,
+                   theDirects,
+                   theUnviewMat,
+                   1, // ID of FSAA program
+                   myPostFSAAProgram);
 
   const Standard_ShortReal aMaxOffset = 0.559017f;
   const Standard_ShortReal aMinOffset = 0.186339f;
@@ -2136,10 +2309,11 @@ Standard_Boolean OpenGl_Workspace::RunRaytraceShaders (const Graphic3d_CView& th
   myObjectNodeInfoTexture->UnbindTexture     (myGlContext, GL_TEXTURE0 + OpenGl_RT_ObjectNodeInfoTexture);
   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);
 
@@ -2168,24 +2342,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))
@@ -2193,22 +2356,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);
@@ -2256,14 +2410,30 @@ Standard_Boolean OpenGl_Workspace::Raytrace (const Graphic3d_CView& theCView,
   {
     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);
   }
 
index 1b860c3..d0c002e 100644 (file)
@@ -1,3 +1,7 @@
+#ifdef USE_TEXTURES
+  #extension GL_ARB_bindless_texture : require
+#endif
+
 //! Normalized pixel coordinates.
 in vec2 vPixel;
 
@@ -20,7 +24,8 @@ uniform vec3 uDirectRT;
 uniform vec3 uDirectRB;
 
 //! Inverse model-view-projection matrix.
-uniform mat4 uInvModelProj;
+uniform mat4 uUnviewMat;
+
 //! Texture buffer of data records of high-level BVH nodes.
 uniform isamplerBuffer uSceneNodeInfoTexture;
 //! Texture buffer of minimum points of high-level BVH nodes.
@@ -41,6 +46,10 @@ uniform samplerBuffer uObjectMaxPointTexture;
 uniform samplerBuffer uGeometryVertexTexture;
 //! Texture buffer of vertex normals.
 uniform samplerBuffer uGeometryNormalTexture;
+#ifdef USE_TEXTURES
+  //! Texture buffer of per-vertex UV-coordinates.
+  uniform samplerBuffer uGeometryTexCrdTexture;
+#endif
 //! Texture buffer of triangle indices.
 uniform isamplerBuffer uGeometryTriangTexture;
 
@@ -73,6 +82,11 @@ uniform float uSceneRadius;
 //! Scene epsilon to prevent self-intersections.
 uniform float uSceneEpsilon;
 
+#ifdef USE_TEXTURES
+  //! Unique 64-bit handles of OpenGL textures.
+  uniform sampler2D uTextureSamplers[MAX_TEX_NUMBER];
+#endif
+
 /////////////////////////////////////////////////////////////////////////////////////////
 // Specific data types
   
@@ -108,7 +122,6 @@ struct SIntersect
 #define AXIS_Y vec3 (0.0f, 1.0f, 0.0f)
 #define AXIS_Z vec3 (0.0f, 0.0f, 1.0f)
 
-
 // =======================================================================
 // function : MatrixRowMultiplyDir
 // purpose  : Multiplies a vector by matrix
@@ -171,7 +184,6 @@ SRay GenerateRay (in vec2 thePixel)
   vec3 aDirection = normalize (mix (aD0, aD1, thePixel.y));
 
   return SRay (mix (aP0, aP1, thePixel.y), aDirection);
-
 }
 
 // =======================================================================
@@ -187,7 +199,7 @@ float ComputeOpenGlDepth (in SRay theRay)
                       2.0f * vPixel.y - 1.0f,
                       2.0f * anOpenGlDepth - 1.0f,
                       1.0f);
-  vec4 aFinal = uInvModelProj * aPoint;
+  vec4 aFinal = uUnviewMat * aPoint;
   aFinal.xyz *= 1.f / aFinal.w;
 
   return (anOpenGlDepth < 1.f) ? length (aFinal.xyz - theRay.Origin) : MAXFLOAT;
@@ -334,7 +346,7 @@ ivec4 ObjectNearestHit (in int theBVHOffset, in int theVrtOffset, in int theTrgO
         {
           if (aHead == theSentinel)
             return aTriIndex;
-            
+
           aNode = Stack[aHead--];
         }
       }
@@ -377,13 +389,16 @@ ivec4 ObjectNearestHit (in int theBVHOffset, in int theVrtOffset, in int theTrgO
   return aTriIndex;
 }
 
-#define MATERIAL_AMBN(index) (7 * index + 0)
-#define MATERIAL_DIFF(index) (7 * index + 1)
-#define MATERIAL_SPEC(index) (7 * index + 2)
-#define MATERIAL_EMIS(index) (7 * index + 3)
-#define MATERIAL_REFL(index) (7 * index + 4)
-#define MATERIAL_REFR(index) (7 * index + 5)
-#define MATERIAL_TRAN(index) (7 * index + 6)
+#define MATERIAL_AMBN(index) (11 * index + 0)
+#define MATERIAL_DIFF(index) (11 * index + 1)
+#define MATERIAL_SPEC(index) (11 * index + 2)
+#define MATERIAL_EMIS(index) (11 * index + 3)
+#define MATERIAL_REFL(index) (11 * index + 4)
+#define MATERIAL_REFR(index) (11 * index + 5)
+#define MATERIAL_TRAN(index) (11 * index + 6)
+#define MATERIAL_TRS1(index) (11 * index + 7)
+#define MATERIAL_TRS2(index) (11 * index + 8)
+#define MATERIAL_TRS3(index) (11 * index + 9)
 
 // =======================================================================
 // function : ObjectAnyHit
@@ -408,7 +423,7 @@ float ObjectAnyHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffse
       float aTimeOut;
       float aTimeLft;
       float aTimeRgh;
-      
+
       aData.y += theBVHOffset;
       aData.z += theBVHOffset;
   
@@ -469,7 +484,7 @@ float ObjectAnyHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffse
     {
       vec3 aNormal;
       vec2 aParams;
-      
+
       for (int anIdx = aData.y; anIdx <= aData.z; ++anIdx)
       {
         ivec4 aTriangle = texelFetch (uGeometryTriangTexture, anIdx + theTrgOffset);
@@ -495,7 +510,7 @@ float ObjectAnyHit (in int theBVHOffset, in int theVrtOffset, in int theTrgOffse
           return 0.0f;
 #endif
       }
-      
+
 #ifdef TRANSPARENT_SHADOWS
       if (aHead == theSentinel || aFactor < 0.1f)
         return aFactor;
@@ -534,12 +549,12 @@ ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theH
     {
       vec3 aNodeMin = texelFetch (uSceneMinPointTexture, aNode).xyz;
       vec3 aNodeMax = texelFetch (uSceneMaxPointTexture, aNode).xyz;
-      
+
       vec3 aTime0 = (aNodeMin - theRay.Origin) * theInverse;
       vec3 aTime1 = (aNodeMax - theRay.Origin) * theInverse;
-      
+
       vec3 aTimes = min (aTime0, aTime1);
-      
+
       if (max (aTimes.x, max (aTimes.y, aTimes.z)) < theHit.Time)
       {
         // fetch object transformation
@@ -576,7 +591,7 @@ ivec4 SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect theH
       
       if (aHead < 0)
         return aHitObject;
-            
+
       aNode = Stack[aHead--];
     }
     else // if inner node
@@ -684,11 +699,11 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)
 #else
       bool isShadow = 0.0f == ObjectAnyHit (
         aData.y, aData.z, aData.w, aTrsfRay, aTrsfInverse, theDistance, aHead);
-        
+
       if (aHead < 0 || isShadow)
         return isShadow ? 0.0f : 1.0f;
 #endif
-            
+
       aNode = Stack[aHead--];
     }
     else // if inner node
@@ -751,7 +766,7 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)
       }
     }
   }
-  
+
 #ifdef TRANSPARENT_SHADOWS
   return aFactor;
 #else
@@ -768,9 +783,9 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)
 vec2 Latlong (in vec3 thePoint, in float theRadius)
 {
   float aPsi = acos (-thePoint.z / theRadius);
-  
+
   float aPhi = atan (thePoint.y, thePoint.x) + PI;
-  
+
   return vec2 (aPhi * 0.1591549f,
                aPsi * 0.3183098f);
 }
@@ -784,12 +799,29 @@ vec3 SmoothNormal (in vec2 theUV, in ivec4 theTriangle)
   vec3 aNormal0 = texelFetch (uGeometryNormalTexture, theTriangle.x).xyz;
   vec3 aNormal1 = texelFetch (uGeometryNormalTexture, theTriangle.y).xyz;
   vec3 aNormal2 = texelFetch (uGeometryNormalTexture, theTriangle.z).xyz;
-  
+
   return normalize (aNormal1 * theUV.x +
                     aNormal2 * theUV.y +
                     aNormal0 * (1.0f - theUV.x - theUV.y));
 }
 
+// =======================================================================
+// function : SmoothUV
+// purpose  : Interpolates UV coordinates across the triangle
+// =======================================================================
+#ifdef USE_TEXTURES
+vec2 SmoothUV (in vec2 theUV, in ivec4 theTriangle)
+{
+  vec2 aTexCrd0 = texelFetch (uGeometryTexCrdTexture, theTriangle.x).st;
+  vec2 aTexCrd1 = texelFetch (uGeometryTexCrdTexture, theTriangle.y).st;
+  vec2 aTexCrd2 = texelFetch (uGeometryTexCrdTexture, theTriangle.z).st;
+
+  return aTexCrd1 * theUV.x +
+         aTexCrd2 * theUV.y +
+         aTexCrd0 * (1.0f - theUV.x - theUV.y);
+}
+#endif
+
 // =======================================================================
 // function : Refract
 // purpose  : Computes refraction ray (also handles TIR)
@@ -799,21 +831,21 @@ vec3 Refract (in vec3 theInput,
               in float theRefractIndex,
               in float theInvRefractIndex)
 {
-  float aNdotI  = dot (theInput, theNormal);
-  
+  float aNdotI = dot (theInput, theNormal);
+
   float anIndex = aNdotI < 0.0f
                 ? theInvRefractIndex
                 : theRefractIndex;
-                
+
   float aSquare = anIndex * anIndex * (1.0f - aNdotI * aNdotI);
-  
+
   if (aSquare > 1.0f)
   {
     return reflect (theInput, theNormal);
   }
-  
+
   float aNdotT = sqrt (1.0f - aSquare);
-  
+
   return normalize (anIndex * theInput -
     (anIndex * aNdotI + (aNdotI < 0.0f ? aNdotT : -aNdotT)) * theNormal);
 }
@@ -828,7 +860,7 @@ vec3 Refract (in vec3 theInput,
 
 // =======================================================================
 // function : Radiance
-// purpose  : Computes color of specified ray
+// purpose  : Computes color along the given ray
 // =======================================================================
 vec4 Radiance (in SRay theRay, in vec3 theInverse)
 {
@@ -839,9 +871,7 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse)
 
   float anOpenGlDepth = ComputeOpenGlDepth (theRay);
 
-  vec3 aViewDir = theRay.Direct;
-
-  for (int aDepth = 0; aDepth < TRACE_DEPTH; ++aDepth)
+  for (int aDepth = 0; aDepth < NB_BOUNCES; ++aDepth)
   {
     SIntersect aHit = SIntersect (MAXFLOAT, vec2 (ZERO), ZERO);
 
@@ -849,82 +879,81 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse)
 
     if (aTriIndex.x == -1)
     {
+      vec4 aColor = vec4 (0.0f, 0.0f, 0.0f, 1.0f);
+
       if (aWeight.w != 0.0f)
       {
-        if (anOpenGlDepth < MAXFLOAT)
-        {
-          vec4 anOpenGlColor = ComputeOpenGlColor (theRay);
-          aResult.xyz += aWeight.xyz * anOpenGlColor.xyz;
-          aWeight.w   *= anOpenGlColor.w;
-        }
-        return vec4 (aResult.x,
-                     aResult.y,
-                     aResult.z,
-                     aWeight.w);
+        if (anOpenGlDepth != MAXFLOAT)
+          aColor = ComputeOpenGlColor (theRay);
       }
-
-      if (bool(uEnvironmentEnable))
+      else if (bool(uEnvironmentEnable))
       {
         float aTime = IntersectSphere (theRay, uSceneRadius);
-        
-        aResult.xyz += aWeight.xyz * textureLod (uEnvironmentMapTexture,
-          Latlong (theRay.Direct * aTime + theRay.Origin, uSceneRadius), 0.0f).xyz;
+
+        aColor = textureLod (uEnvironmentMapTexture, Latlong (
+          theRay.Direct * aTime + theRay.Origin, uSceneRadius), 0.0f);
       }
-      
-      return vec4 (aResult.x,
-                   aResult.y,
-                   aResult.z,
-                   aWeight.w);
+
+      return vec4 (aResult.xyz + aWeight.xyz * aColor.xyz, aWeight.w * aColor.w);
     }
 
     aHit.Normal = normalize (aHit.Normal);
-
-    if (anOpenGlDepth != MAXFLOAT)
-    {
-      float aDepthSlope = dot (theRay.Direct, aHit.Normal);
-      
-      // For polygons that are parallel to the screen plane, the depth slope
-      // is equal to 1, resulting in small polygon offset. For polygons that
-      // that are at a large angle to the screen, the depth slope tends to 1,
-      // resulting in a larger polygon offset
-      float aPolygonOffset = uSceneEpsilon * EPS_SCALE / max (MIN_SLOPE, abs (aDepthSlope));
     
-      if (anOpenGlDepth - aPolygonOffset < aHit.Time)
-      {
-        vec4 aColor = ComputeOpenGlColor (theRay);
-        
-        aResult.xyz += aWeight.xyz * aColor.xyz;
-        aWeight     *= aColor.w;
-        
-        if (all (lessThanEqual (aWeight.xyz, THRESHOLD)))
-        {
-          return vec4 (aResult.x,
-                       aResult.y,
-                       aResult.z,
-                       aWeight.w);
-        }
-      }
+    // For polygons that are parallel to the screen plane, the depth slope
+    // is equal to 1, resulting in small polygon offset. For polygons that
+    // that are at a large angle to the screen, the depth slope tends to 1,
+    // resulting in a larger polygon offset
+    float aPolygonOffset = uSceneEpsilon * min (
+      EPS_SCALE / abs (dot (theRay.Direct, aHit.Normal)), EPS_SCALE / MIN_SLOPE);
+
+    if (anOpenGlDepth - aPolygonOffset < aHit.Time)
+    {
+      vec4 aColor = ComputeOpenGlColor (theRay);
+
+      aResult += aWeight.xyz * aColor.xyz;
+      aWeight *= aColor.w;
     }
 
     vec3 aPoint = theRay.Direct * aHit.Time + theRay.Origin;
-    
+
     vec3 aAmbient  = texelFetch (
       uRaytraceMaterialTexture, MATERIAL_AMBN (aTriIndex.w)).rgb;
-    vec3 aDiffuse  = texelFetch (
-      uRaytraceMaterialTexture, MATERIAL_DIFF (aTriIndex.w)).rgb;
+    vec4 aDiffuse  = texelFetch (
+      uRaytraceMaterialTexture, MATERIAL_DIFF (aTriIndex.w));
     vec4 aSpecular = texelFetch (
       uRaytraceMaterialTexture, MATERIAL_SPEC (aTriIndex.w));
     vec4 aOpacity  = texelFetch (
       uRaytraceMaterialTexture, MATERIAL_TRAN (aTriIndex.w));
     vec3 aEmission = texelFetch (
       uRaytraceMaterialTexture, MATERIAL_EMIS (aTriIndex.w)).rgb;
-    
-    vec3 aNormal = SmoothNormal (aHit.UV, aTriIndex);
+
+#ifdef USE_TEXTURES
+    if (aDiffuse.w >= 0.f)
+    {
+      vec4 aTexCoord = vec4 (SmoothUV (aHit.UV, aTriIndex), 0.f, 1.f);
+
+      vec4 aTrsfRow1 = texelFetch (
+        uRaytraceMaterialTexture, MATERIAL_TRS1 (aTriIndex.w));
+      vec4 aTrsfRow2 = texelFetch (
+        uRaytraceMaterialTexture, MATERIAL_TRS2 (aTriIndex.w));
+
+      aTexCoord.st = vec2 (dot (aTrsfRow1, aTexCoord),
+                           dot (aTrsfRow2, aTexCoord));
+
+      vec3 aTexColor = textureLod (
+        uTextureSamplers[int(aDiffuse.w)], aTexCoord.st, 0.f).rgb;
+
+      aDiffuse.rgb *= aTexColor;
+      aAmbient.rgb *= aTexColor;
+    }
+#endif
 
     vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 0);
     vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 1);
     vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, anObjectId * 4 + 2);
 
+    vec3 aNormal = SmoothNormal (aHit.UV, aTriIndex);
+
     aNormal = normalize (MatrixRowMultiplyDir (
       aNormal, aInvTransf0, aInvTransf1, aInvTransf2));
 
@@ -952,11 +981,11 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse)
       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);
       }
       
@@ -964,27 +993,25 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse)
       {
         vec3 aIntensity = vec3 (texelFetch (
           uRaytraceLightSrcTexture, LIGHT_PWR (aLightIdx)));
+
         float aLdotN = dot (aShadow.Direct, aNormal);
-        
+
         if (aOpacity.y > 0.0f)   // force two-sided lighting
           aLdotN = abs (aLdotN); // for transparent surfaces
-          
+
         if (aLdotN > 0.0f)
         {
           float aRdotV = dot (reflect (aShadow.Direct, aNormal), theRay.Direct);
-          
+
           aResult.xyz += aWeight.xyz * (aOpacity.x * aVisibility) * aIntensity *
-            (aDiffuse * aLdotN + aSpecular.xyz * pow (max (0.0f, aRdotV), aSpecular.w));
+            (aDiffuse.rgb * aLdotN + aSpecular.xyz * pow (max (0.0f, aRdotV), aSpecular.w));
         }
       }
     }
-    
-    aResult.xyz += aWeight.xyz * uGlobalAmbient.xyz *
-      aAmbient * aOpacity.x * max (abs (dot (aNormal, theRay.Direct)), 0.5f);
 
-    aResult.xyz += aWeight.xyz * aOpacity.x * aEmission;
-    
+    aResult.xyz += aWeight.xyz * aOpacity.x * (uGlobalAmbient.xyz *
+      aAmbient * max (abs (dot (aNormal, theRay.Direct)), 0.5f) + aEmission);
+
     if (aOpacity.x != 1.0f)
     {
       aWeight *= aOpacity.y;
@@ -994,13 +1021,13 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse)
         theRay.Direct = Refract (theRay.Direct, aNormal, aOpacity.z, aOpacity.w);
 
         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;
-      
+
         aPoint += aHit.Normal * (dot (aHit.Normal, theRay.Direct) >= 0.0f ? uSceneEpsilon : -uSceneEpsilon);
-        
+
         // Disable combining image with OpenGL output
         anOpenGlDepth = MAXFLOAT;
       }
@@ -1013,26 +1040,26 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse)
     {
       aWeight *= bool(uReflectionsEnable) ?
         texelFetch (uRaytraceMaterialTexture, MATERIAL_REFL (aTriIndex.w)) : vec4 (0.0f);
-      
+
       theRay.Direct = reflect (theRay.Direct, aNormal);
-      
+
       if (dot (theRay.Direct, aHit.Normal) < 0.0f)
       {
         theRay.Direct = reflect (theRay.Direct, aHit.Normal);
       }
 
       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;
-      
+
       aPoint += aHit.Normal * (dot (aHit.Normal, theRay.Direct) >= 0.0f ? uSceneEpsilon : -uSceneEpsilon);
 
       // Disable combining image with OpenGL output
       anOpenGlDepth = MAXFLOAT;
     }
-    
+
     if (all (lessThanEqual (aWeight.xyz, THRESHOLD)))
     {
       return vec4 (aResult.x,
@@ -1040,7 +1067,7 @@ vec4 Radiance (in SRay theRay, in vec3 theInverse)
                    aResult.z,
                    aWeight.w);
     }
-    
+
     theRay.Origin = theRay.Direct * uSceneEpsilon + aPoint;
   }
 
diff --git a/tests/v3d/raytrace/textures b/tests/v3d/raytrace/textures
new file mode 100644 (file)
index 0000000..f58f072
--- /dev/null
@@ -0,0 +1,75 @@
+puts "========"
+puts "Ray Tracing - check refraction"
+puts "========"
+
+vinit View1
+vclear
+vrenderparams -rasterization
+vsetdispmode 1
+vsetgradientbg 180 200 255 180 180 180 2
+
+box wall1 1 8 8
+box wall2 1 8 8
+box wall3 16 8 1
+
+psphere S1 1.5
+psphere S2 1.5
+psphere S3 1.5
+
+box B1 -1.5 -1.5 -1.5 2.5 2 3
+box B2 -1.5 -1.5 -1.5 2.5 2 3
+box B3 -1.5 -1.5 -1.5 2.5 2 3
+
+vdisplay S1
+vdisplay S2
+vdisplay S3
+
+vdisplay B1
+vdisplay B2
+vdisplay B3
+
+vdisplay wall1
+vdisplay wall2
+vdisplay wall3
+
+vtexture S1 8
+vtexture S2 2
+vtexture S3 3
+
+vtexture B1 4
+vtexture B2 5
+vtexture B3 6
+
+vsetlocation S1 2 2 4
+vsetlocation S2 -2 2 4
+vsetlocation S3 -6 2 4
+
+vsetlocation B1 2 6 4
+vsetlocation B2 -2 6 4
+vsetlocation B3 -6 6 4
+
+vsetlocation wall1 -10 0 0
+vsetlocation wall2 5 0 0
+vsetlocation wall3 -10 0 -1
+
+vsetmaterial S1 gold
+vsetmaterial S2 silver
+vsetmaterial S3 copper
+
+vsetmaterial B1 steel
+vsetmaterial B2 pewter
+vsetmaterial B3 chrome
+
+vsetmaterial wall1 stone
+vsetmaterial wall2 stone
+vsetmaterial wall3 pewter
+
+vsetcolor wall1 red
+vsetcolor wall2 green
+
+vright
+vturnview 0 -0.3 0
+vfit
+vlight change 0 pos 1 1 1
+vlight add directional
+vrenderparams -raytrace -raydepth 3 -shadows on -reflections -fsaa