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);
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);
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));
+Graphic3d_AlphaMode.hxx
Graphic3d_ArrayOfPoints.hxx
Graphic3d_ArrayOfPolygons.hxx
Graphic3d_ArrayOfPolylines.hxx
--- /dev/null
+// 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
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)()),
myEdgeColor (theEdgeColor),
myInteriorStyle (theInteriorStyle),
myShadingModel (Graphic3d_TOSM_DEFAULT),
+ myAlphaMode (Graphic3d_AlphaMode_BlendAuto),
+ myAlphaCutoff (0.5f),
myEdgeType (theEdgeLineType),
myEdgeWidth ((float )theEdgeLineWidth),
myHatchStyle (Handle(Graphic3d_HatchStyle)()),
#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>
//! 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(); }
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;
NbMsaaSamples (0),
RenderResolutionScale (1.0f),
ToEnableDepthPrepass (Standard_False),
+ ToEnableAlphaToCoverage (Standard_False),
// ray tracing parameters
IsGlobalIlluminationEnabled (Standard_False),
RaytracingDepth (THE_DEFAULT_DEPTH),
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)
: 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_")
//! 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; }
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
};
myDrawBuffers (1),
myDefaultVao (0),
myColorMask (true),
+ myAlphaToCoverage (false),
myIsGlDebugCtx (Standard_False),
myResolution (Graphic3d_RenderingParams::THE_DEFAULT_RESOLUTION),
myResolutionRatio (1.0f),
// 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);
}
// =======================================================================
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;
}
// =======================================================================
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;
+}
//! 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; }
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)
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;
}
//! 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; }
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
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()
#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);
? 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;
}
aCtx->ShaderManager()->BindLineProgram (NULL,
anAspectLine->Aspect()->Type(),
aShadingModel,
+ Graphic3d_AlphaMode_Opaque,
hasVertColor,
anAspectLine->ShaderProgramRes (aCtx));
break;
const Standard_Boolean toEnableEnvMap = (!aTextures.IsNull() && (aTextures == theWorkspace->EnvironmentTexture()));
aCtx->ShaderManager()->BindFaceProgram (aTextures,
aShadingModel,
+ anAspectFace->Aspect()->AlphaMode(),
hasVertColor,
toEnableEnvMap,
anAspectFace->ShaderProgramRes (aCtx));
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
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());
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);
#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));
#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;
#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;
//! 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)
&& (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);
}
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)
{
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;
//! 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)
{
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);
}
//! 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();
}
//! 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)
"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
myNbLightsMax (0),
myNbClipPlanesMax (0),
myNbFragOutputs (1),
+ myHasAlphaTest (false),
myHasWeightOitOutput (false),
myHasTessShader (false)
{
}
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
}
}
}
+ if (myHasAlphaTest)
+ {
+ anExtensions += "#define OCC_ALPHA_TEST\n";
+ }
if (theCtx->hasSampleVariables == OpenGl_FeatureInExtensions)
{
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
//! 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; }
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
// =======================================================================
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));
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
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);
// 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())
if (theCtx->core11 != NULL)
{
glDisable (GL_TEXTURE_2D);
- glDisable (GL_ALPHA_TEST);
}
#endif
const bool aColorMaskBack = theCtx->SetColorMask (false);
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();
// ==================================
const Handle(OpenGl_Context)& aContext = myWorkspace->GetGlContext();
+ aContext->SetSampleAlphaToCoverage (myRenderParams.ToEnableAlphaToCoverage);
#if !defined(GL_ES_VERSION_2_0)
// Disable current clipping planes
renderFrameStats();
}
+ myWorkspace->ResetAppliedAspect();
+ aContext->SetSampleAlphaToCoverage (false);
+
// reset FFP state for safety
aContext->BindProgram (Handle(OpenGl_ShaderProgram)());
if (aContext->caps->ffpEnable)
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);
}
// =======================================================================
}
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;
//! @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; }
Handle(OpenGl_CappingAlgoFilter) myDefaultCappingAlgoFilter;
OpenGl_AspectFace myNoneCulling;
OpenGl_AspectFace myFrontCulling;
+ OpenGl_AspectFace myFontFaceAspect;
protected: //! @name fields related to status
//! 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)
// 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)
"// 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"
"//! 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"
Standard_Integer ToSetTransparency;
Standard_Real Transparency;
+ Standard_Integer ToSetAlphaMode;
+ Graphic3d_AlphaMode AlphaMode;
+ Standard_ShortReal AlphaCutoff;
+
Standard_Integer ToSetMaterial;
Graphic3d_NameOfMaterial Material;
TCollection_AsciiString MatName;
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),
return ToSetVisibility == 0
&& ToSetLineWidth == 0
&& ToSetTransparency == 0
+ && ToSetAlphaMode == 0
&& ToSetColor == 0
&& ToSetMaterial == 0
&& ToSetShowFreeBoundary == 0
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)
{
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")
{
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;
{
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);
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())
"\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."
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] =
theDI << "\n";
}
theDI << "depth pre-pass: " << (aParams.ToEnableDepthPrepass ? "on" : "off") << "\n";
+ theDI << "alpha to coverage: " << (aParams.ToEnableAlphaToCoverage ? "on" : "off") << "\n";
theDI << "\n";
return 0;
}
++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")
"\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"
--- /dev/null
+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