Increment version of OCCT up to 6.7.3
[occt.git] / src / OpenGl / OpenGl_ShaderManager.cxx
CommitLineData
30f0ad28 1// Created on: 2013-09-26
2// Created by: Denis BOGOLEPOV
d5f74e42 3// Copyright (c) 2013-2014 OPEN CASCADE SAS
30f0ad28 4//
973c2be1 5// This file is part of Open CASCADE Technology software library.
30f0ad28 6//
d5f74e42 7// This library is free software; you can redistribute it and/or modify it under
8// the terms of the GNU Lesser General Public License version 2.1 as published
973c2be1 9// by the Free Software Foundation, with special exception defined in the file
10// OCCT_LGPL_EXCEPTION.txt. Consult the file LICENSE_LGPL_21.txt included in OCCT
11// distribution for complete text of the license and disclaimer of any warranty.
30f0ad28 12//
973c2be1 13// Alternatively, this file may be used under the terms of Open CASCADE
14// commercial license or contractual agreement.
30f0ad28 15
16#include <typeinfo>
17
18#include <OpenGl_AspectFace.hxx>
19#include <OpenGl_AspectLine.hxx>
20#include <OpenGl_AspectMarker.hxx>
21#include <OpenGl_AspectText.hxx>
22#include <OpenGl_Clipping.hxx>
23#include <OpenGl_Context.hxx>
24#include <OpenGl_ShaderManager.hxx>
25#include <OpenGl_ShaderProgram.hxx>
0adbd30f 26#include <OpenGl_Workspace.hxx>
30f0ad28 27
28IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderManager, Standard_Transient)
29IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient)
30
31// =======================================================================
32// function : OpenGl_ShaderManager
33// purpose : Creates new empty shader manager
34// =======================================================================
35OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
e6804ff7 36: myContext (theContext),
37 myIsPP (Standard_False),
38 myLastView (NULL)
30f0ad28 39{
40 //
41}
42
43// =======================================================================
44// function : ~OpenGl_ShaderManager
45// purpose : Releases resources of shader manager
46// =======================================================================
47OpenGl_ShaderManager::~OpenGl_ShaderManager()
48{
49 myProgramList.Clear();
50}
51
52// =======================================================================
53// function : Create
54// purpose : Creates new shader program
55// =======================================================================
392ac980 56void OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
57 TCollection_AsciiString& theShareKey,
58 Handle(OpenGl_ShaderProgram)& theProgram)
30f0ad28 59{
392ac980 60 theProgram.Nullify();
61 if (theProxy.IsNull())
30f0ad28 62 {
392ac980 63 return;
30f0ad28 64 }
392ac980 65
66 theShareKey = theProxy->GetId();
67 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
68 {
05dd08ce 69 if (theProgram->Share())
70 {
71 myProgramList.Append (theProgram);
72 }
392ac980 73 return;
74 }
75
76 theProgram = new OpenGl_ShaderProgram (theProxy);
77 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
30f0ad28 78 {
392ac980 79 theProgram->Release (myContext);
80 theShareKey.Clear();
81 theProgram.Nullify();
82 return;
30f0ad28 83 }
30f0ad28 84
392ac980 85 myProgramList.Append (theProgram);
86 myContext->ShareResource (theShareKey, theProgram);
30f0ad28 87}
88
89// =======================================================================
90// function : Unregister
91// purpose : Removes specified shader program from the manager
92// =======================================================================
392ac980 93void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
94 Handle(OpenGl_ShaderProgram)& theProgram)
30f0ad28 95{
96 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
97 {
98 if (anIt.Value() == theProgram)
99 {
392ac980 100 if (!theProgram->UnShare())
101 {
102 theShareKey.Clear();
103 theProgram.Nullify();
104 return;
105 }
106
30f0ad28 107 myProgramList.Remove (anIt);
392ac980 108 myMaterialStates.UnBind (theProgram);
30f0ad28 109 break;
110 }
111 }
112
113 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
114 if (anID.IsEmpty())
115 {
116 myContext->DelayedRelease (theProgram);
117 theProgram.Nullify();
118 }
119 else
120 {
121 theProgram.Nullify();
05dd08ce 122 myContext->ReleaseResource (anID, Standard_True);
30f0ad28 123 }
124}
125
126// =======================================================================
127// function : ShaderPrograms
128// purpose : Returns list of registered shader programs
129// =======================================================================
130const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
131{
132 return myProgramList;
133}
134
135// =======================================================================
136// function : Empty
137// purpose : Returns true if no program objects are attached
138// =======================================================================
139Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
140{
141 return myProgramList.IsEmpty();
142}
143
144// =======================================================================
145// function : UpdateLightSourceStateTo
146// purpose : Updates state of OCCT light sources
147// =======================================================================
148void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights)
149{
150 myLightSourceState.Set (theLights);
151 myLightSourceState.Update();
152}
153
154// =======================================================================
155// function : SetProjectionState
156// purpose : Sets new state of OCCT projection transform
157// =======================================================================
b5ac8292 158void OpenGl_ShaderManager::UpdateProjectionStateTo (const Tmatrix3* theProjectionMatrix)
30f0ad28 159{
160 myProjectionState.Set (theProjectionMatrix);
161 myProjectionState.Update();
162}
163
164// =======================================================================
165// function : SetModelWorldState
166// purpose : Sets new state of OCCT model-world transform
167// =======================================================================
b5ac8292 168void OpenGl_ShaderManager::UpdateModelWorldStateTo (const Tmatrix3* theModelWorldMatrix)
30f0ad28 169{
170 myModelWorldState.Set (theModelWorldMatrix);
171 myModelWorldState.Update();
172}
173
174// =======================================================================
175// function : SetWorldViewState
176// purpose : Sets new state of OCCT world-view transform
177// =======================================================================
b5ac8292 178void OpenGl_ShaderManager::UpdateWorldViewStateTo (const Tmatrix3* theWorldViewMatrix)
30f0ad28 179{
180 myWorldViewState.Set (theWorldViewMatrix);
181 myWorldViewState.Update();
182}
183
184// =======================================================================
185// function : RevertProjectionStateTo
186// purpose : Reverts state of OCCT projection transform
187// =======================================================================
b5ac8292 188void OpenGl_ShaderManager::RevertProjectionStateTo (const Tmatrix3* theProjectionMatrix)
30f0ad28 189{
190 myProjectionState.Set (theProjectionMatrix);
191 myProjectionState.Revert();
192}
193
194// =======================================================================
195// function : RevertModelWorldStateTo
196// purpose : Reverts state of OCCT model-world transform
197// =======================================================================
b5ac8292 198void OpenGl_ShaderManager::RevertModelWorldStateTo (const Tmatrix3* theModelWorldMatrix)
30f0ad28 199{
200 myModelWorldState.Set (theModelWorldMatrix);
201 myModelWorldState.Revert();
202}
203
204// =======================================================================
205// function : RevertWorldViewStateTo
206// purpose : Reverts state of OCCT world-view transform
207// =======================================================================
b5ac8292 208void OpenGl_ShaderManager::RevertWorldViewStateTo (const Tmatrix3* theWorldViewMatrix)
30f0ad28 209{
210 myWorldViewState.Set (theWorldViewMatrix);
211 myWorldViewState.Revert();
212}
213
214// =======================================================================
215// function : LightSourceState
216// purpose : Returns current state of OCCT light sources
217// =======================================================================
218const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const
219{
220 return myLightSourceState;
221}
222
223// =======================================================================
224// function : ProjectionState
225// purpose : Returns current state of OCCT projection transform
226// =======================================================================
227const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const
228{
229 return myProjectionState;
230}
231
232// =======================================================================
233// function : ModelWorldState
234// purpose : Returns current state of OCCT model-world transform
235// =======================================================================
236const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const
237{
238 return myModelWorldState;
239}
240
241// =======================================================================
242// function : WorldViewState
243// purpose : Returns current state of OCCT world-view transform
244// =======================================================================
245const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const
246{
247 return myWorldViewState;
248}
249
4fe9ad57 250//! Packed properties of light source
251class OpenGl_ShaderLightParameters
252{
253public:
254
255 OpenGl_Vec4 Color;
256 OpenGl_Vec4 Position;
257 OpenGl_Vec4 Direction;
258 OpenGl_Vec4 Parameters;
259
260 //! Returns packed (serialized) representation of light source properties
0adbd30f 261 const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
01eaf654 262 static Standard_Integer NbOfVec4() { return 4; }
4fe9ad57 263
264};
265
266//! Packed light source type information
267class OpenGl_ShaderLightType
268{
269public:
270
271 Standard_Integer Type;
272 Standard_Integer IsHeadlight;
273
274 //! Returns packed (serialized) representation of light source type
0adbd30f 275 const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
01eaf654 276 static Standard_Integer NbOfVec2i() { return 1; }
4fe9ad57 277
278};
279
30f0ad28 280// =======================================================================
281// function : PushLightSourceState
282// purpose : Pushes state of OCCT light sources to the program
283// =======================================================================
284void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
285{
12381341 286 if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)
287 || !theProgram->IsValid())
30f0ad28 288 {
289 return;
290 }
30f0ad28 291
01eaf654 292 OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[OpenGLMaxLights];
293 for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt)
294 {
295 aLightTypeArray[aLightIt].Type = -1;
296 }
297
12381341 298 const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights);
299 if (aLightsDefNb < 1)
300 {
30f0ad28 301 theProgram->SetUniform (myContext,
12381341 302 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
303 0);
30f0ad28 304 theProgram->SetUniform (myContext,
12381341 305 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
306 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
01eaf654 307 theProgram->SetUniform (myContext,
308 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
309 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
310 aLightTypeArray[0].Packed());
12381341 311 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
0c4033b4 312 delete[] aLightTypeArray;
12381341 313 return;
314 }
30f0ad28 315
4fe9ad57 316 OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb];
30f0ad28 317
12381341 318 OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
319 Standard_Integer aLightsNb = 0;
320 for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next())
321 {
322 const OpenGl_Light& aLight = anIter.Value();
323 if (aLight.Type == Visual3d_TOLS_AMBIENT)
30f0ad28 324 {
12381341 325 anAmbient += aLight.Color;
326 continue;
327 }
328 else if (aLightsNb >= OpenGLMaxLights)
329 {
330 continue;
331 }
30f0ad28 332
4fe9ad57 333 OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb];
334 aLightType.Type = aLight.Type;
335 aLightType.IsHeadlight = aLight.IsHeadlight;
30f0ad28 336
4fe9ad57 337 OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb];
338 aLightParams.Color = aLight.Color;
339 aLightParams.Position = aLight.Type == Visual3d_TOLS_DIRECTIONAL
340 ? -aLight.Direction
341 : aLight.Position;
12381341 342 if (aLight.Type == Visual3d_TOLS_SPOT)
343 {
4fe9ad57 344 aLightParams.Direction = aLight.Direction;
30f0ad28 345 }
4fe9ad57 346 aLightParams.Parameters = aLight.Params;
12381341 347 ++aLightsNb;
348 }
30f0ad28 349
12381341 350 theProgram->SetUniform (myContext,
351 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
352 aLightsNb);
353 theProgram->SetUniform (myContext,
354 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
355 anAmbient);
01eaf654 356 theProgram->SetUniform (myContext,
357 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
358 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
359 aLightTypeArray[0].Packed());
12381341 360 if (aLightsNb > 0)
361 {
4fe9ad57 362 theProgram->SetUniform (myContext,
4fe9ad57 363 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
364 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
365 aLightParamsArray[0].Packed());
30f0ad28 366 }
4fe9ad57 367 delete[] aLightParamsArray;
368 delete[] aLightTypeArray;
30f0ad28 369
370 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
371}
372
373// =======================================================================
374// function : PushProjectionState
375// purpose : Pushes state of OCCT projection transform to the program
376// =======================================================================
377void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
378{
379 if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE))
380 {
381 return;
382 }
383
384 theProgram->SetUniform (myContext,
385 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
386 myProjectionState.ProjectionMatrix());
387
388 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
389 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
390 {
391 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
392 }
393
394 theProgram->SetUniform (myContext,
395 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
396 myProjectionState.ProjectionMatrix(), true);
397
398 aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
399 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
400 {
401 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
402 }
403
404 theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
405}
406
407// =======================================================================
408// function : PushModelWorldState
409// purpose : Pushes state of OCCT model-world transform to the program
410// =======================================================================
411void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
412{
413 if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
414 {
415 return;
416 }
417
418 theProgram->SetUniform (myContext,
419 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
420 myModelWorldState.ModelWorldMatrix());
421
422 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
423 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
424 {
425 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
426 }
427
428 theProgram->SetUniform (myContext,
429 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
430 myModelWorldState.ModelWorldMatrix(), true);
431
432 aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
433 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
434 {
435 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
436 }
437
438 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
439}
440
441// =======================================================================
442// function : PushWorldViewState
443// purpose : Pushes state of OCCT world-view transform to the program
444// =======================================================================
445void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
446{
447 if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
448 {
449 return;
450 }
451
452 theProgram->SetUniform (myContext,
453 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
454 myWorldViewState.WorldViewMatrix());
455
456 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
457 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
458 {
459 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
460 }
461
462 theProgram->SetUniform (myContext,
463 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
464 myWorldViewState.WorldViewMatrix(), true);
465
466 aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
467 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
468 {
469 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
470 }
471
472 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
473}
474
475// =======================================================================
476// function : UpdateClippingState
477// purpose : Updates state of OCCT clipping planes
478// =======================================================================
479void OpenGl_ShaderManager::UpdateClippingState()
480{
481 myClippingState.Update();
482}
483
484// =======================================================================
485// function : RevertClippingState
486// purpose : Reverts state of OCCT clipping planes
487// =======================================================================
488void OpenGl_ShaderManager::RevertClippingState()
489{
490 myClippingState.Revert();
491}
492
493// =======================================================================
494// function : PushClippingState
495// purpose : Pushes state of OCCT clipping planes to the program
496// =======================================================================
497void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
498{
499 if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
500 {
501 return;
502 }
503
12381341 504 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
505 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
506 const GLint aLocSpaces = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_SPACES);
507 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION
508 && aLocSpaces == OpenGl_ShaderProgram::INVALID_LOCATION)
509 {
510 return;
511 }
512
5495fa7e 513 GLint aPlanesNb = 0;
51b10cd4 514 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
12381341 515 anIter.More(); anIter.Next())
30f0ad28 516 {
517 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
518 if (!myContext->Clipping().IsEnabled (aPlane))
519 {
520 continue;
521 }
522
12381341 523 ++aPlanesNb;
524 }
525 if (aPlanesNb < 1)
526 {
527 return;
528 }
529
5495fa7e 530 const Standard_Size MAX_CLIP_PLANES = 8;
531 OpenGl_Vec4* anEquations = new OpenGl_Vec4[MAX_CLIP_PLANES];
532 GLint* aSpaces = new GLint [MAX_CLIP_PLANES];
12381341 533 GLuint aPlaneId = 0;
51b10cd4 534 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
12381341 535 anIter.More(); anIter.Next())
536 {
537 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
538 if (!myContext->Clipping().IsEnabled (aPlane))
30f0ad28 539 {
12381341 540 continue;
30f0ad28 541 }
542
12381341 543 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
544 anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(),
545 (float) anEquation.y(),
546 (float) anEquation.z(),
547 (float) anEquation.w());
548 aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane);
549 ++aPlaneId;
30f0ad28 550 }
5495fa7e 551
552 theProgram->SetUniform (myContext,
553 theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT),
554 aPlanesNb);
555 theProgram->SetUniform (myContext, aLocEquations, MAX_CLIP_PLANES, anEquations);
556 theProgram->SetUniform (myContext, aLocSpaces, MAX_CLIP_PLANES, aSpaces);
4fe9ad57 557
12381341 558 delete[] anEquations;
559 delete[] aSpaces;
30f0ad28 560}
561
562// =======================================================================
563// function : UpdateMaterialStateTo
564// purpose : Updates state of OCCT material for specified program
565// =======================================================================
566void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram,
567 const OpenGl_Element* theAspect)
568{
569 if (myMaterialStates.IsBound (theProgram))
570 {
571 myMaterialStates.ChangeFind (theProgram).Set (theAspect);
572 }
573 else
574 {
575 myMaterialStates.Bind (theProgram, OpenGl_MaterialState (theAspect));
576 }
577
578 myMaterialStates.ChangeFind (theProgram).Update();
579}
580
581// =======================================================================
582// function : ResetMaterialStates
583// purpose : Resets state of OCCT material for all programs
584// =======================================================================
585void OpenGl_ShaderManager::ResetMaterialStates()
586{
587 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
588 {
589 anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0);
590 }
591}
592
593// =======================================================================
594// function : MaterialState
595// purpose : Returns state of OCCT material for specified program
596// =======================================================================
597const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
598{
599 if (!myMaterialStates.IsBound (theProgram))
600 return NULL;
601
602 return &myMaterialStates.Find (theProgram);
603}
604
605namespace
606{
607
608static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f);
609
610// =======================================================================
611// function : PushAspectFace
612// purpose :
613// =======================================================================
614static void PushAspectFace (const Handle(OpenGl_Context)& theCtx,
615 const Handle(OpenGl_ShaderProgram)& theProgram,
616 const OpenGl_AspectFace* theAspect)
617{
618 theProgram->SetUniform (theCtx,
619 theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
620 theAspect->DoTextureMap());
30f0ad28 621 theProgram->SetUniform (theCtx,
622 theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),
623 0 /* GL_TEXTURE0 */);
30f0ad28 624 theProgram->SetUniform (theCtx,
625 theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
626 theAspect->DistinguishingMode());
627
0adbd30f 628 OpenGl_Material aParams;
12381341 629 for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
30f0ad28 630 {
12381341 631 const GLint aLoc = theProgram->GetStateLocation (anIndex == 0
632 ? OpenGl_OCCT_FRONT_MATERIAL
633 : OpenGl_OCCT_BACK_MATERIAL);
634 if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
30f0ad28 635 {
12381341 636 continue;
30f0ad28 637 }
30f0ad28 638
0adbd30f 639 aParams.Init (anIndex == 0 ? theAspect->IntFront() : theAspect->IntBack());
640 theProgram->SetUniform (theCtx, aLoc, OpenGl_Material::NbOfVec4(),
641 aParams.Packed());
30f0ad28 642 }
643}
644
645// =======================================================================
646// function : PushAspectLine
647// purpose :
648// =======================================================================
649static void PushAspectLine (const Handle(OpenGl_Context)& theCtx,
650 const Handle(OpenGl_ShaderProgram)& theProgram,
651 const OpenGl_AspectLine* theAspect)
652{
653 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOff);
654 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
655
656 const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
657 theAspect->Color().rgb[1],
658 theAspect->Color().rgb[2],
659 theAspect->Color().rgb[3]);
12381341 660 OpenGl_Vec4 aParams[5];
661 aParams[0] = THE_COLOR_BLACK_VEC4;
662 aParams[1] = THE_COLOR_BLACK_VEC4;
663 aParams[2] = aDiffuse;
664 aParams[3] = THE_COLOR_BLACK_VEC4;
665 aParams[4].x() = 0.0f; // shininess
666 aParams[4].y() = 0.0f; // transparency
4fe9ad57 667 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
668 5, aParams);
30f0ad28 669}
670
671// =======================================================================
672// function : PushAspectText
673// purpose :
674// =======================================================================
675static void PushAspectText (const Handle(OpenGl_Context)& theCtx,
676 const Handle(OpenGl_ShaderProgram)& theProgram,
677 const OpenGl_AspectText* theAspect)
678{
679 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn);
680 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
681 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */);
682
683 OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
684 theAspect->Color().rgb[1],
685 theAspect->Color().rgb[2],
686 theAspect->Color().rgb[3]);
687 if (theAspect->DisplayType() == Aspect_TODT_DEKALE
688 || theAspect->DisplayType() == Aspect_TODT_SUBTITLE)
689 {
690 aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0],
691 theAspect->SubtitleColor().rgb[1],
692 theAspect->SubtitleColor().rgb[2],
693 theAspect->SubtitleColor().rgb[3]);
694 }
695
12381341 696 OpenGl_Vec4 aParams[5];
697 aParams[0] = THE_COLOR_BLACK_VEC4;
698 aParams[1] = THE_COLOR_BLACK_VEC4;
699 aParams[2] = aDiffuse;
700 aParams[3] = THE_COLOR_BLACK_VEC4;
701 aParams[4].x() = 0.0f; // shininess
702 aParams[4].y() = 0.0f; // transparency
4fe9ad57 703 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
704 5, aParams);
30f0ad28 705}
706
707// =======================================================================
708// function : PushAspectMarker
709// purpose :
710// =======================================================================
711static void PushAspectMarker (const Handle(OpenGl_Context)& theCtx,
712 const Handle(OpenGl_ShaderProgram)& theProgram,
713 const OpenGl_AspectMarker* theAspect)
714{
715 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn);
716 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
717 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */);
718
719 const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
720 theAspect->Color().rgb[1],
721 theAspect->Color().rgb[2],
722 theAspect->Color().rgb[3]);
12381341 723 OpenGl_Vec4 aParams[5];
724 aParams[0] = THE_COLOR_BLACK_VEC4;
725 aParams[1] = THE_COLOR_BLACK_VEC4;
726 aParams[2] = aDiffuse;
727 aParams[3] = THE_COLOR_BLACK_VEC4;
728 aParams[4].x() = 0.0f; // shininess
729 aParams[4].y() = 0.0f; // transparency
4fe9ad57 730 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
731 5, aParams);
30f0ad28 732}
733
734}; // nameless namespace
735
736// =======================================================================
737// function : PushMaterialState
738// purpose : Pushes current state of OCCT material to the program
739// =======================================================================
740void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
741{
742 if (!myMaterialStates.IsBound (theProgram))
743 {
744 return;
745 }
746
747 const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram);
748 if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE))
749 {
750 return;
751 }
752
753 if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectFace))
754 {
755 PushAspectFace (myContext, theProgram, dynamic_cast<const OpenGl_AspectFace*> (aState.Aspect()));
756 }
757 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectLine))
758 {
759 PushAspectLine (myContext, theProgram, dynamic_cast<const OpenGl_AspectLine*> (aState.Aspect()));
760 }
761 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectText))
762 {
763 PushAspectText (myContext, theProgram, dynamic_cast<const OpenGl_AspectText*> (aState.Aspect()));
764 }
765 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectMarker))
766 {
767 PushAspectMarker (myContext, theProgram, dynamic_cast<const OpenGl_AspectMarker*> (aState.Aspect()));
768 }
769
770 theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index());
771}
772
773// =======================================================================
774// function : PushWorldViewState
775// purpose : Pushes state of OCCT graphics parameters to the program
776// =======================================================================
777void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
778{
779 PushClippingState (theProgram);
780 PushMaterialState (theProgram);
781 PushWorldViewState (theProgram);
782 PushModelWorldState (theProgram);
783 PushProjectionState (theProgram);
784 PushLightSourceState (theProgram);
12381341 785}