0024192: Adding support for shaders to OCCT visualization toolkit
[occt.git] / src / OpenGl / OpenGl_ShaderManager.cxx
CommitLineData
30f0ad28 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
31IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderManager, Standard_Transient)
32IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient)
33
34// =======================================================================
35// function : OpenGl_ShaderManager
36// purpose : Creates new empty shader manager
37// =======================================================================
38OpenGl_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// =======================================================================
49OpenGl_ShaderManager::~OpenGl_ShaderManager()
50{
51 myProgramList.Clear();
52}
53
54// =======================================================================
55// function : Create
56// purpose : Creates new shader program
57// =======================================================================
58Handle(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// =======================================================================
80void 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// =======================================================================
108const 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// =======================================================================
117Standard_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// =======================================================================
126void 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// =======================================================================
136void 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// =======================================================================
146void 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// =======================================================================
156void 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// =======================================================================
166void 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// =======================================================================
176void 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// =======================================================================
186void 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// =======================================================================
196const 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// =======================================================================
205const 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// =======================================================================
214const 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// =======================================================================
223const 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// =======================================================================
232void 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// =======================================================================
324void 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// =======================================================================
358void 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// =======================================================================
392void 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// =======================================================================
426void OpenGl_ShaderManager::UpdateClippingState()
427{
428 myClippingState.Update();
429}
430
431// =======================================================================
432// function : RevertClippingState
433// purpose : Reverts state of OCCT clipping planes
434// =======================================================================
435void 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// =======================================================================
444void 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// =======================================================================
483void 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// =======================================================================
502void 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// =======================================================================
514const 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
522namespace
523{
524
525static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f);
526
527// =======================================================================
528// function : PushAspectFace
529// purpose :
530// =======================================================================
531static 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// =======================================================================
604static 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// =======================================================================
636static 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// =======================================================================
678static 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// =======================================================================
714void 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// =======================================================================
751void 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}