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>
31 IMPLEMENT_STANDARD_HANDLE (OpenGl_SetOfShaderPrograms, Standard_Transient)
32 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_SetOfShaderPrograms, Standard_Transient)
34 IMPLEMENT_STANDARD_HANDLE (OpenGl_ShaderManager, Standard_Transient)
35 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager, Standard_Transient)
42 //! Definition of VertColor varying.
43 const char THE_VARY_TexCoord_OUT[] =
44 EOL"THE_SHADER_OUT vec2 TexCoord;";
45 const char THE_VARY_TexCoord_IN[] =
46 EOL"THE_SHADER_IN vec2 TexCoord;";
48 //! Auxiliary function to transform normal
49 const char THE_FUNC_transformNormal[] =
50 EOL"vec3 transformNormal (in vec3 theNormal)"
52 EOL" vec4 aResult = occWorldViewMatrixInverseTranspose"
53 EOL" * occModelWorldMatrixInverseTranspose"
54 EOL" * vec4 (theNormal, 0.0);"
55 EOL" return normalize (aResult.xyz);"
58 //! Global shader variable for color definition with lighting enabled.
59 const char THE_FUNC_lightDef[] =
60 EOL"vec3 Ambient;" //!< Ambient contribution of light sources
61 EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources
62 EOL"vec3 Specular;"; //!< Specular contribution of light sources
64 //! Function computes contribution of isotropic point light source
65 const char THE_FUNC_pointLight[] =
66 EOL"void pointLight (in int theId,"
67 EOL" in vec3 theNormal,"
68 EOL" in vec3 theView,"
69 EOL" in vec3 thePoint,"
70 EOL" in bool theIsFront)"
72 EOL" vec3 aLight = occLight_Position (theId).xyz;"
73 EOL" if (occLight_IsHeadlight (theId) == 0)"
75 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));"
77 EOL" aLight -= thePoint;"
79 EOL" float aDist = length (aLight);"
80 EOL" aLight = aLight * (1.0 / aDist);"
82 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
83 EOL" + occLight_LinearAttenuation (theId) * aDist);"
85 EOL" vec3 aHalf = normalize (aLight + theView);"
87 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
88 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
89 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
91 EOL" float aSpecl = 0.0;"
92 EOL" if (aNdotL > 0.0)"
94 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
97 EOL"Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
98 EOL"Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
101 //! Function computes contribution of spotlight source
102 const char THE_FUNC_spotLight[] =
103 EOL"void spotLight (in int theId,"
104 EOL" in vec3 theNormal,"
105 EOL" in vec3 theView,"
106 EOL" in vec3 thePoint,"
107 EOL" in bool theIsFront)"
109 EOL" vec3 aLight = occLight_Position (theId).xyz;"
110 EOL" vec3 aSpotDir = occLight_SpotDirection (theId).xyz;"
111 EOL" if (occLight_IsHeadlight (theId) == 0)"
113 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));"
114 EOL" aSpotDir = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aSpotDir, 0.0));"
116 EOL" aLight -= thePoint;"
118 EOL" float aDist = length (aLight);"
119 EOL" aLight = aLight * (1.0 / aDist);"
121 EOL" aSpotDir = normalize (aSpotDir);"
123 EOL" float aCosA = dot (aSpotDir, -aLight);"
124 EOL" if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
129 EOL" float anExponent = occLight_SpotExponent (theId);"
130 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
131 EOL" + occLight_LinearAttenuation (theId) * aDist);"
132 EOL" if (anExponent > 0.0)"
134 EOL" anAtten *= pow (aCosA, anExponent * 128.0);"
137 EOL" vec3 aHalf = normalize (aLight + theView);"
139 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
140 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
141 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
143 EOL" float aSpecl = 0.0;"
144 EOL" if (aNdotL > 0.0)"
146 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
149 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
150 EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
153 //! Function computes contribution of directional light source
154 const char THE_FUNC_directionalLight[] =
155 EOL"void directionalLight (in int theId,"
156 EOL" in vec3 theNormal,"
157 EOL" in vec3 theView,"
158 EOL" in bool theIsFront)"
160 EOL" vec3 aLight = normalize (occLight_Position (theId).xyz);"
161 EOL" if (occLight_IsHeadlight (theId) == 0)"
163 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 0.0));"
166 EOL" vec3 aHalf = normalize (aLight + theView);"
168 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
169 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
170 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
172 EOL" float aSpecl = 0.0;"
173 EOL" if (aNdotL > 0.0)"
175 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
178 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL;"
179 EOL" Specular += occLight_Specular (theId).rgb * aSpecl;"
182 //! Process clipping planes in Fragment Shader.
183 //! Should be added at the beginning of the main() function.
184 const char THE_FRAG_CLIP_PLANES[] =
185 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)"
187 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
188 EOL" int aClipSpace = occClipPlaneSpaces[aPlaneIter];"
189 EOL" if (aClipSpace == OccEquationCoords_World)"
191 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz) + aClipEquation.w < 0.0)"
196 EOL" else if (aClipSpace == OccEquationCoords_View)"
198 EOL" if (dot (aClipEquation.xyz, Position.xyz) + aClipEquation.w < 0.0)"
207 // =======================================================================
208 // function : OpenGl_ShaderManager
209 // purpose : Creates new empty shader manager
210 // =======================================================================
211 OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
212 : myShadingModel (Visual3d_TOM_VERTEX),
213 myContext (theContext),
219 // =======================================================================
220 // function : ~OpenGl_ShaderManager
221 // purpose : Releases resources of shader manager
222 // =======================================================================
223 OpenGl_ShaderManager::~OpenGl_ShaderManager()
225 myProgramList.Clear();
228 // =======================================================================
231 // =======================================================================
232 void OpenGl_ShaderManager::clear()
234 myProgramList.Clear();
235 myLightPrograms.Nullify();
236 myFlatPrograms = OpenGl_SetOfShaderPrograms();
237 myMapOfLightPrograms.Clear();
238 myFontProgram.Nullify();
239 myBlitProgram.Nullify();
240 for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter)
242 myStereoPrograms[aModeIter].Nullify();
244 switchLightPrograms();
247 // =======================================================================
249 // purpose : Creates new shader program
250 // =======================================================================
251 Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
252 TCollection_AsciiString& theShareKey,
253 Handle(OpenGl_ShaderProgram)& theProgram)
255 theProgram.Nullify();
256 if (theProxy.IsNull())
258 return Standard_False;
261 theShareKey = theProxy->GetId();
262 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
264 if (theProgram->Share())
266 myProgramList.Append (theProgram);
268 return Standard_True;
271 theProgram = new OpenGl_ShaderProgram (theProxy);
272 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
274 theProgram->Release (myContext);
276 theProgram.Nullify();
277 return Standard_False;
280 myProgramList.Append (theProgram);
281 myContext->ShareResource (theShareKey, theProgram);
282 return Standard_True;
285 // =======================================================================
286 // function : Unregister
287 // purpose : Removes specified shader program from the manager
288 // =======================================================================
289 void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
290 Handle(OpenGl_ShaderProgram)& theProgram)
292 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
294 if (anIt.Value() == theProgram)
296 if (!theProgram->UnShare())
299 theProgram.Nullify();
303 myProgramList.Remove (anIt);
304 myMaterialStates.UnBind (theProgram);
309 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
312 myContext->DelayedRelease (theProgram);
313 theProgram.Nullify();
317 theProgram.Nullify();
318 myContext->ReleaseResource (anID, Standard_True);
322 // =======================================================================
323 // function : ShaderPrograms
324 // purpose : Returns list of registered shader programs
325 // =======================================================================
326 const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
328 return myProgramList;
331 // =======================================================================
333 // purpose : Returns true if no program objects are attached
334 // =======================================================================
335 Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
337 return myProgramList.IsEmpty();
340 // =======================================================================
341 // function : switchLightPrograms
343 // =======================================================================
344 void OpenGl_ShaderManager::switchLightPrograms()
346 TCollection_AsciiString aKey (myShadingModel == Visual3d_TOM_FRAGMENT ? "p_" : "g_");
347 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
350 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next())
352 switch (aLightIter.Value().Type)
354 case Visual3d_TOLS_AMBIENT:
355 break; // skip ambient
356 case Visual3d_TOLS_DIRECTIONAL:
359 case Visual3d_TOLS_POSITIONAL:
362 case Visual3d_TOLS_SPOT:
369 if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
371 myLightPrograms = new OpenGl_SetOfShaderPrograms();
372 myMapOfLightPrograms.Bind (aKey, myLightPrograms);
376 // =======================================================================
377 // function : UpdateLightSourceStateTo
378 // purpose : Updates state of OCCT light sources
379 // =======================================================================
380 void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights)
382 myLightSourceState.Set (theLights);
383 myLightSourceState.Update();
384 switchLightPrograms();
387 // =======================================================================
388 // function : SetShadingModel
390 // =======================================================================
391 void OpenGl_ShaderManager::SetShadingModel (const Visual3d_TypeOfModel theModel)
393 myShadingModel = theModel;
394 switchLightPrograms();
397 // =======================================================================
398 // function : SetProjectionState
399 // purpose : Sets new state of OCCT projection transform
400 // =======================================================================
401 void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix)
403 myProjectionState.Set (theProjectionMatrix);
404 myProjectionState.Update();
407 // =======================================================================
408 // function : SetModelWorldState
409 // purpose : Sets new state of OCCT model-world transform
410 // =======================================================================
411 void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix)
413 myModelWorldState.Set (theModelWorldMatrix);
414 myModelWorldState.Update();
417 // =======================================================================
418 // function : SetWorldViewState
419 // purpose : Sets new state of OCCT world-view transform
420 // =======================================================================
421 void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix)
423 myWorldViewState.Set (theWorldViewMatrix);
424 myWorldViewState.Update();
427 // =======================================================================
428 // function : LightSourceState
429 // purpose : Returns current state of OCCT light sources
430 // =======================================================================
431 const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const
433 return myLightSourceState;
436 // =======================================================================
437 // function : ProjectionState
438 // purpose : Returns current state of OCCT projection transform
439 // =======================================================================
440 const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const
442 return myProjectionState;
445 // =======================================================================
446 // function : ModelWorldState
447 // purpose : Returns current state of OCCT model-world transform
448 // =======================================================================
449 const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const
451 return myModelWorldState;
454 // =======================================================================
455 // function : WorldViewState
456 // purpose : Returns current state of OCCT world-view transform
457 // =======================================================================
458 const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const
460 return myWorldViewState;
463 //! Packed properties of light source
464 class OpenGl_ShaderLightParameters
469 OpenGl_Vec4 Position;
470 OpenGl_Vec4 Direction;
471 OpenGl_Vec4 Parameters;
473 //! Returns packed (serialized) representation of light source properties
474 const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
475 static Standard_Integer NbOfVec4() { return 4; }
479 //! Packed light source type information
480 class OpenGl_ShaderLightType
484 Standard_Integer Type;
485 Standard_Integer IsHeadlight;
487 //! Returns packed (serialized) representation of light source type
488 const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
489 static Standard_Integer NbOfVec2i() { return 1; }
493 // =======================================================================
494 // function : PushLightSourceState
495 // purpose : Pushes state of OCCT light sources to the program
496 // =======================================================================
497 void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
499 if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)
500 || !theProgram->IsValid())
505 OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[OpenGLMaxLights];
506 for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt)
508 aLightTypeArray[aLightIt].Type = -1;
511 const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights);
512 if (aLightsDefNb < 1)
514 theProgram->SetUniform (myContext,
515 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
517 theProgram->SetUniform (myContext,
518 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
519 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
520 theProgram->SetUniform (myContext,
521 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
522 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
523 aLightTypeArray[0].Packed());
524 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
525 delete[] aLightTypeArray;
529 OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb];
531 OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
532 Standard_Integer aLightsNb = 0;
533 for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next())
535 const OpenGl_Light& aLight = anIter.Value();
536 if (aLight.Type == Visual3d_TOLS_AMBIENT)
538 anAmbient += aLight.Color;
541 else if (aLightsNb >= OpenGLMaxLights)
546 OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb];
547 aLightType.Type = aLight.Type;
548 aLightType.IsHeadlight = aLight.IsHeadlight;
550 OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb];
551 aLightParams.Color = aLight.Color;
552 aLightParams.Position = aLight.Type == Visual3d_TOLS_DIRECTIONAL
555 if (aLight.Type == Visual3d_TOLS_SPOT)
557 aLightParams.Direction = aLight.Direction;
559 aLightParams.Parameters = aLight.Params;
563 theProgram->SetUniform (myContext,
564 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
566 theProgram->SetUniform (myContext,
567 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
569 theProgram->SetUniform (myContext,
570 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
571 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
572 aLightTypeArray[0].Packed());
575 theProgram->SetUniform (myContext,
576 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
577 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
578 aLightParamsArray[0].Packed());
580 delete[] aLightParamsArray;
581 delete[] aLightTypeArray;
583 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
586 // =======================================================================
587 // function : PushProjectionState
588 // purpose : Pushes state of OCCT projection transform to the program
589 // =======================================================================
590 void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
592 if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE))
597 theProgram->SetUniform (myContext,
598 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
599 myProjectionState.ProjectionMatrix());
601 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
602 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
604 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
607 theProgram->SetUniform (myContext,
608 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
609 myProjectionState.ProjectionMatrix(), true);
611 aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
612 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
614 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
617 theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
620 // =======================================================================
621 // function : PushModelWorldState
622 // purpose : Pushes state of OCCT model-world transform to the program
623 // =======================================================================
624 void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
626 if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
631 theProgram->SetUniform (myContext,
632 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
633 myModelWorldState.ModelWorldMatrix());
635 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
636 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
638 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
641 theProgram->SetUniform (myContext,
642 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
643 myModelWorldState.ModelWorldMatrix(), true);
645 aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
646 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
648 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
651 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
654 // =======================================================================
655 // function : PushWorldViewState
656 // purpose : Pushes state of OCCT world-view transform to the program
657 // =======================================================================
658 void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
660 if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
665 theProgram->SetUniform (myContext,
666 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
667 myWorldViewState.WorldViewMatrix());
669 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
670 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
672 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
675 theProgram->SetUniform (myContext,
676 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
677 myWorldViewState.WorldViewMatrix(), true);
679 aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
680 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
682 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
685 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
688 // =======================================================================
689 // function : UpdateClippingState
690 // purpose : Updates state of OCCT clipping planes
691 // =======================================================================
692 void OpenGl_ShaderManager::UpdateClippingState()
694 myClippingState.Update();
697 // =======================================================================
698 // function : RevertClippingState
699 // purpose : Reverts state of OCCT clipping planes
700 // =======================================================================
701 void OpenGl_ShaderManager::RevertClippingState()
703 myClippingState.Revert();
706 // =======================================================================
707 // function : PushClippingState
708 // purpose : Pushes state of OCCT clipping planes to the program
709 // =======================================================================
710 void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
712 if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
717 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
718 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
719 const GLint aLocSpaces = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_SPACES);
720 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION
721 && aLocSpaces == OpenGl_ShaderProgram::INVALID_LOCATION)
727 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
728 anIter.More(); anIter.Next())
730 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
731 if (!myContext->Clipping().IsEnabled (aPlane))
743 const Standard_Size MAX_CLIP_PLANES = 8;
744 OpenGl_Vec4* anEquations = new OpenGl_Vec4[MAX_CLIP_PLANES];
745 GLint* aSpaces = new GLint [MAX_CLIP_PLANES];
747 for (Graphic3d_SequenceOfHClipPlane::Iterator anIter (myContext->Clipping().Planes());
748 anIter.More(); anIter.Next())
750 const Handle(Graphic3d_ClipPlane)& aPlane = anIter.Value();
751 if (!myContext->Clipping().IsEnabled (aPlane))
756 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
757 anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(),
758 (float) anEquation.y(),
759 (float) anEquation.z(),
760 (float) anEquation.w());
761 aSpaces[aPlaneId] = myContext->Clipping().GetEquationSpace (aPlane);
765 theProgram->SetUniform (myContext,
766 theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT),
768 theProgram->SetUniform (myContext, aLocEquations, MAX_CLIP_PLANES, anEquations);
769 theProgram->SetUniform (myContext, aLocSpaces, MAX_CLIP_PLANES, aSpaces);
771 delete[] anEquations;
775 // =======================================================================
776 // function : UpdateMaterialStateTo
777 // purpose : Updates state of OCCT material for specified program
778 // =======================================================================
779 void OpenGl_ShaderManager::UpdateMaterialStateTo (const Handle(OpenGl_ShaderProgram)& theProgram,
780 const OpenGl_Element* theAspect)
782 if (myMaterialStates.IsBound (theProgram))
784 OpenGl_MaterialState& aState = myMaterialStates.ChangeFind (theProgram);
785 aState.Set (theAspect);
790 myMaterialStates.Bind (theProgram, OpenGl_MaterialState (theAspect));
791 myMaterialStates.ChangeFind (theProgram).Update();
795 // =======================================================================
796 // function : ResetMaterialStates
797 // purpose : Resets state of OCCT material for all programs
798 // =======================================================================
799 void OpenGl_ShaderManager::ResetMaterialStates()
801 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
803 anIt.Value()->UpdateState (OpenGl_MATERIALS_STATE, 0);
807 // =======================================================================
808 // function : MaterialState
809 // purpose : Returns state of OCCT material for specified program
810 // =======================================================================
811 const OpenGl_MaterialState* OpenGl_ShaderManager::MaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
813 if (!myMaterialStates.IsBound (theProgram))
816 return &myMaterialStates.Find (theProgram);
819 // =======================================================================
820 // function : SurfaceDetailState
821 // purpose : Returns current state of OCCT surface detail
822 // =======================================================================
823 const OpenGl_SurfaceDetailState& OpenGl_ShaderManager::SurfaceDetailState() const
825 return mySurfaceDetailState;
828 // =======================================================================
829 // function : UpdateSurfaceDetailStateTo
830 // purpose : Updates state of OCCT surface detail
831 // =======================================================================
832 void OpenGl_ShaderManager::UpdateSurfaceDetailStateTo (const Visual3d_TypeOfSurfaceDetail theDetail)
834 mySurfaceDetailState.Set (theDetail);
835 mySurfaceDetailState.Update();
841 static const OpenGl_Vec4 THE_COLOR_BLACK_VEC4 (0.0f, 0.0f, 0.0f, 0.0f);
843 // =======================================================================
844 // function : PushAspectFace
846 // =======================================================================
847 static void PushAspectFace (const Handle(OpenGl_Context)& theCtx,
848 const Handle(OpenGl_ShaderProgram)& theProgram,
849 const OpenGl_AspectFace* theAspect)
851 theProgram->SetUniform (theCtx,
852 theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
853 theAspect->DoTextureMap());
854 theProgram->SetUniform (theCtx,
855 theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER),
856 0 /* GL_TEXTURE0 */);
857 theProgram->SetUniform (theCtx,
858 theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
859 theAspect->DistinguishingMode());
861 OpenGl_Material aParams;
862 for (Standard_Integer anIndex = 0; anIndex < 2; ++anIndex)
864 const GLint aLoc = theProgram->GetStateLocation (anIndex == 0
865 ? OpenGl_OCCT_FRONT_MATERIAL
866 : OpenGl_OCCT_BACK_MATERIAL);
867 if (aLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
872 aParams.Init (anIndex == 0 || theAspect->DistinguishingMode() != TOn
873 ? theAspect->IntFront()
874 : theAspect->IntBack());
875 theProgram->SetUniform (theCtx, aLoc, OpenGl_Material::NbOfVec4(),
880 // =======================================================================
881 // function : PushAspectLine
883 // =======================================================================
884 static void PushAspectLine (const Handle(OpenGl_Context)& theCtx,
885 const Handle(OpenGl_ShaderProgram)& theProgram,
886 const OpenGl_AspectLine* theAspect)
888 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOff);
889 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
891 const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
892 theAspect->Color().rgb[1],
893 theAspect->Color().rgb[2],
894 theAspect->Color().rgb[3]);
895 OpenGl_Vec4 aParams[5];
896 aParams[0] = THE_COLOR_BLACK_VEC4;
897 aParams[1] = THE_COLOR_BLACK_VEC4;
898 aParams[2] = aDiffuse;
899 aParams[3] = THE_COLOR_BLACK_VEC4;
900 aParams[4].x() = 0.0f; // shininess
901 aParams[4].y() = 0.0f; // transparency
902 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
906 // =======================================================================
907 // function : PushAspectText
909 // =======================================================================
910 static void PushAspectText (const Handle(OpenGl_Context)& theCtx,
911 const Handle(OpenGl_ShaderProgram)& theProgram,
912 const OpenGl_AspectText* theAspect)
914 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn);
915 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
916 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */);
918 OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
919 theAspect->Color().rgb[1],
920 theAspect->Color().rgb[2],
921 theAspect->Color().rgb[3]);
922 if (theAspect->DisplayType() == Aspect_TODT_DEKALE
923 || theAspect->DisplayType() == Aspect_TODT_SUBTITLE)
925 aDiffuse = OpenGl_Vec4 (theAspect->SubtitleColor().rgb[0],
926 theAspect->SubtitleColor().rgb[1],
927 theAspect->SubtitleColor().rgb[2],
928 theAspect->SubtitleColor().rgb[3]);
931 OpenGl_Vec4 aParams[5];
932 aParams[0] = THE_COLOR_BLACK_VEC4;
933 aParams[1] = THE_COLOR_BLACK_VEC4;
934 aParams[2] = aDiffuse;
935 aParams[3] = THE_COLOR_BLACK_VEC4;
936 aParams[4].x() = 0.0f; // shininess
937 aParams[4].y() = 0.0f; // transparency
938 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
942 // =======================================================================
943 // function : PushAspectMarker
945 // =======================================================================
946 static void PushAspectMarker (const Handle(OpenGl_Context)& theCtx,
947 const Handle(OpenGl_ShaderProgram)& theProgram,
948 const OpenGl_AspectMarker* theAspect)
950 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE), TOn);
951 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE), TOff);
952 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_ACTIVE_SAMPLER), 0 /* GL_TEXTURE0 */);
954 const OpenGl_Vec4 aDiffuse (theAspect->Color().rgb[0],
955 theAspect->Color().rgb[1],
956 theAspect->Color().rgb[2],
957 theAspect->Color().rgb[3]);
958 OpenGl_Vec4 aParams[5];
959 aParams[0] = THE_COLOR_BLACK_VEC4;
960 aParams[1] = THE_COLOR_BLACK_VEC4;
961 aParams[2] = aDiffuse;
962 aParams[3] = THE_COLOR_BLACK_VEC4;
963 aParams[4].x() = 0.0f; // shininess
964 aParams[4].y() = 0.0f; // transparency
965 theProgram->SetUniform (theCtx, theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL),
969 }; // nameless namespace
971 // =======================================================================
972 // function : PushMaterialState
973 // purpose : Pushes current state of OCCT material to the program
974 // =======================================================================
975 void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
977 if (!myMaterialStates.IsBound (theProgram))
982 const OpenGl_MaterialState& aState = myMaterialStates.Find (theProgram);
983 if (aState.Index() == theProgram->ActiveState (OpenGl_MATERIALS_STATE))
988 if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectFace))
990 PushAspectFace (myContext, theProgram, dynamic_cast<const OpenGl_AspectFace*> (aState.Aspect()));
992 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectLine))
994 PushAspectLine (myContext, theProgram, dynamic_cast<const OpenGl_AspectLine*> (aState.Aspect()));
996 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectText))
998 PushAspectText (myContext, theProgram, dynamic_cast<const OpenGl_AspectText*> (aState.Aspect()));
1000 else if (typeid (*aState.Aspect()) == typeid (OpenGl_AspectMarker))
1002 PushAspectMarker (myContext, theProgram, dynamic_cast<const OpenGl_AspectMarker*> (aState.Aspect()));
1005 theProgram->UpdateState (OpenGl_MATERIALS_STATE, aState.Index());
1008 // =======================================================================
1009 // function : PushState
1010 // purpose : Pushes state of OCCT graphics parameters to the program
1011 // =======================================================================
1012 void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1014 PushClippingState (theProgram);
1015 PushMaterialState (theProgram);
1016 PushWorldViewState (theProgram);
1017 PushModelWorldState (theProgram);
1018 PushProjectionState (theProgram);
1019 PushLightSourceState (theProgram);
1022 // =======================================================================
1023 // function : prepareStdProgramFont
1025 // =======================================================================
1026 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
1028 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1029 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
1030 + THE_VARY_TexCoord_OUT
1033 EOL" TexCoord = occTexCoord.st;"
1034 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1037 TCollection_AsciiString
1038 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).a; }";
1039 #if !defined(GL_ES_VERSION_2_0)
1040 if (myContext->core11 == NULL)
1042 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).r; }";
1046 TCollection_AsciiString aSrcFrag = TCollection_AsciiString() +
1047 + THE_VARY_TexCoord_IN
1051 EOL" vec4 aColor = occColor;"
1052 EOL" aColor.a *= getAlpha();"
1053 EOL" if (aColor.a <= 0.285) discard;"
1054 EOL" occFragColor = aColor;"
1057 #if !defined(GL_ES_VERSION_2_0)
1058 if (myContext->core32 != NULL)
1060 aProgramSrc->SetHeader ("#version 150");
1063 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1064 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1065 TCollection_AsciiString aKey;
1066 if (!Create (aProgramSrc, aKey, myFontProgram))
1068 myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1069 return Standard_False;
1071 return Standard_True;
1074 // =======================================================================
1075 // function : prepareStdProgramFboBlit
1077 // =======================================================================
1078 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit()
1080 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1081 TCollection_AsciiString aSrcVert =
1082 EOL"THE_SHADER_OUT vec2 TexCoord;"
1085 EOL" TexCoord = occVertex.zw;"
1086 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1089 TCollection_AsciiString aSrcFrag =
1090 EOL"uniform sampler2D uColorSampler;"
1091 EOL"uniform sampler2D uDepthSampler;"
1093 EOL"THE_SHADER_IN vec2 TexCoord;"
1097 EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;"
1098 EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);"
1101 #if defined(GL_ES_VERSION_2_0)
1102 if (myContext->IsGlGreaterEqual (3, 0))
1104 aProgramSrc->SetHeader ("#version 300 es");
1108 // there is no way to draw into depth buffer
1110 EOL"uniform sampler2D uColorSampler;"
1112 EOL"THE_SHADER_IN vec2 TexCoord;"
1116 EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);"
1120 if (myContext->core32 != NULL)
1122 aProgramSrc->SetHeader ("#version 150");
1125 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1126 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1127 TCollection_AsciiString aKey;
1128 if (!Create (aProgramSrc, aKey, myBlitProgram))
1130 myBlitProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1131 return Standard_False;
1134 myContext->BindProgram (myBlitProgram);
1135 myBlitProgram->SetSampler (myContext, "uColorSampler", 0);
1136 myBlitProgram->SetSampler (myContext, "uDepthSampler", 1);
1137 myContext->BindProgram (NULL);
1138 return Standard_True;
1141 // =======================================================================
1142 // function : prepareStdProgramFlat
1144 // =======================================================================
1145 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_ShaderProgram)& theProgram,
1146 const Standard_Integer theBits)
1148 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1149 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
1150 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
1151 TCollection_AsciiString aSrcFragMainGetColor = EOL" occFragColor = getColor();";
1152 if ((theBits & OpenGl_PO_Point) != 0)
1154 #if defined(GL_ES_VERSION_2_0)
1155 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1157 if ((theBits & OpenGl_PO_TextureA) != 0)
1159 TCollection_AsciiString
1160 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, gl_PointCoord).a; }";
1161 #if !defined(GL_ES_VERSION_2_0)
1162 if (myContext->core11 == NULL)
1164 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, gl_PointCoord).r; }";
1168 aSrcFragGetColor = aSrcGetAlpha
1169 + EOL"vec4 getColor(void)"
1171 EOL" vec4 aColor = occColor;"
1172 EOL" aColor.a *= getAlpha();"
1173 EOL" return aColor;"
1176 aSrcFragMainGetColor =
1177 EOL" vec4 aColor = getColor();"
1178 EOL" if (aColor.a <= 0.1) discard;"
1179 EOL" occFragColor = aColor;";
1181 else if ((theBits & OpenGl_PO_TextureRGB) != 0)
1184 EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, gl_PointCoord); }";
1185 aSrcFragMainGetColor =
1186 EOL" vec4 aColor = getColor();"
1187 EOL" if (aColor.a <= 0.1) discard;"
1188 EOL" occFragColor = aColor;";
1193 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1195 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1196 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1197 aSrcVertExtraMain +=
1198 EOL" TexCoord = occTexCoord.st;";
1201 EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, TexCoord.st); }";
1203 else if ((theBits & OpenGl_PO_TextureEnv) != 0)
1205 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1206 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1208 aSrcVertExtraFunc = THE_FUNC_transformNormal;
1210 aSrcVertExtraMain +=
1211 EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1212 EOL" vec3 aNormal = transformNormal (occNormal);"
1213 EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);"
1214 EOL" aReflect.z += 1.0;"
1215 EOL" TexCoord = aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5);";
1218 EOL"vec4 getColor(void) { return occTexture2D (occActiveSampler, TexCoord.st); }";
1221 if ((theBits & OpenGl_PO_VertColor) != 0)
1223 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
1224 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1225 aSrcFragExtraOut += EOL"THE_SHADER_IN vec4 VertColor;";
1226 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
1228 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1231 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1232 EOL"THE_SHADER_OUT vec4 Position;";
1234 EOL"THE_SHADER_IN vec4 PositionWorld;"
1235 EOL"THE_SHADER_IN vec4 Position;";
1236 aSrcVertExtraMain +=
1237 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1238 EOL" Position = occWorldViewMatrix * PositionWorld;";
1239 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1242 TCollection_AsciiString aSrcVertEndMain;
1243 if ((theBits & OpenGl_PO_StippleLine) != 0)
1245 bool hasCaps = false;
1246 #if defined(GL_ES_VERSION_2_0)
1247 if (myContext->IsGlGreaterEqual (3, 0))
1249 aProgramSrc->SetHeader ("#version 300 es");
1253 if (myContext->core32 != NULL)
1255 aProgramSrc->SetHeader ("#version 150");
1263 EOL"THE_SHADER_OUT vec2 ScreenSpaceCoord;";
1265 EOL"THE_SHADER_IN vec2 ScreenSpaceCoord;"
1266 EOL"uniform int uPattern;"
1267 EOL"uniform float uFactor;";
1269 EOL" ScreenSpaceCoord = gl_Position.xy / gl_Position.w;";
1270 aSrcFragMainGetColor =
1271 EOL" float anAngle = atan (dFdx (ScreenSpaceCoord.x), dFdy (ScreenSpaceCoord.y));"
1272 EOL" float aRotatePoint = gl_FragCoord.x * sin (anAngle) + gl_FragCoord.y * cos (anAngle);"
1273 EOL" uint aBit = uint (floor (aRotatePoint / uFactor + 0.5)) & 15U;"
1274 EOL" if ((uint (uPattern) & (1U << aBit)) == 0U) discard;"
1275 EOL" vec4 aColor = getColor();"
1276 EOL" if (aColor.a <= 0.1) discard;"
1277 EOL" occFragColor = aColor;";
1281 const TCollection_ExtendedString aWarnMessage =
1282 "Warning: stipple lines in GLSL will be ignored.";
1283 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION_ARB,
1284 GL_DEBUG_TYPE_PORTABILITY_ARB, 0, GL_DEBUG_SEVERITY_HIGH_ARB, aWarnMessage);
1294 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1304 + aSrcFragMainGetColor
1307 #if !defined(GL_ES_VERSION_2_0)
1308 if (myContext->core32 != NULL)
1310 aProgramSrc->SetHeader ("#version 150");
1313 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1314 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1316 TCollection_AsciiString aKey;
1317 if (!Create (aProgramSrc, aKey, theProgram))
1319 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1320 return Standard_False;
1322 return Standard_True;
1325 // =======================================================================
1326 // function : stdComputeLighting
1328 // =======================================================================
1329 TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (const Standard_Boolean theHasVertColor)
1331 bool aLightsMap[Visual3d_TOLS_SPOT + 1] = { false, false, false, false };
1332 TCollection_AsciiString aLightsFunc, aLightsLoop;
1333 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
1334 if (aLights != NULL)
1336 Standard_Integer anIndex = 0;
1337 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next(), ++anIndex)
1339 switch (aLightIter.Value().Type)
1341 case Visual3d_TOLS_AMBIENT:
1343 break; // skip ambient
1344 case Visual3d_TOLS_DIRECTIONAL:
1345 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
1347 case Visual3d_TOLS_POSITIONAL:
1348 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1350 case Visual3d_TOLS_SPOT:
1351 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1355 bool& aTypeBit = aLightsMap[aLightIter.Value().Type];
1362 switch (aLightIter.Value().Type)
1364 case Visual3d_TOLS_AMBIENT: break;
1365 case Visual3d_TOLS_DIRECTIONAL: aLightsFunc += THE_FUNC_directionalLight; break;
1366 case Visual3d_TOLS_POSITIONAL: aLightsFunc += THE_FUNC_pointLight; break;
1367 case Visual3d_TOLS_SPOT: aLightsFunc += THE_FUNC_spotLight; break;
1372 TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();";
1373 TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();";
1374 if (theHasVertColor)
1376 aGetMatAmbient = "getVertColor();";
1377 aGetMatDiffuse = "getVertColor();";
1380 return TCollection_AsciiString()
1384 EOL"vec4 computeLighting (in vec3 theNormal,"
1385 EOL" in vec3 theView,"
1386 EOL" in vec4 thePoint,"
1387 EOL" in bool theIsFront)"
1389 EOL" Ambient = occLightAmbient.rgb;"
1390 EOL" Diffuse = vec3 (0.0);"
1391 EOL" Specular = vec3 (0.0);"
1392 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
1394 + EOL" vec4 aMaterialAmbient = " + aGetMatAmbient
1395 + EOL" vec4 aMaterialDiffuse = " + aGetMatDiffuse
1396 + EOL" vec4 aMaterialSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
1397 EOL" vec4 aMaterialEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
1398 EOL" return vec4 (Ambient, 1.0) * aMaterialAmbient"
1399 EOL" + vec4 (Diffuse, 1.0) * aMaterialDiffuse"
1400 EOL" + vec4 (Specular, 1.0) * aMaterialSpecular"
1401 EOL" + aMaterialEmission;"
1405 // =======================================================================
1406 // function : prepareStdProgramGouraud
1408 // =======================================================================
1409 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
1410 const Standard_Integer theBits)
1412 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1413 TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
1414 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
1415 if ((theBits & OpenGl_PO_Point) != 0)
1417 #if defined(GL_ES_VERSION_2_0)
1418 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1421 if ((theBits & OpenGl_PO_VertColor) != 0)
1423 aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
1425 if ((theBits & OpenGl_PO_Point) != 0)
1427 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1430 EOL"vec4 getColor(void)"
1432 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
1433 EOL" return occTexture2D(occActiveSampler, gl_PointCoord) * aColor;"
1439 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1441 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1442 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1443 aSrcVertExtraMain +=
1444 EOL" TexCoord = occTexCoord.st;";
1447 EOL"vec4 getColor(void)"
1449 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
1450 EOL" return occTexture2D(occActiveSampler, TexCoord.st) * aColor;"
1454 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1457 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1458 EOL"THE_SHADER_OUT vec4 Position;";
1460 EOL"THE_SHADER_IN vec4 PositionWorld;"
1461 EOL"THE_SHADER_IN vec4 Position;";
1462 aSrcVertExtraMain +=
1463 EOL" PositionWorld = aPositionWorld;"
1464 EOL" Position = aPosition;";
1465 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1468 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
1469 aSrcVert = TCollection_AsciiString()
1470 + THE_FUNC_transformNormal
1475 EOL"THE_SHADER_OUT vec4 FrontColor;"
1476 EOL"THE_SHADER_OUT vec4 BackColor;"
1481 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
1482 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
1483 EOL" vec3 aNormal = transformNormal (occNormal);"
1484 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
1485 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
1486 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
1488 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1491 aSrcFrag = TCollection_AsciiString()
1492 + EOL"THE_SHADER_IN vec4 FrontColor;"
1493 EOL"THE_SHADER_IN vec4 BackColor;"
1499 + EOL" occFragColor = getColor();"
1502 #if !defined(GL_ES_VERSION_2_0)
1503 if (myContext->core32 != NULL)
1505 aProgramSrc->SetHeader ("#version 150");
1508 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1509 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1510 TCollection_AsciiString aKey;
1511 if (!Create (aProgramSrc, aKey, theProgram))
1513 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1514 return Standard_False;
1516 return Standard_True;
1519 // =======================================================================
1520 // function : prepareStdProgramPhong
1522 // =======================================================================
1523 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
1524 const Standard_Integer theBits)
1526 #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
1528 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1529 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain;
1530 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
1531 if ((theBits & OpenGl_PO_Point) != 0)
1533 #if defined(GL_ES_VERSION_2_0)
1534 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1537 if ((theBits & OpenGl_PO_VertColor) != 0)
1539 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
1540 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1541 aSrcFragGetVertColor = EOL"THE_SHADER_IN vec4 VertColor;"
1542 EOL"vec4 getVertColor(void) { return VertColor; }";
1545 if ((theBits & OpenGl_PO_Point) != 0)
1547 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1550 EOL"vec4 getColor(void)"
1552 EOL" vec4 aColor = " thePhongCompLight ";"
1553 EOL" return occTexture2D(occActiveSampler, gl_PointCoord) * aColor;"
1559 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1561 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1562 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1563 aSrcVertExtraMain +=
1564 EOL" TexCoord = occTexCoord.st;";
1567 EOL"vec4 getColor(void)"
1569 EOL" vec4 aColor = " thePhongCompLight ";"
1570 EOL" return occTexture2D(occActiveSampler, TexCoord.st) * aColor;"
1575 if ((theBits & OpenGl_PO_ClipPlanes) != 0)
1577 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES;
1580 aSrcVert = TCollection_AsciiString()
1581 + THE_FUNC_transformNormal
1583 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1584 EOL"THE_SHADER_OUT vec4 Position;"
1585 EOL"THE_SHADER_OUT vec3 Normal;"
1586 EOL"THE_SHADER_OUT vec3 View;"
1591 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1592 EOL" Position = occWorldViewMatrix * PositionWorld;"
1593 EOL" Normal = transformNormal (occNormal);"
1594 EOL" View = vec3 (0.0, 0.0, 1.0);"
1596 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1599 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
1600 aSrcFrag = TCollection_AsciiString()
1601 + EOL"THE_SHADER_IN vec4 PositionWorld;"
1602 EOL"THE_SHADER_IN vec4 Position;"
1603 EOL"THE_SHADER_IN vec3 Normal;"
1604 EOL"THE_SHADER_IN vec3 View;"
1607 + aSrcFragGetVertColor
1614 + EOL" occFragColor = getColor();"
1617 #if !defined(GL_ES_VERSION_2_0)
1618 if (myContext->core32 != NULL)
1620 aProgramSrc->SetHeader ("#version 150");
1623 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1624 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1625 TCollection_AsciiString aKey;
1626 if (!Create (aProgramSrc, aKey, theProgram))
1628 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1629 return Standard_False;
1631 return Standard_True;
1634 // =======================================================================
1635 // function : prepareStdProgramStereo
1637 // =======================================================================
1638 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
1639 const Graphic3d_StereoMode theStereoMode)
1641 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1642 TCollection_AsciiString aSrcVert =
1643 EOL"THE_SHADER_OUT vec2 TexCoord;"
1646 EOL" TexCoord = occVertex.zw;"
1647 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1650 TCollection_AsciiString aSrcFrag;
1651 switch (theStereoMode)
1653 case Graphic3d_StereoMode_Anaglyph:
1656 EOL"uniform sampler2D uLeftSampler;"
1657 EOL"uniform sampler2D uRightSampler;"
1659 EOL"uniform mat4 uMultL;"
1660 EOL"uniform mat4 uMultR;"
1662 EOL"vec4 THE_POW_UP = vec4 (2.2, 2.2, 2.2, 1.0);"
1663 EOL"vec4 THE_POW_DOWN = 1.0 / THE_POW_UP;"
1665 EOL"THE_SHADER_IN vec2 TexCoord;"
1669 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1670 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1671 EOL" aColorL = pow (aColorL, THE_POW_UP);" // normalize
1672 EOL" aColorR = pow (aColorR, THE_POW_UP);"
1673 EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;"
1674 EOL" occFragColor = pow (aColor, THE_POW_DOWN);"
1678 case Graphic3d_StereoMode_RowInterlaced:
1681 EOL"uniform sampler2D uLeftSampler;"
1682 EOL"uniform sampler2D uRightSampler;"
1684 EOL"THE_SHADER_IN vec2 TexCoord;"
1688 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1689 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1690 EOL" if (int (mod (gl_FragCoord.y + 1.5, 2.0)) == 1)"
1692 EOL" occFragColor = aColorL;"
1696 EOL" occFragColor = aColorR;"
1701 case Graphic3d_StereoMode_ColumnInterlaced:
1704 EOL"uniform sampler2D uLeftSampler;"
1705 EOL"uniform sampler2D uRightSampler;"
1707 EOL"THE_SHADER_IN vec2 TexCoord;"
1711 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1712 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1713 EOL" if (int (mod (gl_FragCoord.x + 1.5, 2.0)) != 1)"
1715 EOL" occFragColor = aColorL;"
1719 EOL" occFragColor = aColorR;"
1724 case Graphic3d_StereoMode_ChessBoard:
1727 EOL"uniform sampler2D uLeftSampler;"
1728 EOL"uniform sampler2D uRightSampler;"
1730 EOL"THE_SHADER_IN vec2 TexCoord;"
1734 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1735 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1736 EOL" bool isEvenX = int(mod(floor(gl_FragCoord.x + 1.5), 2.0)) == 1;"
1737 EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y + 1.5), 2.0)) != 1;"
1738 EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))"
1740 EOL" occFragColor = aColorL;"
1744 EOL" occFragColor = aColorR;"
1749 case Graphic3d_StereoMode_SideBySide:
1752 EOL"uniform sampler2D uLeftSampler;"
1753 EOL"uniform sampler2D uRightSampler;"
1755 EOL"THE_SHADER_IN vec2 TexCoord;"
1759 EOL" vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);"
1760 EOL" if (TexCoord.x > 0.5)"
1762 EOL" aTexCoord.x -= 1.0;"
1764 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
1765 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
1766 EOL" if (TexCoord.x <= 0.5)"
1768 EOL" occFragColor = aColorL;"
1772 EOL" occFragColor = aColorR;"
1777 case Graphic3d_StereoMode_OverUnder:
1780 EOL"uniform sampler2D uLeftSampler;"
1781 EOL"uniform sampler2D uRightSampler;"
1783 EOL"THE_SHADER_IN vec2 TexCoord;"
1787 EOL" vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);"
1788 EOL" if (TexCoord.y > 0.5)"
1790 EOL" aTexCoord.y -= 1.0;"
1792 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
1793 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
1794 EOL" if (TexCoord.y <= 0.5)"
1796 EOL" occFragColor = aColorL;"
1800 EOL" occFragColor = aColorR;"
1805 case Graphic3d_StereoMode_QuadBuffer:
1806 case Graphic3d_StereoMode_SoftPageFlip:
1809 /*const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[Graphic3d_StereoMode_QuadBuffer];
1810 if (!aProgram.IsNull())
1812 return aProgram->IsValid();
1815 EOL"uniform sampler2D uLeftSampler;"
1816 EOL"uniform sampler2D uRightSampler;"
1818 EOL"THE_SHADER_IN vec2 TexCoord;"
1822 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1823 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1824 EOL" aColorL.b = 0.0;"
1825 EOL" aColorL.g = 0.0;"
1826 EOL" aColorR.r = 0.0;"
1827 EOL" occFragColor = aColorL + aColorR;"
1833 #if !defined(GL_ES_VERSION_2_0)
1834 if (myContext->core32 != NULL)
1836 aProgramSrc->SetHeader ("#version 150");
1840 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1841 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1842 TCollection_AsciiString aKey;
1843 if (!Create (aProgramSrc, aKey, theProgram))
1845 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1846 return Standard_False;
1849 myContext->BindProgram (theProgram);
1850 theProgram->SetSampler (myContext, "uLeftSampler", 0);
1851 theProgram->SetSampler (myContext, "uRightSampler", 1);
1852 myContext->BindProgram (NULL);
1853 return Standard_True;
1856 // =======================================================================
1857 // function : bindProgramWithState
1859 // =======================================================================
1860 Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram,
1861 const OpenGl_Element* theAspect)
1863 if (!myContext->BindProgram (theProgram))
1865 return Standard_False;
1867 theProgram->ApplyVariables (myContext);
1869 const OpenGl_MaterialState* aMaterialState = MaterialState (theProgram);
1870 if (aMaterialState == NULL || aMaterialState->Aspect() != theAspect)
1872 UpdateMaterialStateTo (theProgram, theAspect);
1875 PushState (theProgram);
1876 return Standard_True;