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