]> OCCT Git - occt.git/commitdiff
0031571: Visualization, TKOpenGl - provide depth peeling OIT option
authorkgv <kgv@opencascade.com>
Tue, 19 May 2020 07:47:25 +0000 (10:47 +0300)
committerbugmaster <bugmaster@opencascade.com>
Wed, 20 Jan 2021 18:21:59 +0000 (21:21 +0300)
Graphic3d_RenderTransparentMethod has been extended by Graphic3d_RTM_DEPTH_PEELING_OIT,
which is handled by OpenGl_LayerList::renderTransparent().

OpenGl_FrameBuffer::Init() now does not silently ignore unknown color attachment format and return failure.
OpenGl_FrameBuffer::InitWrapper() - added constructor wrapping existing color textures.

v3d/transparency/oit: test case added

31 files changed:
src/Graphic3d/Graphic3d_RenderTransparentMethod.hxx
src/Graphic3d/Graphic3d_RenderingParams.hxx
src/Graphic3d/Graphic3d_ShaderProgram.cxx
src/Graphic3d/Graphic3d_ShaderProgram.hxx
src/Graphic3d/Graphic3d_TextureUnit.hxx
src/OpenGl/FILES
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_DepthPeeling.cxx [new file with mode: 0644]
src/OpenGl/OpenGl_DepthPeeling.hxx [new file with mode: 0644]
src/OpenGl/OpenGl_FrameBuffer.cxx
src/OpenGl/OpenGl_FrameBuffer.hxx
src/OpenGl/OpenGl_FrameStats.cxx
src/OpenGl/OpenGl_LayerList.cxx
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_ShaderStates.hxx
src/OpenGl/OpenGl_Texture.hxx
src/OpenGl/OpenGl_TextureFormat.cxx
src/OpenGl/OpenGl_View.cxx
src/OpenGl/OpenGl_View.hxx
src/Shaders/Declarations.glsl
src/Shaders/DeclarationsImpl.glsl
src/Shaders/Shaders_DeclarationsImpl_glsl.pxx
src/Shaders/Shaders_Declarations_glsl.pxx
src/ViewerTest/ViewerTest_OpenGlCommands.cxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx
tests/v3d/transparency/oit [new file with mode: 0644]

index 5066f09cfa287555c225216cbeef0202ed9daf4a..e18dfc11ec749e7038398fdef96e23aa37f8cdf4 100644 (file)
@@ -19,8 +19,9 @@
 //! Enumerates transparency rendering methods supported by rasterization mode.
 enum Graphic3d_RenderTransparentMethod
 {
-  Graphic3d_RTM_BLEND_UNORDERED, //!< Basic blend transparency with non-commuting blend operator without sorting
-  Graphic3d_RTM_BLEND_OIT        //!< Weighted Blended Order-Independent Transparency with depth weight factor
+  Graphic3d_RTM_BLEND_UNORDERED,  //!< Basic blend transparency with non-commuting blend operator without sorting
+  Graphic3d_RTM_BLEND_OIT,        //!< Weighted Blended Order-Independent Transparency with depth weight factor
+  Graphic3d_RTM_DEPTH_PEELING_OIT //!< Depth Peeling with specified number of depth layers
 };
 
 #endif // _Graphic3d_RenderTransparentMethod_HeaderFile
index 7469c9e66ee56e5eb01aa22c70e74191c40909e7..48aebdef11d8f4a97d1e4a18c49aa61ce2c36ad0 100644 (file)
@@ -104,6 +104,7 @@ public:
     PbrEnvBakingProbability     (0.99f),
     //
     OitDepthFactor              (0.0f),
+    NbOitDepthPeelingLayers     (4),
     NbMsaaSamples               (0),
     RenderResolutionScale       (1.0f),
     ShadowMapResolution         (1024),
@@ -197,7 +198,8 @@ public:
   Standard_ShortReal                PbrEnvBakingProbability;     //!< controls strength of samples reducing strategy during specular IBL map's generation
                                                                  //!  (see 'SpecIBLMapSamplesFactor' function for detail explanation) [0.0, 1.0], 0.99 by default
 
-  Standard_ShortReal                OitDepthFactor;              //!< scalar factor [0-1] controlling influence of depth of a fragment to its final coverage
+  Standard_ShortReal                OitDepthFactor;              //!< scalar factor [0-1] controlling influence of depth of a fragment to its final coverage (Graphic3d_RTM_BLEND_OIT), 0.0 by default
+  Standard_Integer                  NbOitDepthPeelingLayers;     //!< number of depth peeling (Graphic3d_RTM_DEPTH_PEELING_OIT) layers, 4 by default
   Standard_Integer                  NbMsaaSamples;               //!< number of MSAA samples (should be within 0..GL_MAX_SAMPLES, power-of-two number), 0 by default
   Standard_ShortReal                RenderResolutionScale;       //!< rendering resolution scale factor, 1 by default;
                                                                  //!  incompatible with MSAA (e.g. NbMsaaSamples should be set to 0)
index 28c8e7eac5016e15859d12a7879d793c4911a6ff..8fac2414a82f0d0c18161ff7c72140f6f67418a2 100755 (executable)
@@ -82,9 +82,9 @@ Graphic3d_ShaderProgram::Graphic3d_ShaderProgram()
   myNbClipPlanesMax (THE_MAX_CLIP_PLANES_DEFAULT),
   myNbFragOutputs (THE_NB_FRAG_OUTPUTS),
   myTextureSetBits (Graphic3d_TextureSetBits_NONE),
+  myOitOutput (Graphic3d_RTM_BLEND_UNORDERED),
   myHasDefSampler (true),
   myHasAlphaTest (false),
-  myHasWeightOitOutput (false),
   myIsPBR (false)
 {
   myID = TCollection_AsciiString ("Graphic3d_ShaderProgram_")
index fb612f15d96acb5d05bc532fb5045e2c27fcb5d2..baf36dd283efe3d6a5390b045e926ade2883c130 100755 (executable)
@@ -16,6 +16,7 @@
 #ifndef _Graphic3d_ShaderProgram_HeaderFile
 #define _Graphic3d_ShaderProgram_HeaderFile
 
+#include <Graphic3d_RenderTransparentMethod.hxx>
 #include <Graphic3d_ShaderAttribute.hxx>
 #include <Graphic3d_ShaderObject.hxx>
 #include <Graphic3d_ShaderVariable.hxx>
@@ -151,12 +152,13 @@ public:
   //! Set if standard program header should define default texture sampler occSampler0.
   void SetDefaultSampler (Standard_Boolean theHasDefSampler) { myHasDefSampler = theHasDefSampler; }
 
-  //! Return true if Fragment Shader color should output the weighted OIT coverage; FALSE by default.
-  Standard_Boolean HasWeightOitOutput() const { return myHasWeightOitOutput; }
+  //! Return if Fragment Shader color should output to OIT buffers; OFF by default.
+  Graphic3d_RenderTransparentMethod OitOutput() const { return myOitOutput; }
 
-  //! Set if Fragment Shader color should output the weighted OIT coverage.
-  //! Note that weighted OIT also requires at least 2 Fragment Outputs (color + coverage).
-  void SetWeightOitOutput (Standard_Boolean theOutput) { myHasWeightOitOutput = theOutput; }
+  //! Set if Fragment Shader color should output to OIT buffers.
+  //! Note that weighted OIT also requires at least 2 Fragment Outputs (color + coverage),
+  //! and Depth Peeling requires at least 3 Fragment Outputs (depth + front color + back color),
+  void SetOitOutput (Graphic3d_RenderTransparentMethod theOutput) { myOitOutput = theOutput; }
 
   //! Return TRUE if standard program header should define functions and variables used in PBR pipeline.
   //! FALSE by default.
@@ -223,9 +225,9 @@ private:
   Standard_Integer              myNbClipPlanesMax; //!< length of array of clipping planes (THE_MAX_CLIP_PLANES)
   Standard_Integer              myNbFragOutputs; //!< length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS)
   Standard_Integer              myTextureSetBits;//!< texture units declared within the program, @sa Graphic3d_TextureSetBits
+  Graphic3d_RenderTransparentMethod myOitOutput; //!< flag indicating that Fragment Shader includes OIT outputs
   Standard_Boolean              myHasDefSampler; //!< flag indicating that program defines default texture sampler occSampler0
   Standard_Boolean              myHasAlphaTest;       //!< flag indicating that Fragment Shader performs alpha test
-  Standard_Boolean              myHasWeightOitOutput; //!< flag indicating that Fragment Shader includes weighted OIT coverage
   Standard_Boolean              myIsPBR;         //!< flag indicating that program defines functions and variables used in PBR pipeline
 
 };
index 34d4aa026d330afaf5cdaac2043ded4be7659d3d..6916c4ada8796258b9b646b4c460e4c53f5c422d 100644 (file)
@@ -67,6 +67,14 @@ enum Graphic3d_TextureUnit
   //! Note that it can be overridden to Graphic3d_TextureUnit_0 for FFP fallback on hardware without multi-texturing.
   Graphic3d_TextureUnit_PointSprite = Graphic3d_TextureUnit_1,
 
+  //! sampler2D occDepthPeelingDepth.
+  //! 1st texture unit for Depth Peeling lookups.
+  Graphic3d_TextureUnit_DepthPeelingDepth = -6,
+
+  //! sampler2D occDepthPeelingFrontColor.
+  //! 2nd texture unit for Depth Peeling lookups.
+  Graphic3d_TextureUnit_DepthPeelingFrontColor = -5,
+
   //! sampler2D occShadowMapSampler.
   //! Directional light source shadowmap texture.
   Graphic3d_TextureUnit_ShadowMap = -4,
@@ -75,10 +83,12 @@ enum Graphic3d_TextureUnit
   //! Lookup table for approximated PBR environment lighting.
   //! Configured as index at the end of available texture units - 3.
   Graphic3d_TextureUnit_PbrEnvironmentLUT = -3,
+
   //! sampler2D occDiffIBLMapSHCoeffs.
   //! Diffuse (irradiance) IBL map's spherical harmonics coefficients baked for PBR from environment cubemap image.
   //! Configured as index at the end of available texture units - 2.
   Graphic3d_TextureUnit_PbrIblDiffuseSH   = -2,
+
   //! samplerCube occSpecIBLMap.
   //! Specular IBL (Image-Based Lighting) environment map baked for PBR from environment cubemap image.
   //! Configured as index at the end of available texture units - 1.
index 5c61112ef68d520f1f82518d22aa471bd028479a..786abcf16d7c0b50a42fd228ea860c7744048f97 100755 (executable)
@@ -75,6 +75,8 @@ OpenGl_ClippingIterator.hxx
 OpenGl_Context.cxx
 OpenGl_Context.hxx
 OpenGl_Context_1.mm
+OpenGl_DepthPeeling.cxx
+OpenGl_DepthPeeling.hxx
 OpenGl_ExtGS.hxx
 OpenGl_GLESExtensions.hxx
 OpenGl_GlFunctions.hxx
index 05d1761729ae7df63cb7dfea95cb58bf6c29c173..097e12fefe943032e3dd0657529c36ed45ce8d82 100644 (file)
@@ -221,6 +221,8 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
   myPBRDiffIBLMapSHTexUnit (Graphic3d_TextureUnit_PbrIblDiffuseSH),
   myPBRSpecIBLMapTexUnit   (Graphic3d_TextureUnit_PbrIblSpecular),
   myShadowMapTexUnit       (Graphic3d_TextureUnit_ShadowMap),
+  myDepthPeelingDepthTexUnit (Graphic3d_TextureUnit_DepthPeelingDepth),
+  myDepthPeelingFrontColorTexUnit (Graphic3d_TextureUnit_DepthPeelingFrontColor),
   myFrameStats (new OpenGl_FrameStats()),
   myActiveMockTextures (0),
   myActiveHatchType (Aspect_HS_SOLID),
@@ -3348,13 +3350,19 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
           || (IsGlGreaterEqual (2, 1) && CheckExtension ("GL_EXT_gpu_shader4"))
         #endif
              );
-  if (myHasPBR)
+
+  myDepthPeelingDepthTexUnit      = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_DepthPeelingDepth);      // -6
+  myDepthPeelingFrontColorTexUnit = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_DepthPeelingFrontColor); // -5
+  myShadowMapTexUnit              = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_ShadowMap);              // -4
+  myPBREnvLUTTexUnit              = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrEnvironmentLUT);      // -3
+  myPBRDiffIBLMapSHTexUnit        = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblDiffuseSH);        // -2
+  myPBRSpecIBLMapTexUnit          = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblSpecular);         // -1
+  if (!myHasPBR)
   {
-    myPBREnvLUTTexUnit       = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrEnvironmentLUT);
-    myPBRDiffIBLMapSHTexUnit = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblDiffuseSH);
-    myPBRSpecIBLMapTexUnit   = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_PbrIblSpecular);
+    myDepthPeelingDepthTexUnit      = static_cast<Graphic3d_TextureUnit>(myDepthPeelingDepthTexUnit + 3);
+    myDepthPeelingFrontColorTexUnit = static_cast<Graphic3d_TextureUnit>(myDepthPeelingFrontColorTexUnit + 3);
+    myShadowMapTexUnit              = static_cast<Graphic3d_TextureUnit>(myShadowMapTexUnit + 3);
   }
-  myShadowMapTexUnit = static_cast<Graphic3d_TextureUnit>(myMaxTexCombined + Graphic3d_TextureUnit_ShadowMap);
 }
 
 // =======================================================================
index 8e7d65780dcd23b46466d793e56b3a899fb32519..493a10e7650e1c33b80f61db43c88ffbfbbb0612 100644 (file)
@@ -633,6 +633,12 @@ public:
   //! Returns texture unit where shadow map is expected to be bound, or 0 if unavailable.
   Graphic3d_TextureUnit ShadowMapTexUnit() const { return myShadowMapTexUnit; }
 
+  //! Returns texture unit for occDepthPeelingDepth within enabled Depth Peeling.
+  Graphic3d_TextureUnit DepthPeelingDepthTexUnit() const { return myDepthPeelingDepthTexUnit; }
+
+  //! Returns texture unit for occDepthPeelingFrontColor within enabled Depth Peeling.
+  Graphic3d_TextureUnit DepthPeelingFrontColorTexUnit() const { return myDepthPeelingFrontColorTexUnit; }
+
   //! Returns true if VBO is supported and permitted.
   inline bool ToUseVbo() const
   {
@@ -1174,6 +1180,9 @@ private: // context info
   Graphic3d_TextureUnit myPBRSpecIBLMapTexUnit;   //!< samplerCube occSpecIBLMap, texture unit where specular IBL map is expected to  be binded (0 if PBR is not supported)
   Graphic3d_TextureUnit myShadowMapTexUnit;       //!< sampler2D occShadowMapSampler
 
+  Graphic3d_TextureUnit myDepthPeelingDepthTexUnit;      //!< sampler2D occDepthPeelingDepth, texture unit for Depth Peeling lookups
+  Graphic3d_TextureUnit myDepthPeelingFrontColorTexUnit; //!< sampler2D occDepthPeelingFrontColor, texture unit for Depth Peeling lookups
+
   Handle(OpenGl_ShaderManager) myShaderManager; //! support object for managing shader programs
 
 private: //! @name fields tracking current state
diff --git a/src/OpenGl/OpenGl_DepthPeeling.cxx b/src/OpenGl/OpenGl_DepthPeeling.cxx
new file mode 100644 (file)
index 0000000..af2e3ad
--- /dev/null
@@ -0,0 +1,107 @@
+// Created on: 2021-01-15
+// Copyright (c) 2021 OPEN CASCADE SAS
+//
+// This file is part of Open CASCADE Technology software library.
+//
+// This library is free software; you can redistribute it and/or modify it under
+// the terms of the GNU Lesser General Public License version 2.1 as published
+// by the Free Software Foundation, with special exception defined in the file
+// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
+// distribution for complete text of the license and disclaimer of any warranty.
+//
+// Alternatively, this file may be used under the terms of Open CASCADE
+// commercial license or contractual agreement.
+
+#include <OpenGl_ArbFBO.hxx>
+#include <OpenGl_DepthPeeling.hxx>
+
+IMPLEMENT_STANDARD_RTTIEXT(OpenGl_DepthPeeling, OpenGl_NamedResource)
+
+//=======================================================================
+// function : OpenGl_DepthPeeling
+// purpose  :
+//=======================================================================
+OpenGl_DepthPeeling::OpenGl_DepthPeeling()
+: OpenGl_NamedResource ("depth_peeling")
+{
+  myDepthPeelFbosOit[0]      = new OpenGl_FrameBuffer();
+  myDepthPeelFbosOit[1]      = new OpenGl_FrameBuffer();
+  myFrontBackColorFbosOit[0] = new OpenGl_FrameBuffer();
+  myFrontBackColorFbosOit[1] = new OpenGl_FrameBuffer();
+  myBlendBackFboOit          = new OpenGl_FrameBuffer();
+}
+
+// =======================================================================
+// function : ~OpenGl_DepthPeeling
+// purpose  :
+// =======================================================================
+OpenGl_DepthPeeling::~OpenGl_DepthPeeling()
+{
+  Release (NULL);
+}
+
+//=======================================================================
+// function : Release
+// purpose  :
+//=======================================================================
+void OpenGl_DepthPeeling::Release (OpenGl_Context* theCtx)
+{
+  myDepthPeelFbosOit[0]     ->Release (theCtx);
+  myDepthPeelFbosOit[1]     ->Release (theCtx);
+  myFrontBackColorFbosOit[0]->Release (theCtx);
+  myFrontBackColorFbosOit[1]->Release (theCtx);
+  myBlendBackFboOit         ->Release (theCtx);
+}
+
+//=======================================================================
+// function : EstimatedDataSize
+// purpose  :
+//=======================================================================
+Standard_Size OpenGl_DepthPeeling::EstimatedDataSize() const
+{
+  return myDepthPeelFbosOit[0]->EstimatedDataSize()
+       + myDepthPeelFbosOit[1]->EstimatedDataSize()
+       + myFrontBackColorFbosOit[0]->EstimatedDataSize()
+       + myFrontBackColorFbosOit[1]->EstimatedDataSize()
+       + myBlendBackFboOit->EstimatedDataSize();
+}
+
+//=======================================================================
+// function : AttachDepthTexture
+// purpose  :
+//=======================================================================
+void OpenGl_DepthPeeling::AttachDepthTexture (const Handle(OpenGl_Context)& theCtx,
+                                              const Handle(OpenGl_Texture)& theDepthStencilTexture)
+{
+  if (!theDepthStencilTexture.IsNull()
+    && theDepthStencilTexture->IsValid())
+  {
+    for (int aPairIter = 0; aPairIter < 2; ++aPairIter)
+    {
+      myDepthPeelFbosOit[aPairIter]->BindBuffer (theCtx);
+      theCtx->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+                                              theDepthStencilTexture->GetTarget(),
+                                              theDepthStencilTexture->TextureId(), 0);
+      myDepthPeelFbosOit[aPairIter]->UnbindBuffer (theCtx);
+    }
+  }
+}
+
+//=======================================================================
+// function : DetachDepthTexture
+// purpose  :
+//=======================================================================
+void OpenGl_DepthPeeling::DetachDepthTexture (const Handle(OpenGl_Context)& theCtx)
+{
+  if (!myDepthPeelFbosOit[0]->DepthStencilTexture().IsNull())
+  {
+    for (int aPairIter = 0; aPairIter < 2; ++aPairIter)
+    {
+      myDepthPeelFbosOit[aPairIter]->BindBuffer (theCtx);
+      theCtx->arbFBO->glFramebufferTexture2D (GL_FRAMEBUFFER, GL_DEPTH_STENCIL_ATTACHMENT,
+                                              myDepthPeelFbosOit[aPairIter]->DepthStencilTexture()->GetTarget(),
+                                              0, 0);
+      myDepthPeelFbosOit[aPairIter]->UnbindBuffer (theCtx);
+    }
+  }
+}
diff --git a/src/OpenGl/OpenGl_DepthPeeling.hxx b/src/OpenGl/OpenGl_DepthPeeling.hxx
new file mode 100644 (file)
index 0000000..b26a958
--- /dev/null
@@ -0,0 +1,62 @@
+// Created on: 2021-01-15
+// Copyright (c) 2021 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_DepthPeeling_HeaderFile
+#define _OpenGl_DepthPeeling_HeaderFile
+
+#include <OpenGl_FrameBuffer.hxx>
+
+//! Class provides FBOs for dual depth peeling.
+class OpenGl_DepthPeeling : public OpenGl_NamedResource
+{
+  DEFINE_STANDARD_RTTIEXT(OpenGl_DepthPeeling, OpenGl_NamedResource)
+public:
+
+  //! Constructor.
+  Standard_EXPORT OpenGl_DepthPeeling();
+
+  //! Destructor.
+  Standard_EXPORT virtual ~OpenGl_DepthPeeling();
+
+  //! Release OpenGL resources
+  Standard_EXPORT virtual void Release (OpenGl_Context* theGlCtx) Standard_OVERRIDE;
+
+  //! Returns estimated GPU memory usage for holding data without considering overheads and allocation alignment rules.
+  Standard_EXPORT virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE;
+
+  //! Attach a texture image
+  Standard_EXPORT void AttachDepthTexture (const Handle(OpenGl_Context)& theCtx,
+                                           const Handle(OpenGl_Texture)& theDepthStencilTexture);
+
+  //! Detach a texture image
+  Standard_EXPORT void DetachDepthTexture (const Handle(OpenGl_Context)& theCtx);
+
+  //! Returns additional buffers for ping-pong
+  const Handle(OpenGl_FrameBuffer)* DepthPeelFbosOit() const { return myDepthPeelFbosOit; }
+
+  //! Returns additional buffers for ping-pong
+  const Handle(OpenGl_FrameBuffer)* FrontBackColorFbosOit() const { return myFrontBackColorFbosOit; }
+
+  //! Returns additional FBO for depth peeling
+  const Handle(OpenGl_FrameBuffer)& BlendBackFboOit() const { return myBlendBackFboOit; }
+
+private:
+
+  Handle(OpenGl_FrameBuffer) myDepthPeelFbosOit[2];      //!< depth + front color + back color
+  Handle(OpenGl_FrameBuffer) myFrontBackColorFbosOit[2]; //!< front color + back color
+  Handle(OpenGl_FrameBuffer) myBlendBackFboOit;
+
+};
+
+#endif // _OpenGl_DepthPeeling_HeaderFile
index a05e3216600c61fe4649d167a33f3b1372c024ba..0956287b83f86c462eb3ed57e8fee9266cce5bff 100644 (file)
@@ -74,7 +74,8 @@ OpenGl_FrameBuffer::OpenGl_FrameBuffer()
   myGlFBufferId (NO_FRAMEBUFFER),
   myGlColorRBufferId (NO_RENDERBUFFER),
   myGlDepthRBufferId (NO_RENDERBUFFER),
-  myIsOwnBuffer  (false),
+  myIsOwnBuffer (false),
+  myIsOwnColor  (false),
   myIsOwnDepth  (false),
   myDepthStencilTexture (new OpenGl_Texture())
 {
@@ -91,6 +92,74 @@ OpenGl_FrameBuffer::~OpenGl_FrameBuffer()
   Release (NULL);
 }
 
+// =======================================================================
+// function : InitWrapper
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_FrameBuffer::InitWrapper (const Handle(OpenGl_Context)& theGlContext,
+                                                  const NCollection_Sequence<Handle(OpenGl_Texture)>& theColorTextures,
+                                                  const Handle(OpenGl_Texture)& theDepthTexture)
+{
+  Release (theGlContext.get());
+  if (theGlContext->arbFBO == NULL)
+  {
+    return false;
+  }
+
+  myColorFormats.Clear();
+  myColorTextures.Clear();
+  for (NCollection_Sequence<Handle(OpenGl_Texture)>::Iterator aColorIter (theColorTextures); aColorIter.More(); aColorIter.Next())
+  {
+    myColorTextures.Append (aColorIter.Value());
+  }
+  myDepthFormat = 0;
+  myDepthStencilTexture = theDepthTexture;
+  myNbSamples = theColorTextures.First()->NbSamples();
+
+  myIsOwnColor  = false;
+  myIsOwnDepth  = false;
+  myIsOwnBuffer = true;
+
+  myVPSizeX = theColorTextures.First()->SizeX();
+  myVPSizeY = theColorTextures.First()->SizeY();
+
+  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.IsNull()
+    && myDepthStencilTexture->IsValid())
+  {
+    if (hasDepthStencilAttach (theGlContext))
+    {
+      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);
+    }
+  }
+  if (theGlContext->arbFBO->glCheckFramebufferStatus (GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
+  {
+    Release (theGlContext.get());
+    return false;
+  }
+
+  UnbindBuffer (theGlContext);
+  return true;
+}
+
 // =======================================================================
 // function : Init
 // purpose  :
@@ -103,9 +172,10 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo
                                            const GLsizei                 theNbSamples)
 {
   OpenGl_ColorFormats aColorFormats;
-
-  aColorFormats.Append (theColorFormat);
-
+  if (theColorFormat != 0)
+  {
+    aColorFormats.Append (theColorFormat);
+  }
   return Init (theGlContext, theSizeX, theSizeY, aColorFormats, theDepthFormat, theNbSamples);
 }
 
@@ -152,6 +222,7 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo
   }
 
   myDepthStencilTexture = theDepthStencilTexture;
+  myIsOwnColor  = true;
   myIsOwnDepth  = false;
   myIsOwnBuffer = true;
 
@@ -168,8 +239,8 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo
     {
       const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
       const GLint                   aColorFormat  = myColorFormats  (aColorBufferIdx);
-      if (aColorFormat != 0
-      && !aColorTexture->Init2DMultisample (theGlContext, theNbSamples,
+      if (aColorFormat == 0
+      || !aColorTexture->Init2DMultisample (theGlContext, theNbSamples,
                                             aColorFormat, aSizeX, aSizeY))
       {
         Release (theGlContext.get());
@@ -184,8 +255,8 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo
       const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
       const GLint                   aColorFormat  = myColorFormats  (aColorBufferIdx);
       const OpenGl_TextureFormat aFormat = OpenGl_TextureFormat::FindSizedFormat (theGlContext, aColorFormat);
-      if (aFormat.IsValid()
-      && !aColorTexture->Init (theGlContext, aFormat, Graphic3d_Vec2i (aSizeX, aSizeY), Graphic3d_TOT_2D))
+      if (!aFormat.IsValid()
+       || !aColorTexture->Init (theGlContext, aFormat, Graphic3d_Vec2i (aSizeX, aSizeY), Graphic3d_TOT_2D))
       {
         Release (theGlContext.get());
         return Standard_False;
@@ -275,6 +346,7 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo
     return Standard_False;
   }
 
+  myIsOwnColor  = true;
   myIsOwnBuffer = true;
   myIsOwnDepth  = true;
 
@@ -292,8 +364,8 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo
     {
       const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
       const GLint                   aColorFormat  = myColorFormats  (aColorBufferIdx);
-      if (aColorFormat != 0
-      && !aColorTexture->Init2DMultisample (theGlContext, theNbSamples, aColorFormat, aSizeX, aSizeY))
+      if (aColorFormat == 0
+      || !aColorTexture->Init2DMultisample (theGlContext, theNbSamples, aColorFormat, aSizeX, aSizeY))
       {
         Release (theGlContext.operator->());
         return Standard_False;
@@ -313,8 +385,8 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo
       const Handle(OpenGl_Texture)& aColorTexture = myColorTextures (aColorBufferIdx);
       const GLint                   aColorFormat  = myColorFormats  (aColorBufferIdx);
       const OpenGl_TextureFormat aFormat = OpenGl_TextureFormat::FindSizedFormat (theGlContext, aColorFormat);
-      if (aFormat.IsValid()
-      && !aColorTexture->Init (theGlContext, aFormat, Graphic3d_Vec2i (aSizeX, aSizeY), Graphic3d_TOT_2D))
+      if (!aFormat.IsValid()
+       || !aColorTexture->Init (theGlContext, aFormat, Graphic3d_Vec2i (aSizeX, aSizeY), Graphic3d_TOT_2D))
       {
         Release (theGlContext.operator->());
         return Standard_False;
@@ -476,6 +548,7 @@ Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& t
   // clean up previous state
   Release (theGlCtx.operator->());
 
+  myIsOwnColor  = true;
   myIsOwnBuffer = true;
   myIsOwnDepth  = true;
 
@@ -573,6 +646,7 @@ Standard_Boolean OpenGl_FrameBuffer::InitWrapper (const Handle(OpenGl_Context)&
   theGlCtx->arbFBO->glGetFramebufferAttachmentParameteriv (GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT,  GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE, &aDepthType);
 
   myGlFBufferId = GLuint(anFbo);
+  myIsOwnColor  = false;
   myIsOwnBuffer = false;
   myIsOwnDepth  = false;
   if (aColorType == GL_RENDERBUFFER)
@@ -648,9 +722,13 @@ void OpenGl_FrameBuffer::Release (OpenGl_Context* theGlCtx)
     myIsOwnBuffer      = false;
   }
 
-  for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
+  if (myIsOwnColor)
   {
-    myColorTextures (aColorBufferIdx)->Release (theGlCtx);
+    for (Standard_Integer aColorBufferIdx = 0; aColorBufferIdx < myColorTextures.Length(); ++aColorBufferIdx)
+    {
+      myColorTextures (aColorBufferIdx)->Release (theGlCtx);
+    }
+    myIsOwnColor = false;
   }
 
   if (myIsOwnDepth)
index d043967779b131457ec2832dddddc9fc4f6a5f9c..bc204e17323f93bd17c004e88affd67c8b278af9 100644 (file)
@@ -216,6 +216,11 @@ public:
   //! Retrieved OpenGL objects will not be destroyed on Release.
   Standard_EXPORT Standard_Boolean InitWrapper (const Handle(OpenGl_Context)& theGlCtx);
 
+  //! Wrap existing color textures.
+  Standard_EXPORT Standard_Boolean InitWrapper (const Handle(OpenGl_Context)& theGlContext,
+                                                const NCollection_Sequence<Handle(OpenGl_Texture)>& theColorTextures,
+                                                const Handle(OpenGl_Texture)& theDepthTexture = Handle(OpenGl_Texture)());
+
   //! Setup viewport to render into FBO
   Standard_EXPORT void SetupViewport (const Handle(OpenGl_Context)& theGlCtx);
 
@@ -286,7 +291,8 @@ protected:
   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
-  bool                   myIsOwnDepth;          //!< flag indicating that FBO should be deallocated by this class
+  bool                   myIsOwnColor;          //!< flag indicating that color textures should be deallocated by this class
+  bool                   myIsOwnDepth;          //!< flag indicating that depth texture  should be deallocated by this class
   OpenGl_TextureArray    myColorTextures;       //!< color texture objects
   Handle(OpenGl_Texture) myDepthStencilTexture; //!< depth-stencil texture object
 
index d4bf258367e6b31174266a28b1d2b1390072274f..568c3c06b4a2b37c849f1acea2c008ce01a5b062 100644 (file)
@@ -15,6 +15,7 @@
 
 #include <OpenGl_GlCore20.hxx>
 #include <OpenGl_View.hxx>
+#include <OpenGl_DepthPeeling.hxx>
 #include <OpenGl_ShadowMap.hxx>
 #include <OpenGl_Workspace.hxx>
 
@@ -149,6 +150,7 @@ void OpenGl_FrameStats::updateStatistics (const Handle(Graphic3d_CView)& theView
       aMemFbos += estimatedDataSize (aView->myMainSceneFbosOit[1]);
       aMemFbos += estimatedDataSize (aView->myImmediateSceneFbosOit[0]);
       aMemFbos += estimatedDataSize (aView->myImmediateSceneFbosOit[1]);
+      aMemFbos += estimatedDataSize (aView->myDepthPeelingFbos);
       // shadowmap FBOs
       aMemFbos += aView->myShadowMaps->EstimatedDataSize();
       // dump FBO
index 12e2754e1da4c7c5c1e633df69bfdd98c196eab7..79b32cc78985653c019dc9220d7eba31047059e2 100644 (file)
@@ -16,6 +16,7 @@
 #include <OpenGl_GlCore15.hxx>
 
 #include <BVH_LinearBuilder.hxx>
+#include <OpenGl_DepthPeeling.hxx>
 #include <OpenGl_FrameBuffer.hxx>
 #include <OpenGl_LayerList.hxx>
 #include <OpenGl_ShaderManager.hxx>
@@ -136,6 +137,11 @@ namespace
     OpenGl_LayerFilter          myLayersToProcess;
     Standard_Boolean            myToDrawImmediate;
   };
+
+  static const Standard_Integer THE_DRAW_BUFFERS0[]   = { GL_COLOR_ATTACHMENT0 };
+  static const Standard_Integer THE_DRAW_BUFFERS01[]  = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0 + 1 };
+  static const Standard_Integer THE_DRAW_BUFFERS012[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0 + 1, GL_COLOR_ATTACHMENT0 + 2 };
+  static const float THE_DEPTH_CLEAR_VALUE = -1e15f;
 }
 
 struct OpenGl_GlobalLayerSettings
@@ -860,17 +866,6 @@ void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)&   theW
                                           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.
@@ -879,105 +874,331 @@ void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)&   theW
     return;
   }
 
-  const Handle(OpenGl_Context) aCtx            = theWorkspace->GetGlContext();
+  const Handle(OpenGl_Context)& aCtx           = theWorkspace->GetGlContext();
   const Handle(OpenGl_ShaderManager)& aManager = aCtx->ShaderManager();
+  const OpenGl_LayerStack::iterator aLayerFrom = theLayerIter;
   OpenGl_View* aView = theWorkspace->View();
-  const float aDepthFactor =  aView != NULL ? aView->RenderingParams().OitDepthFactor : 0.0f;
+
+  Graphic3d_RenderTransparentMethod anOitMode = aView != NULL
+                                              ? aView->RenderingParams().TransparencyMethod
+                                              : Graphic3d_RTM_BLEND_UNORDERED;
 
   const Standard_Integer aPrevFilter = theWorkspace->RenderFilter() & ~(Standard_Integer )(OpenGl_RenderFilter_OpaqueOnly | OpenGl_RenderFilter_TransparentOnly);
   theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_TransparentOnly);
-
   aCtx->core11fwd->glEnable (GL_BLEND);
 
-  if (isEnabledOit)
-  {
-    aManager->SetOitState (true, aDepthFactor);
-
-    theOitAccumFbo->BindBuffer (aCtx);
+  const Handle(OpenGl_FrameBuffer)* aGlDepthPeelFBOs = aView->DepthPeelingFbos()->DepthPeelFbosOit();
+  const Handle(OpenGl_FrameBuffer)* aGlFrontBackColorFBOs = aView->DepthPeelingFbos()->FrontBackColorFbosOit();
+  const Handle(OpenGl_FrameBuffer)& aGlBlendBackFBO = aView->DepthPeelingFbos()->BlendBackFboOit();
 
-    static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0 + 1 };
-    aCtx->SetDrawBuffers (2, aDrawBuffers);
-    aCtx->SetColorMaskRGBA (NCollection_Vec4<bool> (true)); // force writes into all components, including alpha
-    aCtx->core11fwd->glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
-    aCtx->core11fwd->glClear (GL_COLOR_BUFFER_BIT);
-    aCtx->core15fwd->glBlendFuncSeparate (GL_ONE, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
+  // 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).
+  if (anOitMode == Graphic3d_RTM_BLEND_OIT)
+  {
+    if (theOitAccumFbo == NULL
+    ||  theOitAccumFbo->NbColorBuffers() < 2
+    || !theOitAccumFbo->ColorTexture (0)->IsValid()
+    || !theOitAccumFbo->ColorTexture (1)->IsValid())
+    {
+      anOitMode = Graphic3d_RTM_BLEND_UNORDERED;
+    }
   }
-  else
+  else if (anOitMode == Graphic3d_RTM_DEPTH_PEELING_OIT)
+  {
+    if (!aGlBlendBackFBO->IsValid())
+    {
+      anOitMode = Graphic3d_RTM_BLEND_UNORDERED;
+    }
+  }
+  const bool isMSAA = theReadDrawFbo && theReadDrawFbo->NbSamples() > 0;
+  int aDepthPeelingDrawId = -1;
+
+  switch (anOitMode)
   {
-    aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+    case Graphic3d_RTM_BLEND_UNORDERED:
+    {
+      aCtx->core11fwd->glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+      break;
+    }
+    case Graphic3d_RTM_BLEND_OIT:
+    {
+      const float aDepthFactor = aView->RenderingParams().OitDepthFactor;
+      aManager->SetWeighedOitState (aDepthFactor);
+
+      theOitAccumFbo->BindBuffer (aCtx);
+
+      aCtx->SetDrawBuffers (2, THE_DRAW_BUFFERS01);
+      aCtx->SetColorMaskRGBA (NCollection_Vec4<bool> (true)); // force writes into all components, including alpha
+      aCtx->core11fwd->glClearColor (0.0f, 0.0f, 0.0f, 1.0f);
+      aCtx->core11fwd->glClear (GL_COLOR_BUFFER_BIT);
+      aCtx->core15fwd->glBlendFuncSeparate (GL_ONE, GL_ONE, GL_ZERO, GL_ONE_MINUS_SRC_ALPHA);
+      break;
+    }
+    case Graphic3d_RTM_DEPTH_PEELING_OIT:
+    {
+      static const float THE_MIN_DEPTH = 0.0f;
+      static const float THE_MAX_DEPTH = 1.0f;
+
+      aView->DepthPeelingFbos()->AttachDepthTexture (aCtx, theReadDrawFbo->DepthStencilTexture());
+
+      // initialize min/max depth buffer
+      aGlBlendBackFBO->BindDrawBuffer (aCtx);
+      aCtx->SetDrawBuffers (1, THE_DRAW_BUFFERS0);
+      aCtx->core20fwd->glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
+      aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT);
+
+      aGlDepthPeelFBOs[1]->BindDrawBuffer (aCtx);
+      aCtx->SetDrawBuffers (1, THE_DRAW_BUFFERS0);
+      aCtx->core20fwd->glClearColor(-THE_MIN_DEPTH, THE_MAX_DEPTH, 0.0f, 0.0f);
+      aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT);
+
+      aGlFrontBackColorFBOs[0]->BindDrawBuffer (aCtx);
+      aCtx->SetDrawBuffers (2, THE_DRAW_BUFFERS01);
+      aCtx->core20fwd->glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
+      aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT);
+
+      aGlFrontBackColorFBOs[1]->BindDrawBuffer (aCtx);
+      aCtx->SetDrawBuffers (2, THE_DRAW_BUFFERS01);
+      aCtx->core20fwd->glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
+      aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT);
+
+      // draw depth for first pass to peel
+      aGlDepthPeelFBOs[0]->BindBuffer (aCtx);
+
+      aCtx->SetDrawBuffers (1, THE_DRAW_BUFFERS0);
+      aCtx->core20fwd->glClearColor (THE_DEPTH_CLEAR_VALUE, THE_DEPTH_CLEAR_VALUE, 0.0f, 0.0f);
+      aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT);
+      aCtx->core20fwd->glBlendEquation (GL_MAX);
+
+      aManager->SetOitState (Graphic3d_RTM_DEPTH_PEELING_OIT);
+
+      aGlDepthPeelFBOs[1]->ColorTexture (0)->Bind (aCtx, aCtx->DepthPeelingDepthTexUnit());
+      aGlDepthPeelFBOs[1]->ColorTexture (1)->Bind (aCtx, aCtx->DepthPeelingFrontColorTexUnit());
+      break;
+    }
   }
 
   // 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.
+  // overall 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)
+  for (theLayerIter = aLayerFrom; theLayerIter != myTransparentToProcess.Back(); ++theLayerIter)
   {
     renderLayer (theWorkspace, aGlobalSettings, *(*theLayerIter));
   }
 
-  // Revert state of rendering.
-  if (isEnabledOit)
+  switch (anOitMode)
   {
-    aManager->SetOitState (false, aDepthFactor);
-    theOitAccumFbo->UnbindBuffer (aCtx);
-    if (theReadDrawFbo)
+    case Graphic3d_RTM_BLEND_UNORDERED:
     {
-      theReadDrawFbo->BindBuffer (aCtx);
+      break;
     }
+    case Graphic3d_RTM_BLEND_OIT:
+    {
+      // revert state of rendering
+      aManager->ResetOitState();
+      theOitAccumFbo->UnbindBuffer (aCtx);
+      if (theReadDrawFbo)
+      {
+        theReadDrawFbo->BindBuffer (aCtx);
+      }
+
+      aCtx->SetDrawBuffers (1, THE_DRAW_BUFFERS0);
+      aCtx->SetColorMask (true); // update writes into alpha component
+      break;
+    }
+    case Graphic3d_RTM_DEPTH_PEELING_OIT:
+    {
+      // Dual Depth Peeling Ping-Pong
+      const int aNbPasses = aView->RenderingParams().NbOitDepthPeelingLayers;
+      OpenGl_VertexBuffer* aQuadVerts = aView->initBlitQuad (false);
+
+      aGlDepthPeelFBOs[1]->ColorTexture (1)->Unbind (aCtx, aCtx->DepthPeelingFrontColorTexUnit());
+      aGlDepthPeelFBOs[1]->ColorTexture (0)->Unbind (aCtx, aCtx->DepthPeelingDepthTexUnit());
+
+      for (int aPass = 0; aPass < aNbPasses; ++aPass)
+      {
+        const int aReadId = aPass % 2;
+        aDepthPeelingDrawId = 1 - aReadId;
+
+        aGlDepthPeelFBOs[aDepthPeelingDrawId]->BindDrawBuffer (aCtx);
+        aCtx->SetDrawBuffers (1, THE_DRAW_BUFFERS0);
+        aCtx->core20fwd->glClearColor (THE_DEPTH_CLEAR_VALUE, THE_DEPTH_CLEAR_VALUE, 0.0f, 0.0f);
+        aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT);
+
+        aGlFrontBackColorFBOs[aDepthPeelingDrawId]->BindDrawBuffer (aCtx);
+        aCtx->SetDrawBuffers (2, THE_DRAW_BUFFERS01);
+        aCtx->core20fwd->glClearColor (0.0f, 0.0f, 0.0f, 0.0f);
+        aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT);
+
+        ///aGlDepthPeelFBOs[aDepthPeelingDrawId]->BindDrawBuffer (aCtx);
+        aGlDepthPeelFBOs[aDepthPeelingDrawId]->BindBuffer (aCtx);
+        aCtx->SetDrawBuffers (3, THE_DRAW_BUFFERS012);
+        aCtx->core20fwd->glBlendEquation (GL_MAX);
 
-    static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0 };
-    aCtx->SetDrawBuffers (1, aDrawBuffers);
-    aCtx->SetColorMask (true); // update writes into alpha component
+        aGlDepthPeelFBOs[aReadId]->ColorTexture (0)->Bind (aCtx, aCtx->DepthPeelingDepthTexUnit());
+        aGlDepthPeelFBOs[aReadId]->ColorTexture (1)->Bind (aCtx, aCtx->DepthPeelingFrontColorTexUnit());
+
+        // draw geometry
+        for (theLayerIter = aLayerFrom; theLayerIter != myTransparentToProcess.Back(); ++theLayerIter)
+        {
+          renderLayer (theWorkspace, aGlobalSettings, *(*theLayerIter));
+        }
+
+        aGlDepthPeelFBOs[aReadId]->ColorTexture (1)->Unbind (aCtx, aCtx->DepthPeelingFrontColorTexUnit());
+        aGlDepthPeelFBOs[aReadId]->ColorTexture (0)->Unbind (aCtx, aCtx->DepthPeelingDepthTexUnit());
+
+        // blend back color
+        aGlBlendBackFBO->BindDrawBuffer (aCtx);
+        aCtx->SetDrawBuffers (1, THE_DRAW_BUFFERS0);
+        if (aQuadVerts->IsValid()
+         && aManager->BindOitDepthPeelingBlendProgram (isMSAA))
+        {
+          aCtx->core20fwd->glBlendEquation (GL_FUNC_ADD);
+          aCtx->core20fwd->glBlendFuncSeparate (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+          aCtx->core20fwd->glDepthFunc (GL_ALWAYS);
+
+          aQuadVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
+
+          const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)());
+          aGlDepthPeelFBOs[aDepthPeelingDrawId]->ColorTexture (2)->Bind (aCtx, Graphic3d_TextureUnit_0);
+
+          aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
+
+          aQuadVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
+          aGlDepthPeelFBOs[aDepthPeelingDrawId]->ColorTexture (2)->Unbind (aCtx, Graphic3d_TextureUnit_0);
+          aCtx->BindProgram (NULL);
+
+          if (!aTextureBack.IsNull())
+          {
+            aCtx->BindTextures (aTextureBack, Handle(OpenGl_ShaderProgram)());
+          }
+
+          aCtx->core11fwd->glDepthFunc (theGlobalSettings.DepthFunc);
+        }
+        else
+        {
+          aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                             "Initialization of OIT compositing pass has failed.\n"
+                             "  Depth Peeling order-independent transparency will not be available.\n");
+          if (aView != NULL)
+          {
+            Standard_Boolean& aOITFlag = isMSAA ? aView->myToDisableOITMSAA : aView->myToDisableOIT;
+            aOITFlag = Standard_True;
+          }
+        }
+      }
+
+      aManager->ResetOitState();
+      aGlBlendBackFBO->UnbindBuffer (aCtx);
+      if (theReadDrawFbo)
+      {
+        theReadDrawFbo->BindBuffer (aCtx);
+      }
+      aCtx->SetDrawBuffers (1, THE_DRAW_BUFFERS0);
+      break;
+    }
   }
 
   theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_OpaqueOnly);
-  if (isEnabledOit)
+  switch (anOitMode)
   {
-    const Standard_Boolean isMSAA = theReadDrawFbo && theReadDrawFbo->NbSamples() > 0;
-    OpenGl_VertexBuffer*   aVerts = theWorkspace->View()->initBlitQuad (Standard_False);
-    if (aVerts->IsValid() && aManager->BindOitCompositingProgram (isMSAA))
+    case Graphic3d_RTM_BLEND_UNORDERED:
     {
-      aCtx->core11fwd->glDepthFunc (GL_ALWAYS);
-      aCtx->core11fwd->glDepthMask (GL_FALSE);
-
-      // Bind full screen quad buffer and framebuffer resources.
-      aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
+      break;
+    }
+    case Graphic3d_RTM_BLEND_OIT:
+    {
+      // draw full screen quad with special shader to compose the buffers
+      OpenGl_VertexBuffer* aVerts = aView->initBlitQuad (Standard_False);
+      if (aVerts->IsValid()
+       && aManager->BindOitCompositingProgram (isMSAA))
+      {
+        aCtx->core11fwd->glDepthFunc (GL_ALWAYS);
+        aCtx->core11fwd->glDepthMask (GL_FALSE);
 
-      const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)());
+        aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
 
-      theOitAccumFbo->ColorTexture (0)->Bind (aCtx, Graphic3d_TextureUnit_0);
-      theOitAccumFbo->ColorTexture (1)->Bind (aCtx, Graphic3d_TextureUnit_1);
+        const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)());
+        theOitAccumFbo->ColorTexture (0)->Bind (aCtx, Graphic3d_TextureUnit_0);
+        theOitAccumFbo->ColorTexture (1)->Bind (aCtx, Graphic3d_TextureUnit_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);
+        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 (1)->Unbind (aCtx, Graphic3d_TextureUnit_1);
-      theOitAccumFbo->ColorTexture (0)->Unbind (aCtx, Graphic3d_TextureUnit_0);
-      aCtx->BindProgram (NULL);
+        aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
+        theOitAccumFbo->ColorTexture (1)->Unbind (aCtx, Graphic3d_TextureUnit_1);
+        theOitAccumFbo->ColorTexture (0)->Unbind (aCtx, Graphic3d_TextureUnit_0);
+        aCtx->BindProgram (NULL);
 
-      if (!aTextureBack.IsNull())
+        if (!aTextureBack.IsNull())
+        {
+          aCtx->BindTextures (aTextureBack, Handle(OpenGl_ShaderProgram)());
+        }
+      }
+      else
       {
-        aCtx->BindTextures (aTextureBack, Handle(OpenGl_ShaderProgram)());
+        aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                           "Initialization of OIT compositing pass has failed.\n"
+                           "  Blended order-independent transparency will not be available.\n");
+        if (aView != NULL)
+        {
+          Standard_Boolean& aOITFlag = isMSAA ? aView->myToDisableOITMSAA : aView->myToDisableOIT;
+          aOITFlag = Standard_True;
+        }
       }
+      break;
     }
-    else
+    case Graphic3d_RTM_DEPTH_PEELING_OIT:
     {
-      aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
-                         "Initialization of OIT compositing pass has failed.\n"
-                         "  Blended order-independent transparency will not be available.\n");
-      if (aView != NULL)
+      // compose depth peeling results into destination FBO
+      OpenGl_VertexBuffer* aVerts = aView->initBlitQuad (Standard_False);
+      if (aVerts->IsValid()
+       && aManager->BindOitDepthPeelingFlushProgram (isMSAA))
       {
-        Standard_Boolean& aOITFlag = isMSAA ? aView->myToDisableOITMSAA : aView->myToDisableOIT;
-        aOITFlag = Standard_True;
+        aCtx->core20fwd->glBlendFunc (GL_ONE, GL_ONE_MINUS_SRC_ALPHA);
+        aCtx->core20fwd->glDepthFunc (GL_ALWAYS);
+
+        aVerts->BindVertexAttrib (aCtx, Graphic3d_TOA_POS);
+
+        const Handle(OpenGl_TextureSet) aTextureBack = aCtx->BindTextures (Handle(OpenGl_TextureSet)(), Handle(OpenGl_ShaderProgram)());
+        aGlDepthPeelFBOs[aDepthPeelingDrawId]->ColorTexture (1)->Bind (aCtx, Graphic3d_TextureUnit_0);
+        aGlBlendBackFBO->ColorTexture (0)->Bind (aCtx, Graphic3d_TextureUnit_1);
+
+        aCtx->core20fwd->glDrawArrays (GL_TRIANGLE_STRIP, 0, 4);
+
+        aVerts->UnbindVertexAttrib (aCtx, Graphic3d_TOA_POS);
+        aGlBlendBackFBO->ColorTexture (0)->Unbind (aCtx, Graphic3d_TextureUnit_1);
+        aGlDepthPeelFBOs[aDepthPeelingDrawId]->ColorTexture (1)->Unbind (aCtx, Graphic3d_TextureUnit_0);
+        aCtx->BindProgram (NULL);
+
+        if (!aTextureBack.IsNull())
+        {
+          aCtx->BindTextures (aTextureBack, Handle(OpenGl_ShaderProgram)());
+        }
+
+        aCtx->core11fwd->glDepthFunc (theGlobalSettings.DepthFunc);
+      }
+      else
+      {
+        aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                           "Initialization of OIT compositing pass has failed.\n"
+                           "  Depth Peeling order-independent transparency will not be available.\n");
+        if (aView != NULL)
+        {
+          Standard_Boolean& aOITFlag = isMSAA ? aView->myToDisableOITMSAA : aView->myToDisableOIT;
+          aOITFlag = true;
+        }
       }
+      aView->DepthPeelingFbos()->DetachDepthTexture (aCtx);
+      break;
     }
   }
 
index 0c1eabe17780da27cc012c5fa17fe77b361f938a..8b718bb5c7ff5aab6e509629dab8c1b4ad906dcb 100644 (file)
@@ -38,8 +38,9 @@ enum OpenGl_ProgramOptions
   OpenGl_PO_MeshEdges       = 0x0200, //!< draw mesh edges (wireframe)
   OpenGl_PO_AlphaTest       = 0x0400, //!< discard fragment by alpha test (defined by cutoff value)
   OpenGl_PO_WriteOit        = 0x0800, //!< write coverage buffer for Blended Order-Independent Transparency
+  OpenGl_PO_OitDepthPeeling = 0x1000, //!< handle Depth Peeling OIT
   //
-  OpenGl_PO_NB              = 0x1000, //!< overall number of combinations
+  OpenGl_PO_NB              = 0x2000, //!< overall number of combinations
   OpenGl_PO_IsPoint         = OpenGl_PO_PointSimple|OpenGl_PO_PointSprite|OpenGl_PO_PointSpriteA,
   OpenGl_PO_HasTextures     = OpenGl_PO_TextureRGB|OpenGl_PO_TextureEnv,
   OpenGl_PO_NeedsGeomShader = OpenGl_PO_MeshEdges,
index 173156f0265dead69a49708e2140a4b920805ab5..b722f7bfe2a5cb8c6c3db73db9a296d870fa1e95 100644 (file)
@@ -1216,14 +1216,11 @@ void OpenGl_ShaderManager::pushMaterialState (const Handle(OpenGl_ShaderProgram)
 // =======================================================================
 void OpenGl_ShaderManager::pushOitState (const Handle(OpenGl_ShaderProgram)& theProgram) const
 {
-  const GLint aLocOutput = theProgram->GetStateLocation (OpenGl_OCCT_OIT_OUTPUT);
-  if (aLocOutput != OpenGl_ShaderProgram::INVALID_LOCATION)
+  if (const OpenGl_ShaderUniformLocation& aLocOutput = theProgram->GetStateLocation (OpenGl_OCCT_OIT_OUTPUT))
   {
-    theProgram->SetUniform (myContext, aLocOutput, myOitState.ToEnableWrite());
+    theProgram->SetUniform (myContext, aLocOutput, (GLint )myOitState.ActiveMode());
   }
-
-  const GLint aLocDepthFactor = theProgram->GetStateLocation (OpenGl_OCCT_OIT_DEPTH_FACTOR);
-  if (aLocDepthFactor != OpenGl_ShaderProgram::INVALID_LOCATION)
+  if (const OpenGl_ShaderUniformLocation& aLocDepthFactor = theProgram->GetStateLocation (OpenGl_OCCT_OIT_DEPTH_FACTOR))
   {
     theProgram->SetUniform (myContext, aLocDepthFactor, myOitState.DepthFactor());
   }
@@ -1542,17 +1539,6 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const St
       EOL"  float aWeight = occTexture2D (uWeightTexture, TexCoord).r;"
       EOL"  occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
       EOL"}";
-  #if !defined(GL_ES_VERSION_2_0)
-    if (myContext->IsGlGreaterEqual (3, 2))
-    {
-      aProgramSrc->SetHeader ("#version 150");
-    }
-  #else
-    if (myContext->IsGlGreaterEqual (3, 0))
-    {
-      aProgramSrc->SetHeader ("#version 300 es");
-    }
-  #endif
   }
   else
   {
@@ -1566,24 +1552,9 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const St
       EOL"  float aWeight = texelFetch (uWeightTexture, aTexel, gl_SampleID).r;"
       EOL"  occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
       EOL"}";
-  #if !defined(GL_ES_VERSION_2_0)
-    if (myContext->IsGlGreaterEqual (4, 0))
-    {
-      aProgramSrc->SetHeader ("#version 400");
-    }
-  #else
-    if (myContext->IsGlGreaterEqual (3, 2))
-    {
-      aProgramSrc->SetHeader ("#version 320 es");
-    }
-    else if (myContext->IsGlGreaterEqual (3, 0))
-    {
-      aProgramSrc->SetHeader ("#version 300 es"); // with GL_OES_sample_variables extension
-    }
-  #endif
   }
+  defaultOitGlslVersion (aProgramSrc, "weight_oit", theMsaa);
 
-  aProgramSrc->SetId (theMsaa ? "occt_weight-oit-msaa" : "occt_weight-oit");
   aProgramSrc->SetDefaultSampler (false);
   aProgramSrc->SetNbLightsMax (0);
   aProgramSrc->SetNbShadowMaps (0);
@@ -1604,6 +1575,107 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const St
   return Standard_True;
 }
 
+// =======================================================================
+// function : prepareStdProgramOitDepthPeelingBlend
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitDepthPeelingBlend (Standard_Boolean theMsaa)
+{
+  Handle(OpenGl_ShaderProgram)& aProgram = myOitDepthPeelingBlendProgram[theMsaa ? 1 : 0];
+  Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
+  TCollection_AsciiString aSrcVert, aSrcFrag;
+
+  OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
+  aSrcVert =
+    EOL"void main()"
+    EOL"{"
+    EOL"  gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);"
+    EOL"}";
+
+  aUniforms.Append (OpenGl_ShaderObject::ShaderVariable (theMsaa
+                                                       ? "sampler2DMS uDepthPeelingBackColor"
+                                                       :   "sampler2D uDepthPeelingBackColor", Graphic3d_TOS_FRAGMENT));
+  aSrcFrag = TCollection_AsciiString()
+  + EOL"void main()"
+    EOL"{"
+    EOL"  #define THE_SAMPLE_ID " + (theMsaa ? "gl_SampleID" : "0")
+  + EOL"  occFragColor = texelFetch (uDepthPeelingBackColor, ivec2 (gl_FragCoord.xy), THE_SAMPLE_ID);"
+    EOL"  if (occFragColor.a == 0.0) { discard; }"
+    EOL"}";
+
+  defaultOitGlslVersion (aProgramSrc, "oit_peeling_blend", theMsaa);
+  aProgramSrc->SetDefaultSampler (false);
+  aProgramSrc->SetNbLightsMax (0);
+  aProgramSrc->SetNbClipPlanesMax (0);
+  aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX,   aUniforms, aStageInOuts));
+  aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
+  TCollection_AsciiString aKey;
+  if (!Create (aProgramSrc, aKey, aProgram))
+  {
+    aProgram = new OpenGl_ShaderProgram(); // just mark as invalid
+    return false;
+  }
+
+  myContext->BindProgram (aProgram);
+  aProgram->SetSampler (myContext, "uDepthPeelingBackColor", Graphic3d_TextureUnit_0);
+  myContext->BindProgram (Handle(OpenGl_ShaderProgram)());
+  return true;
+}
+
+// =======================================================================
+// function : prepareStdProgramOitDepthPeelingFlush
+// purpose  :
+// =======================================================================
+Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitDepthPeelingFlush (Standard_Boolean theMsaa)
+{
+  Handle(OpenGl_ShaderProgram)& aProgram = myOitDepthPeelingFlushProgram[theMsaa ? 1 : 0];
+  Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
+  TCollection_AsciiString aSrcVert, aSrcFrag;
+
+  OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
+  aSrcVert =
+    EOL"void main()"
+    EOL"{"
+    EOL"  gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);"
+    EOL"}";
+
+  aUniforms.Append (OpenGl_ShaderObject::ShaderVariable (theMsaa
+                                                       ? "sampler2DMS uDepthPeelingFrontColor"
+                                                       :   "sampler2D uDepthPeelingFrontColor", Graphic3d_TOS_FRAGMENT));
+  aUniforms.Append (OpenGl_ShaderObject::ShaderVariable (theMsaa
+                                                       ? "sampler2DMS uDepthPeelingBackColor"
+                                                       :   "sampler2D uDepthPeelingBackColor", Graphic3d_TOS_FRAGMENT));
+  aSrcFrag = TCollection_AsciiString()
+  + EOL"void main()"
+    EOL"{"
+    EOL"  #define THE_SAMPLE_ID " + (theMsaa ? "gl_SampleID" : "0")
+  + EOL"  ivec2 aFragCoord  = ivec2 (gl_FragCoord.xy);"
+    EOL"  vec4  aFrontColor = texelFetch (uDepthPeelingFrontColor, aFragCoord, THE_SAMPLE_ID);"
+    EOL"  vec4  aBackColor  = texelFetch (uDepthPeelingBackColor,  aFragCoord, THE_SAMPLE_ID);"
+    EOL"  float anAlphaMult = 1.0 - aFrontColor.a;"
+    EOL"  occFragColor = vec4 (aFrontColor.rgb + anAlphaMult * aBackColor.rgb, aFrontColor.a + aBackColor.a);"
+    EOL"}";
+
+  defaultOitGlslVersion (aProgramSrc, "oit_peeling_flush", theMsaa);
+  aProgramSrc->SetDefaultSampler (false);
+  aProgramSrc->SetNbLightsMax (0);
+  aProgramSrc->SetNbClipPlanesMax (0);
+  aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX,   aUniforms, aStageInOuts));
+  aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
+  TCollection_AsciiString aKey;
+  if (!Create (aProgramSrc, aKey, aProgram))
+  {
+    aProgram = new OpenGl_ShaderProgram(); // just mark as invalid
+    return false;
+  }
+
+  myContext->BindProgram (aProgram);
+  aProgram->SetSampler (myContext, "uDepthPeelingFrontColor", Graphic3d_TextureUnit_0);
+  aProgram->SetSampler (myContext, "uDepthPeelingBackColor",  Graphic3d_TextureUnit_1);
+  myContext->BindProgram (Handle(OpenGl_ShaderProgram)());
+  return true;
+}
+
 // =======================================================================
 // function : pointSpriteAlphaSrc
 // purpose  :
@@ -1698,6 +1770,7 @@ int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgr
       theProgram->SetHeader ("#version 300 es");
     }
     if ((theBits & OpenGl_PO_WriteOit) != 0
+     || (theBits & OpenGl_PO_OitDepthPeeling) != 0
      || (theBits & OpenGl_PO_StippleLine) != 0)
     {
       if (myContext->IsGlGreaterEqual (3, 0))
@@ -1707,6 +1780,7 @@ int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgr
       else
       {
         aBits = aBits & ~OpenGl_PO_WriteOit;
+        aBits = aBits & ~OpenGl_PO_OitDepthPeeling;
         if (!myContext->oesStdDerivatives)
         {
           aBits = aBits & ~OpenGl_PO_StippleLine;
@@ -1734,6 +1808,49 @@ int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgr
   return aBits;
 }
 
+// =======================================================================
+// function : defaultOitGlslVersion
+// purpose  :
+// =======================================================================
+void OpenGl_ShaderManager::defaultOitGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram,
+                                                  const TCollection_AsciiString& theName,
+                                                  bool theMsaa) const
+{
+  if (theMsaa)
+  {
+  #if !defined(GL_ES_VERSION_2_0)
+    if (myContext->IsGlGreaterEqual (4, 0))
+    {
+      theProgram->SetHeader ("#version 400");
+    }
+  #else
+    if (myContext->IsGlGreaterEqual (3, 2))
+    {
+      theProgram->SetHeader ("#version 320 es");
+    }
+    else if (myContext->IsGlGreaterEqual (3, 0))
+    {
+      theProgram->SetHeader ("#version 300 es"); // with GL_OES_sample_variables extension
+    }
+  #endif
+  }
+  else
+  {
+  #if !defined(GL_ES_VERSION_2_0)
+    if (myContext->IsGlGreaterEqual (3, 2))
+    {
+      theProgram->SetHeader ("#version 150");
+    }
+  #else
+    if (myContext->IsGlGreaterEqual (3, 0))
+    {
+      theProgram->SetHeader ("#version 300 es");
+    }
+  #endif
+  }
+  theProgram->SetId (TCollection_AsciiString ("occt_") + theName + (theMsaa ? "_msaa" : ""));
+}
+
 // =======================================================================
 // function : prepareGeomMainSrc
 // purpose  :
@@ -1968,10 +2085,15 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha
                          : THE_FRAG_CLIP_PLANES_2;
     }
   }
-  if ((theBits & OpenGl_PO_WriteOit) != 0)
+  if ((theBits & OpenGl_PO_OitDepthPeeling) != 0)
+  {
+    aProgramSrc->SetNbFragmentOutputs (3);
+    aProgramSrc->SetOitOutput (Graphic3d_RTM_DEPTH_PEELING_OIT);
+  }
+  else if ((theBits & OpenGl_PO_WriteOit) != 0)
   {
     aProgramSrc->SetNbFragmentOutputs (2);
-    aProgramSrc->SetWeightOitOutput (true);
+    aProgramSrc->SetOitOutput (Graphic3d_RTM_BLEND_OIT);
   }
 
   if (theIsOutline)
@@ -2041,6 +2163,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha
     + aSrcGetAlpha
     + EOL"void main()"
       EOL"{"
+      EOL"  if (occFragEarlyReturn()) { return; }"
     + aSrcFragExtraMain
     + aSrcFragMainGetColor
     + EOL"}";
@@ -2417,10 +2540,15 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
                           : THE_FRAG_CLIP_PLANES_2;
     }
   }
-  if ((theBits & OpenGl_PO_WriteOit) != 0)
+  if ((theBits & OpenGl_PO_OitDepthPeeling) != 0)
+  {
+    aProgramSrc->SetNbFragmentOutputs (3);
+    aProgramSrc->SetOitOutput (Graphic3d_RTM_DEPTH_PEELING_OIT);
+  }
+  else if ((theBits & OpenGl_PO_WriteOit) != 0)
   {
     aProgramSrc->SetNbFragmentOutputs (2);
-    aProgramSrc->SetWeightOitOutput (true);
+    aProgramSrc->SetOitOutput (Graphic3d_RTM_BLEND_OIT);
   }
 
   aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 FrontColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
@@ -2454,6 +2582,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S
     + aSrcFragGetColor
     + EOL"void main()"
       EOL"{"
+      EOL"  if (occFragEarlyReturn()) { return; }"
     + aSrcFragExtraMain
     + EOL"  occSetFragColor (getFinalColor());"
     + EOL"}";
@@ -2620,10 +2749,15 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
                          : THE_FRAG_CLIP_PLANES_2;
     }
   }
-  if ((theBits & OpenGl_PO_WriteOit) != 0)
+  if ((theBits & OpenGl_PO_OitDepthPeeling) != 0)
+  {
+    aProgramSrc->SetNbFragmentOutputs (3);
+    aProgramSrc->SetOitOutput (Graphic3d_RTM_DEPTH_PEELING_OIT);
+  }
+  else if ((theBits & OpenGl_PO_WriteOit) != 0)
   {
     aProgramSrc->SetNbFragmentOutputs (2);
-    aProgramSrc->SetWeightOitOutput (true);
+    aProgramSrc->SetOitOutput (Graphic3d_RTM_BLEND_OIT);
   }
 
   if (isFlatNormal)
@@ -2722,6 +2856,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha
     + EOL
       EOL"void main()"
       EOL"{"
+      EOL"  if (occFragEarlyReturn()) { return; }"
     + aSrcFragExtraMain
     + EOL"  occSetFragColor (getFinalColor());"
     + EOL"}";
index 36558c9c773b94fb8c24c28d2b396f2604c39cd2..7635518ff0ccbc6a369f72f9829edf162355c082 100644 (file)
@@ -220,6 +220,32 @@ public:
     return !aProgram.IsNull() && myContext->BindProgram (aProgram);
   }
 
+  //! Bind program for Depth Peeling order-independent transparency back color blending.
+  Standard_Boolean BindOitDepthPeelingBlendProgram (bool theIsMSAAEnabled)
+  {
+    const Standard_Integer aProgramIdx = theIsMSAAEnabled ? 1 : 0;
+    if (myOitDepthPeelingBlendProgram[aProgramIdx].IsNull())
+    {
+      prepareStdProgramOitDepthPeelingBlend (theIsMSAAEnabled);
+    }
+
+    const Handle(OpenGl_ShaderProgram)& aProgram = myOitDepthPeelingBlendProgram [aProgramIdx];
+    return !aProgram.IsNull() && myContext->BindProgram (aProgram);
+  }
+
+  //! Bind program for Depth Peeling order-independent transparency flush.
+  Standard_Boolean BindOitDepthPeelingFlushProgram (bool theIsMSAAEnabled)
+  {
+    const Standard_Integer aProgramIdx = theIsMSAAEnabled ? 1 : 0;
+    if (myOitDepthPeelingFlushProgram[aProgramIdx].IsNull())
+    {
+      prepareStdProgramOitDepthPeelingFlush (theIsMSAAEnabled);
+    }
+
+    const Handle(OpenGl_ShaderProgram)& aProgram = myOitDepthPeelingFlushProgram [aProgramIdx];
+    return !aProgram.IsNull() && myContext->BindProgram (aProgram);
+  }
+
   //! Bind program for rendering stereoscopic image.
   Standard_Boolean BindStereoProgram (const Graphic3d_StereoMode theStereoMode)
   {
@@ -448,12 +474,26 @@ public:
   //! Returns state of OIT uniforms.
   const OpenGl_OitState& OitState() const { return myOitState; }
 
+  //! Reset the state of OIT rendering pass (only on state change).
+  void ResetOitState()
+  {
+    myOitState.Set (Graphic3d_RTM_BLEND_UNORDERED, 0.0f);
+    myOitState.Update();
+  }
+
   //! Set the state of OIT rendering pass (only on state change).
-  //! @param theToEnableOitWrite [in] flag indicating whether the special output should be written for OIT algorithm.
-  //! @param theDepthFactor [in] the scalar factor of depth influence to the fragment's coverage.
-  void SetOitState (const bool theToEnableOitWrite, const float theDepthFactor)
+  //! @param theMode [in] flag indicating whether the special output should be written for OIT algorithm
+  void SetOitState (Graphic3d_RenderTransparentMethod theMode)
+  {
+    myOitState.Set (theMode, 0.0f);
+    myOitState.Update();
+  }
+
+  //! Set the state of weighed OIT rendering pass (only on state change).
+  //! @param theDepthFactor [in] the scalar factor of depth influence to the fragment's coverage
+  void SetWeighedOitState (float theDepthFactor)
   {
-    myOitState.Set (theToEnableOitWrite, theDepthFactor);
+    myOitState.Set (Graphic3d_RTM_BLEND_OIT, theDepthFactor);
     myOitState.Update();
   }
 
@@ -636,10 +676,14 @@ protected:
       aBits |= OpenGl_PO_VertColor;
     }
 
-    if (myOitState.ToEnableWrite())
+    if (myOitState.ActiveMode() == Graphic3d_RTM_BLEND_OIT)
     {
       aBits |= OpenGl_PO_WriteOit;
     }
+    else if (myOitState.ActiveMode() == Graphic3d_RTM_DEPTH_PEELING_OIT)
+    {
+      aBits |= OpenGl_PO_OitDepthPeeling;
+    }
     return aBits;
   }
 
@@ -686,6 +730,12 @@ protected:
   //! Prepare standard GLSL programs for OIT compositing operation.
   Standard_EXPORT Standard_Boolean prepareStdProgramOitCompositing (const Standard_Boolean theMsaa);
 
+  //! Prepare standard GLSL programs for OIT Depth Peeling blend operation.
+  Standard_EXPORT Standard_Boolean prepareStdProgramOitDepthPeelingBlend (Standard_Boolean theMsaa);
+
+  //! Prepare standard GLSL programs for OIT Depth Peeling flush operation.
+  Standard_EXPORT Standard_Boolean prepareStdProgramOitDepthPeelingFlush (Standard_Boolean theMsaa);
+
   //! Prepare standard GLSL program without lighting.
   Standard_EXPORT Standard_Boolean prepareStdProgramUnlit (Handle(OpenGl_ShaderProgram)& theProgram,
                                                            Standard_Integer theBits,
@@ -753,6 +803,11 @@ protected:
                                                        Standard_Integer theBits,
                                                        bool theUsesDerivates = false) const;
 
+  //! Prepare GLSL version header for OIT composition programs.
+  Standard_EXPORT void defaultOitGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram,
+                                              const TCollection_AsciiString& theName,
+                                              bool theMsaa) const;
+
   //! Prepare GLSL source for geometry shader according to parameters.
   Standard_EXPORT TCollection_AsciiString prepareGeomMainSrc (OpenGl_ShaderObject::ShaderVariableList& theUnifoms,
                                                               OpenGl_ShaderObject::ShaderVariableList& theStageInOuts,
@@ -824,6 +879,8 @@ protected:
                                      myBlitPrograms[2];    //!< standard program for FBO blit emulation
   Handle(OpenGl_ShaderProgram)       myBoundBoxProgram;    //!< standard program for bounding box
   Handle(OpenGl_ShaderProgram)       myOitCompositingProgram[2]; //!< standard program for OIT compositing (default and MSAA).
+  Handle(OpenGl_ShaderProgram)       myOitDepthPeelingBlendProgram[2]; //!< standard program for OIT Depth Peeling blend (default and MSAA)
+  Handle(OpenGl_ShaderProgram)       myOitDepthPeelingFlushProgram[2]; //!< standard program for OIT Depth Peeling flush (default and MSAA)
   OpenGl_MapOfShaderPrograms         myMapOfLightPrograms; //!< map of lighting programs depending on lights configuration
 
   Handle(OpenGl_ShaderProgram)       myPBREnvBakingProgram;//!< program for IBL maps generation used in PBR pipeline
index c7ebf41cdb93901c55064b6dea7d66ab54da682c..040724fb45d394c70303fa55ad56fa02d4e70ebf 100755 (executable)
@@ -176,8 +176,8 @@ OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram
   myNbClipPlanesMax (0),
   myNbFragOutputs (1),
   myTextureSetBits (Graphic3d_TextureSetBits_NONE),
+  myOitOutput (Graphic3d_RTM_BLEND_UNORDERED),
   myHasAlphaTest (false),
-  myHasWeightOitOutput (false),
   myHasTessShader (false)
 {
   memset (myCurrentState, 0, sizeof (myCurrentState));
@@ -206,7 +206,17 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
   myNbFragOutputs = !myProxy.IsNull() ? myProxy->NbFragmentOutputs() : 1;
   myTextureSetBits = Graphic3d_TextureSetBits_NONE;
   myHasAlphaTest  = !myProxy.IsNull() && myProxy->HasAlphaTest();
-  myHasWeightOitOutput = !myProxy.IsNull() ? myProxy->HasWeightOitOutput() && myNbFragOutputs >= 2 : 1;
+  myOitOutput = !myProxy.IsNull() ? myProxy->OitOutput() : Graphic3d_RTM_BLEND_UNORDERED;
+  if (myOitOutput == Graphic3d_RTM_BLEND_OIT
+   && myNbFragOutputs < 2)
+  {
+    myOitOutput = Graphic3d_RTM_BLEND_UNORDERED;
+  }
+  else if (myOitOutput == Graphic3d_RTM_DEPTH_PEELING_OIT
+        && myNbFragOutputs < 3)
+  {
+    myOitOutput = Graphic3d_RTM_BLEND_UNORDERED;
+  }
 
   // detect the minimum GLSL version required for defined Shader Objects
 #if defined(GL_ES_VERSION_2_0)
@@ -334,9 +344,16 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
       if (theCtx->hasDrawBuffers)
       {
         anExtensions += "#define OCC_ENABLE_draw_buffers\n";
-        if (myHasWeightOitOutput)
+        switch (myOitOutput)
         {
-          anExtensions += "#define OCC_WRITE_WEIGHT_OIT_COVERAGE\n";
+          case Graphic3d_RTM_BLEND_UNORDERED:
+            break;
+          case Graphic3d_RTM_BLEND_OIT:
+            anExtensions += "#define OCC_WRITE_WEIGHT_OIT_COVERAGE\n";
+            break;
+          case Graphic3d_RTM_DEPTH_PEELING_OIT:
+            anExtensions += "#define OCC_DEPTH_PEEL_OIT\n";
+            break;
         }
       }
       else
@@ -576,6 +593,15 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)&
     SetUniform (theCtx, aLocSampler, myNbShadowMaps, &aShadowSamplers.front());
   }
 
+  if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occDepthPeelingDepth"))
+  {
+    SetUniform (theCtx, aLocSampler, GLint(theCtx->DepthPeelingDepthTexUnit()));
+  }
+  if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occDepthPeelingFrontColor"))
+  {
+    SetUniform (theCtx, aLocSampler, GLint(theCtx->DepthPeelingFrontColorTexUnit()));
+  }
+
   const TCollection_AsciiString aSamplerNamePrefix ("occSampler");
   const Standard_Integer aNbUnitsMax = Max (theCtx->MaxCombinedTextureUnits(), Graphic3d_TextureUnit_NB);
   for (GLint aUnitIter = 0; aUnitIter < aNbUnitsMax; ++aUnitIter)
index f88eb8a00e06631a1d0254bc37f660c9ba3d3bc0..2d38afd70ad4340d92d1fb42c85c1b8b16e8ec78 100755 (executable)
@@ -301,8 +301,8 @@ public:
   //! Return true if Fragment Shader should perform alpha test; FALSE by default.
   Standard_Boolean HasAlphaTest() const { return myHasAlphaTest; }
 
-  //! Return true if Fragment Shader color should output the weighted OIT coverage; FALSE by default.
-  Standard_Boolean HasWeightOitOutput() const { return myHasWeightOitOutput; }
+  //! Return if Fragment Shader color should output the OIT values; OFF by default.
+  Graphic3d_RenderTransparentMethod OitOutput() const { return myOitOutput; }
 
   //! Return texture units declared within the program, @sa Graphic3d_TextureSetBits.
   Standard_Integer TextureSetBits() const { return myTextureSetBits; }
@@ -678,8 +678,8 @@ protected:
   Standard_Integer                myNbClipPlanesMax; //!< length of array of clipping planes (THE_MAX_CLIP_PLANES)
   Standard_Integer                myNbFragOutputs; //!< length of array of Fragment Shader outputs (THE_NB_FRAG_OUTPUTS)
   Standard_Integer                myTextureSetBits;//!< texture units declared within the program, @sa Graphic3d_TextureSetBits
+  Graphic3d_RenderTransparentMethod myOitOutput;   //!< flag indicating that Fragment Shader includes OIT outputs
   Standard_Boolean                myHasAlphaTest;  //!< flag indicating that Fragment Shader should perform alpha-test
-  Standard_Boolean                myHasWeightOitOutput; //!< flag indicating that Fragment Shader includes weighted OIT coverage
   Standard_Boolean                myHasTessShader; //!< flag indicating that program defines tessellation stage
 
 protected:
index d4fcc96970daa7f6a8e7a210d9e355d308727a18..b7cb484a7dc2c407cb571b17dd594eee6e8ba35e 100755 (executable)
@@ -16,6 +16,7 @@
 #ifndef _OpenGl_State_HeaderFile
 #define _OpenGl_State_HeaderFile
 
+#include <Graphic3d_RenderTransparentMethod.hxx>
 #include <NCollection_List.hxx>
 #include <Graphic3d_LightSet.hxx>
 #include <OpenGl_Element.hxx>
@@ -194,23 +195,23 @@ class OpenGl_OitState : public OpenGl_StateInterface
 public:
 
   //! Creates new uniform state.
-  OpenGl_OitState() : myToEnableWrite (false), myDepthFactor (0.5f) {}
+  OpenGl_OitState() : myOitMode (Graphic3d_RTM_BLEND_UNORDERED), myDepthFactor (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 theDepthFactor [in] scalar factor [0-1] defining influence of depth
   //!  component of a fragment to its final coverage coefficient.
-  void Set (const bool  theToEnableWrite,
+  void Set (Graphic3d_RenderTransparentMethod theMode,
             const float theDepthFactor)
   {
-    myToEnableWrite = theToEnableWrite;
-    myDepthFactor   = static_cast<float> (Max (0.f, Min (1.f, theDepthFactor)));
+    myOitMode = theMode;
+    myDepthFactor = static_cast<float> (Max (0.f, Min (1.f, theDepthFactor)));
   }
 
   //! Returns flag indicating whether writing of output for OIT processing
   //! should be enabled/disabled.
-  bool ToEnableWrite() const { return myToEnableWrite; }
+  Graphic3d_RenderTransparentMethod ActiveMode() const { return myOitMode; }
 
   //! Returns factor defining influence of depth component of a fragment
   //! to its final coverage coefficient.
@@ -218,8 +219,8 @@ public:
 
 private:
 
-  bool  myToEnableWrite; //!< writing color and coverage.
-  float myDepthFactor;   //!< factor of depth influence to coverage.
+  Graphic3d_RenderTransparentMethod myOitMode;     //!< active OIT method for the main GLSL program
+  float                             myDepthFactor; //!< factor of depth influence to coverage
 };
 
 #endif // _OpenGl_State_HeaderFile
index 459c8abcd9b4563a51cecff2055aba5503fcc7f3..a4b2ca42e2c204af5e639f97fb413d332efedb62 100644 (file)
@@ -182,6 +182,9 @@ public:
   //! Return upper mipmap level index (0 means no mipmaps).
   Standard_Integer MaxMipmapLevel() const { return myMaxMipLevel; }
 
+  //! Return number of MSAA samples.
+  Standard_Integer NbSamples() const { return myNbSamples; }
+
   //! Returns estimated GPU memory usage for holding data without considering overheads and allocation alignment rules.
   Standard_EXPORT virtual Standard_Size EstimatedDataSize() const Standard_OVERRIDE;
 
index 19d40028188e56d7362ec6dd07456655645965d4..afbfb07dcf4c03c8a3d02a4dddb10c7d624d07dd 100644 (file)
@@ -327,6 +327,14 @@ OpenGl_TextureFormat OpenGl_TextureFormat::FindSizedFormat (const Handle(OpenGl_
       aFormat.SetDataType (GL_FLOAT);
       return aFormat;
     }
+    case GL_RG32F:
+    {
+      aFormat.SetNbComponents (1);
+      aFormat.SetInternalFormat (theSizedFormat);
+      aFormat.SetPixelFormat (GL_RG);
+      aFormat.SetDataType (GL_FLOAT);
+      return aFormat;
+    }
     case GL_RGBA16F:
     {
       aFormat.SetNbComponents (4);
index 059c663620fb33b4380ad37a4850b395e88811f1..4fcaa1fa3d1d83b025b1504c0f72b6d79d8a51cc 100644 (file)
@@ -25,6 +25,7 @@
 #include <Image_AlienPixMap.hxx>
 #include <OpenGl_ArbFBO.hxx>
 #include <OpenGl_Context.hxx>
+#include <OpenGl_DepthPeeling.hxx>
 #include <OpenGl_FrameBuffer.hxx>
 #include <OpenGl_GlCore11.hxx>
 #include <OpenGl_GraduatedTrihedron.hxx>
@@ -150,6 +151,7 @@ OpenGl_View::OpenGl_View (const Handle(Graphic3d_StructureManager)& theMgr,
   myRaytraceFBO1[1]          = new OpenGl_FrameBuffer();
   myRaytraceFBO2[0]          = new OpenGl_FrameBuffer();
   myRaytraceFBO2[1]          = new OpenGl_FrameBuffer();
+  myDepthPeelingFbos = new OpenGl_DepthPeeling();
   myShadowMaps = new OpenGl_ShadowMapArray();
 }
 
@@ -217,6 +219,7 @@ void OpenGl_View::releaseSrgbResources (const Handle(OpenGl_Context)& theCtx)
   myImmediateSceneFbosOit[0]->Release (theCtx.get());
   myImmediateSceneFbosOit[1]->Release (theCtx.get());
   myXrSceneFbo              ->Release (theCtx.get());
+  myDepthPeelingFbos        ->Release (theCtx.get());
   myOpenGlFBO               ->Release (theCtx.get());
   myOpenGlFBO2              ->Release (theCtx.get());
   myFullScreenQuad           .Release (theCtx.get());
@@ -1017,7 +1020,7 @@ bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj)
     aNbSamples = OpenGl_Context::GetPowerOfTwo (aNbSamples, aCtx->MaxMsaaSamples());
   }
 
-  bool toUseOit = myRenderParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT
+  bool toUseOit = myRenderParams.TransparencyMethod != Graphic3d_RTM_BLEND_UNORDERED
                && checkOitCompatibility (aCtx, aNbSamples > 0);
 
   const bool toInitImmediateFbo = myTransientDrawToFront
@@ -1063,6 +1066,7 @@ bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj)
         }
       }
     }
+
     if (myMainSceneFbos[0]->IsValid() && (toInitImmediateFbo || myImmediateSceneFbos[0]->IsValid()))
     {
       const bool wasFailedImm0 = checkWasFailedFbo (myImmediateSceneFbos[0], myMainSceneFbos[0]);
@@ -1218,7 +1222,44 @@ bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj)
   }
 
   // create color and coverage accumulation buffers required for OIT algorithm
-  if (toUseOit)
+  if (toUseOit
+   && myRenderParams.TransparencyMethod == Graphic3d_RTM_DEPTH_PEELING_OIT)
+  {
+    if (myDepthPeelingFbos->BlendBackFboOit()->GetSizeX() != aRendSizeX
+     || myDepthPeelingFbos->BlendBackFboOit()->GetSizeY() != aRendSizeY)
+    {
+      if (myDepthPeelingFbos->BlendBackFboOit()->Init (aCtx, aRendSizeX, aRendSizeY, GL_RGBA16F, 0))
+      {
+        for (int aPairIter = 0; aPairIter < 2; ++aPairIter)
+        {
+          OpenGl_ColorFormats aColorFormats;
+          aColorFormats.Append (GL_RG32F);
+          aColorFormats.Append (GL_RGBA16F);
+          aColorFormats.Append (GL_RGBA16F);
+          myDepthPeelingFbos->DepthPeelFbosOit()[aPairIter]->Init (aCtx, aRendSizeX, aRendSizeY, aColorFormats, 0);
+
+          NCollection_Sequence<Handle(OpenGl_Texture)> anAttachments;
+          anAttachments.Append (myDepthPeelingFbos->DepthPeelFbosOit()[aPairIter]->ColorTexture (1));
+          anAttachments.Append (myDepthPeelingFbos->DepthPeelFbosOit()[aPairIter]->ColorTexture (2));
+          myDepthPeelingFbos->FrontBackColorFbosOit()[aPairIter]->InitWrapper (aCtx, anAttachments);
+        }
+      }
+      else
+      {
+        toUseOit = false;
+        aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
+                           "Initialization of float texture framebuffer for use with\n"
+                           "  Depth-Peeling order-independent transparency rendering algorithm has failed.");
+      }
+    }
+  }
+  if (!toUseOit)
+  {
+    myDepthPeelingFbos->Release (aCtx.operator->());
+  }
+
+  if (toUseOit
+   && myRenderParams.TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
   {
     Standard_Integer anFboIt = 0;
     for (; anFboIt < 2; ++anFboIt)
@@ -1295,6 +1336,7 @@ bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj)
   }
   if (!toUseOit && myMainSceneFbosOit[0]->IsValid())
   {
+    myDepthPeelingFbos->Release (aCtx.operator->());
     myMainSceneFbosOit     [0]->Release (aCtx.operator->());
     myMainSceneFbosOit     [1]->Release (aCtx.operator->());
     myImmediateSceneFbosOit[0]->Release (aCtx.operator->());
index ea421e54aa3db23f2a1299bdbdfcac9ad814270a..53811ac790c0b6565477c9a726a56af38489629e 100644 (file)
@@ -56,6 +56,7 @@
 struct OpenGl_Matrix;
 
 class Graphic3d_StructureManager;
+class OpenGl_DepthPeeling;
 class OpenGl_GraphicDriver;
 class OpenGl_PBREnvironment;
 class OpenGl_StateCounter;
@@ -206,6 +207,9 @@ public:
                                                   const Standard_Integer theWidth,
                                                   const Standard_Integer theHeight) Standard_OVERRIDE;
 
+  //! Returns additional buffers for depth peeling OIT.
+  const Handle(OpenGl_DepthPeeling)& DepthPeelingFbos() const { return myDepthPeelingFbos; }
+
 public:
 
   //! Returns gradient background fill colors.
@@ -533,7 +537,8 @@ protected: //! @name Rendering properties
   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.
-  Handle(OpenGl_FrameBuffer) myXrSceneFbo;            //!< additional FBO (without MSAA) for submitting to XR
+  Handle(OpenGl_FrameBuffer) myXrSceneFbo;               //!< additional FBO (without MSAA) for submitting to XR
+  Handle(OpenGl_DepthPeeling)   myDepthPeelingFbos;   //!< additional buffers for depth peeling
   Handle(OpenGl_ShadowMapArray) myShadowMaps;         //!< additional FBOs for shadow map rendering
   OpenGl_VertexBuffer        myFullScreenQuad;        //!< Vertices for full-screen quad rendering.
   OpenGl_VertexBuffer        myFullScreenQuadFlip;
index 644fe7b2a90fbeb7084877c6a56c73bcb3f784ca..27418912ca8a0a3694b659e78dabf7c551d3707a 100644 (file)
   #define occFragColor    occFragColor0
   #define occFragCoverage occFragColor1
 
+  #define occPeelDepth      occFragColor0
+  #define occPeelFrontColor occFragColor1
+  #define occPeelBackColor  occFragColor2
+
+  //! Define the main Fragment Shader early return procedure.
+  bool occFragEarlyReturn();
+
   //! Define the main Fragment Shader output - color value.
   void occSetFragColor (in vec4 theColor);
 #endif
index dba698d0f323d52438e2b23133ba260616344f24..791f298c923b2c9e3449f6894b6597fa6d5e8536 100644 (file)
@@ -1,7 +1,41 @@
 
 //! @file DeclarationsImpl.glsl includes implementation of common functions and properties accessors
 #if defined(FRAGMENT_SHADER)
-//! Output color (and coverage for accumulation by OIT algorithm).
+
+#if defined(OCC_DEPTH_PEEL_OIT)
+uniform sampler2D occDepthPeelingDepth;
+uniform sampler2D occDepthPeelingFrontColor;
+int IsFrontPeelLayer = -1;
+bool occFragEarlyReturn()
+{
+  #define THE_DEPTH_CLEAR_VALUE -1e15f
+  ivec2  aFragCoord = ivec2 (gl_FragCoord.xy);
+  vec2   aLastDepth = texelFetch (occDepthPeelingDepth, aFragCoord, 0).rg;
+  occPeelFrontColor = texelFetch (occDepthPeelingFrontColor, aFragCoord, 0);
+  occPeelDepth.rg   = vec2 (THE_DEPTH_CLEAR_VALUE); // depth value always increases, so that MAX blend equation can be used
+  occPeelBackColor  = vec4 (0.0); // back color is blend after each peeling pass
+
+  float aNearDepth = -aLastDepth.x;
+  float aFarDepth  =  aLastDepth.y;
+  float aFragDepth = gl_FragCoord.z; // 0 - 1
+  if (aFragDepth < aNearDepth || aFragDepth > aFarDepth)
+  {
+    return true; // skip peeled depth
+  }
+  else if (aFragDepth > aNearDepth && aFragDepth < aFarDepth)
+  {
+    // to be rendered at next peeling pass
+    occPeelDepth.rg = vec2 (-aFragDepth, aFragDepth);
+    return true;
+  }
+
+  IsFrontPeelLayer = (gl_FragCoord.z == aNearDepth) ? 1 : 0;
+  return false;
+}
+#else
+bool occFragEarlyReturn() { return false; }
+#endif
+
 void occSetFragColor (in vec4 theColor)
 {
 #if defined(OCC_ALPHA_TEST)
@@ -11,6 +45,18 @@ void occSetFragColor (in vec4 theColor)
   float aWeight     = theColor.a * clamp (1e+2 * pow (1.0 - gl_FragCoord.z * occOitDepthFactor, 3.0), 1e-2, 1e+2);
   occFragCoverage.r = theColor.a * aWeight;
   occFragColor      = vec4 (theColor.rgb * theColor.a * aWeight, theColor.a);
+#elif defined(OCC_DEPTH_PEEL_OIT)
+  if (IsFrontPeelLayer == 1) // front is blended directly
+  {
+    vec4 aLastColor = occPeelFrontColor;
+    float anAlphaMult = 1.0 - aLastColor.a;
+    occPeelFrontColor.rgb = aLastColor.rgb + theColor.rgb * theColor.a * anAlphaMult;
+    occPeelFrontColor.a = 1.0 - anAlphaMult * (1.0 - theColor.a);
+  }
+  else if (IsFrontPeelLayer == 0) // back is blended afterwards
+  {
+    occPeelBackColor = theColor;
+  }
 #else
   occFragColor = theColor;
 #endif
index 51a35dc097e350923b184addfb1162d7c06a415e..ebf3a1abc1d835b66ac423ccd232be970d91eb09 100644 (file)
@@ -4,7 +4,41 @@ static const char Shaders_DeclarationsImpl_glsl[] =
   "\n"
   "//! @file DeclarationsImpl.glsl includes implementation of common functions and properties accessors\n"
   "#if defined(FRAGMENT_SHADER)\n"
-  "//! Output color (and coverage for accumulation by OIT algorithm).\n"
+  "\n"
+  "#if defined(OCC_DEPTH_PEEL_OIT)\n"
+  "uniform sampler2D occDepthPeelingDepth;\n"
+  "uniform sampler2D occDepthPeelingFrontColor;\n"
+  "int IsFrontPeelLayer = -1;\n"
+  "bool occFragEarlyReturn()\n"
+  "{\n"
+  "  #define THE_DEPTH_CLEAR_VALUE -1e15f\n"
+  "  ivec2  aFragCoord = ivec2 (gl_FragCoord.xy);\n"
+  "  vec2   aLastDepth = texelFetch (occDepthPeelingDepth, aFragCoord, 0).rg;\n"
+  "  occPeelFrontColor = texelFetch (occDepthPeelingFrontColor, aFragCoord, 0);\n"
+  "  occPeelDepth.rg   = vec2 (THE_DEPTH_CLEAR_VALUE); // depth value always increases, so that MAX blend equation can be used\n"
+  "  occPeelBackColor  = vec4 (0.0); // back color is blend after each peeling pass\n"
+  "\n"
+  "  float aNearDepth = -aLastDepth.x;\n"
+  "  float aFarDepth  =  aLastDepth.y;\n"
+  "  float aFragDepth = gl_FragCoord.z; // 0 - 1\n"
+  "  if (aFragDepth < aNearDepth || aFragDepth > aFarDepth)\n"
+  "  {\n"
+  "    return true; // skip peeled depth\n"
+  "  }\n"
+  "  else if (aFragDepth > aNearDepth && aFragDepth < aFarDepth)\n"
+  "  {\n"
+  "    // to be rendered at next peeling pass\n"
+  "    occPeelDepth.rg = vec2 (-aFragDepth, aFragDepth);\n"
+  "    return true;\n"
+  "  }\n"
+  "\n"
+  "  IsFrontPeelLayer = (gl_FragCoord.z == aNearDepth) ? 1 : 0;\n"
+  "  return false;\n"
+  "}\n"
+  "#else\n"
+  "bool occFragEarlyReturn() { return false; }\n"
+  "#endif\n"
+  "\n"
   "void occSetFragColor (in vec4 theColor)\n"
   "{\n"
   "#if defined(OCC_ALPHA_TEST)\n"
@@ -14,6 +48,18 @@ static const char Shaders_DeclarationsImpl_glsl[] =
   "  float aWeight     = theColor.a * clamp (1e+2 * pow (1.0 - gl_FragCoord.z * occOitDepthFactor, 3.0), 1e-2, 1e+2);\n"
   "  occFragCoverage.r = theColor.a * aWeight;\n"
   "  occFragColor      = vec4 (theColor.rgb * theColor.a * aWeight, theColor.a);\n"
+  "#elif defined(OCC_DEPTH_PEEL_OIT)\n"
+  "  if (IsFrontPeelLayer == 1) // front is blended directly\n"
+  "  {\n"
+  "    vec4 aLastColor = occPeelFrontColor;\n"
+  "    float anAlphaMult = 1.0 - aLastColor.a;\n"
+  "    occPeelFrontColor.rgb = aLastColor.rgb + theColor.rgb * theColor.a * anAlphaMult;\n"
+  "    occPeelFrontColor.a = 1.0 - anAlphaMult * (1.0 - theColor.a);\n"
+  "  }\n"
+  "  else if (IsFrontPeelLayer == 0) // back is blended afterwards\n"
+  "  {\n"
+  "    occPeelBackColor = theColor;\n"
+  "  }\n"
   "#else\n"
   "  occFragColor = theColor;\n"
   "#endif\n"
index b64b83d0453f2263500e7d59a0a1b33f67242d36..c33fdf60c09c22518ab0c0a814b36f5b9f111ad3 100644 (file)
@@ -92,6 +92,13 @@ static const char Shaders_Declarations_glsl[] =
   "  #define occFragColor    occFragColor0\n"
   "  #define occFragCoverage occFragColor1\n"
   "\n"
+  "  #define occPeelDepth      occFragColor0\n"
+  "  #define occPeelFrontColor occFragColor1\n"
+  "  #define occPeelBackColor  occFragColor2\n"
+  "\n"
+  "  //! Define the main Fragment Shader early return procedure.\n"
+  "  bool occFragEarlyReturn();\n"
+  "\n"
   "  //! Define the main Fragment Shader output - color value.\n"
   "  void occSetFragColor (in vec4 theColor);\n"
   "#endif\n"
index 66c8dfbd24fd9f8962cf06ae2a4292ded055d84c..2d51ec7b16ffc1cbfe7ba173be30e541b651e7aa 100644 (file)
@@ -828,7 +828,7 @@ static Standard_Integer VShaderProg (Draw_Interpretor& theDI,
     && ViewerTest::CurrentView()->RenderingParams().TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
   {
     aProgram->SetNbFragmentOutputs (2);
-    aProgram->SetWeightOitOutput (true);
+    aProgram->SetOitOutput (Graphic3d_RTM_BLEND_OIT);
   }
 
   ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName aGlobalPrsIter (GetMapOfAIS());
index 52a772266e9fef88d8fc2020988ee992e0d23328..907a9afe5d5a366f06c4eb78d0521fcccd32b0e6 100644 (file)
@@ -11556,6 +11556,8 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
       case Graphic3d_RTM_BLEND_UNORDERED: theDI << "Basic blended transparency with non-commuting operator "; break;
       case Graphic3d_RTM_BLEND_OIT:       theDI << "Weighted Blended Order-Independent Transparency, depth weight factor: "
                                                 << TCollection_AsciiString (aParams.OitDepthFactor); break;
+      case Graphic3d_RTM_DEPTH_PEELING_OIT: theDI << "Depth Peeling Order-Independent Transparency, Nb.Layers: "
+                                                << TCollection_AsciiString (aParams.NbOitDepthPeelingLayers); break;
     }
     theDI << "\n";
     theDI << "msaa:           " <<  aParams.NbMsaaSamples                               << "\n";
@@ -11801,6 +11803,10 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
         {
           theDI << "on, depth weight factor: " << TCollection_AsciiString (aParams.OitDepthFactor) << " ";
         }
+        else if (aParams.TransparencyMethod == Graphic3d_RTM_DEPTH_PEELING_OIT)
+        {
+          theDI << "on, depth peeling layers: " << TCollection_AsciiString (aParams.NbOitDepthPeelingLayers) << " ";
+        }
         else
         {
           theDI << "off" << " ";
@@ -11815,7 +11821,41 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI,
 
       TCollection_AsciiString aParam = theArgVec[anArgIter];
       aParam.LowerCase();
-      if (aParam.IsRealValue (Standard_True))
+      if (aParam == "peeling"
+       || aParam == "peel")
+      {
+        aParams.TransparencyMethod = Graphic3d_RTM_DEPTH_PEELING_OIT;
+        if (anArgIter + 1 < theArgNb
+         && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsIntegerValue())
+        {
+          ++anArgIter;
+          const Standard_Integer aNbLayers = TCollection_AsciiString (theArgVec[anArgIter]).IntegerValue();
+          if (aNbLayers < 2)
+          {
+            Message::SendFail() << "Syntax error: invalid layers number specified for Depth Peeling OIT " << aNbLayers;
+            return 1;
+          }
+          aParams.NbOitDepthPeelingLayers = TCollection_AsciiString (theArgVec[anArgIter]).IntegerValue();
+        }
+      }
+      else if (aParam == "weighted"
+            || aParam == "weight")
+      {
+        aParams.TransparencyMethod = Graphic3d_RTM_BLEND_OIT;
+        if (anArgIter + 1 < theArgNb
+         && TCollection_AsciiString (theArgVec[anArgIter + 1]).IsRealValue())
+        {
+          ++anArgIter;
+          const Standard_ShortReal aWeight = (Standard_ShortReal)TCollection_AsciiString (theArgVec[anArgIter]).RealValue();
+          if (aWeight < 0.f || aWeight > 1.f)
+          {
+            Message::SendFail() << "Syntax error: invalid value of Weighted Order-Independent Transparency depth weight factor " << aWeight << ". Should be within range [0.0; 1.0]";
+            return 1;
+          }
+          aParams.OitDepthFactor = aWeight;
+        }
+      }
+      else if (aParam.IsRealValue())
       {
         const Standard_ShortReal aWeight = (Standard_ShortReal) Draw::Atof (theArgVec[anArgIter]);
         if (aWeight < 0.f || aWeight > 1.f)
diff --git a/tests/v3d/transparency/oit b/tests/v3d/transparency/oit
new file mode 100644 (file)
index 0000000..2d5e23c
--- /dev/null
@@ -0,0 +1,55 @@
+puts "========"
+puts "0031571: Visualization, TKOpenGl - provide depth peeling OIT option"
+puts "========"
+
+pload MODELING VISUALIZATION
+if { $::tcl_platform(os) == "Darwin" } { vcaps -core }
+set hasVtk 1
+if { [catch { pload VIS }] } { set hasVtk 0 }
+
+# create objects
+pcylinder c 0.5 1
+box b1 -1 -1 -0.5 1 1 1
+box b2  0 0 -0.5 1 1 1
+box b3 -1  0 -0.5 1 1 1
+
+vclear
+vinit View1
+vdisplay -dispMode 1 c b1 b2 b3
+vaspects c  -color yellow -transparency 0.4
+vaspects b1 -color blue   -transparency 0.8
+vaspects b2 -color green  -transparency 0.0
+vaspects b3 -color red    -transparency 0.5
+vfit
+vaxo
+vzoom 0.9
+
+vraytrace 1
+vrenderparams -rayDepth 10
+vdump $imagedir/${casename}_raytrace.png
+
+vraytrace 0
+vrenderparams -oit off
+vdump $imagedir/${casename}_nooit.png
+vrenderparams -oit weight 0.0
+vdump $imagedir/${casename}_weight.png
+vrenderparams -oit peeling 4
+vdump $imagedir/${casename}_peel.png
+
+# vtk viewer
+if { $hasVtk == 1 } {
+  ivtkinit -msaa 0 -srgb 0
+  ivtkdisplay c b1 b2 b3
+  ivtkaxo
+  ivtksetdispmode 1
+  ivtksetcolor c yellow
+  ivtksetcolor b1 blue
+  ivtksetcolor b2 green
+  ivtksetcolor b3 red
+  ivtksettransparency c  0.4
+  ivtksettransparency b1 0.8
+  ivtksettransparency b2 0.0
+  ivtksettransparency b3 0.5
+  ivtkrenderparams -depthPeeling 4
+  ivtkdump $imagedir/${casename}_vtk.png
+}