From: asl Date: Thu, 17 May 2018 13:10:30 +0000 (+0300) Subject: 0024437: Efficient HLR visualization based on OpenGL and GLSL X-Git-Url: http://git.dev.opencascade.org/gitweb/?a=commitdiff_plain;h=d6cb4c349bf18a3b295e201abeeb87e784926afb;p=occt-copy.git 0024437: Efficient HLR visualization based on OpenGL and GLSL New interior style Aspect_IS_OUTLINE is supported for Graphic3d_AspectFillArea3d. If this style is set, the triangles primitive array is drawn using the outline shader --- diff --git a/src/Aspect/Aspect_InteriorStyle.hxx b/src/Aspect/Aspect_InteriorStyle.hxx index e69a2589f2..b197970e39 100644 --- a/src/Aspect/Aspect_InteriorStyle.hxx +++ b/src/Aspect/Aspect_InteriorStyle.hxx @@ -32,7 +32,8 @@ Aspect_IS_HOLLOW, Aspect_IS_HATCH, Aspect_IS_SOLID, Aspect_IS_HIDDENLINE, -Aspect_IS_POINT +Aspect_IS_POINT, +Aspect_IS_OUTLINE }; #endif // _Aspect_InteriorStyle_HeaderFile diff --git a/src/OpenGl/OpenGl_Context.cxx b/src/OpenGl/OpenGl_Context.cxx index 125102fe75..91a832cf00 100644 --- a/src/OpenGl/OpenGl_Context.cxx +++ b/src/OpenGl/OpenGl_Context.cxx @@ -33,6 +33,7 @@ #include #include #include +#include #include #include @@ -3449,6 +3450,79 @@ void OpenGl_Context::SetPointSize (const Standard_ShortReal theSize) #endif } +// ======================================================================= +// function : PushOrthoScale +// purpose : +// ======================================================================= +void OpenGl_Context::PushOrthoScale (const Handle(OpenGl_Workspace)& theWorkspace) +{ + if (!myActiveProgram.IsNull() && !theWorkspace.IsNull()) + { + Standard_ShortReal aScale = (Standard_ShortReal)theWorkspace->View()->Camera()->Scale(); + myActiveProgram->SetUniform(this, myActiveProgram->GetStateLocation(OpenGl_OCCT_ORTHO_SCALE), aScale); + } +} + +// ======================================================================= +// function : SetIsSilhouettePass +// purpose : +// ======================================================================= +void OpenGl_Context::SetIsSilhouettePass (Standard_Boolean isSilhouettePass) +{ + if (!myActiveProgram.IsNull() ) + { + myActiveProgram->SetUniform(this, + myActiveProgram->GetStateLocation(OpenGl_OCCT_IS_SILHOUETTE_PASS), + isSilhouettePass ? 1.0f : 0.0f); + } +} + +// ======================================================================= +// function : PushBackgroundColor +// purpose : +// ======================================================================= +void OpenGl_Context::PushBackgroundColor (const Handle(OpenGl_Workspace)& theWorkspace) +{ + if (!myActiveProgram.IsNull() && !theWorkspace.IsNull()) + { + const Quantity_Color& aBackground = theWorkspace->View()->BackgroundColor().GetRGB(); + myActiveProgram->SetUniform(this, + myActiveProgram->GetStateLocation(OpenGl_OCCT_BACKGROUND_COLOR), + OpenGl_Vec3((Standard_ShortReal)aBackground.Red(), + (Standard_ShortReal)aBackground.Green(), + (Standard_ShortReal)aBackground.Blue())); + } +} + +// ======================================================================= +// function : SetSilhouetteColor +// purpose : +// ======================================================================= +void OpenGl_Context::SetSilhouetteColor (const Quantity_Color& theColor) +{ + if (!myActiveProgram.IsNull()) + { + myActiveProgram->SetUniform(this, + myActiveProgram->GetStateLocation(OpenGl_OCCT_SILHOUETTE_COLOR), + OpenGl_Vec3((Standard_ShortReal)theColor.Red(), + (Standard_ShortReal)theColor.Green(), + (Standard_ShortReal)theColor.Blue())); + } +} + +// ======================================================================= +// function : SetSilhouetteThickness +// purpose : +// ======================================================================= +void OpenGl_Context::SetSilhouetteThickness (Standard_ShortReal theThickness) +{ + if (!myActiveProgram.IsNull()) + { + myActiveProgram->SetUniform(this, + myActiveProgram->GetStateLocation(OpenGl_OCCT_SILHOUETTE_THICKNESS), theThickness); + } +} + // ======================================================================= // function : SetPointSpriteOrigin // purpose : diff --git a/src/OpenGl/OpenGl_Context.hxx b/src/OpenGl/OpenGl_Context.hxx index 13bf652ba2..58f65a8a23 100644 --- a/src/OpenGl/OpenGl_Context.hxx +++ b/src/OpenGl/OpenGl_Context.hxx @@ -45,6 +45,8 @@ #include +class OpenGl_Workspace; + //! Forward declarations #if defined(__APPLE__) #import @@ -735,6 +737,12 @@ public: //! @name methods to alter or retrieve current state //! Setup texture matrix to active GLSL program or to FFP global state using glMatrixMode (GL_TEXTURE). Standard_EXPORT void SetTextureMatrix (const Handle(Graphic3d_TextureParams)& theParams); + Standard_EXPORT void PushOrthoScale (const Handle(OpenGl_Workspace)& theWorkspace); + Standard_EXPORT void SetIsSilhouettePass (Standard_Boolean); + Standard_EXPORT void PushBackgroundColor (const Handle(OpenGl_Workspace)& theWorkspace); + Standard_EXPORT void SetSilhouetteColor (const Quantity_Color&); + Standard_EXPORT void SetSilhouetteThickness (Standard_ShortReal); + //! Bind default Vertex Array Object Standard_EXPORT void BindDefaultVao(); diff --git a/src/OpenGl/OpenGl_PrimitiveArray.cxx b/src/OpenGl/OpenGl_PrimitiveArray.cxx index 8986de7bb6..77e8514fd4 100644 --- a/src/OpenGl/OpenGl_PrimitiveArray.cxx +++ b/src/OpenGl/OpenGl_PrimitiveArray.cxx @@ -24,6 +24,7 @@ #include #include #include +#include #include #include #include @@ -870,7 +871,39 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace anAspectFace->Aspect()->AlphaMode(), hasVertColor, toEnableEnvMap, - anAspectFace->ShaderProgramRes (aCtx)); + anAspectFace->ShaderProgramRes (aCtx), + anAspectFace->Aspect()->InteriorStyle()); + + if (anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_OUTLINE) + { + const Graphic3d_Vec4* aFaceColors = !myBounds.IsNull() && !toHilight && anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_HIDDENLINE + ? myBounds->Colors + : NULL; + + aCtx->PushOrthoScale(theWorkspace); + aCtx->PushBackgroundColor(theWorkspace); + aCtx->SetSilhouetteColor(anAspectFace->Aspect()->EdgeColor()); + + Standard_Integer aViewWidth, aViewHeight; + theWorkspace->View()->Window()->Size(aViewWidth, aViewHeight); + Standard_Integer aMin = aViewWidth < aViewHeight ? aViewWidth : aViewHeight; + + Standard_ShortReal anEdgeWidth = (Standard_ShortReal)anAspectFace->Aspect()->EdgeWidth() / (Standard_ShortReal)aMin; + aCtx->SetSilhouetteThickness(anEdgeWidth); + + aCtx->SetIsSilhouettePass(Standard_True); + GLboolean isCull = glIsEnabled(GL_CULL_FACE); + glEnable(GL_CULL_FACE); + glCullFace(GL_FRONT); + drawArray(theWorkspace, aFaceColors, hasColorAttrib); + + aCtx->SetIsSilhouettePass(Standard_False); + glCullFace(GL_BACK); + drawArray(theWorkspace, aFaceColors, hasColorAttrib); + + if (!isCull) + glDisable(GL_CULL_FACE); + } break; } } @@ -928,8 +961,9 @@ void OpenGl_PrimitiveArray::Render (const Handle(OpenGl_Workspace)& theWorkspace } else { - if (anAspectFace->Aspect()->ToDrawEdges() - || anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_HIDDENLINE) + if ((anAspectFace->Aspect()->ToDrawEdges() + || anAspectFace->Aspect()->InteriorStyle() == Aspect_IS_HIDDENLINE) + && anAspectFace->Aspect()->InteriorStyle() != Aspect_IS_OUTLINE) { const OpenGl_Vec4& anEdgeColor = theWorkspace->EdgeColor(); drawEdges (anEdgeColor, theWorkspace); @@ -1086,3 +1120,4 @@ void OpenGl_PrimitiveArray::InitBuffers (const Handle(OpenGl_Context)& th setDrawMode (theType); } + diff --git a/src/OpenGl/OpenGl_ShaderManager.cxx b/src/OpenGl/OpenGl_ShaderManager.cxx index 6ff6c20b6f..3f595d6925 100644 --- a/src/OpenGl/OpenGl_ShaderManager.cxx +++ b/src/OpenGl/OpenGl_ShaderManager.cxx @@ -1655,12 +1655,57 @@ Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_Sha } } + if ((theBits & OpenGl_PO_OUTLINE) != 0) + { + aSrcVertExtraOut += + EOL"uniform float occOrthoScale;" + EOL"uniform float occIsSilhouettePass;" + EOL"uniform float occSilhouetteThickness;" + EOL"" + EOL"THE_SHADER_IN vec4 normal;" + ; + + aSrcVertExtraMain += + EOL" vec3 delta = vec3(0.0, 0.0, 0.0);" + EOL" if (occIsSilhouettePass > 0.1)" + EOL" {" + EOL" float aShift = occSilhouetteThickness;" + EOL" if (occOrthoScale > 0.0)" + EOL" {" + EOL" aShift *= occOrthoScale;" + EOL" delta = normal.xyz * aShift;" + EOL" }" + EOL" else" + EOL" {" + EOL" vec4 pos = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * vertex;" + EOL" delta = normal.xyz * aShift * pos.w;" + EOL" }" + EOL" }" + EOL" vertex += vec4(delta, 0.0);" + ; + + aSrcFragExtraOut += + EOL"uniform float occIsSilhouettePass;" + EOL"uniform vec3 occBackgroundColor;" + EOL"uniform vec3 occSilhouetteColor;" + ; + + aSrcFragExtraMain += + EOL" vec3 aColor = occBackgroundColor;" + EOL" if (occIsSilhouettePass > 0.1)" + EOL" aColor = occSilhouetteColor;" + ; + + aSrcFragWriteOit = EOL" occSetFragColor(vec4(aColor, 1.0));"; + } + aSrcVert = aSrcVertExtraFunc + EOL"void main()" EOL"{" + EOL" vec4 vertex = occVertex;" + aSrcVertExtraMain - + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;" + + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * vertex;" + aSrcVertEndMain + EOL"}"; diff --git a/src/OpenGl/OpenGl_ShaderManager.hxx b/src/OpenGl/OpenGl_ShaderManager.hxx index 98b1e6ae4d..ddc8392c03 100644 --- a/src/OpenGl/OpenGl_ShaderManager.hxx +++ b/src/OpenGl/OpenGl_ShaderManager.hxx @@ -88,7 +88,8 @@ public: const Graphic3d_AlphaMode theAlphaMode, const Standard_Boolean theHasVertColor, const Standard_Boolean theEnableEnvMap, - const Handle(OpenGl_ShaderProgram)& theCustomProgram) + const Handle(OpenGl_ShaderProgram)& theCustomProgram, + const Aspect_InteriorStyle theStyle) { if (!theCustomProgram.IsNull() || myContext->caps->ffpEnable) @@ -100,7 +101,7 @@ public: && (theTextures.IsNull() || theTextures->IsModulate()) ? theShadingModel : Graphic3d_TOSM_UNLIT; - const Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, theHasVertColor, theEnableEnvMap); + const Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, theHasVertColor, theEnableEnvMap, theStyle); Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (aShadeModelOnFace, aBits); return bindProgramWithState (aProgram); } @@ -415,7 +416,8 @@ protected: Standard_Integer getProgramBits (const Handle(OpenGl_TextureSet)& theTextures, Graphic3d_AlphaMode theAlphaMode, Standard_Boolean theHasVertColor, - Standard_Boolean theEnableEnvMap) + Standard_Boolean theEnableEnvMap, + Aspect_InteriorStyle theStyle=Aspect_IS_EMPTY) { Standard_Integer aBits = 0; @@ -463,6 +465,11 @@ protected: { aBits |= OpenGl_PO_WriteOit; } + + if (theStyle == Aspect_IS_OUTLINE) + { + aBits |= OpenGl_PO_OUTLINE; + } return aBits; } @@ -471,7 +478,8 @@ protected: Standard_Integer theBits) { if (theShadingModel == Graphic3d_TOSM_UNLIT - || (theBits & OpenGl_PO_TextureEnv) != 0) + || (theBits & OpenGl_PO_TextureEnv) != 0 + || (theBits & OpenGl_PO_OUTLINE) != 0) { // If environment map is enabled lighting calculations are // not needed (in accordance with default OCCT behavior) diff --git a/src/OpenGl/OpenGl_ShaderProgram.cxx b/src/OpenGl/OpenGl_ShaderProgram.cxx index 0d665d0057..0d69aa10a7 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.cxx +++ b/src/OpenGl/OpenGl_ShaderProgram.cxx @@ -75,7 +75,13 @@ Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] = "occOitDepthFactor", // OpenGl_OCCT_OIT_DEPTH_FACTOR "occTexTrsf2d", // OpenGl_OCCT_TEXTURE_TRSF2D - "occPointSize" // OpenGl_OCCT_POINT_SIZE + "occPointSize", // OpenGl_OCCT_POINT_SIZE + + "occOrthoScale", // OpenGl_OCCT_ORTHO_SCALE + "occIsSilhouettePass", // OpenGl_OCCT_IS_SILHOUETTE_PASS + "occBackgroundColor", // OpenGl_OCCT_BACKGROUND_COLOR + "occSilhouetteColor", // OpenGl_OCCT_SILHOUETTE_COLOR + "occSilhouetteThickness" // OpenGl_OCCT_SILHOUETTE_THICKNESS }; namespace diff --git a/src/OpenGl/OpenGl_ShaderProgram.hxx b/src/OpenGl/OpenGl_ShaderProgram.hxx index 1f15f0133d..42ff8ff76f 100755 --- a/src/OpenGl/OpenGl_ShaderProgram.hxx +++ b/src/OpenGl/OpenGl_ShaderProgram.hxx @@ -75,6 +75,13 @@ enum OpenGl_StateVariable OpenGl_OCCT_TEXTURE_TRSF2D, OpenGl_OCCT_POINT_SIZE, + // Parameters of outline (silhouette) shader + OpenGl_OCCT_ORTHO_SCALE, + OpenGl_OCCT_IS_SILHOUETTE_PASS, + OpenGl_OCCT_BACKGROUND_COLOR, + OpenGl_OCCT_SILHOUETTE_COLOR, + OpenGl_OCCT_SILHOUETTE_THICKNESS, + // DON'T MODIFY THIS ITEM (insert new items before it) OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES }; diff --git a/src/OpenGl/OpenGl_Text.cxx b/src/OpenGl/OpenGl_Text.cxx index 70cd2fb3a3..84896b7d21 100644 --- a/src/OpenGl/OpenGl_Text.cxx +++ b/src/OpenGl/OpenGl_Text.cxx @@ -651,7 +651,7 @@ void OpenGl_Text::drawRect (const Handle(OpenGl_Context)& theCtx, // bind unlit program theCtx->ShaderManager()->BindFaceProgram (Handle(OpenGl_TextureSet)(), Graphic3d_TOSM_UNLIT, Graphic3d_AlphaMode_Opaque, Standard_False, Standard_False, - Handle(OpenGl_ShaderProgram)()); + Handle(OpenGl_ShaderProgram)(), Aspect_IS_SOLID); #if !defined(GL_ES_VERSION_2_0) if (theCtx->core11 != NULL diff --git a/src/ViewerTest/ViewerTest.cxx b/src/ViewerTest/ViewerTest.cxx index 9e03442a2d..9c7716a220 100644 --- a/src/ViewerTest/ViewerTest.cxx +++ b/src/ViewerTest/ViewerTest.cxx @@ -1554,14 +1554,18 @@ static int VSetInteriorStyle (Draw_Interpretor& theDI, { anInterStyle = Aspect_IS_POINT; } + else if (aStyleArg == "outline") + { + anInterStyle = Aspect_IS_OUTLINE; + } else { const Standard_Integer anIntStyle = aStyleArg.IntegerValue(); if (anIntStyle < Aspect_IS_EMPTY - || anIntStyle > Aspect_IS_POINT) + || anIntStyle > Aspect_IS_OUTLINE) { std::cout << "Error: style must be within a range [0 (Aspect_IS_EMPTY), " - << Aspect_IS_POINT << " (Aspect_IS_POINT)]\n"; + << Aspect_IS_OUTLINE << " (Aspect_IS_OUTLINE)]\n"; return 1; } anInterStyle = (Aspect_InteriorStyle )anIntStyle; diff --git a/tests/bugs/vis/bug24437 b/tests/bugs/vis/bug24437 new file mode 100644 index 0000000000..84f7e8ed99 --- /dev/null +++ b/tests/bugs/vis/bug24437 @@ -0,0 +1,26 @@ +puts "========" +puts "0024437: Efficient HLR visualization based on OpenGL and GLSL" +puts "========" +puts "" + +pload MODELING VISUALIZATION + +vclear +vinit View1 +vsetcolorbg 220 220 220 + +psphere sph 1.0 +box b 1 2 3 +ttranslate b 2 -2 -2 + +vdisplay -dispMode 1 b +vsetinteriorstyle b outline +vshowfaceboundary b 1 255 0 0 1.0 +vsetedgetype b -color 255 0 0 +vfit + +vdisplay -dispMode 1 sph +vsetinteriorstyle sph outline +vshowfaceboundary sph 1 255 0 0 1.0 +vsetedgetype sph -color 255 0 0 +vfit