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_ClippingIterator.hxx>
24 #include <OpenGl_Context.hxx>
25 #include <OpenGl_ShaderManager.hxx>
26 #include <OpenGl_ShaderProgram.hxx>
27 #include <OpenGl_VertexBufferCompat.hxx>
28 #include <OpenGl_Workspace.hxx>
30 #include <TCollection_ExtendedString.hxx>
32 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager,Standard_Transient)
36 //! Number specifying maximum number of light sources to prepare a GLSL program with unrolled loop.
37 const Standard_Integer THE_NB_UNROLLED_LIGHTS_MAX = 32;
39 //! Compute the size of array storing holding light sources definition.
40 static Standard_Integer roundUpMaxLightSources (Standard_Integer theNbLights)
42 Standard_Integer aMaxLimit = THE_NB_UNROLLED_LIGHTS_MAX;
43 for (; aMaxLimit < theNbLights; aMaxLimit *= 2) {}
49 //! Definition of TexCoord varying.
50 const char THE_VARY_TexCoord_OUT[] =
51 EOL"THE_SHADER_OUT vec4 TexCoord;";
52 const char THE_VARY_TexCoord_IN[] =
53 EOL"THE_SHADER_IN vec4 TexCoord;";
54 //! Compute TexCoord value in Vertex Shader
55 const char THE_VARY_TexCoord_Trsf[] =
56 EOL" float aRotSin = occTextureTrsf_RotationSin();"
57 EOL" float aRotCos = occTextureTrsf_RotationCos();"
58 EOL" vec2 aTex2 = (occTexCoord.xy + occTextureTrsf_Translation()) * occTextureTrsf_Scale();"
59 EOL" vec2 aCopy = aTex2;"
60 EOL" aTex2.x = aCopy.x * aRotCos - aCopy.y * aRotSin;"
61 EOL" aTex2.y = aCopy.x * aRotSin + aCopy.y * aRotCos;"
62 EOL" TexCoord = vec4(aTex2, occTexCoord.zw);";
64 //! Auxiliary function to flip gl_PointCoord vertically
65 #define THE_VEC2_glPointCoord "vec2 (gl_PointCoord.x, 1.0 - gl_PointCoord.y)"
67 //! Auxiliary function to transform normal
68 const char THE_FUNC_transformNormal[] =
69 EOL"vec3 transformNormal (in vec3 theNormal)"
71 EOL" vec4 aResult = occWorldViewMatrixInverseTranspose"
72 EOL" * occModelWorldMatrixInverseTranspose"
73 EOL" * vec4 (theNormal, 0.0);"
74 EOL" return normalize (aResult.xyz);"
77 //! Global shader variable for color definition with lighting enabled.
78 const char THE_FUNC_lightDef[] =
79 EOL"vec3 Ambient;" //!< Ambient contribution of light sources
80 EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources
81 EOL"vec3 Specular;"; //!< Specular contribution of light sources
83 //! Function computes contribution of isotropic point light source
84 const char THE_FUNC_pointLight[] =
85 EOL"void pointLight (in int theId,"
86 EOL" in vec3 theNormal,"
87 EOL" in vec3 theView,"
88 EOL" in vec3 thePoint,"
89 EOL" in bool theIsFront)"
91 EOL" vec3 aLight = occLight_Position (theId).xyz;"
92 EOL" if (occLight_IsHeadlight (theId) == 0)"
94 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));"
96 EOL" aLight -= thePoint;"
98 EOL" float aDist = length (aLight);"
99 EOL" aLight = aLight * (1.0 / aDist);"
101 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
102 EOL" + occLight_LinearAttenuation (theId) * aDist);"
104 EOL" vec3 aHalf = normalize (aLight + theView);"
106 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
107 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
108 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
110 EOL" float aSpecl = 0.0;"
111 EOL" if (aNdotL > 0.0)"
113 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
116 EOL"Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
117 EOL"Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
120 //! Function computes contribution of spotlight source
121 const char THE_FUNC_spotLight[] =
122 EOL"void spotLight (in int theId,"
123 EOL" in vec3 theNormal,"
124 EOL" in vec3 theView,"
125 EOL" in vec3 thePoint,"
126 EOL" in bool theIsFront)"
128 EOL" vec3 aLight = occLight_Position (theId).xyz;"
129 EOL" vec3 aSpotDir = occLight_SpotDirection (theId).xyz;"
130 EOL" if (occLight_IsHeadlight (theId) == 0)"
132 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));"
133 EOL" aSpotDir = vec3 (occWorldViewMatrix * vec4 (aSpotDir, 0.0));"
135 EOL" aLight -= thePoint;"
137 EOL" float aDist = length (aLight);"
138 EOL" aLight = aLight * (1.0 / aDist);"
140 EOL" aSpotDir = normalize (aSpotDir);"
142 EOL" float aCosA = dot (aSpotDir, -aLight);"
143 EOL" if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
148 EOL" float anExponent = occLight_SpotExponent (theId);"
149 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
150 EOL" + occLight_LinearAttenuation (theId) * aDist);"
151 EOL" if (anExponent > 0.0)"
153 EOL" anAtten *= pow (aCosA, anExponent * 128.0);"
156 EOL" vec3 aHalf = normalize (aLight + theView);"
158 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
159 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
160 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
162 EOL" float aSpecl = 0.0;"
163 EOL" if (aNdotL > 0.0)"
165 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
168 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
169 EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
172 //! Function computes contribution of directional light source
173 const char THE_FUNC_directionalLight[] =
174 EOL"void directionalLight (in int theId,"
175 EOL" in vec3 theNormal,"
176 EOL" in vec3 theView,"
177 EOL" in bool theIsFront)"
179 EOL" vec3 aLight = normalize (occLight_Position (theId).xyz);"
180 EOL" if (occLight_IsHeadlight (theId) == 0)"
182 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));"
185 EOL" vec3 aHalf = normalize (aLight + theView);"
187 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
188 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
189 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
191 EOL" float aSpecl = 0.0;"
192 EOL" if (aNdotL > 0.0)"
194 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
197 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL;"
198 EOL" Specular += occLight_Specular (theId).rgb * aSpecl;"
201 //! The same as THE_FUNC_directionalLight but for the light with zero index
202 //! (avoids limitations on some mobile devices).
203 const char THE_FUNC_directionalLightFirst[] =
204 EOL"void directionalLightFirst (in vec3 theNormal,"
205 EOL" in vec3 theView,"
206 EOL" in bool theIsFront)"
208 EOL" vec3 aLight = normalize (occLightSources[1].xyz);"
209 EOL" if (occLight_IsHeadlight (0) == 0)"
211 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));"
214 EOL" vec3 aHalf = normalize (aLight + theView);"
216 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
217 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
218 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
220 EOL" float aSpecl = 0.0;"
221 EOL" if (aNdotL > 0.0)"
223 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
226 EOL" Diffuse += occLightSources[0].rgb * aNdotL;"
227 EOL" Specular += occLightSources[0].rgb * aSpecl;"
230 //! Process clipping planes in Fragment Shader.
231 //! Should be added at the beginning of the main() function.
232 const char THE_FRAG_CLIP_PLANES_N[] =
233 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)"
235 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
236 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)"
242 //! Process chains of clipping planes in Fragment Shader.
243 const char THE_FRAG_CLIP_CHAINS_N[] =
244 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount;)"
246 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
247 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)"
249 EOL" if (occClipPlaneChains[aPlaneIter] == 1)"
253 EOL" aPlaneIter += 1;"
257 EOL" aPlaneIter += occClipPlaneChains[aPlaneIter];"
261 //! Process 1 clipping plane in Fragment Shader.
262 const char THE_FRAG_CLIP_PLANES_1[] =
263 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
264 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0)"
269 //! Process 2 clipping planes in Fragment Shader.
270 const char THE_FRAG_CLIP_PLANES_2[] =
271 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
272 EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];"
273 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0"
274 EOL" || dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)"
279 //! Process a chain of 2 clipping planes in Fragment Shader (3/4 section).
280 const char THE_FRAG_CLIP_CHAINS_2[] =
281 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
282 EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];"
283 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0"
284 EOL" && dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)"
289 #if !defined(GL_ES_VERSION_2_0)
291 static const GLfloat THE_DEFAULT_AMBIENT[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
292 static const GLfloat THE_DEFAULT_SPOT_DIR[3] = { 0.0f, 0.0f, -1.0f };
293 static const GLfloat THE_DEFAULT_SPOT_EXPONENT = 0.0f;
294 static const GLfloat THE_DEFAULT_SPOT_CUTOFF = 180.0f;
296 //! Bind FFP light source.
297 static void bindLight (const Graphic3d_CLight& theLight,
298 const GLenum theLightGlId,
299 const OpenGl_Mat4& theModelView,
300 OpenGl_Context* theCtx)
302 // the light is a headlight?
303 if (theLight.IsHeadlight())
305 theCtx->core11->glMatrixMode (GL_MODELVIEW);
306 theCtx->core11->glLoadIdentity();
310 const Graphic3d_Vec4& aLightColor = theLight.PackedColor();
311 switch (theLight.Type())
313 case Graphic3d_TOLS_AMBIENT : break; // handled by separate if-clause at beginning of method
314 case Graphic3d_TOLS_DIRECTIONAL:
316 // if the last parameter of GL_POSITION, is zero, the corresponding light source is a Directional one
317 const OpenGl_Vec4 anInfDir = -theLight.PackedDirection();
319 // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE.
320 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
321 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
322 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
323 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, anInfDir.GetData());
324 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR);
325 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT);
326 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF);
329 case Graphic3d_TOLS_POSITIONAL:
331 // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE
332 const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position().X()), static_cast<float>(theLight.Position().Y()), static_cast<float>(theLight.Position().Z()), 1.0f);
333 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
334 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
335 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
336 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, aPosition.GetData());
337 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR);
338 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT);
339 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF);
340 theCtx->core11->glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation());
341 theCtx->core11->glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation());
342 theCtx->core11->glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0);
345 case Graphic3d_TOLS_SPOT:
347 const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position().X()), static_cast<float>(theLight.Position().Y()), static_cast<float>(theLight.Position().Z()), 1.0f);
348 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
349 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
350 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
351 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, aPosition.GetData());
352 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, theLight.PackedDirection().GetData());
353 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, theLight.Concentration() * 128.0f);
354 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, (theLight.Angle() * 180.0f) / GLfloat(M_PI));
355 theCtx->core11->glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation());
356 theCtx->core11->glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation());
357 theCtx->core11->glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f);
362 // restore matrix in case of headlight
363 if (theLight.IsHeadlight())
365 theCtx->core11->glLoadMatrixf (theModelView.GetData());
368 glEnable (theLightGlId);
374 // =======================================================================
375 // function : OpenGl_ShaderManager
376 // purpose : Creates new empty shader manager
377 // =======================================================================
378 OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
379 : myFfpProgram (new OpenGl_ShaderProgramFFP()),
380 myShadingModel (Graphic3d_TOSM_VERTEX),
381 myUnlitPrograms (new OpenGl_SetOfShaderPrograms()),
382 myContext (theContext),
383 myHasLocalOrigin (Standard_False),
389 // =======================================================================
390 // function : ~OpenGl_ShaderManager
391 // purpose : Releases resources of shader manager
392 // =======================================================================
393 OpenGl_ShaderManager::~OpenGl_ShaderManager()
395 myProgramList.Clear();
398 // =======================================================================
401 // =======================================================================
402 void OpenGl_ShaderManager::clear()
404 myProgramList.Clear();
405 myLightPrograms.Nullify();
406 myUnlitPrograms = new OpenGl_SetOfShaderPrograms();
407 myMapOfLightPrograms.Clear();
408 myFontProgram.Nullify();
409 myBlitProgram.Nullify();
410 myBoundBoxProgram.Nullify();
411 myBoundBoxVertBuffer.Nullify();
412 for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter)
414 myStereoPrograms[aModeIter].Nullify();
416 switchLightPrograms();
419 // =======================================================================
421 // purpose : Creates new shader program
422 // =======================================================================
423 Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
424 TCollection_AsciiString& theShareKey,
425 Handle(OpenGl_ShaderProgram)& theProgram)
427 theProgram.Nullify();
428 if (theProxy.IsNull())
430 return Standard_False;
433 theShareKey = theProxy->GetId();
434 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
436 if (theProgram->Share())
438 myProgramList.Append (theProgram);
440 return Standard_True;
443 theProgram = new OpenGl_ShaderProgram (theProxy);
444 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
446 theProgram->Release (myContext);
448 theProgram.Nullify();
449 return Standard_False;
452 myProgramList.Append (theProgram);
453 myContext->ShareResource (theShareKey, theProgram);
454 return Standard_True;
457 // =======================================================================
458 // function : Unregister
459 // purpose : Removes specified shader program from the manager
460 // =======================================================================
461 void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
462 Handle(OpenGl_ShaderProgram)& theProgram)
464 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
466 if (anIt.Value() == theProgram)
468 if (!theProgram->UnShare())
471 theProgram.Nullify();
475 myProgramList.Remove (anIt);
480 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
483 myContext->DelayedRelease (theProgram);
484 theProgram.Nullify();
488 theProgram.Nullify();
489 myContext->ReleaseResource (anID, Standard_True);
493 // =======================================================================
494 // function : ShaderPrograms
495 // purpose : Returns list of registered shader programs
496 // =======================================================================
497 const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
499 return myProgramList;
502 // =======================================================================
504 // purpose : Returns true if no program objects are attached
505 // =======================================================================
506 Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
508 return myProgramList.IsEmpty();
511 // =======================================================================
512 // function : switchLightPrograms
514 // =======================================================================
515 void OpenGl_ShaderManager::switchLightPrograms()
517 const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources();
518 if (aLights.IsNull())
520 myLightPrograms = myUnlitPrograms;
524 TCollection_AsciiString aKey ("l_");
525 if (aLights->NbEnabled() <= THE_NB_UNROLLED_LIGHTS_MAX)
527 aKey += aLights->KeyEnabledLong();
531 const Standard_Integer aMaxLimit = roundUpMaxLightSources (aLights->NbEnabled());
532 aKey += aLights->KeyEnabledShort();
536 if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
538 myLightPrograms = new OpenGl_SetOfShaderPrograms();
539 myMapOfLightPrograms.Bind (aKey, myLightPrograms);
543 // =======================================================================
544 // function : UpdateLightSourceStateTo
545 // purpose : Updates state of OCCT light sources
546 // =======================================================================
547 void OpenGl_ShaderManager::UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights)
549 myLightSourceState.Set (theLights);
550 myLightSourceState.Update();
551 switchLightPrograms();
554 // =======================================================================
555 // function : UpdateLightSourceState
557 // =======================================================================
558 void OpenGl_ShaderManager::UpdateLightSourceState()
560 myLightSourceState.Update();
563 // =======================================================================
564 // function : SetShadingModel
566 // =======================================================================
567 void OpenGl_ShaderManager::SetShadingModel (const Graphic3d_TypeOfShadingModel theModel)
569 if (theModel == Graphic3d_TOSM_DEFAULT)
571 throw Standard_ProgramError ("OpenGl_ShaderManager::SetShadingModel() - attempt to set invalid Shading Model!");
574 myShadingModel = theModel;
575 switchLightPrograms();
578 // =======================================================================
579 // function : SetProjectionState
580 // purpose : Sets new state of OCCT projection transform
581 // =======================================================================
582 void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix)
584 myProjectionState.Set (theProjectionMatrix);
585 myProjectionState.Update();
588 // =======================================================================
589 // function : SetModelWorldState
590 // purpose : Sets new state of OCCT model-world transform
591 // =======================================================================
592 void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix)
594 myModelWorldState.Set (theModelWorldMatrix);
595 myModelWorldState.Update();
598 // =======================================================================
599 // function : SetWorldViewState
600 // purpose : Sets new state of OCCT world-view transform
601 // =======================================================================
602 void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix)
604 myWorldViewState.Set (theWorldViewMatrix);
605 myWorldViewState.Update();
608 // =======================================================================
609 // function : PushLightSourceState
610 // purpose : Pushes state of OCCT light sources to the program
611 // =======================================================================
612 void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
614 if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE))
619 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
620 if (theProgram == myFfpProgram)
622 #if !defined(GL_ES_VERSION_2_0)
623 if (myContext->core11 == NULL)
628 GLenum aLightGlId = GL_LIGHT0;
629 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
630 for (Graphic3d_LightSet::Iterator aLightIt (myLightSourceState.LightSources(), Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
631 aLightIt.More(); aLightIt.Next())
633 if (aLightGlId > GL_LIGHT7) // only 8 lights in FFP...
635 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
636 "Warning: light sources limit (8) has been exceeded within Fixed-function pipeline.");
640 bindLight (*aLightIt.Value(), aLightGlId, aModelView, myContext);
644 // apply accumulated ambient color
645 const Graphic3d_Vec4 anAmbient = !myLightSourceState.LightSources().IsNull()
646 ? myLightSourceState.LightSources()->AmbientColor()
647 : Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 1.0f);
648 myContext->core11->glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbient.GetData());
650 // GL_LIGHTING is managed by drawers to switch between shaded / no lighting output,
651 // therefore managing the state here does not have any effect - do it just for consistency.
652 if (aLightGlId != GL_LIGHT0)
654 ::glEnable (GL_LIGHTING);
658 ::glDisable (GL_LIGHTING);
660 // switch off unused lights
661 for (; aLightGlId <= GL_LIGHT7; ++aLightGlId)
663 ::glDisable (aLightGlId);
669 const Standard_Integer aNbLightsMax = theProgram->NbLightsMax();
670 const GLint anAmbientLoc = theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT);
671 if (aNbLightsMax == 0
672 && anAmbientLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
677 if (myLightTypeArray.Size() < aNbLightsMax)
679 myLightTypeArray .Resize (0, aNbLightsMax - 1, false);
680 myLightParamsArray.Resize (0, aNbLightsMax - 1, false);
682 for (Standard_Integer aLightIt = 0; aLightIt < aNbLightsMax; ++aLightIt)
684 myLightTypeArray.ChangeValue (aLightIt).Type = -1;
687 if (myLightSourceState.LightSources().IsNull()
688 || myLightSourceState.LightSources()->IsEmpty())
690 theProgram->SetUniform (myContext,
691 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
693 theProgram->SetUniform (myContext,
695 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
696 theProgram->SetUniform (myContext,
697 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
698 aNbLightsMax * OpenGl_ShaderLightType::NbOfVec2i(),
699 myLightTypeArray.First().Packed());
703 Standard_Integer aLightsNb = 0;
704 for (Graphic3d_LightSet::Iterator anIter (myLightSourceState.LightSources(), Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
705 anIter.More(); anIter.Next())
707 const Graphic3d_CLight& aLight = *anIter.Value();
708 if (aLightsNb >= aNbLightsMax)
710 if (aNbLightsMax != 0)
712 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
713 TCollection_AsciiString("Warning: light sources limit (") + aNbLightsMax + ") has been exceeded.");
718 OpenGl_ShaderLightType& aLightType = myLightTypeArray.ChangeValue (aLightsNb);
719 OpenGl_ShaderLightParameters& aLightParams = myLightParamsArray.ChangeValue (aLightsNb);
720 if (!aLight.IsEnabled()) // has no affect with Graphic3d_LightSet::IterationFilter_ExcludeDisabled - here just for consistency
722 // if it is desired to keep disabled light in the same order - we can replace it with a black light so that it will have no influence on result
723 aLightType.Type = -1; // Graphic3d_TOLS_AMBIENT can be used instead
724 aLightType.IsHeadlight = false;
725 aLightParams.Color = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f);
730 aLightType.Type = aLight.Type();
731 aLightType.IsHeadlight = aLight.IsHeadlight();
732 aLightParams.Color = aLight.PackedColor();
733 if (aLight.Type() == Graphic3d_TOLS_DIRECTIONAL)
735 aLightParams.Position = -aLight.PackedDirection();
737 else if (!aLight.IsHeadlight())
739 aLightParams.Position.x() = static_cast<float>(aLight.Position().X() - myLocalOrigin.X());
740 aLightParams.Position.y() = static_cast<float>(aLight.Position().Y() - myLocalOrigin.Y());
741 aLightParams.Position.z() = static_cast<float>(aLight.Position().Z() - myLocalOrigin.Z());
742 aLightParams.Position.w() = 1.0f;
746 aLightParams.Position.x() = static_cast<float>(aLight.Position().X());
747 aLightParams.Position.y() = static_cast<float>(aLight.Position().Y());
748 aLightParams.Position.z() = static_cast<float>(aLight.Position().Z());
749 aLightParams.Position.w() = 1.0f;
752 if (aLight.Type() == Graphic3d_TOLS_SPOT)
754 aLightParams.Direction = aLight.PackedDirection();
756 aLightParams.Parameters = aLight.PackedParams();
760 const Graphic3d_Vec4& anAmbient = myLightSourceState.LightSources()->AmbientColor();
761 theProgram->SetUniform (myContext,
762 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
764 theProgram->SetUniform (myContext,
767 theProgram->SetUniform (myContext,
768 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
769 aNbLightsMax * OpenGl_ShaderLightType::NbOfVec2i(),
770 myLightTypeArray.First().Packed());
773 theProgram->SetUniform (myContext,
774 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
775 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
776 myLightParamsArray.First().Packed());
780 // =======================================================================
781 // function : PushProjectionState
782 // purpose : Pushes state of OCCT projection transform to the program
783 // =======================================================================
784 void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
786 if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE))
791 theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
792 if (theProgram == myFfpProgram)
794 #if !defined(GL_ES_VERSION_2_0)
795 if (myContext->core11 != NULL)
797 myContext->core11->glMatrixMode (GL_PROJECTION);
798 myContext->core11->glLoadMatrixf (myProjectionState.ProjectionMatrix());
804 theProgram->SetUniform (myContext,
805 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
806 myProjectionState.ProjectionMatrix());
808 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
809 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
811 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
814 theProgram->SetUniform (myContext,
815 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
816 myProjectionState.ProjectionMatrix(), true);
818 aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
819 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
821 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
825 // =======================================================================
826 // function : PushModelWorldState
827 // purpose : Pushes state of OCCT model-world transform to the program
828 // =======================================================================
829 void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
831 if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
836 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
837 if (theProgram == myFfpProgram)
839 #if !defined(GL_ES_VERSION_2_0)
840 if (myContext->core11 != NULL)
842 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
843 myContext->core11->glMatrixMode (GL_MODELVIEW);
844 myContext->core11->glLoadMatrixf (aModelView.GetData());
845 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
851 theProgram->SetUniform (myContext,
852 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
853 myModelWorldState.ModelWorldMatrix());
855 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
856 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
858 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
861 theProgram->SetUniform (myContext,
862 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
863 myModelWorldState.ModelWorldMatrix(), true);
865 aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
866 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
868 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
872 // =======================================================================
873 // function : PushWorldViewState
874 // purpose : Pushes state of OCCT world-view transform to the program
875 // =======================================================================
876 void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
878 if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
883 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
884 if (theProgram == myFfpProgram)
886 #if !defined(GL_ES_VERSION_2_0)
887 if (myContext->core11 != NULL)
889 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
890 myContext->core11->glMatrixMode (GL_MODELVIEW);
891 myContext->core11->glLoadMatrixf (aModelView.GetData());
892 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
898 theProgram->SetUniform (myContext,
899 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
900 myWorldViewState.WorldViewMatrix());
902 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
903 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
905 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
908 theProgram->SetUniform (myContext,
909 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
910 myWorldViewState.WorldViewMatrix(), true);
912 aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
913 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
915 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
919 // =======================================================================
920 // function : UpdateClippingState
921 // purpose : Updates state of OCCT clipping planes
922 // =======================================================================
923 void OpenGl_ShaderManager::UpdateClippingState()
925 myClippingState.Update();
928 // =======================================================================
929 // function : RevertClippingState
930 // purpose : Reverts state of OCCT clipping planes
931 // =======================================================================
932 void OpenGl_ShaderManager::RevertClippingState()
934 myClippingState.Revert();
937 // =======================================================================
938 // function : PushClippingState
939 // purpose : Pushes state of OCCT clipping planes to the program
940 // =======================================================================
941 void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
943 if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
948 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
949 if (theProgram == myFfpProgram)
951 #if !defined(GL_ES_VERSION_2_0)
952 if (myContext->core11 == NULL)
957 const Standard_Integer aNbMaxPlanes = myContext->MaxClipPlanes();
958 if (myClipPlaneArrayFfp.Size() < aNbMaxPlanes)
960 myClipPlaneArrayFfp.Resize (0, aNbMaxPlanes - 1, false);
963 Standard_Integer aPlaneId = 0;
964 Standard_Boolean toRestoreModelView = Standard_False;
965 const Handle(Graphic3d_ClipPlane)& aCappedChain = myContext->Clipping().CappedChain();
966 for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
968 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
969 if (aPlaneIter.IsDisabled()
971 || (aPlane == aCappedChain
972 && myContext->Clipping().IsCappingEnableAllExcept()))
976 else if (aPlaneId >= aNbMaxPlanes)
978 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
979 TCollection_ExtendedString("Warning: clipping planes limit (") + aNbMaxPlanes + ") has been exceeded.");
983 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
984 OpenGl_Vec4d& aPlaneEq = myClipPlaneArrayFfp.ChangeValue (aPlaneId);
985 aPlaneEq.x() = anEquation.x();
986 aPlaneEq.y() = anEquation.y();
987 aPlaneEq.z() = anEquation.z();
988 aPlaneEq.w() = anEquation.w();
989 if (myHasLocalOrigin)
991 const gp_XYZ aPos = aPlane->ToPlane().Position().Location().XYZ() - myLocalOrigin;
992 const Standard_Real aD = -(anEquation.x() * aPos.X() + anEquation.y() * aPos.Y() + anEquation.z() * aPos.Z());
996 const GLenum anFfpPlaneID = GL_CLIP_PLANE0 + aPlaneId;
997 if (anFfpPlaneID == GL_CLIP_PLANE0)
999 // set either identity or pure view matrix
1000 toRestoreModelView = Standard_True;
1001 myContext->core11->glMatrixMode (GL_MODELVIEW);
1002 myContext->core11->glLoadMatrixf (myWorldViewState.WorldViewMatrix().GetData());
1005 ::glEnable (anFfpPlaneID);
1006 myContext->core11->glClipPlane (anFfpPlaneID, aPlaneEq);
1011 // switch off unused lights
1012 for (; aPlaneId < aNbMaxPlanes; ++aPlaneId)
1014 ::glDisable (GL_CLIP_PLANE0 + aPlaneId);
1017 // restore combined model-view matrix
1018 if (toRestoreModelView)
1020 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
1021 myContext->core11->glLoadMatrixf (aModelView.GetData());
1027 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
1028 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION)
1033 const Standard_Integer aNbClipPlanesMax = theProgram->NbClipPlanesMax();
1034 const Standard_Integer aNbPlanes = Min (myContext->Clipping().NbClippingOrCappingOn(), aNbClipPlanesMax);
1037 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), 0);
1041 if (myClipPlaneArray.Size() < aNbClipPlanesMax)
1043 myClipPlaneArray.Resize (0, aNbClipPlanesMax - 1, false);
1044 myClipChainArray.Resize (0, aNbClipPlanesMax - 1, false);
1047 Standard_Integer aPlaneId = 0;
1048 const Handle(Graphic3d_ClipPlane)& aCappedChain = myContext->Clipping().CappedChain();
1049 for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
1051 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
1052 if (aPlaneIter.IsDisabled())
1057 if (myContext->Clipping().IsCappingDisableAllExcept())
1059 // enable only specific (sub) plane
1060 if (aPlane != aCappedChain)
1065 Standard_Integer aSubPlaneIndex = 1;
1066 for (const Graphic3d_ClipPlane* aSubPlaneIter = aCappedChain.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex)
1068 if (aSubPlaneIndex == myContext->Clipping().CappedSubPlane())
1070 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->GetEquation(), 1);
1076 else if (aPlane == aCappedChain) // && myContext->Clipping().IsCappingEnableAllExcept()
1078 // enable sub-planes within processed Chain as reversed and ORed, excluding filtered plane
1079 if (aPlaneId + aPlane->NbChainNextPlanes() - 1 > aNbClipPlanesMax)
1081 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
1082 TCollection_AsciiString("Error: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded.");
1086 Standard_Integer aSubPlaneIndex = 1;
1087 for (const Graphic3d_ClipPlane* aSubPlaneIter = aPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex)
1089 if (aSubPlaneIndex != -myContext->Clipping().CappedSubPlane())
1091 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->ReversedEquation(), 1);
1098 if (aPlaneId + aPlane->NbChainNextPlanes() > aNbClipPlanesMax)
1100 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
1101 TCollection_AsciiString("Error: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded.");
1104 for (const Graphic3d_ClipPlane* aSubPlaneIter = aPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get())
1106 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->GetEquation(), aSubPlaneIter->NbChainNextPlanes());
1111 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), aPlaneId);
1112 theProgram->SetUniform (myContext, aLocEquations, aNbClipPlanesMax, &myClipPlaneArray.First());
1113 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_CHAINS), aNbClipPlanesMax, &myClipChainArray.First());
1116 // =======================================================================
1117 // function : PushMaterialState
1119 // =======================================================================
1120 void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1122 if (myMaterialState.Index() == theProgram->ActiveState (OpenGl_MATERIAL_STATE))
1127 const OpenGl_Material& aFrontMat = myMaterialState.FrontMaterial();
1128 const OpenGl_Material& aBackMat = myMaterialState.BackMaterial();
1129 theProgram->UpdateState (OpenGl_MATERIAL_STATE, myMaterialState.Index());
1130 if (theProgram == myFfpProgram)
1132 #if !defined(GL_ES_VERSION_2_0)
1133 if (myContext->core11 == NULL)
1138 if (myMaterialState.AlphaCutoff() < ShortRealLast())
1140 glAlphaFunc (GL_GEQUAL, myMaterialState.AlphaCutoff());
1141 glEnable (GL_ALPHA_TEST);
1145 glDisable (GL_ALPHA_TEST);
1148 const GLenum aFrontFace = myMaterialState.ToDistinguish() ? GL_FRONT : GL_FRONT_AND_BACK;
1149 myContext->core11->glMaterialfv(aFrontFace, GL_AMBIENT, aFrontMat.Ambient.GetData());
1150 myContext->core11->glMaterialfv(aFrontFace, GL_DIFFUSE, aFrontMat.Diffuse.GetData());
1151 myContext->core11->glMaterialfv(aFrontFace, GL_SPECULAR, aFrontMat.Specular.GetData());
1152 myContext->core11->glMaterialfv(aFrontFace, GL_EMISSION, aFrontMat.Emission.GetData());
1153 myContext->core11->glMaterialf (aFrontFace, GL_SHININESS, aFrontMat.Shine());
1154 if (myMaterialState.ToDistinguish())
1156 myContext->core11->glMaterialfv(GL_BACK, GL_AMBIENT, aBackMat.Ambient.GetData());
1157 myContext->core11->glMaterialfv(GL_BACK, GL_DIFFUSE, aBackMat.Diffuse.GetData());
1158 myContext->core11->glMaterialfv(GL_BACK, GL_SPECULAR, aBackMat.Specular.GetData());
1159 myContext->core11->glMaterialfv(GL_BACK, GL_EMISSION, aBackMat.Emission.GetData());
1160 myContext->core11->glMaterialf (GL_BACK, GL_SHININESS, aBackMat.Shine());
1166 theProgram->SetUniform (myContext,
1167 theProgram->GetStateLocation (OpenGl_OCCT_ALPHA_CUTOFF),
1168 myMaterialState.AlphaCutoff());
1169 theProgram->SetUniform (myContext,
1170 theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
1171 myMaterialState.ToMapTexture() ? 1 : 0);
1172 theProgram->SetUniform (myContext,
1173 theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
1174 myMaterialState.ToDistinguish() ? 1 : 0);
1176 const GLint aLocFront = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL);
1177 if (aLocFront != OpenGl_ShaderProgram::INVALID_LOCATION)
1179 theProgram->SetUniform (myContext, aLocFront, OpenGl_Material::NbOfVec4(),
1180 aFrontMat.Packed());
1183 const GLint aLocBack = theProgram->GetStateLocation (OpenGl_OCCT_BACK_MATERIAL);
1184 if (aLocBack != OpenGl_ShaderProgram::INVALID_LOCATION)
1186 theProgram->SetUniform (myContext, aLocBack, OpenGl_Material::NbOfVec4(),
1191 // =======================================================================
1192 // function : PushOitState
1193 // purpose : Pushes state of OIT uniforms to the specified program
1194 // =======================================================================
1195 void OpenGl_ShaderManager::PushOitState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1197 if (!theProgram->IsValid())
1202 if (myOitState.Index() == theProgram->ActiveState (OpenGL_OIT_STATE))
1207 const GLint aLocOutput = theProgram->GetStateLocation (OpenGl_OCCT_OIT_OUTPUT);
1208 if (aLocOutput != OpenGl_ShaderProgram::INVALID_LOCATION)
1210 theProgram->SetUniform (myContext, aLocOutput, myOitState.ToEnableWrite());
1213 const GLint aLocDepthFactor = theProgram->GetStateLocation (OpenGl_OCCT_OIT_DEPTH_FACTOR);
1214 if (aLocDepthFactor != OpenGl_ShaderProgram::INVALID_LOCATION)
1216 theProgram->SetUniform (myContext, aLocDepthFactor, myOitState.DepthFactor());
1220 // =======================================================================
1221 // function : PushState
1222 // purpose : Pushes state of OCCT graphics parameters to the program
1223 // =======================================================================
1224 void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1226 const Handle(OpenGl_ShaderProgram)& aProgram = !theProgram.IsNull() ? theProgram : myFfpProgram;
1227 PushClippingState (aProgram);
1228 PushWorldViewState (aProgram);
1229 PushModelWorldState (aProgram);
1230 PushProjectionState (aProgram);
1231 PushLightSourceState (aProgram);
1232 PushMaterialState (aProgram);
1233 PushOitState (aProgram);
1236 // =======================================================================
1237 // function : prepareStdProgramFont
1239 // =======================================================================
1240 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
1242 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1243 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
1244 + EOL"THE_SHADER_OUT vec2 TexCoord;"
1247 EOL" TexCoord = occTexCoord.st;"
1248 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1251 TCollection_AsciiString
1252 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).a; }";
1253 #if !defined(GL_ES_VERSION_2_0)
1254 if (myContext->core11 == NULL)
1256 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).r; }";
1260 TCollection_AsciiString aSrcFrag = TCollection_AsciiString() +
1261 + EOL"THE_SHADER_IN vec2 TexCoord;"
1265 EOL" vec4 aColor = occColor;"
1266 EOL" aColor.a *= getAlpha();"
1267 EOL" if (aColor.a <= 0.285) discard;"
1268 EOL" occSetFragColor (aColor);"
1271 #if !defined(GL_ES_VERSION_2_0)
1272 if (myContext->core32 != NULL)
1274 aProgramSrc->SetHeader ("#version 150");
1277 if (myContext->IsGlGreaterEqual (3, 1))
1279 // prefer "100 es" on OpenGL ES 3.0 devices
1280 // and "300 es" on newer devices (3.1+)
1281 aProgramSrc->SetHeader ("#version 300 es");
1284 aProgramSrc->SetNbLightsMax (0);
1285 aProgramSrc->SetNbClipPlanesMax (0);
1286 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1287 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1288 TCollection_AsciiString aKey;
1289 if (!Create (aProgramSrc, aKey, myFontProgram))
1291 myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1292 return Standard_False;
1294 return Standard_True;
1297 // =======================================================================
1298 // function : prepareStdProgramFboBlit
1300 // =======================================================================
1301 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit()
1303 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1304 TCollection_AsciiString aSrcVert =
1305 EOL"THE_SHADER_OUT vec2 TexCoord;"
1308 EOL" TexCoord = occVertex.zw;"
1309 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1312 TCollection_AsciiString aSrcFrag =
1313 EOL"uniform sampler2D uColorSampler;"
1314 EOL"uniform sampler2D uDepthSampler;"
1316 EOL"THE_SHADER_IN vec2 TexCoord;"
1320 EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;"
1321 EOL" occSetFragColor (occTexture2D (uColorSampler, TexCoord));"
1324 #if defined(GL_ES_VERSION_2_0)
1325 if (myContext->IsGlGreaterEqual (3, 0))
1327 aProgramSrc->SetHeader ("#version 300 es");
1329 else if (myContext->extFragDepth)
1331 aProgramSrc->SetHeader ("#extension GL_EXT_frag_depth : enable"
1332 EOL"#define gl_FragDepth gl_FragDepthEXT");
1336 // there is no way to draw into depth buffer
1338 EOL"uniform sampler2D uColorSampler;"
1340 EOL"THE_SHADER_IN vec2 TexCoord;"
1344 EOL" occSetFragColor (occTexture2D (uColorSampler, TexCoord));"
1348 if (myContext->core32 != NULL)
1350 aProgramSrc->SetHeader ("#version 150");
1353 aProgramSrc->SetNbLightsMax (0);
1354 aProgramSrc->SetNbClipPlanesMax (0);
1355 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1356 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1357 TCollection_AsciiString aKey;
1358 if (!Create (aProgramSrc, aKey, myBlitProgram))
1360 myBlitProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1361 return Standard_False;
1364 myContext->BindProgram (myBlitProgram);
1365 myBlitProgram->SetSampler (myContext, "uColorSampler", Graphic3d_TextureUnit_0);
1366 myBlitProgram->SetSampler (myContext, "uDepthSampler", Graphic3d_TextureUnit_1);
1367 myContext->BindProgram (NULL);
1368 return Standard_True;
1371 // =======================================================================
1372 // function : prepareStdProgramOitCompositing
1374 // =======================================================================
1375 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const Standard_Boolean theMsaa)
1377 Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram[theMsaa ? 1 : 0];
1378 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1379 TCollection_AsciiString aSrcVert, aSrcFrag;
1382 EOL"THE_SHADER_OUT vec2 TexCoord;"
1385 EOL" TexCoord = occVertex.zw;"
1386 EOL" gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);"
1392 EOL"uniform sampler2D uAccumTexture;"
1393 EOL"uniform sampler2D uWeightTexture;"
1395 EOL"THE_SHADER_IN vec2 TexCoord;"
1399 EOL" vec4 aAccum = occTexture2D (uAccumTexture, TexCoord);"
1400 EOL" float aWeight = occTexture2D (uWeightTexture, TexCoord).r;"
1401 EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
1403 #if !defined(GL_ES_VERSION_2_0)
1404 if (myContext->IsGlGreaterEqual (3, 2))
1406 aProgramSrc->SetHeader ("#version 150");
1409 if (myContext->IsGlGreaterEqual (3, 0))
1411 aProgramSrc->SetHeader ("#version 300 es");
1418 EOL"uniform sampler2DMS uAccumTexture;"
1419 EOL"uniform sampler2DMS uWeightTexture;"
1421 EOL"THE_SHADER_IN vec2 TexCoord;"
1425 EOL" ivec2 aTexel = ivec2 (vec2 (textureSize (uAccumTexture)) * TexCoord);"
1426 EOL" vec4 aAccum = texelFetch (uAccumTexture, aTexel, gl_SampleID);"
1427 EOL" float aWeight = texelFetch (uWeightTexture, aTexel, gl_SampleID).r;"
1428 EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
1430 #if !defined(GL_ES_VERSION_2_0)
1431 if (myContext->IsGlGreaterEqual (4, 0))
1433 aProgramSrc->SetHeader ("#version 400");
1436 if (myContext->IsGlGreaterEqual (3, 2))
1438 aProgramSrc->SetHeader ("#version 320 es");
1440 else if (myContext->IsGlGreaterEqual (3, 0))
1442 aProgramSrc->SetHeader ("#version 300 es"); // with GL_OES_sample_variables extension
1447 aProgramSrc->SetNbLightsMax (0);
1448 aProgramSrc->SetNbClipPlanesMax (0);
1449 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1450 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1451 TCollection_AsciiString aKey;
1452 if (!Create (aProgramSrc, aKey, aProgram))
1454 aProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1455 return Standard_False;
1458 myContext->BindProgram (aProgram);
1459 aProgram->SetSampler (myContext, "uAccumTexture", Graphic3d_TextureUnit_0);
1460 aProgram->SetSampler (myContext, "uWeightTexture", Graphic3d_TextureUnit_1);
1461 myContext->BindProgram (Handle(OpenGl_ShaderProgram)());
1462 return Standard_True;
1465 // =======================================================================
1466 // function : pointSpriteAlphaSrc
1468 // =======================================================================
1469 TCollection_AsciiString OpenGl_ShaderManager::pointSpriteAlphaSrc (const Standard_Integer theBits)
1471 TCollection_AsciiString aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord ").a; }";
1472 #if !defined(GL_ES_VERSION_2_0)
1473 if (myContext->core11 == NULL
1474 && (theBits & OpenGl_PO_TextureA) != 0)
1476 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord ").r; }";
1481 return aSrcGetAlpha;
1487 // =======================================================================
1488 // function : textureUsed
1490 // =======================================================================
1491 static bool textureUsed (const Standard_Integer theBits)
1493 return (theBits & OpenGl_PO_TextureA) != 0 || (theBits & OpenGl_PO_TextureRGB) != 0;
1498 // =======================================================================
1499 // function : prepareStdProgramUnlit
1501 // =======================================================================
1502 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_ShaderProgram)& theProgram,
1503 const Standard_Integer theBits)
1505 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1506 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha;
1507 TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain, aSrcFragWriteOit;
1508 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
1509 TCollection_AsciiString aSrcFragMainGetColor = EOL" occSetFragColor (getColor());";
1510 if ((theBits & OpenGl_PO_Point) != 0)
1512 #if defined(GL_ES_VERSION_2_0)
1513 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1516 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1519 EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord "); }";
1522 if (textureUsed (theBits))
1524 aSrcGetAlpha = pointSpriteAlphaSrc (theBits);
1526 #if !defined(GL_ES_VERSION_2_0)
1527 if (myContext->core11 != NULL
1528 && myContext->IsGlGreaterEqual (2, 1))
1530 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1534 aSrcFragMainGetColor =
1535 EOL" vec4 aColor = getColor();"
1536 EOL" aColor.a = getAlpha();"
1537 EOL" if (aColor.a <= 0.1) discard;"
1538 EOL" occSetFragColor (aColor);";
1542 aSrcFragMainGetColor =
1543 EOL" vec4 aColor = getColor();"
1544 EOL" if (aColor.a <= 0.1) discard;"
1545 EOL" occSetFragColor (aColor);";
1550 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1552 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1553 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1554 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
1557 EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w); }";
1559 else if ((theBits & OpenGl_PO_TextureEnv) != 0)
1561 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1562 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1564 aSrcVertExtraFunc = THE_FUNC_transformNormal;
1566 aSrcVertExtraMain +=
1567 EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1568 EOL" vec3 aNormal = transformNormal (occNormal);"
1569 EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);"
1570 EOL" aReflect.z += 1.0;"
1571 EOL" TexCoord = vec4(aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5), 0.0, 1.0);";
1574 EOL"vec4 getColor(void) { return occTexture2D (occSamplerBaseColor, TexCoord.st); }";
1577 if ((theBits & OpenGl_PO_VertColor) != 0)
1579 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
1580 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1581 aSrcFragExtraOut += EOL"THE_SHADER_IN vec4 VertColor;";
1582 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
1585 int aNbClipPlanes = 0;
1586 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
1589 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1590 EOL"THE_SHADER_OUT vec4 Position;";
1592 EOL"THE_SHADER_IN vec4 PositionWorld;"
1593 EOL"THE_SHADER_IN vec4 Position;";
1594 aSrcVertExtraMain +=
1595 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1596 EOL" Position = occWorldViewMatrix * PositionWorld;";
1598 if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1601 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
1603 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
1606 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
1607 ? THE_FRAG_CLIP_CHAINS_2
1608 : THE_FRAG_CLIP_PLANES_2;
1612 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
1613 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
1614 ? THE_FRAG_CLIP_CHAINS_N
1615 : THE_FRAG_CLIP_PLANES_N;
1618 if ((theBits & OpenGl_PO_WriteOit) != 0)
1620 aProgramSrc->SetNbFragmentOutputs (2);
1621 aProgramSrc->SetWeightOitOutput (true);
1622 #if defined(GL_ES_VERSION_2_0)
1623 if (myContext->IsGlGreaterEqual (3, 0))
1625 aProgramSrc->SetHeader ("#version 300 es");
1630 TCollection_AsciiString aSrcVertEndMain;
1631 if ((theBits & OpenGl_PO_StippleLine) != 0)
1633 bool hasGlslBitOps = false;
1634 #if defined(GL_ES_VERSION_2_0)
1635 if (myContext->IsGlGreaterEqual (3, 0))
1637 aProgramSrc->SetHeader ("#version 300 es");
1638 hasGlslBitOps = true;
1641 if (myContext->IsGlGreaterEqual (3, 0))
1643 aProgramSrc->SetHeader ("#version 130");
1644 hasGlslBitOps = true;
1646 else if(myContext->CheckExtension("GL_EXT_gpu_shader4"))
1648 aProgramSrc->SetHeader ("#extension GL_EXT_gpu_shader4 : enable");
1649 hasGlslBitOps = true;
1656 EOL"THE_SHADER_OUT vec2 ScreenSpaceCoord;";
1658 EOL"THE_SHADER_IN vec2 ScreenSpaceCoord;"
1659 EOL"uniform int uPattern;"
1660 EOL"uniform float uFactor;";
1662 EOL" ScreenSpaceCoord = gl_Position.xy / gl_Position.w;";
1663 aSrcFragMainGetColor =
1664 EOL" float anAngle = atan (dFdx (ScreenSpaceCoord.x), dFdy (ScreenSpaceCoord.y));"
1665 EOL" float aRotatePoint = gl_FragCoord.x * sin (anAngle) + gl_FragCoord.y * cos (anAngle);"
1666 EOL" uint aBit = uint (floor (aRotatePoint / uFactor + 0.5)) & 15U;"
1667 EOL" if ((uint (uPattern) & (1U << aBit)) == 0U) discard;"
1668 EOL" vec4 aColor = getColor();"
1669 EOL" if (aColor.a <= 0.1) discard;"
1670 EOL" occSetFragColor (aColor);";
1674 const TCollection_ExtendedString aWarnMessage =
1675 "Warning: stipple lines in GLSL will be ignored.";
1676 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
1677 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, aWarnMessage);
1687 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1698 + aSrcFragMainGetColor
1702 #if !defined(GL_ES_VERSION_2_0)
1703 if (myContext->core32 != NULL)
1705 aProgramSrc->SetHeader ("#version 150");
1708 if (myContext->IsGlGreaterEqual (3, 1))
1710 // prefer "100 es" on OpenGL ES 3.0 devices
1711 // and "300 es" on newer devices (3.1+)
1712 aProgramSrc->SetHeader ("#version 300 es");
1715 aProgramSrc->SetNbLightsMax (0);
1716 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
1717 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
1718 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
1719 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
1721 TCollection_AsciiString aKey;
1722 if (!Create (aProgramSrc, aKey, theProgram))
1724 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1725 return Standard_False;
1727 return Standard_True;
1730 // =======================================================================
1731 // function : pointSpriteShadingSrc
1733 // =======================================================================
1734 TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TCollection_AsciiString theBaseColorSrc,
1735 const Standard_Integer theBits)
1737 TCollection_AsciiString aSrcFragGetColor;
1738 if ((theBits & OpenGl_PO_TextureA) != 0)
1740 aSrcFragGetColor = pointSpriteAlphaSrc (theBits) +
1741 EOL"vec4 getColor(void)"
1743 EOL" vec4 aColor = " + theBaseColorSrc + ";"
1744 EOL" aColor.a = getAlpha();"
1745 EOL" if (aColor.a <= 0.1) discard;"
1746 EOL" return aColor;"
1749 else if ((theBits & OpenGl_PO_TextureRGB) != 0)
1751 aSrcFragGetColor = TCollection_AsciiString() +
1752 EOL"vec4 getColor(void)"
1754 EOL" vec4 aColor = " + theBaseColorSrc + ";"
1755 EOL" aColor = occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord ") * aColor;"
1756 EOL" if (aColor.a <= 0.1) discard;"
1757 EOL" return aColor;"
1761 return aSrcFragGetColor;
1764 // =======================================================================
1765 // function : stdComputeLighting
1767 // =======================================================================
1768 TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integer& theNbLights,
1769 Standard_Boolean theHasVertColor)
1771 TCollection_AsciiString aLightsFunc, aLightsLoop;
1773 const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources();
1774 if (!aLights.IsNull())
1776 theNbLights = aLights->NbEnabled();
1777 if (theNbLights <= THE_NB_UNROLLED_LIGHTS_MAX)
1779 Standard_Integer anIndex = 0;
1780 for (Graphic3d_LightSet::Iterator aLightIter (aLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
1781 aLightIter.More(); aLightIter.Next(), ++anIndex)
1783 switch (aLightIter.Value()->Type())
1785 case Graphic3d_TOLS_AMBIENT:
1787 break; // skip ambient
1788 case Graphic3d_TOLS_DIRECTIONAL:
1789 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
1791 case Graphic3d_TOLS_POSITIONAL:
1792 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1794 case Graphic3d_TOLS_SPOT:
1795 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1802 theNbLights = roundUpMaxLightSources (theNbLights);
1803 bool isFirstInLoop = true;
1804 aLightsLoop = aLightsLoop +
1805 EOL" for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)"
1807 EOL" int aType = occLight_Type (anIndex);";
1808 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0)
1810 isFirstInLoop = false;
1812 EOL" if (aType == OccLightType_Direct)"
1814 EOL" directionalLight (anIndex, theNormal, theView, theIsFront);"
1817 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
1821 aLightsLoop += EOL" else ";
1823 isFirstInLoop = false;
1825 EOL" if (aType == OccLightType_Point)"
1827 EOL" pointLight (anIndex, theNormal, theView, aPoint, theIsFront);"
1830 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0)
1834 aLightsLoop += EOL" else ";
1836 isFirstInLoop = false;
1838 EOL" if (aType == OccLightType_Spot)"
1840 EOL" spotLight (anIndex, theNormal, theView, aPoint, theIsFront);"
1843 aLightsLoop += EOL" }";
1845 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) == 1
1846 && theNbLights == 1)
1848 // use the version with hard-coded first index
1849 aLightsLoop = EOL" directionalLightFirst(theNormal, theView, theIsFront);";
1850 aLightsFunc += THE_FUNC_directionalLightFirst;
1852 else if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0)
1854 aLightsFunc += THE_FUNC_directionalLight;
1856 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
1858 aLightsFunc += THE_FUNC_pointLight;
1860 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0)
1862 aLightsFunc += THE_FUNC_spotLight;
1866 TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();";
1867 TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();";
1868 if (theHasVertColor)
1870 aGetMatAmbient = "getVertColor();";
1871 aGetMatDiffuse = "getVertColor();";
1874 return TCollection_AsciiString()
1878 EOL"vec4 computeLighting (in vec3 theNormal,"
1879 EOL" in vec3 theView,"
1880 EOL" in vec4 thePoint,"
1881 EOL" in bool theIsFront)"
1883 EOL" Ambient = occLightAmbient.rgb;"
1884 EOL" Diffuse = vec3 (0.0);"
1885 EOL" Specular = vec3 (0.0);"
1886 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
1888 + EOL" vec4 aMatAmbient = " + aGetMatAmbient
1889 + EOL" vec4 aMatDiffuse = " + aGetMatDiffuse
1890 + EOL" vec4 aMatSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
1891 EOL" vec4 aMatEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
1892 EOL" vec3 aColor = Ambient * aMatAmbient.rgb"
1893 EOL" + Diffuse * aMatDiffuse.rgb"
1894 EOL" + Specular * aMatSpecular.rgb"
1895 EOL" + aMatEmission.rgb;"
1896 EOL" return vec4 (aColor, aMatDiffuse.a);"
1900 // =======================================================================
1901 // function : prepareStdProgramGouraud
1903 // =======================================================================
1904 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
1905 const Standard_Integer theBits)
1907 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1908 TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraOut, aSrcVertExtraMain;
1909 TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragExtraMain, aSrcFragWriteOit;
1910 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
1911 if ((theBits & OpenGl_PO_Point) != 0)
1913 #if defined(GL_ES_VERSION_2_0)
1914 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1917 if (textureUsed (theBits))
1919 #if !defined(GL_ES_VERSION_2_0)
1920 if (myContext->core11 != NULL
1921 && myContext->IsGlGreaterEqual (2, 1))
1923 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1927 aSrcFragGetColor = pointSpriteShadingSrc ("gl_FrontFacing ? FrontColor : BackColor", theBits);
1932 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1934 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
1935 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
1936 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
1939 EOL"vec4 getColor(void)"
1941 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
1942 EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;"
1947 if ((theBits & OpenGl_PO_VertColor) != 0)
1949 aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
1952 int aNbClipPlanes = 0;
1953 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
1956 EOL"THE_SHADER_OUT vec4 PositionWorld;"
1957 EOL"THE_SHADER_OUT vec4 Position;";
1959 EOL"THE_SHADER_IN vec4 PositionWorld;"
1960 EOL"THE_SHADER_IN vec4 Position;";
1961 aSrcVertExtraMain +=
1962 EOL" PositionWorld = aPositionWorld;"
1963 EOL" Position = aPosition;";
1965 if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1968 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
1970 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
1973 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
1974 ? THE_FRAG_CLIP_CHAINS_2
1975 : THE_FRAG_CLIP_PLANES_2;
1979 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
1980 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
1981 ? THE_FRAG_CLIP_CHAINS_N
1982 : THE_FRAG_CLIP_PLANES_N;
1985 if ((theBits & OpenGl_PO_WriteOit) != 0)
1987 aProgramSrc->SetNbFragmentOutputs (2);
1988 aProgramSrc->SetWeightOitOutput (true);
1989 #if defined(GL_ES_VERSION_2_0)
1990 if (myContext->IsGlGreaterEqual (3, 0))
1992 aProgramSrc->SetHeader ("#version 300 es");
1997 Standard_Integer aNbLights = 0;
1998 const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, (theBits & OpenGl_PO_VertColor) != 0);
1999 aSrcVert = TCollection_AsciiString()
2000 + THE_FUNC_transformNormal
2005 EOL"THE_SHADER_OUT vec4 FrontColor;"
2006 EOL"THE_SHADER_OUT vec4 BackColor;"
2011 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
2012 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
2013 EOL" vec3 aNormal = transformNormal (occNormal);"
2014 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
2015 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
2016 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
2018 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
2021 aSrcFrag = TCollection_AsciiString()
2022 + EOL"THE_SHADER_IN vec4 FrontColor;"
2023 EOL"THE_SHADER_IN vec4 BackColor;"
2029 + EOL" occSetFragColor (getColor());"
2033 #if !defined(GL_ES_VERSION_2_0)
2034 if (myContext->core32 != NULL)
2036 aProgramSrc->SetHeader ("#version 150");
2039 if (myContext->IsGlGreaterEqual (3, 1))
2041 // prefer "100 es" on OpenGL ES 3.0 devices
2042 // and "300 es" on newer devices (3.1+)
2043 aProgramSrc->SetHeader ("#version 300 es");
2046 aProgramSrc->SetNbLightsMax (aNbLights);
2047 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
2048 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
2049 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
2050 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
2051 TCollection_AsciiString aKey;
2052 if (!Create (aProgramSrc, aKey, theProgram))
2054 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2055 return Standard_False;
2057 return Standard_True;
2060 // =======================================================================
2061 // function : prepareStdProgramPhong
2063 // =======================================================================
2064 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
2065 const Standard_Integer theBits,
2066 const Standard_Boolean theIsFlatNormal)
2068 #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
2069 #if defined(GL_ES_VERSION_2_0)
2070 const bool isFlatNormal = theIsFlatNormal
2071 && (myContext->IsGlGreaterEqual (3, 0)
2072 || myContext->oesStdDerivatives);
2074 const bool isFlatNormal = theIsFlatNormal;
2077 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2078 TCollection_AsciiString aSrcVert, aSrcVertExtraOut, aSrcVertExtraMain;
2079 TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain, aSrcFragWriteOit;
2080 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
2081 if ((theBits & OpenGl_PO_Point) != 0)
2083 #if defined(GL_ES_VERSION_2_0)
2084 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
2087 if (textureUsed (theBits))
2089 #if !defined(GL_ES_VERSION_2_0)
2090 if (myContext->core11 != NULL
2091 && myContext->IsGlGreaterEqual (2, 1))
2093 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
2097 aSrcFragGetColor = pointSpriteShadingSrc (thePhongCompLight, theBits);
2102 if ((theBits & OpenGl_PO_TextureRGB) != 0)
2104 aSrcVertExtraOut += THE_VARY_TexCoord_OUT;
2105 aSrcFragExtraOut += THE_VARY_TexCoord_IN;
2106 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
2109 EOL"vec4 getColor(void)"
2111 EOL" vec4 aColor = " thePhongCompLight ";"
2112 EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;"
2117 if ((theBits & OpenGl_PO_VertColor) != 0)
2119 aSrcVertExtraOut += EOL"THE_SHADER_OUT vec4 VertColor;";
2120 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
2121 aSrcFragGetVertColor = EOL"THE_SHADER_IN vec4 VertColor;"
2122 EOL"vec4 getVertColor(void) { return VertColor; }";
2125 int aNbClipPlanes = 0;
2126 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
2128 if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
2131 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
2133 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
2136 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2137 ? THE_FRAG_CLIP_CHAINS_2
2138 : THE_FRAG_CLIP_PLANES_2;
2142 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
2143 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2144 ? THE_FRAG_CLIP_CHAINS_N
2145 : THE_FRAG_CLIP_PLANES_N;
2148 if ((theBits & OpenGl_PO_WriteOit) != 0)
2150 aProgramSrc->SetNbFragmentOutputs (2);
2151 aProgramSrc->SetWeightOitOutput (true);
2154 aSrcVert = TCollection_AsciiString()
2155 + (isFlatNormal ? "" : THE_FUNC_transformNormal)
2157 EOL"THE_SHADER_OUT vec4 PositionWorld;"
2158 EOL"THE_SHADER_OUT vec4 Position;"
2159 EOL"THE_SHADER_OUT vec3 View;"
2160 + (isFlatNormal ? ""
2161 : EOL"THE_SHADER_OUT vec3 Normal;")
2166 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
2167 EOL" Position = occWorldViewMatrix * PositionWorld;"
2168 + (isFlatNormal ? ""
2169 : EOL" Normal = transformNormal (occNormal);")
2170 + EOL" View = vec3 (0.0, 0.0, 1.0);"
2172 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
2175 Standard_Integer aNbLights = 0;
2176 const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, (theBits & OpenGl_PO_VertColor) != 0);
2177 aSrcFrag = TCollection_AsciiString()
2178 + EOL"THE_SHADER_IN vec4 PositionWorld;"
2179 EOL"THE_SHADER_IN vec4 Position;"
2180 EOL"THE_SHADER_IN vec3 View;"
2183 : EOL"THE_SHADER_IN vec3 Normal;")
2186 + aSrcFragGetVertColor
2194 ? EOL" Normal = normalize (cross (dFdx (Position.xyz / Position.w), dFdy (Position.xyz / Position.w)));"
2195 EOL" if (!gl_FrontFacing) { Normal = -Normal; }"
2197 + EOL" occSetFragColor (getColor());"
2201 #if !defined(GL_ES_VERSION_2_0)
2202 if (myContext->core32 != NULL)
2204 aProgramSrc->SetHeader ("#version 150");
2207 if (myContext->IsGlGreaterEqual (3, 1))
2209 // prefer "100 es" on OpenGL ES 3.0 devices
2210 // and "300 es" on newer devices (3.1+)
2211 aProgramSrc->SetHeader ("#version 300 es");
2213 else if (isFlatNormal)
2215 if (myContext->IsGlGreaterEqual (3, 0))
2217 aProgramSrc->SetHeader ("#version 300 es");
2219 else if (myContext->oesStdDerivatives)
2221 aProgramSrc->SetHeader ("#extension GL_OES_standard_derivatives : enable");
2225 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
2226 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
2227 "Warning: flat shading requires OpenGL ES 3.0+ or GL_OES_standard_derivatives extension.");
2231 aProgramSrc->SetNbLightsMax (aNbLights);
2232 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
2233 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
2234 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
2235 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
2236 TCollection_AsciiString aKey;
2237 if (!Create (aProgramSrc, aKey, theProgram))
2239 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2240 return Standard_False;
2242 return Standard_True;
2245 // =======================================================================
2246 // function : prepareStdProgramStereo
2248 // =======================================================================
2249 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
2250 const Graphic3d_StereoMode theStereoMode)
2252 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2253 TCollection_AsciiString aSrcVert =
2254 EOL"THE_SHADER_OUT vec2 TexCoord;"
2257 EOL" TexCoord = occVertex.zw;"
2258 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
2261 TCollection_AsciiString aSrcFrag;
2262 switch (theStereoMode)
2264 case Graphic3d_StereoMode_Anaglyph:
2267 EOL"uniform sampler2D uLeftSampler;"
2268 EOL"uniform sampler2D uRightSampler;"
2270 EOL"uniform mat4 uMultL;"
2271 EOL"uniform mat4 uMultR;"
2273 EOL"const vec4 THE_POW_UP = vec4 (2.2, 2.2, 2.2, 1.0);"
2274 EOL"const vec4 THE_POW_DOWN = 1.0 / vec4 (2.2, 2.2, 2.2, 1.0);"
2276 EOL"THE_SHADER_IN vec2 TexCoord;"
2280 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2281 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2282 EOL" aColorL = pow (aColorL, THE_POW_UP);" // normalize
2283 EOL" aColorR = pow (aColorR, THE_POW_UP);"
2284 EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;"
2285 EOL" occSetFragColor (pow (aColor, THE_POW_DOWN));"
2289 case Graphic3d_StereoMode_RowInterlaced:
2292 EOL"uniform sampler2D uLeftSampler;"
2293 EOL"uniform sampler2D uRightSampler;"
2295 EOL"THE_SHADER_IN vec2 TexCoord;"
2299 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2300 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2301 EOL" if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)"
2303 EOL" occSetFragColor (aColorL);"
2307 EOL" occSetFragColor (aColorR);"
2312 case Graphic3d_StereoMode_ColumnInterlaced:
2315 EOL"uniform sampler2D uLeftSampler;"
2316 EOL"uniform sampler2D uRightSampler;"
2318 EOL"THE_SHADER_IN vec2 TexCoord;"
2322 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2323 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2324 EOL" if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)"
2326 EOL" occSetFragColor (aColorL);"
2330 EOL" occSetFragColor (aColorR);"
2335 case Graphic3d_StereoMode_ChessBoard:
2338 EOL"uniform sampler2D uLeftSampler;"
2339 EOL"uniform sampler2D uRightSampler;"
2341 EOL"THE_SHADER_IN vec2 TexCoord;"
2345 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2346 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2347 EOL" bool isEvenX = int(mod(floor(gl_FragCoord.x - 1023.5), 2.0)) != 1;"
2348 EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y - 1023.5), 2.0)) == 1;"
2349 EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))"
2351 EOL" occSetFragColor (aColorL);"
2355 EOL" occSetFragColor (aColorR);"
2360 case Graphic3d_StereoMode_SideBySide:
2363 EOL"uniform sampler2D uLeftSampler;"
2364 EOL"uniform sampler2D uRightSampler;"
2366 EOL"THE_SHADER_IN vec2 TexCoord;"
2370 EOL" vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);"
2371 EOL" if (TexCoord.x > 0.5)"
2373 EOL" aTexCoord.x -= 1.0;"
2375 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
2376 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
2377 EOL" if (TexCoord.x <= 0.5)"
2379 EOL" occSetFragColor (aColorL);"
2383 EOL" occSetFragColor (aColorR);"
2388 case Graphic3d_StereoMode_OverUnder:
2391 EOL"uniform sampler2D uLeftSampler;"
2392 EOL"uniform sampler2D uRightSampler;"
2394 EOL"THE_SHADER_IN vec2 TexCoord;"
2398 EOL" vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);"
2399 EOL" if (TexCoord.y > 0.5)"
2401 EOL" aTexCoord.y -= 1.0;"
2403 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
2404 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
2405 EOL" if (TexCoord.y <= 0.5)"
2407 EOL" occSetFragColor (aColorL);"
2411 EOL" occSetFragColor (aColorR);"
2416 case Graphic3d_StereoMode_QuadBuffer:
2417 case Graphic3d_StereoMode_SoftPageFlip:
2420 /*const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[Graphic3d_StereoMode_QuadBuffer];
2421 if (!aProgram.IsNull())
2423 return aProgram->IsValid();
2426 EOL"uniform sampler2D uLeftSampler;"
2427 EOL"uniform sampler2D uRightSampler;"
2429 EOL"THE_SHADER_IN vec2 TexCoord;"
2433 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2434 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2435 EOL" aColorL.b = 0.0;"
2436 EOL" aColorL.g = 0.0;"
2437 EOL" aColorR.r = 0.0;"
2438 EOL" occSetFragColor (aColorL + aColorR);"
2444 #if !defined(GL_ES_VERSION_2_0)
2445 if (myContext->core32 != NULL)
2447 aProgramSrc->SetHeader ("#version 150");
2450 if (myContext->IsGlGreaterEqual (3, 1))
2452 // prefer "100 es" on OpenGL ES 3.0 devices
2453 // and "300 es" on newer devices (3.1+)
2454 aProgramSrc->SetHeader ("#version 300 es");
2458 aProgramSrc->SetNbLightsMax (0);
2459 aProgramSrc->SetNbClipPlanesMax (0);
2460 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
2461 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
2462 TCollection_AsciiString aKey;
2463 if (!Create (aProgramSrc, aKey, theProgram))
2465 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2466 return Standard_False;
2469 myContext->BindProgram (theProgram);
2470 theProgram->SetSampler (myContext, "uLeftSampler", Graphic3d_TextureUnit_0);
2471 theProgram->SetSampler (myContext, "uRightSampler", Graphic3d_TextureUnit_1);
2472 myContext->BindProgram (NULL);
2473 return Standard_True;
2476 // =======================================================================
2477 // function : prepareStdProgramBoundBox
2479 // =======================================================================
2480 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramBoundBox()
2482 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2483 TCollection_AsciiString aSrcVert =
2484 EOL"uniform vec3 occBBoxCenter;"
2485 EOL"uniform vec3 occBBoxSize;"
2489 EOL" vec4 aCenter = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);"
2490 EOL" vec4 aPos = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);"
2491 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * aPos;"
2494 TCollection_AsciiString aSrcFrag =
2497 EOL" occSetFragColor (occColor);"
2500 #if !defined(GL_ES_VERSION_2_0)
2501 if (myContext->core32 != NULL)
2503 aProgramSrc->SetHeader ("#version 150");
2506 if (myContext->IsGlGreaterEqual (3, 1))
2508 // prefer "100 es" on OpenGL ES 3.0 devices
2509 // and "300 es" on newer devices (3.1+)
2510 aProgramSrc->SetHeader ("#version 300 es");
2514 aProgramSrc->SetNbLightsMax (0);
2515 aProgramSrc->SetNbClipPlanesMax (0);
2516 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_VERTEX, aSrcVert));
2517 aProgramSrc->AttachShader (Graphic3d_ShaderObject::CreateFromSource (Graphic3d_TOS_FRAGMENT, aSrcFrag));
2518 TCollection_AsciiString aKey;
2519 if (!Create (aProgramSrc, aKey, myBoundBoxProgram))
2521 myBoundBoxProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2522 return Standard_False;
2525 const OpenGl_Vec4 aMin (-0.5f, -0.5f, -0.5f, 1.0f);
2526 const OpenGl_Vec4 anAxisShifts[3] =
2528 OpenGl_Vec4 (1.0f, 0.0f, 0.0f, 0.0f),
2529 OpenGl_Vec4 (0.0f, 1.0f, 0.0f, 0.0f),
2530 OpenGl_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)
2533 const OpenGl_Vec4 aLookup1 (0.0f, 1.0f, 0.0f, 1.0f);
2534 const OpenGl_Vec4 aLookup2 (0.0f, 0.0f, 1.0f, 1.0f);
2535 OpenGl_Vec4 aLinesVertices[24];
2536 for (int anAxis = 0, aVertex = 0; anAxis < 3; ++anAxis)
2538 for (int aCompIter = 0; aCompIter < 4; ++aCompIter)
2540 aLinesVertices[aVertex++] = aMin
2541 + anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter]
2542 + anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter];
2544 aLinesVertices[aVertex++] = aMin
2545 + anAxisShifts[anAxis]
2546 + anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter]
2547 + anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter];
2550 if (myContext->ToUseVbo())
2552 myBoundBoxVertBuffer = new OpenGl_VertexBuffer();
2553 if (myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData()))
2555 myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer);
2556 return Standard_True;
2559 myBoundBoxVertBuffer = new OpenGl_VertexBufferCompat();
2560 myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData());
2561 myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer);
2562 return Standard_True;
2565 // =======================================================================
2566 // function : bindProgramWithState
2568 // =======================================================================
2569 Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram)
2571 const Standard_Boolean isBound = myContext->BindProgram (theProgram);
2573 && !theProgram.IsNull())
2575 theProgram->ApplyVariables (myContext);
2577 PushState (theProgram);