8ab515b4e4a45ec0d2212ed986017e927912fee1
[occt.git] / src / OpenGl / OpenGl_ShaderManager.cxx
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 #include <typeinfo>
17
18 #include <Graphic3d_TextureParams.hxx>
19 #include <OpenGl_AspectFace.hxx>
20 #include <OpenGl_AspectLine.hxx>
21 #include <OpenGl_AspectMarker.hxx>
22 #include <OpenGl_AspectText.hxx>
23 #include <OpenGl_Clipping.hxx>
24 #include <OpenGl_Context.hxx>
25 #include <OpenGl_ShaderManager.hxx>
26 #include <OpenGl_ShaderProgram.hxx>
27 #include <OpenGl_Workspace.hxx>
28
29 #include <TCollection_ExtendedString.hxx>
30
31
32
33
34 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager,Standard_Transient)
35
36 namespace
37 {
38
39 #define EOL "\n"
40
41 //! Definition of TexCoord varying.
42 const char THE_VARY_TexCoord_OUT[] =
43   EOL"THE_SHADER_OUT vec4 TexCoord;";
44 const char THE_VARY_TexCoord_IN[] =
45   EOL"THE_SHADER_IN  vec4 TexCoord;";
46 //! Compute TexCoord value in Vertex Shader
47 const char THE_VARY_TexCoord_Trsf[] =
48   EOL"  float aRotSin = occTextureTrsf_RotationSin();"
49   EOL"  float aRotCos = occTextureTrsf_RotationCos();"
50   EOL"  vec2  aTex2   = (occTexCoord.xy + occTextureTrsf_Translation()) * occTextureTrsf_Scale();"
51   EOL"  vec2  aCopy   = aTex2;"
52   EOL"  aTex2.x = aCopy.x * aRotCos - aCopy.y * aRotSin;"
53   EOL"  aTex2.y = aCopy.x * aRotSin + aCopy.y * aRotCos;"
54   EOL"  TexCoord = vec4(aTex2, occTexCoord.zw);";
55
56 //! Auxiliary function to transform normal
57 const char THE_FUNC_transformNormal[] =
58   EOL"vec3 transformNormal (in vec3 theNormal)"
59   EOL"{"
60   EOL"  vec4 aResult = occWorldViewMatrixInverseTranspose"
61   EOL"               * occModelWorldMatrixInverseTranspose"
62   EOL"               * vec4 (theNormal, 0.0);"
63   EOL"  return normalize (aResult.xyz);"
64   EOL"}";
65
66 //! Global shader variable for color definition with lighting enabled.
67 const char THE_FUNC_lightDef[] =
68   EOL"vec3 Ambient;"   //!< Ambient  contribution of light sources
69   EOL"vec3 Diffuse;"   //!< Diffuse  contribution of light sources
70   EOL"vec3 Specular;"; //!< Specular contribution of light sources
71
72 //! Function computes contribution of isotropic point light source
73 const char THE_FUNC_pointLight[] =
74   EOL"void pointLight (in int  theId,"
75   EOL"                 in vec3 theNormal,"
76   EOL"                 in vec3 theView,"
77   EOL"                 in vec3 thePoint,"
78   EOL"                 in bool theIsFront)"
79   EOL"{"
80   EOL"  vec3 aLight = occLight_Position (theId).xyz;"
81   EOL"  if (occLight_IsHeadlight (theId) == 0)"
82   EOL"  {"
83   EOL"    aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));"
84   EOL"  }"
85   EOL"  aLight -= thePoint;"
86   EOL
87   EOL"  float aDist = length (aLight);"
88   EOL"  aLight = aLight * (1.0 / aDist);"
89   EOL
90   EOL"  float anAtten = 1.0 / (occLight_ConstAttenuation  (theId)"
91   EOL"                       + occLight_LinearAttenuation (theId) * aDist);"
92   EOL
93   EOL"  vec3 aHalf = normalize (aLight + theView);"
94   EOL
95   EOL"  vec3  aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
96   EOL"  float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
97   EOL"  float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
98   EOL
99   EOL"  float aSpecl = 0.0;"
100   EOL"  if (aNdotL > 0.0)"
101   EOL"  {"
102   EOL"    aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
103   EOL"  }"
104   EOL
105   EOL"Diffuse  += occLight_Diffuse  (theId).rgb * aNdotL * anAtten;"
106   EOL"Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
107   EOL"}";
108
109 //! Function computes contribution of spotlight source
110 const char THE_FUNC_spotLight[] =
111   EOL"void spotLight (in int  theId,"
112   EOL"                in vec3 theNormal,"
113   EOL"                in vec3 theView,"
114   EOL"                in vec3 thePoint,"
115   EOL"                in bool theIsFront)"
116   EOL"{"
117   EOL"  vec3 aLight   = occLight_Position      (theId).xyz;"
118   EOL"  vec3 aSpotDir = occLight_SpotDirection (theId).xyz;"
119   EOL"  if (occLight_IsHeadlight (theId) == 0)"
120   EOL"  {"
121   EOL"    aLight   = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight,   1.0));"
122   EOL"    aSpotDir = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aSpotDir, 0.0));"
123   EOL"  }"
124   EOL"  aLight -= thePoint;"
125   EOL
126   EOL"  float aDist = length (aLight);"
127   EOL"  aLight = aLight * (1.0 / aDist);"
128   EOL
129   EOL"  aSpotDir = normalize (aSpotDir);"
130   // light cone
131   EOL"  float aCosA = dot (aSpotDir, -aLight);"
132   EOL"  if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
133   EOL"  {"
134   EOL"    return;"
135   EOL"  }"
136   EOL
137   EOL"  float anExponent = occLight_SpotExponent (theId);"
138   EOL"  float anAtten    = 1.0 / (occLight_ConstAttenuation  (theId)"
139   EOL"                          + occLight_LinearAttenuation (theId) * aDist);"
140   EOL"  if (anExponent > 0.0)"
141   EOL"  {"
142   EOL"    anAtten *= pow (aCosA, anExponent * 128.0);"
143   EOL"  }"
144   EOL
145   EOL"  vec3 aHalf = normalize (aLight + theView);"
146   EOL
147   EOL"  vec3  aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
148   EOL"  float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
149   EOL"  float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
150   EOL
151   EOL"  float aSpecl = 0.0;"
152   EOL"  if (aNdotL > 0.0)"
153   EOL"  {"
154   EOL"    aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
155   EOL"  }"
156   EOL
157   EOL"  Diffuse  += occLight_Diffuse  (theId).rgb * aNdotL * anAtten;"
158   EOL"  Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
159   EOL"}";
160
161 //! Function computes contribution of directional light source
162 const char THE_FUNC_directionalLight[] =
163   EOL"void directionalLight (in int  theId,"
164   EOL"                       in vec3 theNormal,"
165   EOL"                       in vec3 theView,"
166   EOL"                       in bool theIsFront)"
167   EOL"{"
168   EOL"  vec3 aLight = normalize (occLight_Position (theId).xyz);"
169   EOL"  if (occLight_IsHeadlight (theId) == 0)"
170   EOL"  {"
171   EOL"    aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 0.0));"
172   EOL"  }"
173   EOL
174   EOL"  vec3 aHalf = normalize (aLight + theView);"
175   EOL
176   EOL"  vec3  aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
177   EOL"  float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
178   EOL"  float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
179   EOL
180   EOL"  float aSpecl = 0.0;"
181   EOL"  if (aNdotL > 0.0)"
182   EOL"  {"
183   EOL"    aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
184   EOL"  }"
185   EOL
186   EOL"  Diffuse  += occLight_Diffuse  (theId).rgb * aNdotL;"
187   EOL"  Specular += occLight_Specular (theId).rgb * aSpecl;"
188   EOL"}";
189
190 //! Process clipping planes in Fragment Shader.
191 //! Should be added at the beginning of the main() function.
192 const char THE_FRAG_CLIP_PLANES[] =
193   EOL"  for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)"
194   EOL"  {"
195   EOL"    vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
196   EOL"    int  aClipSpace    = occClipPlaneSpaces[aPlaneIter];"
197   EOL"    if (aClipSpace == OccEquationCoords_World)"
198   EOL"    {"
199   EOL"      if (dot (aClipEquation.xyz, PositionWorld.xyz) + aClipEquation.w < 0.0)"
200   EOL"      {"
201   EOL"        discard;"
202   EOL"      }"
203   EOL"    }"
204   EOL"    else if (aClipSpace == OccEquationCoords_View)"
205   EOL"    {"
206   EOL"      if (dot (aClipEquation.xyz, Position.xyz) + aClipEquation.w < 0.0)"
207   EOL"      {"
208   EOL"        discard;"
209   EOL"      }"
210   EOL"    }"
211   EOL"  }";
212
213 }
214
215 // =======================================================================
216 // function : OpenGl_ShaderManager
217 // purpose  : Creates new empty shader manager
218 // =======================================================================
219 OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
220 : myShadingModel (Graphic3d_TOSM_VERTEX),
221   myContext  (theContext),
222   myLastView (NULL)
223 {
224   //
225 }
226
227 // =======================================================================
228 // function : ~OpenGl_ShaderManager
229 // purpose  : Releases resources of shader manager
230 // =======================================================================
231 OpenGl_ShaderManager::~OpenGl_ShaderManager()
232 {
233   myProgramList.Clear();
234 }
235
236 // =======================================================================
237 // function : clear
238 // purpose  :
239 // =======================================================================
240 void OpenGl_ShaderManager::clear()
241 {
242   myProgramList.Clear();
243   myLightPrograms.Nullify();
244   myFlatPrograms = OpenGl_SetOfShaderPrograms();
245   myMapOfLightPrograms.Clear();
246   myFontProgram.Nullify();
247   myBlitProgram.Nullify();
248   for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter)
249   {
250     myStereoPrograms[aModeIter].Nullify();
251   }
252   switchLightPrograms();
253 }
254
255 // =======================================================================
256 // function : Create
257 // purpose  : Creates new shader program
258 // =======================================================================
259 Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
260                                                TCollection_AsciiString&               theShareKey,
261                                                Handle(OpenGl_ShaderProgram)&          theProgram)
262 {
263   theProgram.Nullify();
264   if (theProxy.IsNull())
265   {
266     return Standard_False;
267   }
268
269   theShareKey = theProxy->GetId();
270   if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
271   {
272     if (theProgram->Share())
273     {
274       myProgramList.Append (theProgram);
275     }
276     return Standard_True;
277   }
278
279   theProgram = new OpenGl_ShaderProgram (theProxy);
280   if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
281   {
282     theProgram->Release (myContext);
283     theShareKey.Clear();
284     theProgram.Nullify();
285     return Standard_False;
286   }
287
288   myProgramList.Append (theProgram);
289   myContext->ShareResource (theShareKey, theProgram);
290   return Standard_True;
291 }
292
293 // =======================================================================
294 // function : Unregister
295 // purpose  : Removes specified shader program from the manager
296 // =======================================================================
297 void OpenGl_ShaderManager::Unregister (TCollection_AsciiString&      theShareKey,
298                                        Handle(OpenGl_ShaderProgram)& theProgram)
299 {
300   for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
301   {
302     if (anIt.Value() == theProgram)
303     {
304       if (!theProgram->UnShare())
305       {
306         theShareKey.Clear();
307         theProgram.Nullify();
308         return;
309       }
310
311       myProgramList.Remove (anIt);
312       myMaterialStates.UnBind (theProgram);
313       break;
314     }
315   }
316
317   const TCollection_AsciiString anID = theProgram->myProxy->GetId();
318   if (anID.IsEmpty())
319   {
320     myContext->DelayedRelease (theProgram);
321     theProgram.Nullify();
322   }
323   else
324   {
325     theProgram.Nullify();
326     myContext->ReleaseResource (anID, Standard_True);
327   }
328 }
329
330 // =======================================================================
331 // function : ShaderPrograms
332 // purpose  : Returns list of registered shader programs
333 // =======================================================================
334 const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
335 {
336   return myProgramList;
337 }
338
339 // =======================================================================
340 // function : Empty
341 // purpose  : Returns true if no program objects are attached
342 // =======================================================================
343 Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
344 {
345   return myProgramList.IsEmpty();
346 }
347
348 // =======================================================================
349 // function : switchLightPrograms
350 // purpose  :
351 // =======================================================================
352 void OpenGl_ShaderManager::switchLightPrograms()
353 {
354   TCollection_AsciiString aKey (myShadingModel == Graphic3d_TOSM_FRAGMENT ? "p_" : "g_");
355   const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
356   if (aLights != NULL)
357   {
358     for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next())
359     {
360       switch (aLightIter.Value().Type)
361       {
362         case Graphic3d_TOLS_AMBIENT:
363           break; // skip ambient
364         case Graphic3d_TOLS_DIRECTIONAL:
365           aKey += "d";
366           break;
367         case Graphic3d_TOLS_POSITIONAL:
368           aKey += "p";
369           break;
370         case Graphic3d_TOLS_SPOT:
371           aKey += "s";
372           break;
373       }
374     }
375   }
376
377   if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
378   {
379     myLightPrograms = new OpenGl_SetOfShaderPrograms();
380     myMapOfLightPrograms.Bind (aKey, myLightPrograms);
381   }
382 }
383
384 // =======================================================================
385 // function : UpdateLightSourceStateTo
386 // purpose  : Updates state of OCCT light sources
387 // =======================================================================
388 void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights)
389 {
390   myLightSourceState.Set (theLights);
391   myLightSourceState.Update();
392   switchLightPrograms();
393 }
394
395 // =======================================================================
396 // function : SetShadingModel
397 // purpose  :
398 // =======================================================================
399 void OpenGl_ShaderManager::SetShadingModel (const Graphic3d_TypeOfShadingModel theModel)
400 {
401   myShadingModel = theModel;
402   switchLightPrograms();
403 }
404
405 // =======================================================================
406 // function : SetProjectionState
407 // purpose  : Sets new state of OCCT projection transform
408 // =======================================================================
409 void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix)
410 {
411   myProjectionState.Set (theProjectionMatrix);
412   myProjectionState.Update();
413 }
414
415 // =======================================================================
416 // function : SetModelWorldState
417 // purpose  : Sets new state of OCCT model-world transform
418 // =======================================================================
419 void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix)
420 {
421   myModelWorldState.Set (theModelWorldMatrix);
422   myModelWorldState.Update();
423 }
424
425 // =======================================================================
426 // function : SetWorldViewState
427 // purpose  : Sets new state of OCCT world-view transform
428 // =======================================================================
429 void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix)
430 {
431   myWorldViewState.Set (theWorldViewMatrix);
432   myWorldViewState.Update();
433 }
434
435 // =======================================================================
436 // function : LightSourceState
437 // purpose  : Returns current state of OCCT light sources
438 // =======================================================================
439 const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const
440 {
441   return myLightSourceState;
442 }
443
444 // =======================================================================
445 // function : ProjectionState
446 // purpose  : Returns current state of OCCT projection transform
447 // =======================================================================
448 const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const
449 {
450   return myProjectionState;
451 }
452
453 // =======================================================================
454 // function : ModelWorldState
455 // purpose  : Returns current state of OCCT model-world transform
456 // =======================================================================
457 const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const
458 {
459   return myModelWorldState;
460 }
461
462 // =======================================================================
463 // function : WorldViewState
464 // purpose  : Returns current state of OCCT world-view transform
465 // =======================================================================
466 const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const
467 {
468   return myWorldViewState;
469 }
470
471 //! Packed properties of light source
472 class OpenGl_ShaderLightParameters
473 {
474 public:
475
476   OpenGl_Vec4 Color;
477   OpenGl_Vec4 Position;
478   OpenGl_Vec4 Direction;
479   OpenGl_Vec4 Parameters;
480
481   //! Returns packed (serialized) representation of light source properties
482   const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
483   static Standard_Integer NbOfVec4() { return 4; }
484
485 };
486
487 //! Packed light source type information
488 class OpenGl_ShaderLightType
489 {
490 public:
491
492   Standard_Integer Type;
493   Standard_Integer IsHeadlight;
494
495   //! Returns packed (serialized) representation of light source type
496   const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
497   static Standard_Integer NbOfVec2i() { return 1; }
498
499 };
500
501 // =======================================================================
502 // function : PushLightSourceState
503 // purpose  : Pushes state of OCCT light sources to the program
504 // =======================================================================
505 void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
506 {
507   if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)
508    || !theProgram->IsValid())
509   {
510     return;
511   }
512
513   OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[OpenGLMaxLights];
514   for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt)
515   {
516     aLightTypeArray[aLightIt].Type = -1;
517   }
518
519   const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights);
520   if (aLightsDefNb < 1)
521   {
522     theProgram->SetUniform (myContext,
523                             theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
524                             0);
525     theProgram->SetUniform (myContext,
526                             theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
527                             OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
528     theProgram->SetUniform (myContext,
529                             theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
530                             OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
531                             aLightTypeArray[0].Packed());
532     theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
533     delete[] aLightTypeArray;
534     return;
535   }
536
537   OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb];
538
539   OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
540   Standard_Integer aLightsNb = 0;
541   for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next())
542   {
543     const OpenGl_Light& aLight = anIter.Value();
544     if (aLight.Type == Graphic3d_TOLS_AMBIENT)
545     {
546       anAmbient += aLight.Color;
547       continue;
548     }
549     else if (aLightsNb >= OpenGLMaxLights)
550     {
551       continue;
552     }
553
554     OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb];
555     aLightType.Type        = aLight.Type;
556     aLightType.IsHeadlight = aLight.IsHeadlight;
557
558     OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb];
559     aLightParams.Color    = aLight.Color;
560     aLightParams.Position = aLight.Type == Graphic3d_TOLS_DIRECTIONAL
561                          ? -aLight.Direction
562                          :  aLight.Position;
563     if (aLight.Type == Graphic3d_TOLS_SPOT)
564     {
565       aLightParams.Direction = aLight.Direction;
566     }
567     aLightParams.Parameters = aLight.Params;
568     ++aLightsNb;
569   }
570
571   theProgram->SetUniform (myContext,
572                           theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
573                           aLightsNb);
574   theProgram->SetUniform (myContext,
575                           theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
576                           anAmbient);
577   theProgram->SetUniform (myContext,
578                           theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
579                           OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
580                           aLightTypeArray[0].Packed());
581   if (aLightsNb > 0)
582   {
583     theProgram->SetUniform (myContext,
584                             theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
585                             aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
586                             aLightParamsArray[0].Packed());
587   }
588   delete[] aLightParamsArray;
589   delete[] aLightTypeArray;
590
591   theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
592 }
593
594 // =======================================================================
595 // function : PushProjectionState
596 // purpose  : Pushes state of OCCT projection transform to the program
597 // =======================================================================
598 void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
599 {
600   if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE))
601   {
602     return;
603   }
604
605   theProgram->SetUniform (myContext,
606                           theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
607                           myProjectionState.ProjectionMatrix());
608
609   GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
610   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
611   {
612     theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
613   }
614
615   theProgram->SetUniform (myContext,
616                           theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
617                           myProjectionState.ProjectionMatrix(), true);
618
619   aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
620   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
621   {
622     theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
623   }
624
625   theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
626 }
627
628 // =======================================================================
629 // function : PushModelWorldState
630 // purpose  : Pushes state of OCCT model-world transform to the program
631 // =======================================================================
632 void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
633 {
634   if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
635   {
636     return;
637   }
638
639   theProgram->SetUniform (myContext,
640                           theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
641                           myModelWorldState.ModelWorldMatrix());
642
643   GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
644   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
645   {
646     theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
647   }
648
649   theProgram->SetUniform (myContext,
650                           theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
651                           myModelWorldState.ModelWorldMatrix(), true);
652
653   aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
654   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
655   {
656     theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
657   }
658
659   theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
660 }
661
662 // =======================================================================
663 // function : PushWorldViewState
664 // purpose  : Pushes state of OCCT world-view transform to the program
665 // =======================================================================
666 void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
667 {
668   if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
669   {
670     return;
671   }
672
673   theProgram->SetUniform (myContext,
674                           theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
675                           myWorldViewState.WorldViewMatrix());
676
677   GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
678   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
679   {
680     theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
681   }
682
683   theProgram->SetUniform (myContext,
684                           theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
685                           myWorldViewState.WorldViewMatrix(), true);
686
687   aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
688   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
689   {
690     theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
691   }
692
693   theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
694 }
695
696 // =======================================================================
697 // function : UpdateClippingState
698 // purpose  : Updates state of OCCT clipping planes
699 // =======================================================================
700 void OpenGl_ShaderManager::UpdateClippingState()
701 {
702   myClippingState.Update();
703 }
704
705 // =======================================================================
706 // function : RevertClippingState
707 // purpose  : Reverts state of OCCT clipping planes
708 // =======================================================================
709 void OpenGl_ShaderManager::RevertClippingState()
710 {
711   myClippingState.Revert();
712 }
713
714 // =======================================================================
715 // function : PushClippingState
716 // purpose  : Pushes state of OCCT clipping planes to the program
717 // =======================================================================
718 void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
719 {
720   if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
721   {
722     return;
723   }
724
725   theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
726   const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
727   const GLint aLocSpaces    = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_SPACES);
728   if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION
729    && aLocSpaces    == OpenGl_ShaderProgram::INVALID_LOCATION)
730   {
731     return;
732   }
733
734   GLint aPlanesNb = 0;
735   for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
736        anIter.More(); anIter.Next())
737   {
738     const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
739     if (!myContext->Clipping().IsEnabled (aPlane))
740     {
741       continue;
742     }
743
744     ++aPlanesNb;
745   }
746   if (aPlanesNb < 1)
747   {
748     return;
749   }
750
751   const Standard_Size MAX_CLIP_PLANES = 8;
752   OpenGl_Vec4* anEquations = new OpenGl_Vec4[MAX_CLIP_PLANES];
753   GLint*       aSpaces     = new GLint      [MAX_CLIP_PLANES];
754   GLuint aPlaneId = 0;
755   for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
756        anIter.More(); anIter.Next())
757   {
758     const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
759     if (!myContext->Clipping().IsEnabled (aPlane))
760     {
761       continue;
762     }
763
764     const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
765     anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(),
766                                          (float) anEquation.y(),
767                                          (float) anEquation.z(),
768                                          (float) anEquation.w());
769     aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane);
770     ++aPlaneId;
771   }
772
773   theProgram->SetUniform (myContext,
774                           theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT),
775                           aPlanesNb);
776   theProgram->SetUniform (myContext, aLocEquations, MAX_CLIP_PLANES, anEquations);
777   theProgram->SetUniform (myContext, aLocSpaces,    MAX_CLIP_PLANES, aSpaces);
778
779   delete[] anEquations;
780   delete[] aSpaces;
781 }
782
783 // =======================================================================
784 // function : UpdateMaterialStateTo
785 // purpose  : Updates state of OCCT material for specified program
786 // =======================================================================
787 void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram,
788                                                   const OpenGl_Element*               theAspect)
789 {
790   if (myMaterialStates.IsBound (theProgram))
791   {
792     OpenGl_MaterialState& aState = myMaterialStates.ChangeFind (theProgram);
793     aState.Set (theAspect);
794     aState.Update();
795   }
796   else
797   {
798     myMaterialStates.Bind       (theProgram, OpenGl_MaterialState (theAspect));
799     myMaterialStates.ChangeFind (theProgram).Update();
800   }
801 }
802
803 // =======================================================================
804 // function : ResetMaterialStates
805 // purpose  : Resets state of OCCT material for all programs
806 // =======================================================================
807 void OpenGl_ShaderManager::ResetMaterialStates()
808 {
809   for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
810   {
811     anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0);
812   }
813 }
814
815 // =======================================================================
816 // function : MaterialState
817 // purpose  : Returns state of OCCT material for specified program
818 // =======================================================================
819 const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
820 {
821   if (!myMaterialStates.IsBound (theProgram))
822     return NULL;
823
824   return &myMaterialStates.Find (theProgram);
825 }
826
827 // =======================================================================
828 // function : SurfaceDetailState
829 // purpose  : Returns current state of OCCT surface detail
830 // =======================================================================
831 const OpenGl_SurfaceDetailState& OpenGl_ShaderManager::SurfaceDetailState() const
832 {
833   return mySurfaceDetailState;
834 }
835
836 // =======================================================================
837 // function : UpdateSurfaceDetailStateTo
838 // purpose  : Updates state of OCCT surface detail
839 // =======================================================================
840 void OpenGl_ShaderManager::UpdateSurfaceDetailStateTo (const Graphic3d_TypeOfSurfaceDetail theDetail)
841 {
842   mySurfaceDetailState.Set (theDetail);
843   mySurfaceDetailState.Update();
844 }
845
846 namespace
847 {
848
849 static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f);
850
851 // =======================================================================
852 // function : PushAspectFace
853 // purpose  :
854 // =======================================================================
855 static void PushAspectFace (const Handle(OpenGl_Context)&       theCtx,
856                             const Handle(OpenGl_ShaderProgram)& theProgram,
857                             const OpenGl_AspectFace*            theAspect)
858 {
859   theProgram->SetUniform (theCtx,
860                           theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
861                           theAspect->DoTextureMap());
862   theProgram->SetUniform (theCtx,
863                           theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),
864                           0 /* GL_TEXTURE0 */);
865   theProgram->SetUniform (theCtx,
866                           theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
867                           theAspect->DistinguishingMode());
868
869   OpenGl_Material aParams;
870   for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
871   {
872     const GLint aLoc = theProgram->GetStateLocation (anIndex == 0
873                                                    ? OpenGl_OCCT_FRONT_MATERIAL
874                                                    : OpenGl_OCCT_BACK_MATERIAL);
875     if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
876     {
877       continue;
878     }
879
880     const OPENGL_SURF_PROP& aProp = anIndex == 0 || theAspect->DistinguishingMode() != TOn
881                                   ? theAspect->IntFront()
882                                   : theAspect->IntBack();
883     aParams.Init (aProp);
884     aParams.Diffuse.a() = aProp.trans;
885     theProgram->SetUniform (theCtx, aLoc, OpenGl_Material::NbOfVec4(),
886                             aParams.Packed());
887   }
888 }
889
890 // =======================================================================
891 // function : PushAspectLine
892 // purpose  :
893 // =======================================================================
894 static void PushAspectLine (const Handle(OpenGl_Context)&       theCtx,
895                             const Handle(OpenGl_ShaderProgram)& theProgram,
896                             const OpenGl_AspectLine*            theAspect)
897 {
898   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),   TOff);
899   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
900
901   const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
902                               theAspect->Color().rgb[1],
903                               theAspect->Color().rgb[2],
904                               theAspect->Color().rgb[3]);
905   OpenGl_Vec4 aParams[5];
906   aParams[0] = THE_COLOR_BLACK_VEC4;
907   aParams[1] = THE_COLOR_BLACK_VEC4;
908   aParams[2] = aDiffuse;
909   aParams[3] = THE_COLOR_BLACK_VEC4;
910   aParams[4].x() = 0.0f; // shininess
911   aParams[4].y() = 0.0f; // transparency
912   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
913                           5, aParams);
914 }
915
916 // =======================================================================
917 // function : PushAspectText
918 // purpose  :
919 // =======================================================================
920 static void PushAspectText (const Handle(OpenGl_Context)&       theCtx,
921                             const Handle(OpenGl_ShaderProgram)& theProgram,
922                             const OpenGl_AspectText*            theAspect)
923 {
924   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),   TOn);
925   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
926   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),   0 /* GL_TEXTURE0 */);
927
928   OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
929                         theAspect->Color().rgb[1],
930                         theAspect->Color().rgb[2],
931                         theAspect->Color().rgb[3]);
932   if (theAspect->DisplayType() == Aspect_TODT_DEKALE
933    || theAspect->DisplayType() == Aspect_TODT_SUBTITLE)
934   {
935     aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0],
936                             theAspect->SubtitleColor().rgb[1],
937                             theAspect->SubtitleColor().rgb[2],
938                             theAspect->SubtitleColor().rgb[3]);
939   }
940
941   OpenGl_Vec4 aParams[5];
942   aParams[0] = THE_COLOR_BLACK_VEC4;
943   aParams[1] = THE_COLOR_BLACK_VEC4;
944   aParams[2] = aDiffuse;
945   aParams[3] = THE_COLOR_BLACK_VEC4;
946   aParams[4].x() = 0.0f; // shininess
947   aParams[4].y() = 0.0f; // transparency
948   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
949                           5, aParams);
950 }
951
952 // =======================================================================
953 // function : PushAspectMarker
954 // purpose  :
955 // =======================================================================
956 static void PushAspectMarker (const Handle(OpenGl_Context)&       theCtx,
957                               const Handle(OpenGl_ShaderProgram)& theProgram,
958                               const OpenGl_AspectMarker*          theAspect)
959 {
960   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),   TOn);
961   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
962   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),   0 /* GL_TEXTURE0 */);
963
964   const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
965                               theAspect->Color().rgb[1],
966                               theAspect->Color().rgb[2],
967                               theAspect->Color().rgb[3]);
968   OpenGl_Vec4 aParams[5];
969   aParams[0] = THE_COLOR_BLACK_VEC4;
970   aParams[1] = THE_COLOR_BLACK_VEC4;
971   aParams[2] = aDiffuse;
972   aParams[3] = THE_COLOR_BLACK_VEC4;
973   aParams[4].x() = 0.0f; // shininess
974   aParams[4].y() = 0.0f; // transparency
975   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
976                           5, aParams);
977 }
978
979 }; // nameless namespace
980
981 // =======================================================================
982 // function : PushMaterialState
983 // purpose  : Pushes current state of OCCT material to the program
984 // =======================================================================
985 void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
986 {
987   if (!myMaterialStates.IsBound (theProgram))
988   {
989     return;
990   }
991
992   const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram);
993   if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE))
994   {
995     return;
996   }
997
998   const OpenGl_Element* anAspect = aState.Aspect();
999   if (typeid (*anAspect) == typeid (OpenGl_AspectFace))
1000   {
1001     PushAspectFace   (myContext, theProgram, dynamic_cast<const OpenGl_AspectFace*> (anAspect));
1002   }
1003   else if (typeid (*anAspect) == typeid (OpenGl_AspectLine))
1004   {
1005     PushAspectLine   (myContext, theProgram, dynamic_cast<const OpenGl_AspectLine*> (anAspect));
1006   }
1007   else if (typeid (*anAspect) == typeid (OpenGl_AspectText))
1008   {
1009     PushAspectText   (myContext, theProgram, dynamic_cast<const OpenGl_AspectText*> (anAspect));
1010   }
1011   else if (typeid (*anAspect) == typeid (OpenGl_AspectMarker))
1012   {
1013     PushAspectMarker (myContext, theProgram, dynamic_cast<const OpenGl_AspectMarker*> (anAspect));
1014   }
1015
1016   theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index());
1017 }
1018
1019 // =======================================================================
1020 // function : PushState
1021 // purpose  : Pushes state of OCCT graphics parameters to the program
1022 // =======================================================================
1023 void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1024 {
1025   PushClippingState    (theProgram);
1026   PushMaterialState    (theProgram);
1027   PushWorldViewState   (theProgram);
1028   PushModelWorldState  (theProgram);
1029   PushProjectionState  (theProgram);
1030   PushLightSourceState (theProgram);
1031 }
1032
1033 // =======================================================================
1034 // function : prepareStdProgramFont
1035 // purpose  :
1036 // =======================================================================
1037 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
1038 {
1039   Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1040   TCollection_AsciiString aSrcVert = TCollection_AsciiString()
1041      + EOL"THE_SHADER_OUT vec2 TexCoord;"
1042        EOL"void main()"
1043        EOL"{"
1044        EOL"  TexCoord = occTexCoord.st;"
1045        EOL"  gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1046        EOL"}";
1047
1048   TCollection_AsciiString
1049     aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).a; }";
1050 #if !defined(GL_ES_VERSION_2_0)
1051   if (myContext->core11 == NULL)
1052   {
1053     aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).r; }";
1054   }
1055 #endif
1056
1057   TCollection_AsciiString aSrcFrag = TCollection_AsciiString() +
1058      + EOL"THE_SHADER_IN vec2 TexCoord;"
1059      + aSrcGetAlpha
1060      + EOL"void main()"
1061        EOL"{"
1062        EOL"  vec4 aColor = occColor;"
1063        EOL"  aColor.a *= getAlpha();"
1064        EOL"  if (aColor.a <= 0.285) discard;"
1065        EOL"  occFragColor = aColor;"
1066        EOL"}";
1067
1068 #if !defined(GL_ES_VERSION_2_0)
1069   if (myContext->core32 != NULL)
1070   {
1071     aProgramSrc->SetHeader ("#version 150");
1072   }
1073 #endif
1074   aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX,   aSrcVert));
1075   aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1076   TCollection_AsciiString aKey;
1077   if (!Create (aProgramSrc, aKey, myFontProgram))
1078   {
1079     myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1080     return Standard_False;
1081   }
1082   return Standard_True;
1083 }
1084
1085 // =======================================================================
1086 // function : prepareStdProgramFboBlit
1087 // purpose  :
1088 // =======================================================================
1089 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit()
1090 {
1091   Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1092   TCollection_AsciiString aSrcVert =
1093       EOL"THE_SHADER_OUT vec2 TexCoord;"
1094       EOL"void main()"
1095       EOL"{"
1096       EOL"  TexCoord    = occVertex.zw;"
1097       EOL"  gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1098       EOL"}";
1099
1100   TCollection_AsciiString aSrcFrag =
1101       EOL"uniform sampler2D uColorSampler;"
1102       EOL"uniform sampler2D uDepthSampler;"
1103       EOL
1104       EOL"THE_SHADER_IN vec2 TexCoord;"
1105       EOL
1106       EOL"void main()"
1107       EOL"{"
1108       EOL"  gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;"
1109       EOL"  occFragColor = occTexture2D (uColorSampler, TexCoord);"
1110       EOL"}";
1111
1112 #if defined(GL_ES_VERSION_2_0)
1113   if (myContext->IsGlGreaterEqual (3, 0))
1114   {
1115     aProgramSrc->SetHeader ("#version 300 es");
1116   }
1117   else
1118   {
1119     // there is no way to draw into depth buffer
1120     aSrcFrag =
1121       EOL"uniform sampler2D uColorSampler;"
1122       EOL
1123       EOL"THE_SHADER_IN vec2 TexCoord;"
1124       EOL
1125       EOL"void main()"
1126       EOL"{"
1127       EOL"  occFragColor = occTexture2D (uColorSampler, TexCoord);"
1128       EOL"}";
1129   }
1130 #else
1131   if (myContext->core32 != NULL)
1132   {
1133     aProgramSrc->SetHeader ("#version 150");
1134   }
1135 #endif
1136   aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX,   aSrcVert));
1137   aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1138   TCollection_AsciiString aKey;
1139   if (!Create (aProgramSrc, aKey, myBlitProgram))
1140   {
1141     myBlitProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1142     return Standard_False;
1143   }
1144
1145   myContext->BindProgram (myBlitProgram);
1146   myBlitProgram->SetSampler (myContext, "uColorSampler", 0);
1147   myBlitProgram->SetSampler (myContext, "uDepthSampler", 1);
1148   myContext->BindProgram (NULL);
1149   return Standard_True;
1150 }
1151
1152 // =======================================================================
1153 // function : prepareStdProgramFlat
1154 // purpose  :
1155 // =======================================================================
1156 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_ShaderProgram)& theProgram,
1157                                                               const Standard_Integer        theBits)
1158 {
1159   Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1160   TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
1161   TCollection_AsciiString aSrcFragGetColor     = EOL"vec4 getColor(void) { return occColor; }";
1162   TCollection_AsciiString aSrcFragMainGetColor = EOL"  occFragColor = getColor();";
1163   if ((theBits & OpenGl_PO_Point) != 0)
1164   {
1165   #if defined(GL_ES_VERSION_2_0)
1166     aSrcVertExtraMain += EOL"  gl_PointSize = occPointSize;";
1167   #endif
1168     if ((theBits & OpenGl_PO_TextureA) != 0)
1169     {
1170       TCollection_AsciiString
1171         aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, gl_PointCoord).a; }";
1172     #if !defined(GL_ES_VERSION_2_0)
1173       if (myContext->core11 == NULL)
1174       {
1175         aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, gl_PointCoord).r; }";
1176       }
1177       else if (myContext->IsGlGreaterEqual (2, 1))
1178       {
1179         aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1180       }
1181     #endif
1182
1183       aSrcFragGetColor = aSrcGetAlpha
1184       + EOL"vec4  getColor(void)"
1185         EOL"{"
1186         EOL"  vec4 aColor = occColor;"
1187         EOL"  aColor.a *= getAlpha();"
1188         EOL"  return aColor;"
1189         EOL"}";
1190
1191       aSrcFragMainGetColor =
1192         EOL"  vec4 aColor = getColor();"
1193         EOL"  if (aColor.a <= 0.1) discard;"
1194         EOL"  occFragColor = aColor;";
1195     }
1196     else if ((theBits & OpenGl_PO_TextureRGB) != 0)
1197     {
1198       aSrcFragGetColor =
1199         EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, gl_PointCoord); }";
1200       aSrcFragMainGetColor =
1201         EOL"  vec4 aColor = getColor();"
1202         EOL"  if (aColor.a <= 0.1) discard;"
1203         EOL"  occFragColor = aColor;";
1204     #if !defined(GL_ES_VERSION_2_0)
1205       if (myContext->core11 != NULL
1206        && myContext->IsGlGreaterEqual (2, 1))
1207       {
1208         aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1209       }
1210     #endif
1211     }
1212   }
1213   else
1214   {
1215     if ((theBits & OpenGl_PO_TextureRGB) != 0)
1216     {
1217       aSrcVertExtraOut  += THE_VARY_TexCoord_OUT;
1218       aSrcFragExtraOut  += THE_VARY_TexCoord_IN;
1219       aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
1220
1221       aSrcFragGetColor =
1222         EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w); }";
1223     }
1224     else if ((theBits & OpenGl_PO_TextureEnv) != 0)
1225     {
1226       aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1227       aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1228
1229       aSrcVertExtraFunc = THE_FUNC_transformNormal;
1230
1231       aSrcVertExtraMain +=
1232         EOL"  vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1233         EOL"  vec3 aNormal   = transformNormal (occNormal);"
1234         EOL"  vec3 aReflect  = reflect (normalize (aPosition.xyz), aNormal);"
1235         EOL"  aReflect.z += 1.0;"
1236         EOL"  TexCoord = aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5);";
1237
1238       aSrcFragGetColor =
1239         EOL"vec4 getColor(void) { return occTexture2D (occActiveSampler, TexCoord.st); }";
1240     }
1241   }
1242   if ((theBits & OpenGl_PO_VertColor) != 0)
1243   {
1244     aSrcVertExtraOut  += EOL"THE_SHADER_OUT vec4 VertColor;";
1245     aSrcVertExtraMain += EOL"  VertColor = occVertColor;";
1246     aSrcFragExtraOut  += EOL"THE_SHADER_IN  vec4 VertColor;";
1247     aSrcFragGetColor  =  EOL"vec4 getColor(void) { return VertColor; }";
1248   }
1249   if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1250   {
1251     aSrcVertExtraOut +=
1252       EOL"THE_SHADER_OUT vec4 PositionWorld;"
1253       EOL"THE_SHADER_OUT vec4 Position;";
1254     aSrcFragExtraOut +=
1255       EOL"THE_SHADER_IN  vec4 PositionWorld;"
1256       EOL"THE_SHADER_IN  vec4 Position;";
1257     aSrcVertExtraMain +=
1258       EOL"  PositionWorld = occModelWorldMatrix * occVertex;"
1259       EOL"  Position      = occWorldViewMatrix * PositionWorld;";
1260     aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1261   }
1262
1263   TCollection_AsciiString aSrcVertEndMain;
1264   if ((theBits & OpenGl_PO_StippleLine) != 0)
1265   {
1266     bool hasGlslBitOps = false;
1267   #if defined(GL_ES_VERSION_2_0)
1268     if (myContext->IsGlGreaterEqual (3, 0))
1269     {
1270       aProgramSrc->SetHeader ("#version 300 es");
1271       hasGlslBitOps = true;
1272     }
1273   #else
1274     if (myContext->IsGlGreaterEqual (3, 0))
1275     {
1276       aProgramSrc->SetHeader ("#version 130");
1277       hasGlslBitOps = true;
1278     }
1279     else if(myContext->CheckExtension("GL_EXT_gpu_shader4"))
1280     {
1281       aProgramSrc->SetHeader ("#extension GL_EXT_gpu_shader4 : enable");
1282       hasGlslBitOps = true;
1283     }
1284   #endif
1285
1286     if (hasGlslBitOps)
1287     {
1288       aSrcVertExtraOut +=
1289         EOL"THE_SHADER_OUT vec2 ScreenSpaceCoord;";
1290       aSrcFragExtraOut +=
1291         EOL"THE_SHADER_IN  vec2 ScreenSpaceCoord;"
1292         EOL"uniform int   uPattern;"
1293         EOL"uniform float uFactor;";
1294       aSrcVertEndMain =
1295         EOL"  ScreenSpaceCoord = gl_Position.xy / gl_Position.w;";
1296       aSrcFragMainGetColor =
1297         EOL"  float anAngle      = atan (dFdx (ScreenSpaceCoord.x), dFdy (ScreenSpaceCoord.y));"
1298         EOL"  float aRotatePoint = gl_FragCoord.x * sin (anAngle) + gl_FragCoord.y * cos (anAngle);"
1299         EOL"  uint  aBit         = uint (floor (aRotatePoint / uFactor + 0.5)) & 15U;"
1300         EOL"  if ((uint (uPattern) & (1U << aBit)) == 0U) discard;"
1301         EOL"  vec4 aColor = getColor();"
1302         EOL"  if (aColor.a <= 0.1) discard;"
1303         EOL"  occFragColor = aColor;";
1304     }
1305     else
1306     {
1307       const TCollection_ExtendedString aWarnMessage =
1308         "Warning: stipple lines in GLSL will be ignored.";
1309       myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1310         GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
1311     }
1312   }
1313
1314   aSrcVert =
1315       aSrcVertExtraFunc
1316     + aSrcVertExtraOut
1317     + EOL"void main()"
1318       EOL"{"
1319     + aSrcVertExtraMain
1320     + EOL"  gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1321     + aSrcVertEndMain
1322     + EOL"}";
1323
1324   aSrcFrag =
1325       aSrcFragExtraOut
1326     + aSrcFragGetColor
1327     + EOL"void main()"
1328       EOL"{"
1329     + aSrcFragExtraMain
1330     + aSrcFragMainGetColor
1331     + EOL"}";
1332
1333 #if !defined(GL_ES_VERSION_2_0)
1334   if (myContext->core32 != NULL)
1335   {
1336     aProgramSrc->SetHeader ("#version 150");
1337   }
1338 #endif
1339   aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX,   aSrcVert));
1340   aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1341
1342   TCollection_AsciiString aKey;
1343   if (!Create (aProgramSrc, aKey, theProgram))
1344   {
1345     theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1346     return Standard_False;
1347   }
1348   return Standard_True;
1349 }
1350
1351 // =======================================================================
1352 // function : stdComputeLighting
1353 // purpose  :
1354 // =======================================================================
1355 TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (const Standard_Boolean theHasVertColor)
1356 {
1357   bool aLightsMap[Graphic3d_TOLS_SPOT + 1] = { false, false, false, false };
1358   TCollection_AsciiString aLightsFunc, aLightsLoop;
1359   const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
1360   if (aLights != NULL)
1361   {
1362     Standard_Integer anIndex = 0;
1363     for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next(), ++anIndex)
1364     {
1365       switch (aLightIter.Value().Type)
1366       {
1367         case Graphic3d_TOLS_AMBIENT:
1368           --anIndex;
1369           break; // skip ambient
1370         case Graphic3d_TOLS_DIRECTIONAL:
1371           aLightsLoop = aLightsLoop + EOL"    directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
1372           break;
1373         case Graphic3d_TOLS_POSITIONAL:
1374           aLightsLoop = aLightsLoop + EOL"    pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1375           break;
1376         case Graphic3d_TOLS_SPOT:
1377           aLightsLoop = aLightsLoop + EOL"    spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1378           break;
1379       }
1380
1381       bool& aTypeBit = aLightsMap[aLightIter.Value().Type];
1382       if (aTypeBit)
1383       {
1384         continue;
1385       }
1386
1387       aTypeBit = true;
1388       switch (aLightIter.Value().Type)
1389       {
1390         case Graphic3d_TOLS_AMBIENT:     break;
1391         case Graphic3d_TOLS_DIRECTIONAL: aLightsFunc += THE_FUNC_directionalLight; break;
1392         case Graphic3d_TOLS_POSITIONAL:  aLightsFunc += THE_FUNC_pointLight;       break;
1393         case Graphic3d_TOLS_SPOT:        aLightsFunc += THE_FUNC_spotLight;        break;
1394       }
1395     }
1396   }
1397
1398   TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient()  : occBackMaterial_Ambient();";
1399   TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse()  : occBackMaterial_Diffuse();";
1400   if (theHasVertColor)
1401   {
1402     aGetMatAmbient = "getVertColor();";
1403     aGetMatDiffuse = "getVertColor();";
1404   }
1405
1406   return TCollection_AsciiString()
1407     + THE_FUNC_lightDef
1408     + aLightsFunc
1409     + EOL
1410       EOL"vec4 computeLighting (in vec3 theNormal,"
1411       EOL"                      in vec3 theView,"
1412       EOL"                      in vec4 thePoint,"
1413       EOL"                      in bool theIsFront)"
1414       EOL"{"
1415       EOL"  Ambient  = occLightAmbient.rgb;"
1416       EOL"  Diffuse  = vec3 (0.0);"
1417       EOL"  Specular = vec3 (0.0);"
1418       EOL"  vec3 aPoint = thePoint.xyz / thePoint.w;"
1419     + aLightsLoop
1420     + EOL"  vec4 aMatAmbient  = " + aGetMatAmbient
1421     + EOL"  vec4 aMatDiffuse  = " + aGetMatDiffuse
1422     + EOL"  vec4 aMatSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
1423       EOL"  vec4 aMatEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
1424       EOL"  vec3 aColor = Ambient  * aMatAmbient.rgb"
1425       EOL"              + Diffuse  * aMatDiffuse.rgb"
1426       EOL"              + Specular * aMatSpecular.rgb"
1427       EOL"                         + aMatEmission.rgb;"
1428       EOL"  return vec4 (aColor, aMatDiffuse.a);"
1429       EOL"}";
1430 }
1431
1432 // =======================================================================
1433 // function : prepareStdProgramGouraud
1434 // purpose  :
1435 // =======================================================================
1436 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
1437                                                                  const Standard_Integer        theBits)
1438 {
1439   Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1440   TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
1441   TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
1442   if ((theBits & OpenGl_PO_Point) != 0)
1443   {
1444   #if defined(GL_ES_VERSION_2_0)
1445     aSrcVertExtraMain += EOL"  gl_PointSize = occPointSize;";
1446   #endif
1447   }
1448   if ((theBits & OpenGl_PO_VertColor) != 0)
1449   {
1450     aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
1451   }
1452   if ((theBits & OpenGl_PO_Point) != 0)
1453   {
1454     if ((theBits & OpenGl_PO_TextureRGB) != 0)
1455     {
1456       aSrcFragGetColor =
1457         EOL"vec4 getColor(void)"
1458         EOL"{"
1459         EOL"  vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
1460         EOL"  return occTexture2D(occActiveSampler, gl_PointCoord) * aColor;"
1461         EOL"}";
1462     #if !defined(GL_ES_VERSION_2_0)
1463       if (myContext->core11 != NULL
1464        && myContext->IsGlGreaterEqual (2, 1))
1465       {
1466         aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1467       }
1468     #endif
1469     }
1470   }
1471   else
1472   {
1473     if ((theBits & OpenGl_PO_TextureRGB) != 0)
1474     {
1475       aSrcVertExtraOut  += THE_VARY_TexCoord_OUT;
1476       aSrcFragExtraOut  += THE_VARY_TexCoord_IN;
1477       aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
1478
1479       aSrcFragGetColor =
1480         EOL"vec4 getColor(void)"
1481         EOL"{"
1482         EOL"  vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
1483         EOL"  return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w) * aColor;"
1484         EOL"}";
1485     }
1486   }
1487   if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1488   {
1489     aSrcVertExtraOut +=
1490       EOL"THE_SHADER_OUT vec4 PositionWorld;"
1491       EOL"THE_SHADER_OUT vec4 Position;";
1492     aSrcFragExtraOut +=
1493       EOL"THE_SHADER_IN  vec4 PositionWorld;"
1494       EOL"THE_SHADER_IN  vec4 Position;";
1495     aSrcVertExtraMain +=
1496       EOL"  PositionWorld = aPositionWorld;"
1497       EOL"  Position      = aPosition;";
1498     aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1499   }
1500
1501   const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
1502   aSrcVert = TCollection_AsciiString()
1503     + THE_FUNC_transformNormal
1504     + EOL
1505     + aSrcVertColor
1506     + aLights
1507     + EOL
1508       EOL"THE_SHADER_OUT vec4 FrontColor;"
1509       EOL"THE_SHADER_OUT vec4 BackColor;"
1510       EOL
1511     + aSrcVertExtraOut
1512     + EOL"void main()"
1513       EOL"{"
1514       EOL"  vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
1515       EOL"  vec4 aPosition      = occWorldViewMatrix * aPositionWorld;"
1516       EOL"  vec3 aNormal        = transformNormal (occNormal);"
1517       EOL"  vec3 aView          = vec3 (0.0, 0.0, 1.0);"
1518       EOL"  FrontColor  = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
1519       EOL"  BackColor   = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
1520     + aSrcVertExtraMain
1521     + EOL"  gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1522       EOL"}";
1523
1524   aSrcFrag = TCollection_AsciiString()
1525     + EOL"THE_SHADER_IN vec4 FrontColor;"
1526       EOL"THE_SHADER_IN vec4 BackColor;"
1527     + aSrcFragExtraOut
1528     + aSrcFragGetColor
1529     + EOL"void main()"
1530       EOL"{"
1531     + aSrcFragExtraMain
1532     + EOL"  occFragColor = getColor();"
1533       EOL"}";
1534
1535 #if !defined(GL_ES_VERSION_2_0)
1536   if (myContext->core32 != NULL)
1537   {
1538     aProgramSrc->SetHeader ("#version 150");
1539   }
1540 #endif
1541   aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX,   aSrcVert));
1542   aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1543   TCollection_AsciiString aKey;
1544   if (!Create (aProgramSrc, aKey, theProgram))
1545   {
1546     theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1547     return Standard_False;
1548   }
1549   return Standard_True;
1550 }
1551
1552 // =======================================================================
1553 // function : prepareStdProgramPhong
1554 // purpose  :
1555 // =======================================================================
1556 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
1557                                                                const Standard_Integer        theBits)
1558 {
1559   #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
1560
1561   Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1562   TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain;
1563   TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
1564   if ((theBits & OpenGl_PO_Point) != 0)
1565   {
1566   #if defined(GL_ES_VERSION_2_0)
1567     aSrcVertExtraMain += EOL"  gl_PointSize = occPointSize;";
1568   #endif
1569   }
1570   if ((theBits & OpenGl_PO_VertColor) != 0)
1571   {
1572     aSrcVertExtraOut    += EOL"THE_SHADER_OUT vec4 VertColor;";
1573     aSrcVertExtraMain   += EOL"  VertColor = occVertColor;";
1574     aSrcFragGetVertColor = EOL"THE_SHADER_IN  vec4 VertColor;"
1575                            EOL"vec4 getVertColor(void) { return VertColor; }";
1576   }
1577
1578   if ((theBits & OpenGl_PO_Point) != 0)
1579   {
1580     if ((theBits & OpenGl_PO_TextureRGB) != 0)
1581     {
1582       aSrcFragGetColor =
1583         EOL"vec4 getColor(void)"
1584         EOL"{"
1585         EOL"  vec4 aColor = " thePhongCompLight ";"
1586         EOL"  return occTexture2D(occActiveSampler, gl_PointCoord) * aColor;"
1587         EOL"}";
1588     #if !defined(GL_ES_VERSION_2_0)
1589       if (myContext->core11 != NULL
1590        && myContext->IsGlGreaterEqual (2, 1))
1591       {
1592         aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1593       }
1594     #endif
1595     }
1596   }
1597   else
1598   {
1599     if ((theBits & OpenGl_PO_TextureRGB) != 0)
1600     {
1601       aSrcVertExtraOut  += THE_VARY_TexCoord_OUT;
1602       aSrcFragExtraOut  += THE_VARY_TexCoord_IN;
1603       aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
1604
1605       aSrcFragGetColor =
1606         EOL"vec4 getColor(void)"
1607         EOL"{"
1608         EOL"  vec4 aColor = " thePhongCompLight ";"
1609         EOL"  return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w) * aColor;"
1610         EOL"}";
1611     }
1612   }
1613
1614   if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1615   {
1616     aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1617   }
1618
1619   aSrcVert = TCollection_AsciiString()
1620     + THE_FUNC_transformNormal
1621     + EOL
1622       EOL"THE_SHADER_OUT vec4 PositionWorld;"
1623       EOL"THE_SHADER_OUT vec4 Position;"
1624       EOL"THE_SHADER_OUT vec3 Normal;"
1625       EOL"THE_SHADER_OUT vec3 View;"
1626       EOL
1627     + aSrcVertExtraOut
1628     + EOL"void main()"
1629       EOL"{"
1630       EOL"  PositionWorld = occModelWorldMatrix * occVertex;"
1631       EOL"  Position      = occWorldViewMatrix * PositionWorld;"
1632       EOL"  Normal        = transformNormal (occNormal);"
1633       EOL"  View          = vec3 (0.0, 0.0, 1.0);"
1634     + aSrcVertExtraMain
1635     + EOL"  gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1636       EOL"}";
1637
1638   const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
1639   aSrcFrag = TCollection_AsciiString()
1640     + EOL"THE_SHADER_IN vec4 PositionWorld;"
1641       EOL"THE_SHADER_IN vec4 Position;"
1642       EOL"THE_SHADER_IN vec3 Normal;"
1643       EOL"THE_SHADER_IN vec3 View;"
1644     + EOL
1645     + aSrcFragExtraOut
1646     + aSrcFragGetVertColor
1647     + aLights
1648     + aSrcFragGetColor
1649     + EOL
1650       EOL"void main()"
1651       EOL"{"
1652     + aSrcFragExtraMain
1653     + EOL"  occFragColor = getColor();"
1654       EOL"}";
1655
1656 #if !defined(GL_ES_VERSION_2_0)
1657   if (myContext->core32 != NULL)
1658   {
1659     aProgramSrc->SetHeader ("#version 150");
1660   }
1661 #endif
1662   aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX,   aSrcVert));
1663   aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1664   TCollection_AsciiString aKey;
1665   if (!Create (aProgramSrc, aKey, theProgram))
1666   {
1667     theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1668     return Standard_False;
1669   }
1670   return Standard_True;
1671 }
1672
1673 // =======================================================================
1674 // function : prepareStdProgramStereo
1675 // purpose  :
1676 // =======================================================================
1677 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
1678                                                                 const Graphic3d_StereoMode    theStereoMode)
1679 {
1680   Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1681   TCollection_AsciiString aSrcVert =
1682       EOL"THE_SHADER_OUT vec2 TexCoord;"
1683       EOL"void main()"
1684       EOL"{"
1685       EOL"  TexCoord    = occVertex.zw;"
1686       EOL"  gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1687       EOL"}";
1688
1689   TCollection_AsciiString aSrcFrag;
1690   switch (theStereoMode)
1691   {
1692     case Graphic3d_StereoMode_Anaglyph:
1693     {
1694       aSrcFrag =
1695           EOL"uniform sampler2D uLeftSampler;"
1696           EOL"uniform sampler2D uRightSampler;"
1697           EOL
1698           EOL"uniform mat4 uMultL;"
1699           EOL"uniform mat4 uMultR;"
1700           EOL
1701           EOL"vec4 THE_POW_UP   = vec4 (2.2, 2.2, 2.2, 1.0);"
1702           EOL"vec4 THE_POW_DOWN = 1.0 / THE_POW_UP;"
1703           EOL
1704           EOL"THE_SHADER_IN vec2 TexCoord;"
1705           EOL
1706           EOL"void main()"
1707           EOL"{"
1708           EOL"  vec4 aColorL = occTexture2D (uLeftSampler,  TexCoord);"
1709           EOL"  vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1710           EOL"  aColorL = pow (aColorL, THE_POW_UP);" // normalize
1711           EOL"  aColorR = pow (aColorR, THE_POW_UP);"
1712           EOL"  vec4 aColor = uMultR * aColorR + uMultL * aColorL;"
1713           EOL"  occFragColor = pow (aColor, THE_POW_DOWN);"
1714           EOL"}";
1715       break;
1716     }
1717     case Graphic3d_StereoMode_RowInterlaced:
1718     {
1719       aSrcFrag =
1720           EOL"uniform sampler2D uLeftSampler;"
1721           EOL"uniform sampler2D uRightSampler;"
1722           EOL
1723           EOL"THE_SHADER_IN vec2 TexCoord;"
1724           EOL
1725           EOL"void main()"
1726           EOL"{"
1727           EOL"  vec4 aColorL = occTexture2D (uLeftSampler,  TexCoord);"
1728           EOL"  vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1729           EOL"  if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)"
1730           EOL"  {"
1731           EOL"    occFragColor = aColorL;"
1732           EOL"  }"
1733           EOL"  else"
1734           EOL"  {"
1735           EOL"    occFragColor = aColorR;"
1736           EOL"  }"
1737           EOL"}";
1738       break;
1739     }
1740     case Graphic3d_StereoMode_ColumnInterlaced:
1741     {
1742       aSrcFrag =
1743           EOL"uniform sampler2D uLeftSampler;"
1744           EOL"uniform sampler2D uRightSampler;"
1745           EOL
1746           EOL"THE_SHADER_IN vec2 TexCoord;"
1747           EOL
1748           EOL"void main()"
1749           EOL"{"
1750           EOL"  vec4 aColorL = occTexture2D (uLeftSampler,  TexCoord);"
1751           EOL"  vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1752           EOL"  if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)"
1753           EOL"  {"
1754           EOL"    occFragColor = aColorL;"
1755           EOL"  }"
1756           EOL"  else"
1757           EOL"  {"
1758           EOL"    occFragColor = aColorR;"
1759           EOL"  }"
1760           EOL"}";
1761       break;
1762     }
1763     case Graphic3d_StereoMode_ChessBoard:
1764     {
1765       aSrcFrag =
1766           EOL"uniform sampler2D uLeftSampler;"
1767           EOL"uniform sampler2D uRightSampler;"
1768           EOL
1769           EOL"THE_SHADER_IN vec2 TexCoord;"
1770           EOL
1771           EOL"void main()"
1772           EOL"{"
1773           EOL"  vec4 aColorL = occTexture2D (uLeftSampler,  TexCoord);"
1774           EOL"  vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1775           EOL"  bool isEvenX = int(mod(floor(gl_FragCoord.x - 1023.5), 2.0)) != 1;"
1776           EOL"  bool isEvenY = int(mod(floor(gl_FragCoord.y - 1023.5), 2.0)) == 1;"
1777           EOL"  if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))"
1778           EOL"  {"
1779           EOL"    occFragColor = aColorL;"
1780           EOL"  }"
1781           EOL"  else"
1782           EOL"  {"
1783           EOL"    occFragColor = aColorR;"
1784           EOL"  }"
1785           EOL"}";
1786       break;
1787     }
1788     case Graphic3d_StereoMode_SideBySide:
1789     {
1790       aSrcFrag =
1791           EOL"uniform sampler2D uLeftSampler;"
1792           EOL"uniform sampler2D uRightSampler;"
1793           EOL
1794           EOL"THE_SHADER_IN vec2 TexCoord;"
1795           EOL
1796           EOL"void main()"
1797           EOL"{"
1798           EOL"  vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);"
1799           EOL"  if (TexCoord.x > 0.5)"
1800           EOL"  {"
1801           EOL"    aTexCoord.x -= 1.0;"
1802           EOL"  }"
1803           EOL"  vec4 aColorL = occTexture2D (uLeftSampler,  aTexCoord);"
1804           EOL"  vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
1805           EOL"  if (TexCoord.x <= 0.5)"
1806           EOL"  {"
1807           EOL"    occFragColor = aColorL;"
1808           EOL"  }"
1809           EOL"  else"
1810           EOL"  {"
1811           EOL"    occFragColor = aColorR;"
1812           EOL"  }"
1813           EOL"}";
1814       break;
1815     }
1816     case Graphic3d_StereoMode_OverUnder:
1817     {
1818       aSrcFrag =
1819           EOL"uniform sampler2D uLeftSampler;"
1820           EOL"uniform sampler2D uRightSampler;"
1821           EOL
1822           EOL"THE_SHADER_IN vec2 TexCoord;"
1823           EOL
1824           EOL"void main()"
1825           EOL"{"
1826           EOL"  vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);"
1827           EOL"  if (TexCoord.y > 0.5)"
1828           EOL"  {"
1829           EOL"    aTexCoord.y -= 1.0;"
1830           EOL"  }"
1831           EOL"  vec4 aColorL = occTexture2D (uLeftSampler,  aTexCoord);"
1832           EOL"  vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
1833           EOL"  if (TexCoord.y <= 0.5)"
1834           EOL"  {"
1835           EOL"    occFragColor = aColorL;"
1836           EOL"  }"
1837           EOL"  else"
1838           EOL"  {"
1839           EOL"    occFragColor = aColorR;"
1840           EOL"  }"
1841           EOL"}";
1842       break;
1843     }
1844     case Graphic3d_StereoMode_QuadBuffer:
1845     case Graphic3d_StereoMode_SoftPageFlip:
1846     default:
1847     {
1848       /*const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[Graphic3d_StereoMode_QuadBuffer];
1849       if (!aProgram.IsNull())
1850       {
1851         return aProgram->IsValid();
1852       }*/
1853       aSrcFrag =
1854           EOL"uniform sampler2D uLeftSampler;"
1855           EOL"uniform sampler2D uRightSampler;"
1856           EOL
1857           EOL"THE_SHADER_IN vec2 TexCoord;"
1858           EOL
1859           EOL"void main()"
1860           EOL"{"
1861           EOL"  vec4 aColorL = occTexture2D (uLeftSampler,  TexCoord);"
1862           EOL"  vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1863           EOL"  aColorL.b = 0.0;"
1864           EOL"  aColorL.g = 0.0;"
1865           EOL"  aColorR.r = 0.0;"
1866           EOL"  occFragColor = aColorL + aColorR;"
1867           EOL"}";
1868       break;
1869     }
1870   }
1871
1872 #if !defined(GL_ES_VERSION_2_0)
1873   if (myContext->core32 != NULL)
1874   {
1875     aProgramSrc->SetHeader ("#version 150");
1876   }
1877 #endif
1878
1879   aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX,   aSrcVert));
1880   aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1881   TCollection_AsciiString aKey;
1882   if (!Create (aProgramSrc, aKey, theProgram))
1883   {
1884     theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1885     return Standard_False;
1886   }
1887
1888   myContext->BindProgram (theProgram);
1889   theProgram->SetSampler (myContext, "uLeftSampler",  0);
1890   theProgram->SetSampler (myContext, "uRightSampler", 1);
1891   myContext->BindProgram (NULL);
1892   return Standard_True;
1893 }
1894
1895 // =======================================================================
1896 // function : bindProgramWithState
1897 // purpose  :
1898 // =======================================================================
1899 Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram,
1900                                                              const OpenGl_Element*               theAspect)
1901 {
1902   if (!myContext->BindProgram (theProgram))
1903   {
1904     return Standard_False;
1905   }
1906   theProgram->ApplyVariables (myContext);
1907
1908   const OpenGl_MaterialState* aMaterialState = MaterialState (theProgram);
1909   if (aMaterialState == NULL || aMaterialState->Aspect() != theAspect)
1910   {
1911     UpdateMaterialStateTo (theProgram, theAspect);
1912   }
1913
1914   PushState (theProgram);
1915   return Standard_True;
1916 }