0024309: TKOpenGl - Delay release of GLSL resources
[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 // =======================================================================
253 // function : PushLightSourceState
254 // purpose  : Pushes state of OCCT light sources to the program
255 // =======================================================================
256 void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
257 {
258   if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE))
259   {
260     return;
261   }
262   
263   theProgram->SetUniform (myContext, theProgram->GetStateLocation (
264     OpenGl_OCC_LIGHT_SOURCE_COUNT), myLightSourceState.LightSources()->Size());
265
266   OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources());
267   for (unsigned int anIndex = 0; anIter.More(); anIter.Next())
268   {
269     if (anIndex >= OpenGLMaxLights)
270     {
271       break;
272     }
273
274     const OpenGl_Light& aLight = anIter.Value();
275     if (aLight.type == TLightAmbient)
276     {
277       OpenGl_Vec3 anAmbient (aLight.col.rgb[0],
278                              aLight.col.rgb[1],
279                              aLight.col.rgb[2]);
280
281       theProgram->SetUniform (myContext,
282         theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_AMBIENT + anIndex), anAmbient);
283
284       anIter.Next();
285       if (!anIter.More())
286       {
287         theProgram->SetUniform (myContext,
288           theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_TYPE + anIndex), int (aLight.type));
289         break;
290       }
291     }
292
293     OpenGl_Vec3 aDiffuse (aLight.col.rgb[0],
294                           aLight.col.rgb[1],
295                           aLight.col.rgb[2]);
296
297     OpenGl_Vec3 aPosition (aLight.type == TLightDirectional ? -aLight.dir[0] : aLight.pos[0],
298                            aLight.type == TLightDirectional ? -aLight.dir[1] : aLight.pos[1],
299                            aLight.type == TLightDirectional ? -aLight.dir[2] : aLight.pos[2]);
300
301     theProgram->SetUniform (myContext,
302       theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_TYPE + anIndex), int (aLight.type));
303
304     theProgram->SetUniform (myContext,
305       theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_HEAD + anIndex), aLight.HeadLight);
306
307     theProgram->SetUniform (myContext,
308       theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_DIFFUSE + anIndex), aDiffuse);
309
310     theProgram->SetUniform (myContext,
311       theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_SPECULAR + anIndex), aDiffuse);
312
313     theProgram->SetUniform (myContext,
314       theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_POSITION + anIndex), aPosition);
315
316     theProgram->SetUniform (myContext,
317       theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_CONST_ATTENUATION + anIndex), aLight.atten[0]);
318
319     theProgram->SetUniform (myContext,
320       theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_LINEAR_ATTENUATION + anIndex), aLight.atten[1]);
321
322     if (aLight.type == TLightSpot)
323     {
324       OpenGl_Vec3 aDirection (aLight.dir[0],
325                               aLight.dir[1],
326                               aLight.dir[2]);
327
328       theProgram->SetUniform (myContext,
329         theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_SPOT_CUTOFF + anIndex), aLight.angle);
330
331       theProgram->SetUniform (myContext,
332         theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_SPOT_EXPONENT + anIndex), aLight.shine);
333
334       theProgram->SetUniform (myContext,
335         theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_0_SPOT_DIRECTION + anIndex), aDirection);
336     }
337
338     ++anIndex;
339   }
340
341   theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
342 }
343
344 // =======================================================================
345 // function : PushProjectionState
346 // purpose  : Pushes state of OCCT projection transform to the program
347 // =======================================================================
348 void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
349 {
350   if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE))
351   {
352     return;
353   }
354
355   theProgram->SetUniform (myContext,
356                           theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
357                           myProjectionState.ProjectionMatrix());
358
359   GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
360   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
361   {
362     theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
363   }
364
365   theProgram->SetUniform (myContext,
366                           theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
367                           myProjectionState.ProjectionMatrix(), true);
368
369   aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
370   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
371   {
372     theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
373   }
374
375   theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
376 }
377
378 // =======================================================================
379 // function : PushModelWorldState
380 // purpose  : Pushes state of OCCT model-world transform to the program
381 // =======================================================================
382 void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
383 {
384   if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
385   {
386     return;
387   }
388
389   theProgram->SetUniform (myContext,
390                           theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
391                           myModelWorldState.ModelWorldMatrix());
392
393   GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
394   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
395   {
396     theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
397   }
398
399   theProgram->SetUniform (myContext,
400                           theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
401                           myModelWorldState.ModelWorldMatrix(), true);
402
403   aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
404   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
405   {
406     theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
407   }
408
409   theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
410 }
411
412 // =======================================================================
413 // function : PushWorldViewState
414 // purpose  : Pushes state of OCCT world-view transform to the program
415 // =======================================================================
416 void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
417 {
418   if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
419   {
420     return;
421   }
422
423   theProgram->SetUniform (myContext,
424                           theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
425                           myWorldViewState.WorldViewMatrix());
426
427   GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
428   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
429   {
430     theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
431   }
432
433   theProgram->SetUniform (myContext,
434                           theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
435                           myWorldViewState.WorldViewMatrix(), true);
436
437   aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
438   if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
439   {
440     theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
441   }
442
443   theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
444 }
445
446 // =======================================================================
447 // function : UpdateClippingState
448 // purpose  : Updates state of OCCT clipping planes
449 // =======================================================================
450 void OpenGl_ShaderManager::UpdateClippingState()
451 {
452   myClippingState.Update();
453 }
454
455 // =======================================================================
456 // function : RevertClippingState
457 // purpose  : Reverts state of OCCT clipping planes
458 // =======================================================================
459 void OpenGl_ShaderManager::RevertClippingState()
460 {
461   myClippingState.Revert();
462 }
463
464 // =======================================================================
465 // function : PushClippingState
466 // purpose  : Pushes state of OCCT clipping planes to the program
467 // =======================================================================
468 void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
469 {
470   if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
471   {
472     return;
473   }
474
475   Graphic3d_SetOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
476   for (GLuint anIndex = 0; anIter.More(); anIter.Next())
477   {
478     const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
479     if (!myContext->Clipping().IsEnabled (aPlane))
480     {
481       continue;
482     }
483
484     GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_0_EQUATION + anIndex);
485     if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
486     {
487       const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
488       theProgram->SetUniform (myContext, aLocation, OpenGl_Vec4 ((float) anEquation.x(),
489                                                                  (float) anEquation.y(),
490                                                                  (float) anEquation.z(),
491                                                                  (float) anEquation.w()));
492     }
493
494     theProgram->SetUniform (myContext,
495                             theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_0_SPACE + anIndex),
496                             myContext->Clipping().GetEquationSpace (aPlane));
497     ++anIndex;
498   }
499
500   theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
501 }
502
503 // =======================================================================
504 // function : UpdateMaterialStateTo
505 // purpose  : Updates state of OCCT material for specified program
506 // =======================================================================
507 void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram,
508                                                   const OpenGl_Element*               theAspect)
509 {
510   if (myMaterialStates.IsBound (theProgram))
511   {
512     myMaterialStates.ChangeFind (theProgram).Set (theAspect);
513   }
514   else
515   {
516     myMaterialStates.Bind (theProgram, OpenGl_MaterialState (theAspect));
517   }
518
519   myMaterialStates.ChangeFind (theProgram).Update();
520 }
521
522 // =======================================================================
523 // function : ResetMaterialStates
524 // purpose  : Resets state of OCCT material for all programs
525 // =======================================================================
526 void OpenGl_ShaderManager::ResetMaterialStates()
527 {
528   for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
529   {
530     anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0);
531   }
532 }
533
534 // =======================================================================
535 // function : MaterialState
536 // purpose  : Returns state of OCCT material for specified program
537 // =======================================================================
538 const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
539 {
540   if (!myMaterialStates.IsBound (theProgram))
541     return NULL;
542
543   return &myMaterialStates.Find (theProgram);
544 }
545
546 namespace
547 {
548
549 static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f);
550
551 // =======================================================================
552 // function : PushAspectFace
553 // purpose  :
554 // =======================================================================
555 static void PushAspectFace (const Handle(OpenGl_Context)&       theCtx,
556                             const Handle(OpenGl_ShaderProgram)& theProgram,
557                             const OpenGl_AspectFace*            theAspect)
558 {
559   theProgram->SetUniform (theCtx,
560                           theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
561                           theAspect->DoTextureMap());
562
563   theProgram->SetUniform (theCtx,
564                           theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),
565                           0 /* GL_TEXTURE0 */);
566
567   theProgram->SetUniform (theCtx,
568                           theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
569                           theAspect->DistinguishingMode());
570
571   for (int anIndex = 0; anIndex < 2; ++anIndex)
572   {
573     const OPENGL_SURF_PROP& aProperties = (anIndex == 0) ? theAspect->IntFront() : theAspect->IntBack();
574     GLint aLocation = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_AMBIENT + anIndex);
575     if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
576     {
577       OpenGl_Vec4 anAmbient (aProperties.ambcol.rgb[0] * aProperties.amb,
578                              aProperties.ambcol.rgb[1] * aProperties.amb,
579                              aProperties.ambcol.rgb[2] * aProperties.amb,
580                              aProperties.ambcol.rgb[3] * aProperties.amb);
581       theProgram->SetUniform (theCtx, aLocation, anAmbient);
582     }
583
584     aLocation = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE + anIndex);
585     if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
586     {
587       OpenGl_Vec4 aDiffuse (aProperties.difcol.rgb[0] * aProperties.diff,
588                             aProperties.difcol.rgb[1] * aProperties.diff,
589                             aProperties.difcol.rgb[2] * aProperties.diff,
590                             aProperties.difcol.rgb[3] * aProperties.diff);
591       theProgram->SetUniform (theCtx, aLocation, aDiffuse);
592     }
593
594     aLocation = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SPECULAR + anIndex);
595     if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
596     {
597       OpenGl_Vec4 aSpecular (aProperties.speccol.rgb[0] * aProperties.spec,
598                              aProperties.speccol.rgb[1] * aProperties.spec,
599                              aProperties.speccol.rgb[2] * aProperties.spec,
600                              aProperties.speccol.rgb[3] * aProperties.spec);
601       theProgram->SetUniform (theCtx, aLocation, aSpecular);
602     }
603
604     aLocation = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_EMISSION + anIndex);
605     if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
606     {
607       OpenGl_Vec4 anEmission (aProperties.emscol.rgb[0] * aProperties.emsv,
608                               aProperties.emscol.rgb[1] * aProperties.emsv,
609                               aProperties.emscol.rgb[2] * aProperties.emsv,
610                               aProperties.emscol.rgb[3] * aProperties.emsv);
611       theProgram->SetUniform (theCtx, aLocation, anEmission);
612     }
613     
614     theProgram->SetUniform (theCtx,
615                             theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SHININESS + anIndex),
616                             aProperties.shine);
617
618     theProgram->SetUniform (theCtx,
619                             theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY + anIndex),
620                             aProperties.trans);
621   }
622 }
623
624 // =======================================================================
625 // function : PushAspectLine
626 // purpose  :
627 // =======================================================================
628 static void PushAspectLine (const Handle(OpenGl_Context)&       theCtx,
629                             const Handle(OpenGl_ShaderProgram)& theProgram,
630                             const OpenGl_AspectLine*            theAspect)
631 {
632   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),   TOff);
633   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
634
635   const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
636                               theAspect->Color().rgb[1],
637                               theAspect->Color().rgb[2],
638                               theAspect->Color().rgb[3]);
639   theProgram->SetUniform (theCtx,
640                           theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_AMBIENT),
641                           THE_COLOR_BLACK_VEC4);
642   theProgram->SetUniform (theCtx,
643                           theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE),
644                           aDiffuse);
645   theProgram->SetUniform (theCtx,
646                           theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SPECULAR),
647                           THE_COLOR_BLACK_VEC4);
648   theProgram->SetUniform (theCtx,
649                           theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_EMISSION),
650                           THE_COLOR_BLACK_VEC4);
651   theProgram->SetUniform (theCtx,
652                           theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY),
653                           0.0f);
654 }
655
656 // =======================================================================
657 // function : PushAspectText
658 // purpose  :
659 // =======================================================================
660 static void PushAspectText (const Handle(OpenGl_Context)&       theCtx,
661                             const Handle(OpenGl_ShaderProgram)& theProgram,
662                             const OpenGl_AspectText*            theAspect)
663 {
664   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),   TOn);
665   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
666   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),   0 /* GL_TEXTURE0 */);
667
668   OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
669                         theAspect->Color().rgb[1],
670                         theAspect->Color().rgb[2],
671                         theAspect->Color().rgb[3]);
672   if (theAspect->DisplayType() == Aspect_TODT_DEKALE
673    || theAspect->DisplayType() == Aspect_TODT_SUBTITLE)
674   {
675     aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0],
676                             theAspect->SubtitleColor().rgb[1],
677                             theAspect->SubtitleColor().rgb[2],
678                             theAspect->SubtitleColor().rgb[3]);
679   }
680
681   theProgram->SetUniform (theCtx,
682                           theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_AMBIENT),
683                           THE_COLOR_BLACK_VEC4);
684   theProgram->SetUniform (theCtx,
685                           theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE),
686                           aDiffuse);
687   theProgram->SetUniform (theCtx,
688                           theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SPECULAR),
689                           THE_COLOR_BLACK_VEC4);
690   theProgram->SetUniform (theCtx,
691                           theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_EMISSION),
692                           THE_COLOR_BLACK_VEC4);
693   theProgram->SetUniform (theCtx,
694                           theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY),
695                           0.0f);
696 }
697
698 // =======================================================================
699 // function : PushAspectMarker
700 // purpose  :
701 // =======================================================================
702 static void PushAspectMarker (const Handle(OpenGl_Context)&       theCtx,
703                               const Handle(OpenGl_ShaderProgram)& theProgram,
704                               const OpenGl_AspectMarker*          theAspect)
705 {
706   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),   TOn);
707   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
708   theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),   0 /* GL_TEXTURE0 */);
709
710   const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
711                               theAspect->Color().rgb[1],
712                               theAspect->Color().rgb[2],
713                               theAspect->Color().rgb[3]);
714
715   theProgram->SetUniform (theCtx,
716                           theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_AMBIENT),
717                           THE_COLOR_BLACK_VEC4);
718   theProgram->SetUniform (theCtx,
719                           theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_DIFFUSE),
720                           aDiffuse);
721   theProgram->SetUniform (theCtx,
722                           theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_SPECULAR),
723                           THE_COLOR_BLACK_VEC4);
724   theProgram->SetUniform (theCtx,
725                           theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_EMISSION),
726                           THE_COLOR_BLACK_VEC4);
727   theProgram->SetUniform (theCtx,
728                           theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL_TRANSPARENCY),
729                           0.0f);
730 }
731
732 }; // nameless namespace
733
734 // =======================================================================
735 // function : PushMaterialState
736 // purpose  : Pushes current state of OCCT material to the program
737 // =======================================================================
738 void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
739 {
740   if (!myMaterialStates.IsBound (theProgram))
741   {
742     return;
743   }
744
745   const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram);
746   if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE))
747   {
748     return;
749   }
750
751   if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectFace))
752   {
753     PushAspectFace   (myContext, theProgram, dynamic_cast<const OpenGl_AspectFace*> (aState.Aspect()));
754   }
755   else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectLine))
756   {
757     PushAspectLine   (myContext, theProgram, dynamic_cast<const OpenGl_AspectLine*> (aState.Aspect()));
758   }
759   else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectText))
760   {
761     PushAspectText   (myContext, theProgram, dynamic_cast<const OpenGl_AspectText*> (aState.Aspect()));
762   }
763   else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectMarker))
764   {
765     PushAspectMarker (myContext, theProgram, dynamic_cast<const OpenGl_AspectMarker*> (aState.Aspect()));
766   }
767
768   theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index());
769 }
770
771 // =======================================================================
772 // function : PushWorldViewState
773 // purpose  : Pushes state of OCCT graphics parameters to the program
774 // =======================================================================
775 void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
776 {
777   PushClippingState    (theProgram);
778   PushMaterialState    (theProgram);
779   PushWorldViewState   (theProgram);
780   PushModelWorldState  (theProgram);
781   PushProjectionState  (theProgram);  
782   PushLightSourceState (theProgram);
783 }