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