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