11a0ebe34febfac7634e16f2ea581d079335e99d
[occt.git] / src / OpenGl / OpenGl_ShaderManager.cxx
1 // Created on: 2013-09-26
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013 OPEN CASCADE SAS
4 //
5 // The content of this file is subject to the Open CASCADE Technology Public
6 // License Version 6.5 (the "License"). You may not use the content of this file
7 // except in compliance with the License. Please obtain a copy of the License
8 // at http://www.opencascade.org and read it completely before using this file.
9 //
10 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
11 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
12 //
13 // The Original Code and all software distributed under the License is
14 // distributed on an "AS IS" basis, without warranty of any kind, and the
15 // Initial Developer hereby disclaims all such warranties, including without
16 // limitation, any warranties of merchantability, fitness for a particular
17 // purpose or non-infringement. Please see the License for the specific terms
18 // and conditions governing the rights and limitations under the License.
19
20 #include <typeinfo>
21
22 #include <OpenGl_AspectFace.hxx>
23 #include <OpenGl_AspectLine.hxx>
24 #include <OpenGl_AspectMarker.hxx>
25 #include <OpenGl_AspectText.hxx>
26 #include <OpenGl_Clipping.hxx>
27 #include <OpenGl_Context.hxx>
28 #include <OpenGl_ShaderManager.hxx>
29 #include <OpenGl_ShaderProgram.hxx>
30 #include <OpenGl_Workspace.hxx>
31
32 IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderManager, Standard_Transient)
33 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient)
34
35 // =======================================================================
36 // function : OpenGl_ShaderManager
37 // purpose  : Creates new empty shader manager
38 // =======================================================================
39 OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
40 : myContext (theContext),
41   myIsPP    (Standard_False)
42 {
43   //
44 }
45
46 // =======================================================================
47 // function : ~OpenGl_ShaderManager
48 // purpose  : Releases resources of shader manager
49 // =======================================================================
50 OpenGl_ShaderManager::~OpenGl_ShaderManager()
51 {
52   myProgramList.Clear();
53 }
54
55 // =======================================================================
56 // function : Create
57 // purpose  : Creates new shader program
58 // =======================================================================
59 void OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
60                                    TCollection_AsciiString&               theShareKey,
61                                    Handle(OpenGl_ShaderProgram)&          theProgram)
62 {
63   theProgram.Nullify();
64   if (theProxy.IsNull())
65   {
66     return;
67   }
68
69   theShareKey = theProxy->GetId();
70   if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
71   {
72     if (theProgram->Share())
73     {
74       myProgramList.Append (theProgram);
75     }
76     return;
77   }
78
79   theProgram = new OpenGl_ShaderProgram (theProxy);
80   if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
81   {
82     theProgram->Release (myContext);
83     theShareKey.Clear();
84     theProgram.Nullify();
85     return;
86   }
87
88   myProgramList.Append (theProgram);
89   myContext->ShareResource (theShareKey, theProgram);
90 }
91
92 // =======================================================================
93 // function : Unregister
94 // purpose  : Removes specified shader program from the manager
95 // =======================================================================
96 void OpenGl_ShaderManager::Unregister (TCollection_AsciiString&      theShareKey,
97                                        Handle(OpenGl_ShaderProgram)& theProgram)
98 {
99   for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
100   {
101     if (anIt.Value() == theProgram)
102     {
103       if (!theProgram->UnShare())
104       {
105         theShareKey.Clear();
106         theProgram.Nullify();
107         return;
108       }
109
110       myProgramList.Remove (anIt);
111       myMaterialStates.UnBind (theProgram);
112       break;
113     }
114   }
115
116   const TCollection_AsciiString anID = theProgram->myProxy->GetId();
117   if (anID.IsEmpty())
118   {
119     myContext->DelayedRelease (theProgram);
120     theProgram.Nullify();
121   }
122   else
123   {
124     theProgram.Nullify();
125     myContext->ReleaseResource (anID, Standard_True);
126   }
127 }
128
129 // =======================================================================
130 // function : ShaderPrograms
131 // purpose  : Returns list of registered shader programs
132 // =======================================================================
133 const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
134 {
135   return myProgramList;
136 }
137
138 // =======================================================================
139 // function : Empty
140 // purpose  : Returns true if no program objects are attached
141 // =======================================================================
142 Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
143 {
144   return myProgramList.IsEmpty();
145 }
146
147 // =======================================================================
148 // function : UpdateLightSourceStateTo
149 // purpose  : Updates state of OCCT light sources
150 // =======================================================================
151 void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights)
152 {
153   myLightSourceState.Set (theLights);
154   myLightSourceState.Update();
155 }
156
157 // =======================================================================
158 // function : SetProjectionState
159 // purpose  : Sets new state of OCCT projection transform
160 // =======================================================================
161 void OpenGl_ShaderManager::UpdateProjectionStateTo (const Tmatrix3& theProjectionMatrix)
162 {
163   myProjectionState.Set (theProjectionMatrix);
164   myProjectionState.Update();
165 }
166
167 // =======================================================================
168 // function : SetModelWorldState
169 // purpose  : Sets new state of OCCT model-world transform
170 // =======================================================================
171 void OpenGl_ShaderManager::UpdateModelWorldStateTo (const Tmatrix3& theModelWorldMatrix)
172 {
173   myModelWorldState.Set (theModelWorldMatrix);
174   myModelWorldState.Update();
175 }
176
177 // =======================================================================
178 // function : SetWorldViewState
179 // purpose  : Sets new state of OCCT world-view transform
180 // =======================================================================
181 void OpenGl_ShaderManager::UpdateWorldViewStateTo (const Tmatrix3& theWorldViewMatrix)
182 {
183   myWorldViewState.Set (theWorldViewMatrix);
184   myWorldViewState.Update();
185 }
186
187 // =======================================================================
188 // function : RevertProjectionStateTo
189 // purpose  : Reverts state of OCCT projection transform
190 // =======================================================================
191 void OpenGl_ShaderManager::RevertProjectionStateTo (const Tmatrix3& theProjectionMatrix)
192 {
193   myProjectionState.Set (theProjectionMatrix);
194   myProjectionState.Revert();
195 }
196
197 // =======================================================================
198 // function : RevertModelWorldStateTo
199 // purpose  : Reverts state of OCCT model-world transform
200 // =======================================================================
201 void OpenGl_ShaderManager::RevertModelWorldStateTo (const Tmatrix3& theModelWorldMatrix)
202 {
203   myModelWorldState.Set (theModelWorldMatrix);
204   myModelWorldState.Revert();
205 }
206
207 // =======================================================================
208 // function : RevertWorldViewStateTo
209 // purpose  : Reverts state of OCCT world-view transform
210 // =======================================================================
211 void OpenGl_ShaderManager::RevertWorldViewStateTo (const Tmatrix3& theWorldViewMatrix)
212 {
213   myWorldViewState.Set (theWorldViewMatrix);
214   myWorldViewState.Revert();
215 }
216
217 // =======================================================================
218 // function : LightSourceState
219 // purpose  : Returns current state of OCCT light sources
220 // =======================================================================
221 const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const
222 {
223   return myLightSourceState;
224 }
225
226 // =======================================================================
227 // function : ProjectionState
228 // purpose  : Returns current state of OCCT projection transform
229 // =======================================================================
230 const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const
231 {
232   return myProjectionState;
233 }
234
235 // =======================================================================
236 // function : ModelWorldState
237 // purpose  : Returns current state of OCCT model-world transform
238 // =======================================================================
239 const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const
240 {
241   return myModelWorldState;
242 }
243
244 // =======================================================================
245 // function : WorldViewState
246 // purpose  : Returns current state of OCCT world-view transform
247 // =======================================================================
248 const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const
249 {
250   return myWorldViewState;
251 }
252
253 //! Packed properties of light source
254 class OpenGl_ShaderLightParameters
255 {
256 public:
257
258   OpenGl_Vec4 Color;
259   OpenGl_Vec4 Position;
260   OpenGl_Vec4 Direction;
261   OpenGl_Vec4 Parameters;
262
263   //! Returns packed (serialized) representation of light source properties
264   const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
265   static Standard_Integer NbOfVec4() { return 4; }
266
267 };
268
269 //! Packed light source type information
270 class OpenGl_ShaderLightType
271 {
272 public:
273
274   Standard_Integer Type;
275   Standard_Integer IsHeadlight;
276
277   //! Returns packed (serialized) representation of light source type
278   const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
279   static Standard_Integer NbOfVec2i() { return 1; }
280
281 };
282
283 // =======================================================================
284 // function : PushLightSourceState
285 // purpose  : Pushes state of OCCT light sources to the program
286 // =======================================================================
287 void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
288 {
289   if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)
290    || !theProgram->IsValid())
291   {
292     return;
293   }
294
295   OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[OpenGLMaxLights];
296   for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt)
297   {
298     aLightTypeArray[aLightIt].Type = -1;
299   }
300
301   const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights);
302   if (aLightsDefNb < 1)
303   {
304     theProgram->SetUniform (myContext,
305                             theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
306                             0);
307     theProgram->SetUniform (myContext,
308                             theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
309                             OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
310     theProgram->SetUniform (myContext,
311                             theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
312                             OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
313                             aLightTypeArray[0].Packed());
314     theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
315     return;
316   }
317
318   OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb];
319
320   OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
321   Standard_Integer aLightsNb = 0;
322   for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next())
323   {
324     const OpenGl_Light& aLight = anIter.Value();
325     if (aLight.Type == Visual3d_TOLS_AMBIENT)
326     {
327       anAmbient += aLight.Color;
328       continue;
329     }
330     else if (aLightsNb >= OpenGLMaxLights)
331     {
332       continue;
333     }
334
335     OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb];
336     aLightType.Type        = aLight.Type;
337     aLightType.IsHeadlight = aLight.IsHeadlight;
338
339     OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb];
340     aLightParams.Color    = aLight.Color;
341     aLightParams.Position = aLight.Type == Visual3d_TOLS_DIRECTIONAL
342                          ? -aLight.Direction
343                          :  aLight.Position;
344     if (aLight.Type == Visual3d_TOLS_SPOT)
345     {
346       aLightParams.Direction = aLight.Direction;
347     }
348     aLightParams.Parameters = aLight.Params;
349     ++aLightsNb;
350   }
351
352   theProgram->SetUniform (myContext,
353                           theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
354                           aLightsNb);
355   theProgram->SetUniform (myContext,
356                           theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
357                           anAmbient);
358   theProgram->SetUniform (myContext,
359                           theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
360                           OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
361                           aLightTypeArray[0].Packed());
362   if (aLightsNb > 0)
363   {
364     theProgram->SetUniform (myContext,
365                             theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
366                             aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
367                             aLightParamsArray[0].Packed());
368   }
369   delete[] aLightParamsArray;
370   delete[] aLightTypeArray;
371
372   theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
373 }
374
375 // =======================================================================
376 // function : PushProjectionState
377 // purpose  : Pushes state of OCCT projection transform to the program
378 // =======================================================================
379 void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
380 {
381   if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE))
382   {
383     return;
384   }
385
386   theProgram->SetUniform (myContext,
387                           theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
388                           myProjectionState.ProjectionMatrix());
389
390   GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
391   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
392   {
393     theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
394   }
395
396   theProgram->SetUniform (myContext,
397                           theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
398                           myProjectionState.ProjectionMatrix(), true);
399
400   aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
401   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
402   {
403     theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
404   }
405
406   theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
407 }
408
409 // =======================================================================
410 // function : PushModelWorldState
411 // purpose  : Pushes state of OCCT model-world transform to the program
412 // =======================================================================
413 void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
414 {
415   if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
416   {
417     return;
418   }
419
420   theProgram->SetUniform (myContext,
421                           theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
422                           myModelWorldState.ModelWorldMatrix());
423
424   GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
425   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
426   {
427     theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
428   }
429
430   theProgram->SetUniform (myContext,
431                           theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
432                           myModelWorldState.ModelWorldMatrix(), true);
433
434   aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
435   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
436   {
437     theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
438   }
439
440   theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
441 }
442
443 // =======================================================================
444 // function : PushWorldViewState
445 // purpose  : Pushes state of OCCT world-view transform to the program
446 // =======================================================================
447 void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
448 {
449   if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
450   {
451     return;
452   }
453
454   theProgram->SetUniform (myContext,
455                           theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
456                           myWorldViewState.WorldViewMatrix());
457
458   GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
459   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
460   {
461     theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
462   }
463
464   theProgram->SetUniform (myContext,
465                           theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
466                           myWorldViewState.WorldViewMatrix(), true);
467
468   aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
469   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
470   {
471     theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
472   }
473
474   theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
475 }
476
477 // =======================================================================
478 // function : UpdateClippingState
479 // purpose  : Updates state of OCCT clipping planes
480 // =======================================================================
481 void OpenGl_ShaderManager::UpdateClippingState()
482 {
483   myClippingState.Update();
484 }
485
486 // =======================================================================
487 // function : RevertClippingState
488 // purpose  : Reverts state of OCCT clipping planes
489 // =======================================================================
490 void OpenGl_ShaderManager::RevertClippingState()
491 {
492   myClippingState.Revert();
493 }
494
495 // =======================================================================
496 // function : PushClippingState
497 // purpose  : Pushes state of OCCT clipping planes to the program
498 // =======================================================================
499 void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
500 {
501   if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
502   {
503     return;
504   }
505
506   theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
507   const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
508   const GLint aLocSpaces    = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_SPACES);
509   if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION
510    && aLocSpaces    == OpenGl_ShaderProgram::INVALID_LOCATION)
511   {
512     return;
513   }
514
515   GLuint aPlanesNb = 0;
516   for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
517        anIter.More(); anIter.Next())
518   {
519     const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
520     if (!myContext->Clipping().IsEnabled (aPlane))
521     {
522       continue;
523     }
524
525     ++aPlanesNb;
526   }
527   if (aPlanesNb < 1)
528   {
529     return;
530   }
531
532   OpenGl_Vec4* anEquations = new OpenGl_Vec4[aPlanesNb];
533   GLint*       aSpaces     = new GLint      [aPlanesNb];
534   GLuint aPlaneId = 0;
535   for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
536        anIter.More(); anIter.Next())
537   {
538     const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
539     if (!myContext->Clipping().IsEnabled (aPlane))
540     {
541       continue;
542     }
543
544     const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
545     anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(),
546                                          (float) anEquation.y(),
547                                          (float) anEquation.z(),
548                                          (float) anEquation.w());
549     aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane);
550     ++aPlaneId;
551   }
552   theProgram->SetUniform (myContext, aLocEquations, aPlanesNb, anEquations[0].GetData());
553   theProgram->SetUniform (myContext, aLocSpaces,    aPlanesNb, aSpaces);
554
555   delete[] anEquations;
556   delete[] aSpaces;
557 }
558
559 // =======================================================================
560 // function : UpdateMaterialStateTo
561 // purpose  : Updates state of OCCT material for specified program
562 // =======================================================================
563 void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram,
564                                                   const OpenGl_Element*               theAspect)
565 {
566   if (myMaterialStates.IsBound (theProgram))
567   {
568     myMaterialStates.ChangeFind (theProgram).Set (theAspect);
569   }
570   else
571   {
572     myMaterialStates.Bind (theProgram, OpenGl_MaterialState (theAspect));
573   }
574
575   myMaterialStates.ChangeFind (theProgram).Update();
576 }
577
578 // =======================================================================
579 // function : ResetMaterialStates
580 // purpose  : Resets state of OCCT material for all programs
581 // =======================================================================
582 void OpenGl_ShaderManager::ResetMaterialStates()
583 {
584   for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
585   {
586     anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0);
587   }
588 }
589
590 // =======================================================================
591 // function : MaterialState
592 // purpose  : Returns state of OCCT material for specified program
593 // =======================================================================
594 const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
595 {
596   if (!myMaterialStates.IsBound (theProgram))
597     return NULL;
598
599   return &myMaterialStates.Find (theProgram);
600 }
601
602 namespace
603 {
604
605 static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f);
606
607 // =======================================================================
608 // function : PushAspectFace
609 // purpose  :
610 // =======================================================================
611 static void PushAspectFace (const Handle(OpenGl_Context)&       theCtx,
612                             const Handle(OpenGl_ShaderProgram)& theProgram,
613                             const OpenGl_AspectFace*            theAspect)
614 {
615   theProgram->SetUniform (theCtx,
616                           theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
617                           theAspect->DoTextureMap());
618   theProgram->SetUniform (theCtx,
619                           theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),
620                           0 /* GL_TEXTURE0 */);
621   theProgram->SetUniform (theCtx,
622                           theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
623                           theAspect->DistinguishingMode());
624
625   OpenGl_Material aParams;
626   for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
627   {
628     const GLint aLoc = theProgram->GetStateLocation (anIndex == 0
629                                                    ? OpenGl_OCCT_FRONT_MATERIAL
630                                                    : OpenGl_OCCT_BACK_MATERIAL);
631     if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
632     {
633       continue;
634     }
635
636     aParams.Init (anIndex == 0 ? theAspect->IntFront() : theAspect->IntBack());
637     theProgram->SetUniform (theCtx, aLoc, OpenGl_Material::NbOfVec4(),
638                             aParams.Packed());
639   }
640 }
641
642 // =======================================================================
643 // function : PushAspectLine
644 // purpose  :
645 // =======================================================================
646 static void PushAspectLine (const Handle(OpenGl_Context)&       theCtx,
647                             const Handle(OpenGl_ShaderProgram)& theProgram,
648                             const OpenGl_AspectLine*            theAspect)
649 {
650   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),   TOff);
651   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
652
653   const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
654                               theAspect->Color().rgb[1],
655                               theAspect->Color().rgb[2],
656                               theAspect->Color().rgb[3]);
657   OpenGl_Vec4 aParams[5];
658   aParams[0] = THE_COLOR_BLACK_VEC4;
659   aParams[1] = THE_COLOR_BLACK_VEC4;
660   aParams[2] = aDiffuse;
661   aParams[3] = THE_COLOR_BLACK_VEC4;
662   aParams[4].x() = 0.0f; // shininess
663   aParams[4].y() = 0.0f; // transparency
664   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
665                           5, aParams);
666 }
667
668 // =======================================================================
669 // function : PushAspectText
670 // purpose  :
671 // =======================================================================
672 static void PushAspectText (const Handle(OpenGl_Context)&       theCtx,
673                             const Handle(OpenGl_ShaderProgram)& theProgram,
674                             const OpenGl_AspectText*            theAspect)
675 {
676   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),   TOn);
677   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
678   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),   0 /* GL_TEXTURE0 */);
679
680   OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
681                         theAspect->Color().rgb[1],
682                         theAspect->Color().rgb[2],
683                         theAspect->Color().rgb[3]);
684   if (theAspect->DisplayType() == Aspect_TODT_DEKALE
685    || theAspect->DisplayType() == Aspect_TODT_SUBTITLE)
686   {
687     aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0],
688                             theAspect->SubtitleColor().rgb[1],
689                             theAspect->SubtitleColor().rgb[2],
690                             theAspect->SubtitleColor().rgb[3]);
691   }
692
693   OpenGl_Vec4 aParams[5];
694   aParams[0] = THE_COLOR_BLACK_VEC4;
695   aParams[1] = THE_COLOR_BLACK_VEC4;
696   aParams[2] = aDiffuse;
697   aParams[3] = THE_COLOR_BLACK_VEC4;
698   aParams[4].x() = 0.0f; // shininess
699   aParams[4].y() = 0.0f; // transparency
700   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
701                           5, aParams);
702 }
703
704 // =======================================================================
705 // function : PushAspectMarker
706 // purpose  :
707 // =======================================================================
708 static void PushAspectMarker (const Handle(OpenGl_Context)&       theCtx,
709                               const Handle(OpenGl_ShaderProgram)& theProgram,
710                               const OpenGl_AspectMarker*          theAspect)
711 {
712   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),   TOn);
713   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
714   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),   0 /* GL_TEXTURE0 */);
715
716   const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
717                               theAspect->Color().rgb[1],
718                               theAspect->Color().rgb[2],
719                               theAspect->Color().rgb[3]);
720   OpenGl_Vec4 aParams[5];
721   aParams[0] = THE_COLOR_BLACK_VEC4;
722   aParams[1] = THE_COLOR_BLACK_VEC4;
723   aParams[2] = aDiffuse;
724   aParams[3] = THE_COLOR_BLACK_VEC4;
725   aParams[4].x() = 0.0f; // shininess
726   aParams[4].y() = 0.0f; // transparency
727   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
728                           5, aParams);
729 }
730
731 }; // nameless namespace
732
733 // =======================================================================
734 // function : PushMaterialState
735 // purpose  : Pushes current state of OCCT material to the program
736 // =======================================================================
737 void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
738 {
739   if (!myMaterialStates.IsBound (theProgram))
740   {
741     return;
742   }
743
744   const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram);
745   if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE))
746   {
747     return;
748   }
749
750   if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectFace))
751   {
752     PushAspectFace   (myContext, theProgram, dynamic_cast<const OpenGl_AspectFace*> (aState.Aspect()));
753   }
754   else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectLine))
755   {
756     PushAspectLine   (myContext, theProgram, dynamic_cast<const OpenGl_AspectLine*> (aState.Aspect()));
757   }
758   else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectText))
759   {
760     PushAspectText   (myContext, theProgram, dynamic_cast<const OpenGl_AspectText*> (aState.Aspect()));
761   }
762   else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectMarker))
763   {
764     PushAspectMarker (myContext, theProgram, dynamic_cast<const OpenGl_AspectMarker*> (aState.Aspect()));
765   }
766
767   theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index());
768 }
769
770 // =======================================================================
771 // function : PushWorldViewState
772 // purpose  : Pushes state of OCCT graphics parameters to the program
773 // =======================================================================
774 void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
775 {
776   PushClippingState    (theProgram);
777   PushMaterialState    (theProgram);
778   PushWorldViewState   (theProgram);
779   PushModelWorldState  (theProgram);
780   PushProjectionState  (theProgram);  
781   PushLightSourceState (theProgram);
782 }