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 // =======================================================================
222 // =======================================================================
223 void OpenGl_ShaderManager::clear()
225 myProgramList.Clear();
226 myLightPrograms.Nullify();
227 myFlatPrograms = OpenGl_SetOfShaderPrograms();
228 myMapOfLightPrograms.Clear();
229 myFontProgram.Nullify();
230 switchLightPrograms();
233 // =======================================================================
235 // purpose : Creates new shader program
236 // =======================================================================
237 Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
238 TCollection_AsciiString& theShareKey,
239 Handle(OpenGl_ShaderProgram)& theProgram)
241 theProgram.Nullify();
242 if (theProxy.IsNull())
244 return Standard_False;
247 theShareKey = theProxy->GetId();
248 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
250 if (theProgram->Share())
252 myProgramList.Append (theProgram);
254 return Standard_True;
257 theProgram = new OpenGl_ShaderProgram (theProxy);
258 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
260 theProgram->Release (myContext);
262 theProgram.Nullify();
263 return Standard_False;
266 myProgramList.Append (theProgram);
267 myContext->ShareResource (theShareKey, theProgram);
268 return Standard_True;
271 // =======================================================================
272 // function : Unregister
273 // purpose : Removes specified shader program from the manager
274 // =======================================================================
275 void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
276 Handle(OpenGl_ShaderProgram)& theProgram)
278 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
280 if (anIt.Value() == theProgram)
282 if (!theProgram->UnShare())
285 theProgram.Nullify();
289 myProgramList.Remove (anIt);
290 myMaterialStates.UnBind (theProgram);
295 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
298 myContext->DelayedRelease (theProgram);
299 theProgram.Nullify();
303 theProgram.Nullify();
304 myContext->ReleaseResource (anID, Standard_True);
308 // =======================================================================
309 // function : ShaderPrograms
310 // purpose : Returns list of registered shader programs
311 // =======================================================================
312 const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
314 return myProgramList;
317 // =======================================================================
319 // purpose : Returns true if no program objects are attached
320 // =======================================================================
321 Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
323 return myProgramList.IsEmpty();
326 // =======================================================================
327 // function : switchLightPrograms
329 // =======================================================================
330 void OpenGl_ShaderManager::switchLightPrograms()
332 TCollection_AsciiString aKey (myShadingModel == Visual3d_TOM_FRAGMENT ? "p_" : "g_");
333 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
336 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next())
338 switch (aLightIter.Value().Type)
340 case Visual3d_TOLS_AMBIENT:
341 break; // skip ambient
342 case Visual3d_TOLS_DIRECTIONAL:
345 case Visual3d_TOLS_POSITIONAL:
348 case Visual3d_TOLS_SPOT:
355 if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
357 myLightPrograms = new OpenGl_SetOfShaderPrograms();
358 myMapOfLightPrograms.Bind (aKey, myLightPrograms);
362 // =======================================================================
363 // function : UpdateLightSourceStateTo
364 // purpose : Updates state of OCCT light sources
365 // =======================================================================
366 void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights)
368 myLightSourceState.Set (theLights);
369 myLightSourceState.Update();
370 switchLightPrograms();
373 // =======================================================================
374 // function : SetShadingModel
376 // =======================================================================
377 void OpenGl_ShaderManager::SetShadingModel (const Visual3d_TypeOfModel theModel)
379 myShadingModel = theModel;
380 switchLightPrograms();
383 // =======================================================================
384 // function : SetProjectionState
385 // purpose : Sets new state of OCCT projection transform
386 // =======================================================================
387 void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix)
389 myProjectionState.Set (theProjectionMatrix);
390 myProjectionState.Update();
393 // =======================================================================
394 // function : SetModelWorldState
395 // purpose : Sets new state of OCCT model-world transform
396 // =======================================================================
397 void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix)
399 myModelWorldState.Set (theModelWorldMatrix);
400 myModelWorldState.Update();
403 // =======================================================================
404 // function : SetWorldViewState
405 // purpose : Sets new state of OCCT world-view transform
406 // =======================================================================
407 void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix)
409 myWorldViewState.Set (theWorldViewMatrix);
410 myWorldViewState.Update();
413 // =======================================================================
414 // function : LightSourceState
415 // purpose : Returns current state of OCCT light sources
416 // =======================================================================
417 const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const
419 return myLightSourceState;
422 // =======================================================================
423 // function : ProjectionState
424 // purpose : Returns current state of OCCT projection transform
425 // =======================================================================
426 const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const
428 return myProjectionState;
431 // =======================================================================
432 // function : ModelWorldState
433 // purpose : Returns current state of OCCT model-world transform
434 // =======================================================================
435 const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const
437 return myModelWorldState;
440 // =======================================================================
441 // function : WorldViewState
442 // purpose : Returns current state of OCCT world-view transform
443 // =======================================================================
444 const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const
446 return myWorldViewState;
449 //! Packed properties of light source
450 class OpenGl_ShaderLightParameters
455 OpenGl_Vec4 Position;
456 OpenGl_Vec4 Direction;
457 OpenGl_Vec4 Parameters;
459 //! Returns packed (serialized) representation of light source properties
460 const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
461 static Standard_Integer NbOfVec4() { return 4; }
465 //! Packed light source type information
466 class OpenGl_ShaderLightType
470 Standard_Integer Type;
471 Standard_Integer IsHeadlight;
473 //! Returns packed (serialized) representation of light source type
474 const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
475 static Standard_Integer NbOfVec2i() { return 1; }
479 // =======================================================================
480 // function : PushLightSourceState
481 // purpose : Pushes state of OCCT light sources to the program
482 // =======================================================================
483 void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
485 if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)
486 || !theProgram->IsValid())
491 OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[OpenGLMaxLights];
492 for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt)
494 aLightTypeArray[aLightIt].Type = -1;
497 const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights);
498 if (aLightsDefNb < 1)
500 theProgram->SetUniform (myContext,
501 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
503 theProgram->SetUniform (myContext,
504 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
505 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
506 theProgram->SetUniform (myContext,
507 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
508 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
509 aLightTypeArray[0].Packed());
510 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
511 delete[] aLightTypeArray;
515 OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb];
517 OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
518 Standard_Integer aLightsNb = 0;
519 for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next())
521 const OpenGl_Light& aLight = anIter.Value();
522 if (aLight.Type == Visual3d_TOLS_AMBIENT)
524 anAmbient += aLight.Color;
527 else if (aLightsNb >= OpenGLMaxLights)
532 OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb];
533 aLightType.Type = aLight.Type;
534 aLightType.IsHeadlight = aLight.IsHeadlight;
536 OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb];
537 aLightParams.Color = aLight.Color;
538 aLightParams.Position = aLight.Type == Visual3d_TOLS_DIRECTIONAL
541 if (aLight.Type == Visual3d_TOLS_SPOT)
543 aLightParams.Direction = aLight.Direction;
545 aLightParams.Parameters = aLight.Params;
549 theProgram->SetUniform (myContext,
550 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
552 theProgram->SetUniform (myContext,
553 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
555 theProgram->SetUniform (myContext,
556 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
557 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
558 aLightTypeArray[0].Packed());
561 theProgram->SetUniform (myContext,
562 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
563 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
564 aLightParamsArray[0].Packed());
566 delete[] aLightParamsArray;
567 delete[] aLightTypeArray;
569 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
572 // =======================================================================
573 // function : PushProjectionState
574 // purpose : Pushes state of OCCT projection transform to the program
575 // =======================================================================
576 void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
578 if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE))
583 theProgram->SetUniform (myContext,
584 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
585 myProjectionState.ProjectionMatrix());
587 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
588 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
590 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
593 theProgram->SetUniform (myContext,
594 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
595 myProjectionState.ProjectionMatrix(), true);
597 aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
598 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
600 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
603 theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
606 // =======================================================================
607 // function : PushModelWorldState
608 // purpose : Pushes state of OCCT model-world transform to the program
609 // =======================================================================
610 void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
612 if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
617 theProgram->SetUniform (myContext,
618 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
619 myModelWorldState.ModelWorldMatrix());
621 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
622 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
624 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
627 theProgram->SetUniform (myContext,
628 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
629 myModelWorldState.ModelWorldMatrix(), true);
631 aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
632 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
634 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
637 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
640 // =======================================================================
641 // function : PushWorldViewState
642 // purpose : Pushes state of OCCT world-view transform to the program
643 // =======================================================================
644 void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
646 if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
651 theProgram->SetUniform (myContext,
652 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
653 myWorldViewState.WorldViewMatrix());
655 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
656 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
658 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
661 theProgram->SetUniform (myContext,
662 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
663 myWorldViewState.WorldViewMatrix(), true);
665 aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
666 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
668 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
671 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
674 // =======================================================================
675 // function : UpdateClippingState
676 // purpose : Updates state of OCCT clipping planes
677 // =======================================================================
678 void OpenGl_ShaderManager::UpdateClippingState()
680 myClippingState.Update();
683 // =======================================================================
684 // function : RevertClippingState
685 // purpose : Reverts state of OCCT clipping planes
686 // =======================================================================
687 void OpenGl_ShaderManager::RevertClippingState()
689 myClippingState.Revert();
692 // =======================================================================
693 // function : PushClippingState
694 // purpose : Pushes state of OCCT clipping planes to the program
695 // =======================================================================
696 void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
698 if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
703 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
704 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
705 const GLint aLocSpaces = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_SPACES);
706 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION
707 && aLocSpaces == OpenGl_ShaderProgram::INVALID_LOCATION)
713 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
714 anIter.More(); anIter.Next())
716 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
717 if (!myContext->Clipping().IsEnabled (aPlane))
729 const Standard_Size MAX_CLIP_PLANES = 8;
730 OpenGl_Vec4* anEquations = new OpenGl_Vec4[MAX_CLIP_PLANES];
731 GLint* aSpaces = new GLint [MAX_CLIP_PLANES];
733 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
734 anIter.More(); anIter.Next())
736 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
737 if (!myContext->Clipping().IsEnabled (aPlane))
742 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
743 anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(),
744 (float) anEquation.y(),
745 (float) anEquation.z(),
746 (float) anEquation.w());
747 aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane);
751 theProgram->SetUniform (myContext,
752 theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT),
754 theProgram->SetUniform (myContext, aLocEquations, MAX_CLIP_PLANES, anEquations);
755 theProgram->SetUniform (myContext, aLocSpaces, MAX_CLIP_PLANES, aSpaces);
757 delete[] anEquations;
761 // =======================================================================
762 // function : UpdateMaterialStateTo
763 // purpose : Updates state of OCCT material for specified program
764 // =======================================================================
765 void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram,
766 const OpenGl_Element* theAspect)
768 if (myMaterialStates.IsBound (theProgram))
770 OpenGl_MaterialState& aState = myMaterialStates.ChangeFind (theProgram);
771 aState.Set (theAspect);
776 myMaterialStates.Bind (theProgram, OpenGl_MaterialState (theAspect));
777 myMaterialStates.ChangeFind (theProgram).Update();
781 // =======================================================================
782 // function : ResetMaterialStates
783 // purpose : Resets state of OCCT material for all programs
784 // =======================================================================
785 void OpenGl_ShaderManager::ResetMaterialStates()
787 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
789 anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0);
793 // =======================================================================
794 // function : MaterialState
795 // purpose : Returns state of OCCT material for specified program
796 // =======================================================================
797 const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
799 if (!myMaterialStates.IsBound (theProgram))
802 return &myMaterialStates.Find (theProgram);
808 static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f);
810 // =======================================================================
811 // function : PushAspectFace
813 // =======================================================================
814 static void PushAspectFace (const Handle(OpenGl_Context)& theCtx,
815 const Handle(OpenGl_ShaderProgram)& theProgram,
816 const OpenGl_AspectFace* theAspect)
818 theProgram->SetUniform (theCtx,
819 theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
820 theAspect->DoTextureMap());
821 theProgram->SetUniform (theCtx,
822 theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),
823 0 /* GL_TEXTURE0 */);
824 theProgram->SetUniform (theCtx,
825 theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
826 theAspect->DistinguishingMode());
828 OpenGl_Material aParams;
829 for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
831 const GLint aLoc = theProgram->GetStateLocation (anIndex == 0
832 ? OpenGl_OCCT_FRONT_MATERIAL
833 : OpenGl_OCCT_BACK_MATERIAL);
834 if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
839 aParams.Init (anIndex == 0 ? theAspect->IntFront() : theAspect->IntBack());
840 theProgram->SetUniform (theCtx, aLoc, OpenGl_Material::NbOfVec4(),
845 // =======================================================================
846 // function : PushAspectLine
848 // =======================================================================
849 static void PushAspectLine (const Handle(OpenGl_Context)& theCtx,
850 const Handle(OpenGl_ShaderProgram)& theProgram,
851 const OpenGl_AspectLine* theAspect)
853 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOff);
854 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
856 const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
857 theAspect->Color().rgb[1],
858 theAspect->Color().rgb[2],
859 theAspect->Color().rgb[3]);
860 OpenGl_Vec4 aParams[5];
861 aParams[0] = THE_COLOR_BLACK_VEC4;
862 aParams[1] = THE_COLOR_BLACK_VEC4;
863 aParams[2] = aDiffuse;
864 aParams[3] = THE_COLOR_BLACK_VEC4;
865 aParams[4].x() = 0.0f; // shininess
866 aParams[4].y() = 0.0f; // transparency
867 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
871 // =======================================================================
872 // function : PushAspectText
874 // =======================================================================
875 static void PushAspectText (const Handle(OpenGl_Context)& theCtx,
876 const Handle(OpenGl_ShaderProgram)& theProgram,
877 const OpenGl_AspectText* theAspect)
879 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn);
880 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
881 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */);
883 OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
884 theAspect->Color().rgb[1],
885 theAspect->Color().rgb[2],
886 theAspect->Color().rgb[3]);
887 if (theAspect->DisplayType() == Aspect_TODT_DEKALE
888 || theAspect->DisplayType() == Aspect_TODT_SUBTITLE)
890 aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0],
891 theAspect->SubtitleColor().rgb[1],
892 theAspect->SubtitleColor().rgb[2],
893 theAspect->SubtitleColor().rgb[3]);
896 OpenGl_Vec4 aParams[5];
897 aParams[0] = THE_COLOR_BLACK_VEC4;
898 aParams[1] = THE_COLOR_BLACK_VEC4;
899 aParams[2] = aDiffuse;
900 aParams[3] = THE_COLOR_BLACK_VEC4;
901 aParams[4].x() = 0.0f; // shininess
902 aParams[4].y() = 0.0f; // transparency
903 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
907 // =======================================================================
908 // function : PushAspectMarker
910 // =======================================================================
911 static void PushAspectMarker (const Handle(OpenGl_Context)& theCtx,
912 const Handle(OpenGl_ShaderProgram)& theProgram,
913 const OpenGl_AspectMarker* theAspect)
915 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn);
916 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
917 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */);
919 const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
920 theAspect->Color().rgb[1],
921 theAspect->Color().rgb[2],
922 theAspect->Color().rgb[3]);
923 OpenGl_Vec4 aParams[5];
924 aParams[0] = THE_COLOR_BLACK_VEC4;
925 aParams[1] = THE_COLOR_BLACK_VEC4;
926 aParams[2] = aDiffuse;
927 aParams[3] = THE_COLOR_BLACK_VEC4;
928 aParams[4].x() = 0.0f; // shininess
929 aParams[4].y() = 0.0f; // transparency
930 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
934 }; // nameless namespace
936 // =======================================================================
937 // function : PushMaterialState
938 // purpose : Pushes current state of OCCT material to the program
939 // =======================================================================
940 void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
942 if (!myMaterialStates.IsBound (theProgram))
947 const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram);
948 if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE))
953 if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectFace))
955 PushAspectFace (myContext, theProgram, dynamic_cast<const OpenGl_AspectFace*> (aState.Aspect()));
957 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectLine))
959 PushAspectLine (myContext, theProgram, dynamic_cast<const OpenGl_AspectLine*> (aState.Aspect()));
961 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectText))
963 PushAspectText (myContext, theProgram, dynamic_cast<const OpenGl_AspectText*> (aState.Aspect()));
965 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectMarker))
967 PushAspectMarker (myContext, theProgram, dynamic_cast<const OpenGl_AspectMarker*> (aState.Aspect()));
970 theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index());
973 // =======================================================================
974 // function : PushWorldViewState
975 // purpose : Pushes state of OCCT graphics parameters to the program
976 // =======================================================================
977 void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
979 PushClippingState (theProgram);
980 PushMaterialState (theProgram);
981 PushWorldViewState (theProgram);
982 PushModelWorldState (theProgram);
983 PushProjectionState (theProgram);
984 PushLightSourceState (theProgram);
987 // =======================================================================
988 // function : prepareStdProgramFont
990 // =======================================================================
991 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
993 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
994 TCollection_AsciiString aSrcVert =
997 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1000 TCollection_AsciiString aSrcFrag =
1001 EOL"float getAlpha(void) { return texture2D(occActiveSampler, gl_PointCoord).a; }"
1004 EOL" vec4 aColor = occColor;"
1005 EOL" aColor.a *= getAlpha();"
1006 EOL" if (aColor.a <= 0.285) discard;"
1007 EOL" gl_FragColor = aColor;"
1010 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1011 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1012 TCollection_AsciiString aKey;
1013 if (!Create (aProgramSrc, aKey, myFontProgram))
1015 myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1016 return Standard_False;
1018 return Standard_True;
1021 // =======================================================================
1022 // function : prepareStdProgramFlat
1024 // =======================================================================
1025 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_ShaderProgram)& theProgram,
1026 const Standard_Integer theBits)
1028 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1029 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
1030 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
1031 TCollection_AsciiString aSrcFragMainGetColor = EOL" gl_FragColor = getColor();";
1032 if ((theBits & OpenGl_PO_Point) != 0)
1034 #if defined(GL_ES_VERSION_2_0)
1035 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1037 if ((theBits & OpenGl_PO_TextureA) != 0)
1040 EOL"float getAlpha(void) { return texture2D(occActiveSampler, gl_PointCoord).a; }"
1041 EOL"vec4 getColor(void)"
1043 EOL" vec4 aColor = occColor;"
1044 EOL" aColor.a *= getAlpha();"
1045 EOL" return aColor;"
1048 aSrcFragMainGetColor =
1049 EOL" vec4 aColor = getColor();"
1050 EOL" if (aColor.a <= 0.1) discard;"
1051 EOL" gl_FragColor = aColor;";
1053 else if ((theBits & OpenGl_PO_TextureRGB) != 0)
1056 EOL"vec4 getColor(void) { return texture2D(occActiveSampler, gl_PointCoord); }";
1057 aSrcFragMainGetColor =
1058 EOL" vec4 aColor = getColor();"
1059 EOL" if (aColor.a <= 0.1) discard;"
1060 EOL" gl_FragColor = aColor;";
1063 if ((theBits & OpenGl_PO_VertColor) != 0)
1065 aSrcVertExtraOut += EOL"varying vec4 VertColor;";
1066 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1067 aSrcFragExtraOut += EOL"varying vec4 VertColor;";
1068 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
1070 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1072 const char THE_POS_VARY[] =
1073 EOL"varying vec4 PositionWorld;"
1074 EOL"varying vec4 Position;";
1076 aSrcVertExtraOut += THE_POS_VARY;
1077 aSrcFragExtraOut += THE_POS_VARY;
1078 aSrcVertExtraMain +=
1079 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1080 EOL" Position = occWorldViewMatrix * PositionWorld;";
1081 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1089 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1098 + aSrcFragMainGetColor
1101 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1102 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1104 TCollection_AsciiString aKey;
1105 if (!Create (aProgramSrc, aKey, theProgram))
1107 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1108 return Standard_False;
1110 return Standard_True;
1113 // =======================================================================
1114 // function : stdComputeLighting
1116 // =======================================================================
1117 TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (const Standard_Boolean theHasVertColor)
1119 bool aLightsMap[Visual3d_TOLS_SPOT + 1] = { false, false, false, false };
1120 TCollection_AsciiString aLightsFunc, aLightsLoop;
1121 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
1122 if (aLights != NULL)
1124 Standard_Integer anIndex = 0;
1125 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next(), ++anIndex)
1127 switch (aLightIter.Value().Type)
1129 case Visual3d_TOLS_AMBIENT:
1131 break; // skip ambient
1132 case Visual3d_TOLS_DIRECTIONAL:
1133 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
1135 case Visual3d_TOLS_POSITIONAL:
1136 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1138 case Visual3d_TOLS_SPOT:
1139 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1143 bool& aTypeBit = aLightsMap[aLightIter.Value().Type];
1150 switch (aLightIter.Value().Type)
1152 case Visual3d_TOLS_AMBIENT: break;
1153 case Visual3d_TOLS_DIRECTIONAL: aLightsFunc += THE_FUNC_directionalLight; break;
1154 case Visual3d_TOLS_POSITIONAL: aLightsFunc += THE_FUNC_pointLight; break;
1155 case Visual3d_TOLS_SPOT: aLightsFunc += THE_FUNC_spotLight; break;
1160 TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();";
1161 TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();";
1162 if (theHasVertColor)
1164 aGetMatAmbient = "getVertColor();";
1165 aGetMatDiffuse = "getVertColor();";
1168 return TCollection_AsciiString()
1172 EOL"vec4 computeLighting (in vec3 theNormal,"
1173 EOL" in vec3 theView,"
1174 EOL" in vec4 thePoint,"
1175 EOL" in bool theIsFront)"
1177 EOL" Ambient = occLightAmbient.rgb;"
1178 EOL" Diffuse = vec3 (0.0);"
1179 EOL" Specular = vec3 (0.0);"
1180 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
1182 + EOL" vec4 aMaterialAmbient = " + aGetMatAmbient
1183 + EOL" vec4 aMaterialDiffuse = " + aGetMatDiffuse
1184 + EOL" vec4 aMaterialSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
1185 EOL" vec4 aMaterialEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
1186 EOL" return vec4 (Ambient, 1.0) * aMaterialAmbient"
1187 EOL" + vec4 (Diffuse, 1.0) * aMaterialDiffuse"
1188 EOL" + vec4 (Specular, 1.0) * aMaterialSpecular"
1189 EOL" + aMaterialEmission;"
1193 // =======================================================================
1194 // function : prepareStdProgramGouraud
1196 // =======================================================================
1197 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
1198 const Standard_Integer theBits)
1200 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1201 TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
1202 if ((theBits & OpenGl_PO_Point) != 0)
1204 #if defined(GL_ES_VERSION_2_0)
1205 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1208 if ((theBits & OpenGl_PO_VertColor) != 0)
1210 aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
1212 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1214 const char THE_POS_VARY[] =
1215 EOL"varying vec4 PositionWorld;"
1216 EOL"varying vec4 Position;";
1218 aSrcVertExtraOut += THE_POS_VARY;
1219 aSrcFragExtraOut += THE_POS_VARY;
1220 aSrcVertExtraMain +=
1221 EOL" PositionWorld = aPositionWorld;"
1222 EOL" Position = aPosition;";
1223 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1226 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
1227 aSrcVert = TCollection_AsciiString()
1228 + THE_FUNC_transformNormal
1233 EOL"varying vec4 FrontColor;"
1234 EOL"varying vec4 BackColor;"
1239 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
1240 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
1241 EOL" vec3 aNormal = transformNormal (occNormal);"
1242 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
1243 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
1244 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
1246 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1249 aSrcFrag = TCollection_AsciiString()
1250 + EOL"varying vec4 FrontColor;"
1251 EOL"varying vec4 BackColor;"
1256 + EOL" gl_FragColor = gl_FrontFacing ? FrontColor : BackColor;"
1259 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1260 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1261 TCollection_AsciiString aKey;
1262 if (!Create (aProgramSrc, aKey, theProgram))
1264 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1265 return Standard_False;
1267 return Standard_True;
1270 // =======================================================================
1271 // function : prepareStdProgramPhong
1273 // =======================================================================
1274 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
1275 const Standard_Integer theBits)
1277 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1278 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragGetColor, aSrcFragExtraMain;
1279 if ((theBits & OpenGl_PO_Point) != 0)
1281 #if defined(GL_ES_VERSION_2_0)
1282 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1285 if ((theBits & OpenGl_PO_VertColor) != 0)
1287 aSrcVertExtraOut += EOL"varying vec4 VertColor;";
1288 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1289 aSrcFragGetColor = EOL"varying vec4 VertColor;"
1290 EOL"vec4 getVertColor(void) { return VertColor; }";
1292 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1294 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1297 aSrcVert = TCollection_AsciiString()
1298 + THE_FUNC_transformNormal
1300 EOL"varying vec4 PositionWorld;"
1301 EOL"varying vec4 Position;"
1302 EOL"varying vec3 Normal;"
1303 EOL"varying vec3 View;"
1308 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1309 EOL" Position = occWorldViewMatrix * PositionWorld;"
1310 EOL" Normal = transformNormal (occNormal);"
1311 EOL" View = vec3 (0.0, 0.0, 1.0);"
1313 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1316 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
1317 aSrcFrag = TCollection_AsciiString()
1318 + EOL"varying vec4 PositionWorld;"
1319 EOL"varying vec4 Position;"
1320 EOL"varying vec3 Normal;"
1321 EOL"varying vec3 View;"
1329 + EOL" gl_FragColor = computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing);"
1332 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1333 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1334 TCollection_AsciiString aKey;
1335 if (!Create (aProgramSrc, aKey, theProgram))
1337 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1338 return Standard_False;
1340 return Standard_True;
1343 // =======================================================================
1344 // function : bindProgramWithState
1346 // =======================================================================
1347 Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram,
1348 const OpenGl_Element* theAspect)
1350 if (!myContext->BindProgram (theProgram))
1352 return Standard_False;
1354 theProgram->ApplyVariables (myContext);
1356 const OpenGl_MaterialState* aMaterialState = MaterialState (theProgram);
1357 if (aMaterialState == NULL || aMaterialState->Aspect() != theAspect)
1359 UpdateMaterialStateTo (theProgram, theAspect);
1362 PushState (theProgram);
1363 return Standard_True;