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   //! Return local camera transformation.
LocalOrigin() const54   const gp_XYZ& LocalOrigin() const { return myLocalOrigin; }
55 
56   //! Setup local camera transformation for compensating float precision issues.
SetLocalOrigin(const gp_XYZ & theOrigin)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.
LocalClippingPlaneW(const Graphic3d_ClipPlane & thePlane) const64   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   Standard_EXPORT const OpenGl_ShaderProgramList& ShaderPrograms() const;
90 
91   //! Returns true if no program objects are registered in the manager.
92   Standard_EXPORT Standard_Boolean IsEmpty() const;
93 
94   //! Bind program for filled primitives rendering
BindFaceProgram(const Handle (OpenGl_TextureSet)& theTextures,Graphic3d_TypeOfShadingModel theShadingModel,Graphic3d_AlphaMode theAlphaMode,Standard_Boolean theHasVertColor,Standard_Boolean theEnableEnvMap,const Handle (OpenGl_ShaderProgram)& theCustomProgram)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
BindFaceProgram(const Handle (OpenGl_TextureSet)& theTextures,Graphic3d_TypeOfShadingModel theShadingModel,Graphic3d_AlphaMode theAlphaMode,Aspect_InteriorStyle theInteriorStyle,Standard_Boolean theHasVertColor,Standard_Boolean theEnableEnvMap,Standard_Boolean theEnableMeshEdges,const Handle (OpenGl_ShaderProgram)& theCustomProgram)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     if (!theCustomProgram.IsNull()
117      || myContext->caps->ffpEnable)
118     {
119       return bindProgramWithState (theCustomProgram);
120     }
121 
122     const Graphic3d_TypeOfShadingModel aShadeModelOnFace = theShadingModel != Graphic3d_TOSM_UNLIT
123                                                         && (theTextures.IsNull() || theTextures->IsModulate())
124                                                         ? theShadingModel
125                                                         : Graphic3d_TOSM_UNLIT;
126     const Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, theInteriorStyle, theHasVertColor, theEnableEnvMap, theEnableMeshEdges);
127     Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (aShadeModelOnFace, aBits);
128     return bindProgramWithState (aProgram);
129   }
130 
131   //! Bind program for line rendering
BindLineProgram(const Handle (OpenGl_TextureSet)& theTextures,const Aspect_TypeOfLine theLineType,const Graphic3d_TypeOfShadingModel theShadingModel,const Graphic3d_AlphaMode theAlphaMode,const Standard_Boolean theHasVertColor,const Handle (OpenGl_ShaderProgram)& theCustomProgram)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);
143     }
144 
145     Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, Aspect_IS_SOLID, theHasVertColor, false, false);
146     if (theLineType != Aspect_TOL_SOLID)
147     {
148       aBits |= OpenGl_PO_StippleLine;
149     }
150 
151     Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theShadingModel, aBits);
152     return bindProgramWithState (aProgram);
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.
BindFontProgram(const Handle (OpenGl_ShaderProgram)& theCustomProgram)163   Standard_Boolean BindFontProgram (const Handle(OpenGl_ShaderProgram)& theCustomProgram)
164   {
165     if (!theCustomProgram.IsNull()
166      || myContext->caps->ffpEnable)
167     {
168       return bindProgramWithState (theCustomProgram);
169     }
170 
171     if (myFontProgram.IsNull())
172     {
173       prepareStdProgramFont();
174     }
175 
176     return bindProgramWithState (myFontProgram);
177   }
178 
179   //! Bind program for outline rendering
BindOutlineProgram()180   Standard_Boolean BindOutlineProgram()
181   {
182     if (myContext->caps->ffpEnable)
183     {
184       return false;
185     }
186 
187     const Standard_Integer aBits = getProgramBits (Handle(OpenGl_TextureSet)(), Graphic3d_AlphaMode_Opaque, Aspect_IS_SOLID, false, false, false);
188     if (myOutlinePrograms.IsNull())
189     {
190       myOutlinePrograms = new OpenGl_SetOfPrograms();
191     }
192     Handle(OpenGl_ShaderProgram)& aProgram = myOutlinePrograms->ChangeValue (aBits);
193     if (aProgram.IsNull())
194     {
195       prepareStdProgramUnlit (aProgram, aBits, true);
196     }
197     return bindProgramWithState (aProgram);
198   }
199 
200   //! Bind program for FBO blit operation.
BindFboBlitProgram()201   Standard_Boolean BindFboBlitProgram()
202   {
203     if (myBlitProgram.IsNull())
204     {
205       prepareStdProgramFboBlit();
206     }
207     return !myBlitProgram.IsNull()
208          && myContext->BindProgram (myBlitProgram);
209   }
210 
211   //! Bind program for blended order-independent transparency buffers compositing.
BindOitCompositingProgram(const Standard_Boolean theIsMSAAEnabled)212   Standard_Boolean BindOitCompositingProgram (const Standard_Boolean theIsMSAAEnabled)
213   {
214     const Standard_Integer aProgramIdx = theIsMSAAEnabled ? 1 : 0;
215     if (myOitCompositingProgram[aProgramIdx].IsNull())
216     {
217       prepareStdProgramOitCompositing (theIsMSAAEnabled);
218     }
219 
220     const Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram [aProgramIdx];
221     return !aProgram.IsNull() && myContext->BindProgram (aProgram);
222   }
223 
224   //! Bind program for rendering stereoscopic image.
BindStereoProgram(const Graphic3d_StereoMode theStereoMode)225   Standard_Boolean BindStereoProgram (const Graphic3d_StereoMode theStereoMode)
226   {
227     if (theStereoMode < 0 || theStereoMode >= Graphic3d_StereoMode_NB)
228     {
229       return Standard_False;
230     }
231 
232     if (myStereoPrograms[theStereoMode].IsNull())
233     {
234       prepareStdProgramStereo (myStereoPrograms[theStereoMode], theStereoMode);
235     }
236     const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[theStereoMode];
237     return !aProgram.IsNull()
238          && myContext->BindProgram (aProgram);
239   }
240 
241   //! Bind program for rendering bounding box.
BindBoundBoxProgram()242   Standard_Boolean BindBoundBoxProgram()
243   {
244     if (myBoundBoxProgram.IsNull())
245     {
246       prepareStdProgramBoundBox();
247     }
248     return bindProgramWithState (myBoundBoxProgram);
249   }
250 
251   //! Returns bounding box vertex buffer.
Handle(OpenGl_VertexBuffer)252   const Handle(OpenGl_VertexBuffer)& BoundBoxVertBuffer() const { return myBoundBoxVertBuffer; }
253 
254   //! Generates shader program to render environment cubemap as background.
255   Standard_EXPORT const Handle(Graphic3d_ShaderProgram)& GetBgCubeMapProgram ();
256 
257 public:
258 
259   //! Returns current state of OCCT light sources.
LightSourceState() const260   const OpenGl_LightSourceState& LightSourceState() const { return myLightSourceState; }
261 
262   //! Updates state of OCCT light sources.
263   Standard_EXPORT void UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights);
264 
265   //! Invalidate state of OCCT light sources.
266   Standard_EXPORT void UpdateLightSourceState();
267 
268   //! Pushes current state of OCCT light sources to specified program (only on state change).
PushLightSourceState(const Handle (OpenGl_ShaderProgram)& theProgram) const269   void PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
270   {
271     if (myLightSourceState.Index() != theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE))
272     {
273       pushLightSourceState (theProgram);
274     }
275   }
276 
277   //! Pushes current state of OCCT light sources to specified program.
278   Standard_EXPORT void pushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
279 
280 public:
281 
282   //! Returns current state of OCCT projection transform.
ProjectionState() const283   const OpenGl_ProjectionState& ProjectionState() const { return myProjectionState; }
284 
285   //! Updates state of OCCT projection transform.
286   Standard_EXPORT void UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix);
287 
288   //! Pushes current state of OCCT projection transform to specified program (only on state change).
PushProjectionState(const Handle (OpenGl_ShaderProgram)& theProgram) const289   void PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
290   {
291     if (myProjectionState.Index() != theProgram->ActiveState (OpenGl_PROJECTION_STATE))
292     {
293       pushProjectionState (theProgram);
294     }
295   }
296 
297   //! Pushes current state of OCCT projection transform to specified program.
298   Standard_EXPORT void pushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
299 
300 public:
301 
302   //! Returns current state of OCCT model-world transform.
ModelWorldState() const303   const OpenGl_ModelWorldState& ModelWorldState() const { return myModelWorldState; }
304 
305   //! Updates state of OCCT model-world transform.
306   Standard_EXPORT void UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix);
307 
308   //! Pushes current state of OCCT model-world transform to specified program (only on state change).
PushModelWorldState(const Handle (OpenGl_ShaderProgram)& theProgram) const309   void PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
310   {
311     if (myModelWorldState.Index() != theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
312     {
313       pushModelWorldState (theProgram);
314     }
315   }
316 
317   //! Pushes current state of OCCT model-world transform to specified program.
318   Standard_EXPORT void pushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
319 
320 public:
321 
322   //! Returns current state of OCCT world-view transform.
WorldViewState() const323   const OpenGl_WorldViewState& WorldViewState() const { return myWorldViewState; }
324 
325   //! Updates state of OCCT world-view transform.
326   Standard_EXPORT void UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix);
327 
328   //! Pushes current state of OCCT world-view transform to specified program (only on state change).
PushWorldViewState(const Handle (OpenGl_ShaderProgram)& theProgram) const329   void PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
330   {
331     if (myWorldViewState.Index() != theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
332     {
333       pushWorldViewState (theProgram);
334     }
335   }
336 
337   //! Pushes current state of OCCT world-view transform to specified program.
338   Standard_EXPORT void pushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
339 
340 public:
341 
342   //! Updates state of OCCT clipping planes.
343   Standard_EXPORT void UpdateClippingState();
344 
345   //! Reverts state of OCCT clipping planes.
346   Standard_EXPORT void RevertClippingState();
347 
348   //! Pushes current state of OCCT clipping planes to specified program (only on state change).
PushClippingState(const Handle (OpenGl_ShaderProgram)& theProgram) const349   void PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
350   {
351     if (myClippingState.Index() != theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
352     {
353       pushClippingState (theProgram);
354     }
355   }
356 
357   //! Pushes current state of OCCT clipping planes to specified program.
358   Standard_EXPORT void pushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
359 
360 public:
361 
362   //! Returns current state of material.
MaterialState() const363   const OpenGl_MaterialState& MaterialState() const { return myMaterialState; }
364 
365   //! Updates state of material.
UpdateMaterialStateTo(const OpenGl_Material & theFrontMat,const OpenGl_Material & theBackMat,const float theAlphaCutoff,const bool theToDistinguish,const bool theToMapTexture)366   void UpdateMaterialStateTo (const OpenGl_Material& theFrontMat,
367                               const OpenGl_Material& theBackMat,
368                               const float theAlphaCutoff,
369                               const bool theToDistinguish,
370                               const bool theToMapTexture)
371   {
372     myMaterialState.Set (theFrontMat, theBackMat, theAlphaCutoff, theToDistinguish, theToMapTexture);
373     myMaterialState.Update();
374   }
375 
376   //! Updates state of material.
UpdateMaterialState()377   void UpdateMaterialState()
378   {
379     myMaterialState.Update();
380   }
381 
382   //! Pushes current state of material to specified program (only on state change).
PushMaterialState(const Handle (OpenGl_ShaderProgram)& theProgram) const383   void PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
384   {
385     if (myMaterialState.Index() != theProgram->ActiveState (OpenGl_MATERIAL_STATE))
386     {
387       pushMaterialState (theProgram);
388     }
389   }
390 
391   //! Pushes current state of material to specified program.
392   Standard_EXPORT void pushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
393 
394 public:
395 
396   //! Setup interior style line edges variables.
397   Standard_EXPORT void PushInteriorState (const Handle(OpenGl_ShaderProgram)& theProgram,
398                                           const Handle(Graphic3d_Aspects)& theAspect) const;
399 
400 public:
401 
402   //! Returns state of OIT uniforms.
OitState() const403   const OpenGl_OitState& OitState() const { return myOitState; }
404 
405   //! Set the state of OIT rendering pass (only on state change).
406   //! @param theToEnableOitWrite [in] flag indicating whether the special output should be written for OIT algorithm.
407   //! @param theDepthFactor [in] the scalar factor of depth influence to the fragment's coverage.
SetOitState(const bool theToEnableOitWrite,const float theDepthFactor)408   void SetOitState (const bool theToEnableOitWrite, const float theDepthFactor)
409   {
410     myOitState.Set (theToEnableOitWrite, theDepthFactor);
411     myOitState.Update();
412   }
413 
414   //! Pushes state of OIT uniforms to the specified program.
PushOitState(const Handle (OpenGl_ShaderProgram)& theProgram) const415   void PushOitState (const Handle(OpenGl_ShaderProgram)& theProgram) const
416   {
417     if (theProgram->IsValid()
418      && myOitState.Index() != theProgram->ActiveState (OpenGL_OIT_STATE))
419     {
420       pushOitState (theProgram);
421     }
422   }
423 
424   //! Pushes state of OIT uniforms to the specified program.
425   Standard_EXPORT void pushOitState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
426 
427 public:
428 
429   //! Pushes current state of OCCT graphics parameters to specified program.
430   Standard_EXPORT void PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
431 
432 public:
433 
434   //! Overwrites context
SetContext(OpenGl_Context * theCtx)435   void SetContext (OpenGl_Context* theCtx)
436   {
437     myContext = theCtx;
438   }
439 
440   //! Returns true when provided context is the same as used one by shader manager.
IsSameContext(OpenGl_Context * theCtx) const441   bool IsSameContext (OpenGl_Context* theCtx) const
442   {
443     return myContext == theCtx;
444   }
445 
446   //! Choose Shading Model for filled primitives.
447   //! Fallbacks to FACET model if there are no normal attributes.
ChooseFaceShadingModel(Graphic3d_TypeOfShadingModel theCustomModel,bool theHasNodalNormals) const448   Graphic3d_TypeOfShadingModel ChooseFaceShadingModel (Graphic3d_TypeOfShadingModel theCustomModel,
449                                                        bool theHasNodalNormals) const
450   {
451     if (!myContext->ColorMask())
452     {
453       return Graphic3d_TOSM_UNLIT;
454     }
455     Graphic3d_TypeOfShadingModel aModel = theCustomModel != Graphic3d_TOSM_DEFAULT ? theCustomModel : myShadingModel;
456     switch (aModel)
457     {
458       case Graphic3d_TOSM_DEFAULT:
459       case Graphic3d_TOSM_UNLIT:
460       case Graphic3d_TOSM_FACET:
461         return aModel;
462       case Graphic3d_TOSM_VERTEX:
463       case Graphic3d_TOSM_FRAGMENT:
464         return theHasNodalNormals ? aModel : Graphic3d_TOSM_FACET;
465     }
466     return Graphic3d_TOSM_UNLIT;
467   }
468 
469   //! Choose Shading Model for line primitives.
470   //! Fallbacks to UNLIT model if there are no normal attributes.
ChooseLineShadingModel(Graphic3d_TypeOfShadingModel theCustomModel,bool theHasNodalNormals) const471   Graphic3d_TypeOfShadingModel ChooseLineShadingModel (Graphic3d_TypeOfShadingModel theCustomModel,
472                                                        bool theHasNodalNormals) const
473   {
474     if (!myContext->ColorMask())
475     {
476       return Graphic3d_TOSM_UNLIT;
477     }
478     Graphic3d_TypeOfShadingModel aModel = theCustomModel != Graphic3d_TOSM_DEFAULT ? theCustomModel : myShadingModel;
479     switch (aModel)
480     {
481       case Graphic3d_TOSM_DEFAULT:
482       case Graphic3d_TOSM_UNLIT:
483       case Graphic3d_TOSM_FACET:
484         return Graphic3d_TOSM_UNLIT;
485       case Graphic3d_TOSM_VERTEX:
486       case Graphic3d_TOSM_FRAGMENT:
487         return theHasNodalNormals ? aModel : Graphic3d_TOSM_UNLIT;
488     }
489     return Graphic3d_TOSM_UNLIT;
490   }
491 
492   //! Choose Shading Model for Marker primitives.
ChooseMarkerShadingModel(Graphic3d_TypeOfShadingModel theCustomModel,bool theHasNodalNormals) const493   Graphic3d_TypeOfShadingModel ChooseMarkerShadingModel (Graphic3d_TypeOfShadingModel theCustomModel,
494                                                          bool theHasNodalNormals) const
495   {
496     return ChooseLineShadingModel (theCustomModel, theHasNodalNormals);
497   }
498 
499   //! Returns default Shading Model.
ShadingModel() const500   Graphic3d_TypeOfShadingModel ShadingModel() const { return myShadingModel; }
501 
502   //! Sets shading model.
503   Standard_EXPORT void SetShadingModel (const Graphic3d_TypeOfShadingModel theModel);
504 
505   //! Sets last view manger used with.
506   //! Helps to handle matrix states in multi-view configurations.
SetLastView(const OpenGl_View * theLastView)507   void SetLastView (const OpenGl_View* theLastView)
508   {
509     myLastView = theLastView;
510   }
511 
512   //! Returns true when provided view is the same as cached one.
IsSameView(const OpenGl_View * theView) const513   bool IsSameView (const OpenGl_View* theView) const
514   {
515     return myLastView == theView;
516   }
517 
518 protected:
519 
520   //! Define clipping planes program bits.
getClipPlaneBits() const521   Standard_Integer getClipPlaneBits() const
522   {
523     const Standard_Integer aNbPlanes = myContext->Clipping().NbClippingOrCappingOn();
524     if (aNbPlanes <= 0)
525     {
526       return 0;
527     }
528 
529     Standard_Integer aBits = 0;
530     if (myContext->Clipping().HasClippingChains())
531     {
532       aBits |= OpenGl_PO_ClipChains;
533     }
534 
535     if (aNbPlanes == 1)
536     {
537       aBits |= OpenGl_PO_ClipPlanes1;
538     }
539     else if (aNbPlanes == 2)
540     {
541       aBits |= OpenGl_PO_ClipPlanes2;
542     }
543     else
544     {
545       aBits |= OpenGl_PO_ClipPlanesN;
546     }
547     return aBits;
548   }
549 
550   //! Define program bits.
getProgramBits(const Handle (OpenGl_TextureSet)& theTextures,Graphic3d_AlphaMode theAlphaMode,Aspect_InteriorStyle theInteriorStyle,Standard_Boolean theHasVertColor,Standard_Boolean theEnableEnvMap,Standard_Boolean theEnableMeshEdges) const551   Standard_Integer getProgramBits (const Handle(OpenGl_TextureSet)& theTextures,
552                                    Graphic3d_AlphaMode theAlphaMode,
553                                    Aspect_InteriorStyle theInteriorStyle,
554                                    Standard_Boolean theHasVertColor,
555                                    Standard_Boolean theEnableEnvMap,
556                                    Standard_Boolean theEnableMeshEdges) const
557   {
558     Standard_Integer aBits = 0;
559     if (theAlphaMode == Graphic3d_AlphaMode_Mask)
560     {
561       aBits |= OpenGl_PO_AlphaTest;
562     }
563 
564     aBits |= getClipPlaneBits();
565     if (theEnableMeshEdges
566      && myContext->hasGeometryStage != OpenGl_FeatureNotAvailable)
567     {
568       aBits |= OpenGl_PO_MeshEdges;
569       if (theInteriorStyle == Aspect_IS_HOLLOW)
570       {
571         aBits |= OpenGl_PO_AlphaTest;
572       }
573     }
574 
575     if (theEnableEnvMap)
576     {
577       // Environment map overwrites material texture
578       aBits |= OpenGl_PO_TextureEnv;
579     }
580     else if (!theTextures.IsNull()
581            && theTextures->HasNonPointSprite())
582     {
583       aBits |= OpenGl_PO_TextureRGB;
584     }
585     if (theHasVertColor
586      && theInteriorStyle != Aspect_IS_HIDDENLINE)
587     {
588       aBits |= OpenGl_PO_VertColor;
589     }
590 
591     if (myOitState.ToEnableWrite())
592     {
593       aBits |= OpenGl_PO_WriteOit;
594     }
595     return aBits;
596   }
597 
598   //! Prepare standard GLSL program.
Handle(OpenGl_ShaderProgram)599   Handle(OpenGl_ShaderProgram)& getStdProgram (Graphic3d_TypeOfShadingModel theShadingModel,
600                                                Standard_Integer theBits)
601   {
602     if (theShadingModel == Graphic3d_TOSM_UNLIT
603      || (theBits & OpenGl_PO_TextureEnv) != 0)
604     {
605       // If environment map is enabled lighting calculations are
606       // not needed (in accordance with default OCCT behavior)
607       Handle(OpenGl_ShaderProgram)& aProgram = myUnlitPrograms->ChangeValue (theBits);
608       if (aProgram.IsNull())
609       {
610         prepareStdProgramUnlit (aProgram, theBits, false);
611       }
612       return aProgram;
613     }
614 
615     Handle(OpenGl_ShaderProgram)& aProgram = myLightPrograms->ChangeValue (theShadingModel, theBits);
616     if (aProgram.IsNull())
617     {
618       prepareStdProgramLight (aProgram, theShadingModel, theBits);
619     }
620     return aProgram;
621   }
622 
623   //! Prepare standard GLSL program for accessing point sprite alpha.
624   Standard_EXPORT TCollection_AsciiString pointSpriteAlphaSrc (Standard_Integer theBits);
625 
626   //! Prepare standard GLSL program for computing point sprite shading.
627   Standard_EXPORT TCollection_AsciiString pointSpriteShadingSrc (const TCollection_AsciiString& theBaseColorSrc,
628                                                                  Standard_Integer theBits);
629 
630   //! Prepare standard GLSL program for textured font.
631   Standard_EXPORT Standard_Boolean prepareStdProgramFont();
632 
633   //! Prepare standard GLSL program for FBO blit operation.
634   Standard_EXPORT Standard_Boolean prepareStdProgramFboBlit();
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.
prepareStdProgramLight(Handle (OpenGl_ShaderProgram)& theProgram,Graphic3d_TypeOfShadingModel theShadingModel,Standard_Integer theBits)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
PackedOpenGl_ShaderManager::OpenGl_ShaderLightParameters711     const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
NbOfVec4OpenGl_ShaderManager::OpenGl_ShaderLightParameters712     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
PackedOpenGl_ShaderManager::OpenGl_ShaderLightType722     const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
NbOfVec2iOpenGl_ShaderManager::OpenGl_ShaderLightType723     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:
OpenGl_ShaderProgramFFP()732     OpenGl_ShaderProgramFFP() {}
733   };
734 
735 protected:
736 
737   //! Append clipping plane definition to temporary buffers.
addClippingPlane(Standard_Integer & thePlaneId,const Graphic3d_ClipPlane & thePlane,const Graphic3d_Vec4d & theEq,const Standard_Integer theChainFwd) const738   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   Handle(OpenGl_ShaderProgram)       myBlitProgram;        //!< standard program for FBO blit emulation
767   Handle(OpenGl_ShaderProgram)       myBoundBoxProgram;    //!< standard program for bounding box
768   Handle(OpenGl_ShaderProgram)       myOitCompositingProgram[2]; //!< standard program for OIT compositing (default and MSAA).
769   OpenGl_MapOfShaderPrograms         myMapOfLightPrograms; //!< map of lighting programs depending on lights configuration
770 
771   Handle(Graphic3d_ShaderProgram)    myBgCubeMapProgram;   //!< program for background cubemap rendering
772 
773   Handle(OpenGl_ShaderProgram)       myStereoPrograms[Graphic3d_StereoMode_NB]; //!< standard stereo programs
774 
775   Handle(OpenGl_VertexBuffer)        myBoundBoxVertBuffer; //!< bounding box vertex buffer
776 
777   OpenGl_Context*                    myContext;            //!< OpenGL context
778 
779 protected:
780 
781   OpenGl_ProjectionState             myProjectionState;    //!< State of OCCT projection  transformation
782   OpenGl_ModelWorldState             myModelWorldState;    //!< State of OCCT model-world transformation
783   OpenGl_WorldViewState              myWorldViewState;     //!< State of OCCT world-view  transformation
784   OpenGl_ClippingState               myClippingState;      //!< State of OCCT clipping planes
785   OpenGl_LightSourceState            myLightSourceState;   //!< State of OCCT light sources
786   OpenGl_MaterialState               myMaterialState;      //!< State of Front and Back materials
787   OpenGl_OitState                    myOitState;           //!< State of OIT uniforms
788 
789   gp_XYZ                             myLocalOrigin;        //!< local camera transformation
790   Standard_Boolean                   myHasLocalOrigin;     //!< flag indicating that local camera transformation has been set
791 
792   mutable NCollection_Array1<OpenGl_ShaderLightType>       myLightTypeArray;
793   mutable NCollection_Array1<OpenGl_ShaderLightParameters> myLightParamsArray;
794   mutable NCollection_Array1<OpenGl_Vec4>                  myClipPlaneArray;
795   mutable NCollection_Array1<OpenGl_Vec4d>                 myClipPlaneArrayFfp;
796   mutable NCollection_Array1<Standard_Integer>             myClipChainArray;
797 
798 private:
799 
800   const OpenGl_View*                 myLastView;           //!< Pointer to the last view shader manager used with
801 
802 };
803 
804 DEFINE_STANDARD_HANDLE(OpenGl_ShaderManager, Standard_Transient)
805 
806 #endif // _OpenGl_ShaderManager_HeaderFile
807