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
//! 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
PbrEnvBakingProbability (0.99f),
//
OitDepthFactor (0.0f),
+ NbOitDepthPeelingLayers (4),
NbMsaaSamples (0),
RenderResolutionScale (1.0f),
ShadowMapResolution (1024),
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)
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_")
#ifndef _Graphic3d_ShaderProgram_HeaderFile
#define _Graphic3d_ShaderProgram_HeaderFile
+#include <Graphic3d_RenderTransparentMethod.hxx>
#include <Graphic3d_ShaderAttribute.hxx>
#include <Graphic3d_ShaderObject.hxx>
#include <Graphic3d_ShaderVariable.hxx>
//! 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.
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
};
//! 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,
//! 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.
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
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),
|| (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);
}
// =======================================================================
//! 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
{
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
--- /dev/null
+// 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);
+ }
+ }
+}
--- /dev/null
+// 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
myGlFBufferId (NO_FRAMEBUFFER),
myGlColorRBufferId (NO_RENDERBUFFER),
myGlDepthRBufferId (NO_RENDERBUFFER),
- myIsOwnBuffer (false),
+ myIsOwnBuffer (false),
+ myIsOwnColor (false),
myIsOwnDepth (false),
myDepthStencilTexture (new OpenGl_Texture())
{
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 :
const GLsizei theNbSamples)
{
OpenGl_ColorFormats aColorFormats;
-
- aColorFormats.Append (theColorFormat);
-
+ if (theColorFormat != 0)
+ {
+ aColorFormats.Append (theColorFormat);
+ }
return Init (theGlContext, theSizeX, theSizeY, aColorFormats, theDepthFormat, theNbSamples);
}
}
myDepthStencilTexture = theDepthStencilTexture;
+ myIsOwnColor = true;
myIsOwnDepth = false;
myIsOwnBuffer = true;
{
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());
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;
return Standard_False;
}
+ myIsOwnColor = true;
myIsOwnBuffer = true;
myIsOwnDepth = true;
{
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;
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;
// clean up previous state
Release (theGlCtx.operator->());
+ myIsOwnColor = true;
myIsOwnBuffer = true;
myIsOwnDepth = true;
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)
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)
//! 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);
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
#include <OpenGl_GlCore20.hxx>
#include <OpenGl_View.hxx>
+#include <OpenGl_DepthPeeling.hxx>
#include <OpenGl_ShadowMap.hxx>
#include <OpenGl_Workspace.hxx>
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
#include <OpenGl_GlCore15.hxx>
#include <BVH_LinearBuilder.hxx>
+#include <OpenGl_DepthPeeling.hxx>
#include <OpenGl_FrameBuffer.hxx>
#include <OpenGl_LayerList.hxx>
#include <OpenGl_ShaderManager.hxx>
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
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.
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;
}
}
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,
// =======================================================================
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());
}
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
{
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);
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 :
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))
else
{
aBits = aBits & ~OpenGl_PO_WriteOit;
+ aBits = aBits & ~OpenGl_PO_OitDepthPeeling;
if (!myContext->oesStdDerivatives)
{
aBits = aBits & ~OpenGl_PO_StippleLine;
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 :
: 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)
+ aSrcGetAlpha
+ EOL"void main()"
EOL"{"
+ EOL" if (occFragEarlyReturn()) { return; }"
+ aSrcFragExtraMain
+ aSrcFragMainGetColor
+ EOL"}";
: 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));
+ aSrcFragGetColor
+ EOL"void main()"
EOL"{"
+ EOL" if (occFragEarlyReturn()) { return; }"
+ aSrcFragExtraMain
+ EOL" occSetFragColor (getFinalColor());"
+ EOL"}";
: 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)
+ EOL
EOL"void main()"
EOL"{"
+ EOL" if (occFragEarlyReturn()) { return; }"
+ aSrcFragExtraMain
+ EOL" occSetFragColor (getFinalColor());"
+ EOL"}";
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)
{
//! 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();
}
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;
}
//! 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,
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,
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
myNbClipPlanesMax (0),
myNbFragOutputs (1),
myTextureSetBits (Graphic3d_TextureSetBits_NONE),
+ myOitOutput (Graphic3d_RTM_BLEND_UNORDERED),
myHasAlphaTest (false),
- myHasWeightOitOutput (false),
myHasTessShader (false)
{
memset (myCurrentState, 0, sizeof (myCurrentState));
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)
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
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)
//! 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; }
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:
#ifndef _OpenGl_State_HeaderFile
#define _OpenGl_State_HeaderFile
+#include <Graphic3d_RenderTransparentMethod.hxx>
#include <NCollection_List.hxx>
#include <Graphic3d_LightSet.hxx>
#include <OpenGl_Element.hxx>
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.
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
//! 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;
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);
#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>
myRaytraceFBO1[1] = new OpenGl_FrameBuffer();
myRaytraceFBO2[0] = new OpenGl_FrameBuffer();
myRaytraceFBO2[1] = new OpenGl_FrameBuffer();
+ myDepthPeelingFbos = new OpenGl_DepthPeeling();
myShadowMaps = new OpenGl_ShadowMapArray();
}
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());
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
}
}
}
+
if (myMainSceneFbos[0]->IsValid() && (toInitImmediateFbo || myImmediateSceneFbos[0]->IsValid()))
{
const bool wasFailedImm0 = checkWasFailedFbo (myImmediateSceneFbos[0], myMainSceneFbos[0]);
}
// 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)
}
if (!toUseOit && myMainSceneFbosOit[0]->IsValid())
{
+ myDepthPeelingFbos->Release (aCtx.operator->());
myMainSceneFbosOit [0]->Release (aCtx.operator->());
myMainSceneFbosOit [1]->Release (aCtx.operator->());
myImmediateSceneFbosOit[0]->Release (aCtx.operator->());
struct OpenGl_Matrix;
class Graphic3d_StructureManager;
+class OpenGl_DepthPeeling;
class OpenGl_GraphicDriver;
class OpenGl_PBREnvironment;
class OpenGl_StateCounter;
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.
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;
#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
//! @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)
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
"\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"
" 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"
" #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"
&& ViewerTest::CurrentView()->RenderingParams().TransparencyMethod == Graphic3d_RTM_BLEND_OIT)
{
aProgram->SetNbFragmentOutputs (2);
- aProgram->SetWeightOitOutput (true);
+ aProgram->SetOitOutput (Graphic3d_RTM_BLEND_OIT);
}
ViewerTest_DoubleMapIteratorOfDoubleMapOfInteractiveAndName aGlobalPrsIter (GetMapOfAIS());
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";
{
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" << " ";
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)
--- /dev/null
+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
+}