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