0030640: Visualization, Graphic3d_Camera - add option creating Projection matrix...
[occt.git] / src / OpenGl / OpenGl_ShaderManager.hxx
1 // Created on: 2013-09-26
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
4 //
5 // This file is part of Open CASCADE Technology software library.
6 //
7 // This library is free software; you can redistribute it and/or modify it under
8 // the terms of the GNU Lesser General Public License version 2.1 as published
9 // by the Free Software Foundation, with special exception defined in the file
10 // OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11 // distribution for complete text of the license and disclaimer of any warranty.
12 //
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
15
16 #ifndef _OpenGl_ShaderManager_HeaderFile
17 #define _OpenGl_ShaderManager_HeaderFile
18
19 #include <Graphic3d_ShaderManager.hxx>
20 #include <NCollection_Sequence.hxx>
21 #include <OpenGl_PBREnvironment.hxx>
22 #include <OpenGl_SetOfShaderPrograms.hxx>
23 #include <OpenGl_ShaderStates.hxx>
24 #include <OpenGl_Aspects.hxx>
25 #include <OpenGl_MaterialState.hxx>
26 #include <OpenGl_Texture.hxx>
27
28 class OpenGl_View;
29 class OpenGl_VertexBuffer;
30
31 //! List of shader programs.
32 typedef NCollection_Sequence<Handle(OpenGl_ShaderProgram)> OpenGl_ShaderProgramList;
33
34 //! This class is responsible for managing shader programs.
35 class OpenGl_ShaderManager : public Graphic3d_ShaderManager
36 {
37   DEFINE_STANDARD_RTTIEXT(OpenGl_ShaderManager, Graphic3d_ShaderManager)
38   friend class OpenGl_ShaderProgram;
39 public:
40
41   //! Creates new empty shader manager.
42   Standard_EXPORT OpenGl_ShaderManager (OpenGl_Context* theContext);
43
44   //! Releases resources of shader manager.
45   Standard_EXPORT virtual ~OpenGl_ShaderManager();
46
47   //! Release all resources.
48   Standard_EXPORT void clear();
49
50   //! Fetch sRGB state from caps and invalidates programs, if necessary.
51   Standard_EXPORT void UpdateSRgbState();
52
53   //! Return local camera transformation.
54   const gp_XYZ& LocalOrigin() const { return myLocalOrigin; }
55
56   //! Setup local camera transformation for compensating float precision issues.
57   void SetLocalOrigin (const gp_XYZ& theOrigin)
58   {
59     myLocalOrigin    = theOrigin;
60     myHasLocalOrigin = !theOrigin.IsEqual (gp_XYZ(0.0, 0.0, 0.0), gp::Resolution());
61   }
62
63   //! Return clipping plane W equation value moved considering local camera transformation.
64   Standard_Real LocalClippingPlaneW (const Graphic3d_ClipPlane& thePlane) const
65   {
66     const Graphic3d_Vec4d& anEq = thePlane.GetEquation();
67     if (myHasLocalOrigin)
68     {
69       const gp_XYZ aPos = thePlane.ToPlane().Position().Location().XYZ() - myLocalOrigin;
70       return -(anEq.x() * aPos.X() + anEq.y() * aPos.Y() + anEq.z() * aPos.Z());
71     }
72     return anEq.w();
73   }
74
75   //! Creates new shader program or re-use shared instance.
76   //! @param theProxy    [IN]  program definition
77   //! @param theShareKey [OUT] sharing key
78   //! @param theProgram  [OUT] OpenGL program
79   //! @return true on success
80   Standard_EXPORT Standard_Boolean Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
81                                            TCollection_AsciiString&               theShareKey,
82                                            Handle(OpenGl_ShaderProgram)&          theProgram);
83
84   //! Unregisters specified shader program.
85   Standard_EXPORT void Unregister (TCollection_AsciiString&      theShareKey,
86                                    Handle(OpenGl_ShaderProgram)& theProgram);
87
88   //! Returns list of registered shader programs.
89   const OpenGl_ShaderProgramList& ShaderPrograms() const { return myProgramList; }
90
91   //! Returns true if no program objects are registered in the manager.
92   Standard_Boolean IsEmpty() const { return myProgramList.IsEmpty(); }
93
94   //! Bind program for filled primitives rendering
95   Standard_Boolean BindFaceProgram (const Handle(OpenGl_TextureSet)& theTextures,
96                                     Graphic3d_TypeOfShadingModel theShadingModel,
97                                     Graphic3d_AlphaMode theAlphaMode,
98                                     Standard_Boolean theHasVertColor,
99                                     Standard_Boolean theEnableEnvMap,
100                                     const Handle(OpenGl_ShaderProgram)& theCustomProgram)
101   {
102     return BindFaceProgram (theTextures, theShadingModel, theAlphaMode, Aspect_IS_SOLID,
103                             theHasVertColor, theEnableEnvMap, false, theCustomProgram);
104   }
105
106   //! Bind program for filled primitives rendering
107   Standard_Boolean BindFaceProgram (const Handle(OpenGl_TextureSet)& theTextures,
108                                     Graphic3d_TypeOfShadingModel theShadingModel,
109                                     Graphic3d_AlphaMode theAlphaMode,
110                                     Aspect_InteriorStyle theInteriorStyle,
111                                     Standard_Boolean theHasVertColor,
112                                     Standard_Boolean theEnableEnvMap,
113                                     Standard_Boolean theEnableMeshEdges,
114                                     const Handle(OpenGl_ShaderProgram)& theCustomProgram)
115   {
116     const Graphic3d_TypeOfShadingModel aShadeModelOnFace = theShadingModel != Graphic3d_TOSM_UNLIT
117                                                         && (theTextures.IsNull() || theTextures->IsModulate())
118                                                         ? theShadingModel
119                                                         : Graphic3d_TOSM_UNLIT;
120     if (!theCustomProgram.IsNull()
121      || myContext->caps->ffpEnable)
122     {
123       return bindProgramWithState (theCustomProgram, aShadeModelOnFace);
124     }
125
126     const Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, theInteriorStyle, theHasVertColor, theEnableEnvMap, theEnableMeshEdges);
127     Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (aShadeModelOnFace, aBits);
128     return bindProgramWithState (aProgram, aShadeModelOnFace);
129   }
130
131   //! Bind program for line rendering
132   Standard_Boolean BindLineProgram (const Handle(OpenGl_TextureSet)&    theTextures,
133                                     const Aspect_TypeOfLine             theLineType,
134                                     const Graphic3d_TypeOfShadingModel  theShadingModel,
135                                     const Graphic3d_AlphaMode           theAlphaMode,
136                                     const Standard_Boolean              theHasVertColor,
137                                     const Handle(OpenGl_ShaderProgram)& theCustomProgram)
138   {
139     if (!theCustomProgram.IsNull()
140      || myContext->caps->ffpEnable)
141     {
142       return bindProgramWithState (theCustomProgram, theShadingModel);
143     }
144
145     Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, Aspect_IS_SOLID, theHasVertColor, false, false);
146     if (theLineType != Aspect_TOL_SOLID)
147     {
148       aBits |= Graphic3d_ShaderFlags_StippleLine;
149     }
150
151     Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theShadingModel, aBits);
152     return bindProgramWithState (aProgram, theShadingModel);
153   }
154
155   //! Bind program for point rendering
156   Standard_EXPORT Standard_Boolean BindMarkerProgram (const Handle(OpenGl_TextureSet)& theTextures,
157                                                       Graphic3d_TypeOfShadingModel theShadingModel,
158                                                       Graphic3d_AlphaMode theAlphaMode,
159                                                       Standard_Boolean theHasVertColor,
160                                                       const Handle(OpenGl_ShaderProgram)& theCustomProgram);
161
162   //! Bind program for rendering alpha-textured font.
163   Standard_Boolean BindFontProgram (const Handle(OpenGl_ShaderProgram)& theCustomProgram);
164
165   //! Bind program for outline rendering
166   Standard_Boolean BindOutlineProgram()
167   {
168     if (myContext->caps->ffpEnable)
169     {
170       return false;
171     }
172
173     const Standard_Integer aBits = getProgramBits (Handle(OpenGl_TextureSet)(), Graphic3d_AlphaMode_Opaque, Aspect_IS_SOLID, false, false, false);
174     if (myOutlinePrograms.IsNull())
175     {
176       myOutlinePrograms = new OpenGl_SetOfPrograms();
177     }
178     Handle(OpenGl_ShaderProgram)& aProgram = myOutlinePrograms->ChangeValue (aBits);
179     if (aProgram.IsNull())
180     {
181       prepareStdProgramUnlit (aProgram, aBits, true);
182     }
183     return bindProgramWithState (aProgram, Graphic3d_TOSM_UNLIT);
184   }
185
186   //! Bind program for FBO blit operation.
187   //! @param theNbSamples       [in] number of samples within source MSAA texture
188   //! @param theIsFallback_sRGB [in] flag indicating that destination buffer is not sRGB-ready
189   Standard_EXPORT Standard_Boolean BindFboBlitProgram (Standard_Integer theNbSamples,
190                                                        Standard_Boolean theIsFallback_sRGB);
191
192   //! Bind program for blended order-independent transparency buffers compositing.
193   Standard_EXPORT Standard_Boolean BindOitCompositingProgram (Standard_Boolean theIsMSAAEnabled);
194
195   //! Bind program for Depth Peeling order-independent transparency back color blending.
196   Standard_EXPORT Standard_Boolean BindOitDepthPeelingBlendProgram (bool theIsMSAAEnabled);
197
198   //! Bind program for Depth Peeling order-independent transparency flush.
199   Standard_EXPORT Standard_Boolean BindOitDepthPeelingFlushProgram (bool theIsMSAAEnabled);
200
201   //! Bind program for rendering stereoscopic image.
202   Standard_EXPORT Standard_Boolean BindStereoProgram (Graphic3d_StereoMode theStereoMode);
203
204   //! Bind program for rendering bounding box.
205   Standard_Boolean BindBoundBoxProgram()
206   {
207     if (myBoundBoxProgram.IsNull())
208     {
209       prepareStdProgramBoundBox();
210     }
211     return bindProgramWithState (myBoundBoxProgram, Graphic3d_TOSM_UNLIT);
212   }
213
214   //! Returns bounding box vertex buffer.
215   const Handle(OpenGl_VertexBuffer)& BoundBoxVertBuffer() const { return myBoundBoxVertBuffer; }
216
217   //! Bind program for IBL maps generation in PBR pipeline.
218   Standard_Boolean BindPBREnvBakingProgram (Standard_Integer theIndex)
219   {
220     if (myPBREnvBakingProgram[theIndex].IsNull())
221     {
222       preparePBREnvBakingProgram (theIndex);
223     }
224     return myContext->BindProgram (myPBREnvBakingProgram[theIndex]);
225   }
226
227   //! Generates shader program to render environment cubemap as background.
228   Standard_EXPORT const Handle(Graphic3d_ShaderProgram)& GetBgCubeMapProgram ();
229
230   //! Resets PBR shading models to corresponding non-PBR ones if PBR is not allowed.
231   static Graphic3d_TypeOfShadingModel PBRShadingModelFallback (Graphic3d_TypeOfShadingModel theShadingModel,
232                                                                Standard_Boolean             theIsPbrAllowed = Standard_False)
233   {
234     if (theIsPbrAllowed)
235     {
236       return theShadingModel;
237     }
238
239     switch (theShadingModel)
240     {
241       case Graphic3d_TOSM_PBR:       return Graphic3d_TOSM_FRAGMENT;
242       case Graphic3d_TOSM_PBR_FACET: return Graphic3d_TOSM_FACET;
243       default: return theShadingModel;
244     }
245   }
246
247 public:
248
249   //! Returns current state of OCCT light sources.
250   const OpenGl_LightSourceState& LightSourceState() const { return myLightSourceState; }
251
252   //! Updates state of OCCT light sources.
253   Standard_EXPORT void UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights,
254                                                  Standard_Integer theSpecIBLMapLevels,
255                                                  const Handle(OpenGl_ShadowMapArray)& theShadowMaps);
256
257   //! Updates state of OCCT light sources to dynamically enable/disable shadowmap.
258   //! @param theToCast [in] flag to enable/disable shadowmap
259   //! @return previous flag state
260   bool SetCastShadows (const bool theToCast)
261   {
262     if (myLightSourceState.ShadowMaps().IsNull()
263      || myLightSourceState.ToCastShadows() == theToCast)
264         {
265       return myLightSourceState.ToCastShadows();
266     }
267
268     myLightSourceState.SetCastShadows (theToCast);
269     switchLightPrograms();
270     return !theToCast;
271   }
272
273   //! Invalidate state of OCCT light sources.
274   Standard_EXPORT void UpdateLightSourceState();
275
276   //! Pushes current state of OCCT light sources to specified program (only on state change).
277   //! Note that light sources definition depends also on WorldViewState.
278   void PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
279   {
280     if (myLightSourceState.Index() != theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)
281      || myWorldViewState.Index()   != theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
282     {
283       pushLightSourceState (theProgram);
284     }
285   }
286
287   //! Pushes current state of OCCT light sources to specified program.
288   Standard_EXPORT void pushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
289
290 public:
291
292   //! Returns current state of OCCT projection transform.
293   const OpenGl_ProjectionState& ProjectionState() const { return myProjectionState; }
294
295   //! Updates state of OCCT projection transform.
296   Standard_EXPORT void UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix);
297
298   //! Pushes current state of OCCT projection transform to specified program (only on state change).
299   void PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
300   {
301     if (myProjectionState.Index() != theProgram->ActiveState (OpenGl_PROJECTION_STATE))
302     {
303       pushProjectionState (theProgram);
304     }
305   }
306
307   //! Pushes current state of OCCT projection transform to specified program.
308   Standard_EXPORT void pushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
309
310 public:
311
312   //! Returns current state of OCCT model-world transform.
313   const OpenGl_ModelWorldState& ModelWorldState() const { return myModelWorldState; }
314
315   //! Updates state of OCCT model-world transform.
316   Standard_EXPORT void UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix);
317
318   //! Pushes current state of OCCT model-world transform to specified program (only on state change).
319   void PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
320   {
321     if (myModelWorldState.Index() != theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
322     {
323       pushModelWorldState (theProgram);
324     }
325   }
326
327   //! Pushes current state of OCCT model-world transform to specified program.
328   Standard_EXPORT void pushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
329
330 public:
331
332   //! Returns current state of OCCT world-view transform.
333   const OpenGl_WorldViewState& WorldViewState() const { return myWorldViewState; }
334
335   //! Updates state of OCCT world-view transform.
336   Standard_EXPORT void UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix);
337
338   //! Pushes current state of OCCT world-view transform to specified program (only on state change).
339   void PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
340   {
341     if (myWorldViewState.Index() != theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
342     {
343       pushWorldViewState (theProgram);
344     }
345   }
346
347   //! Pushes current state of OCCT world-view transform to specified program.
348   Standard_EXPORT void pushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
349
350 public:
351
352   //! Updates state of OCCT clipping planes.
353   Standard_EXPORT void UpdateClippingState();
354
355   //! Reverts state of OCCT clipping planes.
356   Standard_EXPORT void RevertClippingState();
357
358   //! Pushes current state of OCCT clipping planes to specified program (only on state change).
359   void PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
360   {
361     if (myClippingState.Index() != theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
362     {
363       pushClippingState (theProgram);
364     }
365   }
366
367   //! Pushes current state of OCCT clipping planes to specified program.
368   Standard_EXPORT void pushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
369
370 public:
371
372   //! Returns current state of material.
373   const OpenGl_MaterialState& MaterialState() const { return myMaterialState; }
374
375   //! Updates state of material.
376   void UpdateMaterialStateTo (const OpenGl_Material& theFrontMat,
377                               const OpenGl_Material& theBackMat,
378                               const float theAlphaCutoff,
379                               const bool theToDistinguish,
380                               const bool theToMapTexture)
381   {
382     myMaterialState.Set (theFrontMat, theBackMat, theAlphaCutoff, theToDistinguish, theToMapTexture);
383     myMaterialState.Update();
384   }
385
386   //! Updates state of material.
387   void UpdateMaterialState()
388   {
389     myMaterialState.Update();
390   }
391
392   //! Pushes current state of material to specified program (only on state change).
393   void PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
394   {
395     if (myMaterialState.Index() != theProgram->ActiveState (OpenGl_MATERIAL_STATE))
396     {
397       pushMaterialState (theProgram);
398     }
399   }
400
401   //! Pushes current state of material to specified program.
402   Standard_EXPORT void pushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
403
404 public:
405
406   //! Setup interior style line edges variables.
407   Standard_EXPORT void PushInteriorState (const Handle(OpenGl_ShaderProgram)& theProgram,
408                                           const Handle(Graphic3d_Aspects)& theAspect) const;
409
410 public:
411
412   //! Returns state of OIT uniforms.
413   const OpenGl_OitState& OitState() const { return myOitState; }
414
415   //! Reset the state of OIT rendering pass (only on state change).
416   void ResetOitState()
417   {
418     myOitState.Set (Graphic3d_RTM_BLEND_UNORDERED, 0.0f);
419     myOitState.Update();
420   }
421
422   //! Set the state of OIT rendering pass (only on state change).
423   //! @param theMode [in] flag indicating whether the special output should be written for OIT algorithm
424   void SetOitState (Graphic3d_RenderTransparentMethod theMode)
425   {
426     myOitState.Set (theMode, 0.0f);
427     myOitState.Update();
428   }
429
430   //! Set the state of weighed OIT rendering pass (only on state change).
431   //! @param theDepthFactor [in] the scalar factor of depth influence to the fragment's coverage
432   void SetWeighedOitState (float theDepthFactor)
433   {
434     myOitState.Set (Graphic3d_RTM_BLEND_OIT, theDepthFactor);
435     myOitState.Update();
436   }
437
438   //! Pushes state of OIT uniforms to the specified program.
439   void PushOitState (const Handle(OpenGl_ShaderProgram)& theProgram) const
440   {
441     if (theProgram->IsValid()
442      && myOitState.Index() != theProgram->ActiveState (OpenGL_OIT_STATE))
443     {
444       pushOitState (theProgram);
445     }
446   }
447
448   //! Pushes state of OIT uniforms to the specified program.
449   Standard_EXPORT void pushOitState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
450
451 public:
452
453   //! Pushes current state of OCCT graphics parameters to specified program.
454   Standard_EXPORT void PushState (const Handle(OpenGl_ShaderProgram)& theProgram,
455                                   Graphic3d_TypeOfShadingModel theShadingModel = Graphic3d_TOSM_UNLIT) const;
456
457 public:
458
459   //! Overwrites context
460   void SetContext (OpenGl_Context* theCtx)
461   {
462     myContext = theCtx;
463   }
464
465   //! Returns true when provided context is the same as used one by shader manager.
466   bool IsSameContext (OpenGl_Context* theCtx) const
467   {
468     return myContext == theCtx;
469   }
470
471   //! Choose Shading Model for filled primitives.
472   //! Fallbacks to FACET model if there are no normal attributes.
473   //! Fallbacks to corresponding non-PBR models if PBR is unavailable.
474   Graphic3d_TypeOfShadingModel ChooseFaceShadingModel (Graphic3d_TypeOfShadingModel theCustomModel,
475                                                        bool theHasNodalNormals) const
476   {
477     if (!myContext->ColorMask())
478     {
479       return Graphic3d_TOSM_UNLIT;
480     }
481     Graphic3d_TypeOfShadingModel aModel = theCustomModel != Graphic3d_TOSM_DEFAULT ? theCustomModel : myShadingModel;
482     switch (aModel)
483     {
484       case Graphic3d_TOSM_DEFAULT:
485       case Graphic3d_TOSM_UNLIT:
486       case Graphic3d_TOSM_FACET:
487         return aModel;
488       case Graphic3d_TOSM_VERTEX:
489       case Graphic3d_TOSM_FRAGMENT:
490         return theHasNodalNormals ? aModel : Graphic3d_TOSM_FACET;
491       case Graphic3d_TOSM_PBR:
492         return PBRShadingModelFallback (theHasNodalNormals ? aModel : Graphic3d_TOSM_PBR_FACET, IsPbrAllowed());
493       case Graphic3d_TOSM_PBR_FACET:
494         return PBRShadingModelFallback (aModel, IsPbrAllowed());
495     }
496     return Graphic3d_TOSM_UNLIT;
497   }
498
499   //! Choose Shading Model for line primitives.
500   //! Fallbacks to UNLIT model if there are no normal attributes.
501   //! Fallbacks to corresponding non-PBR models if PBR is unavailable.
502   Graphic3d_TypeOfShadingModel ChooseLineShadingModel (Graphic3d_TypeOfShadingModel theCustomModel,
503                                                        bool theHasNodalNormals) const
504   {
505     if (!myContext->ColorMask())
506     {
507       return Graphic3d_TOSM_UNLIT;
508     }
509     Graphic3d_TypeOfShadingModel aModel = theCustomModel != Graphic3d_TOSM_DEFAULT ? theCustomModel : myShadingModel;
510     switch (aModel)
511     {
512       case Graphic3d_TOSM_DEFAULT:
513       case Graphic3d_TOSM_UNLIT:
514       case Graphic3d_TOSM_FACET:
515         return Graphic3d_TOSM_UNLIT;
516       case Graphic3d_TOSM_VERTEX:
517       case Graphic3d_TOSM_FRAGMENT:
518         return theHasNodalNormals ? aModel : Graphic3d_TOSM_UNLIT;
519       case Graphic3d_TOSM_PBR:
520         return PBRShadingModelFallback (theHasNodalNormals ? aModel : Graphic3d_TOSM_UNLIT, IsPbrAllowed());
521       case Graphic3d_TOSM_PBR_FACET:
522         return Graphic3d_TOSM_UNLIT;
523     }
524     return Graphic3d_TOSM_UNLIT;
525   }
526
527   //! Choose Shading Model for Marker primitives.
528   Graphic3d_TypeOfShadingModel ChooseMarkerShadingModel (Graphic3d_TypeOfShadingModel theCustomModel,
529                                                          bool theHasNodalNormals) const
530   {
531     return ChooseLineShadingModel (theCustomModel, theHasNodalNormals);
532   }
533
534   //! Returns default Shading Model.
535   Graphic3d_TypeOfShadingModel ShadingModel() const { return myShadingModel; }
536
537   //! Sets shading model.
538   Standard_EXPORT void SetShadingModel (const Graphic3d_TypeOfShadingModel theModel);
539
540 protected:
541
542   //! Define clipping planes program bits.
543   Standard_Integer getClipPlaneBits() const
544   {
545     const Standard_Integer aNbPlanes = myContext->Clipping().NbClippingOrCappingOn();
546     if (aNbPlanes <= 0)
547     {
548       return 0;
549     }
550
551     Standard_Integer aBits = 0;
552     if (myContext->Clipping().HasClippingChains())
553     {
554       aBits |= Graphic3d_ShaderFlags_ClipChains;
555     }
556
557     if (aNbPlanes == 1)
558     {
559       aBits |= Graphic3d_ShaderFlags_ClipPlanes1;
560     }
561     else if (aNbPlanes == 2)
562     {
563       aBits |= Graphic3d_ShaderFlags_ClipPlanes2;
564     }
565     else
566     {
567       aBits |= Graphic3d_ShaderFlags_ClipPlanesN;
568     }
569     return aBits;
570   }
571
572   //! Define program bits.
573   Standard_Integer getProgramBits (const Handle(OpenGl_TextureSet)& theTextures,
574                                    Graphic3d_AlphaMode theAlphaMode,
575                                    Aspect_InteriorStyle theInteriorStyle,
576                                    Standard_Boolean theHasVertColor,
577                                    Standard_Boolean theEnableEnvMap,
578                                    Standard_Boolean theEnableMeshEdges) const
579   {
580     Standard_Integer aBits = 0;
581     if (theAlphaMode == Graphic3d_AlphaMode_Mask
582      || theAlphaMode == Graphic3d_AlphaMode_MaskBlend)
583     {
584       aBits |= Graphic3d_ShaderFlags_AlphaTest;
585     }
586
587     aBits |= getClipPlaneBits();
588     if (theEnableMeshEdges
589      && myContext->hasGeometryStage != OpenGl_FeatureNotAvailable)
590     {
591       aBits |= Graphic3d_ShaderFlags_MeshEdges;
592       if (theInteriorStyle == Aspect_IS_HOLLOW)
593       {
594         aBits |= Graphic3d_ShaderFlags_AlphaTest;
595       }
596     }
597
598     if (theEnableEnvMap)
599     {
600       // Environment map overwrites material texture
601       aBits |= Graphic3d_ShaderFlags_TextureEnv;
602     }
603     else if (!theTextures.IsNull()
604            && theTextures->HasNonPointSprite())
605     {
606       aBits |= Graphic3d_ShaderFlags_TextureRGB;
607       if ((theTextures->TextureSetBits() & Graphic3d_TextureSetBits_Normal) != 0)
608       {
609         aBits |= Graphic3d_ShaderFlags_TextureNormal;
610       }
611     }
612     if (theHasVertColor
613      && theInteriorStyle != Aspect_IS_HIDDENLINE)
614     {
615       aBits |= Graphic3d_ShaderFlags_VertColor;
616     }
617
618     if (myOitState.ActiveMode() == Graphic3d_RTM_BLEND_OIT)
619     {
620       aBits |= Graphic3d_ShaderFlags_WriteOit;
621     }
622     else if (myOitState.ActiveMode() == Graphic3d_RTM_DEPTH_PEELING_OIT)
623     {
624       aBits |= Graphic3d_ShaderFlags_OitDepthPeeling;
625     }
626     return aBits;
627   }
628
629   //! Prepare standard GLSL program.
630   Handle(OpenGl_ShaderProgram)& getStdProgram (Graphic3d_TypeOfShadingModel theShadingModel,
631                                                Standard_Integer theBits)
632   {
633     if (theShadingModel == Graphic3d_TOSM_UNLIT
634      || (theBits & Graphic3d_ShaderFlags_HasTextures) == Graphic3d_ShaderFlags_TextureEnv)
635     {
636       // If environment map is enabled lighting calculations are
637       // not needed (in accordance with default OCCT behavior)
638       Handle(OpenGl_ShaderProgram)& aProgram = myUnlitPrograms->ChangeValue (theBits);
639       if (aProgram.IsNull())
640       {
641         prepareStdProgramUnlit (aProgram, theBits, false);
642       }
643       return aProgram;
644     }
645
646     Handle(OpenGl_ShaderProgram)& aProgram = myLightPrograms->ChangeValue (theShadingModel, theBits);
647     if (aProgram.IsNull())
648     {
649       prepareStdProgramLight (aProgram, theShadingModel, theBits);
650     }
651     return aProgram;
652   }
653
654   //! Prepare standard GLSL program without lighting.
655   Standard_EXPORT Standard_Boolean prepareStdProgramUnlit (Handle(OpenGl_ShaderProgram)& theProgram,
656                                                            Standard_Integer theBits,
657                                                            Standard_Boolean theIsOutline = false);
658
659   //! Prepare standard GLSL program with lighting.
660   Standard_Boolean prepareStdProgramLight (Handle(OpenGl_ShaderProgram)& theProgram,
661                                            Graphic3d_TypeOfShadingModel theShadingModel,
662                                            Standard_Integer theBits)
663   {
664     switch (theShadingModel)
665     {
666       case Graphic3d_TOSM_UNLIT:     return prepareStdProgramUnlit  (theProgram, theBits, false);
667       case Graphic3d_TOSM_FACET:     return prepareStdProgramPhong  (theProgram, theBits, true);
668       case Graphic3d_TOSM_VERTEX:    return prepareStdProgramGouraud(theProgram, theBits);
669       case Graphic3d_TOSM_DEFAULT:
670       case Graphic3d_TOSM_FRAGMENT:  return prepareStdProgramPhong  (theProgram, theBits, false);
671       case Graphic3d_TOSM_PBR:       return prepareStdProgramPhong  (theProgram, theBits, false, true);
672       case Graphic3d_TOSM_PBR_FACET: return prepareStdProgramPhong  (theProgram, theBits, true, true);
673     }
674     return false;
675   }
676
677   //! Prepare standard GLSL program with per-vertex lighting.
678   Standard_EXPORT Standard_Boolean prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
679                                                              const Standard_Integer        theBits);
680
681   //! Prepare standard GLSL program with per-pixel lighting.
682   //! @param theIsFlatNormal when TRUE, the Vertex normals will be ignored and Face normal will be computed instead
683   //! @param theIsPBR when TRUE, the PBR pipeline will be activated
684   Standard_EXPORT Standard_Boolean prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
685                                                            const Standard_Integer        theBits,
686                                                            const Standard_Boolean        theIsFlatNormal = false,
687                                                            const Standard_Boolean        theIsPBR = false);
688
689   //! Bind specified program to current context and apply state.
690   Standard_EXPORT Standard_Boolean bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram,
691                                                          Graphic3d_TypeOfShadingModel theShadingModel);
692
693   //! Set pointer myLightPrograms to active lighting programs set from myMapOfLightPrograms
694   Standard_EXPORT void switchLightPrograms();
695
696   //! Prepare standard GLSL program for bounding box.
697   Standard_EXPORT Standard_Boolean prepareStdProgramBoundBox();
698
699   //! Prepare GLSL source for IBL generation used in PBR pipeline.
700   Standard_EXPORT Standard_Boolean preparePBREnvBakingProgram (Standard_Integer theIndex);
701
702   //! Checks whether one of PBR shading models is set as default model.
703   Standard_Boolean IsPbrAllowed() const { return myShadingModel == Graphic3d_TOSM_PBR
704                                               || myShadingModel == Graphic3d_TOSM_PBR_FACET; }
705
706 protected:
707
708   //! Packed properties of light source
709   struct OpenGl_ShaderLightParameters
710   {
711     OpenGl_Vec4 Color;      //!< RGB color + Intensity (in .w)
712     OpenGl_Vec4 Position;   //!< XYZ Direction or Position + IsHeadlight (in .w)
713     OpenGl_Vec4 Direction;  //!< spot light XYZ direction + Range (in .w)
714     OpenGl_Vec4 Parameters; //!< same as Graphic3d_CLight::PackedParams()
715
716     //! Returns packed (serialized) representation of light source properties
717     const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
718     static Standard_Integer NbOfVec4() { return 4; }
719   };
720
721   //! Fake OpenGL program for tracking FFP state in the way consistent to programmable pipeline.
722   class OpenGl_ShaderProgramFFP : public OpenGl_ShaderProgram
723   {
724     DEFINE_STANDARD_RTTI_INLINE(OpenGl_ShaderProgramFFP, OpenGl_ShaderProgram)
725     friend class OpenGl_ShaderManager;
726   protected:
727     OpenGl_ShaderProgramFFP() {}
728   };
729
730 protected:
731
732   //! Append clipping plane definition to temporary buffers.
733   void addClippingPlane (Standard_Integer& thePlaneId,
734                          const Graphic3d_ClipPlane& thePlane,
735                          const Graphic3d_Vec4d& theEq,
736                          const Standard_Integer theChainFwd) const
737   {
738     myClipChainArray.SetValue (thePlaneId, theChainFwd);
739     OpenGl_Vec4& aPlaneEq = myClipPlaneArray.ChangeValue (thePlaneId);
740     aPlaneEq.x() = float(theEq.x());
741     aPlaneEq.y() = float(theEq.y());
742     aPlaneEq.z() = float(theEq.z());
743     aPlaneEq.w() = float(theEq.w());
744     if (myHasLocalOrigin)
745     {
746       aPlaneEq.w() = float(LocalClippingPlaneW (thePlane));
747     }
748     ++thePlaneId;
749   }
750
751 protected:
752
753   Handle(OpenGl_ShaderProgramFFP)    myFfpProgram;
754
755   Graphic3d_TypeOfShadingModel       myShadingModel;       //!< lighting shading model
756   OpenGl_ShaderProgramList           myProgramList;        //!< The list of shader programs
757   Handle(OpenGl_SetOfShaderPrograms) myLightPrograms;      //!< pointer to active lighting programs matrix
758   Handle(OpenGl_SetOfPrograms)       myUnlitPrograms;      //!< programs matrix without lighting
759   Handle(OpenGl_SetOfPrograms)       myOutlinePrograms;    //!< programs matrix without lighting for outline presentation
760   Handle(OpenGl_ShaderProgram)       myFontProgram;        //!< standard program for textured text
761   NCollection_Array1<Handle(OpenGl_ShaderProgram)>
762                                      myBlitPrograms[2];    //!< standard program for FBO blit emulation
763   Handle(OpenGl_ShaderProgram)       myBoundBoxProgram;    //!< standard program for bounding box
764   Handle(OpenGl_ShaderProgram)       myOitCompositingProgram[2]; //!< standard program for OIT compositing (default and MSAA).
765   Handle(OpenGl_ShaderProgram)       myOitDepthPeelingBlendProgram[2]; //!< standard program for OIT Depth Peeling blend (default and MSAA)
766   Handle(OpenGl_ShaderProgram)       myOitDepthPeelingFlushProgram[2]; //!< standard program for OIT Depth Peeling flush (default and MSAA)
767   OpenGl_MapOfShaderPrograms         myMapOfLightPrograms; //!< map of lighting programs depending on lights configuration
768
769   Handle(OpenGl_ShaderProgram)       myPBREnvBakingProgram[3]; //!< programs for IBL maps generation used in PBR pipeline (0 for Diffuse; 1 for Specular; 2 for fallback)
770   Handle(Graphic3d_ShaderProgram)    myBgCubeMapProgram;   //!< program for background cubemap rendering
771
772   Handle(OpenGl_ShaderProgram)       myStereoPrograms[Graphic3d_StereoMode_NB]; //!< standard stereo programs
773
774   Handle(OpenGl_VertexBuffer)        myBoundBoxVertBuffer; //!< bounding box vertex buffer
775
776   mutable Handle(OpenGl_PBREnvironment) myPBREnvironment;  //!< manager of IBL maps used in PBR pipeline
777
778   OpenGl_Context*                    myContext;            //!< OpenGL context
779
780 protected:
781
782   OpenGl_ProjectionState             myProjectionState;    //!< State of OCCT projection  transformation
783   OpenGl_ModelWorldState             myModelWorldState;    //!< State of OCCT model-world transformation
784   OpenGl_WorldViewState              myWorldViewState;     //!< State of OCCT world-view  transformation
785   OpenGl_ClippingState               myClippingState;      //!< State of OCCT clipping planes
786   OpenGl_LightSourceState            myLightSourceState;   //!< State of OCCT light sources
787   OpenGl_MaterialState               myMaterialState;      //!< State of Front and Back materials
788   OpenGl_OitState                    myOitState;           //!< State of OIT uniforms
789
790   gp_XYZ                             myLocalOrigin;        //!< local camera transformation
791   Standard_Boolean                   myHasLocalOrigin;     //!< flag indicating that local camera transformation has been set
792
793   mutable NCollection_Array1<Standard_Integer>             myLightTypeArray;
794   mutable NCollection_Array1<OpenGl_ShaderLightParameters> myLightParamsArray;
795   mutable NCollection_Array1<Graphic3d_Mat4>               myShadowMatArray;
796   mutable NCollection_Array1<OpenGl_Vec4>                  myClipPlaneArray;
797   mutable NCollection_Array1<OpenGl_Vec4d>                 myClipPlaneArrayFfp;
798   mutable NCollection_Array1<Standard_Integer>             myClipChainArray;
799
800 };
801
802 #endif // _OpenGl_ShaderManager_HeaderFile