1 // Created on: 2013-09-26
2 // Created by: Denis BOGOLEPOV
3 // Copyright (c) 2013-2014 OPEN CASCADE SAS
5 // This file is part of Open CASCADE Technology software library.
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
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.
13 // Alternatively, this file may be used under the terms of Open CASCADE
14 // commercial license or contractual agreement.
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>
26 #include <OpenGl_Workspace.hxx>
28 IMPLEMENT_STANDARD_HANDLE (OpenGl_SetOfShaderPrograms, Standard_Transient)
29 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_SetOfShaderPrograms, Standard_Transient)
31 IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderManager, Standard_Transient)
32 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient)
39 //! Auxiliary function to transform normal
40 const char THE_FUNC_transformNormal[] =
41 EOL"vec3 transformNormal (in vec3 theNormal)"
43 EOL" vec4 aResult = occWorldViewMatrixInverseTranspose"
44 EOL" * occModelWorldMatrixInverseTranspose"
45 EOL" * vec4 (theNormal, 0.0);"
46 EOL" return normalize (aResult.xyz);"
49 //! Global shader variable for color definition with lighting enabled.
50 const char THE_FUNC_lightDef[] =
51 EOL"vec3 Ambient;" //!< Ambient contribution of light sources
52 EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources
53 EOL"vec3 Specular;"; //!< Specular contribution of light sources
55 //! Function computes contribution of isotropic point light source
56 const char THE_FUNC_pointLight[] =
57 EOL"void pointLight (in int theId,"
58 EOL" in vec3 theNormal,"
59 EOL" in vec3 theView,"
60 EOL" in vec3 thePoint,"
61 EOL" in bool theIsFront)"
63 EOL" vec3 aLight = occLight_Position (theId).xyz;"
64 EOL" if (occLight_IsHeadlight (theId) == 0)"
66 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));"
68 EOL" aLight -= thePoint;"
70 EOL" float aDist = length (aLight);"
71 EOL" aLight = aLight * (1.0 / aDist);"
73 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
74 EOL" + occLight_LinearAttenuation (theId) * aDist);"
76 EOL" vec3 aHalf = normalize (aLight + theView);"
78 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
79 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
80 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
82 EOL" float aSpecl = 0.0;"
83 EOL" if (aNdotL > 0.0)"
85 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
88 EOL"Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
89 EOL"Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
92 //! Function computes contribution of spotlight source
93 const char THE_FUNC_spotLight[] =
94 EOL"void spotLight (in int theId,"
95 EOL" in vec3 theNormal,"
96 EOL" in vec3 theView,"
97 EOL" in vec3 thePoint,"
98 EOL" in bool theIsFront)"
100 EOL" vec3 aLight = occLight_Position (theId).xyz;"
101 EOL" vec3 aSpotDir = occLight_SpotDirection (theId).xyz;"
102 EOL" if (occLight_IsHeadlight (theId) == 0)"
104 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));"
105 EOL" aSpotDir = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aSpotDir, 0.0));"
107 EOL" aLight -= thePoint;"
109 EOL" float aDist = length (aLight);"
110 EOL" aLight = aLight * (1.0 / aDist);"
112 EOL" aSpotDir = normalize (aSpotDir);"
114 EOL" float aCosA = dot (aSpotDir, -aLight);"
115 EOL" if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
120 EOL" float anExponent = occLight_SpotExponent (theId);"
121 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
122 EOL" + occLight_LinearAttenuation (theId) * aDist);"
123 EOL" if (anExponent > 0.0)"
125 EOL" anAtten *= pow (aCosA, anExponent * 128.0);"
128 EOL" vec3 aHalf = normalize (aLight + theView);"
130 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
131 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
132 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
134 EOL" float aSpecl = 0.0;"
135 EOL" if (aNdotL > 0.0)"
137 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
140 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
141 EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
144 //! Function computes contribution of directional light source
145 const char THE_FUNC_directionalLight[] =
146 EOL"void directionalLight (in int theId,"
147 EOL" in vec3 theNormal,"
148 EOL" in vec3 theView,"
149 EOL" in bool theIsFront)"
151 EOL" vec3 aLight = normalize (occLight_Position (theId).xyz);"
152 EOL" if (occLight_IsHeadlight (theId) == 0)"
154 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 0.0));"
157 EOL" vec3 aHalf = normalize (aLight + theView);"
159 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
160 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
161 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
163 EOL" float aSpecl = 0.0;"
164 EOL" if (aNdotL > 0.0)"
166 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
169 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL;"
170 EOL" Specular += occLight_Specular (theId).rgb * aSpecl;"
173 //! Process clipping planes in Fragment Shader.
174 //! Should be added at the beginning of the main() function.
175 const char THE_FRAG_CLIP_PLANES[] =
176 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)"
178 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
179 EOL" int aClipSpace = occClipPlaneSpaces[aPlaneIter];"
180 EOL" if (aClipSpace == OccEquationCoords_World)"
182 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz) + aClipEquation.w < 0.0)"
187 EOL" else if (aClipSpace == OccEquationCoords_View)"
189 EOL" if (dot (aClipEquation.xyz, Position.xyz) + aClipEquation.w < 0.0)"
198 // =======================================================================
199 // function : OpenGl_ShaderManager
200 // purpose : Creates new empty shader manager
201 // =======================================================================
202 OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
203 : myShadingModel (Visual3d_TOM_VERTEX),
204 myContext (theContext),
210 // =======================================================================
211 // function : ~OpenGl_ShaderManager
212 // purpose : Releases resources of shader manager
213 // =======================================================================
214 OpenGl_ShaderManager::~OpenGl_ShaderManager()
216 myProgramList.Clear();
219 // =======================================================================
221 // purpose : Creates new shader program
222 // =======================================================================
223 Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
224 TCollection_AsciiString& theShareKey,
225 Handle(OpenGl_ShaderProgram)& theProgram)
227 theProgram.Nullify();
228 if (theProxy.IsNull())
230 return Standard_False;
233 theShareKey = theProxy->GetId();
234 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
236 if (theProgram->Share())
238 myProgramList.Append (theProgram);
240 return Standard_True;
243 theProgram = new OpenGl_ShaderProgram (theProxy);
244 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
246 theProgram->Release (myContext);
248 theProgram.Nullify();
249 return Standard_False;
252 myProgramList.Append (theProgram);
253 myContext->ShareResource (theShareKey, theProgram);
254 return Standard_True;
257 // =======================================================================
258 // function : Unregister
259 // purpose : Removes specified shader program from the manager
260 // =======================================================================
261 void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
262 Handle(OpenGl_ShaderProgram)& theProgram)
264 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
266 if (anIt.Value() == theProgram)
268 if (!theProgram->UnShare())
271 theProgram.Nullify();
275 myProgramList.Remove (anIt);
276 myMaterialStates.UnBind (theProgram);
281 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
284 myContext->DelayedRelease (theProgram);
285 theProgram.Nullify();
289 theProgram.Nullify();
290 myContext->ReleaseResource (anID, Standard_True);
294 // =======================================================================
295 // function : ShaderPrograms
296 // purpose : Returns list of registered shader programs
297 // =======================================================================
298 const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
300 return myProgramList;
303 // =======================================================================
305 // purpose : Returns true if no program objects are attached
306 // =======================================================================
307 Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
309 return myProgramList.IsEmpty();
312 // =======================================================================
313 // function : switchLightPrograms
315 // =======================================================================
316 void OpenGl_ShaderManager::switchLightPrograms()
318 TCollection_AsciiString aKey (myShadingModel == Visual3d_TOM_FRAGMENT ? "p_" : "g_");
319 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
322 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next())
324 switch (aLightIter.Value().Type)
326 case Visual3d_TOLS_AMBIENT:
327 break; // skip ambient
328 case Visual3d_TOLS_DIRECTIONAL:
331 case Visual3d_TOLS_POSITIONAL:
334 case Visual3d_TOLS_SPOT:
341 if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
343 myLightPrograms = new OpenGl_SetOfShaderPrograms();
344 myMapOfLightPrograms.Bind (aKey, myLightPrograms);
348 // =======================================================================
349 // function : UpdateLightSourceStateTo
350 // purpose : Updates state of OCCT light sources
351 // =======================================================================
352 void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights)
354 myLightSourceState.Set (theLights);
355 myLightSourceState.Update();
356 switchLightPrograms();
359 // =======================================================================
360 // function : SetShadingModel
362 // =======================================================================
363 void OpenGl_ShaderManager::SetShadingModel (const Visual3d_TypeOfModel theModel)
365 myShadingModel = theModel;
366 switchLightPrograms();
369 // =======================================================================
370 // function : SetProjectionState
371 // purpose : Sets new state of OCCT projection transform
372 // =======================================================================
373 void OpenGl_ShaderManager::UpdateProjectionStateTo (const Tmatrix3* theProjectionMatrix)
375 myProjectionState.Set (theProjectionMatrix);
376 myProjectionState.Update();
379 // =======================================================================
380 // function : SetModelWorldState
381 // purpose : Sets new state of OCCT model-world transform
382 // =======================================================================
383 void OpenGl_ShaderManager::UpdateModelWorldStateTo (const Tmatrix3* theModelWorldMatrix)
385 myModelWorldState.Set (theModelWorldMatrix);
386 myModelWorldState.Update();
389 // =======================================================================
390 // function : SetWorldViewState
391 // purpose : Sets new state of OCCT world-view transform
392 // =======================================================================
393 void OpenGl_ShaderManager::UpdateWorldViewStateTo (const Tmatrix3* theWorldViewMatrix)
395 myWorldViewState.Set (theWorldViewMatrix);
396 myWorldViewState.Update();
399 // =======================================================================
400 // function : RevertProjectionStateTo
401 // purpose : Reverts state of OCCT projection transform
402 // =======================================================================
403 void OpenGl_ShaderManager::RevertProjectionStateTo (const Tmatrix3* theProjectionMatrix)
405 myProjectionState.Set (theProjectionMatrix);
406 myProjectionState.Revert();
409 // =======================================================================
410 // function : RevertModelWorldStateTo
411 // purpose : Reverts state of OCCT model-world transform
412 // =======================================================================
413 void OpenGl_ShaderManager::RevertModelWorldStateTo (const Tmatrix3* theModelWorldMatrix)
415 myModelWorldState.Set (theModelWorldMatrix);
416 myModelWorldState.Revert();
419 // =======================================================================
420 // function : RevertWorldViewStateTo
421 // purpose : Reverts state of OCCT world-view transform
422 // =======================================================================
423 void OpenGl_ShaderManager::RevertWorldViewStateTo (const Tmatrix3* theWorldViewMatrix)
425 myWorldViewState.Set (theWorldViewMatrix);
426 myWorldViewState.Revert();
429 // =======================================================================
430 // function : LightSourceState
431 // purpose : Returns current state of OCCT light sources
432 // =======================================================================
433 const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const
435 return myLightSourceState;
438 // =======================================================================
439 // function : ProjectionState
440 // purpose : Returns current state of OCCT projection transform
441 // =======================================================================
442 const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const
444 return myProjectionState;
447 // =======================================================================
448 // function : ModelWorldState
449 // purpose : Returns current state of OCCT model-world transform
450 // =======================================================================
451 const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const
453 return myModelWorldState;
456 // =======================================================================
457 // function : WorldViewState
458 // purpose : Returns current state of OCCT world-view transform
459 // =======================================================================
460 const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const
462 return myWorldViewState;
465 //! Packed properties of light source
466 class OpenGl_ShaderLightParameters
471 OpenGl_Vec4 Position;
472 OpenGl_Vec4 Direction;
473 OpenGl_Vec4 Parameters;
475 //! Returns packed (serialized) representation of light source properties
476 const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
477 static Standard_Integer NbOfVec4() { return 4; }
481 //! Packed light source type information
482 class OpenGl_ShaderLightType
486 Standard_Integer Type;
487 Standard_Integer IsHeadlight;
489 //! Returns packed (serialized) representation of light source type
490 const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
491 static Standard_Integer NbOfVec2i() { return 1; }
495 // =======================================================================
496 // function : PushLightSourceState
497 // purpose : Pushes state of OCCT light sources to the program
498 // =======================================================================
499 void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
501 if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)
502 || !theProgram->IsValid())
507 OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[OpenGLMaxLights];
508 for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt)
510 aLightTypeArray[aLightIt].Type = -1;
513 const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights);
514 if (aLightsDefNb < 1)
516 theProgram->SetUniform (myContext,
517 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
519 theProgram->SetUniform (myContext,
520 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
521 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
522 theProgram->SetUniform (myContext,
523 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
524 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
525 aLightTypeArray[0].Packed());
526 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
527 delete[] aLightTypeArray;
531 OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb];
533 OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
534 Standard_Integer aLightsNb = 0;
535 for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next())
537 const OpenGl_Light& aLight = anIter.Value();
538 if (aLight.Type == Visual3d_TOLS_AMBIENT)
540 anAmbient += aLight.Color;
543 else if (aLightsNb >= OpenGLMaxLights)
548 OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb];
549 aLightType.Type = aLight.Type;
550 aLightType.IsHeadlight = aLight.IsHeadlight;
552 OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb];
553 aLightParams.Color = aLight.Color;
554 aLightParams.Position = aLight.Type == Visual3d_TOLS_DIRECTIONAL
557 if (aLight.Type == Visual3d_TOLS_SPOT)
559 aLightParams.Direction = aLight.Direction;
561 aLightParams.Parameters = aLight.Params;
565 theProgram->SetUniform (myContext,
566 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
568 theProgram->SetUniform (myContext,
569 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
571 theProgram->SetUniform (myContext,
572 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
573 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
574 aLightTypeArray[0].Packed());
577 theProgram->SetUniform (myContext,
578 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
579 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
580 aLightParamsArray[0].Packed());
582 delete[] aLightParamsArray;
583 delete[] aLightTypeArray;
585 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
588 // =======================================================================
589 // function : PushProjectionState
590 // purpose : Pushes state of OCCT projection transform to the program
591 // =======================================================================
592 void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
594 if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE))
599 theProgram->SetUniform (myContext,
600 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
601 myProjectionState.ProjectionMatrix());
603 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
604 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
606 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
609 theProgram->SetUniform (myContext,
610 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
611 myProjectionState.ProjectionMatrix(), true);
613 aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
614 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
616 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
619 theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
622 // =======================================================================
623 // function : PushModelWorldState
624 // purpose : Pushes state of OCCT model-world transform to the program
625 // =======================================================================
626 void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
628 if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
633 theProgram->SetUniform (myContext,
634 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
635 myModelWorldState.ModelWorldMatrix());
637 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
638 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
640 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
643 theProgram->SetUniform (myContext,
644 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
645 myModelWorldState.ModelWorldMatrix(), true);
647 aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
648 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
650 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
653 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
656 // =======================================================================
657 // function : PushWorldViewState
658 // purpose : Pushes state of OCCT world-view transform to the program
659 // =======================================================================
660 void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
662 if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
667 theProgram->SetUniform (myContext,
668 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
669 myWorldViewState.WorldViewMatrix());
671 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
672 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
674 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
677 theProgram->SetUniform (myContext,
678 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
679 myWorldViewState.WorldViewMatrix(), true);
681 aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
682 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
684 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
687 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
690 // =======================================================================
691 // function : UpdateClippingState
692 // purpose : Updates state of OCCT clipping planes
693 // =======================================================================
694 void OpenGl_ShaderManager::UpdateClippingState()
696 myClippingState.Update();
699 // =======================================================================
700 // function : RevertClippingState
701 // purpose : Reverts state of OCCT clipping planes
702 // =======================================================================
703 void OpenGl_ShaderManager::RevertClippingState()
705 myClippingState.Revert();
708 // =======================================================================
709 // function : PushClippingState
710 // purpose : Pushes state of OCCT clipping planes to the program
711 // =======================================================================
712 void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
714 if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
719 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
720 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
721 const GLint aLocSpaces = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_SPACES);
722 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION
723 && aLocSpaces == OpenGl_ShaderProgram::INVALID_LOCATION)
729 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
730 anIter.More(); anIter.Next())
732 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
733 if (!myContext->Clipping().IsEnabled (aPlane))
745 const Standard_Size MAX_CLIP_PLANES = 8;
746 OpenGl_Vec4* anEquations = new OpenGl_Vec4[MAX_CLIP_PLANES];
747 GLint* aSpaces = new GLint [MAX_CLIP_PLANES];
749 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
750 anIter.More(); anIter.Next())
752 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
753 if (!myContext->Clipping().IsEnabled (aPlane))
758 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
759 anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(),
760 (float) anEquation.y(),
761 (float) anEquation.z(),
762 (float) anEquation.w());
763 aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane);
767 theProgram->SetUniform (myContext,
768 theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT),
770 theProgram->SetUniform (myContext, aLocEquations, MAX_CLIP_PLANES, anEquations);
771 theProgram->SetUniform (myContext, aLocSpaces, MAX_CLIP_PLANES, aSpaces);
773 delete[] anEquations;
777 // =======================================================================
778 // function : UpdateMaterialStateTo
779 // purpose : Updates state of OCCT material for specified program
780 // =======================================================================
781 void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram,
782 const OpenGl_Element* theAspect)
784 if (myMaterialStates.IsBound (theProgram))
786 OpenGl_MaterialState& aState = myMaterialStates.ChangeFind (theProgram);
787 aState.Set (theAspect);
792 myMaterialStates.Bind (theProgram, OpenGl_MaterialState (theAspect));
793 myMaterialStates.ChangeFind (theProgram).Update();
797 // =======================================================================
798 // function : ResetMaterialStates
799 // purpose : Resets state of OCCT material for all programs
800 // =======================================================================
801 void OpenGl_ShaderManager::ResetMaterialStates()
803 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
805 anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0);
809 // =======================================================================
810 // function : MaterialState
811 // purpose : Returns state of OCCT material for specified program
812 // =======================================================================
813 const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
815 if (!myMaterialStates.IsBound (theProgram))
818 return &myMaterialStates.Find (theProgram);
824 static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f);
826 // =======================================================================
827 // function : PushAspectFace
829 // =======================================================================
830 static void PushAspectFace (const Handle(OpenGl_Context)& theCtx,
831 const Handle(OpenGl_ShaderProgram)& theProgram,
832 const OpenGl_AspectFace* theAspect)
834 theProgram->SetUniform (theCtx,
835 theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
836 theAspect->DoTextureMap());
837 theProgram->SetUniform (theCtx,
838 theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),
839 0 /* GL_TEXTURE0 */);
840 theProgram->SetUniform (theCtx,
841 theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
842 theAspect->DistinguishingMode());
844 OpenGl_Material aParams;
845 for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
847 const GLint aLoc = theProgram->GetStateLocation (anIndex == 0
848 ? OpenGl_OCCT_FRONT_MATERIAL
849 : OpenGl_OCCT_BACK_MATERIAL);
850 if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
855 aParams.Init (anIndex == 0 ? theAspect->IntFront() : theAspect->IntBack());
856 theProgram->SetUniform (theCtx, aLoc, OpenGl_Material::NbOfVec4(),
861 // =======================================================================
862 // function : PushAspectLine
864 // =======================================================================
865 static void PushAspectLine (const Handle(OpenGl_Context)& theCtx,
866 const Handle(OpenGl_ShaderProgram)& theProgram,
867 const OpenGl_AspectLine* theAspect)
869 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOff);
870 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
872 const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
873 theAspect->Color().rgb[1],
874 theAspect->Color().rgb[2],
875 theAspect->Color().rgb[3]);
876 OpenGl_Vec4 aParams[5];
877 aParams[0] = THE_COLOR_BLACK_VEC4;
878 aParams[1] = THE_COLOR_BLACK_VEC4;
879 aParams[2] = aDiffuse;
880 aParams[3] = THE_COLOR_BLACK_VEC4;
881 aParams[4].x() = 0.0f; // shininess
882 aParams[4].y() = 0.0f; // transparency
883 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
887 // =======================================================================
888 // function : PushAspectText
890 // =======================================================================
891 static void PushAspectText (const Handle(OpenGl_Context)& theCtx,
892 const Handle(OpenGl_ShaderProgram)& theProgram,
893 const OpenGl_AspectText* theAspect)
895 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn);
896 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
897 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */);
899 OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
900 theAspect->Color().rgb[1],
901 theAspect->Color().rgb[2],
902 theAspect->Color().rgb[3]);
903 if (theAspect->DisplayType() == Aspect_TODT_DEKALE
904 || theAspect->DisplayType() == Aspect_TODT_SUBTITLE)
906 aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0],
907 theAspect->SubtitleColor().rgb[1],
908 theAspect->SubtitleColor().rgb[2],
909 theAspect->SubtitleColor().rgb[3]);
912 OpenGl_Vec4 aParams[5];
913 aParams[0] = THE_COLOR_BLACK_VEC4;
914 aParams[1] = THE_COLOR_BLACK_VEC4;
915 aParams[2] = aDiffuse;
916 aParams[3] = THE_COLOR_BLACK_VEC4;
917 aParams[4].x() = 0.0f; // shininess
918 aParams[4].y() = 0.0f; // transparency
919 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
923 // =======================================================================
924 // function : PushAspectMarker
926 // =======================================================================
927 static void PushAspectMarker (const Handle(OpenGl_Context)& theCtx,
928 const Handle(OpenGl_ShaderProgram)& theProgram,
929 const OpenGl_AspectMarker* theAspect)
931 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn);
932 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
933 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */);
935 const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
936 theAspect->Color().rgb[1],
937 theAspect->Color().rgb[2],
938 theAspect->Color().rgb[3]);
939 OpenGl_Vec4 aParams[5];
940 aParams[0] = THE_COLOR_BLACK_VEC4;
941 aParams[1] = THE_COLOR_BLACK_VEC4;
942 aParams[2] = aDiffuse;
943 aParams[3] = THE_COLOR_BLACK_VEC4;
944 aParams[4].x() = 0.0f; // shininess
945 aParams[4].y() = 0.0f; // transparency
946 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
950 }; // nameless namespace
952 // =======================================================================
953 // function : PushMaterialState
954 // purpose : Pushes current state of OCCT material to the program
955 // =======================================================================
956 void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
958 if (!myMaterialStates.IsBound (theProgram))
963 const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram);
964 if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE))
969 if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectFace))
971 PushAspectFace (myContext, theProgram, dynamic_cast<const OpenGl_AspectFace*> (aState.Aspect()));
973 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectLine))
975 PushAspectLine (myContext, theProgram, dynamic_cast<const OpenGl_AspectLine*> (aState.Aspect()));
977 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectText))
979 PushAspectText (myContext, theProgram, dynamic_cast<const OpenGl_AspectText*> (aState.Aspect()));
981 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectMarker))
983 PushAspectMarker (myContext, theProgram, dynamic_cast<const OpenGl_AspectMarker*> (aState.Aspect()));
986 theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index());
989 // =======================================================================
990 // function : PushWorldViewState
991 // purpose : Pushes state of OCCT graphics parameters to the program
992 // =======================================================================
993 void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
995 PushClippingState (theProgram);
996 PushMaterialState (theProgram);
997 PushWorldViewState (theProgram);
998 PushModelWorldState (theProgram);
999 PushProjectionState (theProgram);
1000 PushLightSourceState (theProgram);
1003 // =======================================================================
1004 // function : prepareStdProgramFont
1006 // =======================================================================
1007 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
1009 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1010 TCollection_AsciiString aSrcVert =
1013 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1016 TCollection_AsciiString aSrcFrag =
1017 EOL"float getAlpha(void) { return texture2D(occActiveSampler, gl_PointCoord).a; }"
1020 EOL" vec4 aColor = occColor;"
1021 EOL" aColor.a *= getAlpha();"
1022 EOL" if (aColor.a <= 0.285) discard;"
1023 EOL" gl_FragColor = aColor;"
1026 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1027 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1028 TCollection_AsciiString aKey;
1029 if (!Create (aProgramSrc, aKey, myFontProgram))
1031 myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1032 return Standard_False;
1034 return Standard_True;
1037 // =======================================================================
1038 // function : prepareStdProgramFlat
1040 // =======================================================================
1041 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_ShaderProgram)& theProgram,
1042 const Standard_Integer theBits)
1044 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1045 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
1046 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
1047 TCollection_AsciiString aSrcFragMainGetColor = EOL" gl_FragColor = getColor();";
1048 if ((theBits & OpenGl_PO_Point) != 0)
1050 #if defined(GL_ES_VERSION_2_0)
1051 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1053 if ((theBits & OpenGl_PO_TextureA) != 0)
1056 EOL"float getAlpha(void) { return texture2D(occActiveSampler, gl_PointCoord).a; }"
1057 EOL"vec4 getColor(void)"
1059 EOL" vec4 aColor = occColor;"
1060 EOL" aColor.a *= getAlpha();"
1061 EOL" return aColor;"
1064 aSrcFragMainGetColor =
1065 EOL" vec4 aColor = getColor();"
1066 EOL" if (aColor.a <= 0.1) discard;"
1067 EOL" gl_FragColor = aColor;";
1069 else if ((theBits & OpenGl_PO_TextureRGB) != 0)
1072 EOL"vec4 getColor(void) { return texture2D(occActiveSampler, gl_PointCoord); }";
1073 aSrcFragMainGetColor =
1074 EOL" vec4 aColor = getColor();"
1075 EOL" if (aColor.a <= 0.1) discard;"
1076 EOL" gl_FragColor = aColor;";
1079 if ((theBits & OpenGl_PO_VertColor) != 0)
1081 aSrcVertExtraOut += EOL"varying vec4 VertColor;";
1082 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1083 aSrcFragExtraOut += EOL"varying vec4 VertColor;";
1084 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
1086 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1088 const char THE_POS_VARY[] =
1089 EOL"varying vec4 PositionWorld;"
1090 EOL"varying vec4 Position;";
1092 aSrcVertExtraOut += THE_POS_VARY;
1093 aSrcFragExtraOut += THE_POS_VARY;
1094 aSrcVertExtraMain +=
1095 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1096 EOL" Position = occWorldViewMatrix * PositionWorld;";
1097 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1105 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1114 + aSrcFragMainGetColor
1117 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1118 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1120 TCollection_AsciiString aKey;
1121 if (!Create (aProgramSrc, aKey, theProgram))
1123 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1124 return Standard_False;
1126 return Standard_True;
1129 // =======================================================================
1130 // function : stdComputeLighting
1132 // =======================================================================
1133 TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting()
1135 bool aLightsMap[Visual3d_TOLS_SPOT + 1] = { false, false, false, false };
1136 TCollection_AsciiString aLightsFunc, aLightsLoop;
1137 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
1138 if (aLights != NULL)
1140 Standard_Integer anIndex = 0;
1141 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next(), ++anIndex)
1143 switch (aLightIter.Value().Type)
1145 case Visual3d_TOLS_AMBIENT:
1147 break; // skip ambient
1148 case Visual3d_TOLS_DIRECTIONAL:
1149 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
1151 case Visual3d_TOLS_POSITIONAL:
1152 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1154 case Visual3d_TOLS_SPOT:
1155 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1159 bool& aTypeBit = aLightsMap[aLightIter.Value().Type];
1166 switch (aLightIter.Value().Type)
1168 case Visual3d_TOLS_AMBIENT: break;
1169 case Visual3d_TOLS_DIRECTIONAL: aLightsFunc += THE_FUNC_directionalLight; break;
1170 case Visual3d_TOLS_POSITIONAL: aLightsFunc += THE_FUNC_pointLight; break;
1171 case Visual3d_TOLS_SPOT: aLightsFunc += THE_FUNC_spotLight; break;
1176 return TCollection_AsciiString()
1180 EOL"vec4 computeLighting (in vec3 theNormal,"
1181 EOL" in vec3 theView,"
1182 EOL" in vec4 thePoint,"
1183 EOL" in bool theIsFront)"
1185 EOL" Ambient = occLightAmbient.rgb;"
1186 EOL" Diffuse = vec3 (0.0);"
1187 EOL" Specular = vec3 (0.0);"
1188 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
1190 + EOL" vec4 aMaterialAmbient = theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();"
1191 EOL" vec4 aMaterialDiffuse = theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();"
1192 EOL" vec4 aMaterialSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
1193 EOL" vec4 aMaterialEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
1194 EOL" return vec4 (Ambient, 1.0) * aMaterialAmbient"
1195 EOL" + vec4 (Diffuse, 1.0) * aMaterialDiffuse"
1196 EOL" + vec4 (Specular, 1.0) * aMaterialSpecular"
1197 EOL" + aMaterialEmission;"
1201 // =======================================================================
1202 // function : prepareStdProgramGouraud
1204 // =======================================================================
1205 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
1206 const Standard_Integer theBits)
1208 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1209 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
1210 if ((theBits & OpenGl_PO_Point) != 0)
1212 #if defined(GL_ES_VERSION_2_0)
1213 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1216 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1218 const char THE_POS_VARY[] =
1219 EOL"varying vec4 PositionWorld;"
1220 EOL"varying vec4 Position;";
1222 aSrcVertExtraOut += THE_POS_VARY;
1223 aSrcFragExtraOut += THE_POS_VARY;
1224 aSrcVertExtraMain +=
1225 EOL" PositionWorld = aPositionWorld;"
1226 EOL" Position = aPosition;";
1227 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1230 const TCollection_AsciiString aLights = stdComputeLighting();
1231 aSrcVert = TCollection_AsciiString()
1232 + THE_FUNC_transformNormal
1236 EOL"varying vec4 FrontColor;"
1237 EOL"varying vec4 BackColor;"
1242 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
1243 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
1244 EOL" vec3 aNormal = transformNormal (occNormal);"
1245 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
1246 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
1247 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
1249 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1252 aSrcFrag = TCollection_AsciiString()
1253 + EOL"varying vec4 FrontColor;"
1254 EOL"varying vec4 BackColor;"
1259 + EOL" gl_FragColor = gl_FrontFacing ? FrontColor : BackColor;"
1262 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1263 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1264 TCollection_AsciiString aKey;
1265 if (!Create (aProgramSrc, aKey, theProgram))
1267 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1268 return Standard_False;
1270 return Standard_True;
1273 // =======================================================================
1274 // function : prepareStdProgramPhong
1276 // =======================================================================
1277 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
1278 const Standard_Integer theBits)
1280 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1281 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraMain;
1282 if ((theBits & OpenGl_PO_Point) != 0)
1284 #if defined(GL_ES_VERSION_2_0)
1285 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1288 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1290 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1293 aSrcVert = TCollection_AsciiString()
1294 + THE_FUNC_transformNormal
1296 EOL"varying vec4 PositionWorld;"
1297 EOL"varying vec4 Position;"
1298 EOL"varying vec3 Normal;"
1299 EOL"varying vec3 View;"
1304 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1305 EOL" Position = occWorldViewMatrix * PositionWorld;"
1306 EOL" Normal = transformNormal (occNormal);"
1307 EOL" View = vec3 (0.0, 0.0, 1.0);"
1309 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1312 const TCollection_AsciiString aLights = stdComputeLighting();
1313 aSrcFrag = TCollection_AsciiString()
1314 + EOL"varying vec4 PositionWorld;"
1315 EOL"varying vec4 Position;"
1316 EOL"varying vec3 Normal;"
1317 EOL"varying vec3 View;"
1324 + EOL" gl_FragColor = computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing);"
1327 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1328 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1329 TCollection_AsciiString aKey;
1330 if (!Create (aProgramSrc, aKey, theProgram))
1332 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1333 return Standard_False;
1335 return Standard_True;
1338 // =======================================================================
1339 // function : bindProgramWithState
1341 // =======================================================================
1342 Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram,
1343 const OpenGl_Element* theAspect)
1345 if (!myContext->BindProgram (theProgram))
1347 return Standard_False;
1349 theProgram->ApplyVariables (myContext);
1351 const OpenGl_MaterialState* aMaterialState = MaterialState (theProgram);
1352 if (aMaterialState == NULL || aMaterialState->Aspect() != theAspect)
1354 UpdateMaterialStateTo (theProgram, theAspect);
1357 PushState (theProgram);
1358 return Standard_True;