1
0
mirror of https://git.dev.opencascade.org/repos/occt.git synced 2025-04-16 10:08:36 +03:00

0032648: Visualization, TKOpenGles - support MSAA anti-aliasing within WebGL 2.0

OpenGl_FrameBuffer::Init() now creates MSAA render buffer in case if MSAA textures are unsupported.
In this case OpenGl_View::prepareFrameBuffers() creates MSAA render buffer for main content
and non-MSAA FBO for immediate content as blitting of MSAA render buffers into MSAA targets is unsupported by OpenGL ES 3.0.

env.bat.in has been corrected to include path to custom ANGLE (GLES2_DIR)
in front of Qt which might include its own older ANGLE build.
This commit is contained in:
kgv 2021-11-02 16:23:25 +03:00 committed by inv
parent 45143b7a24
commit c8365a1c28
8 changed files with 268 additions and 69 deletions

View File

@ -131,6 +131,10 @@ if exist "%CASROOT%\custom.bat" (
call "%CASROOT%\custom.bat" %VCVER% %ARCH% %CASDEB% call "%CASROOT%\custom.bat" %VCVER% %ARCH% %CASDEB%
) )
if not ["%QTDIR%"] == [""] (
set "PATH=%QTDIR%/bin;%PATH%"
set "QT_PLUGIN_PATH=%QTDIR%/plugins"
)
if not ["%TCL_DIR%"] == [""] set "PATH=%TCL_DIR%;%PATH%" if not ["%TCL_DIR%"] == [""] set "PATH=%TCL_DIR%;%PATH%"
if not ["%TK_DIR%"] == [""] set "PATH=%TK_DIR%;%PATH%" if not ["%TK_DIR%"] == [""] set "PATH=%TK_DIR%;%PATH%"
if not ["%FREETYPE_DIR%"] == [""] set "PATH=%FREETYPE_DIR%;%PATH%" if not ["%FREETYPE_DIR%"] == [""] set "PATH=%FREETYPE_DIR%;%PATH%"
@ -141,10 +145,6 @@ if not ["%TBB_DIR%"] == [""] set "PATH=%TBB_DIR%;%PATH%"
if not ["%VTK_DIR%"] == [""] set "PATH=%VTK_DIR%;%PATH%" if not ["%VTK_DIR%"] == [""] set "PATH=%VTK_DIR%;%PATH%"
if not ["%FFMPEG_DIR%"] == [""] set "PATH=%FFMPEG_DIR%;%PATH%" if not ["%FFMPEG_DIR%"] == [""] set "PATH=%FFMPEG_DIR%;%PATH%"
if not ["%OPENVR_DIR%"] == [""] set "PATH=%OPENVR_DIR%;%PATH%" if not ["%OPENVR_DIR%"] == [""] set "PATH=%OPENVR_DIR%;%PATH%"
if not ["%QTDIR%"] == [""] (
set "PATH=%QTDIR%/bin;%PATH%"
set "QT_PLUGIN_PATH=%QTDIR%/plugins"
)
rem ----- Set path to 3rd party and OCCT libraries ----- rem ----- Set path to 3rd party and OCCT libraries -----
if not "%CSF_OCCTBinPath%" == "" ( if not "%CSF_OCCTBinPath%" == "" (

View File

@ -184,6 +184,13 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
myClippingState (), myClippingState (),
myGlLibHandle (NULL), myGlLibHandle (NULL),
myFuncs (new OpenGl_GlFunctions()), myFuncs (new OpenGl_GlFunctions()),
myGapi (
#if defined(GL_ES_VERSION_2_0)
Aspect_GraphicsLibrary_OpenGLES
#else
Aspect_GraphicsLibrary_OpenGL
#endif
),
mySupportedFormats (new Image_SupportedFormats()), mySupportedFormats (new Image_SupportedFormats()),
myAnisoMax (1), myAnisoMax (1),
myTexClamp (GL_CLAMP_TO_EDGE), myTexClamp (GL_CLAMP_TO_EDGE),
@ -200,6 +207,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps)
myGlVerMinor (0), myGlVerMinor (0),
myIsInitialized (Standard_False), myIsInitialized (Standard_False),
myIsStereoBuffers (Standard_False), myIsStereoBuffers (Standard_False),
myHasMsaaTextures (Standard_False),
myIsGlNormalizeEnabled (Standard_False), myIsGlNormalizeEnabled (Standard_False),
mySpriteTexUnit (Graphic3d_TextureUnit_PointSprite), mySpriteTexUnit (Graphic3d_TextureUnit_PointSprite),
myHasRayTracing (Standard_False), myHasRayTracing (Standard_False),
@ -1386,6 +1394,7 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
// read version // read version
myGlVerMajor = 0; myGlVerMajor = 0;
myGlVerMinor = 0; myGlVerMinor = 0;
myHasMsaaTextures = false;
myMaxMsaaSamples = 0; myMaxMsaaSamples = 0;
myMaxDrawBuffers = 1; myMaxDrawBuffers = 1;
myMaxColorAttachments = 1; myMaxColorAttachments = 1;
@ -1573,25 +1582,26 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
myClippingState.Init(); myClippingState.Init();
#if defined(GL_ES_VERSION_2_0) #if defined(GL_ES_VERSION_2_0)
if (IsGlGreaterEqual (3, 1) if (IsGlGreaterEqual (3, 0))
&& myFuncs->glTexStorage2DMultisample != NULL)
{ {
// MSAA RenderBuffers have been defined in OpenGL ES 3.0, // MSAA RenderBuffers have been defined in OpenGL ES 3.0, but MSAA Textures - only in OpenGL ES 3.1+
// but MSAA Textures - only in OpenGL ES 3.1+ myHasMsaaTextures = IsGlGreaterEqual (3, 1)
&& myFuncs->glTexStorage2DMultisample != NULL;
::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples); ::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples);
} }
#else #else
if (core30 != NULL) if (core30 != NULL)
{ {
// MSAA RenderBuffers have been defined in OpenGL 3.0, // MSAA RenderBuffers have been defined in OpenGL 3.0, but MSAA Textures - only in OpenGL 3.2+
// but MSAA Textures - only in OpenGL 3.2+
if (core32 != NULL) if (core32 != NULL)
{ {
myHasMsaaTextures = true;
::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples); ::glGetIntegerv (GL_MAX_SAMPLES, &myMaxMsaaSamples);
} }
else if (CheckExtension ("GL_ARB_texture_multisample") else if (CheckExtension ("GL_ARB_texture_multisample")
&& myFuncs->glTexImage2DMultisample != NULL) && myFuncs->glTexImage2DMultisample != NULL)
{ {
myHasMsaaTextures = true;
GLint aNbColorSamples = 0, aNbDepthSamples = 0; GLint aNbColorSamples = 0, aNbDepthSamples = 0;
::glGetIntegerv (GL_MAX_COLOR_TEXTURE_SAMPLES, &aNbColorSamples); ::glGetIntegerv (GL_MAX_COLOR_TEXTURE_SAMPLES, &aNbColorSamples);
::glGetIntegerv (GL_MAX_DEPTH_TEXTURE_SAMPLES, &aNbDepthSamples); ::glGetIntegerv (GL_MAX_DEPTH_TEXTURE_SAMPLES, &aNbDepthSamples);
@ -1599,6 +1609,10 @@ void OpenGl_Context::init (const Standard_Boolean theIsCoreProfile)
} }
} }
#endif #endif
if (myMaxMsaaSamples <= 1)
{
myHasMsaaTextures = false;
}
#if !defined(GL_ES_VERSION_2_0) #if !defined(GL_ES_VERSION_2_0)
if (core32 != NULL && isCoreProfile) if (core32 != NULL && isCoreProfile)
@ -2370,6 +2384,32 @@ Handle(OpenGl_FrameBuffer) OpenGl_Context::SetDefaultFrameBuffer (const Handle(O
return aFbo; return aFbo;
} }
// =======================================================================
// function : IsRender
// purpose :
// =======================================================================
Standard_Boolean OpenGl_Context::IsRender() const
{
#if !defined(GL_ES_VERSION_2_0)
return myRenderMode == GL_RENDER;
#else
return Standard_True;
#endif
}
// =======================================================================
// function : IsFeedback
// purpose :
// =======================================================================
Standard_Boolean OpenGl_Context::IsFeedback() const
{
#if !defined(GL_ES_VERSION_2_0)
return myRenderMode == GL_FEEDBACK;
#else
return Standard_False;
#endif
}
// ======================================================================= // =======================================================================
// function : SetShadingMaterial // function : SetShadingMaterial
// purpose : // purpose :

View File

@ -20,6 +20,7 @@
#include <Aspect_HatchStyle.hxx> #include <Aspect_HatchStyle.hxx>
#include <Aspect_Drawable.hxx> #include <Aspect_Drawable.hxx>
#include <Aspect_Display.hxx> #include <Aspect_Display.hxx>
#include <Aspect_GraphicsLibrary.hxx>
#include <Aspect_RenderingContext.hxx> #include <Aspect_RenderingContext.hxx>
#include <Aspect_TypeOfLine.hxx> #include <Aspect_TypeOfLine.hxx>
#include <NCollection_DataMap.hxx> #include <NCollection_DataMap.hxx>
@ -330,6 +331,9 @@ public:
return (theFuncPtr != NULL); return (theFuncPtr != NULL);
} }
//! Return active graphics library.
Aspect_GraphicsLibrary GraphicsLibrary() const { return myGapi; }
//! @return true if detected GL version is greater or equal to requested one. //! @return true if detected GL version is greater or equal to requested one.
inline Standard_Boolean IsGlGreaterEqual (const Standard_Integer theVerMajor, inline Standard_Boolean IsGlGreaterEqual (const Standard_Integer theVerMajor,
const Standard_Integer theVerMinor) const const Standard_Integer theVerMinor) const
@ -367,24 +371,10 @@ public:
Standard_EXPORT Standard_Boolean SetSwapInterval (const Standard_Integer theInterval); Standard_EXPORT Standard_Boolean SetSwapInterval (const Standard_Integer theInterval);
//! Return true if active mode is GL_RENDER (cached state) //! Return true if active mode is GL_RENDER (cached state)
Standard_Boolean IsRender() const Standard_EXPORT Standard_Boolean IsRender() const;
{
#if !defined(GL_ES_VERSION_2_0)
return myRenderMode == GL_RENDER;
#else
return Standard_True;
#endif
}
//! Return true if active mode is GL_FEEDBACK (cached state) //! Return true if active mode is GL_FEEDBACK (cached state)
Standard_Boolean IsFeedback() const Standard_EXPORT Standard_Boolean IsFeedback() const;
{
#if !defined(GL_ES_VERSION_2_0)
return myRenderMode == GL_FEEDBACK;
#else
return Standard_False;
#endif
}
//! This function retrieves information from GL about free GPU memory that is: //! This function retrieves information from GL about free GPU memory that is:
//! - OS-dependent. On some OS it is per-process and on others - for entire system. //! - OS-dependent. On some OS it is per-process and on others - for entire system.
@ -480,11 +470,9 @@ public:
//! @return true if texture parameters GL_TEXTURE_BASE_LEVEL/GL_TEXTURE_MAX_LEVEL are supported. //! @return true if texture parameters GL_TEXTURE_BASE_LEVEL/GL_TEXTURE_MAX_LEVEL are supported.
Standard_Boolean HasTextureBaseLevel() const Standard_Boolean HasTextureBaseLevel() const
{ {
#if !defined(GL_ES_VERSION_2_0) return myGapi == Aspect_GraphicsLibrary_OpenGLES
return IsGlGreaterEqual (1, 2); ? IsGlGreaterEqual (3, 0)
#else : IsGlGreaterEqual (1, 2);
return IsGlGreaterEqual (3, 0);
#endif
} }
//! Return map of supported texture formats. //! Return map of supported texture formats.
@ -507,6 +495,9 @@ public:
//! Return texture unit to be used for sprites (Graphic3d_TextureUnit_PointSprite by default). //! Return texture unit to be used for sprites (Graphic3d_TextureUnit_PointSprite by default).
Graphic3d_TextureUnit SpriteTextureUnit() const { return mySpriteTexUnit; } Graphic3d_TextureUnit SpriteTextureUnit() const { return mySpriteTexUnit; }
//! @return true if MSAA textures are supported.
Standard_Boolean HasTextureMultisampling() const { return myHasMsaaTextures; }
//! @return value for GL_MAX_SAMPLES //! @return value for GL_MAX_SAMPLES
Standard_Integer MaxMsaaSamples() const { return myMaxMsaaSamples; } Standard_Integer MaxMsaaSamples() const { return myMaxMsaaSamples; }
@ -721,16 +712,8 @@ public:
Standard_EXPORT Standard_Boolean IncludeMessage (const unsigned int theSource, Standard_EXPORT Standard_Boolean IncludeMessage (const unsigned int theSource,
const unsigned int theId); const unsigned int theId);
//! @return true if OpenGl context supports left and //! @return true if OpenGl context supports left and right rendering buffers.
//! right rendering buffers. Standard_Boolean HasStereoBuffers() const { return myIsStereoBuffers; }
Standard_Boolean HasStereoBuffers() const
{
#if !defined(GL_ES_VERSION_2_0)
return myIsStereoBuffers;
#else
return Standard_False;
#endif
}
public: //! @name methods to alter or retrieve current state public: //! @name methods to alter or retrieve current state
@ -1110,6 +1093,7 @@ private: // context info
void* myGlLibHandle; //!< optional handle to GL library void* myGlLibHandle; //!< optional handle to GL library
NCollection_Handle<OpenGl_GlFunctions> NCollection_Handle<OpenGl_GlFunctions>
myFuncs; //!< mega structure for all GL functions myFuncs; //!< mega structure for all GL functions
Aspect_GraphicsLibrary myGapi; //!< GAPI name
Handle(Image_SupportedFormats) Handle(Image_SupportedFormats)
mySupportedFormats; //!< map of supported texture formats mySupportedFormats; //!< map of supported texture formats
Standard_Integer myAnisoMax; //!< maximum level of anisotropy texture filter Standard_Integer myAnisoMax; //!< maximum level of anisotropy texture filter
@ -1127,6 +1111,7 @@ private: // context info
Standard_Integer myGlVerMinor; //!< cached GL version minor number Standard_Integer myGlVerMinor; //!< cached GL version minor number
Standard_Boolean myIsInitialized; //!< flag indicates initialization state Standard_Boolean myIsInitialized; //!< flag indicates initialization state
Standard_Boolean myIsStereoBuffers; //!< context supports stereo buffering Standard_Boolean myIsStereoBuffers; //!< context supports stereo buffering
Standard_Boolean myHasMsaaTextures; //!< context supports MSAA textures
Standard_Boolean myIsGlNormalizeEnabled; //!< GL_NORMALIZE flag Standard_Boolean myIsGlNormalizeEnabled; //!< GL_NORMALIZE flag
//!< Used to tell OpenGl that normals should be normalized //!< Used to tell OpenGl that normals should be normalized
Graphic3d_TextureUnit mySpriteTexUnit; //!< sampler2D occSamplerPointSprite, texture unit for point sprite texture Graphic3d_TextureUnit mySpriteTexUnit; //!< sampler2D occSamplerPointSprite, texture unit for point sprite texture

View File

@ -19,6 +19,7 @@
#include <OpenGl_Texture.hxx> #include <OpenGl_Texture.hxx>
#include <Standard_Assert.hxx> #include <Standard_Assert.hxx>
#include <Standard_NotImplemented.hxx>
#include <TCollection_ExtendedString.hxx> #include <TCollection_ExtendedString.hxx>
IMPLEMENT_STANDARD_RTTIEXT(OpenGl_FrameBuffer,OpenGl_Resource) IMPLEMENT_STANDARD_RTTIEXT(OpenGl_FrameBuffer,OpenGl_Resource)
@ -363,6 +364,13 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo
return Standard_False; return Standard_False;
} }
if (theNbSamples != 0
&& !theGlContext->HasTextureMultisampling()
&& theGlContext->MaxMsaaSamples() > 1)
{
return InitRenderBuffer (theGlContext, theSize, theColorFormats, theDepthFormat, theNbSamples);
}
myIsOwnColor = true; myIsOwnColor = true;
myIsOwnBuffer = true; myIsOwnBuffer = true;
myIsOwnDepth = true; myIsOwnDepth = true;
@ -429,6 +437,16 @@ Standard_Boolean OpenGl_FrameBuffer::Init (const Handle(OpenGl_Context)& theGlCo
theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBufferId); theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBufferId);
theGlContext->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, aDepthStencilFormat, aSizeX, aSizeY); theGlContext->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, aDepthStencilFormat, aSizeX, aSizeY);
theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER); theGlContext->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER);
const GLenum aRendImgErr = theGlContext->core11fwd->glGetError();
if (aRendImgErr != GL_NO_ERROR)
{
theGlContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
TCollection_AsciiString ("Error: FBO depth render buffer ") + aSizeX + "x" + aSizeY
+ " IF: " + OpenGl_TextureFormat::FormatFormat (aDepthStencilFormat)
+ " can not be created with error " + OpenGl_Context::FormatGlError (aRendImgErr) + ".");
Release (theGlContext.get());
return Standard_False;
}
} }
} }
@ -535,8 +553,26 @@ Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& t
const Standard_Integer theDepthFormat, const Standard_Integer theDepthFormat,
const unsigned int theColorRBufferFromWindow) const unsigned int theColorRBufferFromWindow)
{ {
myColorFormats.Clear(); OpenGl_ColorFormats aColorFormats;
myColorFormats.Append (theColorFormat); if (theColorFormat != 0)
{
aColorFormats.Append (theColorFormat);
}
return initRenderBuffer (theGlCtx, theSize, aColorFormats, theDepthFormat, 0, theColorRBufferFromWindow);
}
// =======================================================================
// function : initRenderBuffer
// purpose :
// =======================================================================
Standard_Boolean OpenGl_FrameBuffer::initRenderBuffer (const Handle(OpenGl_Context)& theGlCtx,
const Graphic3d_Vec2i& theSize,
const OpenGl_ColorFormats& theColorFormats,
const Standard_Integer theDepthFormat,
const Standard_Integer theNbSamples,
const unsigned int theColorRBufferFromWindow)
{
myColorFormats = theColorFormats;
if (!myColorTextures.IsEmpty()) if (!myColorTextures.IsEmpty())
{ {
Handle(OpenGl_Texture) aTexutre = myColorTextures.First(); Handle(OpenGl_Texture) aTexutre = myColorTextures.First();
@ -549,7 +585,7 @@ Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& t
} }
myDepthFormat = theDepthFormat; myDepthFormat = theDepthFormat;
myNbSamples = 0; myNbSamples = theNbSamples;
myInitVPSizeX = theSize.x(); myInitVPSizeX = theSize.x();
myInitVPSizeY = theSize.y(); myInitVPSizeY = theSize.y();
if (theGlCtx->arbFBO == NULL) if (theGlCtx->arbFBO == NULL)
@ -559,6 +595,14 @@ Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& t
// clean up previous state // clean up previous state
Release (theGlCtx.operator->()); Release (theGlCtx.operator->());
if (theNbSamples > theGlCtx->MaxMsaaSamples()
|| theNbSamples < 0)
{
theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
TCollection_AsciiString ("Error: FBO creation failed - MSAA") + theNbSamples
+ " render buffer exceeds samples limit: " + theGlCtx->MaxMsaaSamples() + ").");
return Standard_False;
}
myIsOwnColor = true; myIsOwnColor = true;
myIsOwnBuffer = true; myIsOwnBuffer = true;
@ -575,11 +619,43 @@ Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& t
{ {
myGlColorRBufferId = theColorRBufferFromWindow; myGlColorRBufferId = theColorRBufferFromWindow;
} }
else if (theColorFormat != 0) else if (!theColorFormats.IsEmpty())
{ {
if (theColorFormats.Size() != 1)
{
throw Standard_NotImplemented ("Multiple color attachments as FBO render buffers are not implemented");
}
const GLint aColorFormat = theColorFormats.First();
const OpenGl_TextureFormat aFormat = OpenGl_TextureFormat::FindSizedFormat (theGlCtx, aColorFormat);
if (!aFormat.IsValid())
{
Release (theGlCtx.operator->());
return Standard_False;
}
theGlCtx->arbFBO->glGenRenderbuffers (1, &myGlColorRBufferId); theGlCtx->arbFBO->glGenRenderbuffers (1, &myGlColorRBufferId);
theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlColorRBufferId); theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlColorRBufferId);
theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, theColorFormat, aSizeX, aSizeY); if (theNbSamples != 0)
{
theGlCtx->Functions()->glRenderbufferStorageMultisample (GL_RENDERBUFFER, theNbSamples, aFormat.InternalFormat(), aSizeX, aSizeY);
}
else
{
theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, aFormat.InternalFormat(), aSizeX, aSizeY);
}
theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER);
const GLenum aRendImgErr = theGlCtx->core11fwd->glGetError();
if (aRendImgErr != GL_NO_ERROR)
{
theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
TCollection_AsciiString ("Error: FBO color render buffer ") + aSizeX + "x" + aSizeY + "@" + theNbSamples
+ " IF: " + OpenGl_TextureFormat::FormatFormat (aFormat.InternalFormat())
+ " can not be created with error " + OpenGl_Context::FormatGlError (aRendImgErr) + ".");
Release (theGlCtx.get());
return Standard_False;
}
} }
bool hasStencilRB = false; bool hasStencilRB = false;
@ -590,15 +666,36 @@ Standard_Boolean OpenGl_FrameBuffer::InitWithRB (const Handle(OpenGl_Context)& t
theGlCtx->arbFBO->glGenRenderbuffers (1, &myGlDepthRBufferId); theGlCtx->arbFBO->glGenRenderbuffers (1, &myGlDepthRBufferId);
theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBufferId); theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, myGlDepthRBufferId);
if (theNbSamples != 0)
{
theGlCtx->Functions()->glRenderbufferStorageMultisample (GL_RENDERBUFFER, theNbSamples, myDepthFormat, aSizeX, aSizeY);
}
else
{
theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, myDepthFormat, aSizeX, aSizeY); theGlCtx->arbFBO->glRenderbufferStorage (GL_RENDERBUFFER, myDepthFormat, aSizeX, aSizeY);
}
theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER); theGlCtx->arbFBO->glBindRenderbuffer (GL_RENDERBUFFER, NO_RENDERBUFFER);
const GLenum aRendImgErr = theGlCtx->core11fwd->glGetError();
if (aRendImgErr != GL_NO_ERROR)
{
theGlCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
TCollection_AsciiString ("Error: FBO depth render buffer ") + aSizeX + "x" + aSizeY + "@" + theNbSamples
+ " IF: " + OpenGl_TextureFormat::FormatFormat (myDepthFormat)
+ " can not be created with error " + OpenGl_Context::FormatGlError (aRendImgErr) + ".");
Release (theGlCtx.get());
return Standard_False;
}
} }
// create FBO // create FBO
theGlCtx->arbFBO->glGenFramebuffers (1, &myGlFBufferId); theGlCtx->arbFBO->glGenFramebuffers (1, &myGlFBufferId);
theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId); theGlCtx->arbFBO->glBindFramebuffer (GL_FRAMEBUFFER, myGlFBufferId);
if (myGlColorRBufferId != NO_RENDERBUFFER)
{
theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, theGlCtx->arbFBO->glFramebufferRenderbuffer (GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0,
GL_RENDERBUFFER, myGlColorRBufferId); GL_RENDERBUFFER, myGlColorRBufferId);
}
if (myGlDepthRBufferId != NO_RENDERBUFFER) if (myGlDepthRBufferId != NO_RENDERBUFFER)
{ {
if (hasDepthStencilAttach (theGlCtx) && hasStencilRB) if (hasDepthStencilAttach (theGlCtx) && hasStencilRB)

View File

@ -165,9 +165,26 @@ public:
//! (Re-)initialize FBO with properties taken from another FBO. //! (Re-)initialize FBO with properties taken from another FBO.
Standard_Boolean InitLazy (const Handle(OpenGl_Context)& theGlCtx, Standard_Boolean InitLazy (const Handle(OpenGl_Context)& theGlCtx,
const OpenGl_FrameBuffer& theFbo) const OpenGl_FrameBuffer& theFbo,
const Standard_Boolean theToKeepMsaa = true)
{ {
return InitLazy (theGlCtx, Graphic3d_Vec2i (theFbo.myVPSizeX, theFbo.myVPSizeY), theFbo.myColorFormats, theFbo.myDepthFormat, theFbo.myNbSamples); return InitLazy (theGlCtx, Graphic3d_Vec2i (theFbo.myVPSizeX, theFbo.myVPSizeY), theFbo.myColorFormats, theFbo.myDepthFormat, theToKeepMsaa ? theFbo.myNbSamples : 0);
}
//! (Re-)initialize FBO with specified dimensions.
//! The Render Buffer Objects will be used for Color, Depth and Stencil attachments (as opposite to textures).
//! @param theGlCtx currently bound OpenGL context
//! @param theSize render buffer width x height
//! @param theColorFormats list of color render buffer sized format, e.g. GL_RGBA8; list should define only one element
//! @param theDepthFormat depth-stencil render buffer sized format, e.g. GL_DEPTH24_STENCIL8
//! @param theNbSamples MSAA number of samples (0 means normal render buffer)
Standard_Boolean InitRenderBuffer (const Handle(OpenGl_Context)& theGlCtx,
const Graphic3d_Vec2i& theSize,
const OpenGl_ColorFormats& theColorFormats,
const Standard_Integer theDepthFormat,
const Standard_Integer theNbSamples = 0)
{
return initRenderBuffer (theGlCtx, theSize, theColorFormats, theDepthFormat, theNbSamples, 0);
} }
//! (Re-)initialize FBO with specified dimensions. //! (Re-)initialize FBO with specified dimensions.
@ -176,12 +193,12 @@ public:
//! @param theSize render buffer width x height //! @param theSize render buffer width x height
//! @param theColorFormat color render buffer sized format, e.g. GL_RGBA8 //! @param theColorFormat color render buffer sized format, e.g. GL_RGBA8
//! @param theDepthFormat depth-stencil render buffer sized format, e.g. GL_DEPTH24_STENCIL8 //! @param theDepthFormat depth-stencil render buffer sized format, e.g. GL_DEPTH24_STENCIL8
//! @param theColorRBufferFromWindow when specified - should be ID of already initialized RB object, which will be released within this class //! @param theColorRBufferFromWindow should be ID of already initialized RB object, which will be released within this class
Standard_EXPORT Standard_Boolean InitWithRB (const Handle(OpenGl_Context)& theGlCtx, Standard_EXPORT Standard_Boolean InitWithRB (const Handle(OpenGl_Context)& theGlCtx,
const Graphic3d_Vec2i& theSize, const Graphic3d_Vec2i& theSize,
const Standard_Integer theColorFormat, const Standard_Integer theColorFormat,
const Standard_Integer theDepthFormat, const Standard_Integer theDepthFormat,
const unsigned int theColorRBufferFromWindow = 0); const unsigned int theColorRBufferFromWindow);
//! Initialize class from currently bound FBO. //! Initialize class from currently bound FBO.
//! Retrieved OpenGL objects will not be destroyed on Release. //! Retrieved OpenGL objects will not be destroyed on Release.
@ -220,9 +237,15 @@ public:
//! Returns the depth-stencil texture. //! Returns the depth-stencil texture.
const Handle(OpenGl_Texture)& DepthStencilTexture() const { return myDepthStencilTexture; } const Handle(OpenGl_Texture)& DepthStencilTexture() const { return myDepthStencilTexture; }
//! Returns TRUE if color Render Buffer is defined.
bool IsColorRenderBuffer() const { return myGlColorRBufferId != NO_RENDERBUFFER; }
//! Returns the color Render Buffer. //! Returns the color Render Buffer.
unsigned int ColorRenderBuffer() const { return myGlColorRBufferId; } unsigned int ColorRenderBuffer() const { return myGlColorRBufferId; }
//! Returns TRUE if depth Render Buffer is defined.
bool IsDepthStencilRenderBuffer() const { return myGlDepthRBufferId != NO_RENDERBUFFER; }
//! Returns the depth Render Buffer. //! Returns the depth Render Buffer.
unsigned int DepthStencilRenderBuffer() const { return myGlDepthRBufferId; } unsigned int DepthStencilRenderBuffer() const { return myGlDepthRBufferId; }
@ -231,6 +254,21 @@ public:
public: public:
//! (Re-)initialize FBO with specified dimensions.
//! The Render Buffer Objects will be used for Color, Depth and Stencil attachments (as opposite to textures).
//! @param theGlCtx currently bound OpenGL context
//! @param theSize render buffer width x height
//! @param theColorFormats list of color render buffer sized format, e.g. GL_RGBA8
//! @param theDepthFormat depth-stencil render buffer sized format, e.g. GL_DEPTH24_STENCIL8
//! @param theNbSamples MSAA number of samples (0 means normal render buffer)
//! @param theColorRBufferFromWindow when specified - should be ID of already initialized RB object, which will be released within this class
Standard_EXPORT Standard_Boolean initRenderBuffer (const Handle(OpenGl_Context)& theGlCtx,
const Graphic3d_Vec2i& theSize,
const OpenGl_ColorFormats& theColorFormats,
const Standard_Integer theDepthFormat,
const Standard_Integer theNbSamples,
const unsigned int theColorRBufferFromWindow);
//! Initialize FBO for rendering into single/multiple color buffer and depth textures. //! Initialize FBO for rendering into single/multiple color buffer and depth textures.
Standard_DEPRECATED("Obsolete method, use Init() taking Graphic3d_Vec2i") Standard_DEPRECATED("Obsolete method, use Init() taking Graphic3d_Vec2i")
bool Init (const Handle(OpenGl_Context)& theGlCtx, bool Init (const Handle(OpenGl_Context)& theGlCtx,

View File

@ -715,6 +715,9 @@ bool OpenGl_Texture::Init2DMultisample (const Handle(OpenGl_Context)& theCtx,
|| theNbSamples > theCtx->MaxMsaaSamples() || theNbSamples > theCtx->MaxMsaaSamples()
|| theNbSamples < 1) || theNbSamples < 1)
{ {
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
TCollection_AsciiString ("Error: MSAA texture ") + theSizeX + "x" + theSizeY + "@" + myNbSamples
+ " exceeds samples limit: " + theCtx->MaxMsaaSamples() + ".");
return false; return false;
} }
@ -724,26 +727,42 @@ bool OpenGl_Texture::Init2DMultisample (const Handle(OpenGl_Context)& theCtx,
if(theSizeX > theCtx->MaxTextureSize() if(theSizeX > theCtx->MaxTextureSize()
|| theSizeY > theCtx->MaxTextureSize()) || theSizeY > theCtx->MaxTextureSize())
{ {
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
TCollection_AsciiString ("Error: MSAA texture ") + theSizeX + "x" + theSizeY + "@" + myNbSamples
+ " exceeds size limit: " + theCtx->MaxTextureSize() + "x" + theCtx->MaxTextureSize() + ".");
return false; return false;
} }
Bind (theCtx); Bind (theCtx);
//myTextFormat = theTextFormat; //myTextFormat = theTextFormat;
mySizedFormat = theTextFormat; mySizedFormat = theTextFormat;
#if !defined(GL_ES_VERSION_2_0) if (theCtx->HasTextureMultisampling()
if (theCtx->Functions()->glTexStorage2DMultisample != NULL) && theCtx->Functions()->glTexStorage2DMultisample != NULL)
{ {
theCtx->Functions()->glTexStorage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE); theCtx->Functions()->glTexStorage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
} }
else #if !defined(GL_ES_VERSION_2_0)
else if (theCtx->HasTextureMultisampling()
&& theCtx->Functions()->glTexImage2DMultisample != NULL)
{ {
theCtx->Functions()->glTexImage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE); theCtx->Functions()->glTexImage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
} }
#else
theCtx->Functions() ->glTexStorage2DMultisample (myTarget, myNbSamples, theTextFormat, theSizeX, theSizeY, GL_FALSE);
#endif #endif
if (theCtx->core11fwd->glGetError() != GL_NO_ERROR) else
{ {
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
"Error: MSAA textures are not supported by hardware.");
Unbind (theCtx);
return false;
}
const GLenum aTexImgErr = theCtx->core11fwd->glGetError();
if (aTexImgErr != GL_NO_ERROR)
{
theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
TCollection_AsciiString ("Error: MSAA texture ") + theSizeX + "x" + theSizeY + "@" + myNbSamples
+ " IF: " + OpenGl_TextureFormat::FormatFormat (theTextFormat)
+ " cannot be created with error " + OpenGl_Context::FormatGlError (aTexImgErr) + ".");
Unbind (theCtx); Unbind (theCtx);
return false; return false;
} }

View File

@ -1106,6 +1106,11 @@ bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj)
{ {
aNbSamples = OpenGl_Context::GetPowerOfTwo (aNbSamples, aCtx->MaxMsaaSamples()); aNbSamples = OpenGl_Context::GetPowerOfTwo (aNbSamples, aCtx->MaxMsaaSamples());
} }
// Only MSAA textures can be blit into MSAA target,
// while render buffers could be resolved only into non-MSAA targets.
// As result, within obsolete OpenGL ES 3.0 context, we may create only one MSAA render buffer for main scene content
// and blit it into non-MSAA immediate FBO.
const bool hasTextureMsaa = aCtx->HasTextureMultisampling();
bool toUseOit = myRenderParams.TransparencyMethod != Graphic3d_RTM_BLEND_UNORDERED bool toUseOit = myRenderParams.TransparencyMethod != Graphic3d_RTM_BLEND_UNORDERED
&& checkOitCompatibility (aCtx, aNbSamples > 0); && checkOitCompatibility (aCtx, aNbSamples > 0);
@ -1156,7 +1161,7 @@ bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj)
if (myMainSceneFbos[0]->IsValid() && (toInitImmediateFbo || myImmediateSceneFbos[0]->IsValid())) if (myMainSceneFbos[0]->IsValid() && (toInitImmediateFbo || myImmediateSceneFbos[0]->IsValid()))
{ {
const bool wasFailedImm0 = checkWasFailedFbo (myImmediateSceneFbos[0], myMainSceneFbos[0]); const bool wasFailedImm0 = checkWasFailedFbo (myImmediateSceneFbos[0], myMainSceneFbos[0]);
if (!myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]) if (!myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0], hasTextureMsaa)
&& !wasFailedImm0) && !wasFailedImm0)
{ {
TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO " TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO "
@ -1200,7 +1205,7 @@ bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj)
&& myMainSceneFbos[0]->IsValid()) && myMainSceneFbos[0]->IsValid())
{ {
const bool wasFailedMain1 = checkWasFailedFbo (myMainSceneFbos[1], myMainSceneFbos[0]); const bool wasFailedMain1 = checkWasFailedFbo (myMainSceneFbos[1], myMainSceneFbos[0]);
if (!myMainSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]) if (!myMainSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0], true)
&& !wasFailedMain1) && !wasFailedMain1)
{ {
TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Main FBO (second) " TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Main FBO (second) "
@ -1221,14 +1226,14 @@ bool OpenGl_View::prepareFrameBuffers (Graphic3d_Camera::Projection& theProj)
{ {
const bool wasFailedImm0 = checkWasFailedFbo (myImmediateSceneFbos[0], myMainSceneFbos[0]); const bool wasFailedImm0 = checkWasFailedFbo (myImmediateSceneFbos[0], myMainSceneFbos[0]);
const bool wasFailedImm1 = checkWasFailedFbo (myImmediateSceneFbos[1], myMainSceneFbos[0]); const bool wasFailedImm1 = checkWasFailedFbo (myImmediateSceneFbos[1], myMainSceneFbos[0]);
if (!myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0]) if (!myImmediateSceneFbos[0]->InitLazy (aCtx, *myMainSceneFbos[0], hasTextureMsaa)
&& !wasFailedImm0) && !wasFailedImm0)
{ {
TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO (first) " TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO (first) "
+ printFboFormat (myImmediateSceneFbos[0]) + " initialization has failed"; + printFboFormat (myImmediateSceneFbos[0]) + " initialization has failed";
aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg); aCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
} }
if (!myImmediateSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0]) if (!myImmediateSceneFbos[1]->InitLazy (aCtx, *myMainSceneFbos[0], hasTextureMsaa)
&& !wasFailedImm1) && !wasFailedImm1)
{ {
TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO (first) " TCollection_ExtendedString aMsg = TCollection_ExtendedString() + "Error! Immediate FBO (first) "
@ -2649,9 +2654,22 @@ bool OpenGl_View::blitBuffers (OpenGl_FrameBuffer* theReadFbo,
aCtx->SetColorMask (true); // restore default alpha component write state aCtx->SetColorMask (true); // restore default alpha component write state
const bool toApplyGamma = aCtx->ToRenderSRGB() != aCtx->IsFrameBufferSRGB(); const bool toApplyGamma = aCtx->ToRenderSRGB() != aCtx->IsFrameBufferSRGB();
if (aCtx->arbFBOBlit != NULL bool toDrawTexture = true;
&& !toApplyGamma if (aCtx->arbFBOBlit != NULL)
{
if (!toApplyGamma
&& theReadFbo->NbSamples() != 0) && theReadFbo->NbSamples() != 0)
{
toDrawTexture = false;
}
if (theReadFbo->IsColorRenderBuffer())
{
// render buffers could be resolved only via glBlitFramebuffer()
toDrawTexture = false;
}
}
if (!toDrawTexture)
{ {
GLbitfield aCopyMask = 0; GLbitfield aCopyMask = 0;
theReadFbo->BindReadBuffer (aCtx); theReadFbo->BindReadBuffer (aCtx);

View File

@ -785,7 +785,9 @@ void OpenGl_Window::Init()
aDefFbo = new OpenGl_FrameBuffer(); aDefFbo = new OpenGl_FrameBuffer();
} }
if (!aDefFbo->InitWithRB (myGlContext, Graphic3d_Vec2i (myWidth, myHeight), GL_RGBA8, GL_DEPTH24_STENCIL8)) OpenGl_ColorFormats aColorFormats;
aColorFormats.Append (GL_RGBA8);
if (!aDefFbo->InitRenderBuffer (myGlContext, Graphic3d_Vec2i (myWidth, myHeight), aColorFormats, GL_DEPTH24_STENCIL8))
{ {
TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO creation failed"); TCollection_AsciiString aMsg ("OpenGl_Window::CreateWindow: default FBO creation failed");
throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString()); throw Aspect_GraphicDeviceDefinitionError(aMsg.ToCString());