From 31174e1a58880910c42a918abbae45ab0a50156b Mon Sep 17 00:00:00 2001 From: kgv Date: Sat, 12 Dec 2020 12:24:50 +0300 Subject: [PATCH] 0031597: Visualization, TKOpenGl - allow disabling Alpha component writes within OpenGl_Context::ColorMask() Added OpenGl_Caps::buffersOpaqueAlpha option allowing to disable writes into alpha component of color buffer and keep it opaque. Added OpenGl_Context::SetColorMaskRGBA() method overriding each color component deliberately. New option is set within WebGL sample. --- samples/webgl/WasmOcctView.cpp | 1 + src/OpenGl/OpenGl_Caps.cxx | 2 ++ src/OpenGl/OpenGl_Caps.hxx | 11 ++++++++ src/OpenGl/OpenGl_Context.cxx | 20 ++++++++++++--- src/OpenGl/OpenGl_Context.hxx | 11 ++++++-- src/OpenGl/OpenGl_LayerList.cxx | 2 ++ src/OpenGl/OpenGl_View_Redraw.cxx | 27 ++++++++------------ src/ViewerTest/ViewerTest_ViewerCommands.cxx | 15 ++++++++++- 8 files changed, 66 insertions(+), 23 deletions(-) diff --git a/samples/webgl/WasmOcctView.cpp b/samples/webgl/WasmOcctView.cpp index f8e770b8db..db4c6ac773 100644 --- a/samples/webgl/WasmOcctView.cpp +++ b/samples/webgl/WasmOcctView.cpp @@ -227,6 +227,7 @@ bool WasmOcctView::initViewer() Handle(Aspect_DisplayConnection) aDisp; Handle(OpenGl_GraphicDriver) aDriver = new OpenGl_GraphicDriver (aDisp, false); aDriver->ChangeOptions().buffersNoSwap = true; // swap has no effect in WebGL + aDriver->ChangeOptions().buffersOpaqueAlpha = true; // avoid unexpected blending of canvas with page background if (!aDriver->InitContext()) { Message::DefaultMessenger()->Send (TCollection_AsciiString ("Error: EGL initialization failed"), Message_Fail); diff --git a/src/OpenGl/OpenGl_Caps.cxx b/src/OpenGl/OpenGl_Caps.cxx index 5f8c3d3cfd..03ecc8b2ed 100755 --- a/src/OpenGl/OpenGl_Caps.cxx +++ b/src/OpenGl/OpenGl_Caps.cxx @@ -38,6 +38,7 @@ OpenGl_Caps::OpenGl_Caps() #endif swapInterval (1), buffersNoSwap (Standard_False), + buffersOpaqueAlpha(Standard_False), contextStereo (Standard_False), #ifdef OCCT_DEBUG contextDebug (Standard_True), @@ -78,6 +79,7 @@ OpenGl_Caps& OpenGl_Caps::operator= (const OpenGl_Caps& theCopy) useSystemBuffer = theCopy.useSystemBuffer; swapInterval = theCopy.swapInterval; buffersNoSwap = theCopy.buffersNoSwap; + buffersOpaqueAlpha= theCopy.buffersOpaqueAlpha; contextStereo = theCopy.contextStereo; contextDebug = theCopy.contextDebug; contextSyncDebug = theCopy.contextSyncDebug; diff --git a/src/OpenGl/OpenGl_Caps.hxx b/src/OpenGl/OpenGl_Caps.hxx index 6a1a386e27..6657515cf9 100755 --- a/src/OpenGl/OpenGl_Caps.hxx +++ b/src/OpenGl/OpenGl_Caps.hxx @@ -48,6 +48,17 @@ public: //! @name context creation parameters */ Standard_Boolean buffersNoSwap; + /** + * Specify whether alpha component within color buffer should be written or not. + * With alpha write enabled, background is considered transparent by default + * and overridden by alpha value of last drawn object + * (e.g. it could be opaque or not in case of transparent material). + * With alpha writes disabled, color buffer will be kept opaque. + * + * OFF by default. + */ + Standard_Boolean buffersOpaqueAlpha; + /** * Request stereoscopic context (with Quad Buffer). This flag requires support in OpenGL driver. * diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 257f8d425f..53fb914d08 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -4609,17 +4609,29 @@ void OpenGl_Context::DisableFeatures() const #endif } +// ======================================================================= +// function : SetColorMaskRGBA +// purpose : +// ======================================================================= +void OpenGl_Context::SetColorMaskRGBA (const NCollection_Vec4& theVal) +{ + glColorMask (theVal.r() ? GL_TRUE : GL_FALSE, + theVal.g() ? GL_TRUE : GL_FALSE, + theVal.b() ? GL_TRUE : GL_FALSE, + theVal.a() ? GL_TRUE : GL_FALSE); + myColorMask = theVal; +} + // ======================================================================= // function : SetColorMask // purpose : // ======================================================================= bool OpenGl_Context::SetColorMask (bool theToWriteColor) { + const bool anOldValue = myColorMask.r(); + myColorMask.SetValues (theToWriteColor, theToWriteColor, theToWriteColor, caps->buffersOpaqueAlpha ? false : theToWriteColor); const GLboolean toWrite = theToWriteColor ? GL_TRUE : GL_FALSE; - glColorMask (toWrite, toWrite, toWrite, toWrite); - - const bool anOldValue = myColorMask; - myColorMask = theToWriteColor; + glColorMask (toWrite, toWrite, toWrite, myColorMask.a() ? GL_TRUE : GL_FALSE); return anOldValue; } diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index 916478e1a4..e3cc3d7df3 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -805,9 +805,16 @@ public: //! @name methods to alter or retrieve current state Standard_EXPORT void SetFrameBufferSRGB (bool theIsFbo, bool theIsFboSRgb = true); //! Return cached flag indicating writing into color buffer is enabled or disabled (glColorMask). - bool ColorMask() const { return myColorMask; } + const NCollection_Vec4& ColorMaskRGBA() const { return myColorMask; } //! Enable/disable writing into color buffer (wrapper for glColorMask). + Standard_EXPORT void SetColorMaskRGBA (const NCollection_Vec4& theToWriteColor); + + //! Return cached flag indicating writing into color buffer is enabled or disabled (glColorMask). + bool ColorMask() const { return myColorMask.r(); } + + //! Enable/disable writing into color buffer (wrapper for glColorMask). + //! Alpha component writes will be disabled unconditionally in case of caps->buffersOpaqueAlpha. Standard_EXPORT bool SetColorMask (bool theToWriteColor); //! Return TRUE if GL_SAMPLE_ALPHA_TO_COVERAGE usage is allowed. @@ -1190,7 +1197,7 @@ private: //! @name fields tracking current state NCollection_Array1 myDrawBuffers; //!< current draw buffers unsigned int myDefaultVao; //!< default Vertex Array Object - Standard_Boolean myColorMask; //!< flag indicating writing into color buffer is enabled or disabled (glColorMask) + NCollection_Vec4 myColorMask; //!< flag indicating writing into color buffer is enabled or disabled (glColorMask) Standard_Boolean myAllowAlphaToCov; //!< flag allowing GL_SAMPLE_ALPHA_TO_COVERAGE usage Standard_Boolean myAlphaToCoverage; //!< flag indicating GL_SAMPLE_ALPHA_TO_COVERAGE state Standard_Boolean myIsGlDebugCtx; //!< debug context initialization state diff --git a/src/OpenGl/OpenGl_LayerList.cxx b/src/OpenGl/OpenGl_LayerList.cxx index bd4708de1f..e01146f464 100644 --- a/src/OpenGl/OpenGl_LayerList.cxx +++ b/src/OpenGl/OpenGl_LayerList.cxx @@ -883,6 +883,7 @@ void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)& theW static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0, GL_COLOR_ATTACHMENT0 + 1 }; aCtx->SetDrawBuffers (2, aDrawBuffers); + aCtx->SetColorMaskRGBA (NCollection_Vec4 (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); @@ -917,6 +918,7 @@ void OpenGl_LayerList::renderTransparent (const Handle(OpenGl_Workspace)& theW static const Standard_Integer aDrawBuffers[] = { GL_COLOR_ATTACHMENT0 }; aCtx->SetDrawBuffers (1, aDrawBuffers); + aCtx->SetColorMask (true); // update writes into alpha component } theWorkspace->SetRenderFilter (aPrevFilter | OpenGl_RenderFilter_OpaqueOnly); diff --git a/src/OpenGl/OpenGl_View_Redraw.cxx b/src/OpenGl/OpenGl_View_Redraw.cxx index bbe25aa223..ba6fd31cc2 100644 --- a/src/OpenGl/OpenGl_View_Redraw.cxx +++ b/src/OpenGl/OpenGl_View_Redraw.cxx @@ -922,20 +922,17 @@ void OpenGl_View::redraw (const Graphic3d_Camera::Projection theProjection, myWorkspace->UseZBuffer() = Standard_True; myWorkspace->UseDepthWrite() = Standard_True; GLbitfield toClear = GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT; - glDepthFunc (GL_LEQUAL); - glDepthMask (GL_TRUE); - glEnable (GL_DEPTH_TEST); + aCtx->core11fwd->glDepthFunc (GL_LEQUAL); + aCtx->core11fwd->glDepthMask (GL_TRUE); + aCtx->core11fwd->glEnable (GL_DEPTH_TEST); -#if !defined(GL_ES_VERSION_2_0) - glClearDepth (1.0); -#else - glClearDepthf (1.0f); -#endif + aCtx->core11fwd->glClearDepth (1.0); const OpenGl_Vec4 aBgColor = aCtx->Vec4FromQuantityColor (myBgColor); - glClearColor (aBgColor.r(), aBgColor.g(), aBgColor.b(), 0.0f); - - glClear (toClear); + aCtx->SetColorMaskRGBA (NCollection_Vec4 (true)); // force writes into all components, including alpha + aCtx->core11fwd->glClearColor (aBgColor.r(), aBgColor.g(), aBgColor.b(), aCtx->caps->buffersOpaqueAlpha ? 1.0f : 0.0f); + aCtx->core11fwd->glClear (toClear); + aCtx->SetColorMask (true); // restore default alpha component write state render (theProjection, theReadDrawFbo, theOitAccumFbo, Standard_False); } @@ -1487,12 +1484,10 @@ bool OpenGl_View::blitBuffers (OpenGl_FrameBuffer* theReadFbo, const Standard_Integer aViewport[4] = { 0, 0, aDrawSizeX, aDrawSizeY }; aCtx->ResizeViewport (aViewport); -#if !defined(GL_ES_VERSION_2_0) - aCtx->core20fwd->glClearDepth (1.0); -#else - aCtx->core20fwd->glClearDepthf (1.0f); -#endif + aCtx->SetColorMaskRGBA (NCollection_Vec4 (true)); // force writes into all components, including alpha + aCtx->core20fwd->glClearDepth (1.0); aCtx->core20fwd->glClear (GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + aCtx->SetColorMask (true); // restore default alpha component write state const bool toApplyGamma = aCtx->ToRenderSRGB() != aCtx->IsFrameBufferSRGB(); if (aCtx->arbFBOBlit != NULL diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index baeca0e39e..317e3709af 100644 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -6751,6 +6751,7 @@ static int VCaps (Draw_Interpretor& theDI, theDI << "Compatible:" << (aCaps->contextCompatible ? "1" : "0") << "\n"; theDI << "Stereo: " << (aCaps->contextStereo ? "1" : "0") << "\n"; theDI << "WinBuffer: " << (aCaps->useSystemBuffer ? "1" : "0") << "\n"; + theDI << "OpaqueAlpha: " << (aCaps->buffersOpaqueAlpha ? "1" : "0") << "\n"; theDI << "NoExt:" << (aCaps->contextNoExtensions ? "1" : "0") << "\n"; theDI << "MaxVersion:" << aCaps->contextMajorVersionUpper << "." << aCaps->contextMinorVersionUpper << "\n"; theDI << "CompressTextures: " << (aCaps->compressedTexturesDisable ? "0" : "1") << "\n"; @@ -6849,6 +6850,17 @@ static int VCaps (Draw_Interpretor& theDI, } aCaps->contextNoAccel = toEnable; } + else if (anArgCase == "-opaquealpha" + || anArgCase == "-buffersOpaqueAlpha") + { + Standard_Boolean toEnable = Standard_True; + if (++anArgIter < theArgNb + && !Draw::ParseOnOff (theArgVec[anArgIter], toEnable)) + { + --anArgIter; + } + aCaps->buffersOpaqueAlpha = toEnable; + } else if (anArgCase == "-winbuffer" || anArgCase == "-windowbuffer" || anArgCase == "-usewinbuffer" @@ -14519,7 +14531,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands) theCommands.Add ("vcaps", "vcaps [-sRGB {0|1}] [-vbo {0|1}] [-sprites {0|1}] [-ffp {0|1}] [-polygonMode {0|1}]" "\n\t\t: [-compatibleProfile {0|1}] [-compressedTextures {0|1}]" - "\n\t\t: [-vsync {0|1}] [-useWinBuffer {0|1}]" + "\n\t\t: [-vsync {0|1}] [-useWinBuffer {0|1}] [-opaqueAlpha {0|1}]" "\n\t\t: [-quadBuffer {0|1}] [-stereo {0|1}]" "\n\t\t: [-softMode {0|1}] [-noupdate|-update]" "\n\t\t: [-noExtensions {0|1}] [-maxVersion Major Minor]" @@ -14534,6 +14546,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands) "\n\t\t: arrays to GPU memory)" "\n\t\t: sprite - use textured sprites instead of bitmaps" "\n\t\t: vsync - switch VSync on or off" + "\n\t\t: opaqueAlpha - disable writes in alpha component of color buffer" "\n\t\t: winBuffer - allow using window buffer for rendering" "\n\t\t: Context creation options:" "\n\t\t: softMode - software OpenGL implementation"