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_RTTIEXT(OpenGl_ShaderManager,Standard_Transient)
36 //! Clipping planes limit (see the same definition in Declarations.glsl).
37 static const Standard_Size THE_MAX_CLIP_PLANES = 8;
41 //! Definition of TexCoord varying.
42 const char THE_VARY_TexCoord_OUT[] =
43 EOL"THE_SHADER_OUT vec4 TexCoord;";
44 const char THE_VARY_TexCoord_IN[] =
45 EOL"THE_SHADER_IN vec4 TexCoord;";
46 //! Compute TexCoord value in Vertex Shader
47 const char THE_VARY_TexCoord_Trsf[] =
48 EOL" float aRotSin = occTextureTrsf_RotationSin();"
49 EOL" float aRotCos = occTextureTrsf_RotationCos();"
50 EOL" vec2 aTex2 = (occTexCoord.xy + occTextureTrsf_Translation()) * occTextureTrsf_Scale();"
51 EOL" vec2 aCopy = aTex2;"
52 EOL" aTex2.x = aCopy.x * aRotCos - aCopy.y * aRotSin;"
53 EOL" aTex2.y = aCopy.x * aRotSin + aCopy.y * aRotCos;"
54 EOL" TexCoord = vec4(aTex2, occTexCoord.zw);";
56 //! Auxiliary function to flip gl_PointCoord vertically
57 #define THE_VEC2_glPointCoord "vec2 (gl_PointCoord.x, 1.0 - gl_PointCoord.y)"
59 //! Auxiliary function to transform normal
60 const char THE_FUNC_transformNormal[] =
61 EOL"vec3 transformNormal (in vec3 theNormal)"
63 EOL" vec4 aResult = occWorldViewMatrixInverseTranspose"
64 EOL" * occModelWorldMatrixInverseTranspose"
65 EOL" * vec4 (theNormal, 0.0);"
66 EOL" return normalize (aResult.xyz);"
69 //! Global shader variable for color definition with lighting enabled.
70 const char THE_FUNC_lightDef[] =
71 EOL"vec3 Ambient;" //!< Ambient contribution of light sources
72 EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources
73 EOL"vec3 Specular;"; //!< Specular contribution of light sources
75 //! Function computes contribution of isotropic point light source
76 const char THE_FUNC_pointLight[] =
77 EOL"void pointLight (in int theId,"
78 EOL" in vec3 theNormal,"
79 EOL" in vec3 theView,"
80 EOL" in vec3 thePoint,"
81 EOL" in bool theIsFront)"
83 EOL" vec3 aLight = occLight_Position (theId).xyz;"
84 EOL" if (occLight_IsHeadlight (theId) == 0)"
86 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));"
88 EOL" aLight -= thePoint;"
90 EOL" float aDist = length (aLight);"
91 EOL" aLight = aLight * (1.0 / aDist);"
93 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
94 EOL" + occLight_LinearAttenuation (theId) * aDist);"
96 EOL" vec3 aHalf = normalize (aLight + theView);"
98 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
99 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
100 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
102 EOL" float aSpecl = 0.0;"
103 EOL" if (aNdotL > 0.0)"
105 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
108 EOL"Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
109 EOL"Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
112 //! Function computes contribution of spotlight source
113 const char THE_FUNC_spotLight[] =
114 EOL"void spotLight (in int theId,"
115 EOL" in vec3 theNormal,"
116 EOL" in vec3 theView,"
117 EOL" in vec3 thePoint,"
118 EOL" in bool theIsFront)"
120 EOL" vec3 aLight = occLight_Position (theId).xyz;"
121 EOL" vec3 aSpotDir = occLight_SpotDirection (theId).xyz;"
122 EOL" if (occLight_IsHeadlight (theId) == 0)"
124 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 1.0));"
125 EOL" aSpotDir = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aSpotDir, 0.0));"
127 EOL" aLight -= thePoint;"
129 EOL" float aDist = length (aLight);"
130 EOL" aLight = aLight * (1.0 / aDist);"
132 EOL" aSpotDir = normalize (aSpotDir);"
134 EOL" float aCosA = dot (aSpotDir, -aLight);"
135 EOL" if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
140 EOL" float anExponent = occLight_SpotExponent (theId);"
141 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
142 EOL" + occLight_LinearAttenuation (theId) * aDist);"
143 EOL" if (anExponent > 0.0)"
145 EOL" anAtten *= pow (aCosA, anExponent * 128.0);"
148 EOL" vec3 aHalf = normalize (aLight + theView);"
150 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
151 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
152 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
154 EOL" float aSpecl = 0.0;"
155 EOL" if (aNdotL > 0.0)"
157 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
160 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
161 EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
164 //! Function computes contribution of directional light source
165 const char THE_FUNC_directionalLight[] =
166 EOL"void directionalLight (in int theId,"
167 EOL" in vec3 theNormal,"
168 EOL" in vec3 theView,"
169 EOL" in bool theIsFront)"
171 EOL" vec3 aLight = normalize (occLight_Position (theId).xyz);"
172 EOL" if (occLight_IsHeadlight (theId) == 0)"
174 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 0.0));"
177 EOL" vec3 aHalf = normalize (aLight + theView);"
179 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
180 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
181 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
183 EOL" float aSpecl = 0.0;"
184 EOL" if (aNdotL > 0.0)"
186 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
189 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL;"
190 EOL" Specular += occLight_Specular (theId).rgb * aSpecl;"
193 //! The same as THE_FUNC_directionalLight but for the light with zero index
194 //! (avoids limitations on some mobile devices).
195 const char THE_FUNC_directionalLightFirst[] =
196 EOL"void directionalLightFirst (in vec3 theNormal,"
197 EOL" in vec3 theView,"
198 EOL" in bool theIsFront)"
200 EOL" vec3 aLight = normalize (occLightSources[1].xyz);"
201 EOL" if (occLight_IsHeadlight (0) == 0)"
203 EOL" aLight = vec3 (occWorldViewMatrix * occModelWorldMatrix * vec4 (aLight, 0.0));"
206 EOL" vec3 aHalf = normalize (aLight + theView);"
208 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
209 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
210 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
212 EOL" float aSpecl = 0.0;"
213 EOL" if (aNdotL > 0.0)"
215 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
218 EOL" Diffuse += occLightSources[0].rgb * aNdotL;"
219 EOL" Specular += occLightSources[0].rgb * aSpecl;"
222 //! Process clipping planes in Fragment Shader.
223 //! Should be added at the beginning of the main() function.
224 const char THE_FRAG_CLIP_PLANES_N[] =
225 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)"
227 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
228 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)"
234 //! Process 1 clipping plane in Fragment Shader.
235 const char THE_FRAG_CLIP_PLANES_1[] =
236 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
237 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0)"
242 //! Process 2 clipping planes in Fragment Shader.
243 const char THE_FRAG_CLIP_PLANES_2[] =
244 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
245 EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];"
246 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0"
247 EOL" || dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)"
254 // =======================================================================
255 // function : OpenGl_ShaderManager
256 // purpose : Creates new empty shader manager
257 // =======================================================================
258 OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
259 : myShadingModel (Graphic3d_TOSM_VERTEX),
260 myContext (theContext),
266 // =======================================================================
267 // function : ~OpenGl_ShaderManager
268 // purpose : Releases resources of shader manager
269 // =======================================================================
270 OpenGl_ShaderManager::~OpenGl_ShaderManager()
272 myProgramList.Clear();
275 // =======================================================================
278 // =======================================================================
279 void OpenGl_ShaderManager::clear()
281 myProgramList.Clear();
282 myLightPrograms.Nullify();
283 myFlatPrograms = OpenGl_SetOfShaderPrograms();
284 myMapOfLightPrograms.Clear();
285 myFontProgram.Nullify();
286 myBlitProgram.Nullify();
287 for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter)
289 myStereoPrograms[aModeIter].Nullify();
291 switchLightPrograms();
294 // =======================================================================
296 // purpose : Creates new shader program
297 // =======================================================================
298 Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
299 TCollection_AsciiString& theShareKey,
300 Handle(OpenGl_ShaderProgram)& theProgram)
302 theProgram.Nullify();
303 if (theProxy.IsNull())
305 return Standard_False;
308 theShareKey = theProxy->GetId();
309 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
311 if (theProgram->Share())
313 myProgramList.Append (theProgram);
315 return Standard_True;
318 theProgram = new OpenGl_ShaderProgram (theProxy);
319 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
321 theProgram->Release (myContext);
323 theProgram.Nullify();
324 return Standard_False;
327 myProgramList.Append (theProgram);
328 myContext->ShareResource (theShareKey, theProgram);
329 return Standard_True;
332 // =======================================================================
333 // function : Unregister
334 // purpose : Removes specified shader program from the manager
335 // =======================================================================
336 void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
337 Handle(OpenGl_ShaderProgram)& theProgram)
339 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
341 if (anIt.Value() == theProgram)
343 if (!theProgram->UnShare())
346 theProgram.Nullify();
350 myProgramList.Remove (anIt);
355 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
358 myContext->DelayedRelease (theProgram);
359 theProgram.Nullify();
363 theProgram.Nullify();
364 myContext->ReleaseResource (anID, Standard_True);
368 // =======================================================================
369 // function : ShaderPrograms
370 // purpose : Returns list of registered shader programs
371 // =======================================================================
372 const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
374 return myProgramList;
377 // =======================================================================
379 // purpose : Returns true if no program objects are attached
380 // =======================================================================
381 Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
383 return myProgramList.IsEmpty();
386 // =======================================================================
387 // function : switchLightPrograms
389 // =======================================================================
390 void OpenGl_ShaderManager::switchLightPrograms()
392 TCollection_AsciiString aKey (myShadingModel == Graphic3d_TOSM_FRAGMENT ? "p_" : "g_");
393 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
396 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next())
398 switch (aLightIter.Value().Type)
400 case Graphic3d_TOLS_AMBIENT:
401 break; // skip ambient
402 case Graphic3d_TOLS_DIRECTIONAL:
405 case Graphic3d_TOLS_POSITIONAL:
408 case Graphic3d_TOLS_SPOT:
415 if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
417 myLightPrograms = new OpenGl_SetOfShaderPrograms();
418 myMapOfLightPrograms.Bind (aKey, myLightPrograms);
422 // =======================================================================
423 // function : UpdateLightSourceStateTo
424 // purpose : Updates state of OCCT light sources
425 // =======================================================================
426 void OpenGl_ShaderManager::UpdateLightSourceStateTo (const OpenGl_ListOfLight* theLights)
428 myLightSourceState.Set (theLights);
429 myLightSourceState.Update();
430 switchLightPrograms();
433 // =======================================================================
434 // function : SetShadingModel
436 // =======================================================================
437 void OpenGl_ShaderManager::SetShadingModel (const Graphic3d_TypeOfShadingModel theModel)
439 myShadingModel = theModel;
440 switchLightPrograms();
443 // =======================================================================
444 // function : SetProjectionState
445 // purpose : Sets new state of OCCT projection transform
446 // =======================================================================
447 void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix)
449 myProjectionState.Set (theProjectionMatrix);
450 myProjectionState.Update();
453 // =======================================================================
454 // function : SetModelWorldState
455 // purpose : Sets new state of OCCT model-world transform
456 // =======================================================================
457 void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix)
459 myModelWorldState.Set (theModelWorldMatrix);
460 myModelWorldState.Update();
463 // =======================================================================
464 // function : SetWorldViewState
465 // purpose : Sets new state of OCCT world-view transform
466 // =======================================================================
467 void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix)
469 myWorldViewState.Set (theWorldViewMatrix);
470 myWorldViewState.Update();
473 // =======================================================================
474 // function : LightSourceState
475 // purpose : Returns current state of OCCT light sources
476 // =======================================================================
477 const OpenGl_LightSourceState& OpenGl_ShaderManager::LightSourceState() const
479 return myLightSourceState;
482 // =======================================================================
483 // function : ProjectionState
484 // purpose : Returns current state of OCCT projection transform
485 // =======================================================================
486 const OpenGl_ProjectionState& OpenGl_ShaderManager::ProjectionState() const
488 return myProjectionState;
491 // =======================================================================
492 // function : ModelWorldState
493 // purpose : Returns current state of OCCT model-world transform
494 // =======================================================================
495 const OpenGl_ModelWorldState& OpenGl_ShaderManager::ModelWorldState() const
497 return myModelWorldState;
500 // =======================================================================
501 // function : WorldViewState
502 // purpose : Returns current state of OCCT world-view transform
503 // =======================================================================
504 const OpenGl_WorldViewState& OpenGl_ShaderManager::WorldViewState() const
506 return myWorldViewState;
509 //! Packed properties of light source
510 class OpenGl_ShaderLightParameters
515 OpenGl_Vec4 Position;
516 OpenGl_Vec4 Direction;
517 OpenGl_Vec4 Parameters;
519 //! Returns packed (serialized) representation of light source properties
520 const OpenGl_Vec4* Packed() const { return reinterpret_cast<const OpenGl_Vec4*> (this); }
521 static Standard_Integer NbOfVec4() { return 4; }
525 //! Packed light source type information
526 class OpenGl_ShaderLightType
530 Standard_Integer Type;
531 Standard_Integer IsHeadlight;
533 //! Returns packed (serialized) representation of light source type
534 const OpenGl_Vec2i* Packed() const { return reinterpret_cast<const OpenGl_Vec2i*> (this); }
535 static Standard_Integer NbOfVec2i() { return 1; }
539 // =======================================================================
540 // function : PushLightSourceState
541 // purpose : Pushes state of OCCT light sources to the program
542 // =======================================================================
543 void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
545 if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE)
546 || !theProgram->IsValid())
551 OpenGl_ShaderLightType* aLightTypeArray = new OpenGl_ShaderLightType[OpenGLMaxLights];
552 for (Standard_Integer aLightIt = 0; aLightIt < OpenGLMaxLights; ++aLightIt)
554 aLightTypeArray[aLightIt].Type = -1;
557 const Standard_Integer aLightsDefNb = Min (myLightSourceState.LightSources()->Size(), OpenGLMaxLights);
558 if (aLightsDefNb < 1)
560 theProgram->SetUniform (myContext,
561 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
563 theProgram->SetUniform (myContext,
564 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
565 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
566 theProgram->SetUniform (myContext,
567 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
568 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
569 aLightTypeArray[0].Packed());
570 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
571 delete[] aLightTypeArray;
575 OpenGl_ShaderLightParameters* aLightParamsArray = new OpenGl_ShaderLightParameters[aLightsDefNb];
577 OpenGl_Vec4 anAmbient (0.0f, 0.0f, 0.0f, 0.0f);
578 Standard_Integer aLightsNb = 0;
579 for (OpenGl_ListOfLight::Iterator anIter (*myLightSourceState.LightSources()); anIter.More(); anIter.Next())
581 const OpenGl_Light& aLight = anIter.Value();
582 if (aLight.Type == Graphic3d_TOLS_AMBIENT)
584 anAmbient += aLight.Color;
587 else if (aLightsNb >= OpenGLMaxLights)
592 OpenGl_ShaderLightType& aLightType = aLightTypeArray[aLightsNb];
593 aLightType.Type = aLight.Type;
594 aLightType.IsHeadlight = aLight.IsHeadlight;
596 OpenGl_ShaderLightParameters& aLightParams = aLightParamsArray[aLightsNb];
597 aLightParams.Color = aLight.Color;
598 aLightParams.Position = aLight.Type == Graphic3d_TOLS_DIRECTIONAL
601 if (aLight.Type == Graphic3d_TOLS_SPOT)
603 aLightParams.Direction = aLight.Direction;
605 aLightParams.Parameters = aLight.Params;
609 theProgram->SetUniform (myContext,
610 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
612 theProgram->SetUniform (myContext,
613 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT),
615 theProgram->SetUniform (myContext,
616 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
617 OpenGLMaxLights * OpenGl_ShaderLightType::NbOfVec2i(),
618 aLightTypeArray[0].Packed());
621 theProgram->SetUniform (myContext,
622 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
623 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
624 aLightParamsArray[0].Packed());
626 delete[] aLightParamsArray;
627 delete[] aLightTypeArray;
629 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
632 // =======================================================================
633 // function : PushProjectionState
634 // purpose : Pushes state of OCCT projection transform to the program
635 // =======================================================================
636 void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
638 if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE))
643 theProgram->SetUniform (myContext,
644 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
645 myProjectionState.ProjectionMatrix());
647 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
648 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
650 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
653 theProgram->SetUniform (myContext,
654 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
655 myProjectionState.ProjectionMatrix(), true);
657 aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
658 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
660 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
663 theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
666 // =======================================================================
667 // function : PushModelWorldState
668 // purpose : Pushes state of OCCT model-world transform to the program
669 // =======================================================================
670 void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
672 if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
677 theProgram->SetUniform (myContext,
678 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
679 myModelWorldState.ModelWorldMatrix());
681 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
682 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
684 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
687 theProgram->SetUniform (myContext,
688 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
689 myModelWorldState.ModelWorldMatrix(), true);
691 aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
692 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
694 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
697 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
700 // =======================================================================
701 // function : PushWorldViewState
702 // purpose : Pushes state of OCCT world-view transform to the program
703 // =======================================================================
704 void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
706 if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
711 theProgram->SetUniform (myContext,
712 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
713 myWorldViewState.WorldViewMatrix());
715 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
716 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
718 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
721 theProgram->SetUniform (myContext,
722 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
723 myWorldViewState.WorldViewMatrix(), true);
725 aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
726 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
728 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
731 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
734 // =======================================================================
735 // function : UpdateClippingState
736 // purpose : Updates state of OCCT clipping planes
737 // =======================================================================
738 void OpenGl_ShaderManager::UpdateClippingState()
740 myClippingState.Update();
743 // =======================================================================
744 // function : RevertClippingState
745 // purpose : Reverts state of OCCT clipping planes
746 // =======================================================================
747 void OpenGl_ShaderManager::RevertClippingState()
749 myClippingState.Revert();
752 // =======================================================================
753 // function : PushClippingState
754 // purpose : Pushes state of OCCT clipping planes to the program
755 // =======================================================================
756 void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
758 if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
763 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
764 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
765 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION)
770 const GLint aNbPlanes = Min (myContext->Clipping().NbClippingOrCappingOn(), THE_MAX_CLIP_PLANES);
771 theProgram->SetUniform (myContext,
772 theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT),
779 OpenGl_Vec4 anEquations[THE_MAX_CLIP_PLANES];
781 for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
783 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
784 if (aPlaneIter.IsDisabled())
788 else if (aPlaneId >= THE_MAX_CLIP_PLANES)
790 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
791 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
792 "Warning: clipping planes limit (8) has been exceeded.");
796 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
797 anEquations[aPlaneId] = OpenGl_Vec4 ((float) anEquation.x(),
798 (float) anEquation.y(),
799 (float) anEquation.z(),
800 (float) anEquation.w());
804 theProgram->SetUniform (myContext, aLocEquations, THE_MAX_CLIP_PLANES, anEquations);
807 // =======================================================================
808 // function : PushState
809 // purpose : Pushes state of OCCT graphics parameters to the program
810 // =======================================================================
811 void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
813 PushClippingState (theProgram);
814 PushWorldViewState (theProgram);
815 PushModelWorldState (theProgram);
816 PushProjectionState (theProgram);
817 PushLightSourceState (theProgram);
820 // =======================================================================
821 // function : prepareStdProgramFont
823 // =======================================================================
824 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
826 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
827 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
828 + EOL"THE_SHADER_OUT vec2 TexCoord;"
831 EOL" TexCoord = occTexCoord.st;"
832 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
835 TCollection_AsciiString
836 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).a; }";
837 #if !defined(GL_ES_VERSION_2_0)
838 if (myContext->core11 == NULL)
840 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, TexCoord.st).r; }";
844 TCollection_AsciiString aSrcFrag = TCollection_AsciiString() +
845 + EOL"THE_SHADER_IN vec2 TexCoord;"
849 EOL" vec4 aColor = occColor;"
850 EOL" aColor.a *= getAlpha();"
851 EOL" if (aColor.a <= 0.285) discard;"
852 EOL" occFragColor = aColor;"
855 #if !defined(GL_ES_VERSION_2_0)
856 if (myContext->core32 != NULL)
858 aProgramSrc->SetHeader ("#version 150");
861 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
862 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
863 TCollection_AsciiString aKey;
864 if (!Create (aProgramSrc, aKey, myFontProgram))
866 myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
867 return Standard_False;
869 return Standard_True;
872 // =======================================================================
873 // function : prepareStdProgramFboBlit
875 // =======================================================================
876 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit()
878 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
879 TCollection_AsciiString aSrcVert =
880 EOL"THE_SHADER_OUT vec2 TexCoord;"
883 EOL" TexCoord = occVertex.zw;"
884 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
887 TCollection_AsciiString aSrcFrag =
888 EOL"uniform sampler2D uColorSampler;"
889 EOL"uniform sampler2D uDepthSampler;"
891 EOL"THE_SHADER_IN vec2 TexCoord;"
895 EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;"
896 EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);"
899 #if defined(GL_ES_VERSION_2_0)
900 if (myContext->IsGlGreaterEqual (3, 0))
902 aProgramSrc->SetHeader ("#version 300 es");
904 else if (myContext->extFragDepth)
906 aProgramSrc->SetHeader ("#extension GL_EXT_frag_depth : enable"
907 EOL"#define gl_FragDepth gl_FragDepthEXT");
911 // there is no way to draw into depth buffer
913 EOL"uniform sampler2D uColorSampler;"
915 EOL"THE_SHADER_IN vec2 TexCoord;"
919 EOL" occFragColor = occTexture2D (uColorSampler, TexCoord);"
923 if (myContext->core32 != NULL)
925 aProgramSrc->SetHeader ("#version 150");
928 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
929 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
930 TCollection_AsciiString aKey;
931 if (!Create (aProgramSrc, aKey, myBlitProgram))
933 myBlitProgram = new OpenGl_ShaderProgram(); // just mark as invalid
934 return Standard_False;
937 myContext->BindProgram (myBlitProgram);
938 myBlitProgram->SetSampler (myContext, "uColorSampler", 0);
939 myBlitProgram->SetSampler (myContext, "uDepthSampler", 1);
940 myContext->BindProgram (NULL);
941 return Standard_True;
944 // =======================================================================
945 // function : pointSpriteAlphaSrc
947 // =======================================================================
948 TCollection_AsciiString OpenGl_ShaderManager::pointSpriteAlphaSrc (const Standard_Integer theBits)
950 TCollection_AsciiString aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord ").a; }";
951 #if !defined(GL_ES_VERSION_2_0)
952 if (myContext->core11 == NULL
953 && (theBits & OpenGl_PO_TextureA) != 0)
955 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord ").r; }";
966 // =======================================================================
967 // function : textureUsed
969 // =======================================================================
970 static bool textureUsed (const Standard_Integer theBits)
972 return (theBits & OpenGl_PO_TextureA) != 0 || (theBits & OpenGl_PO_TextureRGB) != 0;
977 // =======================================================================
978 // function : prepareStdProgramFlat
980 // =======================================================================
981 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFlat (Handle(OpenGl_ShaderProgram)& theProgram,
982 const Standard_Integer theBits)
984 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
985 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
986 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
987 TCollection_AsciiString aSrcFragMainGetColor = EOL" occFragColor = getColor();";
988 if ((theBits & OpenGl_PO_Point) != 0)
990 #if defined(GL_ES_VERSION_2_0)
991 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
994 if ((theBits & OpenGl_PO_TextureRGB) != 0)
997 EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord "); }";
1000 if (textureUsed (theBits))
1002 aSrcGetAlpha = pointSpriteAlphaSrc (theBits);
1004 #if !defined(GL_ES_VERSION_2_0)
1005 if (myContext->core11 != NULL
1006 && myContext->IsGlGreaterEqual (2, 1))
1008 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1012 aSrcFragMainGetColor =
1013 EOL" vec4 aColor = getColor();"
1014 EOL" aColor.a = getAlpha();"
1015 EOL" if (aColor.a <= 0.1) discard;"
1016 EOL" occFragColor = aColor;";
1020 aSrcFragMainGetColor =
1021 EOL" vec4 aColor = getColor();"
1022 EOL" if (aColor.a <= 0.1) discard;"
1023 EOL" occFragColor = aColor;";
1028 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1030 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1031 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1032 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
1035 EOL"vec4 getColor(void) { return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w); }";
1037 else if ((theBits & OpenGl_PO_TextureEnv) != 0)
1039 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1040 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1042 aSrcVertExtraFunc = THE_FUNC_transformNormal;
1044 aSrcVertExtraMain +=
1045 EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1046 EOL" vec3 aNormal = transformNormal (occNormal);"
1047 EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);"
1048 EOL" aReflect.z += 1.0;"
1049 EOL" TexCoord = vec4(aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5), 0.0, 1.0);";
1052 EOL"vec4 getColor(void) { return occTexture2D (occActiveSampler, TexCoord.st); }";
1055 if ((theBits & OpenGl_PO_VertColor) != 0)
1057 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
1058 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1059 aSrcFragExtraOut += EOL"THE_SHADER_IN vec4 VertColor;";
1060 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
1062 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
1065 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1066 EOL"THE_SHADER_OUT vec4 Position;";
1068 EOL"THE_SHADER_IN vec4 PositionWorld;"
1069 EOL"THE_SHADER_IN vec4 Position;";
1070 aSrcVertExtraMain +=
1071 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1072 EOL" Position = occWorldViewMatrix * PositionWorld;";
1074 if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1076 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
1078 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
1080 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_2;
1084 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
1088 TCollection_AsciiString aSrcVertEndMain;
1089 if ((theBits & OpenGl_PO_StippleLine) != 0)
1091 bool hasGlslBitOps = false;
1092 #if defined(GL_ES_VERSION_2_0)
1093 if (myContext->IsGlGreaterEqual (3, 0))
1095 aProgramSrc->SetHeader ("#version 300 es");
1096 hasGlslBitOps = true;
1099 if (myContext->IsGlGreaterEqual (3, 0))
1101 aProgramSrc->SetHeader ("#version 130");
1102 hasGlslBitOps = true;
1104 else if(myContext->CheckExtension("GL_EXT_gpu_shader4"))
1106 aProgramSrc->SetHeader ("#extension GL_EXT_gpu_shader4 : enable");
1107 hasGlslBitOps = true;
1114 EOL"THE_SHADER_OUT vec2 ScreenSpaceCoord;";
1116 EOL"THE_SHADER_IN vec2 ScreenSpaceCoord;"
1117 EOL"uniform int uPattern;"
1118 EOL"uniform float uFactor;";
1120 EOL" ScreenSpaceCoord = gl_Position.xy / gl_Position.w;";
1121 aSrcFragMainGetColor =
1122 EOL" float anAngle = atan (dFdx (ScreenSpaceCoord.x), dFdy (ScreenSpaceCoord.y));"
1123 EOL" float aRotatePoint = gl_FragCoord.x * sin (anAngle) + gl_FragCoord.y * cos (anAngle);"
1124 EOL" uint aBit = uint (floor (aRotatePoint / uFactor + 0.5)) & 15U;"
1125 EOL" if ((uint (uPattern) & (1U << aBit)) == 0U) discard;"
1126 EOL" vec4 aColor = getColor();"
1127 EOL" if (aColor.a <= 0.1) discard;"
1128 EOL" occFragColor = aColor;";
1132 const TCollection_ExtendedString aWarnMessage =
1133 "Warning: stipple lines in GLSL will be ignored.";
1134 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1135 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
1145 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1156 + aSrcFragMainGetColor
1159 #if !defined(GL_ES_VERSION_2_0)
1160 if (myContext->core32 != NULL)
1162 aProgramSrc->SetHeader ("#version 150");
1165 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1166 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1168 TCollection_AsciiString aKey;
1169 if (!Create (aProgramSrc, aKey, theProgram))
1171 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1172 return Standard_False;
1174 return Standard_True;
1177 // =======================================================================
1178 // function : pointSpriteShadingSrc
1180 // =======================================================================
1181 TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TCollection_AsciiString theBaseColorSrc,
1182 const Standard_Integer theBits)
1184 TCollection_AsciiString aSrcFragGetColor;
1185 if ((theBits & OpenGl_PO_TextureA) != 0)
1187 aSrcFragGetColor = pointSpriteAlphaSrc (theBits) +
1188 EOL"vec4 getColor(void)"
1190 EOL" vec4 aColor = " + theBaseColorSrc + ";"
1191 EOL" aColor.a = getAlpha();"
1192 EOL" if (aColor.a <= 0.1) discard;"
1193 EOL" return aColor;"
1196 else if ((theBits & OpenGl_PO_TextureRGB) != 0)
1198 aSrcFragGetColor = TCollection_AsciiString() +
1199 EOL"vec4 getColor(void)"
1201 EOL" vec4 aColor = " + theBaseColorSrc + ";"
1202 EOL" aColor = occTexture2D(occActiveSampler, " THE_VEC2_glPointCoord ") * aColor;"
1203 EOL" if (aColor.a <= 0.1) discard;"
1204 EOL" return aColor;"
1208 return aSrcFragGetColor;
1211 // =======================================================================
1212 // function : stdComputeLighting
1214 // =======================================================================
1215 TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (const Standard_Boolean theHasVertColor)
1217 Standard_Integer aLightsMap[Graphic3d_TOLS_SPOT + 1] = { 0, 0, 0, 0 };
1218 TCollection_AsciiString aLightsFunc, aLightsLoop;
1219 const OpenGl_ListOfLight* aLights = myLightSourceState.LightSources();
1220 if (aLights != NULL)
1222 Standard_Integer anIndex = 0;
1223 for (OpenGl_ListOfLight::Iterator aLightIter (*aLights); aLightIter.More(); aLightIter.Next(), ++anIndex)
1225 switch (aLightIter.Value().Type)
1227 case Graphic3d_TOLS_AMBIENT:
1229 break; // skip ambient
1230 case Graphic3d_TOLS_DIRECTIONAL:
1231 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
1233 case Graphic3d_TOLS_POSITIONAL:
1234 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1236 case Graphic3d_TOLS_SPOT:
1237 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1240 aLightsMap[aLightIter.Value().Type] += 1;
1242 const Standard_Integer aNbLoopLights = aLightsMap[Graphic3d_TOLS_DIRECTIONAL]
1243 + aLightsMap[Graphic3d_TOLS_POSITIONAL]
1244 + aLightsMap[Graphic3d_TOLS_SPOT];
1245 if (aLightsMap[Graphic3d_TOLS_DIRECTIONAL] == 1
1246 && aNbLoopLights == 1)
1248 // use the version with hard-coded first index
1249 aLightsLoop = EOL" directionalLightFirst(theNormal, theView, theIsFront);";
1250 aLightsFunc += THE_FUNC_directionalLightFirst;
1252 else if (aLightsMap[Graphic3d_TOLS_DIRECTIONAL] > 0)
1254 aLightsFunc += THE_FUNC_directionalLight;
1256 if (aLightsMap[Graphic3d_TOLS_POSITIONAL] > 0)
1258 aLightsFunc += THE_FUNC_pointLight;
1260 if (aLightsMap[Graphic3d_TOLS_SPOT] > 0)
1262 aLightsFunc += THE_FUNC_spotLight;
1266 TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();";
1267 TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();";
1268 if (theHasVertColor)
1270 aGetMatAmbient = "getVertColor();";
1271 aGetMatDiffuse = "getVertColor();";
1274 return TCollection_AsciiString()
1278 EOL"vec4 computeLighting (in vec3 theNormal,"
1279 EOL" in vec3 theView,"
1280 EOL" in vec4 thePoint,"
1281 EOL" in bool theIsFront)"
1283 EOL" Ambient = occLightAmbient.rgb;"
1284 EOL" Diffuse = vec3 (0.0);"
1285 EOL" Specular = vec3 (0.0);"
1286 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
1288 + EOL" vec4 aMatAmbient = " + aGetMatAmbient
1289 + EOL" vec4 aMatDiffuse = " + aGetMatDiffuse
1290 + EOL" vec4 aMatSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
1291 EOL" vec4 aMatEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
1292 EOL" vec3 aColor = Ambient * aMatAmbient.rgb"
1293 EOL" + Diffuse * aMatDiffuse.rgb"
1294 EOL" + Specular * aMatSpecular.rgb"
1295 EOL" + aMatEmission.rgb;"
1296 EOL" return vec4 (aColor, aMatDiffuse.a);"
1300 // =======================================================================
1301 // function : prepareStdProgramGouraud
1303 // =======================================================================
1304 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
1305 const Standard_Integer theBits)
1307 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1308 TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain;
1309 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
1310 if ((theBits & OpenGl_PO_Point) != 0)
1312 #if defined(GL_ES_VERSION_2_0)
1313 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1316 if (textureUsed (theBits))
1318 #if !defined(GL_ES_VERSION_2_0)
1319 if (myContext->core11 != NULL
1320 && myContext->IsGlGreaterEqual (2, 1))
1322 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1326 aSrcFragGetColor = pointSpriteShadingSrc ("gl_FrontFacing ? FrontColor : BackColor", theBits);
1331 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1333 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1334 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1335 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
1338 EOL"vec4 getColor(void)"
1340 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
1341 EOL" return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w) * aColor;"
1346 if ((theBits & OpenGl_PO_VertColor) != 0)
1348 aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
1351 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
1354 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1355 EOL"THE_SHADER_OUT vec4 Position;";
1357 EOL"THE_SHADER_IN vec4 PositionWorld;"
1358 EOL"THE_SHADER_IN vec4 Position;";
1359 aSrcVertExtraMain +=
1360 EOL" PositionWorld = aPositionWorld;"
1361 EOL" Position = aPosition;";
1363 if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1365 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
1367 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
1369 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_2;
1373 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
1377 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
1378 aSrcVert = TCollection_AsciiString()
1379 + THE_FUNC_transformNormal
1384 EOL"THE_SHADER_OUT vec4 FrontColor;"
1385 EOL"THE_SHADER_OUT vec4 BackColor;"
1390 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
1391 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
1392 EOL" vec3 aNormal = transformNormal (occNormal);"
1393 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
1394 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
1395 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
1397 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1400 aSrcFrag = TCollection_AsciiString()
1401 + EOL"THE_SHADER_IN vec4 FrontColor;"
1402 EOL"THE_SHADER_IN vec4 BackColor;"
1408 + EOL" occFragColor = getColor();"
1411 #if !defined(GL_ES_VERSION_2_0)
1412 if (myContext->core32 != NULL)
1414 aProgramSrc->SetHeader ("#version 150");
1417 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1418 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1419 TCollection_AsciiString aKey;
1420 if (!Create (aProgramSrc, aKey, theProgram))
1422 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1423 return Standard_False;
1425 return Standard_True;
1428 // =======================================================================
1429 // function : prepareStdProgramPhong
1431 // =======================================================================
1432 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
1433 const Standard_Integer theBits)
1435 #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
1437 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1438 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain;
1439 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
1440 if ((theBits & OpenGl_PO_Point) != 0)
1442 #if defined(GL_ES_VERSION_2_0)
1443 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1446 if (textureUsed (theBits))
1448 #if !defined(GL_ES_VERSION_2_0)
1449 if (myContext->core11 != NULL
1450 && myContext->IsGlGreaterEqual (2, 1))
1452 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1456 aSrcFragGetColor = pointSpriteShadingSrc (thePhongCompLight, theBits);
1461 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1463 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1464 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1465 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
1468 EOL"vec4 getColor(void)"
1470 EOL" vec4 aColor = " thePhongCompLight ";"
1471 EOL" return occTexture2D(occActiveSampler, TexCoord.st / TexCoord.w) * aColor;"
1476 if ((theBits & OpenGl_PO_VertColor) != 0)
1478 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
1479 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1480 aSrcFragGetVertColor = EOL"THE_SHADER_IN vec4 VertColor;"
1481 EOL"vec4 getVertColor(void) { return VertColor; }";
1484 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
1486 if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1488 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
1490 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
1492 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_2;
1496 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_N;
1500 aSrcVert = TCollection_AsciiString()
1501 + THE_FUNC_transformNormal
1503 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1504 EOL"THE_SHADER_OUT vec4 Position;"
1505 EOL"THE_SHADER_OUT vec3 Normal;"
1506 EOL"THE_SHADER_OUT vec3 View;"
1511 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1512 EOL" Position = occWorldViewMatrix * PositionWorld;"
1513 EOL" Normal = transformNormal (occNormal);"
1514 EOL" View = vec3 (0.0, 0.0, 1.0);"
1516 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1519 const TCollection_AsciiString aLights = stdComputeLighting ((theBits & OpenGl_PO_VertColor) != 0);
1520 aSrcFrag = TCollection_AsciiString()
1521 + EOL"THE_SHADER_IN vec4 PositionWorld;"
1522 EOL"THE_SHADER_IN vec4 Position;"
1523 EOL"THE_SHADER_IN vec3 Normal;"
1524 EOL"THE_SHADER_IN vec3 View;"
1527 + aSrcFragGetVertColor
1534 + EOL" occFragColor = getColor();"
1537 #if !defined(GL_ES_VERSION_2_0)
1538 if (myContext->core32 != NULL)
1540 aProgramSrc->SetHeader ("#version 150");
1543 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1544 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1545 TCollection_AsciiString aKey;
1546 if (!Create (aProgramSrc, aKey, theProgram))
1548 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1549 return Standard_False;
1551 return Standard_True;
1554 // =======================================================================
1555 // function : prepareStdProgramStereo
1557 // =======================================================================
1558 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
1559 const Graphic3d_StereoMode theStereoMode)
1561 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1562 TCollection_AsciiString aSrcVert =
1563 EOL"THE_SHADER_OUT vec2 TexCoord;"
1566 EOL" TexCoord = occVertex.zw;"
1567 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1570 TCollection_AsciiString aSrcFrag;
1571 switch (theStereoMode)
1573 case Graphic3d_StereoMode_Anaglyph:
1576 EOL"uniform sampler2D uLeftSampler;"
1577 EOL"uniform sampler2D uRightSampler;"
1579 EOL"uniform mat4 uMultL;"
1580 EOL"uniform mat4 uMultR;"
1582 EOL"const vec4 THE_POW_UP = vec4 (2.2, 2.2, 2.2, 1.0);"
1583 EOL"const vec4 THE_POW_DOWN = 1.0 / vec4 (2.2, 2.2, 2.2, 1.0);"
1585 EOL"THE_SHADER_IN vec2 TexCoord;"
1589 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1590 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1591 EOL" aColorL = pow (aColorL, THE_POW_UP);" // normalize
1592 EOL" aColorR = pow (aColorR, THE_POW_UP);"
1593 EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;"
1594 EOL" occFragColor = pow (aColor, THE_POW_DOWN);"
1598 case Graphic3d_StereoMode_RowInterlaced:
1601 EOL"uniform sampler2D uLeftSampler;"
1602 EOL"uniform sampler2D uRightSampler;"
1604 EOL"THE_SHADER_IN vec2 TexCoord;"
1608 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1609 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1610 EOL" if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)"
1612 EOL" occFragColor = aColorL;"
1616 EOL" occFragColor = aColorR;"
1621 case Graphic3d_StereoMode_ColumnInterlaced:
1624 EOL"uniform sampler2D uLeftSampler;"
1625 EOL"uniform sampler2D uRightSampler;"
1627 EOL"THE_SHADER_IN vec2 TexCoord;"
1631 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1632 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1633 EOL" if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)"
1635 EOL" occFragColor = aColorL;"
1639 EOL" occFragColor = aColorR;"
1644 case Graphic3d_StereoMode_ChessBoard:
1647 EOL"uniform sampler2D uLeftSampler;"
1648 EOL"uniform sampler2D uRightSampler;"
1650 EOL"THE_SHADER_IN vec2 TexCoord;"
1654 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1655 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1656 EOL" bool isEvenX = int(mod(floor(gl_FragCoord.x - 1023.5), 2.0)) != 1;"
1657 EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y - 1023.5), 2.0)) == 1;"
1658 EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))"
1660 EOL" occFragColor = aColorL;"
1664 EOL" occFragColor = aColorR;"
1669 case Graphic3d_StereoMode_SideBySide:
1672 EOL"uniform sampler2D uLeftSampler;"
1673 EOL"uniform sampler2D uRightSampler;"
1675 EOL"THE_SHADER_IN vec2 TexCoord;"
1679 EOL" vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);"
1680 EOL" if (TexCoord.x > 0.5)"
1682 EOL" aTexCoord.x -= 1.0;"
1684 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
1685 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
1686 EOL" if (TexCoord.x <= 0.5)"
1688 EOL" occFragColor = aColorL;"
1692 EOL" occFragColor = aColorR;"
1697 case Graphic3d_StereoMode_OverUnder:
1700 EOL"uniform sampler2D uLeftSampler;"
1701 EOL"uniform sampler2D uRightSampler;"
1703 EOL"THE_SHADER_IN vec2 TexCoord;"
1707 EOL" vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);"
1708 EOL" if (TexCoord.y > 0.5)"
1710 EOL" aTexCoord.y -= 1.0;"
1712 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
1713 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
1714 EOL" if (TexCoord.y <= 0.5)"
1716 EOL" occFragColor = aColorL;"
1720 EOL" occFragColor = aColorR;"
1725 case Graphic3d_StereoMode_QuadBuffer:
1726 case Graphic3d_StereoMode_SoftPageFlip:
1729 /*const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[Graphic3d_StereoMode_QuadBuffer];
1730 if (!aProgram.IsNull())
1732 return aProgram->IsValid();
1735 EOL"uniform sampler2D uLeftSampler;"
1736 EOL"uniform sampler2D uRightSampler;"
1738 EOL"THE_SHADER_IN vec2 TexCoord;"
1742 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
1743 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
1744 EOL" aColorL.b = 0.0;"
1745 EOL" aColorL.g = 0.0;"
1746 EOL" aColorR.r = 0.0;"
1747 EOL" occFragColor = aColorL + aColorR;"
1753 #if !defined(GL_ES_VERSION_2_0)
1754 if (myContext->core32 != NULL)
1756 aProgramSrc->SetHeader ("#version 150");
1760 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1761 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1762 TCollection_AsciiString aKey;
1763 if (!Create (aProgramSrc, aKey, theProgram))
1765 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1766 return Standard_False;
1769 myContext->BindProgram (theProgram);
1770 theProgram->SetSampler (myContext, "uLeftSampler", 0);
1771 theProgram->SetSampler (myContext, "uRightSampler", 1);
1772 myContext->BindProgram (NULL);
1773 return Standard_True;
1776 // =======================================================================
1777 // function : bindProgramWithState
1779 // =======================================================================
1780 Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram)
1782 if (!myContext->BindProgram (theProgram))
1784 return Standard_False;
1786 theProgram->ApplyVariables (myContext);
1788 PushState (theProgram);
1789 return Standard_True;