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_Aspects.hxx>
20 #include <OpenGl_ClippingIterator.hxx>
21 #include <OpenGl_Context.hxx>
22 #include <OpenGl_ShaderManager.hxx>
23 #include <OpenGl_ShaderProgram.hxx>
24 #include <OpenGl_VertexBufferCompat.hxx>
25 #include <OpenGl_PointSprite.hxx>
26 #include <OpenGl_Workspace.hxx>
28 #include <TCollection_ExtendedString.hxx>
30 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager,Standard_Transient)
34 //! Number specifying maximum number of light sources to prepare a GLSL program with unrolled loop.
35 const Standard_Integer THE_NB_UNROLLED_LIGHTS_MAX = 32;
37 //! Compute the size of array storing holding light sources definition.
38 static Standard_Integer roundUpMaxLightSources (Standard_Integer theNbLights)
40 Standard_Integer aMaxLimit = THE_NB_UNROLLED_LIGHTS_MAX;
41 for (; aMaxLimit < theNbLights; aMaxLimit *= 2) {}
47 //! Compute TexCoord value in Vertex Shader
48 const char THE_VARY_TexCoord_Trsf[] =
49 EOL" float aRotSin = occTextureTrsf_RotationSin();"
50 EOL" float aRotCos = occTextureTrsf_RotationCos();"
51 EOL" vec2 aTex2 = (occTexCoord.xy + occTextureTrsf_Translation()) * occTextureTrsf_Scale();"
52 EOL" vec2 aCopy = aTex2;"
53 EOL" aTex2.x = aCopy.x * aRotCos - aCopy.y * aRotSin;"
54 EOL" aTex2.y = aCopy.x * aRotSin + aCopy.y * aRotCos;"
55 EOL" TexCoord = vec4(aTex2, occTexCoord.zw);";
57 //! Auxiliary function to flip gl_PointCoord vertically
58 #define THE_VEC2_glPointCoord "vec2 (gl_PointCoord.x, 1.0 - gl_PointCoord.y)"
60 //! Auxiliary function to transform normal
61 const char THE_FUNC_transformNormal[] =
62 EOL"vec3 transformNormal (in vec3 theNormal)"
64 EOL" vec4 aResult = occWorldViewMatrixInverseTranspose"
65 EOL" * occModelWorldMatrixInverseTranspose"
66 EOL" * vec4 (theNormal, 0.0);"
67 EOL" return normalize (aResult.xyz);"
70 //! Global shader variable for color definition with lighting enabled.
71 const char THE_FUNC_lightDef[] =
72 EOL"vec3 Ambient;" //!< Ambient contribution of light sources
73 EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources
74 EOL"vec3 Specular;"; //!< Specular contribution of light sources
76 //! Function computes contribution of isotropic point light source
77 const char THE_FUNC_pointLight[] =
78 EOL"void pointLight (in int theId,"
79 EOL" in vec3 theNormal,"
80 EOL" in vec3 theView,"
81 EOL" in vec3 thePoint,"
82 EOL" in bool theIsFront)"
84 EOL" vec3 aLight = occLight_Position (theId).xyz;"
85 EOL" if (occLight_IsHeadlight (theId) == 0)"
87 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));"
89 EOL" aLight -= thePoint;"
91 EOL" float aDist = length (aLight);"
92 EOL" aLight = aLight * (1.0 / aDist);"
94 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
95 EOL" + occLight_LinearAttenuation (theId) * aDist);"
97 EOL" vec3 aHalf = normalize (aLight + theView);"
99 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
100 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
101 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
103 EOL" float aSpecl = 0.0;"
104 EOL" if (aNdotL > 0.0)"
106 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
109 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
110 EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
113 //! Function computes contribution of spotlight source
114 const char THE_FUNC_spotLight[] =
115 EOL"void spotLight (in int theId,"
116 EOL" in vec3 theNormal,"
117 EOL" in vec3 theView,"
118 EOL" in vec3 thePoint,"
119 EOL" in bool theIsFront)"
121 EOL" vec3 aLight = occLight_Position (theId).xyz;"
122 EOL" vec3 aSpotDir = occLight_SpotDirection (theId).xyz;"
123 EOL" if (occLight_IsHeadlight (theId) == 0)"
125 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));"
126 EOL" aSpotDir = vec3 (occWorldViewMatrix * vec4 (aSpotDir, 0.0));"
128 EOL" aLight -= thePoint;"
130 EOL" float aDist = length (aLight);"
131 EOL" aLight = aLight * (1.0 / aDist);"
133 EOL" aSpotDir = normalize (aSpotDir);"
135 EOL" float aCosA = dot (aSpotDir, -aLight);"
136 EOL" if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
141 EOL" float anExponent = occLight_SpotExponent (theId);"
142 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
143 EOL" + occLight_LinearAttenuation (theId) * aDist);"
144 EOL" if (anExponent > 0.0)"
146 EOL" anAtten *= pow (aCosA, anExponent * 128.0);"
149 EOL" vec3 aHalf = normalize (aLight + theView);"
151 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
152 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
153 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
155 EOL" float aSpecl = 0.0;"
156 EOL" if (aNdotL > 0.0)"
158 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
161 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
162 EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
165 //! Function computes contribution of directional light source
166 const char THE_FUNC_directionalLight[] =
167 EOL"void directionalLight (in int theId,"
168 EOL" in vec3 theNormal,"
169 EOL" in vec3 theView,"
170 EOL" in bool theIsFront)"
172 EOL" vec3 aLight = normalize (occLight_Position (theId).xyz);"
173 EOL" if (occLight_IsHeadlight (theId) == 0)"
175 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));"
178 EOL" vec3 aHalf = normalize (aLight + theView);"
180 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
181 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
182 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
184 EOL" float aSpecl = 0.0;"
185 EOL" if (aNdotL > 0.0)"
187 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
190 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL;"
191 EOL" Specular += occLight_Specular (theId).rgb * aSpecl;"
194 //! The same as THE_FUNC_directionalLight but for the light with zero index
195 //! (avoids limitations on some mobile devices).
196 const char THE_FUNC_directionalLightFirst[] =
197 EOL"void directionalLightFirst (in vec3 theNormal,"
198 EOL" in vec3 theView,"
199 EOL" in bool theIsFront)"
201 EOL" vec3 aLight = normalize (occLightSources[1].xyz);"
202 EOL" if (occLight_IsHeadlight (0) == 0)"
204 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));"
207 EOL" vec3 aHalf = normalize (aLight + theView);"
209 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
210 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
211 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
213 EOL" float aSpecl = 0.0;"
214 EOL" if (aNdotL > 0.0)"
216 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
219 EOL" Diffuse += occLightSources[0].rgb * aNdotL;"
220 EOL" Specular += occLightSources[0].rgb * aSpecl;"
223 //! Process clipping planes in Fragment Shader.
224 //! Should be added at the beginning of the main() function.
225 const char THE_FRAG_CLIP_PLANES_N[] =
226 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)"
228 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
229 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)"
235 //! Process chains of clipping planes in Fragment Shader.
236 const char THE_FRAG_CLIP_CHAINS_N[] =
237 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount;)"
239 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
240 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)"
242 EOL" if (occClipPlaneChains[aPlaneIter] == 1)"
246 EOL" aPlaneIter += 1;"
250 EOL" aPlaneIter += occClipPlaneChains[aPlaneIter];"
254 //! Process 1 clipping plane in Fragment Shader.
255 const char THE_FRAG_CLIP_PLANES_1[] =
256 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
257 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0)"
262 //! Process 2 clipping planes in Fragment Shader.
263 const char THE_FRAG_CLIP_PLANES_2[] =
264 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
265 EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];"
266 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0"
267 EOL" || dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)"
272 //! Process a chain of 2 clipping planes in Fragment Shader (3/4 section).
273 const char THE_FRAG_CLIP_CHAINS_2[] =
274 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
275 EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];"
276 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0"
277 EOL" && dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)"
282 //! Modify color for Wireframe presentation.
283 const char THE_FRAG_WIREFRAME_COLOR[] =
284 EOL"vec4 getFinalColor(void)"
286 EOL" float aDistance = min (min (EdgeDistance[0], EdgeDistance[1]), EdgeDistance[2]);"
287 EOL" bool isHollow = occWireframeColor.a < 0.0;"
288 EOL" float aMixVal = smoothstep (occLineWidth - occLineFeather * 0.5, occLineWidth + occLineFeather * 0.5, aDistance);"
289 EOL" vec4 aMixColor = isHollow"
290 EOL" ? vec4 (getColor().rgb, 1.0 - aMixVal)" // edges only (of interior color)
291 EOL" : mix (occWireframeColor, getColor(), aMixVal);" // interior + edges
292 EOL" return aMixColor;"
295 //! Compute gl_Position vertex shader output.
296 const char THE_VERT_gl_Position[] =
297 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;";
299 //! Displace gl_Position alongside vertex normal for outline rendering.
300 //! This code adds silhouette only for smooth surfaces of closed primitive, and produces visual artifacts on sharp edges.
301 const char THE_VERT_gl_Position_OUTLINE[] =
302 EOL" float anOutlineDisp = occOrthoScale > 0.0 ? occOrthoScale : gl_Position.w;"
303 EOL" vec4 anOutlinePos = occVertex + vec4 (occNormal * (occSilhouetteThickness * anOutlineDisp), 0.0);"
304 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * anOutlinePos;";
306 #if !defined(GL_ES_VERSION_2_0)
308 static const GLfloat THE_DEFAULT_AMBIENT[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
309 static const GLfloat THE_DEFAULT_SPOT_DIR[3] = { 0.0f, 0.0f, -1.0f };
310 static const GLfloat THE_DEFAULT_SPOT_EXPONENT = 0.0f;
311 static const GLfloat THE_DEFAULT_SPOT_CUTOFF = 180.0f;
313 //! Bind FFP light source.
314 static void bindLight (const Graphic3d_CLight& theLight,
315 const GLenum theLightGlId,
316 const OpenGl_Mat4& theModelView,
317 OpenGl_Context* theCtx)
319 // the light is a headlight?
320 if (theLight.IsHeadlight())
322 theCtx->core11->glMatrixMode (GL_MODELVIEW);
323 theCtx->core11->glLoadIdentity();
327 const Graphic3d_Vec4& aLightColor = theLight.PackedColor();
328 switch (theLight.Type())
330 case Graphic3d_TOLS_AMBIENT : break; // handled by separate if-clause at beginning of method
331 case Graphic3d_TOLS_DIRECTIONAL:
333 // if the last parameter of GL_POSITION, is zero, the corresponding light source is a Directional one
334 const OpenGl_Vec4 anInfDir = -theLight.PackedDirection();
336 // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE.
337 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
338 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
339 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
340 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, anInfDir.GetData());
341 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR);
342 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT);
343 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF);
346 case Graphic3d_TOLS_POSITIONAL:
348 // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE
349 const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position().X()), static_cast<float>(theLight.Position().Y()), static_cast<float>(theLight.Position().Z()), 1.0f);
350 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
351 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
352 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
353 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, aPosition.GetData());
354 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR);
355 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT);
356 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF);
357 theCtx->core11->glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation());
358 theCtx->core11->glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation());
359 theCtx->core11->glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0);
362 case Graphic3d_TOLS_SPOT:
364 const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position().X()), static_cast<float>(theLight.Position().Y()), static_cast<float>(theLight.Position().Z()), 1.0f);
365 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
366 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
367 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
368 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, aPosition.GetData());
369 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, theLight.PackedDirection().GetData());
370 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, theLight.Concentration() * 128.0f);
371 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, (theLight.Angle() * 180.0f) / GLfloat(M_PI));
372 theCtx->core11->glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation());
373 theCtx->core11->glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation());
374 theCtx->core11->glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f);
379 // restore matrix in case of headlight
380 if (theLight.IsHeadlight())
382 theCtx->core11->glLoadMatrixf (theModelView.GetData());
385 glEnable (theLightGlId);
389 //! Generate map key for light sources configuration.
390 static TCollection_AsciiString genLightKey (const Handle(Graphic3d_LightSet)& theLights)
392 if (theLights->NbEnabled() <= THE_NB_UNROLLED_LIGHTS_MAX)
394 return TCollection_AsciiString ("l_") + theLights->KeyEnabledLong();
397 const Standard_Integer aMaxLimit = roundUpMaxLightSources (theLights->NbEnabled());
398 return TCollection_AsciiString ("l_") + theLights->KeyEnabledShort() + aMaxLimit;
402 // =======================================================================
403 // function : OpenGl_ShaderManager
404 // purpose : Creates new empty shader manager
405 // =======================================================================
406 OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
407 : myFfpProgram (new OpenGl_ShaderProgramFFP()),
408 myShadingModel (Graphic3d_TOSM_VERTEX),
409 myUnlitPrograms (new OpenGl_SetOfPrograms()),
410 myContext (theContext),
411 mySRgbState (theContext->ToRenderSRGB()),
412 myHasLocalOrigin (Standard_False),
418 // =======================================================================
419 // function : ~OpenGl_ShaderManager
420 // purpose : Releases resources of shader manager
421 // =======================================================================
422 OpenGl_ShaderManager::~OpenGl_ShaderManager()
424 myProgramList.Clear();
427 // =======================================================================
430 // =======================================================================
431 void OpenGl_ShaderManager::clear()
433 myProgramList.Clear();
434 myLightPrograms.Nullify();
435 myUnlitPrograms = new OpenGl_SetOfPrograms();
436 myOutlinePrograms.Nullify();
437 myMapOfLightPrograms.Clear();
438 myFontProgram.Nullify();
439 myBlitPrograms[0].Init (Handle(OpenGl_ShaderProgram)());
440 myBlitPrograms[1].Init (Handle(OpenGl_ShaderProgram)());
441 myBoundBoxProgram.Nullify();
442 myBoundBoxVertBuffer.Nullify();
443 for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter)
445 myStereoPrograms[aModeIter].Nullify();
447 switchLightPrograms();
450 // =======================================================================
452 // purpose : Creates new shader program
453 // =======================================================================
454 Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
455 TCollection_AsciiString& theShareKey,
456 Handle(OpenGl_ShaderProgram)& theProgram)
458 theProgram.Nullify();
459 if (theProxy.IsNull())
461 return Standard_False;
464 theShareKey = theProxy->GetId();
465 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
467 if (theProgram->Share())
469 myProgramList.Append (theProgram);
471 return Standard_True;
474 theProgram = new OpenGl_ShaderProgram (theProxy);
475 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
477 theProgram->Release (myContext);
479 theProgram.Nullify();
480 return Standard_False;
483 myProgramList.Append (theProgram);
484 myContext->ShareResource (theShareKey, theProgram);
485 return Standard_True;
488 // =======================================================================
489 // function : Unregister
490 // purpose : Removes specified shader program from the manager
491 // =======================================================================
492 void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
493 Handle(OpenGl_ShaderProgram)& theProgram)
495 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
497 if (anIt.Value() == theProgram)
499 if (!theProgram->UnShare())
502 theProgram.Nullify();
506 myProgramList.Remove (anIt);
511 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
514 myContext->DelayedRelease (theProgram);
515 theProgram.Nullify();
519 theProgram.Nullify();
520 myContext->ReleaseResource (anID, Standard_True);
524 // =======================================================================
525 // function : ShaderPrograms
526 // purpose : Returns list of registered shader programs
527 // =======================================================================
528 const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
530 return myProgramList;
533 // =======================================================================
535 // purpose : Returns true if no program objects are attached
536 // =======================================================================
537 Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
539 return myProgramList.IsEmpty();
542 // =======================================================================
543 // function : switchLightPrograms
545 // =======================================================================
546 void OpenGl_ShaderManager::switchLightPrograms()
548 const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources();
549 if (aLights.IsNull())
551 if (!myMapOfLightPrograms.Find ("unlit", myLightPrograms))
553 myLightPrograms = new OpenGl_SetOfShaderPrograms (myUnlitPrograms);
554 myMapOfLightPrograms.Bind ("unlit", myLightPrograms);
559 const TCollection_AsciiString aKey = genLightKey (aLights);
560 if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
562 myLightPrograms = new OpenGl_SetOfShaderPrograms();
563 myMapOfLightPrograms.Bind (aKey, myLightPrograms);
567 // =======================================================================
568 // function : UpdateSRgbState
570 // =======================================================================
571 void OpenGl_ShaderManager::UpdateSRgbState()
573 if (mySRgbState == myContext->ToRenderSRGB())
578 mySRgbState = myContext->ToRenderSRGB();
580 // special cases - GLSL programs dealing with sRGB/linearRGB internally
581 myStereoPrograms[Graphic3d_StereoMode_Anaglyph].Nullify();
584 // =======================================================================
585 // function : UpdateLightSourceStateTo
586 // purpose : Updates state of OCCT light sources
587 // =======================================================================
588 void OpenGl_ShaderManager::UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights)
590 myLightSourceState.Set (theLights);
591 myLightSourceState.Update();
592 switchLightPrograms();
595 // =======================================================================
596 // function : UpdateLightSourceState
598 // =======================================================================
599 void OpenGl_ShaderManager::UpdateLightSourceState()
601 myLightSourceState.Update();
604 // =======================================================================
605 // function : SetShadingModel
607 // =======================================================================
608 void OpenGl_ShaderManager::SetShadingModel (const Graphic3d_TypeOfShadingModel theModel)
610 if (theModel == Graphic3d_TOSM_DEFAULT)
612 throw Standard_ProgramError ("OpenGl_ShaderManager::SetShadingModel() - attempt to set invalid Shading Model!");
615 myShadingModel = theModel;
616 switchLightPrograms();
619 // =======================================================================
620 // function : SetProjectionState
621 // purpose : Sets new state of OCCT projection transform
622 // =======================================================================
623 void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix)
625 myProjectionState.Set (theProjectionMatrix);
626 myProjectionState.Update();
629 // =======================================================================
630 // function : SetModelWorldState
631 // purpose : Sets new state of OCCT model-world transform
632 // =======================================================================
633 void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix)
635 myModelWorldState.Set (theModelWorldMatrix);
636 myModelWorldState.Update();
639 // =======================================================================
640 // function : SetWorldViewState
641 // purpose : Sets new state of OCCT world-view transform
642 // =======================================================================
643 void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix)
645 myWorldViewState.Set (theWorldViewMatrix);
646 myWorldViewState.Update();
649 // =======================================================================
650 // function : pushLightSourceState
652 // =======================================================================
653 void OpenGl_ShaderManager::pushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
655 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
656 if (theProgram == myFfpProgram)
658 #if !defined(GL_ES_VERSION_2_0)
659 if (myContext->core11 == NULL)
664 GLenum aLightGlId = GL_LIGHT0;
665 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
666 for (Graphic3d_LightSet::Iterator aLightIt (myLightSourceState.LightSources(), Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
667 aLightIt.More(); aLightIt.Next())
669 if (aLightGlId > GL_LIGHT7) // only 8 lights in FFP...
671 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
672 "Warning: light sources limit (8) has been exceeded within Fixed-function pipeline.");
676 bindLight (*aLightIt.Value(), aLightGlId, aModelView, myContext);
680 // apply accumulated ambient color
681 const Graphic3d_Vec4 anAmbient = !myLightSourceState.LightSources().IsNull()
682 ? myLightSourceState.LightSources()->AmbientColor()
683 : Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 1.0f);
684 myContext->core11->glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbient.GetData());
686 // GL_LIGHTING is managed by drawers to switch between shaded / no lighting output,
687 // therefore managing the state here does not have any effect - do it just for consistency.
688 if (aLightGlId != GL_LIGHT0)
690 ::glEnable (GL_LIGHTING);
694 ::glDisable (GL_LIGHTING);
696 // switch off unused lights
697 for (; aLightGlId <= GL_LIGHT7; ++aLightGlId)
699 ::glDisable (aLightGlId);
705 const Standard_Integer aNbLightsMax = theProgram->NbLightsMax();
706 const GLint anAmbientLoc = theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT);
707 if (aNbLightsMax == 0
708 && anAmbientLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
713 if (myLightTypeArray.Size() < aNbLightsMax)
715 myLightTypeArray .Resize (0, aNbLightsMax - 1, false);
716 myLightParamsArray.Resize (0, aNbLightsMax - 1, false);
718 for (Standard_Integer aLightIt = 0; aLightIt < aNbLightsMax; ++aLightIt)
720 myLightTypeArray.ChangeValue (aLightIt).Type = -1;
723 if (myLightSourceState.LightSources().IsNull()
724 || myLightSourceState.LightSources()->IsEmpty())
726 theProgram->SetUniform (myContext,
727 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
729 theProgram->SetUniform (myContext,
731 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
732 theProgram->SetUniform (myContext,
733 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
734 aNbLightsMax * OpenGl_ShaderLightType::NbOfVec2i(),
735 myLightTypeArray.First().Packed());
739 Standard_Integer aLightsNb = 0;
740 for (Graphic3d_LightSet::Iterator anIter (myLightSourceState.LightSources(), Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
741 anIter.More(); anIter.Next())
743 const Graphic3d_CLight& aLight = *anIter.Value();
744 if (aLightsNb >= aNbLightsMax)
746 if (aNbLightsMax != 0)
748 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
749 TCollection_AsciiString("Warning: light sources limit (") + aNbLightsMax + ") has been exceeded.");
754 OpenGl_ShaderLightType& aLightType = myLightTypeArray.ChangeValue (aLightsNb);
755 OpenGl_ShaderLightParameters& aLightParams = myLightParamsArray.ChangeValue (aLightsNb);
756 if (!aLight.IsEnabled()) // has no affect with Graphic3d_LightSet::IterationFilter_ExcludeDisabled - here just for consistency
758 // 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
759 aLightType.Type = -1; // Graphic3d_TOLS_AMBIENT can be used instead
760 aLightType.IsHeadlight = false;
761 aLightParams.Color = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f);
766 // ignoring OpenGl_Context::ToRenderSRGB() for light colors,
767 // as non-absolute colors for lights are rare and require tuning anyway
768 aLightType.Type = aLight.Type();
769 aLightType.IsHeadlight = aLight.IsHeadlight();
770 aLightParams.Color = aLight.PackedColor();
771 if (aLight.Type() == Graphic3d_TOLS_DIRECTIONAL)
773 aLightParams.Position = -aLight.PackedDirection();
775 else if (!aLight.IsHeadlight())
777 aLightParams.Position.x() = static_cast<float>(aLight.Position().X() - myLocalOrigin.X());
778 aLightParams.Position.y() = static_cast<float>(aLight.Position().Y() - myLocalOrigin.Y());
779 aLightParams.Position.z() = static_cast<float>(aLight.Position().Z() - myLocalOrigin.Z());
780 aLightParams.Position.w() = 1.0f;
784 aLightParams.Position.x() = static_cast<float>(aLight.Position().X());
785 aLightParams.Position.y() = static_cast<float>(aLight.Position().Y());
786 aLightParams.Position.z() = static_cast<float>(aLight.Position().Z());
787 aLightParams.Position.w() = 1.0f;
790 if (aLight.Type() == Graphic3d_TOLS_SPOT)
792 aLightParams.Direction = aLight.PackedDirection();
794 aLightParams.Parameters = aLight.PackedParams();
798 const Graphic3d_Vec4& anAmbient = myLightSourceState.LightSources()->AmbientColor();
799 theProgram->SetUniform (myContext,
800 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
802 theProgram->SetUniform (myContext,
805 theProgram->SetUniform (myContext,
806 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
807 aNbLightsMax * OpenGl_ShaderLightType::NbOfVec2i(),
808 myLightTypeArray.First().Packed());
811 theProgram->SetUniform (myContext,
812 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
813 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
814 myLightParamsArray.First().Packed());
818 // =======================================================================
819 // function : pushProjectionState
821 // =======================================================================
822 void OpenGl_ShaderManager::pushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
824 theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
825 if (theProgram == myFfpProgram)
827 #if !defined(GL_ES_VERSION_2_0)
828 if (myContext->core11 != NULL)
830 myContext->core11->glMatrixMode (GL_PROJECTION);
831 myContext->core11->glLoadMatrixf (myProjectionState.ProjectionMatrix());
837 theProgram->SetUniform (myContext,
838 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
839 myProjectionState.ProjectionMatrix());
841 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
842 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
844 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
847 theProgram->SetUniform (myContext,
848 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
849 myProjectionState.ProjectionMatrix(), true);
851 aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
852 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
854 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
858 // =======================================================================
859 // function : pushModelWorldState
861 // =======================================================================
862 void OpenGl_ShaderManager::pushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
864 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
865 if (theProgram == myFfpProgram)
867 #if !defined(GL_ES_VERSION_2_0)
868 if (myContext->core11 != NULL)
870 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
871 myContext->core11->glMatrixMode (GL_MODELVIEW);
872 myContext->core11->glLoadMatrixf (aModelView.GetData());
873 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
879 theProgram->SetUniform (myContext,
880 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
881 myModelWorldState.ModelWorldMatrix());
883 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
884 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
886 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
889 theProgram->SetUniform (myContext,
890 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
891 myModelWorldState.ModelWorldMatrix(), true);
893 aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
894 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
896 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
900 // =======================================================================
901 // function : pushWorldViewState
903 // =======================================================================
904 void OpenGl_ShaderManager::pushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
906 if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
911 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
912 if (theProgram == myFfpProgram)
914 #if !defined(GL_ES_VERSION_2_0)
915 if (myContext->core11 != NULL)
917 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
918 myContext->core11->glMatrixMode (GL_MODELVIEW);
919 myContext->core11->glLoadMatrixf (aModelView.GetData());
920 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
926 theProgram->SetUniform (myContext,
927 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
928 myWorldViewState.WorldViewMatrix());
930 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
931 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
933 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
936 theProgram->SetUniform (myContext,
937 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
938 myWorldViewState.WorldViewMatrix(), true);
940 aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
941 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
943 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
947 // =======================================================================
948 // function : UpdateClippingState
949 // purpose : Updates state of OCCT clipping planes
950 // =======================================================================
951 void OpenGl_ShaderManager::UpdateClippingState()
953 myClippingState.Update();
956 // =======================================================================
957 // function : RevertClippingState
958 // purpose : Reverts state of OCCT clipping planes
959 // =======================================================================
960 void OpenGl_ShaderManager::RevertClippingState()
962 myClippingState.Revert();
965 // =======================================================================
966 // function : pushClippingState
968 // =======================================================================
969 void OpenGl_ShaderManager::pushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
971 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
972 if (theProgram == myFfpProgram)
974 #if !defined(GL_ES_VERSION_2_0)
975 if (myContext->core11 == NULL)
980 const Standard_Integer aNbMaxPlanes = myContext->MaxClipPlanes();
981 if (myClipPlaneArrayFfp.Size() < aNbMaxPlanes)
983 myClipPlaneArrayFfp.Resize (0, aNbMaxPlanes - 1, false);
986 Standard_Integer aPlaneId = 0;
987 Standard_Boolean toRestoreModelView = Standard_False;
988 const Handle(Graphic3d_ClipPlane)& aCappedChain = myContext->Clipping().CappedChain();
989 for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
991 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
992 if (aPlaneIter.IsDisabled()
994 || (aPlane == aCappedChain
995 && myContext->Clipping().IsCappingEnableAllExcept()))
999 else if (aPlaneId >= aNbMaxPlanes)
1001 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
1002 TCollection_ExtendedString("Warning: clipping planes limit (") + aNbMaxPlanes + ") has been exceeded.");
1006 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
1007 OpenGl_Vec4d& aPlaneEq = myClipPlaneArrayFfp.ChangeValue (aPlaneId);
1008 aPlaneEq.x() = anEquation.x();
1009 aPlaneEq.y() = anEquation.y();
1010 aPlaneEq.z() = anEquation.z();
1011 aPlaneEq.w() = anEquation.w();
1012 if (myHasLocalOrigin)
1014 const gp_XYZ aPos = aPlane->ToPlane().Position().Location().XYZ() - myLocalOrigin;
1015 const Standard_Real aD = -(anEquation.x() * aPos.X() + anEquation.y() * aPos.Y() + anEquation.z() * aPos.Z());
1019 const GLenum anFfpPlaneID = GL_CLIP_PLANE0 + aPlaneId;
1020 if (anFfpPlaneID == GL_CLIP_PLANE0)
1022 // set either identity or pure view matrix
1023 toRestoreModelView = Standard_True;
1024 myContext->core11->glMatrixMode (GL_MODELVIEW);
1025 myContext->core11->glLoadMatrixf (myWorldViewState.WorldViewMatrix().GetData());
1028 ::glEnable (anFfpPlaneID);
1029 myContext->core11->glClipPlane (anFfpPlaneID, aPlaneEq);
1034 // switch off unused lights
1035 for (; aPlaneId < aNbMaxPlanes; ++aPlaneId)
1037 ::glDisable (GL_CLIP_PLANE0 + aPlaneId);
1040 // restore combined model-view matrix
1041 if (toRestoreModelView)
1043 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
1044 myContext->core11->glLoadMatrixf (aModelView.GetData());
1050 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
1051 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION)
1056 const Standard_Integer aNbClipPlanesMax = theProgram->NbClipPlanesMax();
1057 const Standard_Integer aNbPlanes = Min (myContext->Clipping().NbClippingOrCappingOn(), aNbClipPlanesMax);
1060 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), 0);
1064 if (myClipPlaneArray.Size() < aNbClipPlanesMax)
1066 myClipPlaneArray.Resize (0, aNbClipPlanesMax - 1, false);
1067 myClipChainArray.Resize (0, aNbClipPlanesMax - 1, false);
1070 Standard_Integer aPlaneId = 0;
1071 const Handle(Graphic3d_ClipPlane)& aCappedChain = myContext->Clipping().CappedChain();
1072 for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
1074 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
1075 if (aPlaneIter.IsDisabled())
1080 if (myContext->Clipping().IsCappingDisableAllExcept())
1082 // enable only specific (sub) plane
1083 if (aPlane != aCappedChain)
1088 Standard_Integer aSubPlaneIndex = 1;
1089 for (const Graphic3d_ClipPlane* aSubPlaneIter = aCappedChain.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex)
1091 if (aSubPlaneIndex == myContext->Clipping().CappedSubPlane())
1093 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->GetEquation(), 1);
1099 else if (aPlane == aCappedChain) // && myContext->Clipping().IsCappingEnableAllExcept()
1101 // enable sub-planes within processed Chain as reversed and ORed, excluding filtered plane
1102 if (aPlaneId + aPlane->NbChainNextPlanes() - 1 > aNbClipPlanesMax)
1104 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
1105 TCollection_AsciiString("Error: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded.");
1109 Standard_Integer aSubPlaneIndex = 1;
1110 for (const Graphic3d_ClipPlane* aSubPlaneIter = aPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex)
1112 if (aSubPlaneIndex != -myContext->Clipping().CappedSubPlane())
1114 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->ReversedEquation(), 1);
1121 if (aPlaneId + aPlane->NbChainNextPlanes() > aNbClipPlanesMax)
1123 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
1124 TCollection_AsciiString("Error: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded.");
1127 for (const Graphic3d_ClipPlane* aSubPlaneIter = aPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get())
1129 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->GetEquation(), aSubPlaneIter->NbChainNextPlanes());
1134 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), aPlaneId);
1135 theProgram->SetUniform (myContext, aLocEquations, aNbClipPlanesMax, &myClipPlaneArray.First());
1136 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_CHAINS), aNbClipPlanesMax, &myClipChainArray.First());
1139 // =======================================================================
1140 // function : pushMaterialState
1142 // =======================================================================
1143 void OpenGl_ShaderManager::pushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1145 const OpenGl_Material& aFrontMat = myMaterialState.FrontMaterial();
1146 const OpenGl_Material& aBackMat = myMaterialState.BackMaterial();
1147 theProgram->UpdateState (OpenGl_MATERIAL_STATE, myMaterialState.Index());
1148 if (theProgram == myFfpProgram)
1150 #if !defined(GL_ES_VERSION_2_0)
1151 if (myContext->core11 == NULL)
1156 if (myMaterialState.AlphaCutoff() < ShortRealLast())
1158 glAlphaFunc (GL_GEQUAL, myMaterialState.AlphaCutoff());
1159 glEnable (GL_ALPHA_TEST);
1163 glDisable (GL_ALPHA_TEST);
1166 const GLenum aFrontFace = myMaterialState.ToDistinguish() ? GL_FRONT : GL_FRONT_AND_BACK;
1167 myContext->core11->glMaterialfv(aFrontFace, GL_AMBIENT, aFrontMat.Ambient.GetData());
1168 myContext->core11->glMaterialfv(aFrontFace, GL_DIFFUSE, aFrontMat.Diffuse.GetData());
1169 myContext->core11->glMaterialfv(aFrontFace, GL_SPECULAR, aFrontMat.Specular.GetData());
1170 myContext->core11->glMaterialfv(aFrontFace, GL_EMISSION, aFrontMat.Emission.GetData());
1171 myContext->core11->glMaterialf (aFrontFace, GL_SHININESS, aFrontMat.Shine());
1172 if (myMaterialState.ToDistinguish())
1174 myContext->core11->glMaterialfv(GL_BACK, GL_AMBIENT, aBackMat.Ambient.GetData());
1175 myContext->core11->glMaterialfv(GL_BACK, GL_DIFFUSE, aBackMat.Diffuse.GetData());
1176 myContext->core11->glMaterialfv(GL_BACK, GL_SPECULAR, aBackMat.Specular.GetData());
1177 myContext->core11->glMaterialfv(GL_BACK, GL_EMISSION, aBackMat.Emission.GetData());
1178 myContext->core11->glMaterialf (GL_BACK, GL_SHININESS, aBackMat.Shine());
1184 theProgram->SetUniform (myContext,
1185 theProgram->GetStateLocation (OpenGl_OCCT_ALPHA_CUTOFF),
1186 myMaterialState.AlphaCutoff());
1187 theProgram->SetUniform (myContext,
1188 theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
1189 myMaterialState.ToMapTexture() ? 1 : 0);
1190 theProgram->SetUniform (myContext,
1191 theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
1192 myMaterialState.ToDistinguish() ? 1 : 0);
1194 if (const OpenGl_ShaderUniformLocation aLocFront = theProgram->GetStateLocation (OpenGl_OCCT_FRONT_MATERIAL))
1196 theProgram->SetUniform (myContext, aLocFront, OpenGl_Material::NbOfVec4(),
1197 aFrontMat.Packed());
1199 if (const OpenGl_ShaderUniformLocation aLocBack = theProgram->GetStateLocation (OpenGl_OCCT_BACK_MATERIAL))
1201 theProgram->SetUniform (myContext, aLocBack, OpenGl_Material::NbOfVec4(),
1206 // =======================================================================
1207 // function : pushOitState
1209 // =======================================================================
1210 void OpenGl_ShaderManager::pushOitState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1212 const GLint aLocOutput = theProgram->GetStateLocation (OpenGl_OCCT_OIT_OUTPUT);
1213 if (aLocOutput != OpenGl_ShaderProgram::INVALID_LOCATION)
1215 theProgram->SetUniform (myContext, aLocOutput, myOitState.ToEnableWrite());
1218 const GLint aLocDepthFactor = theProgram->GetStateLocation (OpenGl_OCCT_OIT_DEPTH_FACTOR);
1219 if (aLocDepthFactor != OpenGl_ShaderProgram::INVALID_LOCATION)
1221 theProgram->SetUniform (myContext, aLocDepthFactor, myOitState.DepthFactor());
1225 // =======================================================================
1226 // function : PushInteriorState
1228 // =======================================================================
1229 void OpenGl_ShaderManager::PushInteriorState (const Handle(OpenGl_ShaderProgram)& theProgram,
1230 const Handle(Graphic3d_Aspects)& theAspect) const
1232 if (theProgram.IsNull()
1233 || !theProgram->IsValid())
1238 if (const OpenGl_ShaderUniformLocation aLocLineWidth = theProgram->GetStateLocation (OpenGl_OCCT_LINE_WIDTH))
1240 theProgram->SetUniform (myContext, aLocLineWidth, theAspect->EdgeWidth() * myContext->LineWidthScale());
1241 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCCT_LINE_FEATHER), myContext->LineFeather() * myContext->LineWidthScale());
1243 if (const OpenGl_ShaderUniformLocation aLocWireframeColor = theProgram->GetStateLocation (OpenGl_OCCT_WIREFRAME_COLOR))
1245 if (theAspect->InteriorStyle() == Aspect_IS_HOLLOW)
1247 theProgram->SetUniform (myContext, aLocWireframeColor, OpenGl_Vec4 (-1.0f, -1.0f, -1.0f, -1.0f));
1251 theProgram->SetUniform (myContext, aLocWireframeColor, myContext->Vec4FromQuantityColor (theAspect->EdgeColorRGBA()));
1254 if (const OpenGl_ShaderUniformLocation aLocQuadModeState = theProgram->GetStateLocation (OpenGl_OCCT_QUAD_MODE_STATE))
1256 theProgram->SetUniform (myContext, aLocQuadModeState, theAspect->ToSkipFirstEdge() ? 1 : 0);
1260 // =======================================================================
1261 // function : PushState
1262 // purpose : Pushes state of OCCT graphics parameters to the program
1263 // =======================================================================
1264 void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1266 const Handle(OpenGl_ShaderProgram)& aProgram = !theProgram.IsNull() ? theProgram : myFfpProgram;
1267 PushClippingState (aProgram);
1268 PushWorldViewState (aProgram);
1269 PushModelWorldState (aProgram);
1270 PushProjectionState (aProgram);
1271 PushLightSourceState (aProgram);
1272 PushMaterialState (aProgram);
1273 PushOitState (aProgram);
1275 if (!theProgram.IsNull())
1277 if (const OpenGl_ShaderUniformLocation& aLocViewPort = theProgram->GetStateLocation (OpenGl_OCCT_VIEWPORT))
1279 theProgram->SetUniform (myContext, aLocViewPort, OpenGl_Vec4 ((float )myContext->Viewport()[0], (float )myContext->Viewport()[1],
1280 (float )myContext->Viewport()[2], (float )myContext->Viewport()[3]));
1285 // =======================================================================
1286 // function : prepareStdProgramFont
1288 // =======================================================================
1289 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
1291 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1292 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT));
1293 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1295 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
1298 EOL" TexCoord = occTexCoord.st;"
1299 + THE_VERT_gl_Position
1302 TCollection_AsciiString
1303 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).a; }";
1304 #if !defined(GL_ES_VERSION_2_0)
1305 if (myContext->core11 == NULL)
1307 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).r; }";
1311 TCollection_AsciiString aSrcFrag =
1315 EOL" vec4 aColor = occColor;"
1316 EOL" aColor.a *= getAlpha();"
1317 EOL" if (aColor.a <= 0.285) discard;"
1318 EOL" occSetFragColor (aColor);"
1321 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1322 defaultGlslVersion (aProgramSrc, "font", 0);
1323 aProgramSrc->SetDefaultSampler (false);
1324 aProgramSrc->SetNbLightsMax (0);
1325 aProgramSrc->SetNbClipPlanesMax (0);
1326 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1327 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
1328 TCollection_AsciiString aKey;
1329 if (!Create (aProgramSrc, aKey, myFontProgram))
1331 myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1332 return Standard_False;
1334 return Standard_True;
1337 // =======================================================================
1338 // function : BindFboBlitProgram
1340 // =======================================================================
1341 Standard_Boolean OpenGl_ShaderManager::BindFboBlitProgram (Standard_Integer theNbSamples,
1342 Standard_Boolean theIsFallback_sRGB)
1344 NCollection_Array1<Handle(OpenGl_ShaderProgram)>& aList = myBlitPrograms[theIsFallback_sRGB ? 1 : 0];
1345 Standard_Integer aNbSamples = Max (theNbSamples, 1);
1346 if (aNbSamples > aList.Upper())
1348 aList.Resize (1, aNbSamples, true);
1351 Handle(OpenGl_ShaderProgram)& aProg = aList[aNbSamples];
1354 prepareStdProgramFboBlit (aProg, aNbSamples, theIsFallback_sRGB);
1356 return !aProg.IsNull()
1357 && myContext->BindProgram (aProg);
1360 // =======================================================================
1361 // function : prepareStdProgramFboBlit
1363 // =======================================================================
1364 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit (Handle(OpenGl_ShaderProgram)& theProgram,
1365 Standard_Integer theNbSamples,
1366 Standard_Boolean theIsFallback_sRGB)
1368 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1369 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1371 TCollection_AsciiString aSrcVert =
1374 EOL" TexCoord = occVertex.zw;"
1375 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1378 TCollection_AsciiString aSrcFrag;
1379 if (theNbSamples > 1)
1381 #if defined(GL_ES_VERSION_2_0)
1382 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("highp sampler2DMS uColorSampler", Graphic3d_TOS_FRAGMENT));
1383 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("highp sampler2DMS uDepthSampler", Graphic3d_TOS_FRAGMENT));
1385 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uColorSampler", Graphic3d_TOS_FRAGMENT));
1386 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uDepthSampler", Graphic3d_TOS_FRAGMENT));
1388 aSrcFrag = TCollection_AsciiString()
1389 + EOL"#define THE_NUM_SAMPLES " + theNbSamples
1390 + (theIsFallback_sRGB ? EOL"#define THE_SHIFT_sRGB" : "")
1393 EOL" ivec2 aSize = textureSize (uColorSampler);"
1394 EOL" ivec2 anUV = ivec2 (vec2 (aSize) * TexCoord);"
1395 EOL" gl_FragDepth = texelFetch (uDepthSampler, anUV, THE_NUM_SAMPLES / 2 - 1).r;"
1397 EOL" vec4 aColor = vec4 (0.0);"
1398 EOL" for (int aSample = 0; aSample < THE_NUM_SAMPLES; ++aSample)"
1400 EOL" vec4 aVal = texelFetch (uColorSampler, anUV, aSample);"
1401 EOL" aColor += aVal;"
1403 EOL" aColor /= float(THE_NUM_SAMPLES);"
1404 EOL"#ifdef THE_SHIFT_sRGB"
1405 EOL" aColor.rgb = pow (aColor.rgb, vec3 (1.0 / 2.2));"
1407 EOL" occSetFragColor (aColor);"
1412 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uColorSampler", Graphic3d_TOS_FRAGMENT));
1413 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uDepthSampler", Graphic3d_TOS_FRAGMENT));
1414 aSrcFrag = TCollection_AsciiString()
1415 + (theIsFallback_sRGB ? EOL"#define THE_SHIFT_sRGB" : "")
1418 EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;"
1419 EOL" vec4 aColor = occTexture2D (uColorSampler, TexCoord);"
1420 EOL"#ifdef THE_SHIFT_sRGB"
1421 EOL" aColor.rgb = pow (aColor.rgb, vec3 (1.0 / 2.2));"
1423 EOL" occSetFragColor (aColor);"
1427 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1428 #if defined(GL_ES_VERSION_2_0)
1429 if (myContext->IsGlGreaterEqual (3, 1))
1431 // required for MSAA sampler
1432 aProgramSrc->SetHeader ("#version 310 es");
1434 else if (myContext->IsGlGreaterEqual (3, 0))
1436 aProgramSrc->SetHeader ("#version 300 es");
1438 else if (myContext->extFragDepth)
1440 aProgramSrc->SetHeader ("#extension GL_EXT_frag_depth : enable"
1441 EOL"#define gl_FragDepth gl_FragDepthEXT");
1445 // there is no way to draw into depth buffer
1449 EOL" occSetFragColor (occTexture2D (uColorSampler, TexCoord));"
1453 if (myContext->core32 != NULL)
1455 aProgramSrc->SetHeader ("#version 150");
1458 TCollection_AsciiString anId = "occt_blit";
1459 if (theNbSamples > 1)
1461 anId += TCollection_AsciiString ("_msaa") + theNbSamples;
1463 if (theIsFallback_sRGB)
1467 aProgramSrc->SetId (anId);
1468 aProgramSrc->SetDefaultSampler (false);
1469 aProgramSrc->SetNbLightsMax (0);
1470 aProgramSrc->SetNbClipPlanesMax (0);
1471 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1472 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
1473 TCollection_AsciiString aKey;
1474 if (!Create (aProgramSrc, aKey, theProgram))
1476 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1477 return Standard_False;
1480 myContext->BindProgram (theProgram);
1481 theProgram->SetSampler (myContext, "uColorSampler", Graphic3d_TextureUnit_0);
1482 theProgram->SetSampler (myContext, "uDepthSampler", Graphic3d_TextureUnit_1);
1483 myContext->BindProgram (NULL);
1484 return Standard_True;
1487 // =======================================================================
1488 // function : prepareStdProgramOitCompositing
1490 // =======================================================================
1491 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const Standard_Boolean theMsaa)
1493 Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram[theMsaa ? 1 : 0];
1494 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1495 TCollection_AsciiString aSrcVert, aSrcFrag;
1497 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1498 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1503 EOL" TexCoord = occVertex.zw;"
1504 EOL" gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);"
1509 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uAccumTexture", Graphic3d_TOS_FRAGMENT));
1510 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uWeightTexture", Graphic3d_TOS_FRAGMENT));
1514 EOL" vec4 aAccum = occTexture2D (uAccumTexture, TexCoord);"
1515 EOL" float aWeight = occTexture2D (uWeightTexture, TexCoord).r;"
1516 EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
1518 #if !defined(GL_ES_VERSION_2_0)
1519 if (myContext->IsGlGreaterEqual (3, 2))
1521 aProgramSrc->SetHeader ("#version 150");
1524 if (myContext->IsGlGreaterEqual (3, 0))
1526 aProgramSrc->SetHeader ("#version 300 es");
1532 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uAccumTexture", Graphic3d_TOS_FRAGMENT));
1533 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uWeightTexture", Graphic3d_TOS_FRAGMENT));
1537 EOL" ivec2 aTexel = ivec2 (vec2 (textureSize (uAccumTexture)) * TexCoord);"
1538 EOL" vec4 aAccum = texelFetch (uAccumTexture, aTexel, gl_SampleID);"
1539 EOL" float aWeight = texelFetch (uWeightTexture, aTexel, gl_SampleID).r;"
1540 EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
1542 #if !defined(GL_ES_VERSION_2_0)
1543 if (myContext->IsGlGreaterEqual (4, 0))
1545 aProgramSrc->SetHeader ("#version 400");
1548 if (myContext->IsGlGreaterEqual (3, 2))
1550 aProgramSrc->SetHeader ("#version 320 es");
1552 else if (myContext->IsGlGreaterEqual (3, 0))
1554 aProgramSrc->SetHeader ("#version 300 es"); // with GL_OES_sample_variables extension
1559 aProgramSrc->SetId (theMsaa ? "occt_weight-oit-msaa" : "occt_weight-oit");
1560 aProgramSrc->SetDefaultSampler (false);
1561 aProgramSrc->SetNbLightsMax (0);
1562 aProgramSrc->SetNbClipPlanesMax (0);
1563 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1564 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
1565 TCollection_AsciiString aKey;
1566 if (!Create (aProgramSrc, aKey, aProgram))
1568 aProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1569 return Standard_False;
1572 myContext->BindProgram (aProgram);
1573 aProgram->SetSampler (myContext, "uAccumTexture", Graphic3d_TextureUnit_0);
1574 aProgram->SetSampler (myContext, "uWeightTexture", Graphic3d_TextureUnit_1);
1575 myContext->BindProgram (Handle(OpenGl_ShaderProgram)());
1576 return Standard_True;
1579 // =======================================================================
1580 // function : pointSpriteAlphaSrc
1582 // =======================================================================
1583 TCollection_AsciiString OpenGl_ShaderManager::pointSpriteAlphaSrc (Standard_Integer theBits)
1585 TCollection_AsciiString aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ").a; }";
1586 #if !defined(GL_ES_VERSION_2_0)
1587 if (myContext->core11 == NULL
1588 && (theBits & OpenGl_PO_PointSpriteA) == OpenGl_PO_PointSpriteA)
1590 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ").r; }";
1595 return aSrcGetAlpha;
1598 // =======================================================================
1599 // function : defaultGlslVersion
1601 // =======================================================================
1602 int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram,
1603 const TCollection_AsciiString& theName,
1605 bool theUsesDerivates) const
1607 int aBits = theBits;
1608 const bool toUseDerivates = theUsesDerivates
1609 || (theBits & OpenGl_PO_StippleLine) != 0;
1610 #if !defined(GL_ES_VERSION_2_0)
1611 if (myContext->core32 != NULL)
1613 theProgram->SetHeader ("#version 150");
1617 if ((theBits & OpenGl_PO_StippleLine) != 0)
1619 if (myContext->IsGlGreaterEqual (3, 0))
1621 theProgram->SetHeader ("#version 130");
1623 else if (myContext->CheckExtension ("GL_EXT_gpu_shader4")) // myContext->hasGlslBitwiseOps == OpenGl_FeatureInExtensions
1625 // GL_EXT_gpu_shader4 defines GLSL type "unsigned int", while core GLSL specs define type "uint"
1626 theProgram->SetHeader ("#extension GL_EXT_gpu_shader4 : enable\n"
1627 "#define uint unsigned int");
1631 (void )toUseDerivates;
1633 // prefer "100 es" on OpenGL ES 3.0- devices (save the features unavailable before "300 es")
1634 // and "300 es" on OpenGL ES 3.1+ devices
1635 if (myContext->IsGlGreaterEqual (3, 1))
1637 if ((theBits & OpenGl_PO_NeedsGeomShader) != 0)
1639 theProgram->SetHeader (myContext->hasGeometryStage != OpenGl_FeatureInExtensions ? "#version 320 es" : "#version 310 es");
1643 theProgram->SetHeader ("#version 300 es");
1648 if ((theBits & OpenGl_PO_WriteOit) != 0
1649 || (theBits & OpenGl_PO_StippleLine) != 0)
1651 if (myContext->IsGlGreaterEqual (3, 0))
1653 theProgram->SetHeader ("#version 300 es");
1657 aBits = aBits & ~OpenGl_PO_WriteOit;
1658 if (!myContext->oesStdDerivatives)
1660 aBits = aBits & ~OpenGl_PO_StippleLine;
1666 if (myContext->IsGlGreaterEqual (3, 0))
1668 theProgram->SetHeader ("#version 300 es");
1670 else if (myContext->oesStdDerivatives)
1672 theProgram->SetHeader ("#extension GL_OES_standard_derivatives : enable");
1678 // should fit OpenGl_PO_NB
1680 Sprintf (aBitsStr, "%04x", aBits);
1681 theProgram->SetId (TCollection_AsciiString ("occt_") + theName + aBitsStr);
1685 // =======================================================================
1686 // function : prepareGeomMainSrc
1688 // =======================================================================
1689 TCollection_AsciiString OpenGl_ShaderManager::prepareGeomMainSrc (OpenGl_ShaderObject::ShaderVariableList& theUnifoms,
1690 OpenGl_ShaderObject::ShaderVariableList& theStageInOuts,
1691 Standard_Integer theBits)
1693 if ((theBits & OpenGl_PO_NeedsGeomShader) == 0)
1695 return TCollection_AsciiString();
1698 TCollection_AsciiString aSrcMainGeom =
1702 if ((theBits & OpenGl_PO_MeshEdges) != 0)
1704 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occViewport", Graphic3d_TOS_GEOMETRY));
1705 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("bool occIsQuadMode", Graphic3d_TOS_GEOMETRY));
1706 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineWidth", Graphic3d_TOS_GEOMETRY));
1707 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineWidth", Graphic3d_TOS_FRAGMENT));
1708 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineFeather", Graphic3d_TOS_FRAGMENT));
1709 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occWireframeColor", Graphic3d_TOS_FRAGMENT));
1710 theStageInOuts.Append(OpenGl_ShaderObject::ShaderVariable ("vec3 EdgeDistance", Graphic3d_TOS_GEOMETRY | Graphic3d_TOS_FRAGMENT));
1712 aSrcMainGeom = TCollection_AsciiString()
1713 + EOL"vec3 ViewPortTransform (vec4 theVec)"
1715 EOL" vec3 aWinCoord = theVec.xyz / theVec.w;"
1716 EOL" aWinCoord = aWinCoord * 0.5 + 0.5;"
1717 EOL" aWinCoord.xy = aWinCoord.xy * occViewport.zw + occViewport.xy;"
1718 EOL" return aWinCoord;"
1721 + EOL" vec3 aSideA = ViewPortTransform (gl_in[2].gl_Position) - ViewPortTransform (gl_in[1].gl_Position);"
1722 EOL" vec3 aSideB = ViewPortTransform (gl_in[2].gl_Position) - ViewPortTransform (gl_in[0].gl_Position);"
1723 EOL" vec3 aSideC = ViewPortTransform (gl_in[1].gl_Position) - ViewPortTransform (gl_in[0].gl_Position);"
1724 EOL" float aQuadArea = abs (aSideB.x * aSideC.y - aSideB.y * aSideC.x);"
1725 EOL" vec3 aLenABC = vec3 (length (aSideA), length (aSideB), length (aSideC));"
1726 EOL" vec3 aHeightABC = vec3 (aQuadArea) / aLenABC;"
1727 EOL" aHeightABC = max (aHeightABC, vec3 (10.0 * occLineWidth));" // avoid shrunk presentation disappearing at distance
1728 EOL" float aQuadModeHeightC = occIsQuadMode ? occLineWidth + 1.0 : 0.0;";
1731 for (Standard_Integer aVertIter = 0; aVertIter < 3; ++aVertIter)
1733 const TCollection_AsciiString aVertIndex (aVertIter);
1734 // pass variables from Vertex shader to Fragment shader through Geometry shader
1735 for (OpenGl_ShaderObject::ShaderVariableList::Iterator aVarListIter (theStageInOuts); aVarListIter.More(); aVarListIter.Next())
1737 if (aVarListIter.Value().Stages == (Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT))
1739 const TCollection_AsciiString aVarName = aVarListIter.Value().Name.Token (" ", 2);
1740 aSrcMainGeom += TCollection_AsciiString()
1741 + EOL" geomOut." + aVarName + " = geomIn[" + aVertIndex + "]." + aVarName + ";";
1745 if ((theBits & OpenGl_PO_MeshEdges) != 0)
1749 case 0: aSrcMainGeom += EOL" EdgeDistance = vec3 (aHeightABC[0], 0.0, aQuadModeHeightC);"; break;
1750 case 1: aSrcMainGeom += EOL" EdgeDistance = vec3 (0.0, aHeightABC[1], aQuadModeHeightC);"; break;
1751 case 2: aSrcMainGeom += EOL" EdgeDistance = vec3 (0.0, 0.0, aHeightABC[2]);"; break;
1754 aSrcMainGeom += TCollection_AsciiString()
1755 + EOL" gl_Position = gl_in[" + aVertIndex + "].gl_Position;"
1756 EOL" EmitVertex();";
1759 EOL" EndPrimitive();"
1762 return aSrcMainGeom;
1765 // =======================================================================
1766 // function : prepareStdProgramUnlit
1768 // =======================================================================
1769 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_ShaderProgram)& theProgram,
1770 Standard_Integer theBits,
1771 Standard_Boolean theIsOutline)
1773 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1774 TCollection_AsciiString aSrcVert, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha, aSrcVertEndMain;
1775 TCollection_AsciiString aSrcFrag, aSrcFragExtraMain;
1776 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
1777 TCollection_AsciiString aSrcFragMainGetColor = EOL" occSetFragColor (getFinalColor());";
1778 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1780 if ((theBits & OpenGl_PO_IsPoint) != 0)
1782 #if defined(GL_ES_VERSION_2_0)
1783 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1786 if ((theBits & OpenGl_PO_PointSprite) != 0)
1788 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT));
1789 if ((theBits & OpenGl_PO_PointSpriteA) != OpenGl_PO_PointSpriteA)
1792 EOL"vec4 getColor(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord "); }";
1794 else if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB
1795 && (theBits & OpenGl_PO_VertColor) == 0)
1797 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX));
1798 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1799 aSrcVertExtraMain +=
1800 EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);";
1802 EOL"vec4 getColor(void) { return VertColor; }";
1805 aSrcGetAlpha = pointSpriteAlphaSrc (theBits);
1807 #if !defined(GL_ES_VERSION_2_0)
1808 if (myContext->core11 != NULL
1809 && myContext->IsGlGreaterEqual (2, 1))
1811 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1815 aSrcFragMainGetColor =
1816 EOL" vec4 aColor = getColor();"
1817 EOL" aColor.a = getAlpha();"
1818 EOL" if (aColor.a <= 0.1) discard;"
1819 EOL" occSetFragColor (aColor);";
1823 if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB
1824 && (theBits & OpenGl_PO_VertColor) == 0)
1826 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX));
1827 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1828 aSrcVertExtraMain +=
1829 EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);";
1831 EOL"vec4 getColor(void) { return VertColor; }";
1834 aSrcFragMainGetColor =
1835 EOL" vec4 aColor = getColor();"
1836 EOL" if (aColor.a <= 0.1) discard;"
1837 EOL" occSetFragColor (aColor);";
1842 if ((theBits & OpenGl_PO_TextureRGB) != 0 || (theBits & OpenGl_PO_TextureEnv) != 0)
1844 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT));
1845 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1848 if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB)
1850 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
1853 EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w); }";
1855 else if ((theBits & OpenGl_PO_TextureEnv) != 0)
1857 aSrcVertExtraFunc = THE_FUNC_transformNormal;
1859 aSrcVertExtraMain +=
1860 EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;"
1861 EOL" vec3 aNormal = transformNormal (occNormal);"
1862 EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);"
1863 EOL" aReflect.z += 1.0;"
1864 EOL" TexCoord = vec4(aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5), 0.0, 1.0);";
1867 EOL"vec4 getColor(void) { return occTexture2D (occSamplerBaseColor, TexCoord.st); }";
1870 if ((theBits & OpenGl_PO_VertColor) != 0)
1872 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1873 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
1874 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
1877 int aNbClipPlanes = 0;
1878 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
1880 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1881 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1882 aSrcVertExtraMain +=
1883 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
1884 EOL" Position = occWorldViewMatrix * PositionWorld;";
1886 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
1888 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
1889 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
1890 ? THE_FRAG_CLIP_CHAINS_N
1891 : THE_FRAG_CLIP_PLANES_N;
1893 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
1896 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
1898 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
1901 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
1902 ? THE_FRAG_CLIP_CHAINS_2
1903 : THE_FRAG_CLIP_PLANES_2;
1906 if ((theBits & OpenGl_PO_WriteOit) != 0)
1908 aProgramSrc->SetNbFragmentOutputs (2);
1909 aProgramSrc->SetWeightOitOutput (true);
1914 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float occOrthoScale", Graphic3d_TOS_VERTEX));
1915 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float occSilhouetteThickness", Graphic3d_TOS_VERTEX));
1916 aSrcVertEndMain = THE_VERT_gl_Position_OUTLINE;
1918 else if ((theBits & OpenGl_PO_StippleLine) != 0)
1920 const Standard_Integer aBits = defaultGlslVersion (aProgramSrc, "unlit", theBits);
1921 if ((aBits & OpenGl_PO_StippleLine) != 0)
1923 if (myContext->hasGlslBitwiseOps != OpenGl_FeatureNotAvailable)
1925 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int occStipplePattern", Graphic3d_TOS_FRAGMENT));
1929 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("bool occStipplePattern[16]", Graphic3d_TOS_FRAGMENT));
1931 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float occStippleFactor", Graphic3d_TOS_FRAGMENT));
1932 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occViewport", Graphic3d_TOS_VERTEX));
1933 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 ScreenSpaceCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1935 EOL" vec2 aPosition = gl_Position.xy / gl_Position.w;"
1936 EOL" aPosition = aPosition * 0.5 + 0.5;"
1937 EOL" ScreenSpaceCoord = aPosition.xy * occViewport.zw + occViewport.xy;";
1938 aSrcFragMainGetColor = TCollection_AsciiString()
1939 + EOL" vec2 anAxis = vec2 (0.0, 1.0);"
1940 EOL" if (abs (dFdx (ScreenSpaceCoord.x)) - abs (dFdy (ScreenSpaceCoord.y)) > 0.001)"
1942 EOL" anAxis = vec2 (1.0, 0.0);"
1944 EOL" float aRotatePoint = dot (gl_FragCoord.xy, anAxis);"
1945 + (myContext->hasGlslBitwiseOps != OpenGl_FeatureNotAvailable
1946 ? EOL" uint aBit = uint (floor (aRotatePoint / occStippleFactor + 0.5)) & 15U;"
1947 EOL" if ((uint (occStipplePattern) & (1U << aBit)) == 0U) discard;"
1948 : EOL" int aBit = int (mod (floor (aRotatePoint / occStippleFactor + 0.5), 16.0));"
1949 EOL" if (!occStipplePattern[aBit]) discard;")
1950 + EOL" vec4 aColor = getFinalColor();"
1951 EOL" if (aColor.a <= 0.1) discard;"
1952 EOL" occSetFragColor (aColor);";
1956 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, "Warning: stipple lines in GLSL will be ignored.");
1965 + THE_VERT_gl_Position
1969 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
1970 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
1971 ? THE_FRAG_WIREFRAME_COLOR
1972 : EOL"#define getFinalColor getColor";
1980 + aSrcFragMainGetColor
1983 defaultGlslVersion (aProgramSrc, theIsOutline ? "outline" : "unlit", theBits);
1984 aProgramSrc->SetDefaultSampler (false);
1985 aProgramSrc->SetNbLightsMax (0);
1986 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
1987 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
1988 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
1989 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
1990 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
1991 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
1992 TCollection_AsciiString aKey;
1993 if (!Create (aProgramSrc, aKey, theProgram))
1995 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1996 return Standard_False;
1998 return Standard_True;
2001 // =======================================================================
2002 // function : pointSpriteShadingSrc
2004 // =======================================================================
2005 TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TCollection_AsciiString& theBaseColorSrc,
2006 Standard_Integer theBits)
2008 TCollection_AsciiString aSrcFragGetColor;
2009 if ((theBits & OpenGl_PO_PointSpriteA) == OpenGl_PO_PointSpriteA)
2011 aSrcFragGetColor = pointSpriteAlphaSrc (theBits) +
2012 EOL"vec4 getColor(void)"
2014 EOL" vec4 aColor = " + theBaseColorSrc + ";"
2015 EOL" aColor.a = getAlpha();"
2016 EOL" if (aColor.a <= 0.1) discard;"
2017 EOL" return aColor;"
2020 else if ((theBits & OpenGl_PO_PointSprite) == OpenGl_PO_PointSprite)
2022 aSrcFragGetColor = TCollection_AsciiString() +
2023 EOL"vec4 getColor(void)"
2025 EOL" vec4 aColor = " + theBaseColorSrc + ";"
2026 EOL" aColor = occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ") * aColor;"
2027 EOL" if (aColor.a <= 0.1) discard;"
2028 EOL" return aColor;"
2032 return aSrcFragGetColor;
2035 // =======================================================================
2036 // function : stdComputeLighting
2038 // =======================================================================
2039 TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integer& theNbLights,
2040 Standard_Boolean theHasVertColor)
2042 TCollection_AsciiString aLightsFunc, aLightsLoop;
2044 const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources();
2045 if (!aLights.IsNull())
2047 theNbLights = aLights->NbEnabled();
2048 if (theNbLights <= THE_NB_UNROLLED_LIGHTS_MAX)
2050 Standard_Integer anIndex = 0;
2051 for (Graphic3d_LightSet::Iterator aLightIter (aLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
2052 aLightIter.More(); aLightIter.Next(), ++anIndex)
2054 switch (aLightIter.Value()->Type())
2056 case Graphic3d_TOLS_AMBIENT:
2058 break; // skip ambient
2059 case Graphic3d_TOLS_DIRECTIONAL:
2060 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
2062 case Graphic3d_TOLS_POSITIONAL:
2063 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
2065 case Graphic3d_TOLS_SPOT:
2066 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
2073 theNbLights = roundUpMaxLightSources (theNbLights);
2074 bool isFirstInLoop = true;
2075 aLightsLoop = aLightsLoop +
2076 EOL" for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)"
2078 EOL" int aType = occLight_Type (anIndex);";
2079 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0)
2081 isFirstInLoop = false;
2083 EOL" if (aType == OccLightType_Direct)"
2085 EOL" directionalLight (anIndex, theNormal, theView, theIsFront);"
2088 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
2092 aLightsLoop += EOL" else ";
2094 isFirstInLoop = false;
2096 EOL" if (aType == OccLightType_Point)"
2098 EOL" pointLight (anIndex, theNormal, theView, aPoint, theIsFront);"
2101 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0)
2105 aLightsLoop += EOL" else ";
2107 isFirstInLoop = false;
2109 EOL" if (aType == OccLightType_Spot)"
2111 EOL" spotLight (anIndex, theNormal, theView, aPoint, theIsFront);"
2114 aLightsLoop += EOL" }";
2116 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) == 1
2117 && theNbLights == 1)
2119 // use the version with hard-coded first index
2120 aLightsLoop = EOL" directionalLightFirst(theNormal, theView, theIsFront);";
2121 aLightsFunc += THE_FUNC_directionalLightFirst;
2123 else if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0)
2125 aLightsFunc += THE_FUNC_directionalLight;
2127 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
2129 aLightsFunc += THE_FUNC_pointLight;
2131 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0)
2133 aLightsFunc += THE_FUNC_spotLight;
2137 TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();";
2138 TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();";
2139 if (theHasVertColor)
2141 aGetMatAmbient = "getVertColor();";
2142 aGetMatDiffuse = "getVertColor();";
2145 return TCollection_AsciiString()
2149 EOL"vec4 computeLighting (in vec3 theNormal,"
2150 EOL" in vec3 theView,"
2151 EOL" in vec4 thePoint,"
2152 EOL" in bool theIsFront)"
2154 EOL" Ambient = occLightAmbient.rgb;"
2155 EOL" Diffuse = vec3 (0.0);"
2156 EOL" Specular = vec3 (0.0);"
2157 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
2159 + EOL" vec4 aMatAmbient = " + aGetMatAmbient
2160 + EOL" vec4 aMatDiffuse = " + aGetMatDiffuse
2161 + EOL" vec4 aMatSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
2162 EOL" vec4 aMatEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
2163 EOL" vec3 aColor = Ambient * aMatAmbient.rgb"
2164 EOL" + Diffuse * aMatDiffuse.rgb"
2165 EOL" + Specular * aMatSpecular.rgb"
2166 EOL" + aMatEmission.rgb;"
2167 EOL" return vec4 (aColor, aMatDiffuse.a);"
2171 // =======================================================================
2172 // function : prepareStdProgramGouraud
2174 // =======================================================================
2175 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
2176 const Standard_Integer theBits)
2178 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2179 TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraMain;
2180 TCollection_AsciiString aSrcFrag, aSrcFragExtraMain;
2181 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
2182 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2184 if ((theBits & OpenGl_PO_IsPoint) != 0)
2186 #if defined(GL_ES_VERSION_2_0)
2187 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
2190 if ((theBits & OpenGl_PO_PointSprite) != 0)
2192 #if !defined(GL_ES_VERSION_2_0)
2193 if (myContext->core11 != NULL
2194 && myContext->IsGlGreaterEqual (2, 1))
2196 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
2200 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT));
2201 aSrcFragGetColor = pointSpriteShadingSrc ("gl_FrontFacing ? FrontColor : BackColor", theBits);
2204 if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB
2205 && (theBits & OpenGl_PO_VertColor) == 0)
2207 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX));
2208 aSrcVertColor = EOL"vec4 getVertColor(void) { return occTexture2D (occSamplerBaseColor, occTexCoord.xy); }";
2213 if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB)
2215 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT));
2216 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2217 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
2220 EOL"vec4 getColor(void)"
2222 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
2223 EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;"
2228 if ((theBits & OpenGl_PO_VertColor) != 0)
2230 aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
2233 int aNbClipPlanes = 0;
2234 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
2236 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2237 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2238 aSrcVertExtraMain +=
2239 EOL" PositionWorld = aPositionWorld;"
2240 EOL" Position = aPosition;";
2242 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
2244 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
2245 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2246 ? THE_FRAG_CLIP_CHAINS_N
2247 : THE_FRAG_CLIP_PLANES_N;
2249 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
2252 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
2254 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
2257 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2258 ? THE_FRAG_CLIP_CHAINS_2
2259 : THE_FRAG_CLIP_PLANES_2;
2262 if ((theBits & OpenGl_PO_WriteOit) != 0)
2264 aProgramSrc->SetNbFragmentOutputs (2);
2265 aProgramSrc->SetWeightOitOutput (true);
2268 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 FrontColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2269 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 BackColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2271 Standard_Integer aNbLights = 0;
2272 const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcVertColor.IsEmpty());
2273 aSrcVert = TCollection_AsciiString()
2274 + THE_FUNC_transformNormal
2280 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
2281 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
2282 EOL" vec3 aNormal = transformNormal (occNormal);"
2283 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
2284 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
2285 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
2287 + THE_VERT_gl_Position
2290 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
2291 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
2292 ? THE_FRAG_WIREFRAME_COLOR
2293 : EOL"#define getFinalColor getColor";
2295 aSrcFrag = TCollection_AsciiString()
2300 + EOL" occSetFragColor (getFinalColor());"
2303 const TCollection_AsciiString aProgId = TCollection_AsciiString ("gouraud-") + genLightKey (myLightSourceState.LightSources()) + "-";
2304 defaultGlslVersion (aProgramSrc, aProgId, theBits);
2305 aProgramSrc->SetDefaultSampler (false);
2306 aProgramSrc->SetNbLightsMax (aNbLights);
2307 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
2308 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
2309 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
2310 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2311 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
2312 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2313 TCollection_AsciiString aKey;
2314 if (!Create (aProgramSrc, aKey, theProgram))
2316 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2317 return Standard_False;
2319 return Standard_True;
2322 // =======================================================================
2323 // function : prepareStdProgramPhong
2325 // =======================================================================
2326 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
2327 const Standard_Integer theBits,
2328 const Standard_Boolean theIsFlatNormal)
2330 #define thePhongCompLight "computeLighting (normalize (Normal), normalize (View), Position, gl_FrontFacing)"
2331 const bool isFlatNormal = theIsFlatNormal
2332 && myContext->hasFlatShading != OpenGl_FeatureNotAvailable;
2333 const char* aDFdxSignReversion = "";
2334 #if defined(GL_ES_VERSION_2_0)
2335 if (isFlatNormal != theIsFlatNormal)
2337 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
2338 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
2339 "Warning: flat shading requires OpenGL ES 3.0+ or GL_OES_standard_derivatives extension.");
2341 else if (isFlatNormal
2342 && myContext->Vendor().Search("qualcomm") != -1)
2344 // workaround Adreno driver bug computing reversed normal using dFdx/dFdy
2345 aDFdxSignReversion = "-";
2346 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
2347 "Warning: applied workaround for flat shading normal computation using dFdx/dFdy on Adreno");
2350 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2351 TCollection_AsciiString aSrcVert, aSrcVertExtraFunc, aSrcVertExtraMain;
2352 TCollection_AsciiString aSrcFrag, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain;
2353 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return " thePhongCompLight "; }";
2354 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2355 if ((theBits & OpenGl_PO_IsPoint) != 0)
2357 #if defined(GL_ES_VERSION_2_0)
2358 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
2361 if ((theBits & OpenGl_PO_PointSprite) != 0)
2363 #if !defined(GL_ES_VERSION_2_0)
2364 if (myContext->core11 != NULL
2365 && myContext->IsGlGreaterEqual (2, 1))
2367 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
2371 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT));
2372 aSrcFragGetColor = pointSpriteShadingSrc (thePhongCompLight, theBits);
2375 if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB
2376 && (theBits & OpenGl_PO_VertColor) == 0)
2378 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX));
2379 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2381 aSrcVertExtraMain += EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);";
2382 aSrcFragGetVertColor = EOL"vec4 getVertColor(void) { return VertColor; }";
2387 if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureRGB)
2389 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT));
2390 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2391 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
2394 EOL"vec4 getColor(void)"
2396 EOL" vec4 aColor = " thePhongCompLight ";"
2397 EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;"
2402 if ((theBits & OpenGl_PO_VertColor) != 0)
2404 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2405 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
2406 aSrcFragGetVertColor = EOL"vec4 getVertColor(void) { return VertColor; }";
2409 int aNbClipPlanes = 0;
2410 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
2412 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
2414 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
2415 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2416 ? THE_FRAG_CLIP_CHAINS_N
2417 : THE_FRAG_CLIP_PLANES_N;
2419 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
2422 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
2424 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
2427 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2428 ? THE_FRAG_CLIP_CHAINS_2
2429 : THE_FRAG_CLIP_PLANES_2;
2432 if ((theBits & OpenGl_PO_WriteOit) != 0)
2434 aProgramSrc->SetNbFragmentOutputs (2);
2435 aProgramSrc->SetWeightOitOutput (true);
2440 aSrcFragExtraOut += EOL"vec3 Normal;";
2441 aSrcFragExtraMain += TCollection_AsciiString()
2442 + EOL" Normal = " + aDFdxSignReversion + "normalize (cross (dFdx (Position.xyz / Position.w), dFdy (Position.xyz / Position.w)));"
2443 EOL" if (!gl_FrontFacing) { Normal = -Normal; }";
2447 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 Normal", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2448 aSrcVertExtraFunc += THE_FUNC_transformNormal;
2449 aSrcVertExtraMain += EOL" Normal = transformNormal (occNormal);";
2452 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2453 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2454 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 View", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2456 aSrcVert = TCollection_AsciiString()
2460 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
2461 EOL" Position = occWorldViewMatrix * PositionWorld;"
2462 + EOL" View = vec3 (0.0, 0.0, 1.0);"
2464 + THE_VERT_gl_Position
2467 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
2468 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
2469 ? THE_FRAG_WIREFRAME_COLOR
2470 : EOL"#define getFinalColor getColor";
2472 Standard_Integer aNbLights = 0;
2473 const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcFragGetVertColor.IsEmpty());
2474 aSrcFrag = TCollection_AsciiString()
2477 + aSrcFragGetVertColor
2484 + EOL" occSetFragColor (getFinalColor());"
2487 const TCollection_AsciiString aProgId = TCollection_AsciiString (theIsFlatNormal ? "flat-" : "phong-") + genLightKey (myLightSourceState.LightSources()) + "-";
2488 defaultGlslVersion (aProgramSrc, aProgId, theBits, isFlatNormal);
2489 aProgramSrc->SetDefaultSampler (false);
2490 aProgramSrc->SetNbLightsMax (aNbLights);
2491 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
2492 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
2493 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
2494 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2495 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
2496 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2497 TCollection_AsciiString aKey;
2498 if (!Create (aProgramSrc, aKey, theProgram))
2500 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2501 return Standard_False;
2503 return Standard_True;
2506 // =======================================================================
2507 // function : prepareStdProgramStereo
2509 // =======================================================================
2510 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
2511 const Graphic3d_StereoMode theStereoMode)
2513 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2514 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2516 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2517 TCollection_AsciiString aSrcVert =
2520 EOL" TexCoord = occVertex.zw;"
2521 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
2524 TCollection_AsciiString aSrcFrag;
2525 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uLeftSampler", Graphic3d_TOS_FRAGMENT));
2526 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uRightSampler", Graphic3d_TOS_FRAGMENT));
2527 const char* aName = "stereo";
2528 switch (theStereoMode)
2530 case Graphic3d_StereoMode_Anaglyph:
2533 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 uMultL", Graphic3d_TOS_FRAGMENT));
2534 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 uMultR", Graphic3d_TOS_FRAGMENT));
2535 const TCollection_AsciiString aNormalize = mySRgbState
2536 ? EOL"#define sRgb2linear(theColor) theColor"
2537 EOL"#define linear2sRgb(theColor) theColor"
2538 : EOL"#define sRgb2linear(theColor) pow(theColor, vec4(2.2, 2.2, 2.2, 1.0))"
2539 EOL"#define linear2sRgb(theColor) pow(theColor, 1.0 / vec4(2.2, 2.2, 2.2, 1.0))";
2540 aSrcFrag = aNormalize
2543 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2544 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2545 EOL" aColorL = sRgb2linear (aColorL);"
2546 EOL" aColorR = sRgb2linear (aColorR);"
2547 EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;"
2548 EOL" occSetFragColor (linear2sRgb (aColor));"
2552 case Graphic3d_StereoMode_RowInterlaced:
2554 aName = "row-interlaced";
2558 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2559 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2560 EOL" if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)"
2562 EOL" occSetFragColor (aColorL);"
2566 EOL" occSetFragColor (aColorR);"
2571 case Graphic3d_StereoMode_ColumnInterlaced:
2573 aName = "column-interlaced";
2577 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2578 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2579 EOL" if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)"
2581 EOL" occSetFragColor (aColorL);"
2585 EOL" occSetFragColor (aColorR);"
2590 case Graphic3d_StereoMode_ChessBoard:
2592 aName = "chessboard";
2596 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2597 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2598 EOL" bool isEvenX = int(mod(floor(gl_FragCoord.x - 1023.5), 2.0)) != 1;"
2599 EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y - 1023.5), 2.0)) == 1;"
2600 EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))"
2602 EOL" occSetFragColor (aColorL);"
2606 EOL" occSetFragColor (aColorR);"
2611 case Graphic3d_StereoMode_SideBySide:
2613 aName = "sidebyside";
2617 EOL" vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);"
2618 EOL" if (TexCoord.x > 0.5)"
2620 EOL" aTexCoord.x -= 1.0;"
2622 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
2623 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
2624 EOL" if (TexCoord.x <= 0.5)"
2626 EOL" occSetFragColor (aColorL);"
2630 EOL" occSetFragColor (aColorR);"
2635 case Graphic3d_StereoMode_OverUnder:
2637 aName = "overunder";
2641 EOL" vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);"
2642 EOL" if (TexCoord.y > 0.5)"
2644 EOL" aTexCoord.y -= 1.0;"
2646 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
2647 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
2648 EOL" if (TexCoord.y <= 0.5)"
2650 EOL" occSetFragColor (aColorL);"
2654 EOL" occSetFragColor (aColorR);"
2659 case Graphic3d_StereoMode_QuadBuffer:
2660 case Graphic3d_StereoMode_SoftPageFlip:
2663 /*const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[Graphic3d_StereoMode_QuadBuffer];
2664 if (!aProgram.IsNull())
2666 return aProgram->IsValid();
2671 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2672 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2673 EOL" aColorL.b = 0.0;"
2674 EOL" aColorL.g = 0.0;"
2675 EOL" aColorR.r = 0.0;"
2676 EOL" occSetFragColor (aColorL + aColorR);"
2682 defaultGlslVersion (aProgramSrc, aName, 0);
2683 aProgramSrc->SetDefaultSampler (false);
2684 aProgramSrc->SetNbLightsMax (0);
2685 aProgramSrc->SetNbClipPlanesMax (0);
2686 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
2687 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
2688 TCollection_AsciiString aKey;
2689 if (!Create (aProgramSrc, aKey, theProgram))
2691 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2692 return Standard_False;
2695 myContext->BindProgram (theProgram);
2696 theProgram->SetSampler (myContext, "uLeftSampler", Graphic3d_TextureUnit_0);
2697 theProgram->SetSampler (myContext, "uRightSampler", Graphic3d_TextureUnit_1);
2698 myContext->BindProgram (NULL);
2699 return Standard_True;
2702 // =======================================================================
2703 // function : prepareStdProgramBoundBox
2705 // =======================================================================
2706 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramBoundBox()
2708 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2710 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2711 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 occBBoxCenter", Graphic3d_TOS_VERTEX));
2712 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 occBBoxSize", Graphic3d_TOS_VERTEX));
2714 TCollection_AsciiString aSrcVert =
2717 EOL" vec4 aCenter = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);"
2718 EOL" vec4 aPos = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);"
2719 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * aPos;"
2722 TCollection_AsciiString aSrcFrag =
2725 EOL" occSetFragColor (occColor);"
2728 defaultGlslVersion (aProgramSrc, "bndbox", 0);
2729 aProgramSrc->SetDefaultSampler (false);
2730 aProgramSrc->SetNbLightsMax (0);
2731 aProgramSrc->SetNbClipPlanesMax (0);
2732 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
2733 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
2734 TCollection_AsciiString aKey;
2735 if (!Create (aProgramSrc, aKey, myBoundBoxProgram))
2737 myBoundBoxProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2738 return Standard_False;
2741 const OpenGl_Vec4 aMin (-0.5f, -0.5f, -0.5f, 1.0f);
2742 const OpenGl_Vec4 anAxisShifts[3] =
2744 OpenGl_Vec4 (1.0f, 0.0f, 0.0f, 0.0f),
2745 OpenGl_Vec4 (0.0f, 1.0f, 0.0f, 0.0f),
2746 OpenGl_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)
2749 const OpenGl_Vec4 aLookup1 (0.0f, 1.0f, 0.0f, 1.0f);
2750 const OpenGl_Vec4 aLookup2 (0.0f, 0.0f, 1.0f, 1.0f);
2751 OpenGl_Vec4 aLinesVertices[24];
2752 for (int anAxis = 0, aVertex = 0; anAxis < 3; ++anAxis)
2754 for (int aCompIter = 0; aCompIter < 4; ++aCompIter)
2756 aLinesVertices[aVertex++] = aMin
2757 + anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter]
2758 + anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter];
2760 aLinesVertices[aVertex++] = aMin
2761 + anAxisShifts[anAxis]
2762 + anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter]
2763 + anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter];
2766 if (myContext->ToUseVbo())
2768 myBoundBoxVertBuffer = new OpenGl_VertexBuffer();
2769 if (myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData()))
2771 myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer);
2772 return Standard_True;
2775 myBoundBoxVertBuffer = new OpenGl_VertexBufferCompat();
2776 myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData());
2777 myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer);
2778 return Standard_True;
2781 // =======================================================================
2782 // function : GetBgCubeMapProgram
2784 // =======================================================================
2785 const Handle(Graphic3d_ShaderProgram)& OpenGl_ShaderManager::GetBgCubeMapProgram ()
2787 if (myBgCubeMapProgram.IsNull())
2789 myBgCubeMapProgram = new Graphic3d_ShaderProgram;
2791 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2792 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable("vec3 ViewDirection", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2793 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uZCoeff", Graphic3d_TOS_VERTEX)); // defines orientation of Z axis to make horizontal flip
2794 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uYCoeff", Graphic3d_TOS_VERTEX)); // defines orientation of Y axis to make vertical flip
2795 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("samplerCube occSampler0", Graphic3d_TOS_FRAGMENT));
2797 TCollection_AsciiString aSrcVert =
2800 EOL" vec4 aViewDirection = occProjectionMatrixInverse * vec4(occVertex.xy, 0.0, 1.0);"
2801 EOL" aViewDirection /= aViewDirection.w;"
2802 EOL" aViewDirection.w = 0.0;"
2803 EOL" ViewDirection = normalize((occWorldViewMatrixInverse * aViewDirection).xyz);"
2804 EOL" ViewDirection = ViewDirection.yzx;" // is needed to sync horizon and frontal camera position
2805 EOL" ViewDirection.y *= uYCoeff;"
2806 EOL" ViewDirection.z *= uZCoeff;"
2807 EOL" gl_Position = vec4(occVertex.xy, 0.0, 1.0);"
2810 TCollection_AsciiString aSrcFrag =
2811 EOL"#define occEnvCubemap occSampler0"
2814 EOL" occSetFragColor (vec4(texture(occEnvCubemap, ViewDirection).rgb, 1.0));"
2817 defaultGlslVersion(myBgCubeMapProgram, "background_cubemap", 0);
2818 myBgCubeMapProgram->SetDefaultSampler(false);
2819 myBgCubeMapProgram->SetNbLightsMax(0);
2820 myBgCubeMapProgram->SetNbClipPlanesMax(0);
2821 myBgCubeMapProgram->AttachShader(OpenGl_ShaderObject::CreateFromSource(aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
2822 myBgCubeMapProgram->AttachShader(OpenGl_ShaderObject::CreateFromSource(aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
2825 return myBgCubeMapProgram;
2828 // =======================================================================
2829 // function : bindProgramWithState
2831 // =======================================================================
2832 Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram)
2834 const Standard_Boolean isBound = myContext->BindProgram (theProgram);
2836 && !theProgram.IsNull())
2838 theProgram->ApplyVariables (myContext);
2840 PushState (theProgram);
2844 // =======================================================================
2845 // function : BindMarkerProgram
2847 // =======================================================================
2848 Standard_Boolean OpenGl_ShaderManager::BindMarkerProgram (const Handle(OpenGl_TextureSet)& theTextures,
2849 Graphic3d_TypeOfShadingModel theShadingModel,
2850 Graphic3d_AlphaMode theAlphaMode,
2851 Standard_Boolean theHasVertColor,
2852 const Handle(OpenGl_ShaderProgram)& theCustomProgram)
2854 if (!theCustomProgram.IsNull()
2855 || myContext->caps->ffpEnable)
2857 return bindProgramWithState (theCustomProgram);
2860 Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, Aspect_IS_SOLID, theHasVertColor, false, false);
2861 if (!theTextures.IsNull()
2862 && theTextures->HasPointSprite())
2864 aBits |= theTextures->Last()->IsAlpha() ? OpenGl_PO_PointSpriteA : OpenGl_PO_PointSprite;
2868 aBits |= OpenGl_PO_PointSimple;
2870 Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theShadingModel, aBits);
2871 return bindProgramWithState (aProgram);