0028912: Visualization, TKOpenGl - multi-texture support
[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 #include <Graphic3d_TypeOfShadingModel.hxx>
22
23 #include <NCollection_DataMap.hxx>
24 #include <NCollection_Sequence.hxx>
25
26 #include <OpenGl_SetOfShaderPrograms.hxx>
27 #include <OpenGl_ShaderStates.hxx>
28 #include <OpenGl_AspectFace.hxx>
29 #include <OpenGl_AspectLine.hxx>
30 #include <OpenGl_AspectText.hxx>
31 #include <OpenGl_AspectMarker.hxx>
32 #include <OpenGl_MaterialState.hxx>
33 #include <OpenGl_Texture.hxx>
34
35 class OpenGl_View;
36
37 //! List of shader programs.
38 typedef NCollection_Sequence<Handle(OpenGl_ShaderProgram)> OpenGl_ShaderProgramList;
39
40 //! This class is responsible for managing shader programs.
41 class OpenGl_ShaderManager : public Standard_Transient
42 {
43   DEFINE_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient)
44   friend class OpenGl_ShaderProgram;
45 public:
46
47   //! Creates new empty shader manager.
48   Standard_EXPORT OpenGl_ShaderManager (OpenGl_Context* theContext);
49
50   //! Releases resources of shader manager.
51   Standard_EXPORT virtual ~OpenGl_ShaderManager();
52
53   //! Release all resources.
54   Standard_EXPORT void clear();
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   //! Creates new shader program or re-use shared instance.
67   //! @param theProxy    [IN]  program definition
68   //! @param theShareKey [OUT] sharing key
69   //! @param theProgram  [OUT] OpenGL program
70   //! @return true on success
71   Standard_EXPORT Standard_Boolean Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
72                                            TCollection_AsciiString&               theShareKey,
73                                            Handle(OpenGl_ShaderProgram)&          theProgram);
74
75   //! Unregisters specified shader program.
76   Standard_EXPORT void Unregister (TCollection_AsciiString&      theShareKey,
77                                    Handle(OpenGl_ShaderProgram)& theProgram);
78
79   //! Returns list of registered shader programs.
80   Standard_EXPORT const OpenGl_ShaderProgramList& ShaderPrograms() const;
81
82   //! Returns true if no program objects are registered in the manager.
83   Standard_EXPORT Standard_Boolean IsEmpty() const;
84
85   //! Bind program for filled primitives rendering
86   Standard_Boolean BindFaceProgram (const Handle(OpenGl_TextureSet)& theTextures,
87                                     const Standard_Boolean           theToLightOn,
88                                     const Standard_Boolean              theHasVertColor,
89                                     const Standard_Boolean              theEnableEnvMap,
90                                     const Handle(OpenGl_ShaderProgram)& theCustomProgram)
91   {
92     if (!theCustomProgram.IsNull()
93      || myContext->caps->ffpEnable)
94     {
95       return bindProgramWithState (theCustomProgram);
96     }
97
98     const Standard_Integer        aBits    = getProgramBits (theTextures, theHasVertColor, theEnableEnvMap);
99     Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theToLightOn, aBits);
100     return bindProgramWithState (aProgram);
101   }
102
103   //! Bind program for line rendering
104   Standard_Boolean BindLineProgram (const Handle(OpenGl_TextureSet)&    theTextures,
105                                     const Standard_Boolean              theStipple,
106                                     const Standard_Boolean              theToLightOn,
107                                     const Standard_Boolean              theHasVertColor,
108                                     const Handle(OpenGl_ShaderProgram)& theCustomProgram)
109   {
110     if (!theCustomProgram.IsNull()
111      || myContext->caps->ffpEnable)
112     {
113       return bindProgramWithState (theCustomProgram);
114     }
115
116     Standard_Integer aBits = getProgramBits (theTextures, theHasVertColor);
117     if (theStipple)
118     {
119       aBits |= OpenGl_PO_StippleLine;
120     }
121
122     Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theToLightOn, aBits);
123     return bindProgramWithState (aProgram);
124   }
125
126   //! Bind program for point rendering
127   Standard_Boolean BindMarkerProgram (const Handle(OpenGl_TextureSet)&    theTextures,
128                                       const Standard_Boolean              theToLightOn,
129                                       const Standard_Boolean              theHasVertColor,
130                                       const Handle(OpenGl_ShaderProgram)& theCustomProgram)
131   {
132     if (!theCustomProgram.IsNull()
133      || myContext->caps->ffpEnable)
134     {
135       return bindProgramWithState (theCustomProgram);
136     }
137
138     const Standard_Integer        aBits    = getProgramBits (theTextures, theHasVertColor) | OpenGl_PO_Point;
139     Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theToLightOn, aBits);
140     return bindProgramWithState (aProgram);
141   }
142
143   //! Bind program for rendering alpha-textured font.
144   Standard_Boolean BindFontProgram (const Handle(OpenGl_ShaderProgram)& theCustomProgram)
145   {
146     if (!theCustomProgram.IsNull()
147      || myContext->caps->ffpEnable)
148     {
149       return bindProgramWithState (theCustomProgram);
150     }
151
152     if (myFontProgram.IsNull())
153     {
154       prepareStdProgramFont();
155     }
156
157     return bindProgramWithState (myFontProgram);
158   }
159
160   //! Bind program for FBO blit operation.
161   Standard_Boolean BindFboBlitProgram()
162   {
163     if (myBlitProgram.IsNull())
164     {
165       prepareStdProgramFboBlit();
166     }
167     return !myBlitProgram.IsNull()
168          && myContext->BindProgram (myBlitProgram);
169   }
170
171   //! Bind program for blended order-independent transparency buffers compositing.
172   Standard_Boolean BindOitCompositingProgram (const Standard_Boolean theIsMSAAEnabled)
173   {
174     const Standard_Integer aProgramIdx = theIsMSAAEnabled ? 1 : 0;
175     if (myOitCompositingProgram[aProgramIdx].IsNull())
176     {
177       prepareStdProgramOitCompositing (theIsMSAAEnabled);
178     }
179
180     const Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram [aProgramIdx];
181     return !aProgram.IsNull() && myContext->BindProgram (aProgram);
182   }
183
184   //! Bind program for rendering stereoscopic image.
185   Standard_Boolean BindStereoProgram (const Graphic3d_StereoMode theStereoMode)
186   {
187     if (theStereoMode < 0 || theStereoMode >= Graphic3d_StereoMode_NB)
188     {
189       return Standard_False;
190     }
191
192     if (myStereoPrograms[theStereoMode].IsNull())
193     {
194       prepareStdProgramStereo (myStereoPrograms[theStereoMode], theStereoMode);
195     }
196     const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[theStereoMode];
197     return !aProgram.IsNull()
198          && myContext->BindProgram (aProgram);
199   }
200
201 public:
202
203   //! Returns current state of OCCT light sources.
204   const OpenGl_LightSourceState& LightSourceState() const { return myLightSourceState; }
205
206   //! Updates state of OCCT light sources.
207   Standard_EXPORT void UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights);
208
209   //! Invalidate state of OCCT light sources.
210   Standard_EXPORT void UpdateLightSourceState();
211
212   //! Pushes current state of OCCT light sources to specified program.
213   Standard_EXPORT void PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
214
215 public:
216
217   //! Returns current state of OCCT projection transform.
218   const OpenGl_ProjectionState& ProjectionState() const { return myProjectionState; }
219
220   //! Updates state of OCCT projection transform.
221   Standard_EXPORT void UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix);
222
223   //! Pushes current state of OCCT projection transform to specified program.
224   Standard_EXPORT void PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
225
226 public:
227
228   //! Returns current state of OCCT model-world transform.
229   const OpenGl_ModelWorldState& ModelWorldState() const { return myModelWorldState; }
230
231   //! Updates state of OCCT model-world transform.
232   Standard_EXPORT void UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix);
233
234   //! Pushes current state of OCCT model-world transform to specified program.
235   Standard_EXPORT void PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
236
237 public:
238
239   //! Returns current state of OCCT world-view transform.
240   const OpenGl_WorldViewState& WorldViewState() const { return myWorldViewState; }
241
242   //! Updates state of OCCT world-view transform.
243   Standard_EXPORT void UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix);
244
245   //! Pushes current state of OCCT world-view transform to specified program.
246   Standard_EXPORT void PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
247
248 public:
249
250   //! Updates state of OCCT clipping planes.
251   Standard_EXPORT void UpdateClippingState();
252
253   //! Reverts state of OCCT clipping planes.
254   Standard_EXPORT void RevertClippingState();
255
256   //! Pushes current state of OCCT clipping planes to specified program.
257   Standard_EXPORT void PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
258
259 public:
260
261   //! Returns current state of material.
262   const OpenGl_MaterialState& MaterialState() const { return myMaterialState; }
263
264   //! Updates state of material.
265   void UpdateMaterialStateTo (const OpenGl_Material& theFrontMat,
266                               const OpenGl_Material& theBackMat,
267                               const bool theToDistinguish,
268                               const bool theToMapTexture)
269   {
270     myMaterialState.Set (theFrontMat, theBackMat, theToDistinguish, theToMapTexture);
271     myMaterialState.Update();
272   }
273
274   //! Updates state of material.
275   void UpdateMaterialState()
276   {
277     myMaterialState.Update();
278   }
279
280   //! Pushes current state of material to specified program.
281   void PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
282
283 public:
284
285   //! Set the state of OIT rendering pass.
286   //! @param theToEnableOitWrite [in] flag indicating whether the special output should be written for OIT algorithm.
287   //! @param theDepthFactor [in] the scalar factor of depth influence to the fragment's coverage.
288   void SetOitState (const bool theToEnableOitWrite, const float theDepthFactor)
289   {
290     myOitState.Set (theToEnableOitWrite, theDepthFactor);
291     myOitState.Update();
292   }
293
294   //! Pushes state of OIT uniforms to the specified program.
295   Standard_EXPORT void PushOitState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
296
297 public:
298
299   //! Pushes current state of OCCT graphics parameters to specified program.
300   Standard_EXPORT void PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const;
301
302 public:
303
304   //! Overwrites context
305   void SetContext (OpenGl_Context* theCtx)
306   {
307     myContext = theCtx;
308   }
309
310   //! Returns true when provided context is the same as used one by shader manager.
311   bool IsSameContext (OpenGl_Context* theCtx) const
312   {
313     return myContext == theCtx;
314   }
315
316   //! Sets shading model.
317   Standard_EXPORT void SetShadingModel (const Graphic3d_TypeOfShadingModel theModel);
318
319   //! Sets last view manger used with.
320   //! Helps to handle matrix states in multi-view configurations.
321   void SetLastView (const OpenGl_View* theLastView)
322   {
323     myLastView = theLastView;
324   }
325
326   //! Returns true when provided view is the same as cached one.
327   bool IsSameView (const OpenGl_View* theView) const
328   {
329     return myLastView == theView;
330   }
331
332 protected:
333
334   //! Define program bits.
335   Standard_Integer getProgramBits (const Handle(OpenGl_TextureSet)& theTextures,
336                                    const Standard_Boolean theHasVertColor,
337                                    const Standard_Boolean theEnableEnvMap = Standard_False)
338
339   {
340     Standard_Integer aBits = 0;
341
342     const Standard_Integer aNbPlanes = myContext->Clipping().NbClippingOrCappingOn();
343     if (aNbPlanes > 0)
344     {
345       aBits |= OpenGl_PO_ClipPlanesN;
346       if (aNbPlanes == 1)
347       {
348         aBits |= OpenGl_PO_ClipPlanes1;
349       }
350       else if (aNbPlanes == 2)
351       {
352         aBits |= OpenGl_PO_ClipPlanes2;
353       }
354     }
355
356     if (theEnableEnvMap)
357     {
358       // Environment map overwrites material texture
359       aBits |= OpenGl_PO_TextureEnv;
360     }
361     else if (!theTextures.IsNull()
362           && !theTextures->IsEmpty()
363           && !theTextures->First().IsNull())
364     {
365       aBits |= theTextures->First()->IsAlpha() ? OpenGl_PO_TextureA : OpenGl_PO_TextureRGB;
366     }
367     if (theHasVertColor)
368     {
369       aBits |= OpenGl_PO_VertColor;
370     }
371
372     if (myOitState.ToEnableWrite())
373     {
374       aBits |= OpenGl_PO_WriteOit;
375     }
376     return aBits;
377   }
378
379   //! Prepare standard GLSL program.
380   Handle(OpenGl_ShaderProgram)& getStdProgram (const Standard_Boolean theToLightOn,
381                                                const Standard_Integer theBits)
382   {
383     // If environment map is enabled lighting calculations are
384     // not needed (in accordance with default OCCT behaviour)
385     if (theToLightOn && (theBits & OpenGl_PO_TextureEnv) == 0)
386     {
387       Handle(OpenGl_ShaderProgram)& aProgram = myLightPrograms->ChangeValue (theBits);
388       if (aProgram.IsNull())
389       {
390         prepareStdProgramLight (aProgram, theBits);
391       }
392       return aProgram;
393     }
394
395     Handle(OpenGl_ShaderProgram)& aProgram = myFlatPrograms.ChangeValue (theBits);
396     if (aProgram.IsNull())
397     {
398       prepareStdProgramFlat (aProgram, theBits);
399     }
400     return aProgram;
401   }
402
403   //! Prepare standard GLSL program for accessing point sprite alpha.
404   Standard_EXPORT TCollection_AsciiString pointSpriteAlphaSrc (const Standard_Integer theBits);
405
406   //! Prepare standard GLSL program for computing point sprite shading.
407   Standard_EXPORT TCollection_AsciiString pointSpriteShadingSrc (const TCollection_AsciiString theBaseColorSrc, const Standard_Integer theBits);
408
409   //! Prepare standard GLSL program for textured font.
410   Standard_EXPORT Standard_Boolean prepareStdProgramFont();
411
412   //! Prepare standard GLSL program for FBO blit operation.
413   Standard_EXPORT Standard_Boolean prepareStdProgramFboBlit();
414
415   //! Prepare standard GLSL programs for OIT compositing operation.
416   Standard_EXPORT Standard_Boolean prepareStdProgramOitCompositing (const Standard_Boolean theMsaa);
417
418   //! Prepare standard GLSL program without lighting.
419   Standard_EXPORT Standard_Boolean prepareStdProgramFlat (Handle(OpenGl_ShaderProgram)& theProgram,
420                                                           const Standard_Integer        theBits);
421
422   //! Prepare standard GLSL program with lighting.
423   Standard_Boolean prepareStdProgramLight (Handle(OpenGl_ShaderProgram)& theProgram,
424                                            const Standard_Integer        theBits)
425   {
426     return myShadingModel == Graphic3d_TOSM_FRAGMENT
427          ? prepareStdProgramPhong   (theProgram, theBits)
428          : prepareStdProgramGouraud (theProgram, theBits);
429   }
430
431   //! Prepare standard GLSL program with per-vertex lighting.
432   Standard_EXPORT Standard_Boolean prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
433                                                              const Standard_Integer        theBits);
434
435   //! Prepare standard GLSL program with per-pixel lighting.
436   Standard_EXPORT Standard_Boolean prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
437                                                            const Standard_Integer        theBits);
438
439   //! Define computeLighting GLSL function depending on current lights configuration
440   //! @param theHasVertColor flag to use getVertColor() instead of Ambient and Diffuse components of active material
441   Standard_EXPORT TCollection_AsciiString stdComputeLighting (const Standard_Boolean theHasVertColor);
442
443   //! Bind specified program to current context and apply state.
444   Standard_EXPORT Standard_Boolean bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram);
445
446   //! Set pointer myLightPrograms to active lighting programs set from myMapOfLightPrograms
447   Standard_EXPORT void switchLightPrograms();
448
449   //! Prepare standard GLSL program for stereoscopic image.
450   Standard_EXPORT Standard_Boolean prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
451                                                             const Graphic3d_StereoMode    theStereoMode);
452
453 protected:
454
455   //! Packed properties of light source
456   struct OpenGl_ShaderLightParameters
457   {
458     OpenGl_Vec4 Color;
459     OpenGl_Vec4 Position;
460     OpenGl_Vec4 Direction;
461     OpenGl_Vec4 Parameters;
462
463     //! Returns packed (serialized) representation of light source properties
464     const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
465     static Standard_Integer NbOfVec4() { return 4; }
466   };
467
468   //! Packed light source type information
469   struct OpenGl_ShaderLightType
470   {
471     Standard_Integer Type;
472     Standard_Integer IsHeadlight;
473
474     //! Returns packed (serialized) representation of light source type
475     const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
476     static Standard_Integer NbOfVec2i() { return 1; }
477   };
478
479   //! Fake OpenGL program for tracking FFP state in the way consistent to programmable pipeline.
480   class OpenGl_ShaderProgramFFP : public OpenGl_ShaderProgram
481   {
482     DEFINE_STANDARD_RTTI_INLINE(OpenGl_ShaderProgramFFP, OpenGl_ShaderProgram)
483     friend class OpenGl_ShaderManager;
484   protected:
485     OpenGl_ShaderProgramFFP() {}
486   };
487
488 protected:
489
490   Handle(OpenGl_ShaderProgramFFP)    myFfpProgram;
491
492   Graphic3d_TypeOfShadingModel       myShadingModel;       //!< lighting shading model
493   OpenGl_ShaderProgramList           myProgramList;        //!< The list of shader programs
494   Handle(OpenGl_SetOfShaderPrograms) myLightPrograms;      //!< pointer to active lighting programs matrix
495   OpenGl_SetOfShaderPrograms         myFlatPrograms;       //!< programs matrix without  lighting
496   Handle(OpenGl_ShaderProgram)       myFontProgram;        //!< standard program for textured text
497   Handle(OpenGl_ShaderProgram)       myBlitProgram;        //!< standard program for FBO blit emulation
498   Handle(OpenGl_ShaderProgram)       myOitCompositingProgram[2]; //!< standard program for OIT compositing (default and MSAA).
499   OpenGl_MapOfShaderPrograms         myMapOfLightPrograms; //!< map of lighting programs depending on shading model and lights configuration
500
501   Handle(OpenGl_ShaderProgram)       myStereoPrograms[Graphic3d_StereoMode_NB]; //!< standard stereo programs
502
503   OpenGl_Context*                    myContext;            //!< OpenGL context
504
505 protected:
506
507   OpenGl_ProjectionState             myProjectionState;    //!< State of OCCT projection  transformation
508   OpenGl_ModelWorldState             myModelWorldState;    //!< State of OCCT model-world transformation
509   OpenGl_WorldViewState              myWorldViewState;     //!< State of OCCT world-view  transformation
510   OpenGl_ClippingState               myClippingState;      //!< State of OCCT clipping planes
511   OpenGl_LightSourceState            myLightSourceState;   //!< State of OCCT light sources
512   OpenGl_MaterialState               myMaterialState;      //!< State of Front and Back materials
513   OpenGl_OitState                    myOitState;           //!< State of OIT uniforms
514
515   gp_XYZ                             myLocalOrigin;        //!< local camera transformation
516   Standard_Boolean                   myHasLocalOrigin;     //!< flag indicating that local camera transformation has been set
517
518   mutable OpenGl_ShaderLightType       myLightTypeArray  [OpenGLMaxLights];
519   mutable OpenGl_ShaderLightParameters myLightParamsArray[OpenGLMaxLights];
520
521 private:
522
523   const OpenGl_View*                 myLastView;           //!< Pointer to the last view shader manager used with
524
525 };
526
527 DEFINE_STANDARD_HANDLE(OpenGl_ShaderManager, Standard_Transient)
528
529 #endif // _OpenGl_ShaderManager_HeaderFile