diff --git a/src/AIS/AIS_RubberBand.cxx b/src/AIS/AIS_RubberBand.cxx index 1d7f1ab9d1..f4a97ab33a 100644 --- a/src/AIS/AIS_RubberBand.cxx +++ b/src/AIS/AIS_RubberBand.cxx @@ -45,6 +45,7 @@ AIS_RubberBand::AIS_RubberBand() myDrawer->SetShadingAspect (new Prs3d_ShadingAspect()); myDrawer->ShadingAspect()->SetMaterial (Graphic3d_NOM_PLASTIC); myDrawer->ShadingAspect()->Aspect()->SetInteriorStyle (Aspect_IS_EMPTY); + myDrawer->ShadingAspect()->Aspect()->SetAlphaMode (Graphic3d_AlphaMode_Blend); myDrawer->ShadingAspect()->SetTransparency (1.0); myDrawer->ShadingAspect()->SetColor (Quantity_NOC_WHITE); @@ -66,6 +67,7 @@ AIS_RubberBand::AIS_RubberBand (const Quantity_Color& theLineColor, myDrawer->SetShadingAspect (new Prs3d_ShadingAspect()); myDrawer->ShadingAspect()->SetMaterial (Graphic3d_NOM_PLASTIC); myDrawer->ShadingAspect()->Aspect()->SetInteriorStyle (Aspect_IS_EMPTY); + myDrawer->ShadingAspect()->Aspect()->SetAlphaMode (Graphic3d_AlphaMode_Blend); myDrawer->ShadingAspect()->SetTransparency (1.0); myDrawer->ShadingAspect()->SetColor (Quantity_NOC_WHITE); @@ -90,6 +92,7 @@ AIS_RubberBand::AIS_RubberBand (const Quantity_Color& theLineColor, myDrawer->ShadingAspect()->SetMaterial (Graphic3d_NOM_PLASTIC); myDrawer->ShadingAspect()->SetColor (theFillColor); myDrawer->ShadingAspect()->Aspect()->SetInteriorStyle (Aspect_IS_SOLID); + myDrawer->ShadingAspect()->Aspect()->SetAlphaMode (Graphic3d_AlphaMode_Blend); myDrawer->ShadingAspect()->SetTransparency (theTransparency); SetTransformPersistence (new Graphic3d_TransformPers (Graphic3d_TMF_2d, Aspect_TOTP_LEFT_LOWER)); diff --git a/src/Graphic3d/FILES b/src/Graphic3d/FILES index 3f7ab9fbf3..25ebb5a4d6 100755 --- a/src/Graphic3d/FILES +++ b/src/Graphic3d/FILES @@ -1,3 +1,4 @@ +Graphic3d_AlphaMode.hxx Graphic3d_ArrayOfPoints.hxx Graphic3d_ArrayOfPolygons.hxx Graphic3d_ArrayOfPolylines.hxx diff --git a/src/Graphic3d/Graphic3d_AlphaMode.hxx b/src/Graphic3d/Graphic3d_AlphaMode.hxx new file mode 100644 index 0000000000..4839417e48 --- /dev/null +++ b/src/Graphic3d/Graphic3d_AlphaMode.hxx @@ -0,0 +1,28 @@ +// Copyright (c) 2018 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 _Graphic3d_AlphaMode_HeaderFile +#define _Graphic3d_AlphaMode_HeaderFile + +//! Defines how alpha value of base color / texture should be treated. +enum Graphic3d_AlphaMode +{ + Graphic3d_AlphaMode_Opaque = 0, //!< rendered output is fully opaque and alpha value is ignored + Graphic3d_AlphaMode_Mask, //!< rendered output is either fully opaque or fully transparent depending on the alpha value and the alpha cutoff value + Graphic3d_AlphaMode_Blend, //!< rendered output is combined with the background + + Graphic3d_AlphaMode_BlendAuto = -1, //!< special value defined for backward compatibility - it is equal to Graphic3d_AlphaMode_Blend when Material transparency is not zero and Graphic3d_AlphaMode_Opaque otherwise; + // since this check ignores possible transparency defined by per-vertex colors and textures - NOT recommended to use! +}; + +#endif // _Graphic3d_AlphaModeHeaderFile diff --git a/src/Graphic3d/Graphic3d_AspectFillArea3d.cxx b/src/Graphic3d/Graphic3d_AspectFillArea3d.cxx index 5398fe27fb..a4e1cb027a 100644 --- a/src/Graphic3d/Graphic3d_AspectFillArea3d.cxx +++ b/src/Graphic3d/Graphic3d_AspectFillArea3d.cxx @@ -27,6 +27,8 @@ Graphic3d_AspectFillArea3d::Graphic3d_AspectFillArea3d() myEdgeColor (Quantity_NOC_WHITE), myInteriorStyle (Aspect_IS_EMPTY), myShadingModel (Graphic3d_TOSM_DEFAULT), + myAlphaMode (Graphic3d_AlphaMode_BlendAuto), + myAlphaCutoff (0.5f), myEdgeType (Aspect_TOL_SOLID), myEdgeWidth (1.0f), myHatchStyle (Handle(Graphic3d_HatchStyle)()), @@ -56,6 +58,8 @@ Graphic3d_AspectFillArea3d::Graphic3d_AspectFillArea3d (const Aspect_InteriorSty myEdgeColor (theEdgeColor), myInteriorStyle (theInteriorStyle), myShadingModel (Graphic3d_TOSM_DEFAULT), + myAlphaMode (Graphic3d_AlphaMode_BlendAuto), + myAlphaCutoff (0.5f), myEdgeType (theEdgeLineType), myEdgeWidth ((float )theEdgeLineWidth), myHatchStyle (Handle(Graphic3d_HatchStyle)()), diff --git a/src/Graphic3d/Graphic3d_AspectFillArea3d.hxx b/src/Graphic3d/Graphic3d_AspectFillArea3d.hxx index dcd532bd81..f7e46e18d5 100644 --- a/src/Graphic3d/Graphic3d_AspectFillArea3d.hxx +++ b/src/Graphic3d/Graphic3d_AspectFillArea3d.hxx @@ -21,6 +21,7 @@ #include <Aspect_PolygonOffsetMode.hxx> #include <Aspect_InteriorStyle.hxx> #include <Aspect_TypeOfLine.hxx> +#include <Graphic3d_AlphaMode.hxx> #include <Graphic3d_HatchStyle.hxx> #include <Graphic3d_MaterialAspect.hxx> #include <Graphic3d_PolygonOffset.hxx> @@ -84,6 +85,20 @@ public: //! Sets shading model void SetShadingModel (const Graphic3d_TypeOfShadingModel theShadingModel) { myShadingModel = theShadingModel; } + //! Returns the way how alpha value should be treated (Graphic3d_AlphaMode_BlendAuto by default, for backward compatibility). + Graphic3d_AlphaMode AlphaMode() const { return myAlphaMode; } + + //! Returns alpha cutoff threshold, for discarding fragments within Graphic3d_AlphaMode_Mask mode (0.5 by default). + //! If the alpha value is greater than or equal to this value then it is rendered as fully opaque, otherwise, it is rendered as fully transparent. + Standard_ShortReal AlphaCutoff() const { return myAlphaCutoff; } + + //! Defines the way how alpha value should be treated. + void SetAlphaMode (Graphic3d_AlphaMode theMode, Standard_ShortReal theAlphaCutoff = 0.5f) + { + myAlphaMode = theMode; + myAlphaCutoff = theAlphaCutoff; + } + //! Return interior color. const Quantity_Color& InteriorColor() const { return myInteriorColor.GetRGB(); } @@ -345,6 +360,8 @@ protected: Quantity_ColorRGBA myEdgeColor; Aspect_InteriorStyle myInteriorStyle; Graphic3d_TypeOfShadingModel myShadingModel; + Graphic3d_AlphaMode myAlphaMode; + Standard_ShortReal myAlphaCutoff; Aspect_TypeOfLine myEdgeType; Standard_ShortReal myEdgeWidth; Handle(Graphic3d_HatchStyle) myHatchStyle; diff --git a/src/Graphic3d/Graphic3d_RenderingParams.hxx b/src/Graphic3d/Graphic3d_RenderingParams.hxx index 17f4913bcd..6c53b3fe3a 100644 --- a/src/Graphic3d/Graphic3d_RenderingParams.hxx +++ b/src/Graphic3d/Graphic3d_RenderingParams.hxx @@ -80,6 +80,7 @@ public: NbMsaaSamples (0), RenderResolutionScale (1.0f), ToEnableDepthPrepass (Standard_False), + ToEnableAlphaToCoverage (Standard_False), // ray tracing parameters IsGlobalIlluminationEnabled (Standard_False), RaytracingDepth (THE_DEFAULT_DEPTH), @@ -147,6 +148,7 @@ public: Standard_ShortReal RenderResolutionScale; //!< rendering resolution scale factor, 1 by default; //! incompatible with MSAA (e.g. NbMsaaSamples should be set to 0) Standard_Boolean ToEnableDepthPrepass; //!< enables/disables depth pre-pass, False by default + Standard_Boolean ToEnableAlphaToCoverage; //!< enables/disables alpha to coverage, False by default Standard_Boolean IsGlobalIlluminationEnabled; //!< enables/disables global illumination effects (path tracing) Standard_Integer SamplesPerPixel; //!< number of samples per pixel (SPP) diff --git a/src/Graphic3d/Graphic3d_ShaderProgram.cxx b/src/Graphic3d/Graphic3d_ShaderProgram.cxx index 4ed105112f..c7638c16f1 100755 --- a/src/Graphic3d/Graphic3d_ShaderProgram.cxx +++ b/src/Graphic3d/Graphic3d_ShaderProgram.cxx @@ -80,6 +80,7 @@ Graphic3d_ShaderProgram::Graphic3d_ShaderProgram() : myNbLightsMax (THE_MAX_LIGHTS_DEFAULT), myNbClipPlanesMax (THE_MAX_CLIP_PLANES_DEFAULT), myNbFragOutputs (THE_NB_FRAG_OUTPUTS), + myHasAlphaTest (false), myHasWeightOitOutput (false) { myID = TCollection_AsciiString ("Graphic3d_ShaderProgram_") diff --git a/src/Graphic3d/Graphic3d_ShaderProgram.hxx b/src/Graphic3d/Graphic3d_ShaderProgram.hxx index 324465e5b8..0e2cd15990 100755 --- a/src/Graphic3d/Graphic3d_ShaderProgram.hxx +++ b/src/Graphic3d/Graphic3d_ShaderProgram.hxx @@ -126,6 +126,13 @@ public: //! Should be done before GLSL program initialization. void SetNbFragmentOutputs (const Standard_Integer theNbOutputs) { myNbFragOutputs = theNbOutputs; } + //! Return true if Fragment Shader should perform alpha test; FALSE by default. + Standard_Boolean HasAlphaTest() const { return myHasAlphaTest; } + + //! Set if Fragment Shader should perform alpha test. + //! Note that this flag is designed for usage with - custom shader program may discard fragment regardless this flag. + void SetAlphaTest (Standard_Boolean theAlphaTest) { myHasAlphaTest = theAlphaTest; } + //! Return true if Fragment Shader color should output the weighted OIT coverage; FALSE by default. Standard_Boolean HasWeightOitOutput() const { return myHasWeightOitOutput; } @@ -183,6 +190,7 @@ private: Standard_Integer myNbLightsMax; //!< length of array of light sources (THE_MAX_LIGHTS) 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_Boolean myHasAlphaTest; //!< flag indicating that Fragment Shader performs alpha test Standard_Boolean myHasWeightOitOutput; //!< flag indicating that Fragment Shader includes weighted OIT coverage }; diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index ed6153436a..18cbea056d 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -191,6 +191,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) myDrawBuffers (1), myDefaultVao (0), myColorMask (true), + myAlphaToCoverage (false), myIsGlDebugCtx (Standard_False), myResolution (Graphic3d_RenderingParams::THE_DEFAULT_RESOLUTION), myResolutionRatio (1.0f), @@ -3193,20 +3194,27 @@ void OpenGl_Context::SetShadingMaterial (const OpenGl_AspectFace* theAspect, // do not update material properties in case of zero reflection mode, // because GL lighting will be disabled by OpenGl_PrimitiveArray::DrawArray() anyway. + const OpenGl_MaterialState& aMatState = myShaderManager->MaterialState(); + const float anAlphaCutoff = anAspect->AlphaMode() == Graphic3d_AlphaMode_Mask + ? anAspect->AlphaCutoff() + : ShortRealLast(); if (theAspect->ShadingModel() == Graphic3d_TOSM_UNLIT) { - return; + if (anAlphaCutoff == aMatState.AlphaCutoff()) + { + return; + } } - - if (myMatFront == myShaderManager->MaterialState().FrontMaterial() - && myMatBack == myShaderManager->MaterialState().BackMaterial() - && toDistinguish == myShaderManager->MaterialState().ToDistinguish() - && toMapTexture == myShaderManager->MaterialState().ToMapTexture()) + else if (myMatFront == aMatState.FrontMaterial() + && myMatBack == aMatState.BackMaterial() + && toDistinguish == aMatState.ToDistinguish() + && toMapTexture == aMatState.ToMapTexture() + && anAlphaCutoff == aMatState.AlphaCutoff()) { return; } - myShaderManager->UpdateMaterialStateTo (myMatFront, myMatBack, toDistinguish, toMapTexture); + myShaderManager->UpdateMaterialStateTo (myMatFront, myMatBack, anAlphaCutoff, toDistinguish, toMapTexture); } // ======================================================================= @@ -3241,9 +3249,12 @@ Standard_Boolean OpenGl_Context::CheckIsTransparent (const OpenGl_AspectFace* th theAlphaBack = aMatBackSrc .Alpha(); } - const bool isTransparent = theAlphaFront < 1.0f - || theAlphaBack < 1.0f; - return isTransparent; + if (anAspect->AlphaMode() == Graphic3d_AlphaMode_BlendAuto) + { + return theAlphaFront < 1.0f + || theAlphaBack < 1.0f; + } + return anAspect->AlphaMode() == Graphic3d_AlphaMode_Blend; } // ======================================================================= @@ -3752,3 +3763,32 @@ bool OpenGl_Context::SetColorMask (bool theToWriteColor) myColorMask = theToWriteColor; return anOldValue; } + +// ======================================================================= +// function : SetSampleAlphaToCoverage +// purpose : +// ======================================================================= +bool OpenGl_Context::SetSampleAlphaToCoverage (bool theToEnable) +{ + if (myAlphaToCoverage == theToEnable) + { + return myAlphaToCoverage; + } + + if (core15fwd != NULL) + { + if (theToEnable) + { + //core15fwd->core15fwd->glSampleCoverage (1.0f, GL_FALSE); + core15fwd->glEnable (GL_SAMPLE_ALPHA_TO_COVERAGE); + } + else + { + core15fwd->glDisable (GL_SAMPLE_ALPHA_TO_COVERAGE); + } + } + + const bool anOldValue = myAlphaToCoverage; + myAlphaToCoverage = theToEnable; + return anOldValue; +} diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index 353aa8de48..96ac2636ee 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -646,6 +646,12 @@ public: //! @name methods to alter or retrieve current state //! Enable/disable writing into color buffer (wrapper for glColorMask). Standard_EXPORT bool SetColorMask (bool theToWriteColor); + //! Return GL_SAMPLE_ALPHA_TO_COVERAGE state. + bool SampleAlphaToCoverage() const { return myAlphaToCoverage; } + + //! Enable/disable GL_SAMPLE_ALPHA_TO_COVERAGE. + Standard_EXPORT bool SetSampleAlphaToCoverage (bool theToEnable); + //! Return back face culling state. bool ToCullBackFaces() const { return myToCullBackFaces; } @@ -929,6 +935,7 @@ private: //! @name fields tracking current state OpenGl_DrawBuffers 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) + Standard_Boolean myAlphaToCoverage; //!< flag indicating GL_SAMPLE_ALPHA_TO_COVERAGE state Standard_Boolean myIsGlDebugCtx; //!< debug context initialization state TCollection_AsciiString myVendor; //!< Graphics Driver's vendor TColStd_PackedMapOfInteger myFilters[6]; //!< messages suppressing filter (for sources from GL_DEBUG_SOURCE_API_ARB to GL_DEBUG_SOURCE_OTHER_ARB) diff --git a/src/OpenGl/OpenGl_MaterialState.hxx b/src/OpenGl/OpenGl_MaterialState.hxx index 3781995534..daf59c8349 100644 --- a/src/OpenGl/OpenGl_MaterialState.hxx +++ b/src/OpenGl/OpenGl_MaterialState.hxx @@ -25,16 +25,18 @@ class OpenGl_MaterialState : public OpenGl_StateInterface public: //! Creates new material state. - OpenGl_MaterialState() : myToDistinguish (false), myToMapTexture (false) {} + OpenGl_MaterialState() : myAlphaCutoff (0.5f), myToDistinguish (false), myToMapTexture (false) {} //! Sets new material aspect. void Set (const OpenGl_Material& theFrontMat, const OpenGl_Material& theBackMat, + const float theAlphaCutoff, const bool theToDistinguish, const bool theToMapTexture) { myMatFront = theFrontMat; myMatBack = theBackMat; + myAlphaCutoff = theAlphaCutoff; myToDistinguish = theToDistinguish; myToMapTexture = theToMapTexture; } @@ -45,6 +47,9 @@ public: //! Return back material. const OpenGl_Material& BackMaterial() const { return myMatBack; } + //! Alpha cutoff value. + float AlphaCutoff() const { return myAlphaCutoff; } + //! Distinguish front/back flag. bool ToDistinguish() const { return myToDistinguish; } @@ -55,6 +60,7 @@ private: OpenGl_Material myMatFront; //!< front material OpenGl_Material myMatBack; //!< back material + float myAlphaCutoff; //!< alpha cutoff value bool myToDistinguish; //!< distinguish front/back flag bool myToMapTexture; //!< flag for mapping a texture diff --git a/src/OpenGl/OpenGl_PrimitiveArray.cxx b/src/OpenGl/OpenGl_PrimitiveArray.cxx index fa805f2168..71c96fe539 100644 --- a/src/OpenGl/OpenGl_PrimitiveArray.cxx +++ b/src/OpenGl/OpenGl_PrimitiveArray.cxx @@ -458,10 +458,8 @@ void OpenGl_PrimitiveArray::drawEdges (const OpenGl_Vec4& theEdgeCo if (aGlContext->core20fwd != NULL) { - aGlContext->ShaderManager()->BindLineProgram (NULL, - anAspect->Aspect()->Type(), - Graphic3d_TOSM_UNLIT, - Standard_False, + aGlContext->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), anAspect->Aspect()->Type(), + Graphic3d_TOSM_UNLIT, Graphic3d_AlphaMode_Opaque, Standard_False, anAspect->ShaderProgramRes (aGlContext)); } const GLenum aDrawMode = !aGlContext->ActiveProgram().IsNull() @@ -569,7 +567,14 @@ void OpenGl_PrimitiveArray::drawMarkers (const Handle(OpenGl_Workspace)& theWork #if !defined(GL_ES_VERSION_2_0) if (aCtx->core11 != NULL) { - aCtx->core11fwd->glDisable (GL_ALPHA_TEST); + if (aCtx->ShaderManager()->MaterialState().AlphaCutoff() >= ShortRealLast()) + { + aCtx->core11fwd->glDisable (GL_ALPHA_TEST); + } + else + { + aCtx->core11fwd->glAlphaFunc (GL_GEQUAL, aCtx->ShaderManager()->MaterialState().AlphaCutoff()); + } } #endif aCtx->SetPointSize (1.0f); @@ -775,11 +780,11 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace ? anAspectMarker->SpriteHighlightRes (aCtx) : aSpriteNormRes; aCtx->BindTextures (aSprite); - aCtx->ShaderManager()->BindMarkerProgram (aSprite, aShadingModel, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx)); + aCtx->ShaderManager()->BindMarkerProgram (aSprite, aShadingModel, Graphic3d_AlphaMode_Opaque, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx)); } else { - aCtx->ShaderManager()->BindMarkerProgram (Handle(OpenGl_TextureSet)(), aShadingModel, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx)); + aCtx->ShaderManager()->BindMarkerProgram (Handle(OpenGl_TextureSet)(), aShadingModel, Graphic3d_AlphaMode_Opaque, hasVertColor, anAspectMarker->ShaderProgramRes (aCtx)); } break; } @@ -790,6 +795,7 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace aCtx->ShaderManager()->BindLineProgram (NULL, anAspectLine->Aspect()->Type(), aShadingModel, + Graphic3d_AlphaMode_Opaque, hasVertColor, anAspectLine->ShaderProgramRes (aCtx)); break; @@ -801,6 +807,7 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace const Standard_Boolean toEnableEnvMap = (!aTextures.IsNull() && (aTextures == theWorkspace->EnvironmentTexture())); aCtx->ShaderManager()->BindFaceProgram (aTextures, aShadingModel, + anAspectFace->Aspect()->AlphaMode(), hasVertColor, toEnableEnvMap, anAspectFace->ShaderProgramRes (aCtx)); diff --git a/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx b/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx index d3b667fe37..f04c5471ff 100644 --- a/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx +++ b/src/OpenGl/OpenGl_SetOfShaderPrograms.hxx @@ -32,8 +32,9 @@ enum OpenGl_ProgramOptions OpenGl_PO_ClipPlanes1 = 0x040, //!< handle 1 clipping plane OpenGl_PO_ClipPlanes2 = 0x080, //!< handle 2 clipping planes OpenGl_PO_ClipPlanesN = 0x100, //!< handle N clipping planes - OpenGl_PO_WriteOit = 0x200, //!< write coverage buffer for Blended Order-Independent Transparency - OpenGl_PO_NB = 0x400 //!< overall number of combinations + OpenGl_PO_AlphaTest = 0x200, //!< discard fragment by alpha test (defined by cutoff value) + OpenGl_PO_WriteOit = 0x400, //!< write coverage buffer for Blended Order-Independent Transparency + OpenGl_PO_NB = 0x800 //!< overall number of combinations }; //! Alias to programs array of predefined length diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index 3ce8652a0c..a83169c8b1 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -1064,6 +1064,16 @@ void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram) return; } + if (myMaterialState.AlphaCutoff() < ShortRealLast()) + { + glAlphaFunc (GL_GEQUAL, myMaterialState.AlphaCutoff()); + glEnable (GL_ALPHA_TEST); + } + else + { + glDisable (GL_ALPHA_TEST); + } + const GLenum aFrontFace = myMaterialState.ToDistinguish() ? GL_FRONT : GL_FRONT_AND_BACK; myContext->core11->glMaterialfv(aFrontFace, GL_AMBIENT, aFrontMat.Ambient.GetData()); myContext->core11->glMaterialfv(aFrontFace, GL_DIFFUSE, aFrontMat.Diffuse.GetData()); @@ -1082,6 +1092,9 @@ void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram) return; } + theProgram->SetUniform (myContext, + theProgram->GetStateLocation (OpenGl_OCCT_ALPHA_CUTOFF), + myMaterialState.AlphaCutoff()); theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), myMaterialState.ToMapTexture() ? 1 : 0); @@ -1626,6 +1639,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha #endif aProgramSrc->SetNbLightsMax (0); aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); + aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert)); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag)); @@ -1952,6 +1966,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_S #endif aProgramSrc->SetNbLightsMax (aNbLights); aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); + aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert)); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag)); TCollection_AsciiString aKey; @@ -2131,6 +2146,7 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_Sha #endif aProgramSrc->SetNbLightsMax (aNbLights); aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes); + aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert)); aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag)); TCollection_AsciiString aKey; diff --git a/src/OpenGl/OpenGl_ShaderManager.hxx b/src/OpenGl/OpenGl_ShaderManager.hxx index 115f0673b4..17270303c7 100644 --- a/src/OpenGl/OpenGl_ShaderManager.hxx +++ b/src/OpenGl/OpenGl_ShaderManager.hxx @@ -84,6 +84,7 @@ public: //! Bind program for filled primitives rendering Standard_Boolean BindFaceProgram (const Handle(OpenGl_TextureSet)& theTextures, const Graphic3d_TypeOfShadingModel theShadingModel, + const Graphic3d_AlphaMode theAlphaMode, const Standard_Boolean theHasVertColor, const Standard_Boolean theEnableEnvMap, const Handle(OpenGl_ShaderProgram)& theCustomProgram) @@ -98,7 +99,7 @@ public: && (theTextures.IsNull() || theTextures->IsModulate()) ? theShadingModel : Graphic3d_TOSM_UNLIT; - const Standard_Integer aBits = getProgramBits (theTextures, theHasVertColor, theEnableEnvMap); + const Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, theHasVertColor, theEnableEnvMap); Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (aShadeModelOnFace, aBits); return bindProgramWithState (aProgram); } @@ -107,6 +108,7 @@ public: Standard_Boolean BindLineProgram (const Handle(OpenGl_TextureSet)& theTextures, const Aspect_TypeOfLine theLineType, const Graphic3d_TypeOfShadingModel theShadingModel, + const Graphic3d_AlphaMode theAlphaMode, const Standard_Boolean theHasVertColor, const Handle(OpenGl_ShaderProgram)& theCustomProgram) { @@ -116,7 +118,7 @@ public: return bindProgramWithState (theCustomProgram); } - Standard_Integer aBits = getProgramBits (theTextures, theHasVertColor); + Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, theHasVertColor, false); if (theLineType != Aspect_TOL_SOLID) { aBits |= OpenGl_PO_StippleLine; @@ -129,6 +131,7 @@ public: //! Bind program for point rendering Standard_Boolean BindMarkerProgram (const Handle(OpenGl_TextureSet)& theTextures, const Graphic3d_TypeOfShadingModel theShadingModel, + const Graphic3d_AlphaMode theAlphaMode, const Standard_Boolean theHasVertColor, const Handle(OpenGl_ShaderProgram)& theCustomProgram) { @@ -138,7 +141,7 @@ public: return bindProgramWithState (theCustomProgram); } - const Standard_Integer aBits = getProgramBits (theTextures, theHasVertColor) | OpenGl_PO_Point; + const Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, theHasVertColor, false) | OpenGl_PO_Point; Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theShadingModel, aBits); return bindProgramWithState (aProgram); } @@ -267,10 +270,11 @@ public: //! Updates state of material. void UpdateMaterialStateTo (const OpenGl_Material& theFrontMat, const OpenGl_Material& theBackMat, + const float theAlphaCutoff, const bool theToDistinguish, const bool theToMapTexture) { - myMaterialState.Set (theFrontMat, theBackMat, theToDistinguish, theToMapTexture); + myMaterialState.Set (theFrontMat, theBackMat, theAlphaCutoff, theToDistinguish, theToMapTexture); myMaterialState.Update(); } @@ -392,11 +396,16 @@ protected: //! Define program bits. Standard_Integer getProgramBits (const Handle(OpenGl_TextureSet)& theTextures, - const Standard_Boolean theHasVertColor, - const Standard_Boolean theEnableEnvMap = Standard_False) + Graphic3d_AlphaMode theAlphaMode, + Standard_Boolean theHasVertColor, + Standard_Boolean theEnableEnvMap) { Standard_Integer aBits = 0; + if (theAlphaMode == Graphic3d_AlphaMode_Mask) + { + aBits |= OpenGl_PO_AlphaTest; + } const Standard_Integer aNbPlanes = myContext->Clipping().NbClippingOrCappingOn(); if (aNbPlanes > 0) diff --git a/src/OpenGl/OpenGl_ShaderProgram.cxx b/src/OpenGl/OpenGl_ShaderProgram.cxx index 1463fee9c5..784dc528ab 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.cxx +++ b/src/OpenGl/OpenGl_ShaderProgram.cxx @@ -67,6 +67,7 @@ Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] = "occDistinguishingMode", // OpenGl_OCCT_DISTINGUISH_MODE "occFrontMaterial", // OpenGl_OCCT_FRONT_MATERIAL "occBackMaterial", // OpenGl_OCCT_BACK_MATERIAL + "occAlphaCutoff", // OpenGl_OCCT_ALPHA_CUTOFF "occColor", // OpenGl_OCCT_COLOR "occOitOutput", // OpenGl_OCCT_OIT_OUTPUT @@ -152,6 +153,7 @@ OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram myNbLightsMax (0), myNbClipPlanesMax (0), myNbFragOutputs (1), + myHasAlphaTest (false), myHasWeightOitOutput (false), myHasTessShader (false) { @@ -183,6 +185,7 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& } myHasTessShader = (aShaderMask & (Graphic3d_TOS_TESS_CONTROL | Graphic3d_TOS_TESS_EVALUATION)) != 0; myNbFragOutputs = !myProxy.IsNull() ? myProxy->NbFragmentOutputs() : 1; + myHasAlphaTest = !myProxy.IsNull() && myProxy->HasAlphaTest(); myHasWeightOitOutput = !myProxy.IsNull() ? myProxy->HasWeightOitOutput() && myNbFragOutputs >= 2 : 1; // detect the minimum GLSL version required for defined Shader Objects @@ -308,6 +311,10 @@ Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& } } } + if (myHasAlphaTest) + { + anExtensions += "#define OCC_ALPHA_TEST\n"; + } if (theCtx->hasSampleVariables == OpenGl_FeatureInExtensions) { diff --git a/src/OpenGl/OpenGl_ShaderProgram.hxx b/src/OpenGl/OpenGl_ShaderProgram.hxx index 86a239c4ea..87941ff0b3 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.hxx +++ b/src/OpenGl/OpenGl_ShaderProgram.hxx @@ -63,6 +63,7 @@ enum OpenGl_StateVariable OpenGl_OCCT_DISTINGUISH_MODE, OpenGl_OCCT_FRONT_MATERIAL, OpenGl_OCCT_BACK_MATERIAL, + OpenGl_OCCT_ALPHA_CUTOFF, OpenGl_OCCT_COLOR, // Weighted, Blended Order-Independent Transparency rendering state @@ -230,6 +231,9 @@ public: //! to be used for initialization occFragColorArray/occFragColorN. Standard_Integer NbFragmentOutputs() const { return myNbFragOutputs; } + //! 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; } @@ -577,6 +581,7 @@ protected: Standard_Integer myNbLightsMax; //!< length of array of light sources (THE_MAX_LIGHTS) 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_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 diff --git a/src/OpenGl/OpenGl_Text.cxx b/src/OpenGl/OpenGl_Text.cxx index 233d64d667..9f162cc35b 100644 --- a/src/OpenGl/OpenGl_Text.cxx +++ b/src/OpenGl/OpenGl_Text.cxx @@ -453,11 +453,12 @@ void OpenGl_Text::StringSize (const Handle(OpenGl_Context)& theCtx, // ======================================================================= void OpenGl_Text::Render (const Handle(OpenGl_Workspace)& theWorkspace) const { + theWorkspace->SetAspectFace (&theWorkspace->FontFaceAspect()); + theWorkspace->ApplyAspectFace(); const OpenGl_AspectText* aTextAspect = theWorkspace->ApplyAspectText(); const Handle(OpenGl_Context)& aCtx = theWorkspace->GetGlContext(); const Handle(OpenGl_TextureSet) aPrevTexture = aCtx->BindTextures (Handle(OpenGl_TextureSet)()); - // Bind custom shader program or generate default version aCtx->ShaderManager()->BindFontProgram (aTextAspect->ShaderProgramRes (aCtx)); @@ -757,8 +758,10 @@ void OpenGl_Text::drawRect (const Handle(OpenGl_Context)& theCtx, myBndVertsVbo->Init (theCtx, 2, 4, aQuad[0].GetData()); } - // bind flat program - theCtx->ShaderManager()->BindFaceProgram (Handle(OpenGl_TextureSet)(), Graphic3d_TOSM_UNLIT, Standard_False, Standard_False, Handle(OpenGl_ShaderProgram)()); + // bind unlit program + theCtx->ShaderManager()->BindFaceProgram (Handle(OpenGl_TextureSet)(), Graphic3d_TOSM_UNLIT, + Graphic3d_AlphaMode_Opaque, Standard_False, Standard_False, + Handle(OpenGl_ShaderProgram)()); #if !defined(GL_ES_VERSION_2_0) if (theCtx->core11 != NULL @@ -901,10 +904,6 @@ void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx, GLint aTexEnvParam = GL_REPLACE; if (theCtx->core11 != NULL) { - // setup alpha test - glAlphaFunc (GL_GEQUAL, 0.285f); - glEnable (GL_ALPHA_TEST); - glDisable (GL_TEXTURE_1D); glEnable (GL_TEXTURE_2D); glGetTexEnviv (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &aTexEnvParam); @@ -918,6 +917,7 @@ void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx, // setup blending glEnable (GL_BLEND); glBlendFunc (GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + const bool anAlphaToCoverageOld = theCtx->SetSampleAlphaToCoverage (false); // extra drawings switch (theTextAspect.Aspect()->DisplayType()) @@ -994,7 +994,6 @@ void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx, if (theCtx->core11 != NULL) { glDisable (GL_TEXTURE_2D); - glDisable (GL_ALPHA_TEST); } #endif const bool aColorMaskBack = theCtx->SetColorMask (false); @@ -1015,15 +1014,12 @@ void OpenGl_Text::render (const Handle(OpenGl_Context)& theCtx, glDisable (GL_BLEND); glDisable (GL_STENCIL_TEST); #if !defined(GL_ES_VERSION_2_0) - if (theCtx->core11 != NULL) - { - glDisable (GL_ALPHA_TEST); - } glDisable (GL_COLOR_LOGIC_OP); theCtx->SetPolygonMode (aPrevPolygonMode); theCtx->SetPolygonHatchEnabled (aPrevHatchingMode); #endif + theCtx->SetSampleAlphaToCoverage (anAlphaToCoverageOld); // model view matrix was modified theCtx->WorldViewState.Pop(); diff --git a/src/OpenGl/OpenGl_View_Redraw.cxx b/src/OpenGl/OpenGl_View_Redraw.cxx index 418f356b1a..d499839e4d 100644 --- a/src/OpenGl/OpenGl_View_Redraw.cxx +++ b/src/OpenGl/OpenGl_View_Redraw.cxx @@ -869,6 +869,7 @@ void OpenGl_View::render (Graphic3d_Camera::Projection theProjection, // ================================== const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext(); + aContext->SetSampleAlphaToCoverage (myRenderParams.ToEnableAlphaToCoverage); #if !defined(GL_ES_VERSION_2_0) // Disable current clipping planes @@ -1032,6 +1033,9 @@ void OpenGl_View::render (Graphic3d_Camera::Projection theProjection, renderFrameStats(); } + myWorkspace->ResetAppliedAspect(); + aContext->SetSampleAlphaToCoverage (false); + // reset FFP state for safety aContext->BindProgram (Handle(OpenGl_ShaderProgram)()); if (aContext->caps->ffpEnable) diff --git a/src/OpenGl/OpenGl_Workspace.cxx b/src/OpenGl/OpenGl_Workspace.cxx index 3f74b0633a..10e0ac40de 100644 --- a/src/OpenGl/OpenGl_Workspace.cxx +++ b/src/OpenGl/OpenGl_Workspace.cxx @@ -169,10 +169,16 @@ OpenGl_Workspace::OpenGl_Workspace (OpenGl_View* theView, const Handle(OpenGl_Wi myDefaultCappingAlgoFilter = new OpenGl_CappingAlgoFilter(); + myFontFaceAspect.Aspect()->SetAlphaMode (Graphic3d_AlphaMode_Mask, 0.285f); + myFontFaceAspect.Aspect()->SetShadingModel (Graphic3d_TOSM_UNLIT); + myNoneCulling .Aspect()->SetSuppressBackFaces (false); myNoneCulling .Aspect()->SetDrawEdges (false); + myNoneCulling .Aspect()->SetAlphaMode (Graphic3d_AlphaMode_Opaque); + myFrontCulling.Aspect()->SetSuppressBackFaces (true); myFrontCulling.Aspect()->SetDrawEdges (false); + myFrontCulling.Aspect()->SetAlphaMode (Graphic3d_AlphaMode_Opaque); } // ======================================================================= @@ -296,7 +302,10 @@ const OpenGl_AspectFace* OpenGl_Workspace::ApplyAspectFace() } if (toSuppressBackFaces) { - if ((float )myAspectFaceSet->Aspect()->FrontMaterial().Transparency() != 0.0f) + if (myAspectFaceSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Blend + || myAspectFaceSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Mask + || (myAspectFaceSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_BlendAuto + && myAspectFaceSet->Aspect()->FrontMaterial().Transparency() != 0.0f)) { // disable culling in case of translucent shading aspect toSuppressBackFaces = false; diff --git a/src/OpenGl/OpenGl_Workspace.hxx b/src/OpenGl/OpenGl_Workspace.hxx index 0a59ff01c1..4a3e602471 100644 --- a/src/OpenGl/OpenGl_Workspace.hxx +++ b/src/OpenGl/OpenGl_Workspace.hxx @@ -257,23 +257,17 @@ public: //! @return applied model structure matrix. inline const OpenGl_Matrix* ModelMatrix() const { return StructureMatrix_applied; } + //! Returns face aspect for textured font rendering. + const OpenGl_AspectFace& FontFaceAspect() const { return myFontFaceAspect; } + //! Returns capping algorithm rendering filter. - const Handle(OpenGl_CappingAlgoFilter)& DefaultCappingAlgoFilter() const - { - return myDefaultCappingAlgoFilter; - } + const Handle(OpenGl_CappingAlgoFilter)& DefaultCappingAlgoFilter() const { return myDefaultCappingAlgoFilter; } //! Returns face aspect for none culling mode. - const OpenGl_AspectFace& NoneCulling() const - { - return myNoneCulling; - } + const OpenGl_AspectFace& NoneCulling() const { return myNoneCulling; } //! Returns face aspect for front face culling mode. - const OpenGl_AspectFace& FrontCulling() const - { - return myFrontCulling; - } + const OpenGl_AspectFace& FrontCulling() const { return myFrontCulling; } //! Sets a new environment texture. void SetEnvironmentTexture (const Handle(OpenGl_TextureSet)& theTexture) { myEnvironmentTexture = theTexture; } @@ -291,6 +285,7 @@ protected: //! @name protected fields Handle(OpenGl_CappingAlgoFilter) myDefaultCappingAlgoFilter; OpenGl_AspectFace myNoneCulling; OpenGl_AspectFace myFrontCulling; + OpenGl_AspectFace myFontFaceAspect; protected: //! @name fields related to status diff --git a/src/Shaders/Declarations.glsl b/src/Shaders/Declarations.glsl index 0f5ba703b8..a3b7e12d29 100644 --- a/src/Shaders/Declarations.glsl +++ b/src/Shaders/Declarations.glsl @@ -168,6 +168,7 @@ uniform float occPointSize; //!< point size //! Parameters of blended order-independent transparency rendering algorithm uniform int occOitOutput; //!< Enable bit for writing output color buffers for OIT (occFragColor, occFragCoverage) uniform float occOitDepthFactor; //!< Influence of the depth component to the coverage of the accumulated fragment +uniform float occAlphaCutoff; //!< alpha test cutoff value //! Parameters of clipping planes #if defined(THE_MAX_CLIP_PLANES) && (THE_MAX_CLIP_PLANES > 0) diff --git a/src/Shaders/DeclarationsImpl.glsl b/src/Shaders/DeclarationsImpl.glsl index d3b16429f7..34bf584e8c 100644 --- a/src/Shaders/DeclarationsImpl.glsl +++ b/src/Shaders/DeclarationsImpl.glsl @@ -16,18 +16,20 @@ // This file includes implementation of common functions and properties accessors #if defined(FRAGMENT_SHADER) -#if defined(OCC_WRITE_WEIGHT_OIT_COVERAGE) -//! Output color and coverage for accumulation by OIT algorithm. +//! Output color (and coverage for accumulation by OIT algorithm). void occSetFragColor (in vec4 theColor) { +#if defined(OCC_ALPHA_TEST) + if (theColor.a < occAlphaCutoff) discard; +#endif +#if defined(OCC_WRITE_WEIGHT_OIT_COVERAGE) 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); -} #else -//! Output color. -void occSetFragColor (in vec4 theColor) { occFragColor = theColor; } + occFragColor = theColor; #endif +} #endif #if defined(THE_MAX_LIGHTS) && (THE_MAX_LIGHTS > 0) diff --git a/src/Shaders/Shaders_DeclarationsImpl_glsl.pxx b/src/Shaders/Shaders_DeclarationsImpl_glsl.pxx index 4ff75929a5..796b4e792d 100644 --- a/src/Shaders/Shaders_DeclarationsImpl_glsl.pxx +++ b/src/Shaders/Shaders_DeclarationsImpl_glsl.pxx @@ -19,18 +19,20 @@ static const char Shaders_DeclarationsImpl_glsl[] = "// This file includes implementation of common functions and properties accessors\n" "\n" "#if defined(FRAGMENT_SHADER)\n" - "#if defined(OCC_WRITE_WEIGHT_OIT_COVERAGE)\n" - "//! Output color and coverage for accumulation by OIT algorithm.\n" + "//! Output color (and coverage for accumulation by OIT algorithm).\n" "void occSetFragColor (in vec4 theColor)\n" "{\n" + "#if defined(OCC_ALPHA_TEST)\n" + " if (theColor.a < occAlphaCutoff) discard;\n" + "#endif\n" + "#if defined(OCC_WRITE_WEIGHT_OIT_COVERAGE)\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" - "}\n" "#else\n" - "//! Output color.\n" - "void occSetFragColor (in vec4 theColor) { occFragColor = theColor; }\n" + " occFragColor = theColor;\n" "#endif\n" + "}\n" "#endif\n" "\n" "#if defined(THE_MAX_LIGHTS) && (THE_MAX_LIGHTS > 0)\n" diff --git a/src/Shaders/Shaders_Declarations_glsl.pxx b/src/Shaders/Shaders_Declarations_glsl.pxx index cec68050b4..ed3045e3b9 100644 --- a/src/Shaders/Shaders_Declarations_glsl.pxx +++ b/src/Shaders/Shaders_Declarations_glsl.pxx @@ -171,6 +171,7 @@ static const char Shaders_Declarations_glsl[] = "//! Parameters of blended order-independent transparency rendering algorithm\n" "uniform int occOitOutput; //!< Enable bit for writing output color buffers for OIT (occFragColor, occFragCoverage)\n" "uniform float occOitDepthFactor; //!< Influence of the depth component to the coverage of the accumulated fragment\n" + "uniform float occAlphaCutoff; //!< alpha test cutoff value\n" "\n" "//! Parameters of clipping planes\n" "#if defined(THE_MAX_CLIP_PLANES) && (THE_MAX_CLIP_PLANES > 0)\n" diff --git a/src/ViewerTest/ViewerTest.cxx b/src/ViewerTest/ViewerTest.cxx index 4f0b48e348..6859350fa6 100644 --- a/src/ViewerTest/ViewerTest.cxx +++ b/src/ViewerTest/ViewerTest.cxx @@ -1694,6 +1694,10 @@ struct ViewerTest_AspectsChangeSet Standard_Integer ToSetTransparency; Standard_Real Transparency; + Standard_Integer ToSetAlphaMode; + Graphic3d_AlphaMode AlphaMode; + Standard_ShortReal AlphaCutoff; + Standard_Integer ToSetMaterial; Graphic3d_NameOfMaterial Material; TCollection_AsciiString MatName; @@ -1739,6 +1743,9 @@ struct ViewerTest_AspectsChangeSet MarkerSize (1.0), ToSetTransparency (0), Transparency (0.0), + ToSetAlphaMode (0), + AlphaMode (Graphic3d_AlphaMode_BlendAuto), + AlphaCutoff (0.5f), ToSetMaterial (0), Material (Graphic3d_NOM_DEFAULT), ToSetShowFreeBoundary (0), @@ -1764,6 +1771,7 @@ struct ViewerTest_AspectsChangeSet return ToSetVisibility == 0 && ToSetLineWidth == 0 && ToSetTransparency == 0 + && ToSetAlphaMode == 0 && ToSetColor == 0 && ToSetMaterial == 0 && ToSetShowFreeBoundary == 0 @@ -1797,11 +1805,17 @@ struct ViewerTest_AspectsChangeSet isOk = Standard_False; } if (theIsSubPart - && ToSetTransparency) + && ToSetTransparency != 0) { std::cout << "Error: the transparency can not be defined for sub-part of object!\n"; isOk = Standard_False; } + if (ToSetAlphaMode == 1 + && (AlphaCutoff <= 0.0f || AlphaCutoff >= 1.0f)) + { + std::cout << "Error: alpha cutoff value should be within (0; 1) range (specified " << AlphaCutoff << ")\n"; + isOk = Standard_False; + } if (ToSetMaterial == 1 && Material == Graphic3d_NOM_DEFAULT) { @@ -2047,6 +2061,53 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/, aChangeSet->Transparency = 0.0; } } + else if (anArg == "-setalphamode") + { + if (++anArgIter >= theArgNb) + { + std::cout << "Error: wrong syntax at " << anArg << "\n"; + return 1; + } + aChangeSet->ToSetAlphaMode = 1; + aChangeSet->AlphaCutoff = 0.5f; + { + TCollection_AsciiString aParam (theArgVec[anArgIter]); + aParam.LowerCase(); + if (aParam == "opaque") + { + aChangeSet->AlphaMode = Graphic3d_AlphaMode_Opaque; + } + else if (aParam == "mask") + { + aChangeSet->AlphaMode = Graphic3d_AlphaMode_Mask; + } + else if (aParam == "blend") + { + aChangeSet->AlphaMode = Graphic3d_AlphaMode_Blend; + } + else if (aParam == "blendauto" + || aParam == "auto") + { + aChangeSet->AlphaMode = Graphic3d_AlphaMode_BlendAuto; + } + else + { + std::cout << "Error: wrong syntax at " << aParam << "\n"; + return 1; + } + } + + if (anArgIter + 1 < theArgNb + && theArgVec[anArgIter + 1][0] != '-') + { + TCollection_AsciiString aParam2 (theArgVec[anArgIter + 1]); + if (aParam2.IsRealValue()) + { + aChangeSet->AlphaCutoff = (float )aParam2.RealValue(); + ++anArgIter; + } + } + } else if (anArg == "-setvis" || anArg == "-setvisibility") { @@ -2376,6 +2437,9 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/, aChangeSet->MarkerSize = 1.0; aChangeSet->ToSetTransparency = -1; aChangeSet->Transparency = 0.0; + aChangeSet->ToSetAlphaMode = -1; + aChangeSet->AlphaMode = Graphic3d_AlphaMode_BlendAuto; + aChangeSet->AlphaCutoff = 0.5f; aChangeSet->ToSetColor = -1; aChangeSet->Color = DEFAULT_COLOR; aChangeSet->ToSetMaterial = -1; @@ -2565,6 +2629,10 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/, { aDrawer->ShadingAspect()->SetTransparency (aChangeSet->Transparency); } + if (aChangeSet->ToSetAlphaMode != 0) + { + aDrawer->ShadingAspect()->Aspect()->SetAlphaMode (aChangeSet->AlphaMode, aChangeSet->AlphaCutoff); + } if (aChangeSet->ToSetMaterial != 0) { aDrawer->ShadingAspect()->SetMaterial (aChangeSet->Material); @@ -2797,6 +2865,16 @@ static Standard_Integer VAspects (Draw_Interpretor& /*theDI*/, aDrawer->SetShadingModel ((aChangeSet->ToSetShadingModel == -1) ? Graphic3d_TOSM_DEFAULT : aChangeSet->ShadingModel, aChangeSet->ToSetShadingModel != -1); toRedisplay = Standard_True; } + if (aChangeSet->ToSetAlphaMode != 0) + { + if (!aDrawer->HasOwnShadingAspect()) + { + aDrawer->SetShadingAspect (new Prs3d_ShadingAspect()); + *aDrawer->ShadingAspect()->Aspect() = *aCtx->DefaultDrawer()->ShadingAspect()->Aspect(); + } + aDrawer->ShadingAspect()->Aspect()->SetAlphaMode (aChangeSet->AlphaMode, aChangeSet->AlphaCutoff); + toRedisplay = Standard_True; + } } for (aChangesIter.Next(); aChangesIter.More(); aChangesIter.Next()) @@ -6340,6 +6418,7 @@ void ViewerTest::Commands(Draw_Interpretor& theCommands) "\n\t\t: [-setHatch HatchStyle]" "\n\t\t: [-setShadingModel {color|flat|gouraud|phong}]" "\n\t\t: [-unsetShadingModel]" + "\n\t\t: [-setAlphaMode {opaque|mask|blend|blendauto} [alphaCutOff=0.5]]" "\n\t\t: Manage presentation properties of all, selected or named objects." "\n\t\t: When -subshapes is specified than following properties will be" "\n\t\t: assigned to specified sub-shapes." diff --git a/src/ViewerTest/ViewerTest_OpenGlCommands.cxx b/src/ViewerTest/ViewerTest_OpenGlCommands.cxx index 4779be62bc..df4d7266f1 100644 --- a/src/ViewerTest/ViewerTest_OpenGlCommands.cxx +++ b/src/ViewerTest/ViewerTest_OpenGlCommands.cxx @@ -164,7 +164,9 @@ void VUserDrawObj::Render(const Handle(OpenGl_Workspace)& theWorkspace) const aTA->Aspect()->Font(); OpenGl_Vec4 aColor = theWorkspace->LineColor(); - aCtx->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), Aspect_TOL_SOLID, Graphic3d_TOSM_UNLIT, false, Handle(OpenGl_ShaderProgram)()); + aCtx->ShaderManager()->BindLineProgram (Handle(OpenGl_TextureSet)(), Aspect_TOL_SOLID, + Graphic3d_TOSM_UNLIT, Graphic3d_AlphaMode_Opaque, false, + Handle(OpenGl_ShaderProgram)()); aCtx->SetColor4fv (aColor); const OpenGl_Vec3 aVertArray[4] = diff --git a/src/ViewerTest/ViewerTest_ViewerCommands.cxx b/src/ViewerTest/ViewerTest_ViewerCommands.cxx index d32bf4a64f..1c1edadafc 100644 --- a/src/ViewerTest/ViewerTest_ViewerCommands.cxx +++ b/src/ViewerTest/ViewerTest_ViewerCommands.cxx @@ -10067,6 +10067,7 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI, theDI << "\n"; } theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass ? "on" : "off") << "\n"; + theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage ? "on" : "off") << "\n"; theDI << "\n"; return 0; } @@ -10212,6 +10213,21 @@ static Standard_Integer VRenderParams (Draw_Interpretor& theDI, ++anArgIter; } } + else if (aFlag == "-samplealphatocoverage" + || aFlag == "-alphatocoverage") + { + if (toPrint) + { + theDI << (aParams.ToEnableAlphaToCoverage ? "on " : "off "); + continue; + } + aParams.ToEnableAlphaToCoverage = Standard_True; + if (anArgIter + 1 < theArgNb + && ViewerTest::ParseOnOff (theArgVec[anArgIter + 1], aParams.ToEnableAlphaToCoverage)) + { + ++anArgIter; + } + } else if (aFlag == "-rendscale" || aFlag == "-renderscale" || aFlag == "-renderresolutionscale") @@ -12201,6 +12217,7 @@ void ViewerTest::ViewerCommands(Draw_Interpretor& theCommands) "\n '-msaa 0..4' Specifies number of samples for MSAA" "\n '-oit off|0.0-1.0' Enables/disables OIT and sets depth weight factor" "\n '-depthPrePass on|off' Enables/disables depth pre-pass" + "\n '-alphatocoverage on|off' Enables/disables alpha to coverage (needs MSAA)" "\n '-rendScale value Rendering resolution scale factor" "\n '-rayTrace' Enables GPU ray-tracing" "\n '-rayDepth 0..10' Defines maximum ray-tracing depth" diff --git a/tests/v3d/glsl/alpha_mask b/tests/v3d/glsl/alpha_mask new file mode 100644 index 0000000000..1cfc0bb274 --- /dev/null +++ b/tests/v3d/glsl/alpha_mask @@ -0,0 +1,38 @@ +puts "========" +puts "Alpha test modes" +puts "========" + +# create box +box b 1 2 3 + +# draw box +vinit View1 +vclear +vzbufftrihedron +vaxo +vdisplay -dispMode 1 b +vfit +vtexture b [locate_data_file images/marker_box2.png] +vrotate 0.2 0.0 0.0 +vaspects -setAlphaMode mask 0.5 +vmoveto 250 250 + +# take snapshots +vrenderparams -msaa 0 -alphaToCoverage 0 +vcaps -ffp 1 +vdump $::imagedir/${::casename}_msaa0_ffp.png + +vcaps -ffp 0 +vdump $::imagedir/${::casename}_msaa0.png + +vrenderparams -msaa 2 -alphaToCoverage 0 +vdump $::imagedir/${::casename}_msaa2.png + +vrenderparams -msaa 2 -alphaToCoverage 1 +vdump $::imagedir/${::casename}_msaa2_cov.png + +vrenderparams -msaa 8 -alphaToCoverage 1 +vdump $::imagedir/${::casename}_msaa8.png + +vrenderparams -msaa 8 -alphaToCoverage 1 +vdump $::imagedir/${::casename}_msaa8_cov.png