diff --git a/src/BinMXCAFDoc/BinMXCAFDoc_VisMaterialDriver.cxx b/src/BinMXCAFDoc/BinMXCAFDoc_VisMaterialDriver.cxx index 7e18a19043..b6f8031978 100644 --- a/src/BinMXCAFDoc/BinMXCAFDoc_VisMaterialDriver.cxx +++ b/src/BinMXCAFDoc/BinMXCAFDoc_VisMaterialDriver.cxx @@ -54,6 +54,7 @@ static Standard_Byte faceCullToChar (Graphic3d_TypeOfBackfacingModel theMode) { case Graphic3d_TypeOfBackfacingModel_Auto: return '0'; case Graphic3d_TypeOfBackfacingModel_BackCulled: return 'B'; + case Graphic3d_TypeOfBackfacingModel_FrontCulled: return 'F'; case Graphic3d_TypeOfBackfacingModel_DoubleSided: return '1'; } return '0'; @@ -66,6 +67,7 @@ static Graphic3d_TypeOfBackfacingModel faceCullFromChar (Standard_Byte theMode) { case '0': return Graphic3d_TypeOfBackfacingModel_Auto; case 'B': return Graphic3d_TypeOfBackfacingModel_BackCulled; + case 'F': return Graphic3d_TypeOfBackfacingModel_FrontCulled; case '1': return Graphic3d_TypeOfBackfacingModel_DoubleSided; } return Graphic3d_TypeOfBackfacingModel_Auto; diff --git a/src/Graphic3d/Graphic3d_TypeOfBackfacingModel.hxx b/src/Graphic3d/Graphic3d_TypeOfBackfacingModel.hxx index aae849b5cd..20e7b8a0a5 100644 --- a/src/Graphic3d/Graphic3d_TypeOfBackfacingModel.hxx +++ b/src/Graphic3d/Graphic3d_TypeOfBackfacingModel.hxx @@ -23,7 +23,8 @@ enum Graphic3d_TypeOfBackfacingModel Graphic3d_TypeOfBackfacingModel_Auto, //!< automatic back face culling enabled for opaque groups with closed flag //! (e.g. solids, see Graphic3d_Group::IsClosed()) Graphic3d_TypeOfBackfacingModel_DoubleSided, //!< no culling (double-sided shading) - Graphic3d_TypeOfBackfacingModel_BackCulled, //!< back face culling + Graphic3d_TypeOfBackfacingModel_BackCulled, //!< back face culling + Graphic3d_TypeOfBackfacingModel_FrontCulled, //!< front face culling // old aliases Graphic3d_TOBM_AUTOMATIC = Graphic3d_TypeOfBackfacingModel_Auto, Graphic3d_TOBM_FORCE = Graphic3d_TypeOfBackfacingModel_DoubleSided, diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index e3655c8d1a..9380b93672 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -237,7 +237,7 @@ OpenGl_Context::OpenGl_Context (const Handle(OpenGl_Caps)& theCaps) myRenderMode (GL_RENDER), myShadeModel (GL_SMOOTH), myPolygonMode (GL_FILL), - myToCullBackFaces (false), + myFaceCulling (Graphic3d_TypeOfBackfacingModel_DoubleSided), myReadBuffer (0), myDrawBuffers (0, 7), myDefaultVao (0), @@ -547,26 +547,35 @@ void OpenGl_Context::SetFrameBufferSRGB (bool theIsFbo, bool theIsFboSRgb) } // ======================================================================= -// function : SetCullBackFaces +// function : SetFaceCulling // purpose : // ======================================================================= -void OpenGl_Context::SetCullBackFaces (bool theToEnable) +void OpenGl_Context::SetFaceCulling (Graphic3d_TypeOfBackfacingModel theMode) { - if (myToCullBackFaces == theToEnable) + if (myFaceCulling == theMode) { return; } - myToCullBackFaces = theToEnable; - if (theToEnable) + if (theMode == Graphic3d_TypeOfBackfacingModel_BackCulled) { - //glCullFace (GL_BACK); GL_BACK by default + if (myFaceCulling == Graphic3d_TypeOfBackfacingModel_FrontCulled) + { + core11fwd->glCullFace (GL_BACK); + } + core11fwd->glEnable (GL_CULL_FACE); + } + else if (theMode == Graphic3d_TypeOfBackfacingModel_FrontCulled) + { + core11fwd->glCullFace (GL_FRONT); core11fwd->glEnable (GL_CULL_FACE); } else { + core11fwd->glCullFace (GL_BACK); core11fwd->glDisable (GL_CULL_FACE); } + myFaceCulling = theMode; } // ======================================================================= @@ -3084,7 +3093,7 @@ void OpenGl_Context::DumpJson (Standard_OStream& theOStream, Standard_Integer th OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myRenderMode) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myPolygonMode) OCCT_DUMP_FIELD_VALUES_DUMPED (theOStream, theDepth, &myPolygonOffset) - OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myToCullBackFaces) + OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myFaceCulling) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myReadBuffer) OCCT_DUMP_FIELD_VALUE_NUMERICAL (theOStream, myDefaultVao) diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index 2d42736de5..f86c4cc461 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -803,10 +803,19 @@ public: //! @name methods to alter or retrieve current state Standard_EXPORT bool SetSampleAlphaToCoverage (bool theToEnable); //! Return back face culling state. - bool ToCullBackFaces() const { return myToCullBackFaces; } + Graphic3d_TypeOfBackfacingModel FaceCulling() const { return myFaceCulling; } //! Enable or disable back face culling (glEnable (GL_CULL_FACE)). - Standard_EXPORT void SetCullBackFaces (bool theToEnable); + Standard_EXPORT void SetFaceCulling (Graphic3d_TypeOfBackfacingModel theMode); + + //! Return back face culling state. + bool ToCullBackFaces() const { return myFaceCulling == Graphic3d_TypeOfBackfacingModel_BackCulled; } + + //! Enable or disable back face culling (glCullFace() + glEnable(GL_CULL_FACE)). + void SetCullBackFaces (bool theToEnable) + { + SetFaceCulling (theToEnable ? Graphic3d_TypeOfBackfacingModel_BackCulled : Graphic3d_TypeOfBackfacingModel_DoubleSided); + } //! Fetch OpenGl context state. This class tracks value of several OpenGl //! state variables. Consulting the cached values is quicker than @@ -1155,7 +1164,7 @@ private: //! @name fields tracking current state Standard_Integer myShadeModel; //!< currently used shade model (glShadeModel) Standard_Integer myPolygonMode; //!< currently used polygon rasterization mode (glPolygonMode) Graphic3d_PolygonOffset myPolygonOffset; //!< currently applied polygon offset - bool myToCullBackFaces; //!< back face culling mode enabled state (glIsEnabled (GL_CULL_FACE)) + Graphic3d_TypeOfBackfacingModel myFaceCulling; //!< back face culling mode enabled state (glIsEnabled (GL_CULL_FACE)) Standard_Integer myReadBuffer; //!< current read buffer NCollection_Array1 myDrawBuffers; //!< current draw buffers diff --git a/src/OpenGl/OpenGl_PrimitiveArray.cxx b/src/OpenGl/OpenGl_PrimitiveArray.cxx index 5f1747ba4d..151d1cc40a 100644 --- a/src/OpenGl/OpenGl_PrimitiveArray.cxx +++ b/src/OpenGl/OpenGl_PrimitiveArray.cxx @@ -1030,10 +1030,9 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace anOutlineProgram->SetUniform (aCtx, anOutlineProgram->GetStateLocation (OpenGl_OCCT_ORTHO_SCALE), anOrthoScale); aCtx->SetColor4fv (anAspectFace->Aspect()->EdgeColorRGBA()); - aCtx->core11fwd->glCullFace (GL_FRONT); + aCtx->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_FrontCulled); drawArray (theWorkspace, NULL, false); - - aCtx->core11fwd->glCullFace (GL_BACK); + aCtx->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_BackCulled); } if (isForcedBlend) diff --git a/src/OpenGl/OpenGl_Workspace.cxx b/src/OpenGl/OpenGl_Workspace.cxx index a59d494af3..91d1fa604f 100644 --- a/src/OpenGl/OpenGl_Workspace.cxx +++ b/src/OpenGl/OpenGl_Workspace.cxx @@ -255,27 +255,34 @@ const OpenGl_Aspects* OpenGl_Workspace::SetAspects (const OpenGl_Aspects* theAsp // ======================================================================= const OpenGl_Aspects* OpenGl_Workspace::ApplyAspects (bool theToBindTextures) { - bool toSuppressBackFaces = myView->BackfacingModel() == Graphic3d_TypeOfBackfacingModel_BackCulled; - if (myView->BackfacingModel() == Graphic3d_TypeOfBackfacingModel_Auto) + //bool toSuppressBackFaces = myView->BackfacingModel() == Graphic3d_TypeOfBackfacingModel_BackCulled; + Graphic3d_TypeOfBackfacingModel aCullFacesMode = myView->BackfacingModel(); + if (aCullFacesMode == Graphic3d_TypeOfBackfacingModel_Auto) { - toSuppressBackFaces = myAspectsSet->Aspect()->FaceCulling() == Graphic3d_TypeOfBackfacingModel_BackCulled; - if (myAspectsSet->Aspect()->FaceCulling() == Graphic3d_TypeOfBackfacingModel_Auto - && myToAllowFaceCulling) + aCullFacesMode = myAspectsSet->Aspect()->FaceCulling(); + if (aCullFacesMode == Graphic3d_TypeOfBackfacingModel_Auto) { - toSuppressBackFaces = true; - if (myAspectsSet->Aspect()->InteriorStyle() == Aspect_IS_HATCH - || myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Blend - || myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Mask - || myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_MaskBlend - || (myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_BlendAuto - && myAspectsSet->Aspect()->FrontMaterial().Transparency() != 0.0f)) + aCullFacesMode = Graphic3d_TypeOfBackfacingModel_DoubleSided; + if (myToAllowFaceCulling) { - // disable culling in case of translucent shading aspect - toSuppressBackFaces = false; + if (myAspectsSet->Aspect()->InteriorStyle() == Aspect_IS_HATCH + || myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Blend + || myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_Mask + || myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_MaskBlend + || (myAspectsSet->Aspect()->AlphaMode() == Graphic3d_AlphaMode_BlendAuto + && myAspectsSet->Aspect()->FrontMaterial().Transparency() != 0.0f)) + { + // disable culling in case of translucent shading aspect + aCullFacesMode = Graphic3d_TypeOfBackfacingModel_DoubleSided; + } + else + { + aCullFacesMode = Graphic3d_TypeOfBackfacingModel_BackCulled; + } } } } - myGlContext->SetCullBackFaces (toSuppressBackFaces); + myGlContext->SetFaceCulling (aCullFacesMode); if (myAspectsSet->Aspect() == myAspectsApplied && myHighlightStyle == myAspectFaceAppliedWithHL) diff --git a/src/RWGltf/RWGltf_GltfMaterialMap.cxx b/src/RWGltf/RWGltf_GltfMaterialMap.cxx index a5f4ee3e11..d3c8cee6c7 100644 --- a/src/RWGltf/RWGltf_GltfMaterialMap.cxx +++ b/src/RWGltf/RWGltf_GltfMaterialMap.cxx @@ -493,7 +493,8 @@ void RWGltf_GltfMaterialMap::DefineMaterial (const XCAFPrs_Style& theStyle, // as both may share the same material having "auto" flag if (theStyle.Material().IsNull() || theStyle.Material()->FaceCulling() == Graphic3d_TypeOfBackfacingModel_Auto - || theStyle.Material()->FaceCulling() == Graphic3d_TypeOfBackfacingModel_DoubleSided) + || theStyle.Material()->FaceCulling() == Graphic3d_TypeOfBackfacingModel_DoubleSided + || theStyle.Material()->FaceCulling() == Graphic3d_TypeOfBackfacingModel_FrontCulled) // front culling flag cannot be exported to glTF { myWriter->Key ("doubleSided"); myWriter->Bool (true); diff --git a/src/ViewerTest/ViewerTest.cxx b/src/ViewerTest/ViewerTest.cxx index 2acf5a4f4c..0d9fe25ead 100644 --- a/src/ViewerTest/ViewerTest.cxx +++ b/src/ViewerTest/ViewerTest.cxx @@ -1683,6 +1683,9 @@ struct ViewerTest_AspectsChangeSet Graphic3d_AlphaMode AlphaMode; Standard_ShortReal AlphaCutoff; + Standard_Integer ToSetFaceCulling; + Graphic3d_TypeOfBackfacingModel FaceCulling; + Standard_Integer ToSetMaterial; Graphic3d_NameOfMaterial Material; TCollection_AsciiString MatName; @@ -1764,6 +1767,8 @@ struct ViewerTest_AspectsChangeSet ToSetAlphaMode (0), AlphaMode (Graphic3d_AlphaMode_BlendAuto), AlphaCutoff (0.5f), + ToSetFaceCulling (0), + FaceCulling (Graphic3d_TypeOfBackfacingModel_Auto), ToSetMaterial (0), Material (Graphic3d_NameOfMaterial_DEFAULT), ToSetShowFreeBoundary (0), @@ -1811,6 +1816,7 @@ struct ViewerTest_AspectsChangeSet && ToSetLineWidth == 0 && ToSetTransparency == 0 && ToSetAlphaMode == 0 + && ToSetFaceCulling == 0 && ToSetColor == 0 && ToSetBackFaceColor == 0 && ToSetMaterial == 0 @@ -2064,6 +2070,15 @@ struct ViewerTest_AspectsChangeSet theDrawer->ShadingAspect()->Aspect()->SetAlphaMode (AlphaMode, AlphaCutoff); } } + if (ToSetFaceCulling != 0) + { + if (ToSetFaceCulling != -1 + || theDrawer->HasOwnShadingAspect()) + { + toRecompute = theDrawer->SetupOwnShadingAspect (aDefDrawer) || toRecompute; + theDrawer->ShadingAspect()->Aspect()->SetFaceCulling (FaceCulling); + } + } if (ToSetHatch != 0) { if (ToSetHatch != -1 @@ -2557,6 +2572,47 @@ static Standard_Integer VAspects (Draw_Interpretor& theDI, } } } + else if (anArg == "-setfaceculling" + || anArg == "-faceculling") + { + if (++anArgIter >= theArgNb) + { + Message::SendFail() << "Error: wrong syntax at " << anArg; + return 1; + } + + aChangeSet->ToSetFaceCulling = 1; + { + TCollection_AsciiString aParam (theArgVec[anArgIter]); + aParam.LowerCase(); + if (aParam == "auto") + { + aChangeSet->FaceCulling = Graphic3d_TypeOfBackfacingModel_Auto; + } + else if (aParam == "backculled" + || aParam == "backcull" + || aParam == "back") + { + aChangeSet->FaceCulling = Graphic3d_TypeOfBackfacingModel_BackCulled; + } + else if (aParam == "frontculled" + || aParam == "frontcull" + || aParam == "front") + { + aChangeSet->FaceCulling = Graphic3d_TypeOfBackfacingModel_FrontCulled; + } + else if (aParam == "doublesided" + || aParam == "off") + { + aChangeSet->FaceCulling = Graphic3d_TypeOfBackfacingModel_DoubleSided; + } + else + { + Message::SendFail() << "Error: wrong syntax at '" << aParam << "'"; + return 1; + } + } + } else if (anArg == "-setvis" || anArg == "-setvisibility" || anArg == "-visibility") @@ -3192,6 +3248,8 @@ static Standard_Integer VAspects (Draw_Interpretor& theDI, aChangeSet->ToSetAlphaMode = -1; aChangeSet->AlphaMode = Graphic3d_AlphaMode_BlendAuto; aChangeSet->AlphaCutoff = 0.5f; + aChangeSet->ToSetFaceCulling = -1; + aChangeSet->FaceCulling = Graphic3d_TypeOfBackfacingModel_Auto; aChangeSet->ToSetColor = -1; aChangeSet->Color = DEFAULT_COLOR; //aChangeSet->ToSetBackFaceColor = -1; // should be reset by ToSetColor @@ -6708,7 +6766,7 @@ vsub 0/1 (off/on) [obj] : Subintensity(on/off) of selected objects vaspects [-noupdate|-update] [name1 [name2 [...]] | -defaults] [-subshapes subname1 [subname2 [...]]] [-visibility {0|1}] [-color {ColorName | R G B}] [-unsetColor] - [-backfaceColor Color] + [-backfaceColor Color] [-faceCulling {auto|back|front|doublesided}] [-material MatName] [-unsetMaterial] [-transparency Transp] [-unsetTransparency] [-width LineWidth] [-unsetWidth] diff --git a/src/XDEDRAW/XDEDRAW_Colors.cxx b/src/XDEDRAW/XDEDRAW_Colors.cxx index 2ab74cad05..faf8258d83 100644 --- a/src/XDEDRAW/XDEDRAW_Colors.cxx +++ b/src/XDEDRAW/XDEDRAW_Colors.cxx @@ -99,6 +99,7 @@ static const char* faceCullToString (Graphic3d_TypeOfBackfacingModel theMode) { case Graphic3d_TypeOfBackfacingModel_Auto: return "Auto"; case Graphic3d_TypeOfBackfacingModel_BackCulled: return "BackCulled"; + case Graphic3d_TypeOfBackfacingModel_FrontCulled: return "FrontCulled"; case Graphic3d_TypeOfBackfacingModel_DoubleSided: return "DoubleSided"; } return ""; @@ -1161,6 +1162,12 @@ static Standard_Integer XAddVisMaterial (Draw_Interpretor& , Standard_Integer th { aMode = Graphic3d_TypeOfBackfacingModel_BackCulled; } + else if (aCullStr == "frontculled" + || aCullStr == "frontcull" + || aCullStr == "front") + { + aMode = Graphic3d_TypeOfBackfacingModel_FrontCulled; + } else if (aCullStr == "doublesided") { aMode = Graphic3d_TypeOfBackfacingModel_DoubleSided; diff --git a/src/XmlMXCAFDoc/XmlMXCAFDoc_VisMaterialDriver.cxx b/src/XmlMXCAFDoc/XmlMXCAFDoc_VisMaterialDriver.cxx index c63fcd1905..257620e455 100644 --- a/src/XmlMXCAFDoc/XmlMXCAFDoc_VisMaterialDriver.cxx +++ b/src/XmlMXCAFDoc/XmlMXCAFDoc_VisMaterialDriver.cxx @@ -256,11 +256,14 @@ Standard_Boolean XmlMXCAFDoc_VisMaterialDriver::Paste (const XmlObjMgt_Persisten aDoubleSidedStr.GetInteger (aDoubleSidedInt); Standard_ShortReal anAlphaCutOff = 0.5f; readReal (theSource, ::AlphaCutOff(), anAlphaCutOff); - aMat->SetFaceCulling (aDoubleSidedInt == 1 - ? Graphic3d_TypeOfBackfacingModel_DoubleSided - : (aDoubleSidedInt == 2 - ? Graphic3d_TypeOfBackfacingModel_BackCulled - : Graphic3d_TypeOfBackfacingModel_Auto)); + switch (aDoubleSidedInt) + { + case 1: aMat->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_DoubleSided); break; + case 2: aMat->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_BackCulled); break; + case 3: aMat->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_FrontCulled); break; + case 0: + default: aMat->SetFaceCulling (Graphic3d_TypeOfBackfacingModel_Auto); break; + } aMat->SetAlphaMode (alphaModeFromString (theSource.Element().getAttribute (::AlphaMode()).GetString()), anAlphaCutOff); Quantity_ColorRGBA aBaseColor; @@ -307,11 +310,14 @@ void XmlMXCAFDoc_VisMaterialDriver::Paste (const Handle(TDF_Attribute)& theSourc XmlObjMgt_SRelocationTable& ) const { Handle(XCAFDoc_VisMaterial) aMat = Handle(XCAFDoc_VisMaterial)::DownCast(theSource); - Standard_Integer aDoubleSidedInt = aMat->FaceCulling() == Graphic3d_TypeOfBackfacingModel_DoubleSided - ? 1 - : (aMat->FaceCulling() == Graphic3d_TypeOfBackfacingModel_BackCulled - ? 2 - : 0); + Standard_Integer aDoubleSidedInt = 0; + switch (aMat->FaceCulling()) + { + case Graphic3d_TypeOfBackfacingModel_DoubleSided: aDoubleSidedInt = 1; break; + case Graphic3d_TypeOfBackfacingModel_BackCulled: aDoubleSidedInt = 2; break; + case Graphic3d_TypeOfBackfacingModel_FrontCulled: aDoubleSidedInt = 3; break; + case Graphic3d_TypeOfBackfacingModel_Auto: aDoubleSidedInt = 0; break; + } theTarget.Element().setAttribute (::IsDoubleSided(), aDoubleSidedInt); theTarget.Element().setAttribute (::AlphaMode(), alphaModeToString (aMat->AlphaMode())); writeReal (theTarget, ::AlphaCutOff(), aMat->AlphaCutOff()); diff --git a/tests/opengl/data/general/cullface b/tests/opengl/data/general/cullface new file mode 100644 index 0000000000..9eddd98fac --- /dev/null +++ b/tests/opengl/data/general/cullface @@ -0,0 +1,42 @@ +puts "========" +puts "0033056: Visualization - add front face culling option" +puts "Check face culling options" +puts "========" + +set THE_NB_BOXES 4 +set THE_COLORS { ORANGE ORANGE ORANGE ORANGE } +set THE_MODES { AUTO BACK FRONT DOUBLESIDED } + +pload MODELING VISUALIZATION +vclear +vinit View1 +vcamera -persp -fovy 80 +vfront + +set x 1 +set z 1 +for { set i 1 } { $i <= $THE_NB_BOXES } { incr i } { + box b$i [expr $x * 300] 0 [expr $z * 400] 200 300 300 + vdisplay -dispMode 1 b$i + vsetcolor b$i [lindex $THE_COLORS [expr $i - 1]] + vaspects b$i -faceCulling [lindex $THE_MODES [expr $i - 1]] + + vdrawtext t$i [lindex $THE_MODES [expr $i - 1]] -pos [expr $x * 300] 0 [expr $z * 400 + 300] -height 16 -color RED -font MONOSPACE -aspect BOLD -valign top + + incr x + if { $i == 2 } { + set x 1 + set z 2 + } +} +vfit + +vaspects -faceBoundaryDraw 1 -faceBoundaryColor RED +vdump $::imagedir/${::casename}_bnds.png + +vaspects -faceBoundaryDraw 0 +vclipplane c -equation 0 1 0 -100 -set +vdump $::imagedir/${::casename}_clip.png + +vclipplane c off +vdump $::imagedir/${::casename}.png