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 <Graphic3d_TextureParams.hxx>
19 #include <OpenGl_AspectFace.hxx>
20 #include <OpenGl_AspectLine.hxx>
21 #include <OpenGl_AspectMarker.hxx>
22 #include <OpenGl_AspectText.hxx>
23 #include <OpenGl_Clipping.hxx>
24 #include <OpenGl_Context.hxx>
25 #include <OpenGl_ShaderManager.hxx>
26 #include <OpenGl_ShaderProgram.hxx>
27 #include <OpenGl_Workspace.hxx>
29 #include <TCollection_ExtendedString.hxx>
39 //! Definition of VertColor varying.
40 const char THE_VARY_TexCoord_OUT[] =
41 EOL"THE_SHADER_OUT vec2 TexCoord;";
42 const char THE_VARY_TexCoord_IN[] =
43 EOL"THE_SHADER_IN vec2 TexCoord;";
45 //! Auxiliary function to transform normal
46 const char THE_FUNC_transformNormal[] =
47 EOL"vec3 transformNormal (in vec3 theNormal)"
49 EOL" vec4 aResult = occWorldViewMatrixInverseTranspose"
50 EOL" * occModelWorldMatrixInverseTranspose"
51 EOL" * vec4 (theNormal, 0.0);"
52 EOL" return normalize (aResult.xyz);"
55 //! Global shader variable for color definition with lighting enabled.
56 const char THE_FUNC_lightDef[] =
57 EOL"vec3 Ambient;" //!< Ambient contribution of light sources
58 EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources
59 EOL"vec3 Specular;"; //!< Specular contribution of light sources
61 //! Function computes contribution of isotropic point light source
62 const char THE_FUNC_pointLight[] =
63 EOL"void pointLight (in int theId,"
64 EOL" in vec3 theNormal,"
65 EOL" in vec3 theView,"
66 EOL" in vec3 thePoint,"
67 EOL" in bool theIsFront)"
69 EOL" vec3 aLight = occLight_Position (theId).xyz;"
70 EOL" if (occLight_IsHeadlight (theId) == 0)"
72 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));"
74 EOL" aLight -= thePoint;"
76 EOL" float aDist = length (aLight);"
77 EOL" aLight = aLight * (1.0 / aDist);"
79 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
80 EOL" + occLight_LinearAttenuation (theId) * aDist);"
82 EOL" vec3 aHalf = normalize (aLight + theView);"
84 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
85 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
86 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
88 EOL" float aSpecl = 0.0;"
89 EOL" if (aNdotL > 0.0)"
91 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
94 EOL"Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
95 EOL"Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
98 //! Function computes contribution of spotlight source
99 const char THE_FUNC_spotLight[] =
100 EOL"void spotLight (in int theId,"
101 EOL" in vec3 theNormal,"
102 EOL" in vec3 theView,"
103 EOL" in vec3 thePoint,"
104 EOL" in bool theIsFront)"
106 EOL" vec3 aLight = occLight_Position (theId).xyz;"
107 EOL" vec3 aSpotDir = occLight_SpotDirection (theId).xyz;"
108 EOL" if (occLight_IsHeadlight (theId) == 0)"
110 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));"
111 EOL" aSpotDir = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aSpotDir, 0.0));"
113 EOL" aLight -= thePoint;"
115 EOL" float aDist = length (aLight);"
116 EOL" aLight = aLight * (1.0 / aDist);"
118 EOL" aSpotDir = normalize (aSpotDir);"
120 EOL" float aCosA = dot (aSpotDir, -aLight);"
121 EOL" if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
126 EOL" float anExponent = occLight_SpotExponent (theId);"
127 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
128 EOL" + occLight_LinearAttenuation (theId) * aDist);"
129 EOL" if (anExponent > 0.0)"
131 EOL" anAtten *= pow (aCosA, anExponent * 128.0);"
134 EOL" vec3 aHalf = normalize (aLight + theView);"
136 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
137 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
138 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
140 EOL" float aSpecl = 0.0;"
141 EOL" if (aNdotL > 0.0)"
143 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
146 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
147 EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
150 //! Function computes contribution of directional light source
151 const char THE_FUNC_directionalLight[] =
152 EOL"void directionalLight (in int theId,"
153 EOL" in vec3 theNormal,"
154 EOL" in vec3 theView,"
155 EOL" in bool theIsFront)"
157 EOL" vec3 aLight = normalize (occLight_Position (theId).xyz);"
158 EOL" if (occLight_IsHeadlight (theId) == 0)"
160 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 0.0));"
163 EOL" vec3 aHalf = normalize (aLight + theView);"
165 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
166 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
167 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
169 EOL" float aSpecl = 0.0;"
170 EOL" if (aNdotL > 0.0)"
172 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
175 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL;"
176 EOL" Specular += occLight_Specular (theId).rgb * aSpecl;"
179 //! Process clipping planes in Fragment Shader.
180 //! Should be added at the beginning of the main() function.
181 const char THE_FRAG_CLIP_PLANES[] =
182 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)"
184 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
185 EOL" int aClipSpace = occClipPlaneSpaces[aPlaneIter];"
186 EOL" if (aClipSpace == OccEquationCoords_World)"
188 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz) + aClipEquation.w < 0.0)"
193 EOL" else if (aClipSpace == OccEquationCoords_View)"
195 EOL" if (dot (aClipEquation.xyz, Position.xyz) + aClipEquation.w < 0.0)"
204 // =======================================================================
205 // function : OpenGl_ShaderManager
206 // purpose : Creates new empty shader manager
207 // =======================================================================
208 OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
209 : myShadingModel (Visual3d_TOM_VERTEX),
210 myContext (theContext),
216 // =======================================================================
217 // function : ~OpenGl_ShaderManager
218 // purpose : Releases resources of shader manager
219 // =======================================================================
220 OpenGl_ShaderManager::~OpenGl_ShaderManager()
222 myProgramList.Clear();
225 // =======================================================================
228 // =======================================================================
229 void OpenGl_ShaderManager::clear()
231 myProgramList.Clear();
232 myLightPrograms.Nullify();
233 myFlatPrograms = OpenGl_SetOfShaderPrograms();
234 myMapOfLightPrograms.Clear();
235 myFontProgram.Nullify();
236 myBlitProgram.Nullify();
237 for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter)
239 myStereoPrograms[aModeIter].Nullify();
241 switchLightPrograms();
244 // =======================================================================
246 // purpose : Creates new shader program
247 // =======================================================================
248 Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
249 TCollection_AsciiString& theShareKey,
250 Handle(OpenGl_ShaderProgram)& theProgram)
252 theProgram.Nullify();
253 if (theProxy.IsNull())
255 return Standard_False;
258 theShareKey = theProxy->GetId();
259 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
261 if (theProgram->Share())
263 myProgramList.Append (theProgram);
265 return Standard_True;
268 theProgram = new OpenGl_ShaderProgram (theProxy);
269 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
271 theProgram->Release (myContext);
273 theProgram.Nullify();
274 return Standard_False;
277 myProgramList.Append (theProgram);
278 myContext->ShareResource (theShareKey, theProgram);
279 return Standard_True;
282 // =======================================================================
283 // function : Unregister
284 // purpose : Removes specified shader program from the manager
285 // =======================================================================
286 void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
287 Handle(OpenGl_ShaderProgram)& theProgram)
289 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
291 if (anIt.Value() == theProgram)
293 if (!theProgram->UnShare())
296 theProgram.Nullify();
300 myProgramList.Remove (anIt);
301 myMaterialStates.UnBind (theProgram);
306 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
309 myContext->DelayedRelease (theProgram);
310 theProgram.Nullify();
314 theProgram.Nullify();
315 myContext->ReleaseResource (anID, Standard_True);
319 // =======================================================================
320 // function : ShaderPrograms
321 // purpose : Returns list of registered shader programs
322 // =======================================================================
323 const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
325 return myProgramList;
328 // =======================================================================
330 // purpose : Returns true if no program objects are attached
331 // =======================================================================
332 Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
334 return myProgramList.IsEmpty();
337 // =======================================================================
338 // function : switchLightPrograms
340 // =======================================================================
341 void OpenGl_ShaderManager::switchLightPrograms()
343 TCollection_AsciiString aKey (myShadingModel == Visual3d_TOM_FRAGMENT ? "p_" : "g_");
344 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
347 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next())
349 switch (aLightIter.Value().Type)
351 case Visual3d_TOLS_AMBIENT:
352 break; // skip ambient
353 case Visual3d_TOLS_DIRECTIONAL:
356 case Visual3d_TOLS_POSITIONAL:
359 case Visual3d_TOLS_SPOT:
366 if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
368 myLightPrograms = new OpenGl_SetOfShaderPrograms();
369 myMapOfLightPrograms.Bind (aKey, myLightPrograms);
373 // =======================================================================
374 // function : UpdateLightSourceStateTo
375 // purpose : Updates state of OCCT light sources
376 // =======================================================================
377 void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights)
379 myLightSourceState.Set (theLights);
380 myLightSourceState.Update();
381 switchLightPrograms();
384 // =======================================================================
385 // function : SetShadingModel
387 // =======================================================================
388 void OpenGl_ShaderManager::SetShadingModel (const Visual3d_TypeOfModel theModel)
390 myShadingModel = theModel;
391 switchLightPrograms();
394 // =======================================================================
395 // function : SetProjectionState
396 // purpose : Sets new state of OCCT projection transform
397 // =======================================================================
398 void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix)
400 myProjectionState.Set (theProjectionMatrix);
401 myProjectionState.Update();
404 // =======================================================================
405 // function : SetModelWorldState
406 // purpose : Sets new state of OCCT model-world transform
407 // =======================================================================
408 void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix)
410 myModelWorldState.Set (theModelWorldMatrix);
411 myModelWorldState.Update();
414 // =======================================================================
415 // function : SetWorldViewState
416 // purpose : Sets new state of OCCT world-view transform
417 // =======================================================================
418 void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix)
420 myWorldViewState.Set (theWorldViewMatrix);
421 myWorldViewState.Update();
424 // =======================================================================
425 // function : LightSourceState
426 // purpose : Returns current state of OCCT light sources
427 // =======================================================================
428 const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const
430 return myLightSourceState;
433 // =======================================================================
434 // function : ProjectionState
435 // purpose : Returns current state of OCCT projection transform
436 // =======================================================================
437 const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const
439 return myProjectionState;
442 // =======================================================================
443 // function : ModelWorldState
444 // purpose : Returns current state of OCCT model-world transform
445 // =======================================================================
446 const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const
448 return myModelWorldState;
451 // =======================================================================
452 // function : WorldViewState
453 // purpose : Returns current state of OCCT world-view transform
454 // =======================================================================
455 const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const
457 return myWorldViewState;
460 //! Packed properties of light source
461 class OpenGl_ShaderLightParameters
466 OpenGl_Vec4 Position;
467 OpenGl_Vec4 Direction;
468 OpenGl_Vec4 Parameters;
470 //! Returns packed (serialized) representation of light source properties
471 const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
472 static Standard_Integer NbOfVec4() { return 4; }
476 //! Packed light source type information
477 class OpenGl_ShaderLightType
481 Standard_Integer Type;
482 Standard_Integer IsHeadlight;
484 //! Returns packed (serialized) representation of light source type
485 const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
486 static Standard_Integer NbOfVec2i() { return 1; }
490 // =======================================================================
491 // function : PushLightSourceState
492 // purpose : Pushes state of OCCT light sources to the program
493 // =======================================================================
494 void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
496 if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)
497 || !theProgram->IsValid())
502 OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[OpenGLMaxLights];
503 for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt)
505 aLightTypeArray[aLightIt].Type = -1;
508 const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights);
509 if (aLightsDefNb < 1)
511 theProgram->SetUniform (myContext,
512 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
514 theProgram->SetUniform (myContext,
515 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
516 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
517 theProgram->SetUniform (myContext,
518 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
519 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
520 aLightTypeArray[0].Packed());
521 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
522 delete[] aLightTypeArray;
526 OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb];
528 OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
529 Standard_Integer aLightsNb = 0;
530 for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next())
532 const OpenGl_Light& aLight = anIter.Value();
533 if (aLight.Type == Visual3d_TOLS_AMBIENT)
535 anAmbient += aLight.Color;
538 else if (aLightsNb >= OpenGLMaxLights)
543 OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb];
544 aLightType.Type = aLight.Type;
545 aLightType.IsHeadlight = aLight.IsHeadlight;
547 OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb];
548 aLightParams.Color = aLight.Color;
549 aLightParams.Position = aLight.Type == Visual3d_TOLS_DIRECTIONAL
552 if (aLight.Type == Visual3d_TOLS_SPOT)
554 aLightParams.Direction = aLight.Direction;
556 aLightParams.Parameters = aLight.Params;
560 theProgram->SetUniform (myContext,
561 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
563 theProgram->SetUniform (myContext,
564 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
566 theProgram->SetUniform (myContext,
567 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
568 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
569 aLightTypeArray[0].Packed());
572 theProgram->SetUniform (myContext,
573 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
574 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
575 aLightParamsArray[0].Packed());
577 delete[] aLightParamsArray;
578 delete[] aLightTypeArray;
580 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
583 // =======================================================================
584 // function : PushProjectionState
585 // purpose : Pushes state of OCCT projection transform to the program
586 // =======================================================================
587 void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
589 if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE))
594 theProgram->SetUniform (myContext,
595 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
596 myProjectionState.ProjectionMatrix());
598 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
599 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
601 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
604 theProgram->SetUniform (myContext,
605 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
606 myProjectionState.ProjectionMatrix(), true);
608 aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
609 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
611 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
614 theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
617 // =======================================================================
618 // function : PushModelWorldState
619 // purpose : Pushes state of OCCT model-world transform to the program
620 // =======================================================================
621 void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
623 if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
628 theProgram->SetUniform (myContext,
629 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
630 myModelWorldState.ModelWorldMatrix());
632 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
633 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
635 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
638 theProgram->SetUniform (myContext,
639 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
640 myModelWorldState.ModelWorldMatrix(), true);
642 aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
643 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
645 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
648 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
651 // =======================================================================
652 // function : PushWorldViewState
653 // purpose : Pushes state of OCCT world-view transform to the program
654 // =======================================================================
655 void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
657 if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
662 theProgram->SetUniform (myContext,
663 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
664 myWorldViewState.WorldViewMatrix());
666 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
667 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
669 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
672 theProgram->SetUniform (myContext,
673 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
674 myWorldViewState.WorldViewMatrix(), true);
676 aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
677 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
679 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
682 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
685 // =======================================================================
686 // function : UpdateClippingState
687 // purpose : Updates state of OCCT clipping planes
688 // =======================================================================
689 void OpenGl_ShaderManager::UpdateClippingState()
691 myClippingState.Update();
694 // =======================================================================
695 // function : RevertClippingState
696 // purpose : Reverts state of OCCT clipping planes
697 // =======================================================================
698 void OpenGl_ShaderManager::RevertClippingState()
700 myClippingState.Revert();
703 // =======================================================================
704 // function : PushClippingState
705 // purpose : Pushes state of OCCT clipping planes to the program
706 // =======================================================================
707 void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
709 if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
714 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
715 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
716 const GLint aLocSpaces = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_SPACES);
717 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION
718 && aLocSpaces == OpenGl_ShaderProgram::INVALID_LOCATION)
724 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
725 anIter.More(); anIter.Next())
727 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
728 if (!myContext->Clipping().IsEnabled (aPlane))
740 const Standard_Size MAX_CLIP_PLANES = 8;
741 OpenGl_Vec4* anEquations = new OpenGl_Vec4[MAX_CLIP_PLANES];
742 GLint* aSpaces = new GLint [MAX_CLIP_PLANES];
744 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
745 anIter.More(); anIter.Next())
747 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
748 if (!myContext->Clipping().IsEnabled (aPlane))
753 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
754 anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(),
755 (float) anEquation.y(),
756 (float) anEquation.z(),
757 (float) anEquation.w());
758 aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane);
762 theProgram->SetUniform (myContext,
763 theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT),
765 theProgram->SetUniform (myContext, aLocEquations, MAX_CLIP_PLANES, anEquations);
766 theProgram->SetUniform (myContext, aLocSpaces, MAX_CLIP_PLANES, aSpaces);
768 delete[] anEquations;
772 // =======================================================================
773 // function : UpdateMaterialStateTo
774 // purpose : Updates state of OCCT material for specified program
775 // =======================================================================
776 void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram,
777 const OpenGl_Element* theAspect)
779 if (myMaterialStates.IsBound (theProgram))
781 OpenGl_MaterialState& aState = myMaterialStates.ChangeFind (theProgram);
782 aState.Set (theAspect);
787 myMaterialStates.Bind (theProgram, OpenGl_MaterialState (theAspect));
788 myMaterialStates.ChangeFind (theProgram).Update();
792 // =======================================================================
793 // function : ResetMaterialStates
794 // purpose : Resets state of OCCT material for all programs
795 // =======================================================================
796 void OpenGl_ShaderManager::ResetMaterialStates()
798 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
800 anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0);
804 // =======================================================================
805 // function : MaterialState
806 // purpose : Returns state of OCCT material for specified program
807 // =======================================================================
808 const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
810 if (!myMaterialStates.IsBound (theProgram))
813 return &myMaterialStates.Find (theProgram);
816 // =======================================================================
817 // function : SurfaceDetailState
818 // purpose : Returns current state of OCCT surface detail
819 // =======================================================================
820 const OpenGl_SurfaceDetailState& OpenGl_ShaderManager::SurfaceDetailState() const
822 return mySurfaceDetailState;
825 // =======================================================================
826 // function : UpdateSurfaceDetailStateTo
827 // purpose : Updates state of OCCT surface detail
828 // =======================================================================
829 void OpenGl_ShaderManager::UpdateSurfaceDetailStateTo (const Visual3d_TypeOfSurfaceDetail theDetail)
831 mySurfaceDetailState.Set (theDetail);
832 mySurfaceDetailState.Update();
838 static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f);
840 // =======================================================================
841 // function : PushAspectFace
843 // =======================================================================
844 static void PushAspectFace (const Handle(OpenGl_Context)& theCtx,
845 const Handle(OpenGl_ShaderProgram)& theProgram,
846 const OpenGl_AspectFace* theAspect)
848 theProgram->SetUniform (theCtx,
849 theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
850 theAspect->DoTextureMap());
851 theProgram->SetUniform (theCtx,
852 theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),
853 0 /* GL_TEXTURE0 */);
854 theProgram->SetUniform (theCtx,
855 theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
856 theAspect->DistinguishingMode());
858 OpenGl_Material aParams;
859 for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
861 const GLint aLoc = theProgram->GetStateLocation (anIndex == 0
862 ? OpenGl_OCCT_FRONT_MATERIAL
863 : OpenGl_OCCT_BACK_MATERIAL);
864 if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
869 aParams.Init (anIndex == 0 || theAspect->DistinguishingMode() != TOn
870 ? theAspect->IntFront()
871 : theAspect->IntBack());
872 theProgram->SetUniform (theCtx, aLoc, OpenGl_Material::NbOfVec4(),
877 // =======================================================================
878 // function : PushAspectLine
880 // =======================================================================
881 static void PushAspectLine (const Handle(OpenGl_Context)& theCtx,
882 const Handle(OpenGl_ShaderProgram)& theProgram,
883 const OpenGl_AspectLine* theAspect)
885 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOff);
886 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
888 const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
889 theAspect->Color().rgb[1],
890 theAspect->Color().rgb[2],
891 theAspect->Color().rgb[3]);
892 OpenGl_Vec4 aParams[5];
893 aParams[0] = THE_COLOR_BLACK_VEC4;
894 aParams[1] = THE_COLOR_BLACK_VEC4;
895 aParams[2] = aDiffuse;
896 aParams[3] = THE_COLOR_BLACK_VEC4;
897 aParams[4].x() = 0.0f; // shininess
898 aParams[4].y() = 0.0f; // transparency
899 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
903 // =======================================================================
904 // function : PushAspectText
906 // =======================================================================
907 static void PushAspectText (const Handle(OpenGl_Context)& theCtx,
908 const Handle(OpenGl_ShaderProgram)& theProgram,
909 const OpenGl_AspectText* theAspect)
911 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn);
912 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
913 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */);
915 OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
916 theAspect->Color().rgb[1],
917 theAspect->Color().rgb[2],
918 theAspect->Color().rgb[3]);
919 if (theAspect->DisplayType() == Aspect_TODT_DEKALE
920 || theAspect->DisplayType() == Aspect_TODT_SUBTITLE)
922 aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0],
923 theAspect->SubtitleColor().rgb[1],
924 theAspect->SubtitleColor().rgb[2],
925 theAspect->SubtitleColor().rgb[3]);
928 OpenGl_Vec4 aParams[5];
929 aParams[0] = THE_COLOR_BLACK_VEC4;
930 aParams[1] = THE_COLOR_BLACK_VEC4;
931 aParams[2] = aDiffuse;
932 aParams[3] = THE_COLOR_BLACK_VEC4;
933 aParams[4].x() = 0.0f; // shininess
934 aParams[4].y() = 0.0f; // transparency
935 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
939 // =======================================================================
940 // function : PushAspectMarker
942 // =======================================================================
943 static void PushAspectMarker (const Handle(OpenGl_Context)& theCtx,
944 const Handle(OpenGl_ShaderProgram)& theProgram,
945 const OpenGl_AspectMarker* theAspect)
947 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn);
948 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
949 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */);
951 const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
952 theAspect->Color().rgb[1],
953 theAspect->Color().rgb[2],
954 theAspect->Color().rgb[3]);
955 OpenGl_Vec4 aParams[5];
956 aParams[0] = THE_COLOR_BLACK_VEC4;
957 aParams[1] = THE_COLOR_BLACK_VEC4;
958 aParams[2] = aDiffuse;
959 aParams[3] = THE_COLOR_BLACK_VEC4;
960 aParams[4].x() = 0.0f; // shininess
961 aParams[4].y() = 0.0f; // transparency
962 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
966 }; // nameless namespace
968 // =======================================================================
969 // function : PushMaterialState
970 // purpose : Pushes current state of OCCT material to the program
971 // =======================================================================
972 void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
974 if (!myMaterialStates.IsBound (theProgram))
979 const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram);
980 if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE))
985 if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectFace))
987 PushAspectFace (myContext, theProgram, dynamic_cast<const OpenGl_AspectFace*> (aState.Aspect()));
989 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectLine))
991 PushAspectLine (myContext, theProgram, dynamic_cast<const OpenGl_AspectLine*> (aState.Aspect()));
993 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectText))
995 PushAspectText (myContext, theProgram, dynamic_cast<const OpenGl_AspectText*> (aState.Aspect()));
997 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectMarker))
999 PushAspectMarker (myContext, theProgram, dynamic_cast<const OpenGl_AspectMarker*> (aState.Aspect()));
1002 theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index());
1005 // =======================================================================
1006 // function : PushState
1007 // purpose : Pushes state of OCCT graphics parameters to the program
1008 // =======================================================================
1009 void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1011 PushClippingState (theProgram);
1012 PushMaterialState (theProgram);
1013 PushWorldViewState (theProgram);
1014 PushModelWorldState (theProgram);
1015 PushProjectionState (theProgram);
1016 PushLightSourceState (theProgram);
1019 // =======================================================================
1020 // function : prepareStdProgramFont
1022 // =======================================================================
1023 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
1025 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1026 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
1027 + THE_VARY_TexCoord_OUT
1030 EOL" TexCoord = occTexCoord.st;"
1031 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1034 TCollection_AsciiString
1035 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).a; }";
1036 #if !defined(GL_ES_VERSION_2_0)
1037 if (myContext->core11 == NULL)
1039 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).r; }";
1043 TCollection_AsciiString aSrcFrag = TCollection_AsciiString() +
1044 + THE_VARY_TexCoord_IN
1048 EOL" vec4 aColor = occColor;"
1049 EOL" aColor.a *= getAlpha();"
1050 EOL" if (aColor.a <= 0.285) discard;"
1051 EOL" occFragColor = aColor;"
1054 #if !defined(GL_ES_VERSION_2_0)
1055 if (myContext->core32 != NULL)
1057 aProgramSrc->SetHeader ("#version 150");
1060 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1061 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1062 TCollection_AsciiString aKey;
1063 if (!Create (aProgramSrc, aKey, myFontProgram))
1065 myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1066 return Standard_False;
1068 return Standard_True;
1071 // =======================================================================
1072 // function : prepareStdProgramFboBlit
1074 // =======================================================================
1075 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit()
1077 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1078 TCollection_AsciiString aSrcVert =
1079 EOL"THE_SHADER_OUT vec2 TexCoord;"
1082 EOL" TexCoord = occVertex.zw;"
1083 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1086 TCollection_AsciiString aSrcFrag =
1087 EOL"uniform sampler2D uColorSampler;"
1088 EOL"uniform sampler2D uDepthSampler;"
1090 EOL"THE_SHADER_IN vec2 TexCoord;"
1094 EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;"
1095 EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);"
1098 #if defined(GL_ES_VERSION_2_0)
1099 if (myContext->IsGlGreaterEqual (3, 0))
1101 aProgramSrc->SetHeader ("#version 300 es");
1105 // there is no way to draw into depth buffer
1107 EOL"uniform sampler2D uColorSampler;"
1109 EOL"THE_SHADER_IN vec2 TexCoord;"
1113 EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);"
1117 if (myContext->core32 != NULL)
1119 aProgramSrc->SetHeader ("#version 150");
1122 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1123 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1124 TCollection_AsciiString aKey;
1125 if (!Create (aProgramSrc, aKey, myBlitProgram))
1127 myBlitProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1128 return Standard_False;
1131 myContext->BindProgram (myBlitProgram);
1132 myBlitProgram->SetSampler (myContext, "uColorSampler", 0);
1133 myBlitProgram->SetSampler (myContext, "uDepthSampler", 1);
1134 myContext->BindProgram (NULL);
1135 return Standard_True;
1138 // =======================================================================
1139 // function : prepareStdProgramFlat
1141 // =======================================================================
1142 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_ShaderProgram)& theProgram,
1143 const Standard_Integer theBits)
1145 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1146 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
1147 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
1148 TCollection_AsciiString aSrcFragMainGetColor = EOL" occFragColor = getColor();";
1149 if ((theBits & OpenGl_PO_Point) != 0)
1151 #if defined(GL_ES_VERSION_2_0)
1152 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1154 if ((theBits & OpenGl_PO_TextureA) != 0)
1156 TCollection_AsciiString
1157 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, gl_PointCoord).a; }";
1158 #if !defined(GL_ES_VERSION_2_0)
1159 if (myContext->core11 == NULL)
1161 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, gl_PointCoord).r; }";
1165 aSrcFragGetColor = aSrcGetAlpha
1166 + EOL"vec4 getColor(void)"
1168 EOL" vec4 aColor = occColor;"
1169 EOL" aColor.a *= getAlpha();"
1170 EOL" return aColor;"
1173 aSrcFragMainGetColor =
1174 EOL" vec4 aColor = getColor();"
1175 EOL" if (aColor.a <= 0.1) discard;"
1176 EOL" occFragColor = aColor;";
1178 else if ((theBits & OpenGl_PO_TextureRGB) != 0)
1181 EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, gl_PointCoord); }";
1182 aSrcFragMainGetColor =
1183 EOL" vec4 aColor = getColor();"
1184 EOL" if (aColor.a <= 0.1) discard;"
1185 EOL" occFragColor = aColor;";
1190 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1192 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1193 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1194 aSrcVertExtraMain +=
1195 EOL" TexCoord = occTexCoord.st;";
1198 EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, TexCoord.st); }";
1200 else if ((theBits & OpenGl_PO_TextureEnv) != 0)
1202 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1203 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1205 aSrcVertExtraFunc = THE_FUNC_transformNormal;
1207 aSrcVertExtraMain +=
1208 EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1209 EOL" vec3 aNormal = transformNormal (occNormal);"
1210 EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);"
1211 EOL" aReflect.z += 1.0;"
1212 EOL" TexCoord = aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5);";
1215 EOL"vec4 getColor(void) { return occTexture2D (occActiveSampler, TexCoord.st); }";
1218 if ((theBits & OpenGl_PO_VertColor) != 0)
1220 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
1221 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1222 aSrcFragExtraOut += EOL"THE_SHADER_IN vec4 VertColor;";
1223 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
1225 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1228 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1229 EOL"THE_SHADER_OUT vec4 Position;";
1231 EOL"THE_SHADER_IN vec4 PositionWorld;"
1232 EOL"THE_SHADER_IN vec4 Position;";
1233 aSrcVertExtraMain +=
1234 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1235 EOL" Position = occWorldViewMatrix * PositionWorld;";
1236 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1239 TCollection_AsciiString aSrcVertEndMain;
1240 if ((theBits & OpenGl_PO_StippleLine) != 0)
1242 bool hasCaps = false;
1243 #if defined(GL_ES_VERSION_2_0)
1244 if (myContext->IsGlGreaterEqual (3, 0))
1246 aProgramSrc->SetHeader ("#version 300 es");
1250 if (myContext->core32 != NULL)
1252 aProgramSrc->SetHeader ("#version 150");
1260 EOL"THE_SHADER_OUT vec2 ScreenSpaceCoord;";
1262 EOL"THE_SHADER_IN vec2 ScreenSpaceCoord;"
1263 EOL"uniform int uPattern;"
1264 EOL"uniform float uFactor;";
1266 EOL" ScreenSpaceCoord = gl_Position.xy / gl_Position.w;";
1267 aSrcFragMainGetColor =
1268 EOL" float anAngle = atan (dFdx (ScreenSpaceCoord.x), dFdy (ScreenSpaceCoord.y));"
1269 EOL" float aRotatePoint = gl_FragCoord.x * sin (anAngle) + gl_FragCoord.y * cos (anAngle);"
1270 EOL" uint aBit = uint (floor (aRotatePoint / uFactor + 0.5)) & 15U;"
1271 EOL" if ((uint (uPattern) & (1U << aBit)) == 0U) discard;"
1272 EOL" vec4 aColor = getColor();"
1273 EOL" if (aColor.a <= 0.1) discard;"
1274 EOL" occFragColor = aColor;";
1278 const TCollection_ExtendedString aWarnMessage =
1279 "Warning: stipple lines in GLSL will be ignored.";
1280 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1281 GL_DEBUG_TYPE_PORTABILITY_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aWarnMessage);
1291 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1301 + aSrcFragMainGetColor
1304 #if !defined(GL_ES_VERSION_2_0)
1305 if (myContext->core32 != NULL)
1307 aProgramSrc->SetHeader ("#version 150");
1310 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1311 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1313 TCollection_AsciiString aKey;
1314 if (!Create (aProgramSrc, aKey, theProgram))
1316 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1317 return Standard_False;
1319 return Standard_True;
1322 // =======================================================================
1323 // function : stdComputeLighting
1325 // =======================================================================
1326 TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (const Standard_Boolean theHasVertColor)
1328 bool aLightsMap[Visual3d_TOLS_SPOT + 1] = { false, false, false, false };
1329 TCollection_AsciiString aLightsFunc, aLightsLoop;
1330 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
1331 if (aLights != NULL)
1333 Standard_Integer anIndex = 0;
1334 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next(), ++anIndex)
1336 switch (aLightIter.Value().Type)
1338 case Visual3d_TOLS_AMBIENT:
1340 break; // skip ambient
1341 case Visual3d_TOLS_DIRECTIONAL:
1342 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
1344 case Visual3d_TOLS_POSITIONAL:
1345 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1347 case Visual3d_TOLS_SPOT:
1348 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1352 bool& aTypeBit = aLightsMap[aLightIter.Value().Type];
1359 switch (aLightIter.Value().Type)
1361 case Visual3d_TOLS_AMBIENT: break;
1362 case Visual3d_TOLS_DIRECTIONAL: aLightsFunc += THE_FUNC_directionalLight; break;
1363 case Visual3d_TOLS_POSITIONAL: aLightsFunc += THE_FUNC_pointLight; break;
1364 case Visual3d_TOLS_SPOT: aLightsFunc += THE_FUNC_spotLight; break;
1369 TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();";
1370 TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();";
1371 if (theHasVertColor)
1373 aGetMatAmbient = "getVertColor();";
1374 aGetMatDiffuse = "getVertColor();";
1377 return TCollection_AsciiString()
1381 EOL"vec4 computeLighting (in vec3 theNormal,"
1382 EOL" in vec3 theView,"
1383 EOL" in vec4 thePoint,"
1384 EOL" in bool theIsFront)"
1386 EOL" Ambient = occLightAmbient.rgb;"
1387 EOL" Diffuse = vec3 (0.0);"
1388 EOL" Specular = vec3 (0.0);"
1389 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
1391 + EOL" vec4 aMaterialAmbient = " + aGetMatAmbient
1392 + EOL" vec4 aMaterialDiffuse = " + aGetMatDiffuse
1393 + EOL" vec4 aMaterialSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
1394 EOL" vec4 aMaterialEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
1395 EOL" return vec4 (Ambient, 1.0) * aMaterialAmbient"
1396 EOL" + vec4 (Diffuse, 1.0) * aMaterialDiffuse"
1397 EOL" + vec4 (Specular, 1.0) * aMaterialSpecular"
1398 EOL" + aMaterialEmission;"
1402 // =======================================================================
1403 // function : prepareStdProgramGouraud
1405 // =======================================================================
1406 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
1407 const Standard_Integer theBits)
1409 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1410 TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
1411 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
1412 if ((theBits & OpenGl_PO_Point) != 0)
1414 #if defined(GL_ES_VERSION_2_0)
1415 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1418 if ((theBits & OpenGl_PO_VertColor) != 0)
1420 aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
1422 if ((theBits & OpenGl_PO_Point) != 0)
1424 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1427 EOL"vec4 getColor(void)"
1429 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
1430 EOL" return occTexture2D(occActiveSampler, gl_PointCoord) * aColor;"
1436 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1438 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1439 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1440 aSrcVertExtraMain +=
1441 EOL" TexCoord = occTexCoord.st;";
1444 EOL"vec4 getColor(void)"
1446 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
1447 EOL" return occTexture2D(occActiveSampler, TexCoord.st) * aColor;"
1451 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1454 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1455 EOL"THE_SHADER_OUT vec4 Position;";
1457 EOL"THE_SHADER_IN vec4 PositionWorld;"
1458 EOL"THE_SHADER_IN vec4 Position;";
1459 aSrcVertExtraMain +=
1460 EOL" PositionWorld = aPositionWorld;"
1461 EOL" Position = aPosition;";
1462 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1465 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
1466 aSrcVert = TCollection_AsciiString()
1467 + THE_FUNC_transformNormal
1472 EOL"THE_SHADER_OUT vec4 FrontColor;"
1473 EOL"THE_SHADER_OUT vec4 BackColor;"
1478 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
1479 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
1480 EOL" vec3 aNormal = transformNormal (occNormal);"
1481 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
1482 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
1483 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
1485 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1488 aSrcFrag = TCollection_AsciiString()
1489 + EOL"THE_SHADER_IN vec4 FrontColor;"
1490 EOL"THE_SHADER_IN vec4 BackColor;"
1496 + EOL" occFragColor = getColor();"
1499 #if !defined(GL_ES_VERSION_2_0)
1500 if (myContext->core32 != NULL)
1502 aProgramSrc->SetHeader ("#version 150");
1505 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1506 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1507 TCollection_AsciiString aKey;
1508 if (!Create (aProgramSrc, aKey, theProgram))
1510 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1511 return Standard_False;
1513 return Standard_True;
1516 // =======================================================================
1517 // function : prepareStdProgramPhong
1519 // =======================================================================
1520 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
1521 const Standard_Integer theBits)
1523 #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
1525 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1526 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain;
1527 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
1528 if ((theBits & OpenGl_PO_Point) != 0)
1530 #if defined(GL_ES_VERSION_2_0)
1531 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1534 if ((theBits & OpenGl_PO_VertColor) != 0)
1536 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
1537 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1538 aSrcFragGetVertColor = EOL"THE_SHADER_IN vec4 VertColor;"
1539 EOL"vec4 getVertColor(void) { return VertColor; }";
1542 if ((theBits & OpenGl_PO_Point) != 0)
1544 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1547 EOL"vec4 getColor(void)"
1549 EOL" vec4 aColor = " thePhongCompLight ";"
1550 EOL" return occTexture2D(occActiveSampler, gl_PointCoord) * aColor;"
1556 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1558 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1559 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1560 aSrcVertExtraMain +=
1561 EOL" TexCoord = occTexCoord.st;";
1564 EOL"vec4 getColor(void)"
1566 EOL" vec4 aColor = " thePhongCompLight ";"
1567 EOL" return occTexture2D(occActiveSampler, TexCoord.st) * aColor;"
1572 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1574 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1577 aSrcVert = TCollection_AsciiString()
1578 + THE_FUNC_transformNormal
1580 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1581 EOL"THE_SHADER_OUT vec4 Position;"
1582 EOL"THE_SHADER_OUT vec3 Normal;"
1583 EOL"THE_SHADER_OUT vec3 View;"
1588 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1589 EOL" Position = occWorldViewMatrix * PositionWorld;"
1590 EOL" Normal = transformNormal (occNormal);"
1591 EOL" View = vec3 (0.0, 0.0, 1.0);"
1593 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1596 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
1597 aSrcFrag = TCollection_AsciiString()
1598 + EOL"THE_SHADER_IN vec4 PositionWorld;"
1599 EOL"THE_SHADER_IN vec4 Position;"
1600 EOL"THE_SHADER_IN vec3 Normal;"
1601 EOL"THE_SHADER_IN vec3 View;"
1604 + aSrcFragGetVertColor
1611 + EOL" occFragColor = getColor();"
1614 #if !defined(GL_ES_VERSION_2_0)
1615 if (myContext->core32 != NULL)
1617 aProgramSrc->SetHeader ("#version 150");
1620 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1621 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1622 TCollection_AsciiString aKey;
1623 if (!Create (aProgramSrc, aKey, theProgram))
1625 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1626 return Standard_False;
1628 return Standard_True;
1631 // =======================================================================
1632 // function : prepareStdProgramStereo
1634 // =======================================================================
1635 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
1636 const Graphic3d_StereoMode theStereoMode)
1638 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1639 TCollection_AsciiString aSrcVert =
1640 EOL"THE_SHADER_OUT vec2 TexCoord;"
1643 EOL" TexCoord = occVertex.zw;"
1644 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1647 TCollection_AsciiString aSrcFrag;
1648 switch (theStereoMode)
1650 case Graphic3d_StereoMode_Anaglyph:
1653 EOL"uniform sampler2D uLeftSampler;"
1654 EOL"uniform sampler2D uRightSampler;"
1656 EOL"uniform mat4 uMultL;"
1657 EOL"uniform mat4 uMultR;"
1659 EOL"vec4 THE_POW_UP = vec4 (2.2, 2.2, 2.2, 1.0);"
1660 EOL"vec4 THE_POW_DOWN = 1.0 / THE_POW_UP;"
1662 EOL"THE_SHADER_IN vec2 TexCoord;"
1666 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1667 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1668 EOL" aColorL = pow (aColorL, THE_POW_UP);" // normalize
1669 EOL" aColorR = pow (aColorR, THE_POW_UP);"
1670 EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;"
1671 EOL" occFragColor = pow (aColor, THE_POW_DOWN);"
1675 case Graphic3d_StereoMode_RowInterlaced:
1678 EOL"uniform sampler2D uLeftSampler;"
1679 EOL"uniform sampler2D uRightSampler;"
1681 EOL"THE_SHADER_IN vec2 TexCoord;"
1685 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1686 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1687 EOL" if (int (mod (gl_FragCoord.y + 1.5, 2.0)) == 1)"
1689 EOL" occFragColor = aColorL;"
1693 EOL" occFragColor = aColorR;"
1698 case Graphic3d_StereoMode_ColumnInterlaced:
1701 EOL"uniform sampler2D uLeftSampler;"
1702 EOL"uniform sampler2D uRightSampler;"
1704 EOL"THE_SHADER_IN vec2 TexCoord;"
1708 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1709 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1710 EOL" if (int (mod (gl_FragCoord.x + 1.5, 2.0)) != 1)"
1712 EOL" occFragColor = aColorL;"
1716 EOL" occFragColor = aColorR;"
1721 case Graphic3d_StereoMode_ChessBoard:
1724 EOL"uniform sampler2D uLeftSampler;"
1725 EOL"uniform sampler2D uRightSampler;"
1727 EOL"THE_SHADER_IN vec2 TexCoord;"
1731 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1732 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1733 EOL" bool isEvenX = int(mod(floor(gl_FragCoord.x + 1.5), 2.0)) == 1;"
1734 EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y + 1.5), 2.0)) != 1;"
1735 EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))"
1737 EOL" occFragColor = aColorL;"
1741 EOL" occFragColor = aColorR;"
1746 case Graphic3d_StereoMode_SideBySide:
1749 EOL"uniform sampler2D uLeftSampler;"
1750 EOL"uniform sampler2D uRightSampler;"
1752 EOL"THE_SHADER_IN vec2 TexCoord;"
1756 EOL" vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);"
1757 EOL" if (TexCoord.x > 0.5)"
1759 EOL" aTexCoord.x -= 1.0;"
1761 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
1762 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
1763 EOL" if (TexCoord.x <= 0.5)"
1765 EOL" occFragColor = aColorL;"
1769 EOL" occFragColor = aColorR;"
1774 case Graphic3d_StereoMode_OverUnder:
1777 EOL"uniform sampler2D uLeftSampler;"
1778 EOL"uniform sampler2D uRightSampler;"
1780 EOL"THE_SHADER_IN vec2 TexCoord;"
1784 EOL" vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);"
1785 EOL" if (TexCoord.y > 0.5)"
1787 EOL" aTexCoord.y -= 1.0;"
1789 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
1790 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
1791 EOL" if (TexCoord.y <= 0.5)"
1793 EOL" occFragColor = aColorL;"
1797 EOL" occFragColor = aColorR;"
1802 case Graphic3d_StereoMode_QuadBuffer:
1803 case Graphic3d_StereoMode_SoftPageFlip:
1806 /*const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[Graphic3d_StereoMode_QuadBuffer];
1807 if (!aProgram.IsNull())
1809 return aProgram->IsValid();
1812 EOL"uniform sampler2D uLeftSampler;"
1813 EOL"uniform sampler2D uRightSampler;"
1815 EOL"THE_SHADER_IN vec2 TexCoord;"
1819 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1820 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1821 EOL" aColorL.b = 0.0;"
1822 EOL" aColorL.g = 0.0;"
1823 EOL" aColorR.r = 0.0;"
1824 EOL" occFragColor = aColorL + aColorR;"
1830 #if !defined(GL_ES_VERSION_2_0)
1831 if (myContext->core32 != NULL)
1833 aProgramSrc->SetHeader ("#version 150");
1837 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1838 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1839 TCollection_AsciiString aKey;
1840 if (!Create (aProgramSrc, aKey, theProgram))
1842 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1843 return Standard_False;
1846 myContext->BindProgram (theProgram);
1847 theProgram->SetSampler (myContext, "uLeftSampler", 0);
1848 theProgram->SetSampler (myContext, "uRightSampler", 1);
1849 myContext->BindProgram (NULL);
1850 return Standard_True;
1853 // =======================================================================
1854 // function : bindProgramWithState
1856 // =======================================================================
1857 Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram,
1858 const OpenGl_Element* theAspect)
1860 if (!myContext->BindProgram (theProgram))
1862 return Standard_False;
1864 theProgram->ApplyVariables (myContext);
1866 const OpenGl_MaterialState* aMaterialState = MaterialState (theProgram);
1867 if (aMaterialState == NULL || aMaterialState->Aspect() != theAspect)
1869 UpdateMaterialStateTo (theProgram, theAspect);
1872 PushState (theProgram);
1873 return Standard_True;