]> OCCT Git - occt.git/commitdiff
0027223: Visualization, Ray Tracing - add support of clipping planes CR27223_1
authorNikolay Gavrilov <nikolay.gavrilov@opencascade.com>
Thu, 13 Oct 2022 13:27:50 +0000 (16:27 +0300)
committerNikolay Gavrilov <nikolay.gavrilov@opencascade.com>
Fri, 18 Nov 2022 09:01:42 +0000 (12:01 +0300)
src/Graphic3d/Graphic3d_CStructure.hxx
src/OpenGl/OpenGl_SceneGeometry.cxx
src/OpenGl/OpenGl_SceneGeometry.hxx
src/OpenGl/OpenGl_Structure.cxx
src/OpenGl/OpenGl_Structure.hxx
src/OpenGl/OpenGl_View.hxx
src/OpenGl/OpenGl_View_Raytrace.cxx
src/Shaders/RaytraceBase.fs
tests/opengl/data/raytrace/clip_planes.tcl [new file with mode: 0644]

index 8138cd165f3afc27c48b76d762decece23dc2f5d..7f4bf3068924735a01698b9529bb02919cfb6863 100644 (file)
@@ -101,7 +101,7 @@ public:
   }
 
   //! Pass clip planes to the associated graphic driver structure
-  void SetClipPlanes (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes) { myClipPlanes = thePlanes; }
+  virtual void SetClipPlanes (const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes) { myClipPlanes = thePlanes; }
 
   //! @return bounding box of this presentation
   const Graphic3d_BndBox3d& BoundingBox() const
index a8ceb444b2776a15ae323b67c6f5a64199f5c843..7d321655fe545ece852c921c91b967f27b09b264 100644 (file)
@@ -521,6 +521,18 @@ Standard_Boolean OpenGl_RaytraceGeometry::UpdateTextureHandles (const Handle(Ope
   return Standard_True;
 }
 
+// =======================================================================
+// function : OpenGl_RaytraceClipPlanes
+// purpose  : Creates new set of clipping planes
+// =======================================================================
+OpenGl_RaytraceClipPlanes::OpenGl_RaytraceClipPlanes()
+{
+  for (Standard_Integer aPlaneIdx = 0; aPlaneIdx < MAX_PLANE_NUMBER; ++aPlaneIdx)
+  {
+    myClipPlanes[aPlaneIdx * 2] = BVH_Vec4f(-1.f, -1.f, -1.f, -1.f);
+  }
+}
+
 namespace OpenGl_Raytrace
 {
   // =======================================================================
index 05705962f5c6570fa5a6075f5ec96c45035eff2c..a1821017df5c813f21e65a7298a536f8a57bba50 100644 (file)
@@ -169,6 +169,133 @@ private:
 
 };
 
+//! Set of clipping planes specific for OpenGL primitive array.
+class OpenGl_RaytraceClipPlanes
+{
+public:
+
+  //! Maximum number of clipping planes used in ray-tracing for each
+  //! OpenGL primitive array. This is not implementation restriction,
+  //! but it is reasonable to limit max number of planes in order to
+  //! simplify GLSL data representation.
+  static const Standard_Integer MAX_PLANE_NUMBER = 8;
+
+  //! State of clipping plane.
+  enum ClipPlaneState {
+
+    CLIP_PLANE_OFF = -1,  //!< plane is deactivated
+    CLIP_PLANE_VIEW = 0,  //!< plane is in view space
+    CLIP_PLANE_WORLD = 1   //!< plane is in world space
+  };
+
+  //! Wrapper for clipping plane configuration.
+  class ClipPlane
+  {
+  public:
+
+    //! Creates new clipping plane wrapper.
+    ClipPlane(BVH_Vec4f& theSettings,
+      BVH_Vec4f& theEquation) : mySettings(theSettings),
+      myEquation(theEquation) {}
+
+    //! Sets 4D equation vector for clipping plane.
+    void SetEquation(const BVH_Vec4d& theEquation, const ClipPlaneState theState = CLIP_PLANE_WORLD)
+    {
+      for (Standard_Integer anIndex = 0; anIndex < 4; ++anIndex)
+      {
+        myEquation[anIndex] = static_cast<Standard_ShortReal> (theEquation[anIndex]);
+      }
+
+      SetState(theState);
+    }
+
+    //! Returns state of clipping plane.
+    ClipPlaneState State()
+    {
+      return static_cast<ClipPlaneState> ((int)mySettings.x());
+    }
+
+    //! Sets state of clipping plane.
+    void SetState(const ClipPlaneState theState)
+    {
+      mySettings.x() = static_cast<Standard_ShortReal> (theState);
+    }
+
+  private:
+
+    //! Settings of clipping plane.
+    BVH_Vec4f& mySettings;
+
+    //! 4D equation vector of clipping plane.
+    BVH_Vec4f& myEquation;
+  };
+
+public:
+
+  //! Creates new set of clipping planes.
+  OpenGl_RaytraceClipPlanes();
+
+  //! Returns clipping plane for the given index.
+  ClipPlane operator[] (const Standard_Integer theIndex)
+  {
+    return ClipPlane(myClipPlanes[theIndex * 2 + 0],
+      myClipPlanes[theIndex * 2 + 1]);
+  }
+
+  //! Returns packed (serialized) representation of clipping planes set.
+  const Standard_ShortReal* Packed()
+  {
+    return reinterpret_cast<Standard_ShortReal*> (this);
+  }
+
+private:
+
+  //! Serialized clipping planes storage.
+  BVH_Vec4f myClipPlanes[MAX_PLANE_NUMBER * 2];
+
+};
+
+//! Stores transform properties of ray-tracing object.
+class OpenGl_RaytraceTransform : public BVH_Transform<Standard_ShortReal, 4>
+{
+public:
+
+  //! Value of invalid clipping plane set.
+  static const Standard_Integer NO_CLIPPING = -1;
+
+public:
+
+  //! Creates new identity transformation.
+  OpenGl_RaytraceTransform() : BVH_Transform<Standard_ShortReal, 4>()
+  {
+    myClipSetID = NO_CLIPPING; // no clipping by default
+  }
+
+  //! Creates new transformation with specified matrix.
+  OpenGl_RaytraceTransform(const BVH_Mat4f& theTransform) : BVH_Transform<Standard_ShortReal, 4>(theTransform)
+  {
+    myClipSetID = NO_CLIPPING; // no clipping by default
+  }
+
+  //! Returns ID of associated set of clipping planes.
+  Standard_Integer ClipSetID() const
+  {
+    return myClipSetID;
+  }
+
+  //! Sets ID of associated set of clipping planes.
+  void SetClipSetID(const Standard_Integer theClipSetID)
+  {
+    myClipSetID = theClipSetID;
+  }
+
+protected:
+
+  //! ID of associated set of clipping planes.
+  Standard_Integer myClipSetID;
+
+};
+
 //! Stores geometry of ray-tracing scene.
 class OpenGl_RaytraceGeometry : public BVH_Geometry<Standard_ShortReal, 3>
 {
@@ -192,6 +319,10 @@ public:
   //! Array of 'front' material properties.
   std::vector<OpenGl_RaytraceMaterial,
     NCollection_StdAllocator<OpenGl_RaytraceMaterial> > Materials;
+  
+  //! Array of sets of clipping plane parameters.
+  std::vector<OpenGl_RaytraceClipPlanes,
+    NCollection_StdAllocator<OpenGl_RaytraceClipPlanes> > ClipPlanes;
 
   //! Global ambient from all light sources.
   BVH_Vec4f Ambient;
index d5c3c5270b2ca11955d8c346a34325eeb7a5b7f8..798ca89b2f0e78de0472f872e2ba8fa6430ff2e4 100644 (file)
@@ -236,6 +236,20 @@ Standard_Boolean OpenGl_Structure::IsRaytracable() const
      &&  myInstancedStructure->IsRaytracable();
 }
 
+// =======================================================================
+// function : SetClipPlanes
+// purpose  :
+// =======================================================================
+void OpenGl_Structure::SetClipPlanes(const Handle(Graphic3d_SequenceOfHClipPlane)&thePlanes)
+{
+  Graphic3d_CStructure::SetClipPlanes(thePlanes);
+
+  if (IsRaytracable())
+  {
+    ++myModificationState;
+  }
+}
+
 // =======================================================================
 // function : UpdateRaytracableState
 // purpose  :
index b7703237831efe8a7a52aef5cbd76ddbf7deb061..bf1eacac390088a06a52b118bdb34ef422ecd0b6 100644 (file)
@@ -132,6 +132,9 @@ protected:
   //! Updates ray-tracable status for structure and its parents.
   void UpdateStateIfRaytracable (const Standard_Boolean toCheck = Standard_True) const;
 
+  //! Pass clip planes to the associated graphic driver structure
+  void SetClipPlanes(const Handle(Graphic3d_SequenceOfHClipPlane)& thePlanes);
+
   //! Renders groups of structure without applying any attributes (i.e. transform, material etc).
   //! @param theWorkspace current workspace
   //! @param theHasClosed flag will be set to TRUE if structure contains at least one group of closed primitives
index 17768a06d13b2e91ac03685fbd68db8d339c1dde..57fe01cb1f651f481a0e6d7c556104be73367470 100644 (file)
@@ -574,6 +574,7 @@ protected: //! @name data types related to ray-tracing
     OpenGl_RT_uSceneEps,
     OpenGl_RT_uLightAmbnt,
     OpenGl_RT_uLightCount,
+    OpenGl_RT_uNbClipPlanes,
 
     // background params
     OpenGl_RT_uBackColorTop,
@@ -1019,6 +1020,8 @@ protected: //! @name fields related to ray-tracing
   Handle(OpenGl_TextureBuffer) myRaytraceMaterialTexture;
   //! Texture buffer of light source properties.
   Handle(OpenGl_TextureBuffer) myRaytraceLightSrcTexture;
+  //! Texture buffer of clipping planes parameters.
+  Handle(OpenGl_TextureBuffer) myRaytraceClippingTexture;
 
   //! 1st framebuffer (FBO) to perform adaptive FSAA.
   //! Used in compatibility mode (no adaptive sampling).
index 299b7b014bc8f71323b0ee8518a2968850f77502..b49c2560784786033ff4aabf13ecde7058d09a2d 100644 (file)
@@ -65,11 +65,12 @@ namespace
 
   static const Graphic3d_TextureUnit OpenGl_RT_RaytraceMaterialTexture = Graphic3d_TextureUnit_9;
   static const Graphic3d_TextureUnit OpenGl_RT_RaytraceLightSrcTexture = Graphic3d_TextureUnit_10;
+  static const Graphic3d_TextureUnit OpenGl_RT_RaytraceClippingTexture = Graphic3d_TextureUnit_11;
 
-  static const Graphic3d_TextureUnit OpenGl_RT_FsaaInputTexture = Graphic3d_TextureUnit_11;
-  static const Graphic3d_TextureUnit OpenGl_RT_PrevAccumTexture = Graphic3d_TextureUnit_12;
+  static const Graphic3d_TextureUnit OpenGl_RT_FsaaInputTexture = Graphic3d_TextureUnit_12;
+  static const Graphic3d_TextureUnit OpenGl_RT_PrevAccumTexture = Graphic3d_TextureUnit_13;
 
-  static const Graphic3d_TextureUnit OpenGl_RT_RaytraceDepthTexture = Graphic3d_TextureUnit_13;
+  static const Graphic3d_TextureUnit OpenGl_RT_RaytraceDepthTexture = Graphic3d_TextureUnit_14;
 }
 
 // =======================================================================
@@ -512,6 +513,47 @@ Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure*
                                                  const Handle(TopLoc_Datum3D)&  theTrsf,
                                                  const Handle(OpenGl_Context)&  theGlContext)
 {
+  // ID of clipping plane set
+  Standard_Integer aClipSetID = OpenGl_RaytraceTransform::NO_CLIPPING;
+  // Collect clipping planes of structure scope
+  if (!theStructure->ClipPlanes().IsNull())
+  //if (!theStructure->ClipPlanes()->IsEmpty())
+  {
+    NCollection_Handle<Graphic3d_SequenceOfHClipPlane> aUserPlanes;
+
+    for (Graphic3d_SequenceOfHClipPlane::Iterator aClipIter(theStructure->ClipPlanes()); aClipIter.More(); aClipIter.Next())
+    {
+      const Handle(Graphic3d_ClipPlane)& aClipPlane = aClipIter.Value();
+
+      if (aClipPlane->IsOn())
+      {
+        if (aUserPlanes.IsNull())
+        {
+          aUserPlanes = new Graphic3d_SequenceOfHClipPlane();
+        }
+
+        aUserPlanes->Append(aClipPlane);
+      }
+    }
+
+    if (!aUserPlanes.IsNull())
+    {
+      myRaytraceGeometry.ClipPlanes.push_back(OpenGl_RaytraceClipPlanes());
+
+      Standard_Integer aPlaneIdx = 0;
+      for (Graphic3d_SequenceOfHClipPlane::Iterator aClipIter(*aUserPlanes); aClipIter.More(); aClipIter.Next(), ++aPlaneIdx)
+      {
+        if (myRaytraceGeometry.ClipPlanes.size() >= OpenGl_RaytraceClipPlanes::MAX_PLANE_NUMBER)
+        {
+          break;
+        }
+        myRaytraceGeometry.ClipPlanes.back()[aPlaneIdx].SetEquation(aClipIter.Value()->GetEquation());
+      }
+
+      aClipSetID = static_cast<Standard_Integer> (myRaytraceGeometry.ClipPlanes.size() - 1);
+    }
+  }
+
   OpenGl_Mat4 aMat4;
   for (OpenGl_Structure::GroupIterator aGroupIter (theStructure->Groups()); aGroupIter.More(); aGroupIter.Next())
   {
@@ -551,13 +593,19 @@ Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure*
           if (aSetIter != myArrayToTrianglesMap.end())
           {
             OpenGl_TriangleSet* aSet = aSetIter->second;
-            opencascade::handle<BVH_Transform<Standard_ShortReal, 4> > aTransform = new BVH_Transform<Standard_ShortReal, 4>();
+            OpenGl_RaytraceTransform* aTransform = new OpenGl_RaytraceTransform;
+            
             if (!theTrsf.IsNull())
             {
               theTrsf->Trsf().GetMat4 (aMat4);
               aTransform->SetTransform (aMat4);
             }
 
+            if (aClipSetID != OpenGl_RaytraceTransform::NO_CLIPPING)
+            {
+              aTransform->SetClipSetID(aClipSetID);
+            }
+
             aSet->SetProperties (aTransform);
             if (aSet->MaterialIndex() != OpenGl_TriangleSet::INVALID_MATERIAL && aSet->MaterialIndex() != aMatID)
             {
@@ -568,13 +616,19 @@ Standard_Boolean OpenGl_View::addRaytraceGroups (const OpenGl_Structure*
           {
             if (Handle(OpenGl_TriangleSet) aSet = addRaytracePrimitiveArray (aPrimArray, aMatID, 0))
             {
-              opencascade::handle<BVH_Transform<Standard_ShortReal, 4> > aTransform = new BVH_Transform<Standard_ShortReal, 4>();
+              OpenGl_RaytraceTransform* aTransform = new OpenGl_RaytraceTransform;
+
               if (!theTrsf.IsNull())
               {
                 theTrsf->Trsf().GetMat4 (aMat4);
                 aTransform->SetTransform (aMat4);
               }
 
+              if (aClipSetID != OpenGl_RaytraceTransform::NO_CLIPPING)
+              {
+                aTransform->SetClipSetID(aClipSetID);
+              }
+
               aSet->SetProperties (aTransform);
               myRaytraceGeometry.Objects().Append (aSet);
             }
@@ -1669,6 +1723,8 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Standard_Integer theS
         "uRaytraceMaterialTexture", OpenGl_RT_RaytraceMaterialTexture);
       aShaderProgram->SetSampler (theGlContext,
         "uRaytraceLightSrcTexture", OpenGl_RT_RaytraceLightSrcTexture);
+      aShaderProgram->SetSampler(theGlContext,
+        "uRaytraceClippingTexture", OpenGl_RT_RaytraceClippingTexture);
 
       if (anIndex == 1)
       {
@@ -1713,6 +1769,8 @@ Standard_Boolean OpenGl_View::initRaytraceResources (const Standard_Integer theS
         aShaderProgram->GetUniformLocation (theGlContext, "uLightCount");
       myUniformLocations[anIndex][OpenGl_RT_uLightAmbnt] =
         aShaderProgram->GetUniformLocation (theGlContext, "uGlobalAmbient");
+      myUniformLocations[anIndex][OpenGl_RT_uNbClipPlanes] =
+        aShaderProgram->GetUniformLocation(theGlContext, "uNbClipPlanes");
 
       myUniformLocations[anIndex][OpenGl_RT_uFsaaOffset] =
         aShaderProgram->GetUniformLocation (theGlContext, "uFsaaOffset");
@@ -1850,6 +1908,7 @@ void OpenGl_View::releaseRaytraceResources (const Handle(OpenGl_Context)& theGlC
 
     nullifyResource (theGlContext, myRaytraceLightSrcTexture);
     nullifyResource (theGlContext, myRaytraceMaterialTexture);
+    nullifyResource (theGlContext, myRaytraceClippingTexture);
 
     myRaytraceGeometry.ReleaseResources (theGlContext);
 
@@ -2190,7 +2249,23 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)&
       return Standard_False;
     }
   }
-  
+
+  /////////////////////////////////////////////////////////////////////////////
+  // Create clip planes buffer
+
+  if (myRaytraceClippingTexture.IsNull()) // create clipping planes buffer
+  {
+    myRaytraceClippingTexture = new OpenGl_TextureBuffer;
+
+    if (!myRaytraceClippingTexture->Create(theGlContext))
+    {
+#ifdef RAY_TRACE_PRINT_INFO
+      std::cout << "Error: Failed to create buffer for clip plane data" << std::endl;
+#endif
+      return Standard_False;
+    }
+  }
+
   /////////////////////////////////////////////////////////////////////////////
   // Write transform buffer
 
@@ -2203,11 +2278,16 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)&
     OpenGl_TriangleSet* aTriangleSet = dynamic_cast<OpenGl_TriangleSet*> (
       myRaytraceGeometry.Objects().ChangeValue (anElemIndex).operator->());
 
-    const BVH_Transform<Standard_ShortReal, 4>* aTransform = dynamic_cast<const BVH_Transform<Standard_ShortReal, 4>* > (aTriangleSet->Properties().get());
+    const OpenGl_RaytraceTransform* aTransform = dynamic_cast<const OpenGl_RaytraceTransform*> (aTriangleSet->Properties().operator->());
+
     Standard_ASSERT_RETURN (aTransform != NULL,
       "OpenGl_TriangleSet does not contain transform", Standard_False);
 
     aNodeTransforms[anElemIndex] = aTransform->Inversed();
+
+    // Note: write clip plane ID in last matrix component, because
+    // the last matrix row is not used for transformation purposes
+    aNodeTransforms[anElemIndex].SetValue(3, 3, aTransform->ClipSetID());
   }
 
   aResult &= mySceneTransformTexture->Init (theGlContext, 4,
@@ -2372,6 +2452,23 @@ Standard_Boolean OpenGl_View::uploadRaytraceData (const Handle(OpenGl_Context)&
     }
   }
 
+  /////////////////////////////////////////////////////////////////////////////
+  // Write clip planes buffer
+
+  if (myRaytraceGeometry.ClipPlanes.size() != 0)
+  {
+    aResult &= myRaytraceClippingTexture->Init(theGlContext, 4,
+      GLsizei(myRaytraceGeometry.ClipPlanes.size() * 16), myRaytraceGeometry.ClipPlanes.front().Packed());
+
+    if (!aResult)
+    {
+#ifdef RAY_TRACE_PRINT_INFO
+      std::cout << "Error: Failed to upload clipping planes buffer" << std::endl;
+#endif
+      return Standard_False;
+    }
+  }
+
   myIsRaytraceDataValid = myRaytraceGeometry.Objects().Size() != 0;
 
 #ifdef RAY_TRACE_PRINT_INFO
@@ -2646,6 +2743,9 @@ Standard_Boolean OpenGl_View::setUniformState (const Standard_Integer        the
   theProgram->SetUniform (theGlContext,
     myUniformLocations[theProgramId][OpenGl_RT_uLightCount], aLightSourceBufferSize);
 
+  theProgram->SetUniform (theGlContext,
+    myUniformLocations[theProgramId][OpenGl_RT_uNbClipPlanes], (int)myRaytraceGeometry.ClipPlanes.size());
+
   // Set array of 64-bit texture handles
   if (theGlContext->arbTexBindless != NULL && myRaytraceGeometry.HasTextures())
   {
@@ -2779,6 +2879,7 @@ void OpenGl_View::bindRaytraceTextures (const Handle(OpenGl_Context)& theGlConte
   mySceneTransformTexture  ->BindTexture (theGlContext, OpenGl_RT_SceneTransformTexture);
   myRaytraceMaterialTexture->BindTexture (theGlContext, OpenGl_RT_RaytraceMaterialTexture);
   myRaytraceLightSrcTexture->BindTexture (theGlContext, OpenGl_RT_RaytraceLightSrcTexture);
+  myRaytraceClippingTexture->BindTexture (theGlContext, OpenGl_RT_RaytraceClippingTexture);
 }
 
 // =======================================================================
@@ -2797,6 +2898,7 @@ void OpenGl_View::unbindRaytraceTextures (const Handle(OpenGl_Context)& theGlCon
   mySceneTransformTexture  ->UnbindTexture (theGlContext, OpenGl_RT_SceneTransformTexture);
   myRaytraceMaterialTexture->UnbindTexture (theGlContext, OpenGl_RT_RaytraceMaterialTexture);
   myRaytraceLightSrcTexture->UnbindTexture (theGlContext, OpenGl_RT_RaytraceLightSrcTexture);
+  myRaytraceClippingTexture->UnbindTexture (theGlContext, OpenGl_RT_RaytraceClippingTexture);
 
   theGlContext->core15fwd->glActiveTexture (GL_TEXTURE0);
 }
index e31b56e6bb8ddb94f8d502e391384410e60e6a69..41fc5da3890f5e36eb09a2c8d6a06981c35a8c64 100644 (file)
@@ -70,6 +70,8 @@ uniform isamplerBuffer uGeometryTriangTexture;
 uniform samplerBuffer uRaytraceMaterialTexture;
 //! Texture buffer of light source properties.
 uniform samplerBuffer uRaytraceLightSrcTexture;
+//! Texture buffer of clipping planes properties.
+uniform samplerBuffer uRaytraceClippingTexture;
 
 #ifdef BACKGROUND_CUBEMAP
   //! Environment cubemap texture.
@@ -87,6 +89,8 @@ uniform samplerBuffer uRaytraceLightSrcTexture;
 uniform int uLightCount;
 //! Intensity of global ambient light.
 uniform vec4 uGlobalAmbient;
+//! Number of clipping planes.
+uniform int uNbClipPlanes;
 
 //! Enables/disables hard shadows.
 uniform int uShadowsEnabled;
@@ -460,6 +464,12 @@ struct SSubTree
 #define MATERIAL_TRS2(index) (19 * index + 8)
 #define MATERIAL_TRS3(index) (19 * index + 9)
 
+#define IS_PLANE_ACTIVE(params) (params.x != -1.F)
+#define IS_PLANE_HIDDEN(params) (params.x == -1.F)
+
+#define PLANE_SETTINGS(trsf, index) (16 * int(trsf.w) + 2 * index + 0)
+#define PLANE_EQUATION(trsf, index) (16 * int(trsf.w) + 2 * index + 1)
+
 #define TRS_OFFSET(treelet) treelet.SubData.x
 #define BVH_OFFSET(treelet) treelet.SubData.y
 #define VRT_OFFSET(treelet) treelet.SubData.z
@@ -512,6 +522,9 @@ STriangle SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect
 
   SSubTree aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT);
 
+  float aClipMax =  MAXFLOAT;
+  float aClipMin = -MAXFLOAT;
+
   for (bool toContinue = true; toContinue; /* none */)
   {
     ivec4 aData = texelFetch (uSceneNodeInfoTexture, aNode);
@@ -620,7 +633,7 @@ STriangle SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect
 
         IntersectTriangle (aSubTree.TrsfRay, aPoints[0], aPoints[1], aPoints[2], aTimeUV, aNormal);
 
-        if (aTimeUV.x < theHit.Time)
+        if (aTimeUV.x > aClipMin && aTimeUV.x < aClipMax && aTimeUV.x < theHit.Time)
         {
           aTriangle.TriIndex = aTriIndex;
           for (int i = 0; i < 3; ++i)
@@ -646,12 +659,33 @@ STriangle SceneNearestHit (in SRay theRay, in vec3 theInverse, inout SIntersect
     }
     else if (aData.x > 0) // switch node
     {
+      aClipMax =  MAXFLOAT;
+      aClipMin = -MAXFLOAT;
+
       aSubTree.SubData = ivec4 (4 * aData.x - 4, aData.yzw); // store BVH sub-root
 
       vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 0);
       vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 1);
       vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 2);
       vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 3);
+      
+      for (int aPlaneIdx = 0; aInvTransf3.w >= 0.0 && aPlaneIdx < uNbClipPlanes; ++aPlaneIdx)
+      {
+        vec4 aSettings = texelFetch (uRaytraceClippingTexture, PLANE_SETTINGS (aInvTransf3, aPlaneIdx));
+        vec4 aEquation = texelFetch (uRaytraceClippingTexture, PLANE_EQUATION (aInvTransf3, aPlaneIdx));
+
+        float aNdotD = -dot (aEquation.xyz, theRay.Direct);
+
+        if (IS_PLANE_ACTIVE (aSettings))
+        {
+          float aPlaneTime = (dot (aEquation.xyz, theRay.Origin) + aEquation.w) / aNdotD;
+
+          if (aNdotD < 0.0)
+            aClipMin = max (aClipMin, aPlaneTime);
+          else
+            aClipMax = min (aClipMax, aPlaneTime);
+        }
+      }
 
       aSubTree.TrsfRay.Direct = MatrixColMultiplyDir (theRay.Direct,
                                                       aInvTransf0,
@@ -689,6 +723,9 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)
   int aStop = -1; // BVH level switch
 
   SSubTree aSubTree = SSubTree (theRay, theInverse, EMPTY_ROOT);
+  
+  float aClipMax =  MAXFLOAT;
+  float aClipMin = -MAXFLOAT;
 
   for (bool toContinue = true; toContinue; /* none */)
   {
@@ -798,12 +835,12 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)
         IntersectTriangle (aSubTree.TrsfRay, aPoint0, aPoint1, aPoint2, aTimeUV, aNormal);
 
 #ifdef TRANSPARENT_SHADOWS
-        if (aTimeUV.x < theDistance)
+        if (aTimeUV.x > aClipMin && aTimeUV.x < aClipMax && aTimeUV.x < theDistance)
         {
           aFactor *= 1.f - texelFetch (uRaytraceMaterialTexture, MATERIAL_TRAN (aTriangle.w)).x;
         }
 #else
-        if (aTimeUV.x < theDistance)
+        if (aTimeUV.x > aClipMin && aTimeUV.x < aClipMax && aTimeUV.x < theDistance)
         {
           aFactor = 0.f;
         }
@@ -822,12 +859,33 @@ float SceneAnyHit (in SRay theRay, in vec3 theInverse, in float theDistance)
     }
     else if (aData.x > 0) // switch node
     {
+      aClipMax =  MAXFLOAT;
+      aClipMin = -MAXFLOAT;
+
       aSubTree.SubData = ivec4 (4 * aData.x - 4, aData.yzw); // store BVH sub-root
 
       vec4 aInvTransf0 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 0);
       vec4 aInvTransf1 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 1);
       vec4 aInvTransf2 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 2);
       vec4 aInvTransf3 = texelFetch (uSceneTransformTexture, TRS_OFFSET (aSubTree) + 3);
+      
+      for (int aPlaneIdx = 0; aInvTransf3.w >= 0.0 && aPlaneIdx < uNbClipPlanes; ++aPlaneIdx)
+      {
+        vec4 aSettings = texelFetch (uRaytraceClippingTexture, PLANE_SETTINGS (aInvTransf3, aPlaneIdx));
+        vec4 aEquation = texelFetch (uRaytraceClippingTexture, PLANE_EQUATION (aInvTransf3, aPlaneIdx));
+
+        float aNdotD = -dot (aEquation.xyz, theRay.Direct);
+
+        if (IS_PLANE_ACTIVE (aSettings))
+        {
+          float aPlaneTime = (dot (aEquation.xyz, theRay.Origin) + aEquation.w) / aNdotD;
+
+          if (aNdotD < 0.0)
+            aClipMin = max (aClipMin, aPlaneTime);
+          else
+            aClipMax = min (aClipMax, aPlaneTime);
+        }
+      }
 
       aSubTree.TrsfRay.Direct = MatrixColMultiplyDir (theRay.Direct,
                                                       aInvTransf0,
diff --git a/tests/opengl/data/raytrace/clip_planes.tcl b/tests/opengl/data/raytrace/clip_planes.tcl
new file mode 100644 (file)
index 0000000..665de40
--- /dev/null
@@ -0,0 +1,90 @@
+pload MODELING VISUALIZATION
+vclear
+vinit name=View1 w=512 h=512
+vglinfo
+
+# setup light sources
+vlight -clear
+vlight -add POSITIONAL -headLight 0 -pos 0.5 0.5 0.85 -smoothRadius 0.06 -intensity 30.0 -name pntlight
+
+vvbo 0
+vsetdispmode 1
+vcamera -persp
+
+# setup outer box
+box b 1 1 1 
+explode b FACE 
+vdisplay -noupdate b_1 b_2 b_3 b_5 b_6
+vlocation -noupdate b_1 -setLocation  1  0  0
+vlocation -noupdate b_2 -setLocation -1  0  0
+vlocation -noupdate b_3 -setLocation  0  1  0
+vlocation -noupdate b_5 -setLocation  0  0  1
+vlocation -noupdate b_6 -setLocation  0  0 -1
+
+vsetmaterial -noupdate b_1 plastic
+vsetmaterial -noupdate b_2 plastic
+vsetmaterial -noupdate b_3 plastic
+vsetmaterial -noupdate b_5 plastic
+vsetmaterial -noupdate b_6 plastic
+vbsdf b_1 -kd 1 0.3 0.3 -ks 0
+vbsdf b_2 -kd 0.3 0.5 1 -ks 0
+vbsdf b_3 -kd 1 -ks 0
+vbsdf b_5 -kd 1 -ks 0
+vbsdf b_6 -kd 1 -ks 0
+
+vfront
+vfit
+
+# setup first inner sphere
+psphere s 0.2
+vdisplay     -noupdate s
+vlocation    -noupdate s -setLocation 0.21 0.5 0.2
+vsetmaterial -noupdate s glass
+vbsdf s -absorpColor 0.8 0.8 1.0
+vbsdf s -absorpCoeff 6
+
+# setup first inner box
+box c 0.3 0.3 0.2
+vdisplay     -noupdate c
+vlocation    -noupdate c -reset -rotate 0 0 0 0 0 1 -30 -translate 0.55 0.5 0.0
+vsetmaterial -noupdate c plastic
+vbsdf c -kd 1.0 0.8 0.2 -ks 0.3 -n
+
+# setup second inner box
+box g 0.25 0.25 0.4
+vdisplay     -noupdate g
+vlocation    -noupdate g -reset -rotate 0 0 0 0 0 1 10 -translate 0.4 0.1 0.0
+vsetmaterial -noupdate g glass
+vbsdf g -absorpColor 0.8 1.0 0.8
+vbsdf g -absorpCoeff 6
+
+# setup second inner sphere
+psphere r 0.1
+vdisplay -noupdate r
+vsetmaterial -noupdate r plastic
+vbsdf r -kd 0.5 0.9 0.3 -ks 0.3 -baseRoughness 0.0 -n
+vbsdf r -baseFresnel Constant 1.0
+vlocation r -setLocation 0.5 0.65 0.1
+
+vclipplane create pln
+vclipplane change pln equation 0 0 1 -0.1
+vclipplane set pln object s
+vclipplane set pln object r
+vclipplane set pln object c
+
+vclipplane create pln2
+vclipplane change pln2 equation 0 0 -1 0.15
+vclipplane set pln2 object s
+vclipplane set pln2 object r
+vclipplane set pln2 object c
+
+
+puts "Trying path tracing mode..."
+vrenderparams -ray -gi -rayDepth 8
+
+puts "Make several path tracing iterations to refine the picture, please wait..."
+vfps 100
+
+vdump $imagedir/${casename}.png
+puts "Done. To improve the image further, or after view manipulations, give command:"
+puts "vfps \[nb_iteratons\] or vrepaint -continuous"