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