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