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 //! Compute TexCoord value in Vertex Shader
50 const char THE_VARY_TexCoord_Trsf[] =
51 EOL" float aRotSin = occTextureTrsf_RotationSin();"
52 EOL" float aRotCos = occTextureTrsf_RotationCos();"
53 EOL" vec2 aTex2 = (occTexCoord.xy + occTextureTrsf_Translation()) * occTextureTrsf_Scale();"
54 EOL" vec2 aCopy = aTex2;"
55 EOL" aTex2.x = aCopy.x * aRotCos - aCopy.y * aRotSin;"
56 EOL" aTex2.y = aCopy.x * aRotSin + aCopy.y * aRotCos;"
57 EOL" TexCoord = vec4(aTex2, occTexCoord.zw);";
59 //! Auxiliary function to flip gl_PointCoord vertically
60 #define THE_VEC2_glPointCoord "vec2 (gl_PointCoord.x, 1.0 - gl_PointCoord.y)"
62 //! Auxiliary function to transform normal
63 const char THE_FUNC_transformNormal[] =
64 EOL"vec3 transformNormal (in vec3 theNormal)"
66 EOL" vec4 aResult = occWorldViewMatrixInverseTranspose"
67 EOL" * occModelWorldMatrixInverseTranspose"
68 EOL" * vec4 (theNormal, 0.0);"
69 EOL" return normalize (aResult.xyz);"
72 //! Global shader variable for color definition with lighting enabled.
73 const char THE_FUNC_lightDef[] =
74 EOL"vec3 Ambient;" //!< Ambient contribution of light sources
75 EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources
76 EOL"vec3 Specular;"; //!< Specular contribution of light sources
78 //! Function computes contribution of isotropic point light source
79 const char THE_FUNC_pointLight[] =
80 EOL"void pointLight (in int theId,"
81 EOL" in vec3 theNormal,"
82 EOL" in vec3 theView,"
83 EOL" in vec3 thePoint,"
84 EOL" in bool theIsFront)"
86 EOL" vec3 aLight = occLight_Position (theId).xyz;"
87 EOL" if (occLight_IsHeadlight (theId) == 0)"
89 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));"
91 EOL" aLight -= thePoint;"
93 EOL" float aDist = length (aLight);"
94 EOL" aLight = aLight * (1.0 / aDist);"
96 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
97 EOL" + occLight_LinearAttenuation (theId) * aDist);"
99 EOL" vec3 aHalf = normalize (aLight + theView);"
101 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
102 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
103 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
105 EOL" float aSpecl = 0.0;"
106 EOL" if (aNdotL > 0.0)"
108 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
111 EOL"Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
112 EOL"Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
115 //! Function computes contribution of spotlight source
116 const char THE_FUNC_spotLight[] =
117 EOL"void spotLight (in int theId,"
118 EOL" in vec3 theNormal,"
119 EOL" in vec3 theView,"
120 EOL" in vec3 thePoint,"
121 EOL" in bool theIsFront)"
123 EOL" vec3 aLight = occLight_Position (theId).xyz;"
124 EOL" vec3 aSpotDir = occLight_SpotDirection (theId).xyz;"
125 EOL" if (occLight_IsHeadlight (theId) == 0)"
127 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));"
128 EOL" aSpotDir = vec3 (occWorldViewMatrix * vec4 (aSpotDir, 0.0));"
130 EOL" aLight -= thePoint;"
132 EOL" float aDist = length (aLight);"
133 EOL" aLight = aLight * (1.0 / aDist);"
135 EOL" aSpotDir = normalize (aSpotDir);"
137 EOL" float aCosA = dot (aSpotDir, -aLight);"
138 EOL" if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
143 EOL" float anExponent = occLight_SpotExponent (theId);"
144 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
145 EOL" + occLight_LinearAttenuation (theId) * aDist);"
146 EOL" if (anExponent > 0.0)"
148 EOL" anAtten *= pow (aCosA, anExponent * 128.0);"
151 EOL" vec3 aHalf = normalize (aLight + theView);"
153 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
154 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
155 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
157 EOL" float aSpecl = 0.0;"
158 EOL" if (aNdotL > 0.0)"
160 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
163 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
164 EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
167 //! Function computes contribution of directional light source
168 const char THE_FUNC_directionalLight[] =
169 EOL"void directionalLight (in int theId,"
170 EOL" in vec3 theNormal,"
171 EOL" in vec3 theView,"
172 EOL" in bool theIsFront)"
174 EOL" vec3 aLight = normalize (occLight_Position (theId).xyz);"
175 EOL" if (occLight_IsHeadlight (theId) == 0)"
177 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));"
180 EOL" vec3 aHalf = normalize (aLight + theView);"
182 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
183 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
184 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
186 EOL" float aSpecl = 0.0;"
187 EOL" if (aNdotL > 0.0)"
189 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
192 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL;"
193 EOL" Specular += occLight_Specular (theId).rgb * aSpecl;"
196 //! The same as THE_FUNC_directionalLight but for the light with zero index
197 //! (avoids limitations on some mobile devices).
198 const char THE_FUNC_directionalLightFirst[] =
199 EOL"void directionalLightFirst (in vec3 theNormal,"
200 EOL" in vec3 theView,"
201 EOL" in bool theIsFront)"
203 EOL" vec3 aLight = normalize (occLightSources[1].xyz);"
204 EOL" if (occLight_IsHeadlight (0) == 0)"
206 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));"
209 EOL" vec3 aHalf = normalize (aLight + theView);"
211 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
212 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
213 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
215 EOL" float aSpecl = 0.0;"
216 EOL" if (aNdotL > 0.0)"
218 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
221 EOL" Diffuse += occLightSources[0].rgb * aNdotL;"
222 EOL" Specular += occLightSources[0].rgb * aSpecl;"
225 //! Process clipping planes in Fragment Shader.
226 //! Should be added at the beginning of the main() function.
227 const char THE_FRAG_CLIP_PLANES_N[] =
228 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)"
230 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
231 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)"
237 //! Process chains of clipping planes in Fragment Shader.
238 const char THE_FRAG_CLIP_CHAINS_N[] =
239 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount;)"
241 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
242 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)"
244 EOL" if (occClipPlaneChains[aPlaneIter] == 1)"
248 EOL" aPlaneIter += 1;"
252 EOL" aPlaneIter += occClipPlaneChains[aPlaneIter];"
256 //! Process 1 clipping plane in Fragment Shader.
257 const char THE_FRAG_CLIP_PLANES_1[] =
258 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
259 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0)"
264 //! Process 2 clipping planes in Fragment Shader.
265 const char THE_FRAG_CLIP_PLANES_2[] =
266 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
267 EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];"
268 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0"
269 EOL" || dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)"
274 //! Process a chain of 2 clipping planes in Fragment Shader (3/4 section).
275 const char THE_FRAG_CLIP_CHAINS_2[] =
276 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
277 EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];"
278 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0"
279 EOL" && dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)"
284 //! Modify color for Wireframe presentation.
285 const char THE_FRAG_WIREFRAME_COLOR[] =
286 EOL"vec4 getFinalColor(void)"
288 EOL" float aDistance = min (min (EdgeDistance[0], EdgeDistance[1]), EdgeDistance[2]);"
289 EOL" bool isHollow = occWireframeColor.a < 0.0;"
290 EOL" float aMixVal = smoothstep (occLineWidth - occLineFeather * 0.5, occLineWidth + occLineFeather * 0.5, aDistance);"
291 EOL" vec4 aMixColor = isHollow"
292 EOL" ? vec4 (getColor().rgb, 1.0 - aMixVal)" // edges only (of interior color)
293 EOL" : mix (occWireframeColor, getColor(), aMixVal);" // interior + edges
294 EOL" return aMixColor;"
297 #if !defined(GL_ES_VERSION_2_0)
299 static const GLfloat THE_DEFAULT_AMBIENT[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
300 static const GLfloat THE_DEFAULT_SPOT_DIR[3] = { 0.0f, 0.0f, -1.0f };
301 static const GLfloat THE_DEFAULT_SPOT_EXPONENT = 0.0f;
302 static const GLfloat THE_DEFAULT_SPOT_CUTOFF = 180.0f;
304 //! Bind FFP light source.
305 static void bindLight (const Graphic3d_CLight& theLight,
306 const GLenum theLightGlId,
307 const OpenGl_Mat4& theModelView,
308 OpenGl_Context* theCtx)
310 // the light is a headlight?
311 if (theLight.IsHeadlight())
313 theCtx->core11->glMatrixMode (GL_MODELVIEW);
314 theCtx->core11->glLoadIdentity();
318 const Graphic3d_Vec4& aLightColor = theLight.PackedColor();
319 switch (theLight.Type())
321 case Graphic3d_TOLS_AMBIENT : break; // handled by separate if-clause at beginning of method
322 case Graphic3d_TOLS_DIRECTIONAL:
324 // if the last parameter of GL_POSITION, is zero, the corresponding light source is a Directional one
325 const OpenGl_Vec4 anInfDir = -theLight.PackedDirection();
327 // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE.
328 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
329 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
330 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
331 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, anInfDir.GetData());
332 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR);
333 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT);
334 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF);
337 case Graphic3d_TOLS_POSITIONAL:
339 // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE
340 const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position().X()), static_cast<float>(theLight.Position().Y()), static_cast<float>(theLight.Position().Z()), 1.0f);
341 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
342 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
343 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
344 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, aPosition.GetData());
345 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR);
346 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT);
347 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF);
348 theCtx->core11->glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation());
349 theCtx->core11->glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation());
350 theCtx->core11->glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0);
353 case Graphic3d_TOLS_SPOT:
355 const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position().X()), static_cast<float>(theLight.Position().Y()), static_cast<float>(theLight.Position().Z()), 1.0f);
356 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
357 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
358 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
359 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, aPosition.GetData());
360 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, theLight.PackedDirection().GetData());
361 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, theLight.Concentration() * 128.0f);
362 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, (theLight.Angle() * 180.0f) / GLfloat(M_PI));
363 theCtx->core11->glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation());
364 theCtx->core11->glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation());
365 theCtx->core11->glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f);
370 // restore matrix in case of headlight
371 if (theLight.IsHeadlight())
373 theCtx->core11->glLoadMatrixf (theModelView.GetData());
376 glEnable (theLightGlId);
382 // =======================================================================
383 // function : OpenGl_ShaderManager
384 // purpose : Creates new empty shader manager
385 // =======================================================================
386 OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
387 : myFfpProgram (new OpenGl_ShaderProgramFFP()),
388 myShadingModel (Graphic3d_TOSM_VERTEX),
389 myUnlitPrograms (new OpenGl_SetOfShaderPrograms()),
390 myContext (theContext),
391 myHasLocalOrigin (Standard_False),
397 // =======================================================================
398 // function : ~OpenGl_ShaderManager
399 // purpose : Releases resources of shader manager
400 // =======================================================================
401 OpenGl_ShaderManager::~OpenGl_ShaderManager()
403 myProgramList.Clear();
406 // =======================================================================
409 // =======================================================================
410 void OpenGl_ShaderManager::clear()
412 myProgramList.Clear();
413 myLightPrograms.Nullify();
414 myUnlitPrograms = new OpenGl_SetOfShaderPrograms();
415 myMapOfLightPrograms.Clear();
416 myFontProgram.Nullify();
417 myBlitProgram.Nullify();
418 myBoundBoxProgram.Nullify();
419 myBoundBoxVertBuffer.Nullify();
420 for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter)
422 myStereoPrograms[aModeIter].Nullify();
424 switchLightPrograms();
427 // =======================================================================
429 // purpose : Creates new shader program
430 // =======================================================================
431 Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
432 TCollection_AsciiString& theShareKey,
433 Handle(OpenGl_ShaderProgram)& theProgram)
435 theProgram.Nullify();
436 if (theProxy.IsNull())
438 return Standard_False;
441 theShareKey = theProxy->GetId();
442 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
444 if (theProgram->Share())
446 myProgramList.Append (theProgram);
448 return Standard_True;
451 theProgram = new OpenGl_ShaderProgram (theProxy);
452 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
454 theProgram->Release (myContext);
456 theProgram.Nullify();
457 return Standard_False;
460 myProgramList.Append (theProgram);
461 myContext->ShareResource (theShareKey, theProgram);
462 return Standard_True;
465 // =======================================================================
466 // function : Unregister
467 // purpose : Removes specified shader program from the manager
468 // =======================================================================
469 void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
470 Handle(OpenGl_ShaderProgram)& theProgram)
472 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
474 if (anIt.Value() == theProgram)
476 if (!theProgram->UnShare())
479 theProgram.Nullify();
483 myProgramList.Remove (anIt);
488 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
491 myContext->DelayedRelease (theProgram);
492 theProgram.Nullify();
496 theProgram.Nullify();
497 myContext->ReleaseResource (anID, Standard_True);
501 // =======================================================================
502 // function : ShaderPrograms
503 // purpose : Returns list of registered shader programs
504 // =======================================================================
505 const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
507 return myProgramList;
510 // =======================================================================
512 // purpose : Returns true if no program objects are attached
513 // =======================================================================
514 Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
516 return myProgramList.IsEmpty();
519 // =======================================================================
520 // function : switchLightPrograms
522 // =======================================================================
523 void OpenGl_ShaderManager::switchLightPrograms()
525 const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources();
526 if (aLights.IsNull())
528 myLightPrograms = myUnlitPrograms;
532 TCollection_AsciiString aKey ("l_");
533 if (aLights->NbEnabled() <= THE_NB_UNROLLED_LIGHTS_MAX)
535 aKey += aLights->KeyEnabledLong();
539 const Standard_Integer aMaxLimit = roundUpMaxLightSources (aLights->NbEnabled());
540 aKey += aLights->KeyEnabledShort();
544 if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
546 myLightPrograms = new OpenGl_SetOfShaderPrograms();
547 myMapOfLightPrograms.Bind (aKey, myLightPrograms);
551 // =======================================================================
552 // function : UpdateLightSourceStateTo
553 // purpose : Updates state of OCCT light sources
554 // =======================================================================
555 void OpenGl_ShaderManager::UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights)
557 myLightSourceState.Set (theLights);
558 myLightSourceState.Update();
559 switchLightPrograms();
562 // =======================================================================
563 // function : UpdateLightSourceState
565 // =======================================================================
566 void OpenGl_ShaderManager::UpdateLightSourceState()
568 myLightSourceState.Update();
571 // =======================================================================
572 // function : SetShadingModel
574 // =======================================================================
575 void OpenGl_ShaderManager::SetShadingModel (const Graphic3d_TypeOfShadingModel theModel)
577 if (theModel == Graphic3d_TOSM_DEFAULT)
579 throw Standard_ProgramError ("OpenGl_ShaderManager::SetShadingModel() - attempt to set invalid Shading Model!");
582 myShadingModel = theModel;
583 switchLightPrograms();
586 // =======================================================================
587 // function : SetProjectionState
588 // purpose : Sets new state of OCCT projection transform
589 // =======================================================================
590 void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix)
592 myProjectionState.Set (theProjectionMatrix);
593 myProjectionState.Update();
596 // =======================================================================
597 // function : SetModelWorldState
598 // purpose : Sets new state of OCCT model-world transform
599 // =======================================================================
600 void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix)
602 myModelWorldState.Set (theModelWorldMatrix);
603 myModelWorldState.Update();
606 // =======================================================================
607 // function : SetWorldViewState
608 // purpose : Sets new state of OCCT world-view transform
609 // =======================================================================
610 void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix)
612 myWorldViewState.Set (theWorldViewMatrix);
613 myWorldViewState.Update();
616 // =======================================================================
617 // function : PushLightSourceState
618 // purpose : Pushes state of OCCT light sources to the program
619 // =======================================================================
620 void OpenGl_ShaderManager::PushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
622 if (myLightSourceState.Index() == theProgram->ActiveState (OpenGl_LIGHT_SOURCES_STATE))
627 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
628 if (theProgram == myFfpProgram)
630 #if !defined(GL_ES_VERSION_2_0)
631 if (myContext->core11 == NULL)
636 GLenum aLightGlId = GL_LIGHT0;
637 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
638 for (Graphic3d_LightSet::Iterator aLightIt (myLightSourceState.LightSources(), Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
639 aLightIt.More(); aLightIt.Next())
641 if (aLightGlId > GL_LIGHT7) // only 8 lights in FFP...
643 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
644 "Warning: light sources limit (8) has been exceeded within Fixed-function pipeline.");
648 bindLight (*aLightIt.Value(), aLightGlId, aModelView, myContext);
652 // apply accumulated ambient color
653 const Graphic3d_Vec4 anAmbient = !myLightSourceState.LightSources().IsNull()
654 ? myLightSourceState.LightSources()->AmbientColor()
655 : Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 1.0f);
656 myContext->core11->glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbient.GetData());
658 // GL_LIGHTING is managed by drawers to switch between shaded / no lighting output,
659 // therefore managing the state here does not have any effect - do it just for consistency.
660 if (aLightGlId != GL_LIGHT0)
662 ::glEnable (GL_LIGHTING);
666 ::glDisable (GL_LIGHTING);
668 // switch off unused lights
669 for (; aLightGlId <= GL_LIGHT7; ++aLightGlId)
671 ::glDisable (aLightGlId);
677 const Standard_Integer aNbLightsMax = theProgram->NbLightsMax();
678 const GLint anAmbientLoc = theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT);
679 if (aNbLightsMax == 0
680 && anAmbientLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
685 if (myLightTypeArray.Size() < aNbLightsMax)
687 myLightTypeArray .Resize (0, aNbLightsMax - 1, false);
688 myLightParamsArray.Resize (0, aNbLightsMax - 1, false);
690 for (Standard_Integer aLightIt = 0; aLightIt < aNbLightsMax; ++aLightIt)
692 myLightTypeArray.ChangeValue (aLightIt).Type = -1;
695 if (myLightSourceState.LightSources().IsNull()
696 || myLightSourceState.LightSources()->IsEmpty())
698 theProgram->SetUniform (myContext,
699 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
701 theProgram->SetUniform (myContext,
703 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
704 theProgram->SetUniform (myContext,
705 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
706 aNbLightsMax * OpenGl_ShaderLightType::NbOfVec2i(),
707 myLightTypeArray.First().Packed());
711 Standard_Integer aLightsNb = 0;
712 for (Graphic3d_LightSet::Iterator anIter (myLightSourceState.LightSources(), Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
713 anIter.More(); anIter.Next())
715 const Graphic3d_CLight& aLight = *anIter.Value();
716 if (aLightsNb >= aNbLightsMax)
718 if (aNbLightsMax != 0)
720 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
721 TCollection_AsciiString("Warning: light sources limit (") + aNbLightsMax + ") has been exceeded.");
726 OpenGl_ShaderLightType& aLightType = myLightTypeArray.ChangeValue (aLightsNb);
727 OpenGl_ShaderLightParameters& aLightParams = myLightParamsArray.ChangeValue (aLightsNb);
728 if (!aLight.IsEnabled()) // has no affect with Graphic3d_LightSet::IterationFilter_ExcludeDisabled - here just for consistency
730 // 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
731 aLightType.Type = -1; // Graphic3d_TOLS_AMBIENT can be used instead
732 aLightType.IsHeadlight = false;
733 aLightParams.Color = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f);
738 aLightType.Type = aLight.Type();
739 aLightType.IsHeadlight = aLight.IsHeadlight();
740 aLightParams.Color = aLight.PackedColor();
741 if (aLight.Type() == Graphic3d_TOLS_DIRECTIONAL)
743 aLightParams.Position = -aLight.PackedDirection();
745 else if (!aLight.IsHeadlight())
747 aLightParams.Position.x() = static_cast<float>(aLight.Position().X() - myLocalOrigin.X());
748 aLightParams.Position.y() = static_cast<float>(aLight.Position().Y() - myLocalOrigin.Y());
749 aLightParams.Position.z() = static_cast<float>(aLight.Position().Z() - myLocalOrigin.Z());
750 aLightParams.Position.w() = 1.0f;
754 aLightParams.Position.x() = static_cast<float>(aLight.Position().X());
755 aLightParams.Position.y() = static_cast<float>(aLight.Position().Y());
756 aLightParams.Position.z() = static_cast<float>(aLight.Position().Z());
757 aLightParams.Position.w() = 1.0f;
760 if (aLight.Type() == Graphic3d_TOLS_SPOT)
762 aLightParams.Direction = aLight.PackedDirection();
764 aLightParams.Parameters = aLight.PackedParams();
768 const Graphic3d_Vec4& anAmbient = myLightSourceState.LightSources()->AmbientColor();
769 theProgram->SetUniform (myContext,
770 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
772 theProgram->SetUniform (myContext,
775 theProgram->SetUniform (myContext,
776 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
777 aNbLightsMax * OpenGl_ShaderLightType::NbOfVec2i(),
778 myLightTypeArray.First().Packed());
781 theProgram->SetUniform (myContext,
782 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
783 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
784 myLightParamsArray.First().Packed());
788 // =======================================================================
789 // function : PushProjectionState
790 // purpose : Pushes state of OCCT projection transform to the program
791 // =======================================================================
792 void OpenGl_ShaderManager::PushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
794 if (myProjectionState.Index() == theProgram->ActiveState (OpenGl_PROJECTION_STATE))
799 theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
800 if (theProgram == myFfpProgram)
802 #if !defined(GL_ES_VERSION_2_0)
803 if (myContext->core11 != NULL)
805 myContext->core11->glMatrixMode (GL_PROJECTION);
806 myContext->core11->glLoadMatrixf (myProjectionState.ProjectionMatrix());
812 theProgram->SetUniform (myContext,
813 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
814 myProjectionState.ProjectionMatrix());
816 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
817 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
819 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
822 theProgram->SetUniform (myContext,
823 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
824 myProjectionState.ProjectionMatrix(), true);
826 aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
827 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
829 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
833 // =======================================================================
834 // function : PushModelWorldState
835 // purpose : Pushes state of OCCT model-world transform to the program
836 // =======================================================================
837 void OpenGl_ShaderManager::PushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
839 if (myModelWorldState.Index() == theProgram->ActiveState (OpenGl_MODEL_WORLD_STATE))
844 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
845 if (theProgram == myFfpProgram)
847 #if !defined(GL_ES_VERSION_2_0)
848 if (myContext->core11 != NULL)
850 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
851 myContext->core11->glMatrixMode (GL_MODELVIEW);
852 myContext->core11->glLoadMatrixf (aModelView.GetData());
853 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
859 theProgram->SetUniform (myContext,
860 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
861 myModelWorldState.ModelWorldMatrix());
863 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
864 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
866 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
869 theProgram->SetUniform (myContext,
870 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
871 myModelWorldState.ModelWorldMatrix(), true);
873 aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
874 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
876 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
880 // =======================================================================
881 // function : PushWorldViewState
882 // purpose : Pushes state of OCCT world-view transform to the program
883 // =======================================================================
884 void OpenGl_ShaderManager::PushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
886 if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
891 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
892 if (theProgram == myFfpProgram)
894 #if !defined(GL_ES_VERSION_2_0)
895 if (myContext->core11 != NULL)
897 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
898 myContext->core11->glMatrixMode (GL_MODELVIEW);
899 myContext->core11->glLoadMatrixf (aModelView.GetData());
900 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
906 theProgram->SetUniform (myContext,
907 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
908 myWorldViewState.WorldViewMatrix());
910 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
911 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
913 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
916 theProgram->SetUniform (myContext,
917 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
918 myWorldViewState.WorldViewMatrix(), true);
920 aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
921 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
923 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
927 // =======================================================================
928 // function : UpdateClippingState
929 // purpose : Updates state of OCCT clipping planes
930 // =======================================================================
931 void OpenGl_ShaderManager::UpdateClippingState()
933 myClippingState.Update();
936 // =======================================================================
937 // function : RevertClippingState
938 // purpose : Reverts state of OCCT clipping planes
939 // =======================================================================
940 void OpenGl_ShaderManager::RevertClippingState()
942 myClippingState.Revert();
945 // =======================================================================
946 // function : PushClippingState
947 // purpose : Pushes state of OCCT clipping planes to the program
948 // =======================================================================
949 void OpenGl_ShaderManager::PushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
951 if (myClippingState.Index() == theProgram->ActiveState (OpenGl_CLIP_PLANES_STATE))
956 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
957 if (theProgram == myFfpProgram)
959 #if !defined(GL_ES_VERSION_2_0)
960 if (myContext->core11 == NULL)
965 const Standard_Integer aNbMaxPlanes = myContext->MaxClipPlanes();
966 if (myClipPlaneArrayFfp.Size() < aNbMaxPlanes)
968 myClipPlaneArrayFfp.Resize (0, aNbMaxPlanes - 1, false);
971 Standard_Integer aPlaneId = 0;
972 Standard_Boolean toRestoreModelView = Standard_False;
973 const Handle(Graphic3d_ClipPlane)& aCappedChain = myContext->Clipping().CappedChain();
974 for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
976 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
977 if (aPlaneIter.IsDisabled()
979 || (aPlane == aCappedChain
980 && myContext->Clipping().IsCappingEnableAllExcept()))
984 else if (aPlaneId >= aNbMaxPlanes)
986 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
987 TCollection_ExtendedString("Warning: clipping planes limit (") + aNbMaxPlanes + ") has been exceeded.");
991 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
992 OpenGl_Vec4d& aPlaneEq = myClipPlaneArrayFfp.ChangeValue (aPlaneId);
993 aPlaneEq.x() = anEquation.x();
994 aPlaneEq.y() = anEquation.y();
995 aPlaneEq.z() = anEquation.z();
996 aPlaneEq.w() = anEquation.w();
997 if (myHasLocalOrigin)
999 const gp_XYZ aPos = aPlane->ToPlane().Position().Location().XYZ() - myLocalOrigin;
1000 const Standard_Real aD = -(anEquation.x() * aPos.X() + anEquation.y() * aPos.Y() + anEquation.z() * aPos.Z());
1004 const GLenum anFfpPlaneID = GL_CLIP_PLANE0 + aPlaneId;
1005 if (anFfpPlaneID == GL_CLIP_PLANE0)
1007 // set either identity or pure view matrix
1008 toRestoreModelView = Standard_True;
1009 myContext->core11->glMatrixMode (GL_MODELVIEW);
1010 myContext->core11->glLoadMatrixf (myWorldViewState.WorldViewMatrix().GetData());
1013 ::glEnable (anFfpPlaneID);
1014 myContext->core11->glClipPlane (anFfpPlaneID, aPlaneEq);
1019 // switch off unused lights
1020 for (; aPlaneId < aNbMaxPlanes; ++aPlaneId)
1022 ::glDisable (GL_CLIP_PLANE0 + aPlaneId);
1025 // restore combined model-view matrix
1026 if (toRestoreModelView)
1028 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
1029 myContext->core11->glLoadMatrixf (aModelView.GetData());
1035 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
1036 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION)
1041 const Standard_Integer aNbClipPlanesMax = theProgram->NbClipPlanesMax();
1042 const Standard_Integer aNbPlanes = Min (myContext->Clipping().NbClippingOrCappingOn(), aNbClipPlanesMax);
1045 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), 0);
1049 if (myClipPlaneArray.Size() < aNbClipPlanesMax)
1051 myClipPlaneArray.Resize (0, aNbClipPlanesMax - 1, false);
1052 myClipChainArray.Resize (0, aNbClipPlanesMax - 1, false);
1055 Standard_Integer aPlaneId = 0;
1056 const Handle(Graphic3d_ClipPlane)& aCappedChain = myContext->Clipping().CappedChain();
1057 for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
1059 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
1060 if (aPlaneIter.IsDisabled())
1065 if (myContext->Clipping().IsCappingDisableAllExcept())
1067 // enable only specific (sub) plane
1068 if (aPlane != aCappedChain)
1073 Standard_Integer aSubPlaneIndex = 1;
1074 for (const Graphic3d_ClipPlane* aSubPlaneIter = aCappedChain.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex)
1076 if (aSubPlaneIndex == myContext->Clipping().CappedSubPlane())
1078 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->GetEquation(), 1);
1084 else if (aPlane == aCappedChain) // && myContext->Clipping().IsCappingEnableAllExcept()
1086 // enable sub-planes within processed Chain as reversed and ORed, excluding filtered plane
1087 if (aPlaneId + aPlane->NbChainNextPlanes() - 1 > aNbClipPlanesMax)
1089 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
1090 TCollection_AsciiString("Error: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded.");
1094 Standard_Integer aSubPlaneIndex = 1;
1095 for (const Graphic3d_ClipPlane* aSubPlaneIter = aPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex)
1097 if (aSubPlaneIndex != -myContext->Clipping().CappedSubPlane())
1099 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->ReversedEquation(), 1);
1106 if (aPlaneId + aPlane->NbChainNextPlanes() > aNbClipPlanesMax)
1108 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
1109 TCollection_AsciiString("Error: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded.");
1112 for (const Graphic3d_ClipPlane* aSubPlaneIter = aPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get())
1114 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->GetEquation(), aSubPlaneIter->NbChainNextPlanes());
1119 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), aPlaneId);
1120 theProgram->SetUniform (myContext, aLocEquations, aNbClipPlanesMax, &myClipPlaneArray.First());
1121 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_CHAINS), aNbClipPlanesMax, &myClipChainArray.First());
1124 // =======================================================================
1125 // function : PushMaterialState
1127 // =======================================================================
1128 void OpenGl_ShaderManager::PushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1130 if (myMaterialState.Index() == theProgram->ActiveState (OpenGl_MATERIAL_STATE))
1135 const OpenGl_Material& aFrontMat = myMaterialState.FrontMaterial();
1136 const OpenGl_Material& aBackMat = myMaterialState.BackMaterial();
1137 theProgram->UpdateState (OpenGl_MATERIAL_STATE, myMaterialState.Index());
1138 if (theProgram == myFfpProgram)
1140 #if !defined(GL_ES_VERSION_2_0)
1141 if (myContext->core11 == NULL)
1146 myContext->SetSampleAlphaToCoverage (false);
1147 if (myMaterialState.AlphaCutoff() < ShortRealLast())
1149 glAlphaFunc (GL_GEQUAL, myMaterialState.AlphaCutoff());
1150 glEnable (GL_ALPHA_TEST);
1154 glDisable (GL_ALPHA_TEST);
1157 const GLenum aFrontFace = myMaterialState.ToDistinguish() ? GL_FRONT : GL_FRONT_AND_BACK;
1158 myContext->core11->glMaterialfv(aFrontFace, GL_AMBIENT, aFrontMat.Ambient.GetData());
1159 myContext->core11->glMaterialfv(aFrontFace, GL_DIFFUSE, aFrontMat.Diffuse.GetData());
1160 myContext->core11->glMaterialfv(aFrontFace, GL_SPECULAR, aFrontMat.Specular.GetData());
1161 myContext->core11->glMaterialfv(aFrontFace, GL_EMISSION, aFrontMat.Emission.GetData());
1162 myContext->core11->glMaterialf (aFrontFace, GL_SHININESS, aFrontMat.Shine());
1163 if (myMaterialState.ToDistinguish())
1165 myContext->core11->glMaterialfv(GL_BACK, GL_AMBIENT, aBackMat.Ambient.GetData());
1166 myContext->core11->glMaterialfv(GL_BACK, GL_DIFFUSE, aBackMat.Diffuse.GetData());
1167 myContext->core11->glMaterialfv(GL_BACK, GL_SPECULAR, aBackMat.Specular.GetData());
1168 myContext->core11->glMaterialfv(GL_BACK, GL_EMISSION, aBackMat.Emission.GetData());
1169 myContext->core11->glMaterialf (GL_BACK, GL_SHININESS, aBackMat.Shine());
1175 myContext->SetSampleAlphaToCoverage (myMaterialState.HasAlphaCutoff());
1176 theProgram->SetUniform (myContext,
1177 theProgram->GetStateLocation (OpenGl_OCCT_ALPHA_CUTOFF),
1178 myMaterialState.AlphaCutoff());
1179 theProgram->SetUniform (myContext,
1180 theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
1181 myMaterialState.ToMapTexture() ? 1 : 0);
1182 theProgram->SetUniform (myContext,
1183 theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
1184 myMaterialState.ToDistinguish() ? 1 : 0);
1186 if (const OpenGl_ShaderUniformLocation aLocFront = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL))
1188 theProgram->SetUniform (myContext, aLocFront, OpenGl_Material::NbOfVec4(),
1189 aFrontMat.Packed());
1191 if (const OpenGl_ShaderUniformLocation aLocBack = theProgram->GetStateLocation (OpenGl_OCCT_BACK_MATERIAL))
1193 theProgram->SetUniform (myContext, aLocBack, OpenGl_Material::NbOfVec4(),
1198 // =======================================================================
1199 // function : PushOitState
1200 // purpose : Pushes state of OIT uniforms to the specified program
1201 // =======================================================================
1202 void OpenGl_ShaderManager::PushOitState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1204 if (!theProgram->IsValid())
1209 if (myOitState.Index() == theProgram->ActiveState (OpenGL_OIT_STATE))
1214 const GLint aLocOutput = theProgram->GetStateLocation (OpenGl_OCCT_OIT_OUTPUT);
1215 if (aLocOutput != OpenGl_ShaderProgram::INVALID_LOCATION)
1217 theProgram->SetUniform (myContext, aLocOutput, myOitState.ToEnableWrite());
1220 const GLint aLocDepthFactor = theProgram->GetStateLocation (OpenGl_OCCT_OIT_DEPTH_FACTOR);
1221 if (aLocDepthFactor != OpenGl_ShaderProgram::INVALID_LOCATION)
1223 theProgram->SetUniform (myContext, aLocDepthFactor, myOitState.DepthFactor());
1227 // =======================================================================
1228 // function : PushInteriorState
1230 // =======================================================================
1231 void OpenGl_ShaderManager::PushInteriorState (const Handle(OpenGl_ShaderProgram)& theProgram,
1232 const Handle(Graphic3d_AspectFillArea3d)& theAspect) const
1234 if (theProgram.IsNull()
1235 || !theProgram->IsValid())
1240 if (const OpenGl_ShaderUniformLocation aLocViewPort = theProgram->GetStateLocation (OpenGl_OCCT_VIEWPORT))
1242 theProgram->SetUniform (myContext, aLocViewPort, OpenGl_Vec4 ((float )myContext->Viewport()[0], (float )myContext->Viewport()[1], (float )myContext->Viewport()[2], (float )myContext->Viewport()[3]));
1244 if (const OpenGl_ShaderUniformLocation aLocLineWidth = theProgram->GetStateLocation (OpenGl_OCCT_LINE_WIDTH))
1246 theProgram->SetUniform (myContext, aLocLineWidth, theAspect->EdgeWidth() * myContext->LineWidthScale());
1247 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCCT_LINE_FEATHER), myContext->LineFeather() * myContext->LineWidthScale());
1249 if (const OpenGl_ShaderUniformLocation aLocWireframeColor = theProgram->GetStateLocation (OpenGl_OCCT_WIREFRAME_COLOR))
1251 if (theAspect->InteriorStyle() == Aspect_IS_HOLLOW)
1253 theProgram->SetUniform (myContext, aLocWireframeColor, OpenGl_Vec4 (-1.0f, -1.0f, -1.0f, -1.0f));
1257 theProgram->SetUniform (myContext, aLocWireframeColor, theAspect->EdgeColorRGBA());
1260 if (const OpenGl_ShaderUniformLocation aLocQuadModeState = theProgram->GetStateLocation (OpenGl_OCCT_QUAD_MODE_STATE))
1262 theProgram->SetUniform (myContext, aLocQuadModeState, theAspect->ToSkipFirstEdge() ? 1 : 0);
1266 // =======================================================================
1267 // function : PushState
1268 // purpose : Pushes state of OCCT graphics parameters to the program
1269 // =======================================================================
1270 void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1272 const Handle(OpenGl_ShaderProgram)& aProgram = !theProgram.IsNull() ? theProgram : myFfpProgram;
1273 PushClippingState (aProgram);
1274 PushWorldViewState (aProgram);
1275 PushModelWorldState (aProgram);
1276 PushProjectionState (aProgram);
1277 PushLightSourceState (aProgram);
1278 PushMaterialState (aProgram);
1279 PushOitState (aProgram);
1282 // =======================================================================
1283 // function : prepareStdProgramFont
1285 // =======================================================================
1286 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
1288 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1289 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1291 TCollection_AsciiString aSrcVert =
1294 EOL" TexCoord = occTexCoord.st;"
1295 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1298 TCollection_AsciiString
1299 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).a; }";
1300 #if !defined(GL_ES_VERSION_2_0)
1301 if (myContext->core11 == NULL)
1303 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).r; }";
1307 TCollection_AsciiString aSrcFrag =
1311 EOL" vec4 aColor = occColor;"
1312 EOL" aColor.a *= getAlpha();"
1313 EOL" if (aColor.a <= 0.285) discard;"
1314 EOL" occSetFragColor (aColor);"
1317 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1318 defaultGlslVersion (aProgramSrc, 0);
1319 aProgramSrc->SetNbLightsMax (0);
1320 aProgramSrc->SetNbClipPlanesMax (0);
1321 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1322 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
1323 TCollection_AsciiString aKey;
1324 if (!Create (aProgramSrc, aKey, myFontProgram))
1326 myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1327 return Standard_False;
1329 return Standard_True;
1332 // =======================================================================
1333 // function : prepareStdProgramFboBlit
1335 // =======================================================================
1336 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit()
1338 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1339 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1341 TCollection_AsciiString aSrcVert =
1344 EOL" TexCoord = occVertex.zw;"
1345 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1348 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uColorSampler", Graphic3d_TOS_FRAGMENT));
1349 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uDepthSampler", Graphic3d_TOS_FRAGMENT));
1350 TCollection_AsciiString aSrcFrag =
1353 EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;"
1354 EOL" occSetFragColor (occTexture2D (uColorSampler, TexCoord));"
1357 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1358 #if defined(GL_ES_VERSION_2_0)
1359 if (myContext->IsGlGreaterEqual (3, 0))
1361 aProgramSrc->SetHeader ("#version 300 es");
1363 else if (myContext->extFragDepth)
1365 aProgramSrc->SetHeader ("#extension GL_EXT_frag_depth : enable"
1366 EOL"#define gl_FragDepth gl_FragDepthEXT");
1370 // there is no way to draw into depth buffer
1374 EOL" occSetFragColor (occTexture2D (uColorSampler, TexCoord));"
1378 if (myContext->core32 != NULL)
1380 aProgramSrc->SetHeader ("#version 150");
1383 aProgramSrc->SetNbLightsMax (0);
1384 aProgramSrc->SetNbClipPlanesMax (0);
1385 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1386 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
1387 TCollection_AsciiString aKey;
1388 if (!Create (aProgramSrc, aKey, myBlitProgram))
1390 myBlitProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1391 return Standard_False;
1394 myContext->BindProgram (myBlitProgram);
1395 myBlitProgram->SetSampler (myContext, "uColorSampler", Graphic3d_TextureUnit_0);
1396 myBlitProgram->SetSampler (myContext, "uDepthSampler", Graphic3d_TextureUnit_1);
1397 myContext->BindProgram (NULL);
1398 return Standard_True;
1401 // =======================================================================
1402 // function : prepareStdProgramOitCompositing
1404 // =======================================================================
1405 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const Standard_Boolean theMsaa)
1407 Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram[theMsaa ? 1 : 0];
1408 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1409 TCollection_AsciiString aSrcVert, aSrcFrag;
1411 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1412 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1417 EOL" TexCoord = occVertex.zw;"
1418 EOL" gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);"
1423 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uAccumTexture", Graphic3d_TOS_FRAGMENT));
1424 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uWeightTexture", Graphic3d_TOS_FRAGMENT));
1428 EOL" vec4 aAccum = occTexture2D (uAccumTexture, TexCoord);"
1429 EOL" float aWeight = occTexture2D (uWeightTexture, TexCoord).r;"
1430 EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
1432 #if !defined(GL_ES_VERSION_2_0)
1433 if (myContext->IsGlGreaterEqual (3, 2))
1435 aProgramSrc->SetHeader ("#version 150");
1438 if (myContext->IsGlGreaterEqual (3, 0))
1440 aProgramSrc->SetHeader ("#version 300 es");
1446 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uAccumTexture", Graphic3d_TOS_FRAGMENT));
1447 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uWeightTexture", Graphic3d_TOS_FRAGMENT));
1451 EOL" ivec2 aTexel = ivec2 (vec2 (textureSize (uAccumTexture)) * TexCoord);"
1452 EOL" vec4 aAccum = texelFetch (uAccumTexture, aTexel, gl_SampleID);"
1453 EOL" float aWeight = texelFetch (uWeightTexture, aTexel, gl_SampleID).r;"
1454 EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
1456 #if !defined(GL_ES_VERSION_2_0)
1457 if (myContext->IsGlGreaterEqual (4, 0))
1459 aProgramSrc->SetHeader ("#version 400");
1462 if (myContext->IsGlGreaterEqual (3, 2))
1464 aProgramSrc->SetHeader ("#version 320 es");
1466 else if (myContext->IsGlGreaterEqual (3, 0))
1468 aProgramSrc->SetHeader ("#version 300 es"); // with GL_OES_sample_variables extension
1473 aProgramSrc->SetNbLightsMax (0);
1474 aProgramSrc->SetNbClipPlanesMax (0);
1475 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1476 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
1477 TCollection_AsciiString aKey;
1478 if (!Create (aProgramSrc, aKey, aProgram))
1480 aProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1481 return Standard_False;
1484 myContext->BindProgram (aProgram);
1485 aProgram->SetSampler (myContext, "uAccumTexture", Graphic3d_TextureUnit_0);
1486 aProgram->SetSampler (myContext, "uWeightTexture", Graphic3d_TextureUnit_1);
1487 myContext->BindProgram (Handle(OpenGl_ShaderProgram)());
1488 return Standard_True;
1491 // =======================================================================
1492 // function : pointSpriteAlphaSrc
1494 // =======================================================================
1495 TCollection_AsciiString OpenGl_ShaderManager::pointSpriteAlphaSrc (const Standard_Integer theBits)
1497 TCollection_AsciiString aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord ").a; }";
1498 #if !defined(GL_ES_VERSION_2_0)
1499 if (myContext->core11 == NULL
1500 && (theBits & OpenGl_PO_TextureA) != 0)
1502 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord ").r; }";
1507 return aSrcGetAlpha;
1513 // =======================================================================
1514 // function : textureUsed
1516 // =======================================================================
1517 static bool textureUsed (const Standard_Integer theBits)
1519 return (theBits & OpenGl_PO_TextureA) != 0 || (theBits & OpenGl_PO_TextureRGB) != 0;
1524 // =======================================================================
1525 // function : defaultGlslVersion
1527 // =======================================================================
1528 int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram,
1530 bool theUsesDerivates) const
1532 int aBits = theBits;
1533 #if !defined(GL_ES_VERSION_2_0)
1534 if (myContext->core32 != NULL)
1536 theProgram->SetHeader ("#version 150");
1540 if ((theBits & OpenGl_PO_StippleLine) != 0)
1542 if (myContext->IsGlGreaterEqual (3, 0))
1544 theProgram->SetHeader ("#version 130");
1546 else if (myContext->CheckExtension ("GL_EXT_gpu_shader4"))
1548 theProgram->SetHeader ("#extension GL_EXT_gpu_shader4 : enable");
1552 aBits = aBits & ~OpenGl_PO_StippleLine;
1556 (void )theUsesDerivates;
1558 // prefer "100 es" on OpenGL ES 3.0- devices (save the features unavailable before "300 es")
1559 // and "300 es" on OpenGL ES 3.1+ devices
1560 if (myContext->IsGlGreaterEqual (3, 1))
1562 if ((theBits & OpenGl_PO_NeedsGeomShader) != 0)
1564 theProgram->SetHeader (myContext->hasGeometryStage != OpenGl_FeatureInExtensions ? "#version 320 es" : "#version 310 es");
1568 theProgram->SetHeader ("#version 300 es");
1573 if ((theBits & OpenGl_PO_WriteOit) != 0
1574 || (theBits & OpenGl_PO_StippleLine) != 0)
1576 if (myContext->IsGlGreaterEqual (3, 0))
1578 theProgram->SetHeader ("#version 300 es");
1582 aBits = aBits & ~OpenGl_PO_WriteOit;
1583 aBits = aBits & ~OpenGl_PO_StippleLine;
1586 if (theUsesDerivates)
1588 if (myContext->IsGlGreaterEqual (3, 0))
1590 theProgram->SetHeader ("#version 300 es");
1592 else if (myContext->oesStdDerivatives)
1594 theProgram->SetHeader ("#extension GL_OES_standard_derivatives : enable");
1602 // =======================================================================
1603 // function : prepareGeomMainSrc
1605 // =======================================================================
1606 TCollection_AsciiString OpenGl_ShaderManager::prepareGeomMainSrc (OpenGl_ShaderObject::ShaderVariableList& theUnifoms,
1607 OpenGl_ShaderObject::ShaderVariableList& theStageInOuts,
1608 Standard_Integer theBits)
1610 if ((theBits & OpenGl_PO_NeedsGeomShader) == 0)
1612 return TCollection_AsciiString();
1615 TCollection_AsciiString aSrcMainGeom =
1619 if ((theBits & OpenGl_PO_MeshEdges) != 0)
1621 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occViewport", Graphic3d_TOS_GEOMETRY));
1622 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("bool occIsQuadMode", Graphic3d_TOS_GEOMETRY));
1623 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineWidth", Graphic3d_TOS_GEOMETRY));
1624 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineWidth", Graphic3d_TOS_FRAGMENT));
1625 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineFeather", Graphic3d_TOS_FRAGMENT));
1626 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occWireframeColor", Graphic3d_TOS_FRAGMENT));
1627 theStageInOuts.Append(OpenGl_ShaderObject::ShaderVariable ("vec3 EdgeDistance", Graphic3d_TOS_GEOMETRY | Graphic3d_TOS_FRAGMENT));
1629 aSrcMainGeom = TCollection_AsciiString()
1630 + EOL"vec3 ViewPortTransform (vec4 theVec)"
1632 EOL" vec3 aWinCoord = theVec.xyz / theVec.w;"
1633 EOL" aWinCoord = aWinCoord * 0.5 + 0.5;"
1634 EOL" aWinCoord.xy = aWinCoord.xy * occViewport.zw + occViewport.xy;"
1635 EOL" return aWinCoord;"
1638 + EOL" vec3 aSideA = ViewPortTransform (gl_in[2].gl_Position) - ViewPortTransform (gl_in[1].gl_Position);"
1639 EOL" vec3 aSideB = ViewPortTransform (gl_in[2].gl_Position) - ViewPortTransform (gl_in[0].gl_Position);"
1640 EOL" vec3 aSideC = ViewPortTransform (gl_in[1].gl_Position) - ViewPortTransform (gl_in[0].gl_Position);"
1641 EOL" float aQuadArea = abs (aSideB.x * aSideC.y - aSideB.y * aSideC.x);"
1642 EOL" vec3 aLenABC = vec3 (length (aSideA), length (aSideB), length (aSideC));"
1643 EOL" vec3 aHeightABC = vec3 (aQuadArea) / aLenABC;"
1644 EOL" aHeightABC = max (aHeightABC, vec3 (10.0 * occLineWidth));" // avoid shrunk presentation disappearing at distance
1645 EOL" float aQuadModeHeightC = occIsQuadMode ? occLineWidth + 1.0 : 0.0;";
1648 for (Standard_Integer aVertIter = 0; aVertIter < 3; ++aVertIter)
1650 const TCollection_AsciiString aVertIndex (aVertIter);
1651 // pass variables from Vertex shader to Fragment shader through Geometry shader
1652 for (OpenGl_ShaderObject::ShaderVariableList::Iterator aVarListIter (theStageInOuts); aVarListIter.More(); aVarListIter.Next())
1654 if (aVarListIter.Value().Stages == (Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT))
1656 const TCollection_AsciiString aVarName = aVarListIter.Value().Name.Token (" ", 2);
1657 aSrcMainGeom += TCollection_AsciiString()
1658 + EOL" geomOut." + aVarName + " = geomIn[" + aVertIndex + "]." + aVarName + ";";
1662 if ((theBits & OpenGl_PO_MeshEdges) != 0)
1666 case 0: aSrcMainGeom += EOL" EdgeDistance = vec3 (aHeightABC[0], 0.0, aQuadModeHeightC);"; break;
1667 case 1: aSrcMainGeom += EOL" EdgeDistance = vec3 (0.0, aHeightABC[1], aQuadModeHeightC);"; break;
1668 case 2: aSrcMainGeom += EOL" EdgeDistance = vec3 (0.0, 0.0, aHeightABC[2]);"; break;
1671 aSrcMainGeom += TCollection_AsciiString()
1672 + EOL" gl_Position = gl_in[" + aVertIndex + "].gl_Position;"
1673 EOL" EmitVertex();";
1676 EOL" EndPrimitive();"
1679 return aSrcMainGeom;
1682 // =======================================================================
1683 // function : prepareStdProgramUnlit
1685 // =======================================================================
1686 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_ShaderProgram)& theProgram,
1687 const Standard_Integer theBits)
1689 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1690 TCollection_AsciiString aSrcVert, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha, aSrcVertEndMain;
1691 TCollection_AsciiString aSrcFrag, aSrcFragExtraMain;
1692 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
1693 TCollection_AsciiString aSrcFragMainGetColor = EOL" occSetFragColor (getFinalColor());";
1694 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1696 if ((theBits & OpenGl_PO_Point) != 0)
1698 #if defined(GL_ES_VERSION_2_0)
1699 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1702 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1705 EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord "); }";
1708 if (textureUsed (theBits))
1710 aSrcGetAlpha = pointSpriteAlphaSrc (theBits);
1712 #if !defined(GL_ES_VERSION_2_0)
1713 if (myContext->core11 != NULL
1714 && myContext->IsGlGreaterEqual (2, 1))
1716 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1720 aSrcFragMainGetColor =
1721 EOL" vec4 aColor = getColor();"
1722 EOL" aColor.a = getAlpha();"
1723 EOL" if (aColor.a <= 0.1) discard;"
1724 EOL" occSetFragColor (aColor);";
1728 aSrcFragMainGetColor =
1729 EOL" vec4 aColor = getColor();"
1730 EOL" if (aColor.a <= 0.1) discard;"
1731 EOL" occSetFragColor (aColor);";
1736 if ((theBits & OpenGl_PO_TextureRGB) != 0 || (theBits & OpenGl_PO_TextureEnv) != 0)
1738 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1741 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1743 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
1746 EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w); }";
1748 else if ((theBits & OpenGl_PO_TextureEnv) != 0)
1750 aSrcVertExtraFunc = THE_FUNC_transformNormal;
1752 aSrcVertExtraMain +=
1753 EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1754 EOL" vec3 aNormal = transformNormal (occNormal);"
1755 EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);"
1756 EOL" aReflect.z += 1.0;"
1757 EOL" TexCoord = vec4(aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5), 0.0, 1.0);";
1760 EOL"vec4 getColor(void) { return occTexture2D (occSamplerBaseColor, TexCoord.st); }";
1763 if ((theBits & OpenGl_PO_VertColor) != 0)
1765 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1766 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1767 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
1770 int aNbClipPlanes = 0;
1771 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
1773 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1774 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1775 aSrcVertExtraMain +=
1776 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1777 EOL" Position = occWorldViewMatrix * PositionWorld;";
1779 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
1781 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
1782 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
1783 ? THE_FRAG_CLIP_CHAINS_N
1784 : THE_FRAG_CLIP_PLANES_N;
1786 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1789 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
1791 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
1794 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
1795 ? THE_FRAG_CLIP_CHAINS_2
1796 : THE_FRAG_CLIP_PLANES_2;
1799 if ((theBits & OpenGl_PO_WriteOit) != 0)
1801 aProgramSrc->SetNbFragmentOutputs (2);
1802 aProgramSrc->SetWeightOitOutput (true);
1805 if ((theBits & OpenGl_PO_StippleLine) != 0)
1807 const Standard_Integer aBits = defaultGlslVersion (aProgramSrc, theBits);
1808 if ((aBits & OpenGl_PO_StippleLine) != 0)
1810 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uPattern", Graphic3d_TOS_FRAGMENT));
1811 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float uFactor", Graphic3d_TOS_FRAGMENT));
1812 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 ScreenSpaceCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1814 EOL" ScreenSpaceCoord = gl_Position.xy / gl_Position.w;";
1815 aSrcFragMainGetColor =
1816 EOL" float anAngle = atan (dFdx (ScreenSpaceCoord.x), dFdy (ScreenSpaceCoord.y));"
1817 EOL" float aRotatePoint = gl_FragCoord.x * sin (anAngle) + gl_FragCoord.y * cos (anAngle);"
1818 EOL" uint aBit = uint (floor (aRotatePoint / uFactor + 0.5)) & 15U;"
1819 EOL" if ((uint (uPattern) & (1U << aBit)) == 0U) discard;"
1820 EOL" vec4 aColor = getFinalColor();"
1821 EOL" if (aColor.a <= 0.1) discard;"
1822 EOL" occSetFragColor (aColor);";
1826 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, "Warning: stipple lines in GLSL will be ignored.");
1835 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1839 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
1840 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
1841 ? THE_FRAG_WIREFRAME_COLOR
1842 : EOL"#define getFinalColor getColor";
1850 + aSrcFragMainGetColor
1853 defaultGlslVersion (aProgramSrc, theBits);
1854 aProgramSrc->SetNbLightsMax (0);
1855 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
1856 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
1857 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
1858 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
1859 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
1860 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
1861 TCollection_AsciiString aKey;
1862 if (!Create (aProgramSrc, aKey, theProgram))
1864 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1865 return Standard_False;
1867 return Standard_True;
1870 // =======================================================================
1871 // function : pointSpriteShadingSrc
1873 // =======================================================================
1874 TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TCollection_AsciiString theBaseColorSrc,
1875 const Standard_Integer theBits)
1877 TCollection_AsciiString aSrcFragGetColor;
1878 if ((theBits & OpenGl_PO_TextureA) != 0)
1880 aSrcFragGetColor = pointSpriteAlphaSrc (theBits) +
1881 EOL"vec4 getColor(void)"
1883 EOL" vec4 aColor = " + theBaseColorSrc + ";"
1884 EOL" aColor.a = getAlpha();"
1885 EOL" if (aColor.a <= 0.1) discard;"
1886 EOL" return aColor;"
1889 else if ((theBits & OpenGl_PO_TextureRGB) != 0)
1891 aSrcFragGetColor = TCollection_AsciiString() +
1892 EOL"vec4 getColor(void)"
1894 EOL" vec4 aColor = " + theBaseColorSrc + ";"
1895 EOL" aColor = occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord ") * aColor;"
1896 EOL" if (aColor.a <= 0.1) discard;"
1897 EOL" return aColor;"
1901 return aSrcFragGetColor;
1904 // =======================================================================
1905 // function : stdComputeLighting
1907 // =======================================================================
1908 TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integer& theNbLights,
1909 Standard_Boolean theHasVertColor)
1911 TCollection_AsciiString aLightsFunc, aLightsLoop;
1913 const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources();
1914 if (!aLights.IsNull())
1916 theNbLights = aLights->NbEnabled();
1917 if (theNbLights <= THE_NB_UNROLLED_LIGHTS_MAX)
1919 Standard_Integer anIndex = 0;
1920 for (Graphic3d_LightSet::Iterator aLightIter (aLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
1921 aLightIter.More(); aLightIter.Next(), ++anIndex)
1923 switch (aLightIter.Value()->Type())
1925 case Graphic3d_TOLS_AMBIENT:
1927 break; // skip ambient
1928 case Graphic3d_TOLS_DIRECTIONAL:
1929 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
1931 case Graphic3d_TOLS_POSITIONAL:
1932 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1934 case Graphic3d_TOLS_SPOT:
1935 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1942 theNbLights = roundUpMaxLightSources (theNbLights);
1943 bool isFirstInLoop = true;
1944 aLightsLoop = aLightsLoop +
1945 EOL" for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)"
1947 EOL" int aType = occLight_Type (anIndex);";
1948 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0)
1950 isFirstInLoop = false;
1952 EOL" if (aType == OccLightType_Direct)"
1954 EOL" directionalLight (anIndex, theNormal, theView, theIsFront);"
1957 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
1961 aLightsLoop += EOL" else ";
1963 isFirstInLoop = false;
1965 EOL" if (aType == OccLightType_Point)"
1967 EOL" pointLight (anIndex, theNormal, theView, aPoint, theIsFront);"
1970 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0)
1974 aLightsLoop += EOL" else ";
1976 isFirstInLoop = false;
1978 EOL" if (aType == OccLightType_Spot)"
1980 EOL" spotLight (anIndex, theNormal, theView, aPoint, theIsFront);"
1983 aLightsLoop += EOL" }";
1985 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) == 1
1986 && theNbLights == 1)
1988 // use the version with hard-coded first index
1989 aLightsLoop = EOL" directionalLightFirst(theNormal, theView, theIsFront);";
1990 aLightsFunc += THE_FUNC_directionalLightFirst;
1992 else if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0)
1994 aLightsFunc += THE_FUNC_directionalLight;
1996 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
1998 aLightsFunc += THE_FUNC_pointLight;
2000 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0)
2002 aLightsFunc += THE_FUNC_spotLight;
2006 TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();";
2007 TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();";
2008 if (theHasVertColor)
2010 aGetMatAmbient = "getVertColor();";
2011 aGetMatDiffuse = "getVertColor();";
2014 return TCollection_AsciiString()
2018 EOL"vec4 computeLighting (in vec3 theNormal,"
2019 EOL" in vec3 theView,"
2020 EOL" in vec4 thePoint,"
2021 EOL" in bool theIsFront)"
2023 EOL" Ambient = occLightAmbient.rgb;"
2024 EOL" Diffuse = vec3 (0.0);"
2025 EOL" Specular = vec3 (0.0);"
2026 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
2028 + EOL" vec4 aMatAmbient = " + aGetMatAmbient
2029 + EOL" vec4 aMatDiffuse = " + aGetMatDiffuse
2030 + EOL" vec4 aMatSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
2031 EOL" vec4 aMatEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
2032 EOL" vec3 aColor = Ambient * aMatAmbient.rgb"
2033 EOL" + Diffuse * aMatDiffuse.rgb"
2034 EOL" + Specular * aMatSpecular.rgb"
2035 EOL" + aMatEmission.rgb;"
2036 EOL" return vec4 (aColor, aMatDiffuse.a);"
2040 // =======================================================================
2041 // function : prepareStdProgramGouraud
2043 // =======================================================================
2044 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
2045 const Standard_Integer theBits)
2047 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2048 TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraMain;
2049 TCollection_AsciiString aSrcFrag, aSrcFragExtraMain;
2050 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
2051 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2053 if ((theBits & OpenGl_PO_Point) != 0)
2055 #if defined(GL_ES_VERSION_2_0)
2056 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
2059 if (textureUsed (theBits))
2061 #if !defined(GL_ES_VERSION_2_0)
2062 if (myContext->core11 != NULL
2063 && myContext->IsGlGreaterEqual (2, 1))
2065 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
2069 aSrcFragGetColor = pointSpriteShadingSrc ("gl_FrontFacing ? FrontColor : BackColor", theBits);
2074 if ((theBits & OpenGl_PO_TextureRGB) != 0)
2076 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2077 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
2080 EOL"vec4 getColor(void)"
2082 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
2083 EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;"
2088 if ((theBits & OpenGl_PO_VertColor) != 0)
2090 aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
2093 int aNbClipPlanes = 0;
2094 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
2096 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2097 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2098 aSrcVertExtraMain +=
2099 EOL" PositionWorld = aPositionWorld;"
2100 EOL" Position = aPosition;";
2102 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
2104 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
2105 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2106 ? THE_FRAG_CLIP_CHAINS_N
2107 : THE_FRAG_CLIP_PLANES_N;
2109 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
2112 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
2114 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
2117 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2118 ? THE_FRAG_CLIP_CHAINS_2
2119 : THE_FRAG_CLIP_PLANES_2;
2122 if ((theBits & OpenGl_PO_WriteOit) != 0)
2124 aProgramSrc->SetNbFragmentOutputs (2);
2125 aProgramSrc->SetWeightOitOutput (true);
2128 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 FrontColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2129 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 BackColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2131 Standard_Integer aNbLights = 0;
2132 const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, (theBits & OpenGl_PO_VertColor) != 0);
2133 aSrcVert = TCollection_AsciiString()
2134 + THE_FUNC_transformNormal
2140 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
2141 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
2142 EOL" vec3 aNormal = transformNormal (occNormal);"
2143 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
2144 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
2145 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
2147 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
2150 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
2151 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
2152 ? THE_FRAG_WIREFRAME_COLOR
2153 : EOL"#define getFinalColor getColor";
2155 aSrcFrag = TCollection_AsciiString()
2160 + EOL" occSetFragColor (getFinalColor());"
2163 defaultGlslVersion (aProgramSrc, theBits);
2164 aProgramSrc->SetNbLightsMax (aNbLights);
2165 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
2166 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
2167 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
2168 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2169 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
2170 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2171 TCollection_AsciiString aKey;
2172 if (!Create (aProgramSrc, aKey, theProgram))
2174 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2175 return Standard_False;
2177 return Standard_True;
2180 // =======================================================================
2181 // function : prepareStdProgramPhong
2183 // =======================================================================
2184 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
2185 const Standard_Integer theBits,
2186 const Standard_Boolean theIsFlatNormal)
2188 #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
2189 const bool isFlatNormal = theIsFlatNormal
2190 && myContext->hasFlatShading != OpenGl_FeatureNotAvailable;
2191 const char* aDFdxSignReversion = "";
2192 #if defined(GL_ES_VERSION_2_0)
2193 if (isFlatNormal != theIsFlatNormal)
2195 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
2196 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
2197 "Warning: flat shading requires OpenGL ES 3.0+ or GL_OES_standard_derivatives extension.");
2199 else if (isFlatNormal
2200 && myContext->Vendor().Search("qualcomm") != -1)
2202 // workaround Adreno driver bug computing reversed normal using dFdx/dFdy
2203 aDFdxSignReversion = "-";
2204 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
2205 "Warning: applied workaround for flat shading normal computation using dFdx/dFdy on Adreno");
2208 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2209 TCollection_AsciiString aSrcVert, aSrcVertExtraFunc, aSrcVertExtraMain;
2210 TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain;
2211 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
2212 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2213 if ((theBits & OpenGl_PO_Point) != 0)
2215 #if defined(GL_ES_VERSION_2_0)
2216 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
2219 if (textureUsed (theBits))
2221 #if !defined(GL_ES_VERSION_2_0)
2222 if (myContext->core11 != NULL
2223 && myContext->IsGlGreaterEqual (2, 1))
2225 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
2229 aSrcFragGetColor = pointSpriteShadingSrc (thePhongCompLight, theBits);
2234 if ((theBits & OpenGl_PO_TextureRGB) != 0)
2236 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2237 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
2240 EOL"vec4 getColor(void)"
2242 EOL" vec4 aColor = " thePhongCompLight ";"
2243 EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;"
2248 if ((theBits & OpenGl_PO_VertColor) != 0)
2250 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2251 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
2252 aSrcFragGetVertColor = EOL"vec4 getVertColor(void) { return VertColor; }";
2255 int aNbClipPlanes = 0;
2256 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
2258 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
2260 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
2261 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2262 ? THE_FRAG_CLIP_CHAINS_N
2263 : THE_FRAG_CLIP_PLANES_N;
2265 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
2268 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
2270 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
2273 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2274 ? THE_FRAG_CLIP_CHAINS_2
2275 : THE_FRAG_CLIP_PLANES_2;
2278 if ((theBits & OpenGl_PO_WriteOit) != 0)
2280 aProgramSrc->SetNbFragmentOutputs (2);
2281 aProgramSrc->SetWeightOitOutput (true);
2286 aSrcFragExtraOut += EOL"vec3 Normal;";
2287 aSrcFragExtraMain += TCollection_AsciiString()
2288 + EOL" Normal = " + aDFdxSignReversion + "normalize (cross (dFdx (Position.xyz / Position.w), dFdy (Position.xyz / Position.w)));"
2289 EOL" if (!gl_FrontFacing) { Normal = -Normal; }";
2293 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 Normal", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2294 aSrcVertExtraFunc += THE_FUNC_transformNormal;
2295 aSrcVertExtraMain += EOL" Normal = transformNormal (occNormal);";
2298 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2299 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2300 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 View", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2302 aSrcVert = TCollection_AsciiString()
2306 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
2307 EOL" Position = occWorldViewMatrix * PositionWorld;"
2308 + EOL" View = vec3 (0.0, 0.0, 1.0);"
2310 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
2313 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
2314 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
2315 ? THE_FRAG_WIREFRAME_COLOR
2316 : EOL"#define getFinalColor getColor";
2318 Standard_Integer aNbLights = 0;
2319 const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, (theBits & OpenGl_PO_VertColor) != 0);
2320 aSrcFrag = TCollection_AsciiString()
2323 + aSrcFragGetVertColor
2330 + EOL" occSetFragColor (getFinalColor());"
2333 defaultGlslVersion (aProgramSrc, theBits, isFlatNormal);
2334 aProgramSrc->SetNbLightsMax (aNbLights);
2335 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
2336 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
2337 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
2338 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2339 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
2340 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2341 TCollection_AsciiString aKey;
2342 if (!Create (aProgramSrc, aKey, theProgram))
2344 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2345 return Standard_False;
2347 return Standard_True;
2350 // =======================================================================
2351 // function : prepareStdProgramStereo
2353 // =======================================================================
2354 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
2355 const Graphic3d_StereoMode theStereoMode)
2357 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2358 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2360 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2361 TCollection_AsciiString aSrcVert =
2364 EOL" TexCoord = occVertex.zw;"
2365 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
2368 TCollection_AsciiString aSrcFrag;
2369 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uLeftSampler", Graphic3d_TOS_FRAGMENT));
2370 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uRightSampler", Graphic3d_TOS_FRAGMENT));
2371 switch (theStereoMode)
2373 case Graphic3d_StereoMode_Anaglyph:
2375 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 uMultL", Graphic3d_TOS_FRAGMENT));
2376 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 uMultR", Graphic3d_TOS_FRAGMENT));
2378 EOL"const vec4 THE_POW_UP = vec4 (2.2, 2.2, 2.2, 1.0);"
2379 EOL"const vec4 THE_POW_DOWN = 1.0 / vec4 (2.2, 2.2, 2.2, 1.0);"
2383 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2384 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2385 EOL" aColorL = pow (aColorL, THE_POW_UP);" // normalize
2386 EOL" aColorR = pow (aColorR, THE_POW_UP);"
2387 EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;"
2388 EOL" occSetFragColor (pow (aColor, THE_POW_DOWN));"
2392 case Graphic3d_StereoMode_RowInterlaced:
2397 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2398 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2399 EOL" if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)"
2401 EOL" occSetFragColor (aColorL);"
2405 EOL" occSetFragColor (aColorR);"
2410 case Graphic3d_StereoMode_ColumnInterlaced:
2415 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2416 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2417 EOL" if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)"
2419 EOL" occSetFragColor (aColorL);"
2423 EOL" occSetFragColor (aColorR);"
2428 case Graphic3d_StereoMode_ChessBoard:
2433 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2434 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2435 EOL" bool isEvenX = int(mod(floor(gl_FragCoord.x - 1023.5), 2.0)) != 1;"
2436 EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y - 1023.5), 2.0)) == 1;"
2437 EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))"
2439 EOL" occSetFragColor (aColorL);"
2443 EOL" occSetFragColor (aColorR);"
2448 case Graphic3d_StereoMode_SideBySide:
2453 EOL" vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);"
2454 EOL" if (TexCoord.x > 0.5)"
2456 EOL" aTexCoord.x -= 1.0;"
2458 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
2459 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
2460 EOL" if (TexCoord.x <= 0.5)"
2462 EOL" occSetFragColor (aColorL);"
2466 EOL" occSetFragColor (aColorR);"
2471 case Graphic3d_StereoMode_OverUnder:
2476 EOL" vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);"
2477 EOL" if (TexCoord.y > 0.5)"
2479 EOL" aTexCoord.y -= 1.0;"
2481 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
2482 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
2483 EOL" if (TexCoord.y <= 0.5)"
2485 EOL" occSetFragColor (aColorL);"
2489 EOL" occSetFragColor (aColorR);"
2494 case Graphic3d_StereoMode_QuadBuffer:
2495 case Graphic3d_StereoMode_SoftPageFlip:
2498 /*const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[Graphic3d_StereoMode_QuadBuffer];
2499 if (!aProgram.IsNull())
2501 return aProgram->IsValid();
2506 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2507 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2508 EOL" aColorL.b = 0.0;"
2509 EOL" aColorL.g = 0.0;"
2510 EOL" aColorR.r = 0.0;"
2511 EOL" occSetFragColor (aColorL + aColorR);"
2517 defaultGlslVersion (aProgramSrc, 0);
2518 aProgramSrc->SetNbLightsMax (0);
2519 aProgramSrc->SetNbClipPlanesMax (0);
2520 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
2521 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
2522 TCollection_AsciiString aKey;
2523 if (!Create (aProgramSrc, aKey, theProgram))
2525 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2526 return Standard_False;
2529 myContext->BindProgram (theProgram);
2530 theProgram->SetSampler (myContext, "uLeftSampler", Graphic3d_TextureUnit_0);
2531 theProgram->SetSampler (myContext, "uRightSampler", Graphic3d_TextureUnit_1);
2532 myContext->BindProgram (NULL);
2533 return Standard_True;
2536 // =======================================================================
2537 // function : prepareStdProgramBoundBox
2539 // =======================================================================
2540 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramBoundBox()
2542 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2544 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2545 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 occBBoxCenter", Graphic3d_TOS_VERTEX));
2546 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 occBBoxSize", Graphic3d_TOS_VERTEX));
2548 TCollection_AsciiString aSrcVert =
2551 EOL" vec4 aCenter = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);"
2552 EOL" vec4 aPos = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);"
2553 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * aPos;"
2556 TCollection_AsciiString aSrcFrag =
2559 EOL" occSetFragColor (occColor);"
2562 defaultGlslVersion (aProgramSrc, 0);
2563 aProgramSrc->SetNbLightsMax (0);
2564 aProgramSrc->SetNbClipPlanesMax (0);
2565 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
2566 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
2567 TCollection_AsciiString aKey;
2568 if (!Create (aProgramSrc, aKey, myBoundBoxProgram))
2570 myBoundBoxProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2571 return Standard_False;
2574 const OpenGl_Vec4 aMin (-0.5f, -0.5f, -0.5f, 1.0f);
2575 const OpenGl_Vec4 anAxisShifts[3] =
2577 OpenGl_Vec4 (1.0f, 0.0f, 0.0f, 0.0f),
2578 OpenGl_Vec4 (0.0f, 1.0f, 0.0f, 0.0f),
2579 OpenGl_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)
2582 const OpenGl_Vec4 aLookup1 (0.0f, 1.0f, 0.0f, 1.0f);
2583 const OpenGl_Vec4 aLookup2 (0.0f, 0.0f, 1.0f, 1.0f);
2584 OpenGl_Vec4 aLinesVertices[24];
2585 for (int anAxis = 0, aVertex = 0; anAxis < 3; ++anAxis)
2587 for (int aCompIter = 0; aCompIter < 4; ++aCompIter)
2589 aLinesVertices[aVertex++] = aMin
2590 + anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter]
2591 + anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter];
2593 aLinesVertices[aVertex++] = aMin
2594 + anAxisShifts[anAxis]
2595 + anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter]
2596 + anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter];
2599 if (myContext->ToUseVbo())
2601 myBoundBoxVertBuffer = new OpenGl_VertexBuffer();
2602 if (myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData()))
2604 myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer);
2605 return Standard_True;
2608 myBoundBoxVertBuffer = new OpenGl_VertexBufferCompat();
2609 myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData());
2610 myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer);
2611 return Standard_True;
2614 // =======================================================================
2615 // function : bindProgramWithState
2617 // =======================================================================
2618 Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram)
2620 const Standard_Boolean isBound = myContext->BindProgram (theProgram);
2622 && !theProgram.IsNull())
2624 theProgram->ApplyVariables (myContext);
2626 PushState (theProgram);