]> OCCT Git - occt-copy.git/commitdiff
0027925: Visualization - implement order-independent transparency algorithm within...
authorapl <anton.poletaev@opencascade.com>
Thu, 13 Apr 2017 10:25:13 +0000 (13:25 +0300)
committerapl <anton.poletaev@opencascade.com>
Thu, 13 Apr 2017 10:25:13 +0000 (13:25 +0300)
The weighted, blended order-independent transparency algorithm has been added rasterization pipeline.
It requires shaders, multiple render targets extension and floating point texture format.
Patch does not modify API and does not require porting - it adds new rendering options (vrenderparams):
- OIT-enabling flag and,
- Scalar factor [0-1] controlling influence of a fragment's depth to its visibility.
The feature supports MSAA, OpenGL ES 2.0 and ANGLE.

The usage rules for default transparency algorithm become simpler - rendering priority of transparent graphical
structures is managed automatically, therefore no need to change it application side.

33 files changed:
src/AIS/AIS_Shape.cxx
src/AIS/AIS_Triangulation.cxx
src/Graphic3d/Graphic3d_RenderingParams.hxx
src/OpenGl/FILES
src/OpenGl/OpenGl_CappingAlgo.cxx
src/OpenGl/OpenGl_CappingAlgo.hxx
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_Element.hxx
src/OpenGl/OpenGl_FrameBuffer.cxx
src/OpenGl/OpenGl_FrameBuffer.hxx
src/OpenGl/OpenGl_GlFunctions.hxx
src/OpenGl/OpenGl_Layer.cxx
src/OpenGl/OpenGl_Layer.hxx
src/OpenGl/OpenGl_LayerList.cxx
src/OpenGl/OpenGl_LayerList.hxx
src/OpenGl/OpenGl_OitUniformState.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_PrimitiveArray.hxx
src/OpenGl/OpenGl_RenderFilter.hxx
src/OpenGl/OpenGl_SetOfShaderPrograms.hxx
src/OpenGl/OpenGl_ShaderManager.cxx
src/OpenGl/OpenGl_ShaderManager.hxx
src/OpenGl/OpenGl_ShaderProgram.cxx
src/OpenGl/OpenGl_ShaderProgram.hxx
src/OpenGl/OpenGl_Texture.cxx
src/OpenGl/OpenGl_View.cxx
src/OpenGl/OpenGl_View.hxx
src/OpenGl/OpenGl_View_Redraw.cxx
src/OpenGl/OpenGl_Workspace.cxx
src/OpenGl/OpenGl_Workspace.hxx
src/Shaders/PhongShading.fs
src/Shaders/Shaders_Declarations_glsl.pxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx

index 484a33c968f2cac66391ebf33fbb568f2934f6d3..9796f04f91710d626734303b2345d217f322db97 100644 (file)
@@ -981,7 +981,6 @@ void AIS_Shape::SetTransparency (const Standard_Real theValue)
     }
 
     const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
-    aPrs->SetDisplayPriority (10); // force highest priority for translucent objects
     for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
     {
       const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
@@ -1037,7 +1036,6 @@ void AIS_Shape::UnsetTransparency()
         aGroup->SetGroupPrimitivesAspect (anAreaAsp);
       }
     }
-    aPrs->ResetDisplayPriority();
   }
 
   myRecomputeEveryPrs = Standard_False; // no mode to recalculate :only viewer update
index f4df8e4c278d38eacaece23bb4ff7de454f6cadc..3374b05f61254ba2004929ccfcbc2c7b08b4b8dc 100644 (file)
@@ -105,11 +105,6 @@ void AIS_Triangulation::updatePresentation()
 
       const Handle(Prs3d_Presentation)& aPrs = aPrsModed.Presentation()->Presentation();
 
-      if (IsTransparent())
-      {
-        aPrs->SetDisplayPriority (10); // force highest priority for translucent objects
-      }
-
       for (Graphic3d_SequenceOfGroup::Iterator aGroupIt (aPrs->Groups()); aGroupIt.More(); aGroupIt.Next())
       {
         const Handle(Graphic3d_Group)& aGroup = aGroupIt.Value();
@@ -118,11 +113,6 @@ void AIS_Triangulation::updatePresentation()
           aGroup->SetGroupPrimitivesAspect (anAreaAsp);
         }
       }
-
-      if (!IsTransparent())
-      {
-        aPrs->ResetDisplayPriority();
-      }
     }
 
     myRecomputeEveryPrs = Standard_False; // no mode to recalculate - only viewer update
index b264d443610f1da222c85e5f0f99e18db9340aaf..bda650918b135761821e58ec86d5d585eedd0f4c 100644 (file)
@@ -48,6 +48,8 @@ public:
   Graphic3d_RenderingParams()
   : Method                      (Graphic3d_RM_RASTERIZATION),
     NbMsaaSamples               (0),
+    IsOitEnabled                (Standard_True),
+    OitDepthWeight              (0.0f),
     // ray tracing parameters
     IsGlobalIlluminationEnabled (Standard_False),
     RaytracingDepth             (THE_DEFAULT_DEPTH),
@@ -90,6 +92,8 @@ public:
 
   Graphic3d_RenderingMode Method;                      //!< specifies rendering mode, Graphic3d_RM_RASTERIZATION by default
   Standard_Integer        NbMsaaSamples;               //!< number of MSAA samples (should be within 0..GL_MAX_SAMPLES, power-of-two number), 0 by default
+  Standard_Boolean        IsOitEnabled;                //!< enables/disables order-independent transparency for rasterization, True by default
+  Standard_ShortReal      OitDepthWeight;              //!< scalar factor [0-1] controlling influence of depth of a fragment to its final coverage
 
   Standard_Boolean        IsGlobalIlluminationEnabled; //!< enables/disables global illumination effects (path tracing)
   Standard_Integer        SamplesPerPixel;             //!< number of samples per pixel (SPP)
index b9dbf9e68e0acc43bf3bdbbb401399b80101c115..3aec70537bcbeab15e3ca17f67e28a76bc31503f 100755 (executable)
@@ -104,6 +104,7 @@ OpenGl_IndexBuffer.cxx
 OpenGl_IndexBuffer.hxx
 OpenGl_Layer.cxx
 OpenGl_Layer.hxx
+OpenGl_OitUniformState.hxx
 OpenGl_RenderFilter.cxx
 OpenGl_RenderFilter.hxx
 OpenGl_Sampler.cxx
index f0bfb6695a5568a87b1dfaaab00effa35c5e6097..3ba9545632d4f47e6bcb39ee33308329cda3ae1c 100755 (executable)
@@ -27,14 +27,6 @@ IMPLEMENT_STANDARD_RTTIEXT(OpenGl_CappingAlgoFilter,OpenGl_RenderFilter)
 
 namespace
 {
-#if !defined(GL_ES_VERSION_2_0)
-  static const GLint THE_FILLPRIM_FROM = GL_TRIANGLES;
-  static const GLint THE_FILLPRIM_TO   = GL_POLYGON;
-#else
-  static const GLint THE_FILLPRIM_FROM = GL_TRIANGLES;
-  static const GLint THE_FILLPRIM_TO   = GL_TRIANGLE_FAN;
-#endif
-
   //! Render infinite capping plane.
   //! @param theWorkspace [in] the GL workspace, context state.
   //! @param thePlane [in] the graphical plane, for which the capping surface is rendered.
@@ -88,8 +80,14 @@ namespace
       theWorkspace->ApplyAspectFace();
 
       // evaluate number of pair faces
-      glDisable (GL_DEPTH_TEST);
-      glDepthMask (GL_FALSE);
+      if (theWorkspace->UseZBuffer())
+      {
+        glDisable (GL_DEPTH_TEST);
+      }
+      if (theWorkspace->UseDepthWrite())
+      {
+        glDepthMask (GL_FALSE);
+      }
       glStencilFunc (GL_ALWAYS, 1, 0x01);
       glStencilOp (GL_KEEP, GL_INVERT, GL_INVERT);
 
@@ -119,10 +117,16 @@ namespace
 
       // render capping plane using the generated stencil mask
       glColorMask (GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
-      glDepthMask (GL_TRUE);
+      if (theWorkspace->UseDepthWrite())
+      {
+        glDepthMask (GL_TRUE);
+      }
       glStencilFunc (GL_EQUAL, 1, 0x01);
       glStencilOp (GL_KEEP, GL_KEEP, GL_KEEP);
-      glEnable (GL_DEPTH_TEST);
+      if (theWorkspace->UseZBuffer())
+      {
+        glEnable (GL_DEPTH_TEST);
+      }
 
       renderPlane (theWorkspace, thePlane, aRenderPlane->ToUseObjectProperties()
                                          ? aGroupIter.Value()->AspectFace()
@@ -160,7 +164,9 @@ void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorks
 
   // replace primitive groups rendering filter
   Handle(OpenGl_RenderFilter) aRenderFilter = theWorkspace->GetRenderFilter();
-  theWorkspace->SetRenderFilter (theWorkspace->DefaultCappingAlgoFilter());
+  Handle(OpenGl_CappingAlgoFilter) aCappingFilter = theWorkspace->DefaultCappingAlgoFilter();
+  aCappingFilter->SetPreviousFilter (aRenderFilter);
+  theWorkspace->SetRenderFilter (aCappingFilter);
 
   // prepare for rendering the clip planes
   glEnable (GL_STENCIL_TEST);
@@ -214,10 +220,16 @@ void OpenGl_CappingAlgo::RenderCapping (const Handle(OpenGl_Workspace)& theWorks
 // function : CanRender
 // purpose  :
 // =======================================================================
-Standard_Boolean OpenGl_CappingAlgoFilter::CanRender (const OpenGl_Element* theElement)
+Standard_Boolean OpenGl_CappingAlgoFilter::ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
+                                                         const OpenGl_Element* theGlElement)
 {
-  const OpenGl_PrimitiveArray* aPArray = dynamic_cast<const OpenGl_PrimitiveArray*> (theElement);
+  if (!myFilter.IsNull() && !myFilter->ShouldRender (theWorkspace, theGlElement))
+  {
+    return Standard_False;
+  }
+
+  const OpenGl_PrimitiveArray* aPArray = dynamic_cast<const OpenGl_PrimitiveArray*> (theGlElement);
   return aPArray != NULL
-      && aPArray->DrawMode() >= THE_FILLPRIM_FROM
-      && aPArray->DrawMode() <= THE_FILLPRIM_TO;
+      && aPArray->DrawMode() >= OpenGl_PrimitiveArray::THE_FILLPRIM_FROM
+      && aPArray->DrawMode() <= OpenGl_PrimitiveArray::THE_FILLPRIM_TO;
 }
index 7fc7881448393ee16ec71905d523e6fc78b139df..23d9ae33b0df467a5978957c8094d5ecec6a3914 100755 (executable)
@@ -49,14 +49,23 @@ public:
   //! Default constructor.
   OpenGl_CappingAlgoFilter() {}
 
+  //! Sets the current active filter in workspace.
+  //! @param thePrevFilter [in] the previously active filter that should have additive effect.
+  void SetPreviousFilter (const Handle(OpenGl_RenderFilter)& thePrevFitler) { myFilter = thePrevFitler; }
+
   //! Checks whether the element can be rendered or not.
   //! @param theElement [in] the element to check.
   //! @return True if element can be rendered.
-  virtual Standard_Boolean CanRender (const OpenGl_Element* theElement) Standard_OVERRIDE;
+  virtual Standard_Boolean ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
+                                         const OpenGl_Element* theGlElement) Standard_OVERRIDE;
+
+private:
+
+  Handle(OpenGl_RenderFilter) myFilter; //!< Previous active filter that should be combined.
 
 public:
 
-  DEFINE_STANDARD_RTTIEXT(OpenGl_CappingAlgoFilter,OpenGl_RenderFilter)
+  DEFINE_STANDARD_RTTIEXT(OpenGl_CappingAlgoFilter, OpenGl_RenderFilter)
 };
 
 #endif
index 43ae9fa763d1a7baa933e8ca4d637ea4ad3034c5..37fc98e3d72adcfa5446103da4ca524e156462d5 100644 (file)
@@ -127,6 +127,8 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   arbNPTW  (Standard_False),
   arbTexRG (Standard_False),
   arbTexFloat (Standard_False),
+  arbTexHalfFloat (Standard_False),
+  arbSampleShading (Standard_False),
   arbTexBindless (NULL),
   arbTBO (NULL),
   arbTboRGB32 (Standard_False),
@@ -152,11 +154,13 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   myMaxTexDim  (1024),
   myMaxClipPlanes (6),
   myMaxMsaaSamples(0),
+  myMaxDrawBuffers (1),
   myGlVerMajor (0),
   myGlVerMinor (0),
   myIsInitialized (Standard_False),
   myIsStereoBuffers (Standard_False),
   myIsGlNormalizeEnabled (Standard_False),
+  myHasHalfFloatTextures (Standard_False),
   myHasRayTracing (Standard_False),
   myHasRayTracingTextures (Standard_False),
   myHasRayTracingAdaptiveSampling (Standard_False),
@@ -171,7 +175,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
 #endif
   myToCullBackFaces (false),
   myReadBuffer (0),
-  myDrawBuffer (0),
+  myDrawBuffers (1),
   myDefaultVao (0),
   myIsGlDebugCtx (Standard_False),
   myResolutionRatio (1.0f)
@@ -371,18 +375,60 @@ void OpenGl_Context::SetReadBuffer (const Standard_Integer theReadBuffer)
 void OpenGl_Context::SetDrawBuffer (const Standard_Integer theDrawBuffer)
 {
 #if !defined(GL_ES_VERSION_2_0)
-  myDrawBuffer = !myIsStereoBuffers ? stereoToMonoBuffer (theDrawBuffer) : theDrawBuffer;
-  if (myDrawBuffer < GL_COLOR_ATTACHMENT0
+  const Standard_Integer aDrawBuffer = !myIsStereoBuffers ? stereoToMonoBuffer (theDrawBuffer) : theDrawBuffer;
+  if (aDrawBuffer < GL_COLOR_ATTACHMENT0
    && arbFBO != NULL)
   {
     arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
   }
-  ::glDrawBuffer (myDrawBuffer);
+  ::glDrawBuffer (aDrawBuffer);
+
+  myDrawBuffers.Clear();
+
+  if (aDrawBuffer != GL_NONE)
+  {
+    myDrawBuffers.SetValue (0, aDrawBuffer);
+  }
 #else
   (void )theDrawBuffer;
 #endif
 }
 
+// =======================================================================
+// function : SetDrawBuffers
+// purpose  :
+// =======================================================================
+void OpenGl_Context::SetDrawBuffers (const Standard_Integer theNb, const Standard_Integer* theDrawBuffers)
+{
+  Standard_ASSERT_RETURN (Functions()->glDrawBuffers != NULL, "Multiple render targets feature is not supported by the context", Standard_ASSERT_DO_NOTHING());
+
+  myDrawBuffers.Clear();
+
+  Standard_Boolean useDefaultFbo = Standard_False;
+  for (Standard_Integer anI = 0; anI < theNb; ++anI)
+  {
+#if !defined(GL_ES_VERSION_2_0)
+    const Standard_Integer aDrawBuffer = !myIsStereoBuffers ? stereoToMonoBuffer (theDrawBuffers[anI]) : theDrawBuffers[anI];
+#else
+    const Standard_Integer aDrawBuffer = theDrawBuffers[anI];
+#endif
+    if (aDrawBuffer < GL_COLOR_ATTACHMENT0 && aDrawBuffer != GL_NONE)
+    {
+      useDefaultFbo = Standard_True;
+    }
+    else if (aDrawBuffer != GL_NONE)
+    {
+      myDrawBuffers.SetValue (anI, aDrawBuffer);
+    }
+  }
+  if (arbFBO != NULL && useDefaultFbo)
+  {
+    arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, OpenGl_FrameBuffer::NO_FRAMEBUFFER);
+  }
+
+  Functions()->glDrawBuffers (theNb, (const GLenum*)theDrawBuffers);
+}
+
 // =======================================================================
 // function : SetCullBackFaces
 // purpose  :
@@ -419,9 +465,35 @@ void OpenGl_Context::FetchState()
     ::glGetIntegerv (GL_RENDER_MODE, &myRenderMode);
   }
 
-  // cache buffers state
+  // cache read buffers state
   ::glGetIntegerv (GL_READ_BUFFER, &myReadBuffer);
-  ::glGetIntegerv (GL_DRAW_BUFFER, &myDrawBuffer);
+
+  // cache draw buffers state
+  myDrawBuffers.Clear();
+
+  Standard_Integer aDrawBuffer;
+
+  if (myMaxDrawBuffers == 1)
+  {
+    ::glGetIntegerv (GL_DRAW_BUFFER, &aDrawBuffer);
+
+    if (aDrawBuffer != GL_NONE)
+    {
+      myDrawBuffers.SetValue (0, aDrawBuffer);
+    }
+  }
+  else
+  {
+    for (Standard_Integer anI = 0; anI < myMaxDrawBuffers; ++anI)
+    {
+      ::glGetIntegerv (GL_DRAW_BUFFER0 + anI, &aDrawBuffer);
+
+      if (aDrawBuffer != GL_NONE)
+      {
+        myDrawBuffers.SetValue (anI, aDrawBuffer);
+      }
+    }
+  }
 #endif
 }
 
@@ -1096,6 +1168,7 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
   myGlVerMajor = 0;
   myGlVerMinor = 0;
   myMaxMsaaSamples = 0;
+  myMaxDrawBuffers = 1;
   ReadGlVersion (myGlVerMajor, myGlVerMinor);
   myVendor = (const char* )::glGetString (GL_VENDOR);
   if (!caps->ffpEnable
@@ -1188,6 +1261,8 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
   arbNPTW     = Standard_True;
   arbTexRG    = IsGlGreaterEqual (3, 0)
              || CheckExtension ("GL_EXT_texture_rg");
+  arbSampleShading = IsGlGreaterEqual (3, 2)
+                  || CheckExtension ("GL_OES_sample_variables");
   extBgra     = CheckExtension ("GL_EXT_texture_format_BGRA8888");
   extAnis = CheckExtension ("GL_EXT_texture_filter_anisotropic");
   extPDS  = CheckExtension ("GL_OES_packed_depth_stencil");
@@ -1227,8 +1302,10 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
     hasHighp = Standard_True;
   }
 
-  arbTexFloat = IsGlGreaterEqual (3, 0)
-             && FindProc ("glTexImage3D", myFuncs->glTexImage3D);
+  arbTexFloat     = IsGlGreaterEqual (3, 0)
+                  && FindProc ("glTexImage3D", myFuncs->glTexImage3D);
+  arbTexHalfFloat = IsGlGreaterEqual (3, 0)
+                  || CheckExtension ("GL_OES_texture_half_float");
 
   const Standard_Boolean hasTexBuffer32  = IsGlGreaterEqual (3, 2) && FindProc ("glTexBuffer", myFuncs->glTexBuffer);
   const Standard_Boolean hasExtTexBuffer = CheckExtension ("GL_EXT_texture_buffer") && FindProc ("glTexBufferEXT", myFuncs->glTexBuffer);
@@ -1268,19 +1345,30 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
     }
   }
 
+  const Standard_Boolean hasDrawBuffersExt = (IsGlGreaterEqual (3, 0) || CheckExtension ("GL_EXT_draw_buffers"))
+                                          && FindProc ("glDrawBuffersEXT", myFuncs->glDrawBuffers);
+  // get number of maximum supported draw buffers
+  if (hasDrawBuffersExt)
+  {
+    glGetIntegerv (GL_MAX_DRAW_BUFFERS, &myMaxDrawBuffers);
+  }
 #else
 
   myTexClamp = IsGlGreaterEqual (1, 2) ? GL_CLAMP_TO_EDGE : GL_CLAMP;
 
-  hasTexRGBA8 = Standard_True;
-  arbNPTW     = CheckExtension ("GL_ARB_texture_non_power_of_two");
-  arbTexFloat = IsGlGreaterEqual (3, 0)
-             || CheckExtension ("GL_ARB_texture_float");
-  extBgra     = CheckExtension ("GL_EXT_bgra");
-  extAnis     = CheckExtension ("GL_EXT_texture_filter_anisotropic");
-  extPDS      = CheckExtension ("GL_EXT_packed_depth_stencil");
-  atiMem      = CheckExtension ("GL_ATI_meminfo");
-  nvxMem      = CheckExtension ("GL_NVX_gpu_memory_info");
+  hasTexRGBA8     = Standard_True;
+  arbNPTW         = CheckExtension ("GL_ARB_texture_non_power_of_two");
+  arbTexFloat     = IsGlGreaterEqual (3, 0)
+                  || CheckExtension ("GL_ARB_texture_float");
+  arbTexHalfFloat = IsGlGreaterEqual (3, 0)
+                  || CheckExtension ("GL_ARB_half_float_pixel");
+  arbSampleShading = IsGlGreaterEqual (4, 0)
+                  || CheckExtension("GL_ARB_sample_shading");
+  extBgra          = CheckExtension ("GL_EXT_bgra");
+  extAnis          = CheckExtension ("GL_EXT_texture_filter_anisotropic");
+  extPDS           = CheckExtension ("GL_EXT_packed_depth_stencil");
+  atiMem           = CheckExtension ("GL_ATI_meminfo");
+  nvxMem           = CheckExtension ("GL_NVX_gpu_memory_info");
 
   GLint aStereo = GL_FALSE;
   glGetIntegerv (GL_STEREO, &aStereo);
@@ -1288,6 +1376,12 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
 
   // get number of maximum clipping planes
   glGetIntegerv (GL_MAX_CLIP_PLANES,  &myMaxClipPlanes);
+
+  // get number of maximum supported draw buffers
+  if (IsGlGreaterEqual (2, 0))
+  {
+    glGetIntegerv (GL_MAX_DRAW_BUFFERS, &myMaxDrawBuffers);
+  }
 #endif
 
   glGetIntegerv (GL_MAX_TEXTURE_SIZE, &myMaxTexDim);
@@ -2848,7 +2942,6 @@ Handle(OpenGl_FrameBuffer) OpenGl_Context::SetDefaultFrameBuffer (const Handle(O
 // =======================================================================
 void OpenGl_Context::SetShadingMaterial (const OpenGl_AspectFace* theAspect,
                                          const Handle(Graphic3d_PresentationAttributes)& theHighlight,
-                                         const Standard_Boolean theUseDepthWrite,
                                          Standard_Integer& theRenderingPassFlags)
 {
   const Handle(Graphic3d_AspectFillArea3d)& anAspect = (!theHighlight.IsNull() && !theHighlight->BasicFillAreaAspect().IsNull())
@@ -2902,26 +2995,12 @@ void OpenGl_Context::SetShadingMaterial (const OpenGl_AspectFace* theAspect,
       theRenderingPassFlags |= OPENGL_NS_2NDPASSNEED;
     }
 
-    GLboolean aDepthMask = GL_TRUE;
     if (aTranspFront != 0.0f
      || aTranspBack  != 0.0f)
     {
       // render transparent
       myMatFront.Diffuse.a() = 1.0f - aTranspFront;
       myMatBack .Diffuse.a() = 1.0f - aTranspBack;
-      glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-      glEnable (GL_BLEND);
-      aDepthMask = GL_FALSE;
-    }
-    else
-    {
-      // render opaque
-      glBlendFunc (GL_ONE, GL_ZERO);
-      glDisable (GL_BLEND);
-    }
-    if (theUseDepthWrite)
-    {
-      glDepthMask (aDepthMask);
     }
   }
 
index e5bddc03808368360f6719e627a68678889224f4..555abc2f33dde2142828ec784591b68276a7b0f7 100644 (file)
 #include <Aspect_TypeOfLine.hxx>
 #include <NCollection_DataMap.hxx>
 #include <Graphic3d_DiagnosticInfo.hxx>
-#include <NCollection_Map.hxx>
+#include <NCollection_Array1.hxx>
 #include <NCollection_Handle.hxx>
 #include <NCollection_List.hxx>
+#include <NCollection_Map.hxx>
+#include <NCollection_SparseArray.hxx>
 #include <Message.hxx>
 #include <OpenGl_Caps.hxx>
 #include <OpenGl_LineAttributes.hxx>
@@ -43,6 +45,8 @@
 
 #include <NCollection_Shared.hxx>
 
+#include <vector>
+
 //! Forward declarations
 #if defined(__APPLE__)
   #import <TargetConditionals.h>
@@ -456,12 +460,18 @@ public:
   //! @return value for GL_MAX_SAMPLES
   Standard_Integer MaxMsaaSamples() const { return myMaxMsaaSamples; }
 
+  //! @return value for GL_MAX_DRAW_BUFFERS
+  Standard_Integer MaxDrawBuffers() const { return myMaxDrawBuffers; }
+
   //! Get maximum number of clip planes supported by OpenGl.
   //! This value is implementation dependent. At least 6
   //! planes should be supported by OpenGl (see specs).
   //! @return value for GL_MAX_CLIP_PLANES
   Standard_Integer MaxClipPlanes() const { return myMaxClipPlanes; }
 
+  //! @return TRUE if half-float textures are supported by OpenGl.
+  Standard_Boolean HasHalfFloatTextures() const { return myHasHalfFloatTextures; }
+
   //! @return TRUE if ray tracing mode is supported
   Standard_Boolean HasRayTracing() const { return myHasRayTracing; }
 
@@ -583,12 +593,18 @@ public: //! @name methods to alter or retrieve current state
   //! Switch read buffer, wrapper for ::glReadBuffer().
   Standard_EXPORT void SetReadBuffer (const Standard_Integer theReadBuffer);
 
-  //! Return active draw buffer.
-  Standard_Integer DrawBuffer() { return myDrawBuffer; }
+  //! Return active draw buffer attached to a render target referred by layout location.
+  Standard_Integer DrawBuffer (const Standard_Integer theLayoutIdx = 0)
+  {
+    return myDrawBuffers.IsBound (theLayoutIdx) ? myDrawBuffers.Value (theLayoutIdx) : GL_NONE;
+  }
 
   //! Switch draw buffer, wrapper for ::glDrawBuffer().
   Standard_EXPORT void SetDrawBuffer (const Standard_Integer theDrawBuffer);
 
+  //! Switch draw buffer, wrapper for ::glDrawBuffers (GLsizei, const GLenum*).
+  Standard_EXPORT void SetDrawBuffers (const Standard_Integer theNb, const Standard_Integer* theDrawBuffers);
+
   //! Switch read/draw buffers.
   void SetReadDrawBuffer (const Standard_Integer theBuffer)
   {
@@ -628,7 +644,6 @@ public: //! @name methods to alter or retrieve current state
   //! Setup current shading material.
   Standard_EXPORT void SetShadingMaterial (const OpenGl_AspectFace* theAspect,
                                            const Handle(Graphic3d_PresentationAttributes)& theHighlight,
-                                           const Standard_Boolean theUseDepthWrite,
                                            Standard_Integer& theRenderingPassFlags);
 
   //! Setup current color.
@@ -723,26 +738,28 @@ public: //! @name core profiles
 
 public: //! @name extensions
 
-  Standard_Boolean       hasHighp;       //!< highp in GLSL ES fragment shader is supported
-  Standard_Boolean       hasUintIndex;   //!< GLuint for index buffer is supported (always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_element_index_uint)
-  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
-  Standard_Boolean       arbTexFloat;    //!< GL_ARB_texture_float (on desktop OpenGL - since 3.0 or as extension GL_ARB_texture_float; on OpenGL ES - since 3.0)
-  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_ArbFBOBlit*     arbFBOBlit;     //!< glBlitFramebuffer function, moved out from OpenGl_ArbFBO structure for compatibility with OpenGL ES 2.0
-  Standard_Boolean       extFragDepth;   //!< GL_EXT_frag_depth on OpenGL ES 2.0 (gl_FragDepthEXT built-in variable, before OpenGL ES 3.0)
-  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       hasUintIndex;    //!< GLuint for index buffer is supported (always available on desktop; on OpenGL ES - since 3.0 or as extension GL_OES_element_index_uint)
+  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
+  Standard_Boolean       arbTexFloat;     //!< GL_ARB_texture_float (on desktop OpenGL - since 3.0 or as extension GL_ARB_texture_float; on OpenGL ES - since 3.0)
+  Standard_Boolean       arbTexHalfFloat; //!< GL_ARB_half_float_pixel (on desktop OpenGL - since 3.0 or as extension GL_ARB_half_float_pixel; on OpenGL ES - since 3.0 or as extension GL_OES_texture_half_float)
+  Standard_Boolean       arbSampleShading;//!< GL_ARB_sample_shading
+  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_ArbFBOBlit*     arbFBOBlit;      //!< glBlitFramebuffer function, moved out from OpenGl_ArbFBO structure for compatibility with OpenGL ES 2.0
+  Standard_Boolean       extFragDepth;    //!< GL_EXT_frag_depth on OpenGL ES 2.0 (gl_FragDepthEXT built-in variable, before OpenGL ES 3.0)
+  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
 
 public: //! @name public properties tracking current state
 
@@ -777,6 +794,7 @@ private: // context info
   typedef NCollection_Shared< NCollection_DataMap<TCollection_AsciiString, Standard_Integer> > OpenGl_DelayReleaseMap;
   typedef NCollection_Shared< NCollection_DataMap<TCollection_AsciiString, Handle(OpenGl_Resource)> > OpenGl_ResourcesMap;
   typedef NCollection_Shared< NCollection_List<Handle(OpenGl_Resource)> > OpenGl_ResourcesStack;
+  typedef NCollection_SparseArray<Standard_Integer> OpenGl_DrawBuffers;
 
   Handle(OpenGl_ResourcesMap)    mySharedResources; //!< shared resources with unique identification key
   Handle(OpenGl_DelayReleaseMap) myDelayed;         //!< shared resources for delayed release
@@ -792,6 +810,7 @@ private: // context info
   Standard_Integer myMaxTexDim;            //!< value for GL_MAX_TEXTURE_SIZE
   Standard_Integer myMaxClipPlanes;        //!< value for GL_MAX_CLIP_PLANES
   Standard_Integer myMaxMsaaSamples;       //!< value for GL_MAX_SAMPLES
+  Standard_Integer myMaxDrawBuffers;       //!< value for GL_MAX_DRAW_BUFFERS
   Standard_Integer myGlVerMajor;           //!< cached GL version major number
   Standard_Integer myGlVerMinor;           //!< cached GL version minor number
   Standard_Boolean myIsInitialized;        //!< flag indicates initialization state
@@ -799,6 +818,7 @@ private: // context info
   Standard_Boolean myIsGlNormalizeEnabled; //!< GL_NORMALIZE flag
                                            //!< Used to tell OpenGl that normals should be normalized
 
+  Standard_Boolean myHasHalfFloatTextures;          //! indicates whether half-float textures are supported
   Standard_Boolean myHasRayTracing;                 //! indicates whether ray tracing mode is supported 
   Standard_Boolean myHasRayTracingTextures;         //! indicates whether textures in ray tracing mode are supported 
   Standard_Boolean myHasRayTracingAdaptiveSampling; //! indicates whether adaptive screen sampling in ray tracing mode is supported 
@@ -817,7 +837,7 @@ private: //! @name fields tracking current state
   Standard_Integer              myPolygonMode;     //!< currently used polygon rasterization mode (glPolygonMode)
   bool                          myToCullBackFaces; //!< back face culling mode enabled state (glIsEnabled (GL_CULL_FACE))
   Standard_Integer              myReadBuffer;      //!< current read buffer
-  Standard_Integer              myDrawBuffer;      //!< current draw buffer
+  OpenGl_DrawBuffers            myDrawBuffers;     //!< current draw buffers
   unsigned int                  myDefaultVao;      //!< default Vertex Array Object
   Standard_Boolean              myIsGlDebugCtx;    //!< debug context initialization state
   TCollection_AsciiString       myVendor;          //!< Graphics Driver's vendor
index b3354212b680bf2fa839c038e89540611703297f..bbfb52a2483fef94f38999f6e2dc7cc88ebfd3ff 100644 (file)
@@ -68,7 +68,7 @@ public:
     RenderFiltered (const Handle(OpenGl_Workspace)& theWorkspace,
                     const Handle(OpenGl_RenderFilter)& theFilter) const
   {
-    if (!theFilter.IsNull() && !theFilter->CanRender (this))
+    if (!theFilter.IsNull() && !theFilter->ShouldRender (theWorkspace, this))
     {
       return Standard_False;
     }
index 6f686a48d4e0aa8cfa2895b71a33f461463a942c..c9abe4ff531eb9f773d87724c383813f18ade5b4 100644 (file)
@@ -18,6 +18,8 @@
 #include <Standard_Assert.hxx>
 #include <TCollection_ExtendedString.hxx>
 
+#include <algorithm>
+
 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_FrameBuffer,OpenGl_Resource)
 
 namespace
@@ -64,6 +66,68 @@ namespace
     return false;
   }
 
+  //! Determine data type from texture sized format.
+  static bool getColorDataFormat (GLint   theTextFormat,
+                                  GLenum& thePixelFormat,
+                                  GLenum& theDataType)
+  {
+    switch (theTextFormat)
+    {
+      case GL_RGBA32F:
+      {
+        thePixelFormat = GL_RGBA;
+        theDataType    = GL_FLOAT;
+        return true;
+      }
+      case GL_R32F:
+      {
+        thePixelFormat = GL_RED;
+        theDataType    = GL_FLOAT;
+        return true;
+      }
+      case GL_RGBA16F:
+      {
+        thePixelFormat = GL_RGBA;
+        theDataType    = GL_HALF_FLOAT;
+        return true;
+      }
+      case GL_R16F:
+      {
+        thePixelFormat = GL_RED;
+        theDataType    = GL_HALF_FLOAT;
+        return true;
+      }
+      case GL_RGBA8:
+      {
+        thePixelFormat = GL_RGBA;
+        theDataType    = GL_UNSIGNED_INT;
+        return true;
+      }
+      case GL_RGBA:
+      {
+        thePixelFormat = GL_RGBA;
+        theDataType    = GL_UNSIGNED_BYTE;
+        return true;
+      }
+    }
+    return false;
+  }
+
+  //! Checks whether two format arrays are equal or not.
+  static bool operator== (const OpenGl_ColorFormats& theFmt1,
+                          const OpenGl_ColorFormats& theFmt2)
+  {
+    if (theFmt1.Length() != theFmt2.Length())
+      return false;
+    OpenGl_ColorFormats::Iterator anIt1 (theFmt1);
+    OpenGl_ColorFormats::Iterator anIt2 (theFmt1);
+    for (; anIt1.More(); anIt1.Next(), anIt2.Next())
+    {
+      if (anIt1.Value() != anIt2.Value())
+        return false;
+    }
+    return true;
+  }
 }
 
 // =======================================================================
@@ -74,16 +138,16 @@ OpenGl_FrameBuffer::OpenGl_FrameBuffer()
 : myVPSizeX (0),
   myVPSizeY (0),
   myNbSamples (0),
-  myColorFormat (GL_RGBA8),
   myDepthFormat (GL_DEPTH24_STENCIL8),
   myGlFBufferId (NO_FRAMEBUFFER),
   myGlColorRBufferId (NO_RENDERBUFFER),
   myGlDepthRBufferId (NO_RENDERBUFFER),
   myIsOwnBuffer  (false),
-  myColorTexture (new OpenGl_Texture()),
+  myIsOwnDepth   (false),
   myDepthStencilTexture (new OpenGl_Texture())
 {
-  //
+  myColorFormats.Append (GL_RGBA8);
+  myColorTextures.Append (new OpenGl_Texture());
 }
 
 // =======================================================================
@@ -100,15 +164,49 @@ OpenGl_FrameBuffer::~OpenGl_FrameBuffer()
 // purpose  :
 // =======================================================================
 Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
-                                           const GLsizei   theSizeX,
-                                           const GLsizei   theSizeY,
-                                           const GLint     theColorFormat,
-                                           const GLint     theDepthFormat,
-                                           const GLsizei   theNbSamples)
+                                           const GLsizei                 theSizeX,
+                                           const GLsizei                 theSizeY,
+                                           const GLint                   theColorFormat,
+                                           const GLint                   theDepthFormat,
+                                           const GLsizei                 theNbSamples)
 {
-  myColorFormat = theColorFormat;
-  myDepthFormat = theDepthFormat;
-  myNbSamples   = theNbSamples;
+  OpenGl_ColorFormats aColorFormats;
+
+  aColorFormats.Append (theColorFormat);
+
+  return Init (theGlContext, theSizeX, theSizeY, aColorFormats, theDepthFormat, theNbSamples);
+}
+
+// =======================================================================
+// function : Init
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
+                                           const GLsizei                 theSizeX,
+                                           const GLsizei                 theSizeY,
+                                           const OpenGl_ColorFormats&    theColorFormats,
+                                           const Handle(OpenGl_Texture)& theDepthStencilTexture,
+                                           const GLsizei                 theNbSamples)
+{
+  myColorFormats = theColorFormats;
+
+  OpenGl_TextureArray aTextures (myColorTextures);
+  if (!myColorTextures.IsEmpty())
+  {
+    OpenGl_TextureArray::Iterator aTextureIt (myColorTextures);
+    for (; aTextureIt.More(); aTextureIt.Next())
+    {
+      aTextureIt.Value()->Release (theGlContext.operator->());
+    }
+    myColorTextures.Clear();
+  }
+  for (Standard_Integer aLength = 0; aLength < myColorFormats.Length(); ++aLength)
+  {
+    myColorTextures.Append (aLength < aTextures.Length() ? aTextures.Value (aLength) : new OpenGl_Texture());
+  }
+
+  myDepthFormat         = theDepthStencilTexture->GetFormat();
+  myNbSamples           = theNbSamples;
   if (theGlContext->arbFBO == NULL)
   {
     return Standard_False;
@@ -116,12 +214,14 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo
 
   // clean up previous state
   Release (theGlContext.operator->());
-  if (myColorFormat == 0
+  if (std::count (myColorFormats.begin(), myColorFormats.end(), 0) == myColorFormats.Length()
    && myDepthFormat == 0)
   {
     return Standard_False;
   }
 
+  myDepthStencilTexture = theDepthStencilTexture;
+  myIsOwnDepth  = false;
   myIsOwnBuffer = true;
 
   // setup viewport sizes as is
@@ -133,11 +233,147 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo
   // Create the textures (will be used as color buffer and depth-stencil buffer)
   if (theNbSamples != 0)
   {
-    if (myColorFormat != 0
-    && !myColorTexture       ->Init2DMultisample (theGlContext, theNbSamples, myColorFormat, aSizeX, aSizeY))
+    for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
     {
-      Release (theGlContext.operator->());
-      return Standard_False;
+      const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
+      const GLint                   aColorFormat  = myColorFormats  (aColorBufferIdx);
+      if (aColorFormat != 0
+      && !aColorTexture->Init2DMultisample (theGlContext, theNbSamples,
+                                            aColorFormat, aSizeX, aSizeY))
+      {
+        Release (theGlContext.operator->());
+        return Standard_False;
+      }
+    }
+  }
+  else
+  {
+    GLenum aPixelFormat = 0;
+    GLenum aDataType    = 0;
+    for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
+    {
+      const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
+      const GLint                   aColorFormat  = myColorFormats  (aColorBufferIdx);
+      if (aColorFormat != 0
+      &&  getColorDataFormat (aColorFormat, aPixelFormat, aDataType)
+      && !aColorTexture->Init (theGlContext, aColorFormat,
+                               aPixelFormat, aDataType,
+                               aSizeX, aSizeY, Graphic3d_TOT_2D))
+      {
+        Release (theGlContext.operator->());
+        return Standard_False;
+      }
+    }
+  }
+
+  // Build FBO and setup it as texture
+  theGlContext->arbFBO->glGenFramebuffers (1, &myGlFBufferId);
+  theGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
+
+  for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
+  {
+    const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
+
+    if (aColorTexture->IsValid())
+    {
+      theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + aColorBufferIdx,
+                                                    aColorTexture->GetTarget(), aColorTexture->TextureId(), 0);
+    }
+  }
+
+  if (myDepthStencilTexture->IsValid())
+  {
+  #ifdef GL_DEPTH_STENCIL_ATTACHMENT
+    theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+                                                  myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
+  #else
+    theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+                                                  myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
+    theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_STENCIL_ATTACHMENT,
+                                                  myDepthStencilTexture->GetTarget(), myDepthStencilTexture->TextureId(), 0);
+  #endif
+  }
+  else if (myGlDepthRBufferId != NO_RENDERBUFFER)
+  {
+    theGlContext->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,
+                                                     GL_RENDERBUFFER, myGlDepthRBufferId);
+  }
+  if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+  {
+    Release (theGlContext.operator->());
+    return Standard_False;
+  }
+
+  UnbindBuffer (theGlContext);
+  return Standard_True;
+}
+
+// =======================================================================
+// function : Init
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlContext,
+                                           const GLsizei                 theSizeX,
+                                           const GLsizei                 theSizeY,
+                                           const OpenGl_ColorFormats&    theColorFormats,
+                                           const GLint                   theDepthFormat,
+                                           const GLsizei                 theNbSamples)
+{
+  myColorFormats = theColorFormats;
+
+  OpenGl_TextureArray aTextures (myColorTextures);
+  if (!myColorTextures.IsEmpty())
+  {
+    OpenGl_TextureArray::Iterator aTextureIt (myColorTextures);
+    for (; aTextureIt.More(); aTextureIt.Next())
+    {
+      aTextureIt.Value()->Release (theGlContext.operator->());
+    }
+    myColorTextures.Clear();
+  }
+  for (Standard_Integer aLength = 0; aLength < myColorFormats.Length(); ++aLength)
+  {
+    myColorTextures.Append (aLength < aTextures.Length() ? aTextures.Value (aLength) : new OpenGl_Texture());
+  }
+
+  myDepthFormat  = theDepthFormat;
+  myNbSamples    = theNbSamples;
+  if (theGlContext->arbFBO == NULL)
+  {
+    return Standard_False;
+  }
+
+  // clean up previous state
+  Release (theGlContext.operator->());
+  if (std::count (myColorFormats.begin(), myColorFormats.end(), 0) == myColorFormats.Length()
+   && myDepthFormat == 0)
+  {
+    return Standard_False;
+  }
+
+  myIsOwnBuffer = true;
+  myIsOwnDepth  = true;
+
+  // setup viewport sizes as is
+  myVPSizeX = theSizeX;
+  myVPSizeY = theSizeY;
+  const Standard_Integer aSizeX = theSizeX > 0 ? theSizeX : 2;
+  const Standard_Integer aSizeY = theSizeY > 0 ? theSizeY : 2;
+
+  // Create the textures (will be used as color buffer and depth-stencil buffer)
+  if (theNbSamples != 0)
+  {
+    for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
+    {
+      const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
+      const GLint                   aColorFormat  = myColorFormats  (aColorBufferIdx);
+      if (aColorFormat != 0
+      && !aColorTexture->Init2DMultisample (theGlContext, theNbSamples,
+                                            aColorFormat, aSizeX, aSizeY))
+      {
+        Release (theGlContext.operator->());
+        return Standard_False;
+      }
     }
     if (myDepthFormat != 0
     && !myDepthStencilTexture->Init2DMultisample (theGlContext, theNbSamples, myDepthFormat, aSizeX, aSizeY))
@@ -148,19 +384,25 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo
   }
   else
   {
-    if (myColorFormat != 0
-    && !myColorTexture->Init (theGlContext, myColorFormat,
-                              GL_RGBA, GL_UNSIGNED_BYTE,
-                              aSizeX, aSizeY, Graphic3d_TOT_2D))
+    GLenum aPixelFormat = 0;
+    GLenum aDataType    = 0;
+    for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
     {
-      Release (theGlContext.operator->());
-      return Standard_False;
+      const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
+      const GLint                   aColorFormat  = myColorFormats  (aColorBufferIdx);
+      if (aColorFormat != 0
+      &&  getColorDataFormat (aColorFormat, aPixelFormat, aDataType)
+      && !aColorTexture->Init (theGlContext, aColorFormat,
+                               aPixelFormat, aDataType,
+                               aSizeX, aSizeY, Graphic3d_TOT_2D))
+      {
+        Release (theGlContext.operator->());
+        return Standard_False;
+      }
     }
 
     // extensions (GL_OES_packed_depth_stencil, GL_OES_depth_texture) + GL version might be used to determine supported formats
     // instead of just trying to create such texture
-    GLenum aPixelFormat = 0;
-    GLenum aDataType    = 0;
     if (myDepthFormat != 0
     &&  getDepthDataFormat (myDepthFormat, aPixelFormat, aDataType)
     && !myDepthStencilTexture->Init (theGlContext, myDepthFormat,
@@ -185,11 +427,18 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo
   // Build FBO and setup it as texture
   theGlContext->arbFBO->glGenFramebuffers (1, &myGlFBufferId);
   theGlContext->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
-  if (myColorTexture->IsValid())
+
+  for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
   {
-    theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
-                                                  myColorTexture->GetTarget(), myColorTexture->TextureId(), 0);
+    const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
+
+    if (aColorTexture->IsValid())
+    {
+      theGlContext->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0 + aColorBufferIdx,
+                                                    aColorTexture->GetTarget(), aColorTexture->TextureId(), 0);
+    }
   }
+
   if (myDepthStencilTexture->IsValid())
   {
   #ifdef GL_DEPTH_STENCIL_ATTACHMENT
@@ -218,7 +467,7 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo
 }
 
 // =======================================================================
-// function : Init
+// function : InitLazy
 // purpose  :
 // =======================================================================
 Standard_Boolean OpenGl_FrameBuffer::InitLazy (const Handle(OpenGl_Context)& theGlContext,
@@ -228,16 +477,44 @@ Standard_Boolean OpenGl_FrameBuffer::InitLazy (const Handle(OpenGl_Context)& the
                                                const GLint                   theDepthFormat,
                                                const GLsizei                 theNbSamples)
 {
-  if (myVPSizeX     == theViewportSizeX
-   && myVPSizeY     == theViewportSizeY
-   && myColorFormat == theColorFormat
-   && myDepthFormat == theDepthFormat
-   && myNbSamples   == theNbSamples)
+  OpenGl_ColorFormats aColorFormats;
+
+  aColorFormats.Append (theColorFormat);
+
+  return InitLazy (theGlContext, theViewportSizeX, theViewportSizeY, aColorFormats, theDepthFormat, theNbSamples);
+}
+
+// =======================================================================
+// function : InitLazy
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_FrameBuffer::InitLazy (const Handle(OpenGl_Context)& theGlContext,
+                                               const GLsizei                 theViewportSizeX,
+                                               const GLsizei                 theViewportSizeY,
+                                               const OpenGl_ColorFormats&    theColorFormats,
+                                               const GLint                   theDepthFormat,
+                                               const GLsizei                 theNbSamples)
+{
+  if (myVPSizeX      == theViewportSizeX
+   && myVPSizeY      == theViewportSizeY
+   && myColorFormats == theColorFormats
+   && myDepthFormat  == theDepthFormat
+   && myNbSamples    == theNbSamples)
   {
     return IsValid();
   }
 
-  return Init (theGlContext, theViewportSizeX, theViewportSizeY, theColorFormat, theDepthFormat, theNbSamples);
+  return Init (theGlContext, theViewportSizeX, theViewportSizeY, theColorFormats, theDepthFormat, theNbSamples);
+}
+
+// =======================================================================
+// function : InitLazy
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_FrameBuffer::InitLazy (const Handle(OpenGl_Context)& theGlCtx,
+                                               const OpenGl_FrameBuffer&     theFbo)
+{
+  return InitLazy (theGlCtx, theFbo.myVPSizeX, theFbo.myVPSizeY, theFbo.myColorFormats, theFbo.myDepthFormat, theFbo.myNbSamples);
 }
 
 // =======================================================================
@@ -251,9 +528,22 @@ Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& t
                                                  const GLint                   theDepthFormat,
                                                  const GLuint                  theColorRBufferFromWindow)
 {
-  myColorFormat = theColorFormat;
-  myDepthFormat = theDepthFormat;
-  myNbSamples   = 0;
+  myColorFormats.Clear();
+  myColorFormats.Append (theColorFormat);
+  if (!myColorTextures.IsEmpty())
+  {
+    Handle(OpenGl_Texture) aTexutre = myColorTextures.First();
+    OpenGl_TextureArray::Iterator aTextureIt (myColorTextures);
+    for (; aTextureIt.More(); aTextureIt.Next())
+    {
+      aTextureIt.Value()->Release (theGlCtx.operator->());
+    }
+    myColorTextures.Clear();
+    myColorTextures.Append (aTexutre);
+  }
+
+  myDepthFormat  = theDepthFormat;
+  myNbSamples    = 0;
   if (theGlCtx->arbFBO == NULL)
   {
     return Standard_False;
@@ -263,6 +553,7 @@ Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& t
   Release (theGlCtx.operator->());
 
   myIsOwnBuffer = true;
+  myIsOwnDepth  = true;
 
   // setup viewport sizes as is
   myVPSizeX = theSizeX;
@@ -275,11 +566,11 @@ Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& t
   {
     myGlColorRBufferId = theColorRBufferFromWindow;
   }
-  else if (myColorFormat != 0)
+  else if (theColorFormat != 0)
   {
     theGlCtx->arbFBO->glGenRenderbuffers (1, &myGlColorRBufferId);
     theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlColorRBufferId);
-    theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, myColorFormat, aSizeX, aSizeY);
+    theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, theColorFormat, aSizeX, aSizeY);
   }
 
   if (myDepthFormat != 0)
@@ -344,17 +635,19 @@ Standard_Boolean OpenGl_FrameBuffer::InitWrapper (const Handle(OpenGl_Context)&
   GLint aColorId   = 0;
   GLint aDepthType = 0;
   GLint aDepthId   = 0;
+
   theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &aColorType);
   theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,  GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &aDepthType);
 
   myGlFBufferId = GLuint(anFbo);
   myIsOwnBuffer = false;
+  myIsOwnDepth  = false;
   if (aColorType == GL_RENDERBUFFER)
   {
     theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &aColorId);
     myGlColorRBufferId = aColorId;
   }
-  else if (aColorType != GL_NONE)
+  else if (aColorType != 0)
   {
     TCollection_ExtendedString aMsg = "OpenGl_FrameBuffer::InitWrapper(), color attachment of unsupported type has been skipped!";
     theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
@@ -369,7 +662,7 @@ Standard_Boolean OpenGl_FrameBuffer::InitWrapper (const Handle(OpenGl_Context)&
     theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,  GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME, &aDepthId);
     myGlDepthRBufferId = aDepthId;
   }
-  else if (aDepthType != GL_NONE)
+  else if (aDepthType != 0)
   {
     TCollection_ExtendedString aMsg = "OpenGl_FrameBuffer::InitWrapper(), depth attachment of unsupported type has been skipped!";
     theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
@@ -422,8 +715,17 @@ void OpenGl_FrameBuffer::Release (OpenGl_Context* theGlCtx)
     myIsOwnBuffer      = false;
   }
 
-  myColorTexture->Release (theGlCtx);
-  myDepthStencilTexture->Release (theGlCtx);
+  for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < NbColorBuffers(); ++aColorBufferIdx)
+  {
+    myColorTextures (aColorBufferIdx)->Release (theGlCtx);
+  }
+
+  if (myIsOwnDepth)
+  {
+    myDepthStencilTexture->Release (theGlCtx);
+
+    myIsOwnDepth = false;
+  }
 
   myVPSizeX = 0;
   myVPSizeY = 0;
index 6baf4ff8b8d70c56361585a8a67eded4506e16b3..6f5c17088387a366d5a8205c6ef24fb3257c0978 100644 (file)
 #include <OpenGl_Resource.hxx>
 #include <OpenGl_Texture.hxx>
 
+#include <NCollection_Vector.hxx>
+
 class OpenGl_FrameBuffer;
 DEFINE_STANDARD_HANDLE(OpenGl_FrameBuffer, OpenGl_Resource)
 
+//! Short declaration of useful collection types.
+typedef NCollection_Vector<GLint> OpenGl_ColorFormats;
+
 //! Class implements FrameBuffer Object (FBO) resource
 //! intended for off-screen rendering.
 class OpenGl_FrameBuffer : public OpenGl_Resource
 {
-
 public:
 
   //! Helpful constants
@@ -35,7 +39,7 @@ public:
 
 public:
 
-  //! Empty constructor
+  //! Constructor.
   Standard_EXPORT OpenGl_FrameBuffer();
 
   //! Destructor
@@ -50,10 +54,16 @@ public:
     return myNbSamples;
   }
 
+  //! Number of color buffers.
+  GLsizei NbColorBuffers() const
+  {
+    return myColorTextures.Length();
+  }
+
   //! Return true if FBO has been created with color attachment.
-  bool HasColor() const
+  bool HasColor (const GLint theColorBufferIdx = 0) const
   {
-    return myColorFormat != 0;
+    return myColorFormats (theColorBufferIdx) != 0;
   }
 
   //! Return true if FBO has been created with depth attachment.
@@ -65,13 +75,13 @@ public:
   //! Textures width.
   GLsizei GetSizeX() const
   {
-    return myColorTexture->SizeX();
+    return myColorTextures (0)->SizeX();
   }
 
   //! Textures height.
   GLsizei GetSizeY() const
   {
-    return myColorTexture->SizeY();
+    return myColorTextures (0)->SizeY();
   }
 
   //! Viewport width.
@@ -92,13 +102,20 @@ public:
     return isValidFrameBuffer();
   }
 
+  Standard_EXPORT Standard_Boolean Init (const Handle(OpenGl_Context)& theGlCtx,
+                                         const GLsizei                 theSizeX,
+                                         const GLsizei                 theSizeY,
+                                         const OpenGl_ColorFormats&    theColorFormats,
+                                         const Handle(OpenGl_Texture)& theDepthStencilTexture,
+                                         const GLsizei                 theNbSamples = 0);
+
   //! Initialize FBO for rendering into textures.
-  //! @param theGlCtx       currently bound OpenGL context
-  //! @param theSizeX       texture width
-  //! @param theSizeY       texture height
-  //! @param theColorFormat color         texture sized format (0 means no color attachment), e.g. GL_RGBA8
-  //! @param theDepthFormat depth-stencil texture sized format (0 means no depth attachment), e.g. GL_DEPTH24_STENCIL8
-  //! @param theNbSamples   MSAA number of samples (0 means normal texture)
+  //! @param theGlCtx        currently bound OpenGL context
+  //! @param theSizeX        texture width
+  //! @param theSizeY        texture height
+  //! @param theColorFormat  color         texture sized format (0 means no color attachment), e.g. GL_RGBA8
+  //! @param theDepthFormat  depth-stencil texture sized format (0 means no depth attachment), e.g. GL_DEPTH24_STENCIL8
+  //! @param theNbSamples    MSAA number of samples (0 means normal texture)
   //! @return true on success
   Standard_EXPORT Standard_Boolean Init (const Handle(OpenGl_Context)& theGlCtx,
                                          const GLsizei                 theSizeX,
@@ -107,6 +124,21 @@ public:
                                          const GLint                   theDepthFormat,
                                          const GLsizei                 theNbSamples = 0);
 
+  //! Initialize FBO for rendering into textures.
+  //! @param theGlCtx        currently bound OpenGL context
+  //! @param theSizeX        texture width
+  //! @param theSizeY        texture height
+  //! @param theColorFormats color         texture sized format (0 means no color attachment), e.g. GL_RGBA8
+  //! @param theDepthFormat  depth-stencil texture sized format (0 means no depth attachment), e.g. GL_DEPTH24_STENCIL8
+  //! @param theNbSamples    MSAA number of samples (0 means normal texture)
+  //! @return true on success
+  Standard_EXPORT Standard_Boolean Init (const Handle(OpenGl_Context)& theGlCtx,
+                                         const GLsizei                 theSizeX,
+                                         const GLsizei                 theSizeY,
+                                         const OpenGl_ColorFormats&    theColorFormats,
+                                         const GLint                   theDepthFormat,
+                                         const GLsizei                 theNbSamples = 0);
+
   //! (Re-)initialize FBO with specified dimensions.
   Standard_EXPORT Standard_Boolean InitLazy (const Handle(OpenGl_Context)& theGlCtx,
                                              const GLsizei                 theViewportSizeX,
@@ -115,20 +147,25 @@ public:
                                              const GLint                   theDepthFormat,
                                              const GLsizei                 theNbSamples = 0);
 
+  //! (Re-)initialize FBO with specified dimensions.
+  Standard_EXPORT Standard_Boolean InitLazy (const Handle(OpenGl_Context)& theGlCtx,
+                                             const GLsizei                 theViewportSizeX,
+                                             const GLsizei                 theViewportSizeY,
+                                             const OpenGl_ColorFormats&    theColorFormats,
+                                             const GLint                   theDepthFormat,
+                                             const GLsizei                 theNbSamples = 0);
+
   //! (Re-)initialize FBO with properties taken from another FBO.
-  Standard_Boolean InitLazy (const Handle(OpenGl_Context)& theGlCtx,
-                             const OpenGl_FrameBuffer&     theFbo)
-  {
-    return InitLazy (theGlCtx, theFbo.myVPSizeX, theFbo.myVPSizeY, theFbo.myColorFormat, theFbo.myDepthFormat, theFbo.myNbSamples);
-  }
+  Standard_EXPORT Standard_Boolean InitLazy (const Handle(OpenGl_Context)& theGlCtx,
+                                             const OpenGl_FrameBuffer&     theFbo);
 
   //! (Re-)initialize FBO with specified dimensions.
   //! The Render Buffer Objects will be used for Color, Depth and Stencil attachments (as opposite to textures).
-  //! @param theGlCtx       currently bound OpenGL context
-  //! @param theSizeX       render buffer width
-  //! @param theSizeY       render buffer height
-  //! @param theColorFormat color         render buffer sized format, e.g. GL_RGBA8
-  //! @param theDepthFormat depth-stencil render buffer sized format, e.g. GL_DEPTH24_STENCIL8
+  //! @param theGlCtx        currently bound OpenGL context
+  //! @param theSizeX        render buffer width
+  //! @param theSizeY        render buffer height
+  //! @param theColorFormat  color         render buffer sized format, e.g. GL_RGBA8
+  //! @param theDepthFormat  depth-stencil render buffer sized format, e.g. GL_DEPTH24_STENCIL8
   //! @param theColorRBufferFromWindow when specified - should be ID of already initialized RB object, which will be released within this class
   Standard_EXPORT Standard_Boolean InitWithRB (const Handle(OpenGl_Context)& theGlCtx,
                                                const GLsizei                 theSizeX,
@@ -161,9 +198,9 @@ public:
   Standard_EXPORT virtual void UnbindBuffer (const Handle(OpenGl_Context)& theGlCtx);
 
   //! Returns the color texture.
-  inline const Handle(OpenGl_Texture)& ColorTexture() const
+  inline const Handle(OpenGl_Texture)& ColorTexture (const GLint theColorBufferIdx = 0) const
   {
-    return myColorTexture;
+    return myColorTextures (theColorBufferIdx);
   }
 
   //! Returns the depth-stencil texture.
@@ -193,16 +230,19 @@ protected:
 
 protected:
 
+  typedef NCollection_Vector<Handle(OpenGl_Texture)> OpenGl_TextureArray;
+
   GLsizei                myVPSizeX;             //!< viewport width  (should be <= texture width)
   GLsizei                myVPSizeY;             //!< viewport height (should be <= texture height)
   GLsizei                myNbSamples;           //!< number of MSAA samples
-  GLint                  myColorFormat;         //!< sized format for color         texture, GL_RGBA8 by default
+  OpenGl_ColorFormats    myColorFormats;        //!< sized format for color         texture, GL_RGBA8 by default
   GLint                  myDepthFormat;         //!< sized format for depth-stencil texture, GL_DEPTH24_STENCIL8 by default
   GLuint                 myGlFBufferId;         //!< FBO object ID
   GLuint                 myGlColorRBufferId;    //!< color         Render Buffer object (alternative to myColorTexture)
   GLuint                 myGlDepthRBufferId;    //!< depth-stencil Render Buffer object (alternative to myDepthStencilTexture)
   bool                   myIsOwnBuffer;         //!< flag indicating that FBO should be deallocated by this class
-  Handle(OpenGl_Texture) myColorTexture;        //!< color texture object
+  bool                   myIsOwnDepth;          //!< flag indicating that FBO should be deallocated by this class
+  OpenGl_TextureArray    myColorTextures;       //!< color texture objects
   Handle(OpenGl_Texture) myDepthStencilTexture; //!< depth-stencil texture object
 
 public:
index 37af4709affbb8ee485bac6758d3de2b1c79f9d0..05e0b27463cf0b93322ccd2ea9fe6c63467c8683 100644 (file)
   #define GL_DEBUG_SEVERITY_HIGH        0x9146
   #define GL_DEBUG_SEVERITY_MEDIUM      0x9147
   #define GL_DEBUG_SEVERITY_LOW         0x9148
+
+  // GL_EXT_draw_buffers
+  #define GL_MAX_COLOR_ATTACHMENTS       0x8CDF
+  #define GL_MAX_DRAW_BUFFERS            0x8824
+  #define GL_DRAW_BUFFER0                0x8825
+  #define GL_DRAW_BUFFER1                0x8826
+  #define GL_DRAW_BUFFER2                0x8827
+  #define GL_DRAW_BUFFER3                0x8828
+  #define GL_DRAW_BUFFER4                0x8829
+  #define GL_DRAW_BUFFER5                0x882A
+  #define GL_DRAW_BUFFER6                0x882B
+  #define GL_DRAW_BUFFER7                0x882C
+  #define GL_DRAW_BUFFER8                0x882D
+  #define GL_DRAW_BUFFER9                0x882E
+  #define GL_DRAW_BUFFER10               0x882F
+  #define GL_DRAW_BUFFER11               0x8830
+  #define GL_DRAW_BUFFER12               0x8831
+  #define GL_DRAW_BUFFER13               0x8832
+  #define GL_DRAW_BUFFER14               0x8833
+  #define GL_DRAW_BUFFER15               0x8834
+  #define GL_COLOR_ATTACHMENT0           0x8CE0
+  #define GL_COLOR_ATTACHMENT1           0x8CE1
+  #define GL_COLOR_ATTACHMENT2           0x8CE2
+  #define GL_COLOR_ATTACHMENT3           0x8CE3
+  #define GL_COLOR_ATTACHMENT4           0x8CE4
+  #define GL_COLOR_ATTACHMENT5           0x8CE5
+  #define GL_COLOR_ATTACHMENT6           0x8CE6
+  #define GL_COLOR_ATTACHMENT7           0x8CE7
+  #define GL_COLOR_ATTACHMENT8           0x8CE8
+  #define GL_COLOR_ATTACHMENT9           0x8CE9
+  #define GL_COLOR_ATTACHMENT10          0x8CEA
+  #define GL_COLOR_ATTACHMENT11          0x8CEB
+  #define GL_COLOR_ATTACHMENT12          0x8CEC
+  #define GL_COLOR_ATTACHMENT13          0x8CED
+  #define GL_COLOR_ATTACHMENT14          0x8CEE
+  #define GL_COLOR_ATTACHMENT15          0x8CEF
+
+  // OES_texture_half_float
+  #define GL_HALF_FLOAT                  0x8D61
 #endif
 
 #if !defined(HAVE_EGL) && (defined(__ANDROID__) || defined(__QNX__) || defined(HAVE_GLES2) || defined(OCCT_UWP))
@@ -752,6 +791,9 @@ public: //! @name OpenGL ES 3.0
   typedef void (*glTexImage3D_t)(GLenum target, GLint level, GLint internalFormat, GLsizei width, GLsizei height, GLsizei depth, GLint border, GLenum format, GLenum type, const GLvoid* data);
   glTexImage3D_t glTexImage3D;
 
+  typedef void (*glDrawBuffers_t)(GLsizei n, const GLenum* bufs);
+  glDrawBuffers_t glDrawBuffers;
+
 public: //! @name OpenGL ES 3.1
 
   typedef void (*glTexStorage2DMultisample_t)(GLenum target, GLsizei samples, GLenum internalformat, GLsizei width, GLsizei height, GLboolean fixedsamplelocations);
index c9bb46beeb37b78df302ff84894c990318e1a8d4..0e0554d4f5bdfae142745fe91ab88d20d8e36028 100644 (file)
@@ -687,7 +687,9 @@ void OpenGl_Layer::Render (const Handle(OpenGl_Workspace)&   theWorkspace,
   theWorkspace->SetPolygonOffset (myLayerSettings.PolygonOffset());
 
   // handle depth write
-  theWorkspace->UseDepthWrite() = myLayerSettings.ToEnableDepthWrite();
+  theWorkspace->UseDepthWrite() = myLayerSettings.ToEnableDepthWrite()
+                               && theDefaultSettings.DepthMask == GL_TRUE;
+
   glDepthMask (theWorkspace->UseDepthWrite() ? GL_TRUE : GL_FALSE);
 
   const Standard_Boolean hasLocalCS = !myLayerSettings.OriginTransformation().IsNull();
index 57edf25f96352ab2e9fa6b74b2878499510e2611..6a215e20ba52fefaa52821fc9ab2c1ac13cc8814 100644 (file)
@@ -27,7 +27,6 @@
 #include <Graphic3d_Camera.hxx>
 #include <OpenGl_GlCore11.hxx>
 
-
 struct OpenGl_GlobalLayerSettings
 {
   GLint DepthFunc;
index 5f6c61973c4fa7e52da55fe5ade50418237765a5..d239cc1f9b93af94fa793c9cf79b645242548796 100644 (file)
 // Alternatively, this file may be used under the terms of Open CASCADE
 // commercial license or contractual agreement.
 
-#include <OpenGl_GlCore11.hxx>
+#include <OpenGl_GlCore15.hxx>
 
+#include <OpenGl_FrameBuffer.hxx>
 #include <OpenGl_LayerList.hxx>
+#include <OpenGl_ShaderManager.hxx>
 #include <OpenGl_Structure.hxx>
+#include <OpenGl_VertexBuffer.hxx>
+#include <OpenGl_View.hxx>
 #include <OpenGl_Workspace.hxx>
 
 #include <Graphic3d_GraphicDriver.hxx>
@@ -31,7 +35,9 @@ OpenGl_LayerList::OpenGl_LayerList (const Standard_Integer theNbPriorities)
   myNbPriorities (theNbPriorities),
   myNbStructures (0),
   myImmediateNbStructures (0),
-  myModifStateOfRaytraceable (0)
+  myModifStateOfRaytraceable (0),
+  myRenderOpaqueFilter (new OpenGl_OpaqueFilter()),
+  myRenderTranspFilter (new OpenGl_TransparentFilter())
 {
   // insert default priority layers
   myLayers.Append (OpenGl_Layer (myNbPriorities));
@@ -50,6 +56,8 @@ OpenGl_LayerList::OpenGl_LayerList (const Standard_Integer theNbPriorities)
   myLayerIds.Bind (Graphic3d_ZLayerId_TopOSD,  myLayers.Upper());
 
   myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
+
+  myTransparentToProcess.Allocate (myLayers.Length());
 }
 
 //=======================================================================
@@ -76,6 +84,8 @@ void OpenGl_LayerList::AddLayer (const Graphic3d_ZLayerId theLayerId)
   // add the new layer
   myLayers.Append (OpenGl_Layer (myNbPriorities));
   myLayerIds.Bind (theLayerId, myLayers.Length());
+
+  myTransparentToProcess.Allocate (myLayers.Length());
 }
 
 //=======================================================================
@@ -128,6 +138,8 @@ void OpenGl_LayerList::RemoveLayer (const Graphic3d_ZLayerId theLayerId)
   }
 
   myDefaultLayerIndex = myLayerIds.Find (Graphic3d_ZLayerId_Default);
+
+  myTransparentToProcess.Allocate (myLayers.Length());
 }
 
 //=======================================================================
@@ -378,17 +390,39 @@ void OpenGl_LayerList::SetLayerSettings (const Graphic3d_ZLayerId        theLaye
 //=======================================================================
 void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
                                const Standard_Boolean          theToDrawImmediate,
-                               const OpenGl_LayerFilter        theLayersToProcess) const
+                               const OpenGl_LayerFilter        theLayersToProcess,
+                               OpenGl_FrameBuffer*             theReadDrawFbo,
+                               OpenGl_FrameBuffer*             theOitAccumFbo) const
 {
+  // Remember global settings for glDepth function and write mask.
   OpenGl_GlobalLayerSettings aDefaultSettings;
 
   const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext();
   aCtx->core11fwd->glGetIntegerv (GL_DEPTH_FUNC,      &aDefaultSettings.DepthFunc);
   aCtx->core11fwd->glGetBooleanv (GL_DEPTH_WRITEMASK, &aDefaultSettings.DepthMask);
 
+  // Two render filters are used to support transparency draw. Opaque filter accepts
+  // only non-transparent OpenGl elements of a layer and counts number of skipped
+  // transparent ones. If the counter has positive value the layer is added into
+  // transparency post-processing stack. At the end of drawing or once the depth
+  // buffer is to be cleared the layers in the stack should be drawn using
+  // blending and depth mask settings and another transparency filter which accepts
+  // only transparent OpenGl elements of a layer. The stack <myTransparentToProcess>
+  // was preallocated before going into this method and has enough space to keep
+  // maximum number of references to layers, therefore it will not increase memory
+  // fragmentation during regular rendering.
+  const Handle(OpenGl_RenderFilter) aPrevFilter = theWorkspace->GetRenderFilter();
+  myRenderOpaqueFilter->SetPreviousFilter (aPrevFilter);
+  myRenderTranspFilter->SetPreviousFilter (aPrevFilter);
+  theWorkspace->SetRenderFilter (myRenderOpaqueFilter);
+
+  myTransparentToProcess.Clear();
+
+  OpenGl_LayerStack      ::iterator aStackIter (myTransparentToProcess.Origin());
+  OpenGl_SequenceOfLayers::iterator anIts (myLayers.begin());
   Standard_Integer aSeqId = myLayers.Lower();
-  bool toClearDepth = false;
-  for (OpenGl_SequenceOfLayers::Iterator anIts (myLayers); anIts.More(); anIts.Next(), ++aSeqId)
+  bool toClearDepth     = false;
+  for (; anIts != myLayers.end(); ++anIts, ++aSeqId)
   {
     if (theLayersToProcess == OpenGl_LF_Bottom)
     {
@@ -403,28 +437,54 @@ void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
       if (aSeqId != myDefaultLayerIndex) continue;
     }
 
-    const OpenGl_Layer& aLayer = anIts.Value();
+    const OpenGl_Layer& aLayer = (*anIts);
     if (aLayer.IsImmediate() != theToDrawImmediate)
     {
       continue;
     }
     else if (aLayer.NbStructures() < 1)
     {
-      // make sure to clear depth of previous layers even if layer has no structures
+      // Make sure to clear depth of previous layers even if layer has no structures.
       toClearDepth = toClearDepth || aLayer.LayerSettings().ToClearDepth();
       continue;
     }
 
-    // depth buffers
+    // At this point the depth buffer may be set to clear by
+    // previous configuration of layers or configuration of the
+    // current layer. Additional rendering pass to handle transparent
+    // elements of recently drawn layers require use of current depth
+    // buffer so we put remaining layers for processing as one bunch before
+    // erasing the depth buffer.
     if (toClearDepth
      || aLayer.LayerSettings().ToClearDepth())
     {
+      if (!myTransparentToProcess.IsEmpty())
+      {
+        renderTransparent (theWorkspace, aStackIter, aDefaultSettings, theReadDrawFbo, theOitAccumFbo);
+      }
+
       toClearDepth = false;
       glDepthMask (GL_TRUE);
       glClear (GL_DEPTH_BUFFER_BIT);
     }
 
+    // Render opaque OpenGl elements of a layer and count the number of skipped.
+    // If a layer has skipped (e.g. transparent) elements it should be added into
+    // the transparency post-processing stack.
+    myRenderOpaqueFilter->SetSkippedCounter (0);
+
     aLayer.Render (theWorkspace, aDefaultSettings);
+
+    if (myRenderOpaqueFilter->NbSkipped() > 0)
+    {
+      myTransparentToProcess.Push (&aLayer);
+    }
+  }
+
+  // Before finishing process the remaining collected layers with transparency.
+  if (!myTransparentToProcess.IsEmpty())
+  {
+    renderTransparent (theWorkspace, aStackIter, aDefaultSettings, theReadDrawFbo, theOitAccumFbo);
   }
 
   if (toClearDepth)
@@ -435,4 +495,232 @@ void OpenGl_LayerList::Render (const Handle(OpenGl_Workspace)& theWorkspace,
 
   aCtx->core11fwd->glDepthMask (aDefaultSettings.DepthMask);
   aCtx->core11fwd->glDepthFunc (aDefaultSettings.DepthFunc);
+
+  theWorkspace->SetRenderFilter (aPrevFilter);
+}
+
+//=======================================================================
+//function : renderTransparent
+//purpose  : Render transparent objects using blending operator.
+//=======================================================================
+void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)&   theWorkspace,
+                                          OpenGl_LayerStack::iterator&      theLayerIter,
+                                          const OpenGl_GlobalLayerSettings& theGlobalSettings,
+                                          OpenGl_FrameBuffer*               theReadDrawFbo,
+                                          OpenGl_FrameBuffer*               theOitAccumFbo) const
+{
+  // Blended order-independent transparency algorithm require several preconditions
+  // to be enabled. It should be requested by user, at least two outputs from
+  // fragment shader should be supported by GPU, so is the given framebuffer
+  // should contain two additional color buffers to handle accumulated color channels,
+  // blended alpha channel and weight factors - these accumulation buffers are required
+  // to implement commuting blend operator (at least OpenGl 2.0 should be available).
+  const bool isEnabledOit = theOitAccumFbo != NULL
+                         && theOitAccumFbo->NbColorBuffers() >= 2
+                         && theOitAccumFbo->ColorTexture (0)->IsValid()
+                         && theOitAccumFbo->ColorTexture (1)->IsValid();
+
+  // Check if current iterator has already reached the end of the stack.
+  // This should happen if no additional layers has been added to
+  // the processing stack after last transparency pass.
+  if (theLayerIter == myTransparentToProcess.Back())
+  {
+    return;
+  }
+
+  const Handle(OpenGl_Context) aCtx            = theWorkspace->GetGlContext();
+  const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
+  const OpenGl_View* aView                     = theWorkspace->View();
+  const float aOitDepthWeight = aView ? aView->RenderingParams().OitDepthWeight : 0.0f;
+
+  theWorkspace->SetRenderFilter (myRenderTranspFilter);
+
+  aCtx->core11fwd->glEnable (GL_BLEND);
+
+  if (isEnabledOit)
+  {
+    aManager->SetOitState (true, aOitDepthWeight);
+
+    theOitAccumFbo->BindBuffer (aCtx);
+
+    static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT1 };
+    aCtx->SetDrawBuffers (2, aDrawBuffers);
+    aCtx->core11fwd->glClearColor (0.f, 0.f, 0.f, 1.f);
+    aCtx->core11fwd->glClear (GL_COLOR_BUFFER_BIT);
+    aCtx->core15fwd->glBlendFuncSeparate (GL_ONE, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
+  }
+  else
+  {
+    aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+  }
+
+  // During blended order-independent transparency pass the depth test
+  // should be enabled to discard fragments covered by opaque geometry
+  // and depth writing should be disabled, because transparent fragments
+  // overal each other with non unitary coverage factor.
+  OpenGl_GlobalLayerSettings aGlobalSettings = theGlobalSettings;
+  aGlobalSettings.DepthMask   = GL_FALSE;
+  aCtx->core11fwd->glDepthMask (GL_FALSE);
+
+  for (; theLayerIter != myTransparentToProcess.Back(); ++theLayerIter)
+  {
+    (*theLayerIter)->Render (theWorkspace, aGlobalSettings);
+  }
+
+  // Revert state of rendering.
+  if (isEnabledOit)
+  {
+    aManager->SetOitState (false, aOitDepthWeight);
+
+    theOitAccumFbo->UnbindBuffer (aCtx);
+
+    if (theReadDrawFbo)
+    {
+      theReadDrawFbo->BindBuffer (aCtx);
+    }
+
+    static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
+
+    aCtx->SetDrawBuffers (1, aDrawBuffers);
+  }
+
+  theWorkspace->SetRenderFilter (myRenderOpaqueFilter);
+
+  if (isEnabledOit)
+  {
+    const Standard_Boolean isMSAA = theReadDrawFbo && theReadDrawFbo->NbSamples() > 0;
+
+    OpenGl_VertexBuffer* aVerts = theWorkspace->View()->initBlitQuad (Standard_False);
+
+    if (aVerts->IsValid() && aManager->BindOitCompositingProgram (isMSAA))
+    {
+      aCtx->core11fwd->glDepthFunc (GL_ALWAYS);
+      aCtx->core11fwd->glDepthMask (GL_FALSE);
+
+      // Bind full screen quad buffer and framebuffer resources.
+      aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
+
+      const Handle(OpenGl_Texture) aTextureBack = theWorkspace->DisableTexture();
+
+      theOitAccumFbo->ColorTexture (0)->Bind (aCtx, GL_TEXTURE0 + 0);
+      theOitAccumFbo->ColorTexture (1)->Bind (aCtx, GL_TEXTURE0 + 1);
+
+      // Draw full screen quad with special shader to compose the buffers.
+      aCtx->core11fwd->glBlendFunc (GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA);
+      aCtx->core11fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
+
+      // Unbind OpenGL texture objects and shader program.
+      aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
+      theOitAccumFbo->ColorTexture (0)->Unbind (aCtx, GL_TEXTURE0 + 0);
+      theOitAccumFbo->ColorTexture (1)->Unbind (aCtx, GL_TEXTURE0 + 1);
+      aCtx->BindProgram (NULL);
+
+      if (!aTextureBack.IsNull())
+      {
+        theWorkspace->EnableTexture (aTextureBack);
+      }
+    }
+    else
+    {
+      TCollection_ExtendedString aMsg = TCollection_ExtendedString()
+                                      + "Initialization of OIT compositing pass has failed.\n"
+                                      + "  Blended order-independent transparency will not be available.\n";
+      aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                         GL_DEBUG_TYPE_ERROR,
+                         0,
+                         GL_DEBUG_SEVERITY_HIGH,
+                        aMsg);
+      OpenGl_View* aView = theWorkspace->View();
+      if (aView)
+      {
+        Standard_Boolean& aOITFlag = isMSAA ? aView->myToDisableOITMSAA : aView->myToDisableOIT;
+        aOITFlag = Standard_True;
+      }
+    }
+  }
+
+  aCtx->core11fwd->glDisable (GL_BLEND);
+  aCtx->core11fwd->glBlendFunc (GL_ONE, GL_ZERO);
+  aCtx->core11fwd->glDepthMask (theGlobalSettings.DepthMask);
+  aCtx->core11fwd->glDepthFunc (theGlobalSettings.DepthFunc);
+}
+
+//=======================================================================
+//class    : OpenGl_OpaqueFilter
+//function : ShouldRender
+//purpose  : Checks whether the element should be rendered or skipped.
+//=======================================================================
+Standard_Boolean OpenGl_LayerList::OpenGl_OpaqueFilter::ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
+                                                                      const OpenGl_Element*           theGlElement)
+{
+  if (!myFilter.IsNull() && !myFilter->ShouldRender (theWorkspace, theGlElement))
+  {
+    return Standard_False;
+  }
+
+  const OpenGl_PrimitiveArray* aPArray = dynamic_cast<const OpenGl_PrimitiveArray*> (theGlElement);
+  if (aPArray != NULL
+      && aPArray->DrawMode() >= OpenGl_PrimitiveArray::THE_FILLPRIM_FROM
+      && aPArray->DrawMode() <= OpenGl_PrimitiveArray::THE_FILLPRIM_TO)
+  {
+    const OpenGl_AspectFace* anAspect = theWorkspace->ApplyAspectFace();
+    if (anAspect)
+    {
+      const bool toDistinguish = anAspect->Aspect()->Distinguish();
+      const Graphic3d_MaterialAspect& aMatFrontSrc = anAspect->Aspect()->FrontMaterial();
+      const Graphic3d_MaterialAspect& aMatBackSrc  = toDistinguish
+                                                    ? anAspect->Aspect()->BackMaterial()
+                                                    : aMatFrontSrc;
+
+      const Standard_Size aSkippedCounter  = mySkippedCounter;
+      if (((float)aMatFrontSrc.Transparency() > ShortRealEpsilon())
+       || ((float)aMatBackSrc .Transparency() > ShortRealEpsilon()))
+      {
+        mySkippedCounter++;
+      }
+
+      return mySkippedCounter == aSkippedCounter;
+    }
+  }
+
+  return Standard_True;
+}
+
+//=======================================================================
+//class    : OpenGl_TransparentFilter
+//function : ShouldRender
+//purpose  : Checks whether the element should be rendered or skipped.
+//=======================================================================
+Standard_Boolean OpenGl_LayerList::OpenGl_TransparentFilter::ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
+                                                                           const OpenGl_Element*           theGlElement)
+{
+  if (!myFilter.IsNull() && !myFilter->ShouldRender (theWorkspace, theGlElement))
+  {
+    return Standard_False;
+  }
+
+  const OpenGl_PrimitiveArray* aPArray = dynamic_cast<const OpenGl_PrimitiveArray*> (theGlElement);
+  if (aPArray != NULL
+      && aPArray->DrawMode() >= OpenGl_PrimitiveArray::THE_FILLPRIM_FROM
+      && aPArray->DrawMode() <= OpenGl_PrimitiveArray::THE_FILLPRIM_TO)
+  {
+    const OpenGl_AspectFace* anAspect = theWorkspace->ApplyAspectFace();
+    if (anAspect)
+    {
+      const bool toDistinguish = anAspect->Aspect()->Distinguish();
+      const Graphic3d_MaterialAspect& aMatFrontSrc = anAspect->Aspect()->FrontMaterial();
+      const Graphic3d_MaterialAspect& aMatBackSrc  = toDistinguish
+                                                    ? anAspect->Aspect()->BackMaterial()
+                                                    : aMatFrontSrc;
+
+      return ((float)aMatFrontSrc.Transparency() > ShortRealEpsilon())
+          || ((float)aMatBackSrc .Transparency() > ShortRealEpsilon());
+    }
+  }
+  else
+  {
+    return dynamic_cast<const OpenGl_AspectFace*> (theGlElement) != NULL;
+  }
+
+  return Standard_False;
 }
index cd45cc3fd0cab61324f6d7125936811d63761017..7b1c2f1086a610f31145d8b5b4ccffce4c2e7d13 100644 (file)
@@ -19,6 +19,8 @@
 #include <OpenGl_Layer.hxx>
 #include <OpenGl_LayerFilter.hxx>
 
+#include <NCollection_Array1.hxx>
+#include <NCollection_Handle.hxx>
 #include <NCollection_Sequence.hxx>
 #include <NCollection_DataMap.hxx>
 
@@ -89,7 +91,9 @@ public:
   //! Render this element
   void Render (const Handle(OpenGl_Workspace)& theWorkspace,
                const Standard_Boolean          theToDrawImmediate,
-               const OpenGl_LayerFilter        theLayersToProcess) const;
+               const OpenGl_LayerFilter        theLayersToProcess,
+               OpenGl_FrameBuffer*             theReadDrawFbo,
+               OpenGl_FrameBuffer*             theOitAccumFbo) const;
 
   //! Returns the set of OpenGL Z-layers.
   const OpenGl_SequenceOfLayers& Layers() const { return myLayers; }
@@ -104,6 +108,132 @@ public:
   //! Returns structure modification state (for ray-tracing).
   Standard_Size ModificationStateOfRaytracable() const { return myModifStateOfRaytraceable; }
 
+protected:
+
+  //! Filter of TKOpenGl elements for processing only shading geometry and
+  //! for collecting number of skipped elements to an external counter.
+  class OpenGl_OpaqueFilter : public OpenGl_RenderFilter
+  {
+  public:
+
+    //! Constructor.
+    //! @param thePrevFilter [in] the previously active filter that should have additive effect.
+    OpenGl_OpaqueFilter() : mySkippedCounter (0) {}
+
+    //! Sets the current active filter in workspace.
+    //! @param thePrevFilter [in] the previously active filter that should have additive effect.
+    void SetPreviousFilter (const Handle(OpenGl_RenderFilter)& thePrevFitler) { myFilter = thePrevFitler; }
+
+    //! Sets the value of the skipped elements counter.
+    void SetSkippedCounter (const Standard_Size theCounter) { mySkippedCounter = theCounter; }
+
+    //! Returns number of skipped elements.
+    Standard_Size NbSkipped() const { return mySkippedCounter; }
+
+    //! Checks whether the element should be rendered or skipped.
+    //! @param theWorkspace [in] the currently used workspace for rendering.
+    //! @param theGlElement [in] the TKOpenGl rendering queue element that should be checked before streaming to GPU.
+    Standard_EXPORT virtual Standard_Boolean ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
+                                                           const OpenGl_Element*           theGlElement) Standard_OVERRIDE;
+
+    DEFINE_STANDARD_RTTI_INLINE (OpenGl_OpaqueFilter, OpenGl_RenderFilter)
+
+  private:
+
+    Standard_Size mySkippedCounter;   //!< Counter of skipped elements.
+    Handle(OpenGl_RenderFilter) myFilter; //!< Previous active filter that should be combined.
+  };
+
+  //! Filter of TKOpenGl elements for keeping only shading geometry with transparency.
+  class OpenGl_TransparentFilter : public OpenGl_RenderFilter
+  {
+  public:
+
+    //! Constructor.
+    OpenGl_TransparentFilter() {}
+
+    //! Sets the current active filter in workspace.
+    //! @param thePrevFilter [in] the previously active filter that should have additive effect.
+    void SetPreviousFilter (const Handle(OpenGl_RenderFilter)& thePrevFitler) { myFilter = thePrevFitler; }
+
+    //! Checks whether the element should be rendered or skipped.
+    //! @param theWorkspace [in] the currently used workspace for rendering.
+    //! @param theGlElement [in] the TKOpenGl rendering queue element that should be checked before streaming to GPU.
+    Standard_EXPORT virtual Standard_Boolean ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
+                                                           const OpenGl_Element*           theGlElement) Standard_OVERRIDE;
+
+    DEFINE_STANDARD_RTTI_INLINE (OpenGl_TransparentFilter, OpenGl_RenderFilter)
+
+  private:
+
+    Handle(OpenGl_RenderFilter) myFilter; //!< Previous active filter that should be combined.
+  };
+
+  //! Stack of references to existing layers of predefined maximum size.
+  class OpenGl_LayerStack
+  {
+  public:
+    typedef NCollection_Array1<const OpenGl_Layer*>::iterator iterator;
+
+    //! Reallocate internal buffer of the stack.
+    void Allocate (const Standard_Integer theSize)
+    {
+      if (theSize > 0)
+      {
+        myStackSpace = new NCollection_Array1<const OpenGl_Layer*> (1, theSize);
+        myStackSpace->Init (NULL);
+        myBackPtr    = myStackSpace->begin();
+      }
+      else
+      {
+        myStackSpace.Nullify();
+        myBackPtr = iterator();
+      }
+    }
+
+    //! Clear stack.
+    void Clear()
+    {
+      if (myStackSpace)
+      {
+        myStackSpace->Init (NULL);
+        myBackPtr = myStackSpace->begin();
+      }
+    }
+
+    //! Push a new layer reference to the stack.
+    void Push (const OpenGl_Layer* theLayer) { (*myBackPtr++) = theLayer; }
+
+    //! Returns iterator to the origin of the stack.
+    iterator Origin() const { return myStackSpace.IsNull() ? iterator() : myStackSpace->begin(); }
+
+    //! Returns iterator to the back of the stack (after last item added).
+    iterator Back() const { return myBackPtr; }
+
+    //! Returns true if nothing has been pushed into the stack.
+    Standard_Boolean IsEmpty() const { return Back() == Origin(); }
+
+  private:
+
+    NCollection_Handle<NCollection_Array1<const OpenGl_Layer*> > myStackSpace;
+    iterator                                                     myBackPtr;
+  };
+
+  //! Render transparent objects using blending operator.
+  //! Additional accumulation framebuffer is used for blended order-independent
+  //! transparency algorithm. It should support floating-point color components
+  //! and share depth with main reading/drawing framebuffer.
+  //! @param theWorkspace [in] the currently used workspace for rendering.
+  //! @param theLayerIter [in/out] the current iterator of transparent layers to process.
+  //! @param theGlobalSettings [in] the set of global settings used for rendering.
+  //! @param theReadDrawFbo [in] the framebuffer for reading depth and writing final color.
+  //! @param theOitAccumFbo [in] the framebuffer for accumulating color and coverage for OIT process.
+  void renderTransparent (const Handle(OpenGl_Workspace)&   theWorkspace,
+                          OpenGl_LayerStack::iterator&      theLayerIter,
+                          const OpenGl_GlobalLayerSettings& theGlobalSettings,
+                          OpenGl_FrameBuffer*               theReadDrawFbo,
+                          OpenGl_FrameBuffer*               theOitAccumFbo) const;
+
 protected:
 
   // number of structures temporary put to default layer
@@ -117,6 +247,12 @@ protected:
 
   mutable Standard_Size   myModifStateOfRaytraceable;
 
+  //! Collection of references to layers with transparency gathered during rendering pass.
+  mutable OpenGl_LayerStack myTransparentToProcess;
+
+  Handle(OpenGl_OpaqueFilter)      myRenderOpaqueFilter; //!< rendering filter for opaque drawing pass (blended OIT).
+  Handle(OpenGl_TransparentFilter) myRenderTranspFilter; //!< rendering filter for transparency drawing pass (blended OIT).
+
 public:
 
   DEFINE_STANDARD_ALLOC
diff --git a/src/OpenGl/OpenGl_OitUniformState.hxx b/src/OpenGl/OpenGl_OitUniformState.hxx
new file mode 100644 (file)
index 0000000..9e1cff8
--- /dev/null
@@ -0,0 +1,55 @@
+// Created on: 2017-01-26
+// Created by: Anton POLETAEV
+// Copyright (c) 2017 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_OitUniformState_HeaderFile
+#define _OpenGl_OitUniformState_HeaderFile
+
+#include <OpenGl_ShaderStates.hxx>
+
+//! Defines generic state of order-independent transparency rendering properties.
+class OpenGl_OitUniformState : public OpenGl_StateInterface
+{
+public:
+
+  //! Creates new uniform state.
+  OpenGl_OitUniformState() : myToEnableWrite (false), myDepthWeight (0.5f) {}
+
+  //! Sets the uniform values.
+  //! @param theToEnableWrite [in] flag indicating whether color and coverage
+  //!  values for OIT processing should be written by shader program.
+  //! @param theDepthWeight [in] scalar factor [0-1] defining influence of depth
+  //!  component of a fragment to its final coverage coefficient.
+  void Set (const bool  theToEnableWrite,
+            const float theDepthWeight)
+  {
+    myToEnableWrite = theToEnableWrite;
+    myDepthWeight   = Max (0.f, Min (1.f, theDepthWeight));
+  }
+
+  //! Returns flag indicating whether writing of output for OIT processing
+  //! should be enabled/disabled.
+  bool ToEnableWrite() const { return myToEnableWrite; }
+
+  //! Returns factor defining influence of depth component of a fragment
+  //! to its final coverage coefficient.
+  float DepthWeight() const { return myDepthWeight; }
+
+private:
+
+  bool  myToEnableWrite; //!< writing color and coverage.
+  float myDepthWeight;   //!< factor of depth influence to coverage.
+};
+
+#endif // _OpenGl_OitUniformState_HeaderFile
index 167dfe22986b920656cce4e54784e323a27a0c7e..fccdcb07de2e04412a9d4f677bb8d98d27effc07 100644 (file)
@@ -40,6 +40,14 @@ public:
     DRAW_MODE_NONE = -1
   };
 
+#if !defined(GL_ES_VERSION_2_0)
+  static const GLint THE_FILLPRIM_FROM = GL_TRIANGLES;
+  static const GLint THE_FILLPRIM_TO   = GL_POLYGON;
+#else
+  static const GLint THE_FILLPRIM_FROM = GL_TRIANGLES;
+  static const GLint THE_FILLPRIM_TO   = GL_TRIANGLE_FAN;
+#endif
+
   //! Empty constructor
   Standard_EXPORT OpenGl_PrimitiveArray (const OpenGl_GraphicDriver* theDriver);
 
index a82a1cc4456e2bae38e5d9f8fc2197e1a4c5b649..ac1a156227dbd3e15918fff3042613aba5131977 100755 (executable)
@@ -23,6 +23,7 @@ class OpenGl_RenderFilter;
 DEFINE_STANDARD_HANDLE (OpenGl_RenderFilter, Standard_Transient)
 
 class OpenGl_Element;
+class OpenGl_Workspace;
 
 //! Base class for defining element rendering filters.
 //! This class can be used in pair with advance rendering passes, and for 
@@ -32,13 +33,14 @@ class OpenGl_RenderFilter : public Standard_Transient
 public:
 
   //! Checks whether the element can be rendered or not.
+  //! @param theWorkspace [in] the current workspace.
   //! @param theElement [in] the element to check.
   //! @return True if element can be rendered.
-  virtual Standard_Boolean CanRender (const OpenGl_Element* theElement) = 0;
+  virtual Standard_Boolean ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace, const OpenGl_Element* theElement) = 0;
 
 public:
 
-  DEFINE_STANDARD_RTTIEXT(OpenGl_RenderFilter,Standard_Transient)
+  DEFINE_STANDARD_RTTIEXT(OpenGl_RenderFilter, Standard_Transient)
 };
 
 #endif
index c4977b6a68ee6efdeebd0dbf716fe991c7fc523b..6bfd58a08a61751e72b1ed0539483dadedbb6dac 100644 (file)
@@ -31,7 +31,8 @@ enum OpenGl_ProgramOptions
   OpenGl_PO_ClipPlanes1 = 0x040, //!< handle 1 clipping plane
   OpenGl_PO_ClipPlanes2 = 0x080, //!< handle 2 clipping planes
   OpenGl_PO_ClipPlanesN = 0x100, //!< handle N clipping planes
-  OpenGl_PO_NB          = 0x200  //!< overall number of combinations
+  OpenGl_PO_WriteOit    = 0x200, //!< write color/coverage buffer for blended order independet transparency
+  OpenGl_PO_NB          = 0x400  //!< overall number of combinations
 };
 
 //! Alias to programs array of predefined length
index 991824cc76d8ac92e8221402cce16e922fa1d41a..7feee964d11cbc8650a6f66ad0d98f323f200898 100644 (file)
@@ -331,6 +331,12 @@ const char THE_FRAG_CLIP_PLANES_2[] =
   }
 #endif
 
+//! Output color and coverage for accumulation by OIT algorithm.
+const char THE_FRAG_write_oit_buffers[] =
+  EOL"  float aWeight     = occFragColor.a * clamp (1e+2 * pow (1.0 - gl_FragCoord.z * occOitDepthWeight, 3.0), 1e-2, 1e+2);"
+  EOL"  occFragCoverage.r = occFragColor.a * aWeight;"
+  EOL"  occFragColor      = vec4 (occFragColor.rgb * occFragColor.a * aWeight, occFragColor.a);";
+
 }
 
 // =======================================================================
@@ -1069,6 +1075,37 @@ void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)
   }
 }
 
+// =======================================================================
+// function : PushOitUniformState
+// purpose  : Pushes state of OIT uniforms to the specified program
+// =======================================================================
+void OpenGl_ShaderManager::PushOitUniformState (const Handle(OpenGl_ShaderProgram)& theProgram) const
+{
+  if (!theProgram->IsValid())
+  {
+    return;
+  }
+
+  if (myOitUniformState.Index() == theProgram->ActiveState (OpenGL_OIT_UNIFORM_STATE))
+  {
+    return;
+  }
+
+  const GLint aLocEnableWrite = theProgram->GetStateLocation (OpenGl_OCCT_OIT_ENABLE_WRITE);
+  if (aLocEnableWrite != OpenGl_ShaderProgram::INVALID_LOCATION)
+  {
+    theProgram->SetUniform (myContext, aLocEnableWrite,
+                            myOitUniformState.ToEnableWrite());
+  }
+
+  const GLint aLocDepthWeight = theProgram->GetStateLocation (OpenGl_OCCT_OIT_DEPTH_WEIGHT);
+  if (aLocDepthWeight != OpenGl_ShaderProgram::INVALID_LOCATION)
+  {
+    theProgram->SetUniform (myContext, aLocDepthWeight,
+                            myOitUniformState.DepthWeight());
+  }
+}
+
 // =======================================================================
 // function : PushState
 // purpose  : Pushes state of OCCT graphics parameters to the program
@@ -1082,6 +1119,7 @@ void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& thePro
   PushProjectionState  (aProgram);
   PushLightSourceState (aProgram);
   PushMaterialState    (aProgram);
+  PushOitUniformState  (aProgram);
 }
 
 // =======================================================================
@@ -1208,6 +1246,82 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit()
   return Standard_True;
 }
 
+// =======================================================================
+// function : prepareStdProgramOitCompositing
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const Standard_Boolean theMsaa)
+{
+  Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram [theMsaa ? 1 : 0];
+  Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
+  TCollection_AsciiString aSrcVert, aSrcFrag;
+
+  aSrcVert =
+    EOL"THE_SHADER_OUT vec2 TexCoord;"
+    EOL"void main()"
+    EOL"{"
+    EOL"  TexCoord    = occVertex.zw;"
+    EOL"  gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
+    EOL"}";
+
+  if (!theMsaa)
+  {
+    aSrcFrag =
+      EOL"uniform sampler2D uAccumTexture;"
+      EOL"uniform sampler2D uWeightTexture;"
+      EOL
+      EOL"THE_SHADER_IN vec2 TexCoord;"
+      EOL
+      EOL"void main()"
+      EOL"{"
+      EOL"  vec4 aAccum   = occTexture2D (uAccumTexture,  TexCoord);"
+      EOL"  float aWeight = occTexture2D (uWeightTexture, TexCoord).r;"
+      EOL"  occFragColor = vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a);"
+      EOL"}";
+
+    if (myContext->IsGlGreaterEqual (3, 2))
+    {
+      aProgramSrc->SetHeader ("#version 150");
+    }
+  }
+  else
+  {
+    aSrcFrag =
+      EOL"uniform sampler2DMS uAccumTexture;"
+      EOL"uniform sampler2DMS uWeightTexture;"
+      EOL
+      EOL"THE_SHADER_IN vec2 TexCoord;"
+      EOL
+      EOL"void main()"
+      EOL"{"
+      EOL"  ivec2 aTexel  = ivec2 (textureSize (uAccumTexture) * TexCoord);"
+      EOL"  vec4 aAccum   = texelFetch (uAccumTexture,  aTexel, gl_SampleID);"
+      EOL"  float aWeight = texelFetch (uWeightTexture, aTexel, gl_SampleID).r;"
+      EOL"  occFragColor = vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a);"
+      EOL"}";
+
+    if (myContext->IsGlGreaterEqual (4, 0))
+    {
+      aProgramSrc->SetHeader ("#version 400");
+    }
+  }
+
+  aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX,   aSrcVert));
+  aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
+  TCollection_AsciiString aKey;
+  if (!Create (aProgramSrc, aKey, aProgram))
+  {
+    aProgram = new OpenGl_ShaderProgram(); // just mark as invalid
+    return Standard_False;
+  }
+
+  myContext->BindProgram (aProgram);
+  aProgram->SetSampler (myContext, "uAccumTexture", 0);
+  aProgram->SetSampler (myContext, "uWeightTexture", 1);
+  myContext->BindProgram (NULL);
+  return Standard_True;
+}
+
 // =======================================================================
 // function : pointSpriteAlphaSrc
 // purpose  :
@@ -1249,7 +1363,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
                                                               const Standard_Integer        theBits)
 {
   Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
-  TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
+  TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha, aSrcFrag;
+  TCollection_AsciiString aSrcFragExtraOut, aSrcFragExtraMain, aSrcFragWriteOit;
   TCollection_AsciiString aSrcFragGetColor     = EOL"vec4 getColor(void) { return occColor; }";
   TCollection_AsciiString aSrcFragMainGetColor = EOL"  occFragColor = getColor();";
   if ((theBits & OpenGl_PO_Point) != 0)
@@ -1351,6 +1466,10 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
       aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
     }
   }
+  if ((theBits & OpenGl_PO_WriteOit) != 0)
+  {
+    aSrcFragWriteOit += THE_FRAG_write_oit_buffers;
+  }
 
   TCollection_AsciiString aSrcVertEndMain;
   if ((theBits & OpenGl_PO_StippleLine) != 0)
@@ -1421,6 +1540,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_Shad
       EOL"{"
     + aSrcFragExtraMain
     + aSrcFragMainGetColor
+    + aSrcFragWriteOit
     + EOL"}";
 
 #if !defined(GL_ES_VERSION_2_0)
@@ -1572,7 +1692,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
                                                                  const Standard_Integer        theBits)
 {
   Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
-  TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
+  TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut;
+  TCollection_AsciiString aSrcFragExtraMain, aSrcFragWriteOit;
   TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
   if ((theBits & OpenGl_PO_Point) != 0)
   {
@@ -1640,6 +1761,10 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
       aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
     }
   }
+  if ((theBits & OpenGl_PO_WriteOit) != 0)
+  {
+    aSrcFragWriteOit += THE_FRAG_write_oit_buffers;
+  }
 
   const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
   aSrcVert = TCollection_AsciiString()
@@ -1673,7 +1798,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
       EOL"{"
     + aSrcFragExtraMain
     + EOL"  occFragColor = getColor();"
-      EOL"}";
+    + aSrcFragWriteOit
+    + EOL"}";
 
 #if !defined(GL_ES_VERSION_2_0)
   if (myContext->core32 != NULL)
@@ -1702,7 +1828,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
   #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
 
   Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
-  TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain;
+  TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut;
+  TCollection_AsciiString aSrcFragGetVertColor, aSrcFragExtraMain, aSrcFragWriteOit;
   TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
   if ((theBits & OpenGl_PO_Point) != 0)
   {
@@ -1763,6 +1890,10 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
       aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
     }
   }
+  if ((theBits & OpenGl_PO_WriteOit) != 0)
+  {
+    aSrcFragWriteOit += THE_FRAG_write_oit_buffers;
+  }
 
   aSrcVert = TCollection_AsciiString()
     + THE_FUNC_transformNormal
@@ -1799,7 +1930,8 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
       EOL"{"
     + aSrcFragExtraMain
     + EOL"  occFragColor = getColor();"
-      EOL"}";
+    + aSrcFragWriteOit
+    + EOL"}";
 
 #if !defined(GL_ES_VERSION_2_0)
   if (myContext->core32 != NULL)
index ce503a634c96261965b11451b37a7bcc42daa991..0b9c9821213c4b5c6a326efbbed54638843aae37 100644 (file)
 #include <NCollection_DataMap.hxx>
 #include <NCollection_Sequence.hxx>
 
-#include <OpenGl_SetOfShaderPrograms.hxx>
-#include <OpenGl_ShaderStates.hxx>
 #include <OpenGl_AspectFace.hxx>
 #include <OpenGl_AspectLine.hxx>
-#include <OpenGl_AspectText.hxx>
 #include <OpenGl_AspectMarker.hxx>
+#include <OpenGl_AspectText.hxx>
+#include <OpenGl_OitUniformState.hxx>
+#include <OpenGl_SetOfShaderPrograms.hxx>
+#include <OpenGl_ShaderStates.hxx>
 #include <OpenGl_MaterialState.hxx>
 #include <OpenGl_Texture.hxx>
 
@@ -168,6 +169,19 @@ public:
          && myContext->BindProgram (myBlitProgram);
   }
 
+  //! Bind program for blended order-independent transparency buffers compositing.
+  Standard_Boolean BindOitCompositingProgram (const Standard_Boolean theIsMSAAEnabled)
+  {
+    const Standard_Integer aProgramIdx = theIsMSAAEnabled ? 1 : 0;
+    if (myOitCompositingProgram[aProgramIdx].IsNull())
+    {
+      prepareStdProgramOitCompositing (theIsMSAAEnabled);
+    }
+
+    const Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram [aProgramIdx];
+    return !aProgram.IsNull() && myContext->BindProgram (aProgram);
+  }
+
   //! Bind program for rendering stereoscopic image.
   Standard_Boolean BindStereoProgram (const Graphic3d_StereoMode theStereoMode)
   {
@@ -267,6 +281,20 @@ public:
   //! Pushes current state of material to specified program.
   void PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
 
+public:
+
+  //! Set the state of OIT rendering pass.
+  //! @param theToEnableOitWrite [in] flag indicating whether the special output should be written for OIT algorithm.
+  //! @param theDepthWeight [in] the scalar factor of depth influence to the fragment's coverage.
+  void SetOitState (const bool theToEnableOitWrite, const float theDepthWeight)
+  {
+    myOitUniformState.Set (theToEnableOitWrite, theDepthWeight);
+    myOitUniformState.Update();
+  }
+
+  //! Pushes state of OIT uniforms to the specified program.
+  Standard_EXPORT void PushOitUniformState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
+
 public:
 
   //! Pushes current state of OCCT graphics parameters to specified program.
@@ -339,6 +367,12 @@ protected:
     {
       aBits |= OpenGl_PO_VertColor;
     }
+
+    if (myOitUniformState.ToEnableWrite())
+    {
+      aBits |= OpenGl_PO_WriteOit;
+    }
+
     return aBits;
   }
 
@@ -378,6 +412,9 @@ protected:
   //! Prepare standard GLSL program for FBO blit operation.
   Standard_EXPORT Standard_Boolean prepareStdProgramFboBlit();
 
+  //! Prepare standard GLSL programs for Oit compositing operation.
+  Standard_EXPORT Standard_Boolean prepareStdProgramOitCompositing (const Standard_Boolean theMsaa);
+
   //! Prepare standard GLSL program without lighting.
   Standard_EXPORT Standard_Boolean prepareStdProgramFlat (Handle(OpenGl_ShaderProgram)& theProgram,
                                                           const Standard_Integer        theBits);
@@ -452,13 +489,14 @@ protected:
 
   Handle(OpenGl_ShaderProgramFFP)    myFfpProgram;
 
-  Graphic3d_TypeOfShadingModel       myShadingModel;       //!< lighting shading model
-  OpenGl_ShaderProgramList           myProgramList;        //!< The list of shader programs
-  Handle(OpenGl_SetOfShaderPrograms) myLightPrograms;      //!< pointer to active lighting programs matrix
-  OpenGl_SetOfShaderPrograms         myFlatPrograms;       //!< programs matrix without  lighting
-  Handle(OpenGl_ShaderProgram)       myFontProgram;        //!< standard program for textured text
-  Handle(OpenGl_ShaderProgram)       myBlitProgram;        //!< standard program for FBO blit emulation
-  OpenGl_MapOfShaderPrograms         myMapOfLightPrograms; //!< map of lighting programs depending on shading model and lights configuration
+  Graphic3d_TypeOfShadingModel       myShadingModel;             //!< lighting shading model
+  OpenGl_ShaderProgramList           myProgramList;              //!< The list of shader programs
+  Handle(OpenGl_SetOfShaderPrograms) myLightPrograms;            //!< pointer to active lighting programs matrix
+  OpenGl_SetOfShaderPrograms         myFlatPrograms;             //!< programs matrix without  lighting
+  Handle(OpenGl_ShaderProgram)       myFontProgram;              //!< standard program for textured text
+  Handle(OpenGl_ShaderProgram)       myBlitProgram;              //!< standard program for FBO blit emulation
+  Handle(OpenGl_ShaderProgram)       myOitCompositingProgram[2]; //!< standard program for OIT compositing (default and msaa).
+  OpenGl_MapOfShaderPrograms         myMapOfLightPrograms;       //!< map of lighting programs depending on shading model and lights configuration
 
   Handle(OpenGl_ShaderProgram)       myStereoPrograms[Graphic3d_StereoMode_NB]; //!< standard stereo programs
 
@@ -472,6 +510,7 @@ protected:
   OpenGl_ClippingState               myClippingState;      //!< State of OCCT clipping planes
   OpenGl_LightSourceState            myLightSourceState;   //!< State of OCCT light sources
   OpenGl_MaterialState               myMaterialState;      //!< State of Front and Back materials
+  OpenGl_OitUniformState             myOitUniformState;    //!< State of OIT uniforms
 
   gp_XYZ                             myLocalOrigin;        //!< local camera transformation
   Standard_Boolean                   myHasLocalOrigin;     //!< flag indicating that local camera transformation has been set
index d792b16afaa3d12ffef67f40b5d75c7203d598f0..4f1aefb11fcfb52b0590ee4de1b5ac333984cd3c 100755 (executable)
@@ -70,11 +70,27 @@ Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
   "occBackMaterial",       // OpenGl_OCCT_BACK_MATERIAL
   "occColor",              // OpenGl_OCCT_COLOR
 
+  "occOitEnableWrite",     // OpenGl_OCCT_OIT_ENABLE_WRITE
+  "occOitDepthWeight",     // OpenGl_OCCT_OIT_DEPTH_WEIGHT
+
   "occTexTrsf2d",          // OpenGl_OCCT_TEXTURE_TRSF2D
   "occPointSize"           // OpenGl_OCCT_POINT_SIZE
-
 };
 
+namespace
+{
+  #define EOL "\n"
+  const char THE_enable_draw_buffers[] =
+    EOL"#ifdef GL_ES"
+    EOL"  #if (__VERSION__ < 300)"
+    EOL"    #extension GL_EXT_draw_buffers : enable"
+    EOL"  #endif"
+    EOL"#else"
+    EOL"  #extension GL_ARB_draw_buffers : enable"
+    EOL"#endif"
+    EOL"#define OCC_enable_draw_buffers 1";
+}
+
 // =======================================================================
 // function : OpenGl_VariableSetterSelector
 // purpose  : Creates new variable setter selector
@@ -204,11 +220,16 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
     }
 
     TCollection_AsciiString aSource = aDeclarations + anIter.Value()->Source();
+    TCollection_AsciiString aExtensions;
+    if (theCtx->MaxDrawBuffers() > 1) {
+      aExtensions += THE_enable_draw_buffers;
+    }
+
     switch (anIter.Value()->Type())
     {
       case Graphic3d_TOS_VERTEX:
       {
-        aSource = aHeader + TCollection_AsciiString ("#define VERTEX_SHADER\n") + aSource;
+        aSource = aHeader + TCollection_AsciiString ("#define VERTEX_SHADER\n") + aExtensions + aSource;
         break;
       }
       case Graphic3d_TOS_FRAGMENT:
@@ -219,9 +240,9 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
                                          "precision highp int;\n"
                                        : "precision mediump float;\n"
                                          "precision mediump int;\n");
-        aSource = aHeader + aPrefix + aSource;
+        aSource = aHeader + aPrefix + aExtensions + aSource;
       #else
-        aSource = aHeader + aSource;
+        aSource = aHeader + aExtensions + aSource;
       #endif
         break;
       }
index f38506fa7411ee987c6d6b9591b84d8d84e24d3b..0d3c39c8d76c2259d9e4eabf4c34635788d09995 100755 (executable)
@@ -65,6 +65,11 @@ enum OpenGl_StateVariable
   OpenGl_OCCT_BACK_MATERIAL,
   OpenGl_OCCT_COLOR,
 
+  // Order-independent transparency rendering state
+  OpenGl_OCCT_OIT_ENABLE_WRITE, //!< Enable bit for writing color (occFragColor) and coverage (occFragCoverage) buffers of OIT processing
+  OpenGl_OCCT_OIT_DEPTH_WEIGHT, //!< Influence of the depth component to the coverage of the accumulated fragment
+
+  // Context-dependent state
   OpenGl_OCCT_TEXTURE_TRSF2D,
   OpenGl_OCCT_POINT_SIZE,
 
@@ -124,6 +129,7 @@ enum OpenGl_UniformStateType
   OpenGl_PROJECTION_STATE,
   OpenGl_MATERIAL_STATE,
   OpenGl_SURF_DETAIL_STATE,
+  OpenGL_OIT_UNIFORM_STATE,
   OpenGl_UniformStateType_NB
 };
 
index f0ec3e49699cfd321c1376b008e607c6573dfea8..0020bd2a6a2ff9c610bd77e914906ea2ec8574f9 100644 (file)
@@ -900,6 +900,20 @@ bool OpenGl_Texture::Init3D (const Handle(OpenGl_Context)& theCtx,
     Unbind (theCtx);
     return false;
   }
+  else if (theDataType == GL_HALF_FLOAT && !theCtx->arbTexHalfFloat)
+  {
+    TCollection_ExtendedString aMsg ("Error: half-precision floating-point textures are not supported by hardware.");
+
+    theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                         GL_DEBUG_TYPE_ERROR,
+                         0,
+                         GL_DEBUG_SEVERITY_HIGH,
+                         aMsg);
+
+    Release (theCtx.operator->());
+    Unbind (theCtx);
+    return false;
+  }
 
   const GLint anIntFormat = theTextFormat;
 
index c60c68452caa2f2c9b14a36f1b8ce436ae0ccad8..32b165aef27aeb118531c28ee3f79139d5c9ed35 100644 (file)
@@ -61,11 +61,17 @@ OpenGl_View::OpenGl_View (const Handle(Graphic3d_StructureManager)& theMgr,
   myToShowGradTrihedron  (false),
   myStateCounter         (theCounter),
   myLastLightSourceState (0, 0),
+#if !defined(GL_ES_VERSION_2_0)
   myFboColorFormat       (GL_RGBA8),
+#else
+  myFboColorFormat       (GL_RGBA),
+#endif
   myFboDepthFormat       (GL_DEPTH24_STENCIL8),
   myToFlipOutput         (Standard_False),
   myFrameCounter         (0),
   myHasFboBlit           (Standard_True),
+  myToDisableOIT         (Standard_False),
+  myToDisableOITMSAA     (Standard_False),
   myToDisableMSAA        (Standard_False),
   myTransientDrawToFront (Standard_True),
   myBackBufferRestored   (Standard_False),
@@ -90,17 +96,21 @@ OpenGl_View::OpenGl_View (const Handle(Graphic3d_StructureManager)& theMgr,
   aLight.Color.b()   = 1.;
   myNoShadingLight.Append (aLight);
 
-  myCurrLightSourceState  = myStateCounter->Increment();
-  myMainSceneFbos[0]      = new OpenGl_FrameBuffer();
-  myMainSceneFbos[1]      = new OpenGl_FrameBuffer();
-  myImmediateSceneFbos[0] = new OpenGl_FrameBuffer();
-  myImmediateSceneFbos[1] = new OpenGl_FrameBuffer();
-  myOpenGlFBO             = new OpenGl_FrameBuffer();
-  myOpenGlFBO2            = new OpenGl_FrameBuffer();
-  myRaytraceFBO1[0]       = new OpenGl_FrameBuffer();
-  myRaytraceFBO1[1]       = new OpenGl_FrameBuffer();
-  myRaytraceFBO2[0]       = new OpenGl_FrameBuffer();
-  myRaytraceFBO2[1]       = new OpenGl_FrameBuffer();
+  myCurrLightSourceState     = myStateCounter->Increment();
+  myMainSceneFbos[0]         = new OpenGl_FrameBuffer();
+  myMainSceneFbos[1]         = new OpenGl_FrameBuffer();
+  myMainSceneFbosOit[0]      = new OpenGl_FrameBuffer();
+  myMainSceneFbosOit[1]      = new OpenGl_FrameBuffer();
+  myImmediateSceneFbos[0]    = new OpenGl_FrameBuffer();
+  myImmediateSceneFbos[1]    = new OpenGl_FrameBuffer();
+  myImmediateSceneFbosOit[0] = new OpenGl_FrameBuffer();
+  myImmediateSceneFbosOit[1] = new OpenGl_FrameBuffer();
+  myOpenGlFBO                = new OpenGl_FrameBuffer();
+  myOpenGlFBO2               = new OpenGl_FrameBuffer();
+  myRaytraceFBO1[0]          = new OpenGl_FrameBuffer();
+  myRaytraceFBO1[1]          = new OpenGl_FrameBuffer();
+  myRaytraceFBO2[0]          = new OpenGl_FrameBuffer();
+  myRaytraceFBO2[1]          = new OpenGl_FrameBuffer();
 }
 
 // =======================================================================
@@ -142,14 +152,18 @@ void OpenGl_View::ReleaseGlResources (const Handle(OpenGl_Context)& theCtx)
     myBgTextureArray->Release (theCtx.operator->());
   }
 
-  myMainSceneFbos[0]     ->Release (theCtx.operator->());
-  myMainSceneFbos[1]     ->Release (theCtx.operator->());
-  myImmediateSceneFbos[0]->Release (theCtx.operator->());
-  myImmediateSceneFbos[1]->Release (theCtx.operator->());
-  myOpenGlFBO            ->Release (theCtx.operator->());
-  myOpenGlFBO2           ->Release (theCtx.operator->());
-  myFullScreenQuad        .Release (theCtx.operator->());
-  myFullScreenQuadFlip    .Release (theCtx.operator->());
+  myMainSceneFbos[0]        ->Release (theCtx.operator->());
+  myMainSceneFbos[1]        ->Release (theCtx.operator->());
+  myMainSceneFbosOit[0]     ->Release (theCtx.operator->());
+  myMainSceneFbosOit[1]     ->Release (theCtx.operator->());
+  myImmediateSceneFbos[0]   ->Release (theCtx.operator->());
+  myImmediateSceneFbos[1]   ->Release (theCtx.operator->());
+  myImmediateSceneFbosOit[0]->Release (theCtx.operator->());
+  myImmediateSceneFbosOit[1]->Release (theCtx.operator->());
+  myOpenGlFBO               ->Release (theCtx.operator->());
+  myOpenGlFBO2              ->Release (theCtx.operator->());
+  myFullScreenQuad           .Release (theCtx.operator->());
+  myFullScreenQuadFlip       .Release (theCtx.operator->());
 
   releaseRaytraceResources (theCtx);
 }
index 3a1bfaa77b4363de9e42eed802bae69639c555c0..d4b4d94bca36f771148839d636b183216c890200 100644 (file)
@@ -367,7 +367,8 @@ protected: //! @name low-level redrawing sub-routines
 
   //! Redraws view for the given monographic camera projection, or left/right eye.
   Standard_EXPORT virtual void redraw (const Graphic3d_Camera::Projection theProjection,
-                                       OpenGl_FrameBuffer*                theReadDrawFbo);
+                                       OpenGl_FrameBuffer*                theReadDrawFbo,
+                                       OpenGl_FrameBuffer*                theOitAccumFbo);
 
   //! Redraws view for the given monographic camera projection, or left/right eye.
   //!
@@ -384,6 +385,7 @@ protected: //! @name low-level redrawing sub-routines
   Standard_EXPORT virtual bool redrawImmediate (const Graphic3d_Camera::Projection theProjection,
                                                 OpenGl_FrameBuffer* theReadFbo,
                                                 OpenGl_FrameBuffer* theDrawFbo,
+                                                OpenGl_FrameBuffer* theOitAccumFbo,
                                                 const Standard_Boolean theIsPartialUpdate = Standard_False);
 
   //! Blit image from/to specified buffers.
@@ -399,17 +401,21 @@ protected: //! @name Rendering of GL graphics (with prepared drawing buffer).
   //! Renders the graphical contents of the view into the preprepared window or framebuffer.
   //! @param theProjection [in] the projection that should be used for rendering.
   //! @param theReadDrawFbo [in] the framebuffer for rendering graphics.
+  //! @param theOitAccumFbo [in] the framebuffer for accumulating color and coverage for OIT process.
   //! @param theToDrawImmediate [in] the flag indicates whether the rendering performs in immediate mode.
   Standard_EXPORT virtual void render (Graphic3d_Camera::Projection theProjection,
                                        OpenGl_FrameBuffer*          theReadDrawFbo,
+                                       OpenGl_FrameBuffer*          theOitAccumFbo,
                                        const Standard_Boolean       theToDrawImmediate);
 
   //! Renders the graphical scene.
   //! @param theProjection [in] the projection that is used for rendering.
   //! @param theReadDrawFbo [in] the framebuffer for rendering graphics.
+  //! @param theOitAccumFbo [in] the framebuffer for accumulating color and coverage for OIT process.
   //! @param theToDrawImmediate [in] the flag indicates whether the rendering performs in immediate mode.
   Standard_EXPORT virtual void renderScene (Graphic3d_Camera::Projection theProjection,
                                             OpenGl_FrameBuffer*    theReadDrawFbo,
+                                            OpenGl_FrameBuffer*    theOitAccumFbo,
                                             const Standard_Boolean theToDrawImmediate);
 
   //! Draw background (gradient / image)
@@ -418,9 +424,11 @@ protected: //! @name Rendering of GL graphics (with prepared drawing buffer).
   //! Render set of structures presented in the view.
   //! @param theProjection [in] the projection that is used for rendering.
   //! @param theReadDrawFbo [in] the framebuffer for rendering graphics.
+  //! @param theOitAccumFbo [in] the framebuffer for accumulating color and coverage for OIT process.
   //! @param theToDrawImmediate [in] the flag indicates whether the rendering performs in immediate mode.
   Standard_EXPORT virtual void renderStructs (Graphic3d_Camera::Projection theProjection,
                                               OpenGl_FrameBuffer*    theReadDrawFbo,
+                                              OpenGl_FrameBuffer*    theOitAccumFbo,
                                               const Standard_Boolean theToDrawImmediate);
 
   //! Renders trihedron.
@@ -460,6 +468,15 @@ private:
   //! Blend together views pair into stereo image.
   void drawStereoPair (OpenGl_FrameBuffer* theDrawFbo);
 
+  //! Check and update OIT compatibility with current OpenGL context's state.
+  bool checkOitCompatibility (const Handle(OpenGl_Context)& theGlContext,
+                              const Standard_Boolean theMSAA);
+
+  //! Chooses compatible internal color format for OIT frame buffer.
+  bool chooseOitColorConfiguration (const Handle(OpenGl_Context)& theGlContext,
+                                    const Standard_Integer theConfigIndex,
+                                    OpenGl_ColorFormats& theFormats);
+
 protected:
 
   OpenGl_GraphicDriver*    myDriver;
@@ -513,13 +530,18 @@ protected: //! @name Rendering properties
   //! of the view (without presentation of immediate layers).
   GLint                      myFboColorFormat;        //!< sized format for color attachments
   GLint                      myFboDepthFormat;        //!< sized format for depth-stencil attachments
+  OpenGl_ColorFormats        myFboOitColorConfig;     //!< selected color format configuration for OIT color attachments
   Handle(OpenGl_FrameBuffer) myMainSceneFbos[2];
-  Handle(OpenGl_FrameBuffer) myImmediateSceneFbos[2]; //!< Additional buffers for immediate layer in stereo mode.
+  Handle(OpenGl_FrameBuffer) myMainSceneFbosOit[2];      //!< Additional buffers for transparent draw of main layer.
+  Handle(OpenGl_FrameBuffer) myImmediateSceneFbos[2];    //!< Additional buffers for immediate layer in stereo mode.
+  Handle(OpenGl_FrameBuffer) myImmediateSceneFbosOit[2]; //!< Additional buffers for transparency draw of immediate layer.
   OpenGl_VertexBuffer        myFullScreenQuad;        //!< Vertices for full-screen quad rendering.
   OpenGl_VertexBuffer        myFullScreenQuadFlip;
   Standard_Boolean           myToFlipOutput;          //!< Flag to draw result image upside-down
   unsigned int               myFrameCounter;          //!< redraw counter, for debugging
   Standard_Boolean           myHasFboBlit;            //!< disable FBOs on failure
+  Standard_Boolean           myToDisableOIT;          //!< disable OIT on failure
+  Standard_Boolean           myToDisableOITMSAA;      //!< disable OIT with MSAA on failure
   Standard_Boolean           myToDisableMSAA;         //!< disable MSAA after failure
   Standard_Boolean           myTransientDrawToFront; //!< optimization flag for immediate mode (to render directly to the front buffer)
   Standard_Boolean           myBackBufferRestored;
@@ -1051,6 +1073,7 @@ public:
 
   friend class OpenGl_GraphicDriver;
   friend class OpenGl_Workspace;
+  friend class OpenGl_LayerList;
 };
 
 #endif // _OpenGl_View_Header
index 7835b4f3a18dbae6bde60826c8b461ec834655bb..d15d44994d9e1bc3ac62d51367855e3ddddf9370 100644 (file)
@@ -163,6 +163,12 @@ void OpenGl_View::Redraw()
     aNbSamples = OpenGl_Context::GetPowerOfTwo (aNbSamples, aCtx->MaxMsaaSamples());
   }
 
+  bool toUseOit = myRenderParams.IsOitEnabled
+    && checkOitCompatibility (aCtx, aNbSamples > 0);
+
+  bool toInitImmediateFbo = myTransientDrawToFront
+    && (!aCtx->caps->useSystemBuffer || (toUseOit && HasImmediateStructures()));
+
   if ( aFrameBuffer == NULL
    && !aCtx->DefaultFrameBuffer().IsNull()
    &&  aCtx->DefaultFrameBuffer()->IsValid())
@@ -173,7 +179,8 @@ void OpenGl_View::Redraw()
   if (myHasFboBlit
    && (myTransientDrawToFront
     || aProjectType == Graphic3d_Camera::Projection_Stereo
-    || aNbSamples != 0))
+    || aNbSamples != 0
+    || toUseOit))
   {
     if (myMainSceneFbos[0]->GetVPSizeX() != aSizeX
      || myMainSceneFbos[0]->GetVPSizeY() != aSizeY
@@ -193,12 +200,10 @@ void OpenGl_View::Redraw()
       {
         myMainSceneFbos[0]->Init (aCtx, aSizeX, aSizeY, myFboColorFormat, myFboDepthFormat, aNbSamples);
       }
-      if (myTransientDrawToFront
-       && !aCtx->caps->useSystemBuffer
-       && myMainSceneFbos[0]->IsValid())
-      {
-        myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]);
-      }
+    }
+    if (myMainSceneFbos[0]->IsValid() && (toInitImmediateFbo || myImmediateSceneFbos[0]->IsValid()))
+    {
+      myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]);
     }
   }
   else
@@ -238,6 +243,93 @@ void OpenGl_View::Redraw()
     }
   }
 
+  // create color and coverage accumulation buffers required for OIT algorithm
+  if (toUseOit)
+  {
+    Standard_Integer anFboIt = 0;
+    for (; anFboIt < 2; ++anFboIt)
+    {
+      if (myMainSceneFbos[anFboIt]->IsValid()
+       && (myMainSceneFbosOit[anFboIt]->GetVPSizeX() != aSizeX
+        || myMainSceneFbosOit[anFboIt]->GetVPSizeY() != aSizeY
+        || myMainSceneFbosOit[anFboIt]->NbSamples() != aNbSamples))
+      {
+        Standard_Integer aColorConfig = 0;
+        for (;;) // seemly responding to driver limitation (GL_FRAMEBUFFER_UNSUPPORTED)
+        {
+          if (myFboOitColorConfig.IsEmpty())
+          {
+            if (!chooseOitColorConfiguration (aCtx, aColorConfig++, myFboOitColorConfig))
+            {
+              break;
+            }
+          }
+          if (myMainSceneFbosOit[anFboIt]->Init (aCtx, aSizeX, aSizeY, myFboOitColorConfig, myMainSceneFbos[anFboIt]->DepthStencilTexture(), aNbSamples))
+          {
+            break;
+          }
+          myFboOitColorConfig.Clear();
+        }
+        if (!myMainSceneFbosOit[anFboIt]->IsValid())
+        {
+          break;
+        }
+      }
+      else if (!myMainSceneFbosOit[anFboIt]->IsValid())
+      {
+        myMainSceneFbosOit[anFboIt]->Release (aCtx.operator->());
+        myMainSceneFbosOit[anFboIt]->ChangeViewport (0, 0);
+      }
+
+      if (myImmediateSceneFbos[anFboIt]->IsValid()
+       && (myImmediateSceneFbosOit[anFboIt]->GetVPSizeX() != aSizeX
+        || myImmediateSceneFbosOit[anFboIt]->GetVPSizeY() != aSizeY
+        || myImmediateSceneFbosOit[anFboIt]->NbSamples() != aNbSamples))
+      {
+        if (!myImmediateSceneFbosOit[anFboIt]->Init (aCtx, aSizeX, aSizeY, myFboOitColorConfig, myImmediateSceneFbos[anFboIt]->DepthStencilTexture(), aNbSamples))
+        {
+          break;
+        }
+      }
+      else if (!myImmediateSceneFbosOit[anFboIt]->IsValid())
+      {
+        myImmediateSceneFbosOit[anFboIt]->Release (aCtx.operator->());
+        myImmediateSceneFbosOit[anFboIt]->ChangeViewport (0, 0);
+      }
+    }
+    if (!anFboIt) // only the first OIT framebuffer is mandatory
+    {
+      TCollection_ExtendedString aMsg = 
+        "Initialization of float texture framebuffer for use with\n"
+        "  blended order-independent transparency rendering algorithm has failed.\n"
+        "  Blended order-independent transparency will not be available.\n";
+
+      aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                          GL_DEBUG_TYPE_ERROR,
+                          0,
+                          GL_DEBUG_SEVERITY_HIGH,
+                          aMsg);
+
+      if (aNbSamples > 0)
+        myToDisableOITMSAA = Standard_True;
+      else
+        myToDisableOIT     = Standard_True;
+
+      toUseOit = false;
+    }
+  }
+  if (!toUseOit && myMainSceneFbosOit[0]->IsValid())
+  {
+    myMainSceneFbosOit     [0]->Release (aCtx.operator->());
+    myMainSceneFbosOit     [1]->Release (aCtx.operator->());
+    myImmediateSceneFbosOit[0]->Release (aCtx.operator->());
+    myImmediateSceneFbosOit[1]->Release (aCtx.operator->());
+    myMainSceneFbosOit     [0]->ChangeViewport (0, 0);
+    myMainSceneFbosOit     [1]->ChangeViewport (0, 0);
+    myImmediateSceneFbosOit[0]->ChangeViewport (0, 0);
+    myImmediateSceneFbosOit[1]->ChangeViewport (0, 0);
+  }
+
   if (aProjectType == Graphic3d_Camera::Projection_Stereo)
   {
     OpenGl_FrameBuffer* aMainFbos[2] =
@@ -245,34 +337,51 @@ void OpenGl_View::Redraw()
       myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL,
       myMainSceneFbos[1]->IsValid() ? myMainSceneFbos[1].operator->() : NULL
     };
+    OpenGl_FrameBuffer* aMainFbosOit[2] =
+    {
+      myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL,
+      myMainSceneFbosOit[1]->IsValid() ? myMainSceneFbosOit[1].operator->() :
+        myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL
+    };
+
     OpenGl_FrameBuffer* anImmFbos[2] =
     {
       myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
       myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
     };
+    OpenGl_FrameBuffer* anImmFbosOit[2] =
+    {
+      myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL,
+      myImmediateSceneFbosOit[1]->IsValid() ? myImmediateSceneFbosOit[1].operator->() :
+        myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL
+    };
 
     if (!myTransientDrawToFront)
     {
-      anImmFbos[0] = aMainFbos[0];
-      anImmFbos[1] = aMainFbos[1];
+      anImmFbos   [0] = aMainFbos   [0];
+      anImmFbos   [1] = aMainFbos   [1];
+      anImmFbosOit[0] = aMainFbosOit[0];
+      anImmFbosOit[1] = aMainFbosOit[1];
     }
     else if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
           || aStereoMode == Graphic3d_StereoMode_QuadBuffer)
     {
-      anImmFbos[0] = NULL;
-      anImmFbos[1] = NULL;
+      anImmFbos   [0] = NULL;
+      anImmFbos   [1] = NULL;
+      anImmFbosOit[0] = NULL;
+      anImmFbosOit[1] = NULL;
     }
 
   #if !defined(GL_ES_VERSION_2_0)
     aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
   #endif
-    redraw (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0]);
+    redraw (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], aMainFbosOit[0]);
     myBackBufferRestored = Standard_True;
     myIsImmediateDrawn   = Standard_False;
   #if !defined(GL_ES_VERSION_2_0)
     aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_LEFT : GL_BACK);
   #endif
-    if (!redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], anImmFbos[0]))
+    if (!redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye, aMainFbos[0], anImmFbos[0], anImmFbosOit[0]))
     {
       toSwap = false;
     }
@@ -284,10 +393,10 @@ void OpenGl_View::Redraw()
   #if !defined(GL_ES_VERSION_2_0)
     aCtx->SetReadDrawBuffer (aStereoMode == Graphic3d_StereoMode_QuadBuffer ? GL_BACK_RIGHT : GL_BACK);
   #endif
-    redraw (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1]);
+    redraw (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], aMainFbosOit[1]);
     myBackBufferRestored = Standard_True;
     myIsImmediateDrawn   = Standard_False;
-    if (!redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], anImmFbos[1]))
+    if (!redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye, aMainFbos[1], anImmFbos[1], anImmFbosOit[1]))
     {
       toSwap = false;
     }
@@ -299,15 +408,19 @@ void OpenGl_View::Redraw()
   }
   else
   {
-    OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : aFrameBuffer;
-    OpenGl_FrameBuffer* anImmFbo = aFrameBuffer;
-    if (!aCtx->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid())
+    OpenGl_FrameBuffer* aMainFbo    = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : aFrameBuffer;
+    OpenGl_FrameBuffer* aMainFboOit = myMainSceneFbosOit[0]->IsValid() ? myMainSceneFbosOit[0].operator->() : NULL;
+    OpenGl_FrameBuffer* anImmFbo    = aFrameBuffer;
+    OpenGl_FrameBuffer* anImmFboOit = NULL;
+    if (!myTransientDrawToFront)
     {
-      anImmFbo = myImmediateSceneFbos[0].operator->();
+      anImmFbo    = aMainFbo;
+      anImmFboOit = aMainFboOit;
     }
-    if (!myTransientDrawToFront)
+    else if (myImmediateSceneFbos[0]->IsValid())
     {
-      anImmFbo = aMainFbo;
+      anImmFbo    = myImmediateSceneFbos[0].operator->();
+      anImmFboOit = myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL;
     }
 
   #if !defined(GL_ES_VERSION_2_0)
@@ -316,10 +429,10 @@ void OpenGl_View::Redraw()
       aCtx->SetReadDrawBuffer (GL_BACK);
     }
   #endif
-    redraw (aProjectType, aMainFbo);
+    redraw (aProjectType, aMainFbo, aMainFboOit);
     myBackBufferRestored = Standard_True;
     myIsImmediateDrawn   = Standard_False;
-    if (!redrawImmediate (aProjectType, aMainFbo, anImmFbo))
+    if (!redrawImmediate (aProjectType, aMainFbo, anImmFbo, anImmFboOit))
     {
       toSwap = false;
     }
@@ -422,11 +535,19 @@ void OpenGl_View::RedrawImmediate()
       myImmediateSceneFbos[0]->IsValid() ? myImmediateSceneFbos[0].operator->() : NULL,
       myImmediateSceneFbos[1]->IsValid() ? myImmediateSceneFbos[1].operator->() : NULL
     };
+    OpenGl_FrameBuffer* anImmFbosOit[2] =
+    {
+      myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL,
+      myImmediateSceneFbosOit[1]->IsValid() ? myImmediateSceneFbosOit[1].operator->() :
+        myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL
+    };
     if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
      || aStereoMode == Graphic3d_StereoMode_QuadBuffer)
     {
-      anImmFbos[0] = NULL;
-      anImmFbos[1] = NULL;
+      anImmFbos[0]    = NULL;
+      anImmFbos[1]    = NULL;
+      anImmFbosOit[0] = NULL;
+      anImmFbosOit[1] = NULL;
     }
 
     if (aCtx->arbFBO != NULL)
@@ -442,6 +563,7 @@ void OpenGl_View::RedrawImmediate()
     toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoLeftEye,
                               aMainFbos[0],
                               anImmFbos[0],
+                              anImmFbosOit[0],
                               Standard_True) || toSwap;
     if (aStereoMode == Graphic3d_StereoMode_SoftPageFlip
     &&  toSwap
@@ -463,6 +585,7 @@ void OpenGl_View::RedrawImmediate()
     toSwap = redrawImmediate (Graphic3d_Camera::Projection_MonoRightEye,
                               aMainFbos[1],
                               anImmFbos[1],
+                              anImmFbosOit[1],
                               Standard_True) || toSwap;
     if (anImmFbos[0] != NULL)
     {
@@ -473,9 +596,11 @@ void OpenGl_View::RedrawImmediate()
   {
     OpenGl_FrameBuffer* aMainFbo = myMainSceneFbos[0]->IsValid() ? myMainSceneFbos[0].operator->() : NULL;
     OpenGl_FrameBuffer* anImmFbo = aFrameBuffer;
-    if (!aCtx->caps->useSystemBuffer && myImmediateSceneFbos[0]->IsValid())
+    OpenGl_FrameBuffer* anImmFboOit = NULL;
+    if (myImmediateSceneFbos[0]->IsValid())
     {
-      anImmFbo = myImmediateSceneFbos[0].operator->();
+      anImmFbo    = myImmediateSceneFbos[0].operator->();
+      anImmFboOit = myImmediateSceneFbosOit[0]->IsValid() ? myImmediateSceneFbosOit[0].operator->() : NULL;
     }
   #if !defined(GL_ES_VERSION_2_0)
     if (aMainFbo == NULL)
@@ -486,6 +611,7 @@ void OpenGl_View::RedrawImmediate()
     toSwap = redrawImmediate (aProjectType,
                               aMainFbo,
                               anImmFbo,
+                              anImmFboOit,
                               Standard_True) || toSwap;
     if (anImmFbo != NULL
      && anImmFbo != aFrameBuffer)
@@ -517,7 +643,9 @@ void OpenGl_View::RedrawImmediate()
 // function : redraw
 // purpose  :
 // =======================================================================
-void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection, OpenGl_FrameBuffer* theReadDrawFbo)
+void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection,
+                          OpenGl_FrameBuffer* theReadDrawFbo,
+                          OpenGl_FrameBuffer* theOitAccumFbo)
 {
   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
   if (theReadDrawFbo != NULL)
@@ -552,7 +680,7 @@ void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection, Open
 
   glClear (toClear);
 
-  render (theProjection, theReadDrawFbo, Standard_False);
+  render (theProjection, theReadDrawFbo, theOitAccumFbo, Standard_False);
 }
 
 // =======================================================================
@@ -562,6 +690,7 @@ void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection, Open
 bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProjection,
                                    OpenGl_FrameBuffer*    theReadFbo,
                                    OpenGl_FrameBuffer*    theDrawFbo,
+                                   OpenGl_FrameBuffer*    theOitAccumFbo,
                                    const Standard_Boolean theIsPartialUpdate)
 {
   Handle(OpenGl_Context) aCtx = myWorkspace->GetGlContext();
@@ -617,7 +746,7 @@ bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProject
   glClearDepthf (1.0f);
 #endif
 
-  render (theProjection, theDrawFbo, Standard_True);
+  render (theProjection, theDrawFbo, theOitAccumFbo, Standard_True);
 
   return !toCopyBackToFront;
 }
@@ -628,6 +757,7 @@ bool OpenGl_View::redrawImmediate (const Graphic3d_Camera::Projection theProject
 //=======================================================================
 void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
                           OpenGl_FrameBuffer*          theOutputFBO,
+                          OpenGl_FrameBuffer*          theOitAccumFbo,
                           const Standard_Boolean       theToDrawImmediate)
 {
   // ==================================
@@ -752,7 +882,7 @@ void OpenGl_View::render (Graphic3d_Camera::Projection theProjection,
 
   myWorkspace->SetEnvironmentTexture (myTextureEnv);
 
-  renderScene (theProjection, theOutputFBO, theToDrawImmediate);
+  renderScene (theProjection, theOutputFBO, theOitAccumFbo, theToDrawImmediate);
 
   myWorkspace->SetEnvironmentTexture (Handle(OpenGl_Texture)());
 
@@ -812,6 +942,7 @@ void OpenGl_View::InvalidateBVHData (const Graphic3d_ZLayerId theLayerId)
 //=======================================================================
 void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection,
                                  OpenGl_FrameBuffer*          theReadDrawFbo,
+                                 OpenGl_FrameBuffer*          theOitAccumFbo,
                                  const Standard_Boolean       theToDrawImmediate)
 {
   if ( myZLayers.NbStructures() <= 0 )
@@ -848,7 +979,7 @@ void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection,
       if (aCtx->arbFBOBlit != NULL)
       {
         // Render bottom OSD layer
-        myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Bottom);
+        myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Bottom, theReadDrawFbo, theOitAccumFbo);
 
         myWorkspace->SetRenderFilter (myRaytraceFilter);
         {
@@ -862,7 +993,7 @@ void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection,
           }
 
           // Render non-polygonal elements in default layer
-          myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Default);
+          myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Default, theReadDrawFbo, theOitAccumFbo);
         }
         myWorkspace->SetRenderFilter (myRaytraceFilter->PrevRenderFilter());
       }
@@ -884,7 +1015,7 @@ void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection,
       raytrace (aSizeX, aSizeY, theProjection, theReadDrawFbo, aCtx);
 
       // Render upper (top and topmost) OpenGL layers
-      myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Upper);
+      myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_Upper, theReadDrawFbo, theOitAccumFbo);
     }
   }
 
@@ -892,7 +1023,7 @@ void OpenGl_View::renderStructs (Graphic3d_Camera::Projection theProjection,
   // mode or in case of ray-tracing failure
   if (toRenderGL)
   {
-    myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_All);
+    myZLayers.Render (myWorkspace, theToDrawImmediate, OpenGl_LF_All, theReadDrawFbo, theOitAccumFbo);
 
     // Set flag that scene was redrawn by standard pipeline
     myWasRedrawnGL = Standard_True;
@@ -926,6 +1057,7 @@ void OpenGl_View::Invalidate()
 //=======================================================================
 void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection,
                                OpenGl_FrameBuffer*          theReadDrawFbo,
+                               OpenGl_FrameBuffer*          theOitAccumFbo,
                                const Standard_Boolean       theToDrawImmediate)
 {
   const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext();
@@ -942,7 +1074,7 @@ void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection,
   myWorkspace->NamedStatus &= ~(OPENGL_NS_2NDPASSNEED | OPENGL_NS_2NDPASSDO);
 
   // First pass
-  renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
+  renderStructs (theProjection, theReadDrawFbo, theOitAccumFbo, theToDrawImmediate);
   myWorkspace->DisableTexture();
 
   // Second pass
@@ -972,7 +1104,7 @@ void OpenGl_View::renderScene (Graphic3d_Camera::Projection theProjection,
     glEnable (GL_DEPTH_TEST);
 
     // Render the view
-    renderStructs (theProjection, theReadDrawFbo, theToDrawImmediate);
+    renderStructs (theProjection, theReadDrawFbo, theOitAccumFbo, theToDrawImmediate);
     myWorkspace->DisableTexture();
 
     // Restore properties back
@@ -1477,3 +1609,74 @@ void OpenGl_View::copyBackToFront()
 #endif
   myIsImmediateDrawn = Standard_False;
 }
+
+// =======================================================================
+// function : checkOitCompatibility
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_View::checkOitCompatibility (const Handle(OpenGl_Context)& theGlContext,
+                                                     const Standard_Boolean theMSAA)
+{
+  // determine if OIT is supported by current OpenGl context
+  Standard_Boolean& aToDisableOIT = theMSAA ? myToDisableMSAA : myToDisableOIT;
+
+  if (!aToDisableOIT && theMSAA)
+  {
+    if (!theGlContext->arbSampleShading)
+    {
+      TCollection_ExtendedString aMsg = TCollection_ExtendedString()
+                                      + "Current version of GLSL does not support built-in sample variables.\n"
+                                      + "  Blended order-independent transparency will not be available.\n";
+      theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                                 GL_DEBUG_TYPE_ERROR,
+                                 0,
+                                 GL_DEBUG_SEVERITY_HIGH,
+                                 aMsg);
+
+      aToDisableOIT = Standard_True;
+    }
+  }
+  else if (!aToDisableOIT)
+  {
+    if (theGlContext->MaxDrawBuffers() < 2)
+    {
+      TCollection_ExtendedString aMsg = TCollection_ExtendedString()
+                                      + "OpenGL context does not support multiple rendering targets.\n"
+                                      + "  Blended order-independent transparency will not be available.\n";
+      theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
+                                 GL_DEBUG_TYPE_ERROR,
+                                 0,
+                                 GL_DEBUG_SEVERITY_HIGH,
+                                 aMsg);
+      aToDisableOIT = Standard_True;
+    }
+  }
+
+  return !aToDisableOIT;
+}
+
+// =======================================================================
+// function : chooseOitColorConfiguration
+// purpose  :
+// =======================================================================
+bool OpenGl_View::chooseOitColorConfiguration (const Handle(OpenGl_Context)& theGlContext,
+                                               const Standard_Integer theConfigIndex,
+                                               OpenGl_ColorFormats& theFormats)
+{
+  theFormats.Clear();
+
+  switch (theConfigIndex)
+  {
+    case 0: // choose best applicable color format combination
+      theFormats.Append (theGlContext->arbTexHalfFloat ? GL_RGBA16F : GL_RGBA32F);
+      theFormats.Append (theGlContext->arbTexHalfFloat ? GL_R16F    : GL_R32F);
+      return true;
+
+    case 1: // choose non-optimal applicable color format combination
+      theFormats.Append (theGlContext->arbTexHalfFloat ? GL_RGBA16F : GL_RGBA32F);
+      theFormats.Append (theGlContext->arbTexHalfFloat ? GL_RGBA16F : GL_RGBA32F);
+      return true;
+  }
+
+  return false; // color combination does not exist
+}
index f0597506462d52f1f1e2d43356300252e2e3e620..0fb379582d824b083b79d8929786e14aa2faea98 100644 (file)
@@ -715,7 +715,7 @@ const OpenGl_AspectFace* OpenGl_Workspace::ApplyAspectFace()
   }
   else
   {
-    myGlContext->SetShadingMaterial (myAspectFaceSet, myHighlightStyle, myUseDepthWrite, NamedStatus);
+    myGlContext->SetShadingMaterial (myAspectFaceSet, myHighlightStyle, NamedStatus);
   }
 
   if (myAspectFaceSet->Aspect()->ToMapTexture())
@@ -1107,15 +1107,16 @@ Standard_Boolean OpenGl_Workspace::BufferDump (const Handle(OpenGl_FrameBuffer)&
 }
 
 // =======================================================================
-// function : CanRender
+// function : ShouldRender
 // purpose  :
 // =======================================================================
-Standard_Boolean OpenGl_RaytraceFilter::CanRender (const OpenGl_Element* theElement)
+Standard_Boolean OpenGl_RaytraceFilter::ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
+                                                      const OpenGl_Element* theElement)
 {
   Standard_Boolean aPrevFilterResult = Standard_True;
   if (!myPrevRenderFilter.IsNull())
   {
-    aPrevFilterResult = myPrevRenderFilter->CanRender (theElement);
+    aPrevFilterResult = myPrevRenderFilter->ShouldRender (theWorkspace, theElement);
   }
   return aPrevFilterResult &&
     !OpenGl_Raytrace::IsRaytracedElement (theElement);
index 0723828136b45e9411de91c613c60140c7e16b7f..34f66aacd3fb21c72f3d71484bd1b6301af2cef3 100644 (file)
@@ -62,7 +62,8 @@ public:
   //! Checks whether the element can be rendered or not.
   //! @param theElement [in] the element to check.
   //! @return True if element can be rendered.
-  virtual Standard_Boolean CanRender (const OpenGl_Element* theElement) Standard_OVERRIDE;
+  virtual Standard_Boolean ShouldRender (const Handle(OpenGl_Workspace)& theWorkspace,
+                                         const OpenGl_Element*           theElement) Standard_OVERRIDE;
 
 private:
 
index 925e5d2f2b9fcc0ad9b046edbf5998cd9336f959..439b793f2f8117e9e358c7ea53aee5407157f064 100755 (executable)
@@ -166,10 +166,11 @@ vec4 computeLighting (in vec3 theNormal,
   vec4 aMaterialDiffuse  = gl_FrontFacing ? occFrontMaterial_Diffuse()  : occBackMaterial_Diffuse();
   vec4 aMaterialSpecular = gl_FrontFacing ? occFrontMaterial_Specular() : occBackMaterial_Specular();
   vec4 aMaterialEmission = gl_FrontFacing ? occFrontMaterial_Emission() : occBackMaterial_Emission();
-  return vec4 (Ambient,  1.0) * aMaterialAmbient
-       + vec4 (Diffuse,  1.0) * aMaterialDiffuse
-       + vec4 (Specular, 1.0) * aMaterialSpecular
-                              + aMaterialEmission;
+  vec3 aColor = Ambient  * aMaterialAmbient.rgb
+              + Diffuse  * aMaterialDiffuse.rgb
+              + Specular * aMaterialSpecular.rgb
+                         + aMaterialEmission.rgb;
+  return vec4 (aColor, aMaterialDiffuse.a);
 }
 
 //! Entry point to the Fragment Shader
@@ -185,7 +186,14 @@ void main()
     }
   }
 
-  gl_FragColor = computeLighting (normalize (Normal),
+  occFragColor = computeLighting (normalize (Normal),
                                   normalize (View),
                                   Position);
+
+  if (occOitEnableWrite != 0)
+  {
+    float aWeight     = occFragColor.a * clamp (1e+2 * pow (1.0 - gl_FragCoord.z * occOitDepthWeight, 3.0), 1e-2, 1e+2);
+    occFragCoverage.r = occFragColor.a * aWeight;
+    occFragColor      = vec4 (occFragColor.rgb * occFragColor.a * aWeight, occFragColor.a);
+  }
 }
index da738498f8276b6e6cedf154ea20b86dd156f8c9..4e030f5e658a27d2aff23531530571e7733dad63 100644 (file)
@@ -50,8 +50,16 @@ static const char Shaders_Declarations_glsl[] =
   "  THE_ATTRIBUTE vec4 occVertColor;\n"
   "#elif (__VERSION__ >= 130)\n"
   "  out vec4 occFragColor;\n"
+  "  #ifdef OCC_enable_draw_buffers\n"
+  "    out vec4 occFragCoverage;\n"
+  "  #endif\n"
   "#else\n"
-  "  #define occFragColor gl_FragColor\n"
+  "  #ifdef OCC_enable_draw_buffers\n"
+  "    #define occFragColor    gl_FragData[0]\n"
+  "    #define occFragCoverage gl_FragData[1]\n"
+  "  #else\n"
+  "    #define occFragColor gl_FragColor\n"
+  "  #endif\n"
   "#endif\n"
   "\n"
   "// Matrix state\n"
@@ -113,6 +121,10 @@ static const char Shaders_Declarations_glsl[] =
   "uniform               vec4      occTexTrsf2d[2];       //!< 2D texture transformation parameters\n"
   "uniform               float     occPointSize;          //!< point size\n"
   "\n"
+  "//! Parameters of blended order-independent transparency rendering algorithm\n"
+  "uniform               int       occOitEnableWrite; //!< Enable bit for writing color (occFragColor), coverage (occFragCoverage) buffers of OIT processing\n"
+  "uniform               float     occOitDepthWeight; //!< Influence of the depth component to the coverage of the accumulated fragment\n"
+  "\n"
   "//! Parameters of clipping planes\n"
   "uniform               vec4 occClipPlaneEquations[THE_MAX_CLIP_PLANES];\n"
   "uniform THE_PREC_ENUM int  occClipPlaneCount;   //!< Total number of clip planes\n";
index ce91b42a55bc75ce3bdeca8d94070c92c762d997..3692b6204adb576c41376eaccd0d77526b7b1b60 100644 (file)
@@ -9065,6 +9065,8 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
     }
     theDI << "\n";
     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
+    theDI << "oit:            " << (aParams.IsOitEnabled                ? "on" : "off") << "\n";
+    theDI << "oitDepthWeight: " <<  aParams.OitDepthWeight                              << "\n";
     theDI << "rayDepth:       " <<  aParams.RaytracingDepth                             << "\n";
     theDI << "fsaa:           " << (aParams.IsAntialiasingEnabled       ? "on" : "off") << "\n";
     theDI << "shadows:        " << (aParams.IsShadowEnabled             ? "on" : "off") << "\n";
@@ -9171,6 +9173,46 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
         aParams.NbMsaaSamples = aNbSamples;
       }
     }
+    else if (aFlag == "-oit")
+    {
+      if (toPrint)
+      {
+        theDI << (aParams.IsOitEnabled ? "on" : "off") << " ";
+        continue;
+      }
+      Standard_Boolean toEnable = Standard_True;
+      if (++anArgIter < theArgNb
+      && !ViewerTest::ParseOnOff (theArgVec[anArgIter], toEnable))
+      {
+        --anArgIter;
+      }
+      aParams.IsOitEnabled = toEnable;
+    }
+    else if (aFlag == "-oitdepth"
+          || aFlag == "-oitdepthweight")
+    {
+      if (toPrint)
+      {
+        theDI << aParams.OitDepthWeight << " ";
+        continue;
+      }
+      else if (++anArgIter >= theArgNb)
+      {
+        std::cerr << "Error: wrong syntax at argument '" << anArg << "'\n";
+        return 1;
+      }
+      const Standard_Real aWeight = Draw::Atof (theArgVec[anArgIter]);
+
+      if (aWeight < 0.0 || aWeight > 1.0)
+      {
+        std::cerr << "Error: invalid value of order-indepedent transparency depth weight " << aWeight << ". Should be within range [0.0; 1.0]\n";
+        return 1;
+      }
+      else
+      {
+        aParams.OitDepthWeight = static_cast<Standard_ShortReal> (aWeight);
+      }
+    }
     else if (aFlag == "-raydepth"
           || aFlag == "-ray_depth")
     {
@@ -10926,6 +10968,8 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands)
     "\n    Manages rendering parameters: "
     "\n      '-raster'               Disables GPU ray-tracing"
     "\n      '-msaa         0..4'    Specifies number of samples for MSAA"
+    "\n      '-oit            on|off'  Enables/disables blended order-independent transparency"
+    "\n      '-oitDepthWeight 0.0-1.0' Defines influence of fragment depth to its coverage"
     "\n      '-rayTrace'             Enables  GPU ray-tracing"
     "\n      '-rayDepth     0..10'   Defines maximum ray-tracing depth"
     "\n      '-shadows      on|off'  Enables/disables shadows rendering"