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