Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-08 09:17:09

0001 // Created on: 2013-09-26
0002 // Created by: Denis BOGOLEPOV
0003 // Copyright (c) 2013-2014 OPEN CASCADE SAS
0004 //
0005 // This file is part of Open CASCADE Technology software library.
0006 //
0007 // This library is free software; you can redistribute it and/or modify it under
0008 // the terms of the GNU Lesser General Public License version 2.1 as published
0009 // by the Free Software Foundation, with special exception defined in the file
0010 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
0011 // distribution for complete text of the license and disclaimer of any warranty.
0012 //
0013 // Alternatively, this file may be used under the terms of Open CASCADE
0014 // commercial license or contractual agreement.
0015 
0016 #ifndef _OpenGl_ShaderManager_HeaderFile
0017 #define _OpenGl_ShaderManager_HeaderFile
0018 
0019 #include <Graphic3d_ShaderManager.hxx>
0020 #include <OpenGl_Aspects.hxx>
0021 #include <OpenGl_Context.hxx>
0022 #include <OpenGl_MaterialState.hxx>
0023 #include <OpenGl_PBREnvironment.hxx>
0024 #include <OpenGl_SetOfShaderPrograms.hxx>
0025 #include <OpenGl_ShaderProgram.hxx>
0026 #include <OpenGl_ShaderStates.hxx>
0027 #include <OpenGl_Texture.hxx>
0028 #include <OpenGl_TextureSet.hxx>
0029 
0030 class OpenGl_VertexBuffer;
0031 
0032 //! List of shader programs.
0033 typedef NCollection_Sequence<Handle(OpenGl_ShaderProgram)> OpenGl_ShaderProgramList;
0034 
0035 //! This class is responsible for managing shader programs.
0036 class OpenGl_ShaderManager : public Graphic3d_ShaderManager
0037 {
0038   DEFINE_STANDARD_RTTIEXT(OpenGl_ShaderManager, Graphic3d_ShaderManager)
0039   friend class OpenGl_ShaderProgram;
0040 
0041 public:
0042   //! Creates new empty shader manager.
0043   Standard_EXPORT OpenGl_ShaderManager(OpenGl_Context* theContext);
0044 
0045   //! Releases resources of shader manager.
0046   Standard_EXPORT virtual ~OpenGl_ShaderManager();
0047 
0048   //! Release all resources.
0049   Standard_EXPORT void clear();
0050 
0051   //! Fetch sRGB state from caps and invalidates programs, if necessary.
0052   Standard_EXPORT void UpdateSRgbState();
0053 
0054   //! Return local camera transformation.
0055   const gp_XYZ& LocalOrigin() const { return myLocalOrigin; }
0056 
0057   //! Setup local camera transformation for compensating float precision issues.
0058   void SetLocalOrigin(const gp_XYZ& theOrigin)
0059   {
0060     myLocalOrigin    = theOrigin;
0061     myHasLocalOrigin = !theOrigin.IsEqual(gp_XYZ(0.0, 0.0, 0.0), gp::Resolution());
0062   }
0063 
0064   //! Return clipping plane W equation value moved considering local camera transformation.
0065   Standard_Real LocalClippingPlaneW(const Graphic3d_ClipPlane& thePlane) const
0066   {
0067     const Graphic3d_Vec4d& anEq = thePlane.GetEquation();
0068     if (myHasLocalOrigin)
0069     {
0070       const gp_XYZ aPos = thePlane.ToPlane().Position().Location().XYZ() - myLocalOrigin;
0071       return -(anEq.x() * aPos.X() + anEq.y() * aPos.Y() + anEq.z() * aPos.Z());
0072     }
0073     return anEq.w();
0074   }
0075 
0076   //! Creates new shader program or re-use shared instance.
0077   //! @param[in] theProxy      program definition
0078   //! @param[out] theShareKey  sharing key
0079   //! @param[out] theProgram   OpenGL program
0080   //! @return true on success
0081   Standard_EXPORT Standard_Boolean Create(const Handle(Graphic3d_ShaderProgram)& theProxy,
0082                                           TCollection_AsciiString&               theShareKey,
0083                                           Handle(OpenGl_ShaderProgram)&          theProgram);
0084 
0085   //! Unregisters specified shader program.
0086   Standard_EXPORT void Unregister(TCollection_AsciiString&      theShareKey,
0087                                   Handle(OpenGl_ShaderProgram)& theProgram);
0088 
0089   //! Returns list of registered shader programs.
0090   const OpenGl_ShaderProgramList& ShaderPrograms() const { return myProgramList; }
0091 
0092   //! Returns true if no program objects are registered in the manager.
0093   Standard_Boolean IsEmpty() const { return myProgramList.IsEmpty(); }
0094 
0095   //! Bind program for filled primitives rendering
0096   Standard_Boolean BindFaceProgram(const Handle(OpenGl_TextureSet)&    theTextures,
0097                                    Graphic3d_TypeOfShadingModel        theShadingModel,
0098                                    Graphic3d_AlphaMode                 theAlphaMode,
0099                                    Standard_Boolean                    theHasVertColor,
0100                                    Standard_Boolean                    theEnableEnvMap,
0101                                    const Handle(OpenGl_ShaderProgram)& theCustomProgram)
0102   {
0103     return BindFaceProgram(theTextures,
0104                            theShadingModel,
0105                            theAlphaMode,
0106                            Aspect_IS_SOLID,
0107                            theHasVertColor,
0108                            theEnableEnvMap,
0109                            false,
0110                            theCustomProgram);
0111   }
0112 
0113   //! Bind program for filled primitives rendering
0114   Standard_Boolean BindFaceProgram(const Handle(OpenGl_TextureSet)&    theTextures,
0115                                    Graphic3d_TypeOfShadingModel        theShadingModel,
0116                                    Graphic3d_AlphaMode                 theAlphaMode,
0117                                    Aspect_InteriorStyle                theInteriorStyle,
0118                                    Standard_Boolean                    theHasVertColor,
0119                                    Standard_Boolean                    theEnableEnvMap,
0120                                    Standard_Boolean                    theEnableMeshEdges,
0121                                    const Handle(OpenGl_ShaderProgram)& theCustomProgram)
0122   {
0123     const Graphic3d_TypeOfShadingModel aShadeModelOnFace =
0124       theShadingModel != Graphic3d_TypeOfShadingModel_Unlit
0125           && (theTextures.IsNull() || theTextures->IsModulate())
0126         ? theShadingModel
0127         : Graphic3d_TypeOfShadingModel_Unlit;
0128     if (!theCustomProgram.IsNull() || myContext->caps->ffpEnable)
0129     {
0130       return bindProgramWithState(theCustomProgram, aShadeModelOnFace);
0131     }
0132 
0133     const Standard_Integer        aBits    = getProgramBits(theTextures,
0134                                                   theAlphaMode,
0135                                                   theInteriorStyle,
0136                                                   theHasVertColor,
0137                                                   theEnableEnvMap,
0138                                                   theEnableMeshEdges);
0139     Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram(aShadeModelOnFace, aBits);
0140     return bindProgramWithState(aProgram, aShadeModelOnFace);
0141   }
0142 
0143   //! Bind program for line rendering
0144   Standard_Boolean BindLineProgram(const Handle(OpenGl_TextureSet)&    theTextures,
0145                                    const Aspect_TypeOfLine             theLineType,
0146                                    const Graphic3d_TypeOfShadingModel  theShadingModel,
0147                                    const Graphic3d_AlphaMode           theAlphaMode,
0148                                    const Standard_Boolean              theHasVertColor,
0149                                    const Handle(OpenGl_ShaderProgram)& theCustomProgram)
0150   {
0151     if (!theCustomProgram.IsNull() || myContext->caps->ffpEnable)
0152     {
0153       return bindProgramWithState(theCustomProgram, theShadingModel);
0154     }
0155 
0156     Standard_Integer aBits =
0157       getProgramBits(theTextures, theAlphaMode, Aspect_IS_SOLID, theHasVertColor, false, false);
0158     if (theLineType != Aspect_TOL_SOLID)
0159     {
0160       aBits |= Graphic3d_ShaderFlags_StippleLine;
0161     }
0162 
0163     Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram(theShadingModel, aBits);
0164     return bindProgramWithState(aProgram, theShadingModel);
0165   }
0166 
0167   //! Bind program for point rendering
0168   Standard_EXPORT Standard_Boolean
0169     BindMarkerProgram(const Handle(OpenGl_TextureSet)&    theTextures,
0170                       Graphic3d_TypeOfShadingModel        theShadingModel,
0171                       Graphic3d_AlphaMode                 theAlphaMode,
0172                       Standard_Boolean                    theHasVertColor,
0173                       const Handle(OpenGl_ShaderProgram)& theCustomProgram);
0174 
0175   //! Bind program for rendering alpha-textured font.
0176   Standard_Boolean BindFontProgram(const Handle(OpenGl_ShaderProgram)& theCustomProgram);
0177 
0178   //! Bind program for outline rendering
0179   Standard_Boolean BindOutlineProgram()
0180   {
0181     if (myContext->caps->ffpEnable)
0182     {
0183       return false;
0184     }
0185 
0186     const Standard_Integer aBits = getProgramBits(Handle(OpenGl_TextureSet)(),
0187                                                   Graphic3d_AlphaMode_Opaque,
0188                                                   Aspect_IS_SOLID,
0189                                                   false,
0190                                                   false,
0191                                                   false);
0192     if (myOutlinePrograms.IsNull())
0193     {
0194       myOutlinePrograms = new OpenGl_SetOfPrograms();
0195     }
0196     Handle(OpenGl_ShaderProgram)& aProgram = myOutlinePrograms->ChangeValue(aBits);
0197     if (aProgram.IsNull())
0198     {
0199       prepareStdProgramUnlit(aProgram, aBits, true);
0200     }
0201     return bindProgramWithState(aProgram, Graphic3d_TypeOfShadingModel_Unlit);
0202   }
0203 
0204   //! Bind program for FBO blit operation.
0205   //! @param[in] theNbSamples        number of samples within source MSAA texture
0206   //! @param theIsFallback_sRGB[in]  flag indicating that destination buffer is not sRGB-ready
0207   Standard_EXPORT Standard_Boolean BindFboBlitProgram(Standard_Integer theNbSamples,
0208                                                       Standard_Boolean theIsFallback_sRGB);
0209 
0210   //! Bind program for blended order-independent transparency buffers compositing.
0211   Standard_EXPORT Standard_Boolean BindOitCompositingProgram(Standard_Boolean theIsMSAAEnabled);
0212 
0213   //! Bind program for Depth Peeling order-independent transparency back color blending.
0214   Standard_EXPORT Standard_Boolean BindOitDepthPeelingBlendProgram(bool theIsMSAAEnabled);
0215 
0216   //! Bind program for Depth Peeling order-independent transparency flush.
0217   Standard_EXPORT Standard_Boolean BindOitDepthPeelingFlushProgram(bool theIsMSAAEnabled);
0218 
0219   //! Bind program for rendering stereoscopic image.
0220   Standard_EXPORT Standard_Boolean BindStereoProgram(Graphic3d_StereoMode theStereoMode);
0221 
0222   //! Bind program for rendering bounding box.
0223   Standard_Boolean BindBoundBoxProgram()
0224   {
0225     if (myBoundBoxProgram.IsNull())
0226     {
0227       prepareStdProgramBoundBox();
0228     }
0229     return bindProgramWithState(myBoundBoxProgram, Graphic3d_TypeOfShadingModel_Unlit);
0230   }
0231 
0232   //! Returns bounding box vertex buffer.
0233   const Handle(OpenGl_VertexBuffer)& BoundBoxVertBuffer() const { return myBoundBoxVertBuffer; }
0234 
0235   //! Bind program for IBL maps generation in PBR pipeline.
0236   Standard_Boolean BindPBREnvBakingProgram(Standard_Integer theIndex)
0237   {
0238     if (myPBREnvBakingProgram[theIndex].IsNull())
0239     {
0240       preparePBREnvBakingProgram(theIndex);
0241     }
0242     return myContext->BindProgram(myPBREnvBakingProgram[theIndex]);
0243   }
0244 
0245   //! Generates shader program to render environment cubemap as background.
0246   Standard_EXPORT const Handle(Graphic3d_ShaderProgram)& GetBgCubeMapProgram();
0247 
0248   //! Generates shader program to render skydome background.
0249   Standard_EXPORT const Handle(Graphic3d_ShaderProgram)& GetBgSkydomeProgram();
0250 
0251   //! Generates shader program to render correctly colored quad.
0252   Standard_EXPORT const Handle(Graphic3d_ShaderProgram)& GetColoredQuadProgram();
0253 
0254   //! Resets PBR shading models to corresponding non-PBR ones if PBR is not allowed.
0255   static Graphic3d_TypeOfShadingModel PBRShadingModelFallback(
0256     Graphic3d_TypeOfShadingModel theShadingModel,
0257     Standard_Boolean             theIsPbrAllowed = Standard_False)
0258   {
0259     if (theIsPbrAllowed)
0260     {
0261       return theShadingModel;
0262     }
0263 
0264     switch (theShadingModel)
0265     {
0266       case Graphic3d_TypeOfShadingModel_Pbr:
0267         return Graphic3d_TypeOfShadingModel_Phong;
0268       case Graphic3d_TypeOfShadingModel_PbrFacet:
0269         return Graphic3d_TypeOfShadingModel_PhongFacet;
0270       default:
0271         return theShadingModel;
0272     }
0273   }
0274 
0275 public:
0276   //! Returns current state of OCCT light sources.
0277   const OpenGl_LightSourceState& LightSourceState() const { return myLightSourceState; }
0278 
0279   //! Updates state of OCCT light sources.
0280   Standard_EXPORT void UpdateLightSourceStateTo(const Handle(Graphic3d_LightSet)& theLights,
0281                                                 Standard_Integer theSpecIBLMapLevels,
0282                                                 const Handle(OpenGl_ShadowMapArray)& theShadowMaps);
0283 
0284   //! Updates state of OCCT light sources to dynamically enable/disable shadowmap.
0285   //! @param[in] theToCast  flag to enable/disable shadowmap
0286   //! @return previous flag state
0287   bool SetCastShadows(const bool theToCast)
0288   {
0289     if (myLightSourceState.ShadowMaps().IsNull() || myLightSourceState.ToCastShadows() == theToCast)
0290     {
0291       return myLightSourceState.ToCastShadows();
0292     }
0293 
0294     myLightSourceState.SetCastShadows(theToCast);
0295     switchLightPrograms();
0296     return !theToCast;
0297   }
0298 
0299   //! Invalidate state of OCCT light sources.
0300   Standard_EXPORT void UpdateLightSourceState();
0301 
0302   //! Pushes current state of OCCT light sources to specified program (only on state change).
0303   //! Note that light sources definition depends also on WorldViewState.
0304   void PushLightSourceState(const Handle(OpenGl_ShaderProgram)& theProgram) const
0305   {
0306     if (myLightSourceState.Index() != theProgram->ActiveState(OpenGl_LIGHT_SOURCES_STATE)
0307         || myWorldViewState.Index() != theProgram->ActiveState(OpenGl_WORLD_VIEW_STATE))
0308     {
0309       pushLightSourceState(theProgram);
0310     }
0311   }
0312 
0313   //! Pushes current state of OCCT light sources to specified program.
0314   Standard_EXPORT void pushLightSourceState(const Handle(OpenGl_ShaderProgram)& theProgram) const;
0315 
0316 public:
0317   //! Returns current state of OCCT projection transform.
0318   const OpenGl_ProjectionState& ProjectionState() const { return myProjectionState; }
0319 
0320   //! Updates state of OCCT projection transform.
0321   Standard_EXPORT void UpdateProjectionStateTo(const OpenGl_Mat4& theProjectionMatrix);
0322 
0323   //! Pushes current state of OCCT projection transform to specified program (only on state change).
0324   void PushProjectionState(const Handle(OpenGl_ShaderProgram)& theProgram) const
0325   {
0326     if (myProjectionState.Index() != theProgram->ActiveState(OpenGl_PROJECTION_STATE))
0327     {
0328       pushProjectionState(theProgram);
0329     }
0330   }
0331 
0332   //! Pushes current state of OCCT projection transform to specified program.
0333   Standard_EXPORT void pushProjectionState(const Handle(OpenGl_ShaderProgram)& theProgram) const;
0334 
0335 public:
0336   //! Returns current state of OCCT model-world transform.
0337   const OpenGl_ModelWorldState& ModelWorldState() const { return myModelWorldState; }
0338 
0339   //! Updates state of OCCT model-world transform.
0340   Standard_EXPORT void UpdateModelWorldStateTo(const OpenGl_Mat4& theModelWorldMatrix);
0341 
0342   //! Pushes current state of OCCT model-world transform to specified program (only on state
0343   //! change).
0344   void PushModelWorldState(const Handle(OpenGl_ShaderProgram)& theProgram) const
0345   {
0346     if (myModelWorldState.Index() != theProgram->ActiveState(OpenGl_MODEL_WORLD_STATE))
0347     {
0348       pushModelWorldState(theProgram);
0349     }
0350   }
0351 
0352   //! Pushes current state of OCCT model-world transform to specified program.
0353   Standard_EXPORT void pushModelWorldState(const Handle(OpenGl_ShaderProgram)& theProgram) const;
0354 
0355 public:
0356   //! Returns current state of OCCT world-view transform.
0357   const OpenGl_WorldViewState& WorldViewState() const { return myWorldViewState; }
0358 
0359   //! Updates state of OCCT world-view transform.
0360   Standard_EXPORT void UpdateWorldViewStateTo(const OpenGl_Mat4& theWorldViewMatrix);
0361 
0362   //! Pushes current state of OCCT world-view transform to specified program (only on state change).
0363   void PushWorldViewState(const Handle(OpenGl_ShaderProgram)& theProgram) const
0364   {
0365     if (myWorldViewState.Index() != theProgram->ActiveState(OpenGl_WORLD_VIEW_STATE))
0366     {
0367       pushWorldViewState(theProgram);
0368     }
0369   }
0370 
0371   //! Pushes current state of OCCT world-view transform to specified program.
0372   Standard_EXPORT void pushWorldViewState(const Handle(OpenGl_ShaderProgram)& theProgram) const;
0373 
0374 public:
0375   //! Updates state of OCCT clipping planes.
0376   Standard_EXPORT void UpdateClippingState();
0377 
0378   //! Reverts state of OCCT clipping planes.
0379   Standard_EXPORT void RevertClippingState();
0380 
0381   //! Pushes current state of OCCT clipping planes to specified program (only on state change).
0382   void PushClippingState(const Handle(OpenGl_ShaderProgram)& theProgram) const
0383   {
0384     if (myClippingState.Index() != theProgram->ActiveState(OpenGl_CLIP_PLANES_STATE))
0385     {
0386       pushClippingState(theProgram);
0387     }
0388   }
0389 
0390   //! Pushes current state of OCCT clipping planes to specified program.
0391   Standard_EXPORT void pushClippingState(const Handle(OpenGl_ShaderProgram)& theProgram) const;
0392 
0393 public:
0394   //! Returns current state of material.
0395   const OpenGl_MaterialState& MaterialState() const { return myMaterialState; }
0396 
0397   //! Updates state of material.
0398   void UpdateMaterialStateTo(const OpenGl_Material& theMat,
0399                              const float            theAlphaCutoff,
0400                              const bool             theToDistinguish,
0401                              const bool             theToMapTexture)
0402   {
0403     myMaterialState.Set(theMat, theAlphaCutoff, theToDistinguish, theToMapTexture);
0404     myMaterialState.Update();
0405   }
0406 
0407   //! Updates state of material.
0408   void UpdateMaterialState() { myMaterialState.Update(); }
0409 
0410   //! Pushes current state of material to specified program (only on state change).
0411   void PushMaterialState(const Handle(OpenGl_ShaderProgram)& theProgram) const
0412   {
0413     if (myMaterialState.Index() != theProgram->ActiveState(OpenGl_MATERIAL_STATE))
0414     {
0415       pushMaterialState(theProgram);
0416     }
0417   }
0418 
0419   //! Pushes current state of material to specified program.
0420   Standard_EXPORT void pushMaterialState(const Handle(OpenGl_ShaderProgram)& theProgram) const;
0421 
0422 public:
0423   //! Setup interior style line edges variables.
0424   Standard_EXPORT void PushInteriorState(const Handle(OpenGl_ShaderProgram)& theProgram,
0425                                          const Handle(Graphic3d_Aspects)&    theAspect) const;
0426 
0427 public:
0428   //! Returns state of OIT uniforms.
0429   const OpenGl_OitState& OitState() const { return myOitState; }
0430 
0431   //! Reset the state of OIT rendering pass (only on state change).
0432   void ResetOitState()
0433   {
0434     myOitState.Set(Graphic3d_RTM_BLEND_UNORDERED, 0.0f);
0435     myOitState.Update();
0436   }
0437 
0438   //! Set the state of OIT rendering pass (only on state change).
0439   //! @param[in] theMode  flag indicating whether the special output should be written for OIT
0440   //! algorithm
0441   void SetOitState(Graphic3d_RenderTransparentMethod theMode)
0442   {
0443     myOitState.Set(theMode, 0.0f);
0444     myOitState.Update();
0445   }
0446 
0447   //! Set the state of weighed OIT rendering pass (only on state change).
0448   //! @param[in] theDepthFactor  the scalar factor of depth influence to the fragment's coverage
0449   void SetWeighedOitState(float theDepthFactor)
0450   {
0451     myOitState.Set(Graphic3d_RTM_BLEND_OIT, theDepthFactor);
0452     myOitState.Update();
0453   }
0454 
0455   //! Pushes state of OIT uniforms to the specified program.
0456   void PushOitState(const Handle(OpenGl_ShaderProgram)& theProgram) const
0457   {
0458     if (theProgram->IsValid() && myOitState.Index() != theProgram->ActiveState(OpenGL_OIT_STATE))
0459     {
0460       pushOitState(theProgram);
0461     }
0462   }
0463 
0464   //! Pushes state of OIT uniforms to the specified program.
0465   Standard_EXPORT void pushOitState(const Handle(OpenGl_ShaderProgram)& theProgram) const;
0466 
0467 public:
0468   //! Pushes current state of OCCT graphics parameters to specified program.
0469   Standard_EXPORT void PushState(
0470     const Handle(OpenGl_ShaderProgram)& theProgram,
0471     Graphic3d_TypeOfShadingModel        theShadingModel = Graphic3d_TypeOfShadingModel_Unlit) const;
0472 
0473 public:
0474   //! Overwrites context
0475   void SetContext(OpenGl_Context* theCtx) { myContext = theCtx; }
0476 
0477   //! Returns true when provided context is the same as used one by shader manager.
0478   bool IsSameContext(OpenGl_Context* theCtx) const { return myContext == theCtx; }
0479 
0480   //! Choose Shading Model for filled primitives.
0481   //! Fallbacks to FACET model if there are no normal attributes.
0482   //! Fallbacks to corresponding non-PBR models if PBR is unavailable.
0483   Graphic3d_TypeOfShadingModel ChooseFaceShadingModel(Graphic3d_TypeOfShadingModel theCustomModel,
0484                                                       bool theHasNodalNormals) const
0485   {
0486     if (!myContext->ColorMask())
0487     {
0488       return Graphic3d_TypeOfShadingModel_Unlit;
0489     }
0490     Graphic3d_TypeOfShadingModel aModel =
0491       theCustomModel != Graphic3d_TypeOfShadingModel_DEFAULT ? theCustomModel : myShadingModel;
0492     switch (aModel)
0493     {
0494       case Graphic3d_TypeOfShadingModel_DEFAULT:
0495       case Graphic3d_TypeOfShadingModel_Unlit:
0496       case Graphic3d_TypeOfShadingModel_PhongFacet:
0497         return aModel;
0498       case Graphic3d_TypeOfShadingModel_Gouraud:
0499       case Graphic3d_TypeOfShadingModel_Phong:
0500         return theHasNodalNormals ? aModel : Graphic3d_TypeOfShadingModel_PhongFacet;
0501       case Graphic3d_TypeOfShadingModel_Pbr:
0502         return PBRShadingModelFallback(theHasNodalNormals ? aModel
0503                                                           : Graphic3d_TypeOfShadingModel_PbrFacet,
0504                                        IsPbrAllowed());
0505       case Graphic3d_TypeOfShadingModel_PbrFacet:
0506         return PBRShadingModelFallback(aModel, IsPbrAllowed());
0507     }
0508     return Graphic3d_TypeOfShadingModel_Unlit;
0509   }
0510 
0511   //! Choose Shading Model for line primitives.
0512   //! Fallbacks to UNLIT model if there are no normal attributes.
0513   //! Fallbacks to corresponding non-PBR models if PBR is unavailable.
0514   Graphic3d_TypeOfShadingModel ChooseLineShadingModel(Graphic3d_TypeOfShadingModel theCustomModel,
0515                                                       bool theHasNodalNormals) const
0516   {
0517     if (!myContext->ColorMask())
0518     {
0519       return Graphic3d_TypeOfShadingModel_Unlit;
0520     }
0521     Graphic3d_TypeOfShadingModel aModel =
0522       theCustomModel != Graphic3d_TypeOfShadingModel_DEFAULT ? theCustomModel : myShadingModel;
0523     switch (aModel)
0524     {
0525       case Graphic3d_TypeOfShadingModel_DEFAULT:
0526       case Graphic3d_TypeOfShadingModel_Unlit:
0527       case Graphic3d_TypeOfShadingModel_PhongFacet:
0528         return Graphic3d_TypeOfShadingModel_Unlit;
0529       case Graphic3d_TypeOfShadingModel_Gouraud:
0530       case Graphic3d_TypeOfShadingModel_Phong:
0531         return theHasNodalNormals ? aModel : Graphic3d_TypeOfShadingModel_Unlit;
0532       case Graphic3d_TypeOfShadingModel_Pbr:
0533         return PBRShadingModelFallback(theHasNodalNormals ? aModel
0534                                                           : Graphic3d_TypeOfShadingModel_Unlit,
0535                                        IsPbrAllowed());
0536       case Graphic3d_TypeOfShadingModel_PbrFacet:
0537         return Graphic3d_TypeOfShadingModel_Unlit;
0538     }
0539     return Graphic3d_TypeOfShadingModel_Unlit;
0540   }
0541 
0542   //! Choose Shading Model for Marker primitives.
0543   Graphic3d_TypeOfShadingModel ChooseMarkerShadingModel(Graphic3d_TypeOfShadingModel theCustomModel,
0544                                                         bool theHasNodalNormals) const
0545   {
0546     return ChooseLineShadingModel(theCustomModel, theHasNodalNormals);
0547   }
0548 
0549   //! Returns default Shading Model.
0550   Graphic3d_TypeOfShadingModel ShadingModel() const { return myShadingModel; }
0551 
0552   //! Sets shading model.
0553   Standard_EXPORT void SetShadingModel(const Graphic3d_TypeOfShadingModel theModel);
0554 
0555 protected:
0556   //! Define clipping planes program bits.
0557   Standard_Integer getClipPlaneBits() const
0558   {
0559     const Standard_Integer aNbPlanes = myContext->Clipping().NbClippingOrCappingOn();
0560     if (aNbPlanes <= 0)
0561     {
0562       return 0;
0563     }
0564 
0565     Standard_Integer aBits = 0;
0566     if (myContext->Clipping().HasClippingChains())
0567     {
0568       aBits |= Graphic3d_ShaderFlags_ClipChains;
0569     }
0570 
0571     if (aNbPlanes == 1)
0572     {
0573       aBits |= Graphic3d_ShaderFlags_ClipPlanes1;
0574     }
0575     else if (aNbPlanes == 2)
0576     {
0577       aBits |= Graphic3d_ShaderFlags_ClipPlanes2;
0578     }
0579     else
0580     {
0581       aBits |= Graphic3d_ShaderFlags_ClipPlanesN;
0582     }
0583     return aBits;
0584   }
0585 
0586   //! Define program bits.
0587   Standard_Integer getProgramBits(const Handle(OpenGl_TextureSet)& theTextures,
0588                                   Graphic3d_AlphaMode              theAlphaMode,
0589                                   Aspect_InteriorStyle             theInteriorStyle,
0590                                   Standard_Boolean                 theHasVertColor,
0591                                   Standard_Boolean                 theEnableEnvMap,
0592                                   Standard_Boolean                 theEnableMeshEdges) const
0593   {
0594     Standard_Integer aBits = 0;
0595     if (theAlphaMode == Graphic3d_AlphaMode_Mask || theAlphaMode == Graphic3d_AlphaMode_MaskBlend)
0596     {
0597       aBits |= Graphic3d_ShaderFlags_AlphaTest;
0598     }
0599 
0600     aBits |= getClipPlaneBits();
0601     if (theEnableMeshEdges && myContext->hasGeometryStage != OpenGl_FeatureNotAvailable)
0602     {
0603       aBits |= Graphic3d_ShaderFlags_MeshEdges;
0604       if (theInteriorStyle == Aspect_IS_HOLLOW)
0605       {
0606         aBits |= Graphic3d_ShaderFlags_AlphaTest;
0607       }
0608     }
0609 
0610     if (theEnableEnvMap)
0611     {
0612       // Environment map overwrites material texture
0613       aBits |= Graphic3d_ShaderFlags_TextureEnv;
0614     }
0615     else if (!theTextures.IsNull() && theTextures->HasNonPointSprite())
0616     {
0617       aBits |= Graphic3d_ShaderFlags_TextureRGB;
0618       if ((theTextures->TextureSetBits() & Graphic3d_TextureSetBits_Normal) != 0)
0619       {
0620         aBits |= Graphic3d_ShaderFlags_TextureNormal;
0621       }
0622     }
0623     if (theHasVertColor && theInteriorStyle != Aspect_IS_HIDDENLINE)
0624     {
0625       aBits |= Graphic3d_ShaderFlags_VertColor;
0626     }
0627 
0628     if (myOitState.ActiveMode() == Graphic3d_RTM_BLEND_OIT)
0629     {
0630       aBits |= Graphic3d_ShaderFlags_WriteOit;
0631     }
0632     else if (myOitState.ActiveMode() == Graphic3d_RTM_DEPTH_PEELING_OIT)
0633     {
0634       aBits |= Graphic3d_ShaderFlags_OitDepthPeeling;
0635     }
0636     return aBits;
0637   }
0638 
0639   //! Prepare standard GLSL program.
0640   Handle(OpenGl_ShaderProgram)& getStdProgram(Graphic3d_TypeOfShadingModel theShadingModel,
0641                                               Standard_Integer             theBits)
0642   {
0643     if (theShadingModel == Graphic3d_TypeOfShadingModel_Unlit
0644         || (theBits & Graphic3d_ShaderFlags_HasTextures) == Graphic3d_ShaderFlags_TextureEnv)
0645     {
0646       // If environment map is enabled lighting calculations are
0647       // not needed (in accordance with default OCCT behavior)
0648       Handle(OpenGl_ShaderProgram)& aProgram = myUnlitPrograms->ChangeValue(theBits);
0649       if (aProgram.IsNull())
0650       {
0651         prepareStdProgramUnlit(aProgram, theBits, false);
0652       }
0653       return aProgram;
0654     }
0655 
0656     Handle(OpenGl_ShaderProgram)& aProgram = myLightPrograms->ChangeValue(theShadingModel, theBits);
0657     if (aProgram.IsNull())
0658     {
0659       prepareStdProgramLight(aProgram, theShadingModel, theBits);
0660     }
0661     return aProgram;
0662   }
0663 
0664   //! Prepare standard GLSL program without lighting.
0665   Standard_EXPORT Standard_Boolean prepareStdProgramUnlit(Handle(OpenGl_ShaderProgram)& theProgram,
0666                                                           Standard_Integer              theBits,
0667                                                           Standard_Boolean theIsOutline = false);
0668 
0669   //! Prepare standard GLSL program with lighting.
0670   Standard_Boolean prepareStdProgramLight(Handle(OpenGl_ShaderProgram)& theProgram,
0671                                           Graphic3d_TypeOfShadingModel  theShadingModel,
0672                                           Standard_Integer              theBits)
0673   {
0674     switch (theShadingModel)
0675     {
0676       case Graphic3d_TypeOfShadingModel_Unlit:
0677         return prepareStdProgramUnlit(theProgram, theBits, false);
0678       case Graphic3d_TypeOfShadingModel_PhongFacet:
0679         return prepareStdProgramPhong(theProgram, theBits, true);
0680       case Graphic3d_TypeOfShadingModel_Gouraud:
0681         return prepareStdProgramGouraud(theProgram, theBits);
0682       case Graphic3d_TypeOfShadingModel_DEFAULT:
0683       case Graphic3d_TypeOfShadingModel_Phong:
0684         return prepareStdProgramPhong(theProgram, theBits, false);
0685       case Graphic3d_TypeOfShadingModel_Pbr:
0686         return prepareStdProgramPhong(theProgram, theBits, false, true);
0687       case Graphic3d_TypeOfShadingModel_PbrFacet:
0688         return prepareStdProgramPhong(theProgram, theBits, true, true);
0689     }
0690     return false;
0691   }
0692 
0693   //! Prepare standard GLSL program with per-vertex lighting.
0694   Standard_EXPORT Standard_Boolean
0695     prepareStdProgramGouraud(Handle(OpenGl_ShaderProgram)& theProgram,
0696                              const Standard_Integer        theBits);
0697 
0698   //! Prepare standard GLSL program with per-pixel lighting.
0699   //! @param theIsFlatNormal when TRUE, the Vertex normals will be ignored and Face normal will be
0700   //! computed instead
0701   //! @param theIsPBR when TRUE, the PBR pipeline will be activated
0702   Standard_EXPORT Standard_Boolean
0703     prepareStdProgramPhong(Handle(OpenGl_ShaderProgram)& theProgram,
0704                            const Standard_Integer        theBits,
0705                            const Standard_Boolean        theIsFlatNormal = false,
0706                            const Standard_Boolean        theIsPBR        = false);
0707 
0708   //! Bind specified program to current context and apply state.
0709   Standard_EXPORT Standard_Boolean
0710     bindProgramWithState(const Handle(OpenGl_ShaderProgram)& theProgram,
0711                          Graphic3d_TypeOfShadingModel        theShadingModel);
0712 
0713   //! Set pointer myLightPrograms to active lighting programs set from myMapOfLightPrograms
0714   Standard_EXPORT void switchLightPrograms();
0715 
0716   //! Prepare standard GLSL program for bounding box.
0717   Standard_EXPORT Standard_Boolean prepareStdProgramBoundBox();
0718 
0719   //! Prepare GLSL source for IBL generation used in PBR pipeline.
0720   Standard_EXPORT Standard_Boolean preparePBREnvBakingProgram(Standard_Integer theIndex);
0721 
0722   //! Checks whether one of PBR shading models is set as default model.
0723   Standard_Boolean IsPbrAllowed() const
0724   {
0725     return myShadingModel == Graphic3d_TypeOfShadingModel_Pbr
0726            || myShadingModel == Graphic3d_TypeOfShadingModel_PbrFacet;
0727   }
0728 
0729 protected:
0730   //! Packed properties of light source
0731   struct OpenGl_ShaderLightParameters
0732   {
0733     OpenGl_Vec4 Color;      //!< RGB color + Intensity (in .w)
0734     OpenGl_Vec4 Position;   //!< XYZ Direction or Position + IsHeadlight (in .w)
0735     OpenGl_Vec4 Direction;  //!< spot light XYZ direction + Range (in .w)
0736     OpenGl_Vec4 Parameters; //!< same as Graphic3d_CLight::PackedParams()
0737 
0738     //! Returns packed (serialized) representation of light source properties
0739     const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*>(this); }
0740 
0741     static Standard_Integer NbOfVec4() { return 4; }
0742   };
0743 
0744   //! Fake OpenGL program for tracking FFP state in the way consistent to programmable pipeline.
0745   class OpenGl_ShaderProgramFFP : public OpenGl_ShaderProgram
0746   {
0747     DEFINE_STANDARD_RTTI_INLINE(OpenGl_ShaderProgramFFP, OpenGl_ShaderProgram)
0748     friend class OpenGl_ShaderManager;
0749 
0750   protected:
0751     OpenGl_ShaderProgramFFP() {}
0752   };
0753 
0754 protected:
0755   //! Append clipping plane definition to temporary buffers.
0756   void addClippingPlane(Standard_Integer&          thePlaneId,
0757                         const Graphic3d_ClipPlane& thePlane,
0758                         const Graphic3d_Vec4d&     theEq,
0759                         const Standard_Integer     theChainFwd) const
0760   {
0761     myClipChainArray.SetValue(thePlaneId, theChainFwd);
0762     OpenGl_Vec4& aPlaneEq = myClipPlaneArray.ChangeValue(thePlaneId);
0763     aPlaneEq.x()          = float(theEq.x());
0764     aPlaneEq.y()          = float(theEq.y());
0765     aPlaneEq.z()          = float(theEq.z());
0766     aPlaneEq.w()          = float(theEq.w());
0767     if (myHasLocalOrigin)
0768     {
0769       aPlaneEq.w() = float(LocalClippingPlaneW(thePlane));
0770     }
0771     ++thePlaneId;
0772   }
0773 
0774 protected:
0775   Handle(OpenGl_ShaderProgramFFP) myFfpProgram;
0776 
0777   Graphic3d_TypeOfShadingModel myShadingModel; //!< lighting shading model
0778   OpenGl_ShaderProgramList     myProgramList;  //!< The list of shader programs
0779                                                // clang-format off
0780   Handle(OpenGl_SetOfShaderPrograms) myLightPrograms;      //!< pointer to active lighting programs matrix
0781   Handle(OpenGl_SetOfPrograms)       myUnlitPrograms;      //!< programs matrix without lighting
0782   Handle(OpenGl_SetOfPrograms)       myOutlinePrograms;    //!< programs matrix without lighting for outline presentation
0783   Handle(OpenGl_ShaderProgram)       myFontProgram;        //!< standard program for textured text
0784   NCollection_Array1<Handle(OpenGl_ShaderProgram)>
0785                                      myBlitPrograms[2];    //!< standard program for FBO blit emulation
0786   Handle(OpenGl_ShaderProgram)       myBoundBoxProgram;    //!< standard program for bounding box
0787   Handle(OpenGl_ShaderProgram)       myOitCompositingProgram[2]; //!< standard program for OIT compositing (default and MSAA).
0788   Handle(OpenGl_ShaderProgram)       myOitDepthPeelingBlendProgram[2]; //!< standard program for OIT Depth Peeling blend (default and MSAA)
0789   Handle(OpenGl_ShaderProgram)       myOitDepthPeelingFlushProgram[2]; //!< standard program for OIT Depth Peeling flush (default and MSAA)
0790   OpenGl_MapOfShaderPrograms         myMapOfLightPrograms; //!< map of lighting programs depending on lights configuration
0791 
0792   Handle(OpenGl_ShaderProgram)       myPBREnvBakingProgram[3]; //!< programs for IBL maps generation used in PBR pipeline (0 for Diffuse; 1 for Specular; 2 for fallback)
0793   Handle(Graphic3d_ShaderProgram)    myBgCubeMapProgram;       //!< program for background cubemap rendering
0794   Handle(Graphic3d_ShaderProgram)    myBgSkydomeProgram;       //!< program for background cubemap rendering
0795   Handle(Graphic3d_ShaderProgram)    myColoredQuadProgram;     //!< program for correct quad rendering
0796 
0797   Handle(OpenGl_ShaderProgram)       myStereoPrograms[Graphic3d_StereoMode_NB]; //!< standard stereo programs
0798 
0799   Handle(OpenGl_VertexBuffer)        myBoundBoxVertBuffer; //!< bounding box vertex buffer
0800 
0801   mutable Handle(OpenGl_PBREnvironment) myPBREnvironment;  //!< manager of IBL maps used in PBR pipeline
0802 
0803   OpenGl_Context*                    myContext;            //!< OpenGL context
0804 
0805 protected:
0806 
0807   OpenGl_ProjectionState             myProjectionState;    //!< State of OCCT projection  transformation
0808   OpenGl_ModelWorldState             myModelWorldState;    //!< State of OCCT model-world transformation
0809   OpenGl_WorldViewState              myWorldViewState;     //!< State of OCCT world-view  transformation
0810   OpenGl_ClippingState               myClippingState;      //!< State of OCCT clipping planes
0811   OpenGl_LightSourceState            myLightSourceState;   //!< State of OCCT light sources
0812   OpenGl_MaterialState               myMaterialState;      //!< State of Front and Back materials
0813   OpenGl_OitState                    myOitState;           //!< State of OIT uniforms
0814 
0815   gp_XYZ                             myLocalOrigin;        //!< local camera transformation
0816   Standard_Boolean                   myHasLocalOrigin;     //!< flag indicating that local camera transformation has been set
0817                                                // clang-format on
0818 
0819   mutable NCollection_Array1<Standard_Integer>             myLightTypeArray;
0820   mutable NCollection_Array1<OpenGl_ShaderLightParameters> myLightParamsArray;
0821   mutable NCollection_Array1<Graphic3d_Mat4>               myShadowMatArray;
0822   mutable NCollection_Array1<OpenGl_Vec4>                  myClipPlaneArray;
0823   mutable NCollection_Array1<OpenGl_Vec4d>                 myClipPlaneArrayFfp;
0824   mutable NCollection_Array1<Standard_Integer>             myClipChainArray;
0825 };
0826 
0827 #endif // _OpenGl_ShaderManager_HeaderFile