0024250: TKOpenGl - per-pixel lighting using GLSL program (Phong shading)
[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// =======================================================================
392ac980 58void OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
59 TCollection_AsciiString& theShareKey,
60 Handle(OpenGl_ShaderProgram)& theProgram)
30f0ad28 61{
392ac980 62 theProgram.Nullify();
63 if (theProxy.IsNull())
30f0ad28 64 {
392ac980 65 return;
30f0ad28 66 }
392ac980 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()))
30f0ad28 77 {
392ac980 78 theProgram->Release (myContext);
79 theShareKey.Clear();
80 theProgram.Nullify();
81 return;
30f0ad28 82 }
30f0ad28 83
392ac980 84 myProgramList.Append (theProgram);
85 myContext->ShareResource (theShareKey, theProgram);
30f0ad28 86}
87
88// =======================================================================
89// function : Unregister
90// purpose : Removes specified shader program from the manager
91// =======================================================================
392ac980 92void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
93 Handle(OpenGl_ShaderProgram)& theProgram)
30f0ad28 94{
95 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
96 {
97 if (anIt.Value() == theProgram)
98 {
392ac980 99 if (!theProgram->UnShare())
100 {
101 theShareKey.Clear();
102 theProgram.Nullify();
103 return;
104 }
105
30f0ad28 106 myProgramList.Remove (anIt);
392ac980 107 myMaterialStates.UnBind (theProgram);
30f0ad28 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// =======================================================================
129const 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// =======================================================================
138Standard_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// =======================================================================
147void 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// =======================================================================
157void 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// =======================================================================
167void 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// =======================================================================
177void 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// =======================================================================
187void 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// =======================================================================
197void 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// =======================================================================
207void 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// =======================================================================
217const 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// =======================================================================
226const 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// =======================================================================
235const 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// =======================================================================
244const 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// =======================================================================
253void 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// =======================================================================
345void 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// =======================================================================
379void 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// =======================================================================
413void 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// =======================================================================
447void OpenGl_ShaderManager::UpdateClippingState()
448{
449 myClippingState.Update();
450}
451
452// =======================================================================
453// function : RevertClippingState
454// purpose : Reverts state of OCCT clipping planes
455// =======================================================================
456void 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// =======================================================================
465void 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// =======================================================================
504void 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// =======================================================================
523void 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// =======================================================================
535const 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
543namespace
544{
545
546static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f);
547
548// =======================================================================
549// function : PushAspectFace
550// purpose :
551// =======================================================================
552static 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// =======================================================================
625static 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// =======================================================================
657static 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// =======================================================================
699static 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// =======================================================================
735void 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// =======================================================================
772void 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}