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