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);
380 //! Generate map key for light sources configuration.
381 static TCollection_AsciiString genLightKey (const Handle(Graphic3d_LightSet)& theLights)
383 if (theLights->NbEnabled() <= THE_NB_UNROLLED_LIGHTS_MAX)
385 return TCollection_AsciiString ("l_") + theLights->KeyEnabledLong();
388 const Standard_Integer aMaxLimit = roundUpMaxLightSources (theLights->NbEnabled());
389 return TCollection_AsciiString ("l_") + theLights->KeyEnabledShort() + aMaxLimit;
393 // =======================================================================
394 // function : OpenGl_ShaderManager
395 // purpose : Creates new empty shader manager
396 // =======================================================================
397 OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
398 : myFfpProgram (new OpenGl_ShaderProgramFFP()),
399 myShadingModel (Graphic3d_TOSM_VERTEX),
400 myUnlitPrograms (new OpenGl_SetOfShaderPrograms()),
401 myContext (theContext),
402 myHasLocalOrigin (Standard_False),
408 // =======================================================================
409 // function : ~OpenGl_ShaderManager
410 // purpose : Releases resources of shader manager
411 // =======================================================================
412 OpenGl_ShaderManager::~OpenGl_ShaderManager()
414 myProgramList.Clear();
417 // =======================================================================
420 // =======================================================================
421 void OpenGl_ShaderManager::clear()
423 myProgramList.Clear();
424 myLightPrograms.Nullify();
425 myUnlitPrograms = new OpenGl_SetOfShaderPrograms();
426 myMapOfLightPrograms.Clear();
427 myFontProgram.Nullify();
428 myBlitProgram.Nullify();
429 myBoundBoxProgram.Nullify();
430 myBoundBoxVertBuffer.Nullify();
431 for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter)
433 myStereoPrograms[aModeIter].Nullify();
435 switchLightPrograms();
438 // =======================================================================
440 // purpose : Creates new shader program
441 // =======================================================================
442 Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
443 TCollection_AsciiString& theShareKey,
444 Handle(OpenGl_ShaderProgram)& theProgram)
446 theProgram.Nullify();
447 if (theProxy.IsNull())
449 return Standard_False;
452 theShareKey = theProxy->GetId();
453 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
455 if (theProgram->Share())
457 myProgramList.Append (theProgram);
459 return Standard_True;
462 theProgram = new OpenGl_ShaderProgram (theProxy);
463 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
465 theProgram->Release (myContext);
467 theProgram.Nullify();
468 return Standard_False;
471 myProgramList.Append (theProgram);
472 myContext->ShareResource (theShareKey, theProgram);
473 return Standard_True;
476 // =======================================================================
477 // function : Unregister
478 // purpose : Removes specified shader program from the manager
479 // =======================================================================
480 void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
481 Handle(OpenGl_ShaderProgram)& theProgram)
483 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
485 if (anIt.Value() == theProgram)
487 if (!theProgram->UnShare())
490 theProgram.Nullify();
494 myProgramList.Remove (anIt);
499 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
502 myContext->DelayedRelease (theProgram);
503 theProgram.Nullify();
507 theProgram.Nullify();
508 myContext->ReleaseResource (anID, Standard_True);
512 // =======================================================================
513 // function : ShaderPrograms
514 // purpose : Returns list of registered shader programs
515 // =======================================================================
516 const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
518 return myProgramList;
521 // =======================================================================
523 // purpose : Returns true if no program objects are attached
524 // =======================================================================
525 Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
527 return myProgramList.IsEmpty();
530 // =======================================================================
531 // function : switchLightPrograms
533 // =======================================================================
534 void OpenGl_ShaderManager::switchLightPrograms()
536 const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources();
537 if (aLights.IsNull())
539 myLightPrograms = myUnlitPrograms;
543 const TCollection_AsciiString aKey = genLightKey (aLights);
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, "font", 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->SetId ("occt_blit");
1384 aProgramSrc->SetNbLightsMax (0);
1385 aProgramSrc->SetNbClipPlanesMax (0);
1386 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1387 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
1388 TCollection_AsciiString aKey;
1389 if (!Create (aProgramSrc, aKey, myBlitProgram))
1391 myBlitProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1392 return Standard_False;
1395 myContext->BindProgram (myBlitProgram);
1396 myBlitProgram->SetSampler (myContext, "uColorSampler", Graphic3d_TextureUnit_0);
1397 myBlitProgram->SetSampler (myContext, "uDepthSampler", Graphic3d_TextureUnit_1);
1398 myContext->BindProgram (NULL);
1399 return Standard_True;
1402 // =======================================================================
1403 // function : prepareStdProgramOitCompositing
1405 // =======================================================================
1406 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const Standard_Boolean theMsaa)
1408 Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram[theMsaa ? 1 : 0];
1409 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1410 TCollection_AsciiString aSrcVert, aSrcFrag;
1412 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1413 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1418 EOL" TexCoord = occVertex.zw;"
1419 EOL" gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);"
1424 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uAccumTexture", Graphic3d_TOS_FRAGMENT));
1425 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uWeightTexture", Graphic3d_TOS_FRAGMENT));
1429 EOL" vec4 aAccum = occTexture2D (uAccumTexture, TexCoord);"
1430 EOL" float aWeight = occTexture2D (uWeightTexture, TexCoord).r;"
1431 EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
1433 #if !defined(GL_ES_VERSION_2_0)
1434 if (myContext->IsGlGreaterEqual (3, 2))
1436 aProgramSrc->SetHeader ("#version 150");
1439 if (myContext->IsGlGreaterEqual (3, 0))
1441 aProgramSrc->SetHeader ("#version 300 es");
1447 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uAccumTexture", Graphic3d_TOS_FRAGMENT));
1448 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uWeightTexture", Graphic3d_TOS_FRAGMENT));
1452 EOL" ivec2 aTexel = ivec2 (vec2 (textureSize (uAccumTexture)) * TexCoord);"
1453 EOL" vec4 aAccum = texelFetch (uAccumTexture, aTexel, gl_SampleID);"
1454 EOL" float aWeight = texelFetch (uWeightTexture, aTexel, gl_SampleID).r;"
1455 EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
1457 #if !defined(GL_ES_VERSION_2_0)
1458 if (myContext->IsGlGreaterEqual (4, 0))
1460 aProgramSrc->SetHeader ("#version 400");
1463 if (myContext->IsGlGreaterEqual (3, 2))
1465 aProgramSrc->SetHeader ("#version 320 es");
1467 else if (myContext->IsGlGreaterEqual (3, 0))
1469 aProgramSrc->SetHeader ("#version 300 es"); // with GL_OES_sample_variables extension
1474 aProgramSrc->SetId (theMsaa ? "occt_weight-oit-msaa" : "occt_weight-oit");
1475 aProgramSrc->SetNbLightsMax (0);
1476 aProgramSrc->SetNbClipPlanesMax (0);
1477 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1478 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
1479 TCollection_AsciiString aKey;
1480 if (!Create (aProgramSrc, aKey, aProgram))
1482 aProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1483 return Standard_False;
1486 myContext->BindProgram (aProgram);
1487 aProgram->SetSampler (myContext, "uAccumTexture", Graphic3d_TextureUnit_0);
1488 aProgram->SetSampler (myContext, "uWeightTexture", Graphic3d_TextureUnit_1);
1489 myContext->BindProgram (Handle(OpenGl_ShaderProgram)());
1490 return Standard_True;
1493 // =======================================================================
1494 // function : pointSpriteAlphaSrc
1496 // =======================================================================
1497 TCollection_AsciiString OpenGl_ShaderManager::pointSpriteAlphaSrc (const Standard_Integer theBits)
1499 TCollection_AsciiString aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord ").a; }";
1500 #if !defined(GL_ES_VERSION_2_0)
1501 if (myContext->core11 == NULL
1502 && (theBits & OpenGl_PO_TextureA) != 0)
1504 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord ").r; }";
1509 return aSrcGetAlpha;
1515 // =======================================================================
1516 // function : textureUsed
1518 // =======================================================================
1519 static bool textureUsed (const Standard_Integer theBits)
1521 return (theBits & OpenGl_PO_TextureA) != 0 || (theBits & OpenGl_PO_TextureRGB) != 0;
1526 // =======================================================================
1527 // function : defaultGlslVersion
1529 // =======================================================================
1530 int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram,
1531 const TCollection_AsciiString& theName,
1533 bool theUsesDerivates) const
1535 int aBits = theBits;
1536 #if !defined(GL_ES_VERSION_2_0)
1537 if (myContext->core32 != NULL)
1539 theProgram->SetHeader ("#version 150");
1543 if ((theBits & OpenGl_PO_StippleLine) != 0)
1545 if (myContext->IsGlGreaterEqual (3, 0))
1547 theProgram->SetHeader ("#version 130");
1549 else if (myContext->CheckExtension ("GL_EXT_gpu_shader4"))
1551 theProgram->SetHeader ("#extension GL_EXT_gpu_shader4 : enable");
1555 aBits = aBits & ~OpenGl_PO_StippleLine;
1559 (void )theUsesDerivates;
1561 // prefer "100 es" on OpenGL ES 3.0- devices (save the features unavailable before "300 es")
1562 // and "300 es" on OpenGL ES 3.1+ devices
1563 if (myContext->IsGlGreaterEqual (3, 1))
1565 if ((theBits & OpenGl_PO_NeedsGeomShader) != 0)
1567 theProgram->SetHeader (myContext->hasGeometryStage != OpenGl_FeatureInExtensions ? "#version 320 es" : "#version 310 es");
1571 theProgram->SetHeader ("#version 300 es");
1576 if ((theBits & OpenGl_PO_WriteOit) != 0
1577 || (theBits & OpenGl_PO_StippleLine) != 0)
1579 if (myContext->IsGlGreaterEqual (3, 0))
1581 theProgram->SetHeader ("#version 300 es");
1585 aBits = aBits & ~OpenGl_PO_WriteOit;
1586 aBits = aBits & ~OpenGl_PO_StippleLine;
1589 if (theUsesDerivates)
1591 if (myContext->IsGlGreaterEqual (3, 0))
1593 theProgram->SetHeader ("#version 300 es");
1595 else if (myContext->oesStdDerivatives)
1597 theProgram->SetHeader ("#extension GL_OES_standard_derivatives : enable");
1603 // should fit OpenGl_PO_NB
1605 Sprintf (aBitsStr, "%04x", aBits);
1606 theProgram->SetId (TCollection_AsciiString ("occt_") + theName + aBitsStr);
1610 // =======================================================================
1611 // function : prepareGeomMainSrc
1613 // =======================================================================
1614 TCollection_AsciiString OpenGl_ShaderManager::prepareGeomMainSrc (OpenGl_ShaderObject::ShaderVariableList& theUnifoms,
1615 OpenGl_ShaderObject::ShaderVariableList& theStageInOuts,
1616 Standard_Integer theBits)
1618 if ((theBits & OpenGl_PO_NeedsGeomShader) == 0)
1620 return TCollection_AsciiString();
1623 TCollection_AsciiString aSrcMainGeom =
1627 if ((theBits & OpenGl_PO_MeshEdges) != 0)
1629 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occViewport", Graphic3d_TOS_GEOMETRY));
1630 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("bool occIsQuadMode", Graphic3d_TOS_GEOMETRY));
1631 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineWidth", Graphic3d_TOS_GEOMETRY));
1632 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineWidth", Graphic3d_TOS_FRAGMENT));
1633 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineFeather", Graphic3d_TOS_FRAGMENT));
1634 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occWireframeColor", Graphic3d_TOS_FRAGMENT));
1635 theStageInOuts.Append(OpenGl_ShaderObject::ShaderVariable ("vec3 EdgeDistance", Graphic3d_TOS_GEOMETRY | Graphic3d_TOS_FRAGMENT));
1637 aSrcMainGeom = TCollection_AsciiString()
1638 + EOL"vec3 ViewPortTransform (vec4 theVec)"
1640 EOL" vec3 aWinCoord = theVec.xyz / theVec.w;"
1641 EOL" aWinCoord = aWinCoord * 0.5 + 0.5;"
1642 EOL" aWinCoord.xy = aWinCoord.xy * occViewport.zw + occViewport.xy;"
1643 EOL" return aWinCoord;"
1646 + EOL" vec3 aSideA = ViewPortTransform (gl_in[2].gl_Position) - ViewPortTransform (gl_in[1].gl_Position);"
1647 EOL" vec3 aSideB = ViewPortTransform (gl_in[2].gl_Position) - ViewPortTransform (gl_in[0].gl_Position);"
1648 EOL" vec3 aSideC = ViewPortTransform (gl_in[1].gl_Position) - ViewPortTransform (gl_in[0].gl_Position);"
1649 EOL" float aQuadArea = abs (aSideB.x * aSideC.y - aSideB.y * aSideC.x);"
1650 EOL" vec3 aLenABC = vec3 (length (aSideA), length (aSideB), length (aSideC));"
1651 EOL" vec3 aHeightABC = vec3 (aQuadArea) / aLenABC;"
1652 EOL" aHeightABC = max (aHeightABC, vec3 (10.0 * occLineWidth));" // avoid shrunk presentation disappearing at distance
1653 EOL" float aQuadModeHeightC = occIsQuadMode ? occLineWidth + 1.0 : 0.0;";
1656 for (Standard_Integer aVertIter = 0; aVertIter < 3; ++aVertIter)
1658 const TCollection_AsciiString aVertIndex (aVertIter);
1659 // pass variables from Vertex shader to Fragment shader through Geometry shader
1660 for (OpenGl_ShaderObject::ShaderVariableList::Iterator aVarListIter (theStageInOuts); aVarListIter.More(); aVarListIter.Next())
1662 if (aVarListIter.Value().Stages == (Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT))
1664 const TCollection_AsciiString aVarName = aVarListIter.Value().Name.Token (" ", 2);
1665 aSrcMainGeom += TCollection_AsciiString()
1666 + EOL" geomOut." + aVarName + " = geomIn[" + aVertIndex + "]." + aVarName + ";";
1670 if ((theBits & OpenGl_PO_MeshEdges) != 0)
1674 case 0: aSrcMainGeom += EOL" EdgeDistance = vec3 (aHeightABC[0], 0.0, aQuadModeHeightC);"; break;
1675 case 1: aSrcMainGeom += EOL" EdgeDistance = vec3 (0.0, aHeightABC[1], aQuadModeHeightC);"; break;
1676 case 2: aSrcMainGeom += EOL" EdgeDistance = vec3 (0.0, 0.0, aHeightABC[2]);"; break;
1679 aSrcMainGeom += TCollection_AsciiString()
1680 + EOL" gl_Position = gl_in[" + aVertIndex + "].gl_Position;"
1681 EOL" EmitVertex();";
1684 EOL" EndPrimitive();"
1687 return aSrcMainGeom;
1690 // =======================================================================
1691 // function : prepareStdProgramUnlit
1693 // =======================================================================
1694 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_ShaderProgram)& theProgram,
1695 const Standard_Integer theBits)
1697 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1698 TCollection_AsciiString aSrcVert, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha, aSrcVertEndMain;
1699 TCollection_AsciiString aSrcFrag, aSrcFragExtraMain;
1700 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
1701 TCollection_AsciiString aSrcFragMainGetColor = EOL" occSetFragColor (getFinalColor());";
1702 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1704 if ((theBits & OpenGl_PO_Point) != 0)
1706 #if defined(GL_ES_VERSION_2_0)
1707 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1710 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1713 EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord "); }";
1716 if (textureUsed (theBits))
1718 aSrcGetAlpha = pointSpriteAlphaSrc (theBits);
1720 #if !defined(GL_ES_VERSION_2_0)
1721 if (myContext->core11 != NULL
1722 && myContext->IsGlGreaterEqual (2, 1))
1724 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1728 aSrcFragMainGetColor =
1729 EOL" vec4 aColor = getColor();"
1730 EOL" aColor.a = getAlpha();"
1731 EOL" if (aColor.a <= 0.1) discard;"
1732 EOL" occSetFragColor (aColor);";
1736 aSrcFragMainGetColor =
1737 EOL" vec4 aColor = getColor();"
1738 EOL" if (aColor.a <= 0.1) discard;"
1739 EOL" occSetFragColor (aColor);";
1744 if ((theBits & OpenGl_PO_TextureRGB) != 0 || (theBits & OpenGl_PO_TextureEnv) != 0)
1746 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1749 if ((theBits & OpenGl_PO_TextureRGB) != 0)
1751 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
1754 EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w); }";
1756 else if ((theBits & OpenGl_PO_TextureEnv) != 0)
1758 aSrcVertExtraFunc = THE_FUNC_transformNormal;
1760 aSrcVertExtraMain +=
1761 EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1762 EOL" vec3 aNormal = transformNormal (occNormal);"
1763 EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);"
1764 EOL" aReflect.z += 1.0;"
1765 EOL" TexCoord = vec4(aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5), 0.0, 1.0);";
1768 EOL"vec4 getColor(void) { return occTexture2D (occSamplerBaseColor, TexCoord.st); }";
1771 if ((theBits & OpenGl_PO_VertColor) != 0)
1773 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1774 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1775 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
1778 int aNbClipPlanes = 0;
1779 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
1781 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1782 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1783 aSrcVertExtraMain +=
1784 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1785 EOL" Position = occWorldViewMatrix * PositionWorld;";
1787 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
1789 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
1790 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
1791 ? THE_FRAG_CLIP_CHAINS_N
1792 : THE_FRAG_CLIP_PLANES_N;
1794 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1797 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
1799 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
1802 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
1803 ? THE_FRAG_CLIP_CHAINS_2
1804 : THE_FRAG_CLIP_PLANES_2;
1807 if ((theBits & OpenGl_PO_WriteOit) != 0)
1809 aProgramSrc->SetNbFragmentOutputs (2);
1810 aProgramSrc->SetWeightOitOutput (true);
1813 if ((theBits & OpenGl_PO_StippleLine) != 0)
1815 const Standard_Integer aBits = defaultGlslVersion (aProgramSrc, "unlit", theBits);
1816 if ((aBits & OpenGl_PO_StippleLine) != 0)
1818 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uPattern", Graphic3d_TOS_FRAGMENT));
1819 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float uFactor", Graphic3d_TOS_FRAGMENT));
1820 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 ScreenSpaceCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1822 EOL" ScreenSpaceCoord = gl_Position.xy / gl_Position.w;";
1823 aSrcFragMainGetColor =
1824 EOL" float anAngle = atan (dFdx (ScreenSpaceCoord.x), dFdy (ScreenSpaceCoord.y));"
1825 EOL" float aRotatePoint = gl_FragCoord.x * sin (anAngle) + gl_FragCoord.y * cos (anAngle);"
1826 EOL" uint aBit = uint (floor (aRotatePoint / uFactor + 0.5)) & 15U;"
1827 EOL" if ((uint (uPattern) & (1U << aBit)) == 0U) discard;"
1828 EOL" vec4 aColor = getFinalColor();"
1829 EOL" if (aColor.a <= 0.1) discard;"
1830 EOL" occSetFragColor (aColor);";
1834 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, "Warning: stipple lines in GLSL will be ignored.");
1843 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1847 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
1848 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
1849 ? THE_FRAG_WIREFRAME_COLOR
1850 : EOL"#define getFinalColor getColor";
1858 + aSrcFragMainGetColor
1861 defaultGlslVersion (aProgramSrc, "unlit", theBits);
1862 aProgramSrc->SetNbLightsMax (0);
1863 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
1864 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
1865 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
1866 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
1867 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
1868 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
1869 TCollection_AsciiString aKey;
1870 if (!Create (aProgramSrc, aKey, theProgram))
1872 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1873 return Standard_False;
1875 return Standard_True;
1878 // =======================================================================
1879 // function : pointSpriteShadingSrc
1881 // =======================================================================
1882 TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TCollection_AsciiString theBaseColorSrc,
1883 const Standard_Integer theBits)
1885 TCollection_AsciiString aSrcFragGetColor;
1886 if ((theBits & OpenGl_PO_TextureA) != 0)
1888 aSrcFragGetColor = pointSpriteAlphaSrc (theBits) +
1889 EOL"vec4 getColor(void)"
1891 EOL" vec4 aColor = " + theBaseColorSrc + ";"
1892 EOL" aColor.a = getAlpha();"
1893 EOL" if (aColor.a <= 0.1) discard;"
1894 EOL" return aColor;"
1897 else if ((theBits & OpenGl_PO_TextureRGB) != 0)
1899 aSrcFragGetColor = TCollection_AsciiString() +
1900 EOL"vec4 getColor(void)"
1902 EOL" vec4 aColor = " + theBaseColorSrc + ";"
1903 EOL" aColor = occTexture2D(occSamplerBaseColor, " THE_VEC2_glPointCoord ") * aColor;"
1904 EOL" if (aColor.a <= 0.1) discard;"
1905 EOL" return aColor;"
1909 return aSrcFragGetColor;
1912 // =======================================================================
1913 // function : stdComputeLighting
1915 // =======================================================================
1916 TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integer& theNbLights,
1917 Standard_Boolean theHasVertColor)
1919 TCollection_AsciiString aLightsFunc, aLightsLoop;
1921 const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources();
1922 if (!aLights.IsNull())
1924 theNbLights = aLights->NbEnabled();
1925 if (theNbLights <= THE_NB_UNROLLED_LIGHTS_MAX)
1927 Standard_Integer anIndex = 0;
1928 for (Graphic3d_LightSet::Iterator aLightIter (aLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
1929 aLightIter.More(); aLightIter.Next(), ++anIndex)
1931 switch (aLightIter.Value()->Type())
1933 case Graphic3d_TOLS_AMBIENT:
1935 break; // skip ambient
1936 case Graphic3d_TOLS_DIRECTIONAL:
1937 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
1939 case Graphic3d_TOLS_POSITIONAL:
1940 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1942 case Graphic3d_TOLS_SPOT:
1943 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
1950 theNbLights = roundUpMaxLightSources (theNbLights);
1951 bool isFirstInLoop = true;
1952 aLightsLoop = aLightsLoop +
1953 EOL" for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)"
1955 EOL" int aType = occLight_Type (anIndex);";
1956 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0)
1958 isFirstInLoop = false;
1960 EOL" if (aType == OccLightType_Direct)"
1962 EOL" directionalLight (anIndex, theNormal, theView, theIsFront);"
1965 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
1969 aLightsLoop += EOL" else ";
1971 isFirstInLoop = false;
1973 EOL" if (aType == OccLightType_Point)"
1975 EOL" pointLight (anIndex, theNormal, theView, aPoint, theIsFront);"
1978 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0)
1982 aLightsLoop += EOL" else ";
1984 isFirstInLoop = false;
1986 EOL" if (aType == OccLightType_Spot)"
1988 EOL" spotLight (anIndex, theNormal, theView, aPoint, theIsFront);"
1991 aLightsLoop += EOL" }";
1993 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) == 1
1994 && theNbLights == 1)
1996 // use the version with hard-coded first index
1997 aLightsLoop = EOL" directionalLightFirst(theNormal, theView, theIsFront);";
1998 aLightsFunc += THE_FUNC_directionalLightFirst;
2000 else if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0)
2002 aLightsFunc += THE_FUNC_directionalLight;
2004 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
2006 aLightsFunc += THE_FUNC_pointLight;
2008 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0)
2010 aLightsFunc += THE_FUNC_spotLight;
2014 TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();";
2015 TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();";
2016 if (theHasVertColor)
2018 aGetMatAmbient = "getVertColor();";
2019 aGetMatDiffuse = "getVertColor();";
2022 return TCollection_AsciiString()
2026 EOL"vec4 computeLighting (in vec3 theNormal,"
2027 EOL" in vec3 theView,"
2028 EOL" in vec4 thePoint,"
2029 EOL" in bool theIsFront)"
2031 EOL" Ambient = occLightAmbient.rgb;"
2032 EOL" Diffuse = vec3 (0.0);"
2033 EOL" Specular = vec3 (0.0);"
2034 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
2036 + EOL" vec4 aMatAmbient = " + aGetMatAmbient
2037 + EOL" vec4 aMatDiffuse = " + aGetMatDiffuse
2038 + EOL" vec4 aMatSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
2039 EOL" vec4 aMatEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
2040 EOL" vec3 aColor = Ambient * aMatAmbient.rgb"
2041 EOL" + Diffuse * aMatDiffuse.rgb"
2042 EOL" + Specular * aMatSpecular.rgb"
2043 EOL" + aMatEmission.rgb;"
2044 EOL" return vec4 (aColor, aMatDiffuse.a);"
2048 // =======================================================================
2049 // function : prepareStdProgramGouraud
2051 // =======================================================================
2052 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
2053 const Standard_Integer theBits)
2055 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2056 TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraMain;
2057 TCollection_AsciiString aSrcFrag, aSrcFragExtraMain;
2058 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
2059 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2061 if ((theBits & OpenGl_PO_Point) != 0)
2063 #if defined(GL_ES_VERSION_2_0)
2064 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
2067 if (textureUsed (theBits))
2069 #if !defined(GL_ES_VERSION_2_0)
2070 if (myContext->core11 != NULL
2071 && myContext->IsGlGreaterEqual (2, 1))
2073 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
2077 aSrcFragGetColor = pointSpriteShadingSrc ("gl_FrontFacing ? FrontColor : BackColor", theBits);
2082 if ((theBits & OpenGl_PO_TextureRGB) != 0)
2084 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2085 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
2088 EOL"vec4 getColor(void)"
2090 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
2091 EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;"
2096 if ((theBits & OpenGl_PO_VertColor) != 0)
2098 aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
2101 int aNbClipPlanes = 0;
2102 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
2104 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2105 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2106 aSrcVertExtraMain +=
2107 EOL" PositionWorld = aPositionWorld;"
2108 EOL" Position = aPosition;";
2110 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
2112 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
2113 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2114 ? THE_FRAG_CLIP_CHAINS_N
2115 : THE_FRAG_CLIP_PLANES_N;
2117 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
2120 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
2122 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
2125 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2126 ? THE_FRAG_CLIP_CHAINS_2
2127 : THE_FRAG_CLIP_PLANES_2;
2130 if ((theBits & OpenGl_PO_WriteOit) != 0)
2132 aProgramSrc->SetNbFragmentOutputs (2);
2133 aProgramSrc->SetWeightOitOutput (true);
2136 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 FrontColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2137 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 BackColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2139 Standard_Integer aNbLights = 0;
2140 const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, (theBits & OpenGl_PO_VertColor) != 0);
2141 aSrcVert = TCollection_AsciiString()
2142 + THE_FUNC_transformNormal
2148 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
2149 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
2150 EOL" vec3 aNormal = transformNormal (occNormal);"
2151 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
2152 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
2153 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
2155 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
2158 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
2159 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
2160 ? THE_FRAG_WIREFRAME_COLOR
2161 : EOL"#define getFinalColor getColor";
2163 aSrcFrag = TCollection_AsciiString()
2168 + EOL" occSetFragColor (getFinalColor());"
2171 const TCollection_AsciiString aProgId = TCollection_AsciiString ("gouraud-") + genLightKey (myLightSourceState.LightSources()) + "-";
2172 defaultGlslVersion (aProgramSrc, aProgId, theBits);
2173 aProgramSrc->SetNbLightsMax (aNbLights);
2174 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
2175 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
2176 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
2177 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2178 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
2179 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2180 TCollection_AsciiString aKey;
2181 if (!Create (aProgramSrc, aKey, theProgram))
2183 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2184 return Standard_False;
2186 return Standard_True;
2189 // =======================================================================
2190 // function : prepareStdProgramPhong
2192 // =======================================================================
2193 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
2194 const Standard_Integer theBits,
2195 const Standard_Boolean theIsFlatNormal)
2197 #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
2198 const bool isFlatNormal = theIsFlatNormal
2199 && myContext->hasFlatShading != OpenGl_FeatureNotAvailable;
2200 const char* aDFdxSignReversion = "";
2201 #if defined(GL_ES_VERSION_2_0)
2202 if (isFlatNormal != theIsFlatNormal)
2204 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
2205 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
2206 "Warning: flat shading requires OpenGL ES 3.0+ or GL_OES_standard_derivatives extension.");
2208 else if (isFlatNormal
2209 && myContext->Vendor().Search("qualcomm") != -1)
2211 // workaround Adreno driver bug computing reversed normal using dFdx/dFdy
2212 aDFdxSignReversion = "-";
2213 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
2214 "Warning: applied workaround for flat shading normal computation using dFdx/dFdy on Adreno");
2217 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2218 TCollection_AsciiString aSrcVert, aSrcVertExtraFunc, aSrcVertExtraMain;
2219 TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain;
2220 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
2221 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2222 if ((theBits & OpenGl_PO_Point) != 0)
2224 #if defined(GL_ES_VERSION_2_0)
2225 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
2228 if (textureUsed (theBits))
2230 #if !defined(GL_ES_VERSION_2_0)
2231 if (myContext->core11 != NULL
2232 && myContext->IsGlGreaterEqual (2, 1))
2234 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
2238 aSrcFragGetColor = pointSpriteShadingSrc (thePhongCompLight, theBits);
2243 if ((theBits & OpenGl_PO_TextureRGB) != 0)
2245 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2246 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
2249 EOL"vec4 getColor(void)"
2251 EOL" vec4 aColor = " thePhongCompLight ";"
2252 EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;"
2257 if ((theBits & OpenGl_PO_VertColor) != 0)
2259 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2260 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
2261 aSrcFragGetVertColor = EOL"vec4 getVertColor(void) { return VertColor; }";
2264 int aNbClipPlanes = 0;
2265 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
2267 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
2269 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
2270 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2271 ? THE_FRAG_CLIP_CHAINS_N
2272 : THE_FRAG_CLIP_PLANES_N;
2274 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
2277 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
2279 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
2282 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2283 ? THE_FRAG_CLIP_CHAINS_2
2284 : THE_FRAG_CLIP_PLANES_2;
2287 if ((theBits & OpenGl_PO_WriteOit) != 0)
2289 aProgramSrc->SetNbFragmentOutputs (2);
2290 aProgramSrc->SetWeightOitOutput (true);
2295 aSrcFragExtraOut += EOL"vec3 Normal;";
2296 aSrcFragExtraMain += TCollection_AsciiString()
2297 + EOL" Normal = " + aDFdxSignReversion + "normalize (cross (dFdx (Position.xyz / Position.w), dFdy (Position.xyz / Position.w)));"
2298 EOL" if (!gl_FrontFacing) { Normal = -Normal; }";
2302 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 Normal", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2303 aSrcVertExtraFunc += THE_FUNC_transformNormal;
2304 aSrcVertExtraMain += EOL" Normal = transformNormal (occNormal);";
2307 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2308 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2309 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 View", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2311 aSrcVert = TCollection_AsciiString()
2315 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
2316 EOL" Position = occWorldViewMatrix * PositionWorld;"
2317 + EOL" View = vec3 (0.0, 0.0, 1.0);"
2319 + EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;"
2322 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
2323 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
2324 ? THE_FRAG_WIREFRAME_COLOR
2325 : EOL"#define getFinalColor getColor";
2327 Standard_Integer aNbLights = 0;
2328 const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, (theBits & OpenGl_PO_VertColor) != 0);
2329 aSrcFrag = TCollection_AsciiString()
2332 + aSrcFragGetVertColor
2339 + EOL" occSetFragColor (getFinalColor());"
2342 const TCollection_AsciiString aProgId = TCollection_AsciiString (theIsFlatNormal ? "flat-" : "phong-") + genLightKey (myLightSourceState.LightSources()) + "-";
2343 defaultGlslVersion (aProgramSrc, aProgId, theBits, isFlatNormal);
2344 aProgramSrc->SetNbLightsMax (aNbLights);
2345 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
2346 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
2347 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
2348 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2349 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
2350 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2351 TCollection_AsciiString aKey;
2352 if (!Create (aProgramSrc, aKey, theProgram))
2354 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2355 return Standard_False;
2357 return Standard_True;
2360 // =======================================================================
2361 // function : prepareStdProgramStereo
2363 // =======================================================================
2364 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
2365 const Graphic3d_StereoMode theStereoMode)
2367 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2368 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2370 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2371 TCollection_AsciiString aSrcVert =
2374 EOL" TexCoord = occVertex.zw;"
2375 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
2378 TCollection_AsciiString aSrcFrag;
2379 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uLeftSampler", Graphic3d_TOS_FRAGMENT));
2380 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uRightSampler", Graphic3d_TOS_FRAGMENT));
2381 const char* aName = "stereo";
2382 switch (theStereoMode)
2384 case Graphic3d_StereoMode_Anaglyph:
2387 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 uMultL", Graphic3d_TOS_FRAGMENT));
2388 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 uMultR", Graphic3d_TOS_FRAGMENT));
2390 EOL"const vec4 THE_POW_UP = vec4 (2.2, 2.2, 2.2, 1.0);"
2391 EOL"const vec4 THE_POW_DOWN = 1.0 / vec4 (2.2, 2.2, 2.2, 1.0);"
2395 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2396 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2397 EOL" aColorL = pow (aColorL, THE_POW_UP);" // normalize
2398 EOL" aColorR = pow (aColorR, THE_POW_UP);"
2399 EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;"
2400 EOL" occSetFragColor (pow (aColor, THE_POW_DOWN));"
2404 case Graphic3d_StereoMode_RowInterlaced:
2406 aName = "row-interlaced";
2410 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2411 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2412 EOL" if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)"
2414 EOL" occSetFragColor (aColorL);"
2418 EOL" occSetFragColor (aColorR);"
2423 case Graphic3d_StereoMode_ColumnInterlaced:
2425 aName = "column-interlaced";
2429 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2430 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2431 EOL" if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)"
2433 EOL" occSetFragColor (aColorL);"
2437 EOL" occSetFragColor (aColorR);"
2442 case Graphic3d_StereoMode_ChessBoard:
2444 aName = "chessboard";
2448 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2449 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2450 EOL" bool isEvenX = int(mod(floor(gl_FragCoord.x - 1023.5), 2.0)) != 1;"
2451 EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y - 1023.5), 2.0)) == 1;"
2452 EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))"
2454 EOL" occSetFragColor (aColorL);"
2458 EOL" occSetFragColor (aColorR);"
2463 case Graphic3d_StereoMode_SideBySide:
2465 aName = "sidebyside";
2469 EOL" vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);"
2470 EOL" if (TexCoord.x > 0.5)"
2472 EOL" aTexCoord.x -= 1.0;"
2474 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
2475 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
2476 EOL" if (TexCoord.x <= 0.5)"
2478 EOL" occSetFragColor (aColorL);"
2482 EOL" occSetFragColor (aColorR);"
2487 case Graphic3d_StereoMode_OverUnder:
2489 aName = "overunder";
2493 EOL" vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);"
2494 EOL" if (TexCoord.y > 0.5)"
2496 EOL" aTexCoord.y -= 1.0;"
2498 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
2499 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
2500 EOL" if (TexCoord.y <= 0.5)"
2502 EOL" occSetFragColor (aColorL);"
2506 EOL" occSetFragColor (aColorR);"
2511 case Graphic3d_StereoMode_QuadBuffer:
2512 case Graphic3d_StereoMode_SoftPageFlip:
2515 /*const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[Graphic3d_StereoMode_QuadBuffer];
2516 if (!aProgram.IsNull())
2518 return aProgram->IsValid();
2523 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2524 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2525 EOL" aColorL.b = 0.0;"
2526 EOL" aColorL.g = 0.0;"
2527 EOL" aColorR.r = 0.0;"
2528 EOL" occSetFragColor (aColorL + aColorR);"
2534 defaultGlslVersion (aProgramSrc, aName, 0);
2535 aProgramSrc->SetNbLightsMax (0);
2536 aProgramSrc->SetNbClipPlanesMax (0);
2537 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
2538 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
2539 TCollection_AsciiString aKey;
2540 if (!Create (aProgramSrc, aKey, theProgram))
2542 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2543 return Standard_False;
2546 myContext->BindProgram (theProgram);
2547 theProgram->SetSampler (myContext, "uLeftSampler", Graphic3d_TextureUnit_0);
2548 theProgram->SetSampler (myContext, "uRightSampler", Graphic3d_TextureUnit_1);
2549 myContext->BindProgram (NULL);
2550 return Standard_True;
2553 // =======================================================================
2554 // function : prepareStdProgramBoundBox
2556 // =======================================================================
2557 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramBoundBox()
2559 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2561 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2562 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 occBBoxCenter", Graphic3d_TOS_VERTEX));
2563 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 occBBoxSize", Graphic3d_TOS_VERTEX));
2565 TCollection_AsciiString aSrcVert =
2568 EOL" vec4 aCenter = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);"
2569 EOL" vec4 aPos = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);"
2570 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * aPos;"
2573 TCollection_AsciiString aSrcFrag =
2576 EOL" occSetFragColor (occColor);"
2579 defaultGlslVersion (aProgramSrc, "bndbox", 0);
2580 aProgramSrc->SetNbLightsMax (0);
2581 aProgramSrc->SetNbClipPlanesMax (0);
2582 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
2583 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
2584 TCollection_AsciiString aKey;
2585 if (!Create (aProgramSrc, aKey, myBoundBoxProgram))
2587 myBoundBoxProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2588 return Standard_False;
2591 const OpenGl_Vec4 aMin (-0.5f, -0.5f, -0.5f, 1.0f);
2592 const OpenGl_Vec4 anAxisShifts[3] =
2594 OpenGl_Vec4 (1.0f, 0.0f, 0.0f, 0.0f),
2595 OpenGl_Vec4 (0.0f, 1.0f, 0.0f, 0.0f),
2596 OpenGl_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)
2599 const OpenGl_Vec4 aLookup1 (0.0f, 1.0f, 0.0f, 1.0f);
2600 const OpenGl_Vec4 aLookup2 (0.0f, 0.0f, 1.0f, 1.0f);
2601 OpenGl_Vec4 aLinesVertices[24];
2602 for (int anAxis = 0, aVertex = 0; anAxis < 3; ++anAxis)
2604 for (int aCompIter = 0; aCompIter < 4; ++aCompIter)
2606 aLinesVertices[aVertex++] = aMin
2607 + anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter]
2608 + anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter];
2610 aLinesVertices[aVertex++] = aMin
2611 + anAxisShifts[anAxis]
2612 + anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter]
2613 + anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter];
2616 if (myContext->ToUseVbo())
2618 myBoundBoxVertBuffer = new OpenGl_VertexBuffer();
2619 if (myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData()))
2621 myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer);
2622 return Standard_True;
2625 myBoundBoxVertBuffer = new OpenGl_VertexBufferCompat();
2626 myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData());
2627 myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer);
2628 return Standard_True;
2631 // =======================================================================
2632 // function : bindProgramWithState
2634 // =======================================================================
2635 Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram)
2637 const Standard_Boolean isBound = myContext->BindProgram (theProgram);
2639 && !theProgram.IsNull())
2641 theProgram->ApplyVariables (myContext);
2643 PushState (theProgram);