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