diff --git a/src/Graphic3d/Graphic3d_CStructure.cxx b/src/Graphic3d/Graphic3d_CStructure.cxx
index 7da948ff3e..58bc6e0fb3 100644
--- a/src/Graphic3d/Graphic3d_CStructure.cxx
+++ b/src/Graphic3d/Graphic3d_CStructure.cxx
@@ -27,21 +27,23 @@ IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_CStructure,Standard_Transient)
 //purpose  :
 //=============================================================================
 Graphic3d_CStructure::Graphic3d_CStructure (const Handle(Graphic3d_StructureManager)& theManager)
-: myZLayer         (Graphic3d_ZLayerId_Default),
-  Priority         (Structure_MAX_PRIORITY / 2),
-  PreviousPriority (Structure_MAX_PRIORITY / 2),
-  ContainsFacet    (0),
-  IsInfinite       (0),
-  stick            (0),
-  highlight        (0),
-  visible          (1),
-  HLRValidation    (0),
-  IsForHighlight   (Standard_False),
-  IsMutable        (Standard_False),
-  Is2dText         (Standard_False),
-  myGraphicDriver  (theManager->GraphicDriver()),
-  myIsCulled       (Standard_True),
-  myBndBoxClipCheck(Standard_True)
+: myZLayer            (Graphic3d_ZLayerId_Default),
+  Priority            (Structure_MAX_PRIORITY / 2),
+  PreviousPriority    (Structure_MAX_PRIORITY / 2),
+  ContainsFacet       (0),
+  IsInfinite          (0),
+  stick               (0),
+  highlight           (0),
+  visible             (1),
+  HLRValidation       (0),
+  IsForHighlight      (Standard_False),
+  IsMutable           (Standard_False),
+  Is2dText            (Standard_False),
+  myGraphicDriver     (theManager->GraphicDriver()),
+  myIsCulled          (Standard_True),
+  myBndBoxClipCheck   (Standard_True),
+  myHasGroupZLayer    (Standard_False),
+  myCurrentZLayerMode (Graphic3d_ZLayerId_UNKNOWN)
 {
   Id = myGraphicDriver->NewIdentification();
 }
@@ -85,4 +87,6 @@ void Graphic3d_CStructure::DumpJson (Standard_OStream& theOStream, Standard_Inte
 
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsCulled)
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myBndBoxClipCheck)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myHasGroupZLayer)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myCurrentZLayerMode)
 }
diff --git a/src/Graphic3d/Graphic3d_CStructure.hxx b/src/Graphic3d/Graphic3d_CStructure.hxx
index 6ce2599277..db15b19a99 100644
--- a/src/Graphic3d/Graphic3d_CStructure.hxx
+++ b/src/Graphic3d/Graphic3d_CStructure.hxx
@@ -149,7 +149,19 @@ public:
   Standard_Boolean BndBoxClipCheck() const { return myBndBoxClipCheck; }
 
   //! Enable/disable check of object's bounding box clipping before drawing of object.
-  void SetBndBoxClipCheck(Standard_Boolean theBndBoxClipCheck) { myBndBoxClipCheck = theBndBoxClipCheck; }
+  void SetBndBoxClipCheck (Standard_Boolean theBndBoxClipCheck) { myBndBoxClipCheck = theBndBoxClipCheck; }
+
+  //! Returns TRUE if some groups possess different zlayers; FALSE by default;
+  Standard_Boolean HasGroupZLayer() const { return myHasGroupZLayer; }
+
+  //! Set value defining if some groups possess different zlayers;
+  void SetGroupZLayer (Standard_Boolean theValue) { myHasGroupZLayer = theValue; }
+
+  //! Returns the current zlayer that is being rendered; Returns invalid layer if not initialized;
+  Graphic3d_ZLayerId CurrentZLayerMode() const { return myCurrentZLayerMode; }
+
+  //! Set value defining the current zlayer that is being rendered. Set invalid if not rendering;
+  void SetCurrentZLayerMode (const Graphic3d_ZLayerId theValue) const { myCurrentZLayerMode = theValue; }
 
   //! Checks if the structure should be included into BVH tree or not.
   Standard_Boolean IsAlwaysRendered() const
@@ -232,8 +244,10 @@ protected:
   Handle(Graphic3d_SequenceOfHClipPlane) myClipPlanes;
   Handle(Graphic3d_PresentationAttributes) myHighlightStyle; //! Current highlight style; is set only if highlight flag is true
 
-  mutable Standard_Boolean myIsCulled; //!< A status specifying is structure needs to be rendered after BVH tree traverse
-  Standard_Boolean myBndBoxClipCheck;  //!< Flag responsible for checking of bounding box clipping before drawing of object
+  mutable Standard_Boolean myIsCulled;            //!< A status specifying is structure needs to be rendered after BVH tree traverse
+  Standard_Boolean myBndBoxClipCheck;             //!< Flag responsible for checking of bounding box clipping before drawing of object
+  Standard_Boolean myHasGroupZLayer;              //!< Flag specifying that some groups might have different zlayers
+  mutable Graphic3d_ZLayerId myCurrentZLayerMode; //!< Index of the zlayer that is being used during render stage for groups
 
 public:
 
diff --git a/src/Graphic3d/Graphic3d_CView.cxx b/src/Graphic3d/Graphic3d_CView.cxx
index 2219b947e9..6441f4450c 100644
--- a/src/Graphic3d/Graphic3d_CView.cxx
+++ b/src/Graphic3d/Graphic3d_CView.cxx
@@ -284,6 +284,12 @@ void Graphic3d_CView::ReCompute (const Handle(Graphic3d_Structure)& theStruct)
     InvalidateBVHData (aLayerId);
   }
 
+  if (theStruct->CStructure()->HasGroupZLayer())
+  {
+    updateStructure (theStruct->CStructure(), theStruct->DisplayPriority());
+    return;
+  }
+
   if (!ComputedMode()
    || !IsActive()
    || !theStruct->IsDisplayed())
diff --git a/src/Graphic3d/Graphic3d_CView.hxx b/src/Graphic3d/Graphic3d_CView.hxx
index 07f48f47cb..9c57b756e0 100644
--- a/src/Graphic3d/Graphic3d_CView.hxx
+++ b/src/Graphic3d/Graphic3d_CView.hxx
@@ -540,6 +540,10 @@ public: //! @name obsolete Graduated Trihedron functionality
 
 private:
 
+  //! Updates the structure for display lists of the view.
+  virtual void updateStructure (const Handle(Graphic3d_CStructure)& theStructure,
+                                const Standard_Integer thePriority) = 0;
+
   //! Adds the structure to display lists of the view.
   virtual void displayStructure (const Handle(Graphic3d_CStructure)& theStructure,
                                  const Standard_Integer thePriority) = 0;
diff --git a/src/Graphic3d/Graphic3d_Group.cxx b/src/Graphic3d/Graphic3d_Group.cxx
index 9ea7a7d29b..59f144cb16 100644
--- a/src/Graphic3d/Graphic3d_Group.cxx
+++ b/src/Graphic3d/Graphic3d_Group.cxx
@@ -49,7 +49,8 @@ IMPLEMENT_STANDARD_RTTIEXT(Graphic3d_Group,Standard_Transient)
 Graphic3d_Group::Graphic3d_Group (const Handle(Graphic3d_Structure)& theStruct)
 : myStructure     (theStruct.operator->()),
   myIsClosed      (false),
-  myContainsFacet (false)
+  myContainsFacet (false),
+  myZLayerId      (Graphic3d_ZLayerId_UNKNOWN)
 {
   //
 }
@@ -307,6 +308,21 @@ void Graphic3d_Group::Marker (const Graphic3d_Vertex& thePoint,
   AddPrimitiveArray (aPoints, theToEvalMinMax);
 }
 
+//=======================================================================
+//function : SetZLayer
+//purpose  : Set the value of the ZLayer for the group structure
+//           and update zlayer structures
+//=======================================================================
+void Graphic3d_Group::SetZLayer (const Graphic3d_ZLayerId theLayerId, Standard_Boolean theToUpdate)
+{
+  myZLayerId = theLayerId;
+  myStructure->myCStructure->SetGroupZLayer (Standard_True);
+  if (theToUpdate)
+  {
+    myStructure->ReCompute();
+  }
+}
+
 // =======================================================================
 // function : Text
 // purpose  :
@@ -463,4 +479,5 @@ void Graphic3d_Group::DumpJson (Standard_OStream& theOStream, Standard_Integer t
 
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myIsClosed)
   OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myContainsFacet)
+  OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myZLayerId)
 }
diff --git a/src/Graphic3d/Graphic3d_Group.hxx b/src/Graphic3d/Graphic3d_Group.hxx
index fb6748302e..87a5d8799d 100644
--- a/src/Graphic3d/Graphic3d_Group.hxx
+++ b/src/Graphic3d/Graphic3d_Group.hxx
@@ -32,6 +32,7 @@
 #include <Graphic3d_IndexBuffer.hxx>
 #include <Graphic3d_Buffer.hxx>
 #include <Graphic3d_BoundBuffer.hxx>
+#include <Graphic3d_ZLayerId.hxx>
 #include <gp_Ax2.hxx>
 #include <TCollection_ExtendedString.hxx>
 
@@ -128,6 +129,14 @@ public:
   //! Creates a primitive array with single marker using AddPrimitiveArray().
   Standard_EXPORT void Marker (const Graphic3d_Vertex& thePoint, const Standard_Boolean theToEvalMinMax = Standard_True);
 
+  //! Get ID of Z layer for main presentation.
+  Standard_EXPORT Graphic3d_ZLayerId GetZLayer() const { return myZLayerId; }
+
+  //! Set Z layer ID and update all presentations of the presentable object.
+  //! The layers mechanism allows drawing objects in higher layers in overlay of objects in lower layers.
+  //! @theToUpdate is used to check if the group zlayer setting requires the updating in the zlayers list (FALSE by default).
+  Standard_EXPORT virtual void SetZLayer (const Graphic3d_ZLayerId theLayerId, Standard_Boolean theToUpdate = Standard_False);
+
 public:
 
   //! sets the stencil test to theIsEnabled state;
@@ -294,7 +303,7 @@ protected:
   Graphic3d_BndBox4f   myBounds;        //!< bounding box
   bool                 myIsClosed;      //!< flag indicating closed volume
   bool                 myContainsFacet; //!< flag indicating that this group contains face primitives
-
+  Graphic3d_ZLayerId   myZLayerId;      //!< current zlayer ID for this group
 };
 
 DEFINE_STANDARD_HANDLE(Graphic3d_Group, Standard_Transient)
diff --git a/src/Graphic3d/Graphic3d_Structure.cxx b/src/Graphic3d/Graphic3d_Structure.cxx
index 3aa4780fdb..88eb43b4fb 100644
--- a/src/Graphic3d/Graphic3d_Structure.cxx
+++ b/src/Graphic3d/Graphic3d_Structure.cxx
@@ -1023,7 +1023,7 @@ void Graphic3d_Structure::Update (const bool theUpdateLayer) const
 //function : SetZLayer
 //purpose  :
 //=======================================================================
-void Graphic3d_Structure::SetZLayer (const Graphic3d_ZLayerId theLayerId)
+void Graphic3d_Structure::SetZLayer (const Graphic3d_ZLayerId theLayerId, const Standard_Boolean theToPropagate)
 {
   // if the structure is not displayed, unable to change its display layer
   if (IsDeleted ())
@@ -1031,6 +1031,13 @@ void Graphic3d_Structure::SetZLayer (const Graphic3d_ZLayerId theLayerId)
 
   myStructureManager->ChangeZLayer (this, theLayerId);
   myCStructure->SetZLayer (theLayerId);
+  if (theToPropagate)
+  {
+    for (Graphic3d_SequenceOfGroup::Iterator aGroupIter(Groups()); aGroupIter.More(); aGroupIter.Next())
+    {
+      aGroupIter.Value()->SetZLayer (theLayerId, Standard_True);
+    }
+  }
 }
 
 //=======================================================================
diff --git a/src/Graphic3d/Graphic3d_Structure.hxx b/src/Graphic3d/Graphic3d_Structure.hxx
index facfcd281e..455c4f460d 100644
--- a/src/Graphic3d/Graphic3d_Structure.hxx
+++ b/src/Graphic3d/Graphic3d_Structure.hxx
@@ -135,7 +135,8 @@ public:
   //! allows to display structures presented in higher layers in overlay
   //! of structures in lower layers by switching off z buffer depth
   //! test between layers
-  Standard_EXPORT void SetZLayer (const Graphic3d_ZLayerId theLayerId);
+  //! @theToPropagate - flag to determine if structure zlayer should be the same for every group (TRUE by default.)
+  Standard_EXPORT void SetZLayer (const Graphic3d_ZLayerId theLayerId, const Standard_Boolean theToPropagate = Standard_True);
   
   //! Get Z layer ID of displayed structure.
   //! The method returns -1 if the structure has no ID (deleted from graphic driver).
diff --git a/src/OpenGl/OpenGl_LayerList.cxx b/src/OpenGl/OpenGl_LayerList.cxx
index bd4708de1f..2dfe7bf00d 100644
--- a/src/OpenGl/OpenGl_LayerList.cxx
+++ b/src/OpenGl/OpenGl_LayerList.cxx
@@ -319,6 +319,32 @@ void OpenGl_LayerList::RemoveStructure (const OpenGl_Structure* theStructure)
 
   Standard_Integer aPriority = -1;
 
+  // Check if structure has groups in multiple zlayers.
+  if (theStructure->HasGroupZLayer())
+  {
+    // Remove every reference of this structure from all zlayers
+    for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter(myLayers); aLayerIter.More(); aLayerIter.Next())
+    {
+      const Handle(Graphic3d_Layer)& aLayerEx = aLayerIter.ChangeValue();
+
+      if (aLayerEx->Remove (theStructure, aPriority))
+      {
+        --myNbStructures;
+        if (aLayerEx->IsImmediate())
+        {
+          --myImmediateNbStructures;
+        }
+
+        if (aLayerEx->LayerSettings().IsRaytracable()
+          && theStructure->IsRaytracable())
+        {
+          ++myModifStateOfRaytraceable;
+        }
+      }
+    }
+    return;
+  }
+
   // remove structure from associated list
   // if the structure is not found there,
   // scan through layers and remove it
@@ -658,7 +684,11 @@ void OpenGl_LayerList::renderLayer (const Handle(OpenGl_Workspace)& theWorkspace
       {
         continue;
       }
-
+      // Check if within the structure, there are multiple groups assigned to different zlayers.
+      if (aStruct->HasGroupZLayer())
+      {
+        aStruct->SetCurrentZLayerMode (theLayer.LayerId());
+      }
       aStruct->Render (theWorkspace);
     }
   }
diff --git a/src/OpenGl/OpenGl_Structure.cxx b/src/OpenGl/OpenGl_Structure.cxx
index b7533c16ff..29db041180 100644
--- a/src/OpenGl/OpenGl_Structure.cxx
+++ b/src/OpenGl/OpenGl_Structure.cxx
@@ -388,11 +388,14 @@ void OpenGl_Structure::renderGeometry (const Handle(OpenGl_Workspace)& theWorksp
   {
     myInstancedStructure->renderGeometry (theWorkspace, theHasClosed);
   }
-
   for (OpenGl_Structure::GroupIterator aGroupIter (myGroups); aGroupIter.More(); aGroupIter.Next())
   {
-    theHasClosed = theHasClosed || aGroupIter.Value()->IsClosed();
-    aGroupIter.Value()->Render (theWorkspace);
+    Handle(OpenGl_Group) aGroup = aGroupIter.Value();
+    theHasClosed = theHasClosed || aGroup->IsClosed();
+    if (aGroup->GetZLayer() == CurrentZLayerMode())
+    {
+      aGroup->Render (theWorkspace);
+    }
   }
 }
 
diff --git a/src/OpenGl/OpenGl_View.cxx b/src/OpenGl/OpenGl_View.cxx
index 25e5eb6ab2..5ee6929496 100644
--- a/src/OpenGl/OpenGl_View.cxx
+++ b/src/OpenGl/OpenGl_View.cxx
@@ -763,6 +763,27 @@ void OpenGl_View::FBOChangeViewport (const Handle(Standard_Transient)& theFbo,
   aFrameBuffer->ChangeViewport (theWidth, theHeight);
 }
 
+
+//=======================================================================
+//function : updateStructure
+//purpose  :
+//=======================================================================
+void OpenGl_View::updateStructure (const Handle(Graphic3d_CStructure)& theStructure,
+                                   const Standard_Integer thePriority)
+{
+  if (theStructure->HasGroupZLayer())
+  {
+    static Standard_Integer aDummyPriority;
+    // Remove existing structure references before adding them in case 
+    // there were changes in a group's zlayer.
+    for (NCollection_List<Handle(Graphic3d_Layer)>::Iterator aLayerIter(myZLayers.Layers()); aLayerIter.More(); aLayerIter.Next())
+    {
+      aLayerIter.Value()->Remove (theStructure.get(), aDummyPriority);
+    }
+    displayStructure (theStructure, thePriority);
+  }
+}
+
 //=======================================================================
 //function : displayStructure
 //purpose  :
@@ -770,9 +791,26 @@ void OpenGl_View::FBOChangeViewport (const Handle(Standard_Transient)& theFbo,
 void OpenGl_View::displayStructure (const Handle(Graphic3d_CStructure)& theStructure,
                                     const Standard_Integer              thePriority)
 {
-  const OpenGl_Structure*  aStruct = static_cast<const OpenGl_Structure*> (theStructure.get());
-  const Graphic3d_ZLayerId aZLayer = aStruct->ZLayer();
-  myZLayers.AddStructure (aStruct, aZLayer, thePriority);
+  const OpenGl_Structure* aStruct = static_cast<const OpenGl_Structure*> (theStructure.get());
+  Graphic3d_SequenceOfGroup aSeqGroups = aStruct->Groups();
+  if (aStruct->HasGroupZLayer())
+  {
+    // Add structure reference to the different zlayers that each group is assigned to.
+    NCollection_List<Graphic3d_ZLayerId> aZList;
+    for (OpenGl_Structure::GroupIterator aGroupIter(aSeqGroups); aGroupIter.More(); aGroupIter.Next())
+    {
+      Graphic3d_ZLayerId aLayerId = aGroupIter.Value()->GetZLayer();
+      if (!aZList.Contains(aLayerId))
+      {
+        aZList.Append (aLayerId);
+        myZLayers.AddStructure (aStruct, aLayerId, thePriority);
+      }
+    }
+  }
+  else
+  {
+    myZLayers.AddStructure (aStruct, aStruct->ZLayer(), thePriority);
+  }
 }
 
 //=======================================================================
diff --git a/src/OpenGl/OpenGl_View.hxx b/src/OpenGl/OpenGl_View.hxx
index ebaed8983f..e5a0cd1410 100644
--- a/src/OpenGl/OpenGl_View.hxx
+++ b/src/OpenGl/OpenGl_View.hxx
@@ -429,6 +429,10 @@ protected: //! @name Rendering of GL graphics (with prepared drawing buffer).
 
 private:
 
+  //! Updates the structure for display lists of the view.
+  Standard_EXPORT virtual void updateStructure (const Handle(Graphic3d_CStructure)& theStructure,
+                                                const Standard_Integer thePriority) Standard_OVERRIDE;
+
   //! Adds the structure to display lists of the view.
   Standard_EXPORT virtual void displayStructure (const Handle(Graphic3d_CStructure)& theStructure,
                                                  const Standard_Integer thePriority) Standard_OVERRIDE;
diff --git a/src/ViewerTest/ViewerTest_ObjectCommands.cxx b/src/ViewerTest/ViewerTest_ObjectCommands.cxx
index cf6f8abf5e..b31597675a 100644
--- a/src/ViewerTest/ViewerTest_ObjectCommands.cxx
+++ b/src/ViewerTest/ViewerTest_ObjectCommands.cxx
@@ -107,6 +107,7 @@
 #include <Graphic3d_AttribBuffer.hxx>
 #include <Graphic3d_AspectMarker3d.hxx>
 #include <Graphic3d_Group.hxx>
+#include <Graphic3d_Text.hxx>
 #include <Standard_Real.hxx>
 
 #include <AIS_Circle.hxx>
@@ -6844,6 +6845,142 @@ static int VNormals (Draw_Interpretor& theDI,
   return 0;
 }
 
+//=======================================================================
+//function : vAddGroup
+//purpose  : add group to existing interactive object
+//=======================================================================
+static int vAddGroup (Draw_Interpretor& /*theDI*/, Standard_Integer theNbArgs, const char** theArgVec)
+{
+  const Handle(AIS_InteractiveContext)& aContext = ViewerTest::GetAISContext();
+  const Handle(V3d_View)& aView = ViewerTest::CurrentView();
+  if (aContext.IsNull() || aView.IsNull())
+  {
+    Message::SendFail ("Error: no active viewer");
+    return 1;
+  }
+
+  if (theNbArgs < 3)
+  {
+    Message::SendFail ("Error: wrong number of arguments.");
+    return 1;
+  }
+
+  Standard_Integer anArgIter = 1;
+  Handle(AIS_InteractiveObject) anObj;
+
+  const TCollection_AsciiString aName (theArgVec[anArgIter++]);
+  GetMapOfAIS().Find2 (aName, anObj);
+  if (anObj.IsNull())
+  {
+    Message::SendFail() << "Error: object '" << aName << "' is not displayed";
+    return 1;
+  }
+  // Check for zlayer and color parameters.
+  Quantity_Color aColor(Quantity_NOC_INDIANRED);
+  Graphic3d_ZLayerId aLayerID = anObj->ZLayer();
+  for (Standard_Integer anIter = anArgIter; anIter < theNbArgs; ++anIter)
+  {
+    const TCollection_AsciiString anArg(theArgVec[anIter]);
+    if (anArg == "-zlayer")
+    {
+      if (!ViewerTest::ParseZLayer (theArgVec[++anIter], aLayerID))
+      {
+        Message::SendFail() << "Specified zlayer does not exist.";
+        return 1;
+      }
+      if (aLayerID == Graphic3d_ZLayerId_UNKNOWN)
+      {
+        std::cout << "Warning: you set this group with unknown zlayer.";
+        aLayerID = anObj->ZLayer();
+      }
+    }
+    else if (anArg == "-color")
+    {
+      if (theNbArgs - anIter > 3)
+      {
+        Standard_Integer aNbParsed = Draw::ParseColor (3, theArgVec + anIter + 1, aColor);
+        if (aNbParsed == 0)
+        {
+          Message::SendFail() << "Syntax error for color.";
+          return 1;
+        }
+      }
+      else
+      {
+        std::cout << "\nIncorrect number of color values (RGB).\n";
+      }
+
+    }
+  }
+  // For the given type create primitive.
+  const TCollection_AsciiString aType(theArgVec[anArgIter++]);
+  if (aType == "quad")
+  {
+    if (theNbArgs < 8)
+    {
+      Message::SendFail ("Error: wrong number of arguments for quad group.");
+      return 1;
+    }
+    if (anObj->Presentation().IsNull())
+    {
+      Message::SendFail ("Error: Interactive object does not have current presentation.");
+      return 1;
+    }
+    // Get quad dimensions
+    Handle(Graphic3d_Group) aNewGroup = anObj->Presentation()->NewGroup();
+    Standard_Real aPx = Draw::Atof (theArgVec[anArgIter++]);
+    Standard_Real aPy = Draw::Atof (theArgVec[anArgIter++]);
+    Standard_Real aDx = Draw::Atof (theArgVec[anArgIter++]);
+    Standard_Real aDy = Draw::Atof (theArgVec[anArgIter++]);
+    Standard_Real aZ = Draw::Atof (theArgVec[anArgIter++]);
+
+    aNewGroup->SetZLayer (aLayerID, Standard_True);
+    Handle(Prs3d_LineAspect) anAspectQuadTop = new Prs3d_LineAspect(aColor, (Aspect_TypeOfLine)0, 2.0);
+    aNewGroup->SetGroupPrimitivesAspect (anAspectQuadTop->Aspect());
+    Handle(Graphic3d_ArrayOfTriangles) aPrim = new Graphic3d_ArrayOfTriangles(4, 6, Graphic3d_ArrayFlags_None);
+    aPrim->AddVertex (aPx - aDx, aPy, aZ);
+    aPrim->AddVertex (aPx + aDx, aPy, aZ);
+    aPrim->AddVertex (aPx, aPy + aDy, aZ);
+    aPrim->AddVertex (aPx, aPy - aDy, aZ);
+    aPrim->AddEdges (1, 2, 3);
+    aPrim->AddEdges (1, 2, 4);
+    aNewGroup->AddPrimitiveArray (aPrim);
+  }
+  else if (aType == "text")
+  {
+    if (theNbArgs < 8)
+    {
+      Message::SendFail ("Error: wrong number of arguments for text group.");
+      return 1;
+    }
+    if (anObj->Presentation().IsNull())
+    {
+      Message::SendFail ("Error: Interactive object does not have current presentation.");
+      return 1;
+    }
+    // Get text properties
+    Handle(Graphic3d_Group) aNewGroup = anObj->Presentation()->NewGroup();
+    const TCollection_AsciiString aTextValue (theArgVec[anArgIter++]);
+    Standard_Real aPx = Draw::Atof (theArgVec[anArgIter++]);
+    Standard_Real aPy = Draw::Atof (theArgVec[anArgIter++]);
+    Standard_Real aPz = Draw::Atof (theArgVec[anArgIter++]);
+    Standard_Real aHeight = Draw::Atof (theArgVec[anArgIter++]);
+
+    aNewGroup->SetZLayer (aLayerID, Standard_True);
+    Handle(Graphic3d_AspectText3d) aTextAspect = new Graphic3d_AspectText3d (aColor, Font_NOF_MONOSPACE, 1.0, 0.0);
+    aNewGroup->SetGroupPrimitivesAspect (aTextAspect);
+    Graphic3d_Vertex aMarker (aPx, aPy, aPz);
+    Handle(Graphic3d_Text) aText = new Graphic3d_Text (aHeight);
+    aText->SetText (aTextValue);
+    aText->SetOrientation (gp_Ax2(gp_Pnt(aPx, aPy, aPz), gp::DZ()));
+    aText->SetOwnAnchorPoint (Standard_False);
+    aNewGroup->AddText (aText);
+  }
+  aContext->Display (anObj, Standard_True);
+  return 0;
+}
+
+
 //=======================================================================
 //function : ObjectsCommands
 //purpose  :
@@ -7235,4 +7372,12 @@ void ViewerTest::ObjectCommands(Draw_Interpretor& theCommands)
                    "\n\t\t:        [-useMesh] [-oriented {0}1}=0]"
                    "\n\t\t:  Displays/Hides normals calculated on shape geometry or retrieved from triangulation",
                    __FILE__, VNormals, group);
+
+  theCommands.Add ("vaddgroup",
+                   "vaddgroup name [type=quad|text] -zlayer=value\n"
+                   "quad: [x y dx dy depth color]\n"
+                   "text: [val px py pz height color]\n"
+                   "zlayer id of the zlayer\n"
+                   "add graphic3d_group to existing object",
+                   __FILE__, vAddGroup, group);
 }
diff --git a/tests/v3d/materials/bug33504 b/tests/v3d/materials/bug33504
new file mode 100644
index 0000000000..55437e6294
--- /dev/null
+++ b/tests/v3d/materials/bug33504
@@ -0,0 +1,37 @@
+puts "========"
+puts "0033504: Visualization - Request OCC function extension AIS_InteractiveObject"
+puts "========"
+puts ""
+
+pload MODELING VISUALIZATION
+vclear
+vinit
+vcylinder cyl 1 2 10 -nbSlices 100
+box b1 5 5 5 3 3 3
+vdisplay b1 -dispmode 1 -layer 0
+vobjzlayer set b1 -2
+vobjzlayer set b1 0
+vfit
+#add groups with different zlayer settings
+vaddgroup b1 quad 5 5 1 1 3 -zlayer 0 -color 0.0 0.0 1.0
+vaddgroup b1 quad 5 5 1 1 5 -zlayer -3 -color 0.0 1.0 0.0
+vaddgroup b1 quad 5 5 1 1 7 -zlayer -2 -color 1.0 0.0 0.0
+vaddgroup b1 text myKindOfText 5 5 10 20 -zlayer -4 -color 1.0 0.0 1.0
+
+#general perspective
+vviewparams -scale 40.0 -proj 0.0 -1.0 1.0 -up 0.0 0.0 1.0 -at 2.5 2.5 0.0
+vdump $imagedir/${casename}_generalperpective.png
+#front perspective
+vviewparams -scale 40.0 -proj 0.0 0.0 1.0 -up 0.0 0.0 1.0 -at 2.5 2.5 0.0
+if { [vreadpixel 245 150 rgb name] != "GREEN" } { puts "Error: Green quad should be visible." }
+vdump $imagedir/${casename}_front.png
+#back perspective
+vviewparams -scale 40.0 -proj 0.0 0.0 -1.0 -up 0.0 0.0 1.0 -at 2.5 2.5 0.0
+if { [vreadpixel 165 150 rgb name] != "GREEN" } { puts "Error: Green quad should be visible." }
+vdump $imagedir/${casename}_back.png
+#front cylinder
+vviewparams -scale 40.0 -proj -1.0 -1.0 -0.6 -up 0.0 0.0 1.0 -at -2.5 -2.5 0.0
+vdump $imagedir/${casename}_cylinderperpective.png
+#different perspective
+vviewparams -scale 40.0 -proj -1.0 -1.0 -1.9 -up 0.0 0.0 1.0 -at -0.5 -0.5 0.0
+vdump $imagedir/${casename}_generalperspective2.png