]> OCCT Git - occt.git/commitdiff
0031597: Visualization, TKOpenGl - allow disabling Alpha component writes within...
authorkgv <kgv@opencascade.com>
Sat, 12 Dec 2020 09:24:50 +0000 (12:24 +0300)
committerbugmaster <bugmaster@opencascade.com>
Thu, 17 Dec 2020 18:05:02 +0000 (21:05 +0300)
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
src/OpenGl/OpenGl_Caps.cxx
src/OpenGl/OpenGl_Caps.hxx
src/OpenGl/OpenGl_Context.cxx
src/OpenGl/OpenGl_Context.hxx
src/OpenGl/OpenGl_LayerList.cxx
src/OpenGl/OpenGl_View_Redraw.cxx
src/ViewerTest/ViewerTest_ViewerCommands.cxx

index f8e770b8dbd01490680e4f72ed1d007002d18dd6..db4c6ac7734271103e33c2f50be98a3691a407d5 100644 (file)
@@ -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);
index 5f8c3d3cfdb7966f20af457f955b24a5a96dad41..03ecc8b2ed040be4c1a98adc4a4fcba1fab5ea37 100755 (executable)
@@ -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;
index 6a1a386e27db332b989c3ea5fac43288d63662fb..6657515cf9037e73be1657c2c6b36197ec38a069 100755 (executable)
@@ -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.
    *
index 257f8d425faa5979f61318fd9ecc3c515f120782..53fb914d08f6908471aa8bdf1f5e6999331439f1 100644 (file)
@@ -4609,17 +4609,29 @@ void OpenGl_Context::DisableFeatures() const
 #endif
 }
 
+// =======================================================================
+// function : SetColorMaskRGBA
+// purpose  :
+// =======================================================================
+void OpenGl_Context::SetColorMaskRGBA (const NCollection_Vec4<bool>& 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;
 }
 
index 916478e1a47f26f7fe4a6c014f7e3d01ee522e5d..e3cc3d7df3901554617fe5b7acb766ca0d2dc5f5 100644 (file)
@@ -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<bool>& ColorMaskRGBA() const { return myColorMask; }
 
   //! Enable/disable writing into color buffer (wrapper for glColorMask).
+  Standard_EXPORT void SetColorMaskRGBA (const NCollection_Vec4<bool>& 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<Standard_Integer>
                                 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<bool>        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
index bd4708de1fda3279410a369f4596c2b31dd5f97c..e01146f4645eaca06dd53647156c4f9e26420578 100644 (file)
@@ -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<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);
@@ -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);
index bbe25aa22338bd7fb3dffd40c8b6a42e6a4722d1..ba6fd31cc2629f81b1340d323ebd4229cfb8e3e3 100644 (file)
@@ -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<bool> (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<bool> (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
index baeca0e39e557e9be20932b03de2a801c6c9f1c3..317e3709af16a944871f92a81bb4583ef093034a 100644 (file)
@@ -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"