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 <Graphic3d_CubeMapPacked.hxx>
23 #include <OpenGl_ShaderManager.hxx>
24 #include <OpenGl_ShaderProgram.hxx>
25 #include <OpenGl_VertexBufferCompat.hxx>
26 #include <OpenGl_PointSprite.hxx>
27 #include <OpenGl_Workspace.hxx>
28 #include <TCollection_ExtendedString.hxx>
30 #include "../Shaders/Shaders_PBRDistribution_glsl.pxx"
31 #include "../Shaders/Shaders_PBRGeometry_glsl.pxx"
32 #include "../Shaders/Shaders_PBRFresnel_glsl.pxx"
33 #include "../Shaders/Shaders_PBRCookTorrance_glsl.pxx"
34 #include "../Shaders/Shaders_PBRIllumination_glsl.pxx"
35 #include "../Shaders/Shaders_PBREnvBaking_fs.pxx"
36 #include "../Shaders/Shaders_PBREnvBaking_vs.pxx"
38 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager,Standard_Transient)
42 //! Number specifying maximum number of light sources to prepare a GLSL program with unrolled loop.
43 const Standard_Integer THE_NB_UNROLLED_LIGHTS_MAX = 32;
45 //! Compute the size of array storing holding light sources definition.
46 static Standard_Integer roundUpMaxLightSources (Standard_Integer theNbLights)
48 Standard_Integer aMaxLimit = THE_NB_UNROLLED_LIGHTS_MAX;
49 for (; aMaxLimit < theNbLights; aMaxLimit *= 2) {}
55 //! Compute TexCoord value in Vertex Shader
56 const char THE_VARY_TexCoord_Trsf[] =
57 EOL" float aRotSin = occTextureTrsf_RotationSin();"
58 EOL" float aRotCos = occTextureTrsf_RotationCos();"
59 EOL" vec2 aTex2 = (occTexCoord.xy + occTextureTrsf_Translation()) * occTextureTrsf_Scale();"
60 EOL" vec2 aCopy = aTex2;"
61 EOL" aTex2.x = aCopy.x * aRotCos - aCopy.y * aRotSin;"
62 EOL" aTex2.y = aCopy.x * aRotSin + aCopy.y * aRotCos;"
63 EOL" TexCoord = vec4(aTex2, occTexCoord.zw);";
65 //! Auxiliary function to flip gl_PointCoord vertically
66 #define THE_VEC2_glPointCoord "vec2 (gl_PointCoord.x, 1.0 - gl_PointCoord.y)"
68 //! Auxiliary function to transform normal from model to view coordinate system.
69 const char THE_FUNC_transformNormal_view[] =
70 EOL"vec3 transformNormal (in vec3 theNormal)"
72 EOL" vec4 aResult = occWorldViewMatrixInverseTranspose"
73 EOL" * occModelWorldMatrixInverseTranspose"
74 EOL" * vec4 (theNormal, 0.0);"
75 EOL" return normalize (aResult.xyz);"
78 //! The same function as THE_FUNC_transformNormal but is used in PBR pipeline.
79 //! The normals are expected to be in world coordinate system in PBR pipeline.
80 const char THE_FUNC_transformNormal_world[] =
81 EOL"vec3 transformNormal (in vec3 theNormal)"
83 EOL" vec4 aResult = occModelWorldMatrixInverseTranspose"
84 EOL" * vec4 (theNormal, 0.0);"
85 EOL" return normalize (aResult.xyz);"
88 //! Global shader variable for color definition with lighting enabled.
89 const char THE_FUNC_lightDef[] =
90 EOL"vec3 Ambient;" //!< Ambient contribution of light sources
91 EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources
92 EOL"vec3 Specular;"; //!< Specular contribution of light sources
94 //! Global shader variable for color definition with lighting enabled.
95 const char THE_FUNC_PBR_lightDef[] =
96 EOL"vec3 DirectLighting;" //!< Accumulator of direct lighting from light sources
97 EOL"vec4 BaseColor;" //!< Base color (albedo) of material for PBR
98 EOL"float Metallic;" //!< Metallic coefficient of material
99 EOL"float NormalizedRoughness;" //!< Normalized roughness coefficient of material
100 EOL"float Roughness;" //!< Roughness coefficient of material
101 EOL"vec3 Emission;" //!< Light intensity emitted by material
102 EOL"float IOR;"; //!< Material's index of refraction
104 //! Function computes contribution of isotropic point light source
105 const char THE_FUNC_pointLight[] =
106 EOL"void pointLight (in int theId,"
107 EOL" in vec3 theNormal,"
108 EOL" in vec3 theView,"
109 EOL" in vec3 thePoint,"
110 EOL" in bool theIsFront)"
112 EOL" vec3 aLight = occLight_Position (theId).xyz;"
113 EOL" if (!occLight_IsHeadlight (theId))"
115 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));"
117 EOL" aLight -= thePoint;"
119 EOL" float aDist = length (aLight);"
120 EOL" aLight = aLight * (1.0 / aDist);"
122 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
123 EOL" + occLight_LinearAttenuation (theId) * aDist);"
125 EOL" vec3 aHalf = normalize (aLight + theView);"
127 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
128 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
129 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
131 EOL" float aSpecl = 0.0;"
132 EOL" if (aNdotL > 0.0)"
134 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
137 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
138 EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
141 //! Function computes contribution of isotropic point light source
142 const char THE_FUNC_PBR_pointLight[] =
143 EOL"void pointLight (in int theId,"
144 EOL" in vec3 theNormal,"
145 EOL" in vec3 theView,"
146 EOL" in vec3 thePoint,"
147 EOL" in bool theIsFront)"
149 EOL" vec3 aLight = occLight_Position (theId).xyz;"
150 EOL" if (occLight_IsHeadlight (theId))"
152 EOL" aLight = vec3 (occWorldViewMatrixInverse * vec4 (aLight, 1.0));"
154 EOL" aLight -= thePoint;"
156 EOL" float aDist = length (aLight);"
157 EOL" aLight /= aDist;"
159 EOL" float anAtten = 1.0 / max (aDist * aDist, 0.01);"
161 EOL" theNormal = theIsFront ? theNormal : -theNormal;"
162 EOL" DirectLighting += occPBRIllumination (theView,"
169 EOL" occLight_Specular(theId).rgb,"
170 EOL" occLight_Intensity(theId) * anAtten);"
173 //! Function computes contribution of spotlight source
174 const char THE_FUNC_spotLight[] =
175 EOL"void spotLight (in int theId,"
176 EOL" in vec3 theNormal,"
177 EOL" in vec3 theView,"
178 EOL" in vec3 thePoint,"
179 EOL" in bool theIsFront)"
181 EOL" vec3 aLight = occLight_Position (theId).xyz;"
182 EOL" vec3 aSpotDir = occLight_SpotDirection (theId).xyz;"
183 EOL" if (!occLight_IsHeadlight (theId))"
185 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));"
186 EOL" aSpotDir = vec3 (occWorldViewMatrix * vec4 (aSpotDir, 0.0));"
188 EOL" aLight -= thePoint;"
190 EOL" float aDist = length (aLight);"
191 EOL" aLight = aLight * (1.0 / aDist);"
193 EOL" aSpotDir = normalize (aSpotDir);"
195 EOL" float aCosA = dot (aSpotDir, -aLight);"
196 EOL" if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
201 EOL" float anExponent = occLight_SpotExponent (theId);"
202 EOL" float anAtten = 1.0 / (occLight_ConstAttenuation (theId)"
203 EOL" + occLight_LinearAttenuation (theId) * aDist);"
204 EOL" if (anExponent > 0.0)"
206 EOL" anAtten *= pow (aCosA, anExponent * 128.0);"
209 EOL" vec3 aHalf = normalize (aLight + theView);"
211 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
212 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
213 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
215 EOL" float aSpecl = 0.0;"
216 EOL" if (aNdotL > 0.0)"
218 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
221 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL * anAtten;"
222 EOL" Specular += occLight_Specular (theId).rgb * aSpecl * anAtten;"
225 //! Function computes contribution of spotlight source
226 const char THE_FUNC_PBR_spotLight[] =
227 EOL"void spotLight (in int theId,"
228 EOL" in vec3 theNormal,"
229 EOL" in vec3 theView,"
230 EOL" in vec3 thePoint,"
231 EOL" in bool theIsFront)"
233 EOL" vec3 aLight = occLight_Position (theId).xyz;"
234 EOL" vec3 aSpotDir = occLight_SpotDirection (theId).xyz;"
235 EOL" if (occLight_IsHeadlight (theId))"
237 EOL" aLight = vec3 (occWorldViewMatrixInverse * vec4 (aLight, 1.0));"
238 EOL" aSpotDir = vec3 (occWorldViewMatrixInverse * vec4 (aSpotDir, 0.0));"
240 EOL" aLight -= thePoint;"
242 EOL" float aDist = length (aLight);"
243 EOL" aLight /= aDist;"
245 EOL" aSpotDir = normalize (aSpotDir);"
247 EOL" float aCosA = dot (aSpotDir, -aLight);"
248 EOL" if (aCosA >= 1.0 || aCosA < cos (occLight_SpotCutOff (theId)))"
253 EOL" float anExponent = occLight_SpotExponent (theId);"
254 EOL" float anAtten = 1.0 / max (aDist * aDist, 0.01);"
255 EOL" if (anExponent > 0.0)"
257 EOL" anAtten *= pow (aCosA, anExponent * 128.0);"
260 EOL" theNormal = theIsFront ? theNormal : -theNormal;"
261 EOL" DirectLighting += occPBRIllumination (theView,"
268 EOL" occLight_Specular(theId).rgb,"
269 EOL" occLight_Intensity(theId) * anAtten);"
272 //! Function computes contribution of directional light source
273 const char THE_FUNC_directionalLight[] =
274 EOL"void directionalLight (in int theId,"
275 EOL" in vec3 theNormal,"
276 EOL" in vec3 theView,"
277 EOL" in bool theIsFront)"
279 EOL" vec3 aLight = normalize (occLight_Position (theId).xyz);"
280 EOL" if (!occLight_IsHeadlight (theId))"
282 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));"
285 EOL" vec3 aHalf = normalize (aLight + theView);"
287 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
288 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
289 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
291 EOL" float aSpecl = 0.0;"
292 EOL" if (aNdotL > 0.0)"
294 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
297 EOL" Diffuse += occLight_Diffuse (theId).rgb * aNdotL;"
298 EOL" Specular += occLight_Specular (theId).rgb * aSpecl;"
301 //! Function computes contribution of directional light source
302 const char THE_FUNC_PBR_directionalLight[] =
303 EOL"void directionalLight (in int theId,"
304 EOL" in vec3 theNormal,"
305 EOL" in vec3 theView,"
306 EOL" in bool theIsFront)"
308 EOL" vec3 aLight = normalize (occLight_Position (theId).xyz);"
309 EOL" if (occLight_IsHeadlight (theId))"
311 EOL" aLight = vec3 (occWorldViewMatrixInverse * vec4 (aLight, 0.0));"
314 EOL" theNormal = theIsFront ? theNormal : -theNormal;"
315 EOL" DirectLighting += occPBRIllumination (theView,"
322 EOL" occLight_Specular(theId).rgb,"
323 EOL" occLight_Intensity(theId));"
326 //! The same as THE_FUNC_directionalLight but for the light with zero index
327 //! (avoids limitations on some mobile devices).
328 const char THE_FUNC_directionalLightFirst[] =
329 EOL"void directionalLightFirst (in vec3 theNormal,"
330 EOL" in vec3 theView,"
331 EOL" in bool theIsFront)"
333 EOL" vec3 aLight = normalize (occLightSources[1].xyz);"
334 EOL" if (!occLight_IsHeadlight (0))"
336 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));"
339 EOL" vec3 aHalf = normalize (aLight + theView);"
341 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
342 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
343 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
345 EOL" float aSpecl = 0.0;"
346 EOL" if (aNdotL > 0.0)"
348 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
351 EOL" Diffuse += occLightSources[0].rgb * aNdotL;"
352 EOL" Specular += occLightSources[0].rgb * aSpecl;"
355 //! Returns the real cubemap fetching direction considering sides orientation, memory layout and vertical flip.
356 const char THE_FUNC_cubemap_vector_transform[] =
357 EOL"vec3 cubemapVectorTransform (in vec3 theVector,"
358 EOL" in int theYCoeff,"
359 EOL" in int theZCoeff)"
361 EOL" theVector = theVector.yzx;"
362 EOL" theVector.y *= float(theYCoeff);"
363 EOL" theVector.z *= float(theZCoeff);"
364 EOL" return theVector;"
367 //! Process clipping planes in Fragment Shader.
368 //! Should be added at the beginning of the main() function.
369 const char THE_FRAG_CLIP_PLANES_N[] =
370 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)"
372 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
373 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)"
379 //! Process chains of clipping planes in Fragment Shader.
380 const char THE_FRAG_CLIP_CHAINS_N[] =
381 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount;)"
383 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
384 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)"
386 EOL" if (occClipPlaneChains[aPlaneIter] == 1)"
390 EOL" aPlaneIter += 1;"
394 EOL" aPlaneIter += occClipPlaneChains[aPlaneIter];"
398 //! Process 1 clipping plane in Fragment Shader.
399 const char THE_FRAG_CLIP_PLANES_1[] =
400 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
401 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0)"
406 //! Process 2 clipping planes in Fragment Shader.
407 const char THE_FRAG_CLIP_PLANES_2[] =
408 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
409 EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];"
410 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0"
411 EOL" || dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)"
416 //! Process a chain of 2 clipping planes in Fragment Shader (3/4 section).
417 const char THE_FRAG_CLIP_CHAINS_2[] =
418 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
419 EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];"
420 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0"
421 EOL" && dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)"
426 //! Modify color for Wireframe presentation.
427 const char THE_FRAG_WIREFRAME_COLOR[] =
428 EOL"vec4 getFinalColor(void)"
430 EOL" float aDistance = min (min (EdgeDistance[0], EdgeDistance[1]), EdgeDistance[2]);"
431 EOL" bool isHollow = occWireframeColor.a < 0.0;"
432 EOL" float aMixVal = smoothstep (occLineWidth - occLineFeather * 0.5, occLineWidth + occLineFeather * 0.5, aDistance);"
433 EOL" vec4 aMixColor = isHollow"
434 EOL" ? vec4 (getColor().rgb, 1.0 - aMixVal)" // edges only (of interior color)
435 EOL" : mix (occWireframeColor, getColor(), aMixVal);" // interior + edges
436 EOL" return aMixColor;"
439 //! Compute gl_Position vertex shader output.
440 const char THE_VERT_gl_Position[] =
441 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;";
443 //! Displace gl_Position alongside vertex normal for outline rendering.
444 //! This code adds silhouette only for smooth surfaces of closed primitive, and produces visual artifacts on sharp edges.
445 const char THE_VERT_gl_Position_OUTLINE[] =
446 EOL" float anOutlineDisp = occOrthoScale > 0.0 ? occOrthoScale : gl_Position.w;"
447 EOL" vec4 anOutlinePos = occVertex + vec4 (occNormal * (occSilhouetteThickness * anOutlineDisp), 0.0);"
448 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * anOutlinePos;";
450 #if !defined(GL_ES_VERSION_2_0)
452 static const GLfloat THE_DEFAULT_AMBIENT[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
453 static const GLfloat THE_DEFAULT_SPOT_DIR[3] = { 0.0f, 0.0f, -1.0f };
454 static const GLfloat THE_DEFAULT_SPOT_EXPONENT = 0.0f;
455 static const GLfloat THE_DEFAULT_SPOT_CUTOFF = 180.0f;
457 //! Bind FFP light source.
458 static void bindLight (const Graphic3d_CLight& theLight,
459 const GLenum theLightGlId,
460 const OpenGl_Mat4& theModelView,
461 OpenGl_Context* theCtx)
463 // the light is a headlight?
464 if (theLight.IsHeadlight())
466 theCtx->core11->glMatrixMode (GL_MODELVIEW);
467 theCtx->core11->glLoadIdentity();
471 const Graphic3d_Vec4& aLightColor = theLight.PackedColor();
472 switch (theLight.Type())
474 case Graphic3d_TOLS_AMBIENT : break; // handled by separate if-clause at beginning of method
475 case Graphic3d_TOLS_DIRECTIONAL:
477 // if the last parameter of GL_POSITION, is zero, the corresponding light source is a Directional one
478 const OpenGl_Vec4 anInfDir = -theLight.PackedDirection();
480 // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE.
481 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
482 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
483 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
484 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, anInfDir.GetData());
485 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR);
486 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT);
487 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF);
490 case Graphic3d_TOLS_POSITIONAL:
492 // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE
493 const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position().X()), static_cast<float>(theLight.Position().Y()), static_cast<float>(theLight.Position().Z()), 1.0f);
494 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
495 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
496 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
497 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, aPosition.GetData());
498 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR);
499 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT);
500 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF);
501 theCtx->core11->glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation());
502 theCtx->core11->glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation());
503 theCtx->core11->glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0);
506 case Graphic3d_TOLS_SPOT:
508 const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position().X()), static_cast<float>(theLight.Position().Y()), static_cast<float>(theLight.Position().Z()), 1.0f);
509 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
510 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
511 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
512 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, aPosition.GetData());
513 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, theLight.PackedDirection().GetData());
514 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, theLight.Concentration() * 128.0f);
515 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, (theLight.Angle() * 180.0f) / GLfloat(M_PI));
516 theCtx->core11->glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation());
517 theCtx->core11->glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation());
518 theCtx->core11->glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f);
523 // restore matrix in case of headlight
524 if (theLight.IsHeadlight())
526 theCtx->core11->glLoadMatrixf (theModelView.GetData());
529 glEnable (theLightGlId);
533 //! Generate map key for light sources configuration.
534 static TCollection_AsciiString genLightKey (const Handle(Graphic3d_LightSet)& theLights)
536 if (theLights->NbEnabled() <= THE_NB_UNROLLED_LIGHTS_MAX)
538 return TCollection_AsciiString ("l_") + theLights->KeyEnabledLong();
541 const Standard_Integer aMaxLimit = roundUpMaxLightSources (theLights->NbEnabled());
542 return TCollection_AsciiString ("l_") + theLights->KeyEnabledShort() + aMaxLimit;
546 // =======================================================================
547 // function : OpenGl_ShaderManager
548 // purpose : Creates new empty shader manager
549 // =======================================================================
550 OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
551 : myFfpProgram (new OpenGl_ShaderProgramFFP()),
552 myShadingModel (Graphic3d_TOSM_VERTEX),
553 myUnlitPrograms (new OpenGl_SetOfPrograms()),
554 myContext (theContext),
555 mySRgbState (theContext->ToRenderSRGB()),
556 myHasLocalOrigin (Standard_False),
562 // =======================================================================
563 // function : ~OpenGl_ShaderManager
564 // purpose : Releases resources of shader manager
565 // =======================================================================
566 OpenGl_ShaderManager::~OpenGl_ShaderManager()
568 myProgramList.Clear();
569 if (!myPBREnvironment.IsNull())
571 myPBREnvironment->Release (myContext);
575 // =======================================================================
578 // =======================================================================
579 void OpenGl_ShaderManager::clear()
581 myProgramList.Clear();
582 myLightPrograms.Nullify();
583 myUnlitPrograms = new OpenGl_SetOfPrograms();
584 myOutlinePrograms.Nullify();
585 myMapOfLightPrograms.Clear();
586 myFontProgram.Nullify();
587 myBlitPrograms[0].Init (Handle(OpenGl_ShaderProgram)());
588 myBlitPrograms[1].Init (Handle(OpenGl_ShaderProgram)());
589 myBoundBoxProgram.Nullify();
590 myBoundBoxVertBuffer.Nullify();
591 for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter)
593 myStereoPrograms[aModeIter].Nullify();
595 switchLightPrograms();
598 // =======================================================================
600 // purpose : Creates new shader program
601 // =======================================================================
602 Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
603 TCollection_AsciiString& theShareKey,
604 Handle(OpenGl_ShaderProgram)& theProgram)
606 theProgram.Nullify();
607 if (theProxy.IsNull())
609 return Standard_False;
612 theShareKey = theProxy->GetId();
613 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
615 if (theProgram->Share())
617 myProgramList.Append (theProgram);
619 return Standard_True;
622 theProgram = new OpenGl_ShaderProgram (theProxy);
623 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
625 theProgram->Release (myContext);
627 theProgram.Nullify();
628 return Standard_False;
631 myProgramList.Append (theProgram);
632 myContext->ShareResource (theShareKey, theProgram);
633 return Standard_True;
636 // =======================================================================
637 // function : Unregister
638 // purpose : Removes specified shader program from the manager
639 // =======================================================================
640 void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
641 Handle(OpenGl_ShaderProgram)& theProgram)
643 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
645 if (anIt.Value() == theProgram)
647 if (!theProgram->UnShare())
650 theProgram.Nullify();
654 myProgramList.Remove (anIt);
659 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
662 myContext->DelayedRelease (theProgram);
663 theProgram.Nullify();
667 theProgram.Nullify();
668 myContext->ReleaseResource (anID, Standard_True);
672 // =======================================================================
673 // function : ShaderPrograms
674 // purpose : Returns list of registered shader programs
675 // =======================================================================
676 const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
678 return myProgramList;
681 // =======================================================================
683 // purpose : Returns true if no program objects are attached
684 // =======================================================================
685 Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
687 return myProgramList.IsEmpty();
690 // =======================================================================
691 // function : switchLightPrograms
693 // =======================================================================
694 void OpenGl_ShaderManager::switchLightPrograms()
696 const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources();
697 if (aLights.IsNull())
699 if (!myMapOfLightPrograms.Find ("unlit", myLightPrograms))
701 myLightPrograms = new OpenGl_SetOfShaderPrograms (myUnlitPrograms);
702 myMapOfLightPrograms.Bind ("unlit", myLightPrograms);
707 const TCollection_AsciiString aKey = genLightKey (aLights);
708 if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
710 myLightPrograms = new OpenGl_SetOfShaderPrograms();
711 myMapOfLightPrograms.Bind (aKey, myLightPrograms);
715 // =======================================================================
716 // function : UpdateSRgbState
718 // =======================================================================
719 void OpenGl_ShaderManager::UpdateSRgbState()
721 if (mySRgbState == myContext->ToRenderSRGB())
726 mySRgbState = myContext->ToRenderSRGB();
728 // special cases - GLSL programs dealing with sRGB/linearRGB internally
729 myStereoPrograms[Graphic3d_StereoMode_Anaglyph].Nullify();
732 // =======================================================================
733 // function : UpdateLightSourceStateTo
734 // purpose : Updates state of OCCT light sources
735 // =======================================================================
736 void OpenGl_ShaderManager::UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights,
737 Standard_Integer theSpecIBLMapLevels)
739 myLightSourceState.Set (theLights);
740 myLightSourceState.SetSpecIBLMapLevels (theSpecIBLMapLevels);
741 myLightSourceState.Update();
742 switchLightPrograms();
745 // =======================================================================
746 // function : UpdateLightSourceState
748 // =======================================================================
749 void OpenGl_ShaderManager::UpdateLightSourceState()
751 myLightSourceState.Update();
754 // =======================================================================
755 // function : SetShadingModel
757 // =======================================================================
758 void OpenGl_ShaderManager::SetShadingModel (const Graphic3d_TypeOfShadingModel theModel)
760 if (theModel == Graphic3d_TOSM_DEFAULT)
762 throw Standard_ProgramError ("OpenGl_ShaderManager::SetShadingModel() - attempt to set invalid Shading Model!");
765 myShadingModel = theModel;
766 switchLightPrograms();
769 // =======================================================================
770 // function : SetProjectionState
771 // purpose : Sets new state of OCCT projection transform
772 // =======================================================================
773 void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix)
775 myProjectionState.Set (theProjectionMatrix);
776 myProjectionState.Update();
779 // =======================================================================
780 // function : SetModelWorldState
781 // purpose : Sets new state of OCCT model-world transform
782 // =======================================================================
783 void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix)
785 myModelWorldState.Set (theModelWorldMatrix);
786 myModelWorldState.Update();
789 // =======================================================================
790 // function : SetWorldViewState
791 // purpose : Sets new state of OCCT world-view transform
792 // =======================================================================
793 void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix)
795 myWorldViewState.Set (theWorldViewMatrix);
796 myWorldViewState.Update();
799 // =======================================================================
800 // function : pushLightSourceState
802 // =======================================================================
803 void OpenGl_ShaderManager::pushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
805 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
806 if (theProgram == myFfpProgram)
808 #if !defined(GL_ES_VERSION_2_0)
809 if (myContext->core11 == NULL)
814 GLenum aLightGlId = GL_LIGHT0;
815 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
816 for (Graphic3d_LightSet::Iterator aLightIt (myLightSourceState.LightSources(), Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
817 aLightIt.More(); aLightIt.Next())
819 if (aLightGlId > GL_LIGHT7) // only 8 lights in FFP...
821 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
822 "Warning: light sources limit (8) has been exceeded within Fixed-function pipeline.");
826 bindLight (*aLightIt.Value(), aLightGlId, aModelView, myContext);
830 // apply accumulated ambient color
831 const Graphic3d_Vec4 anAmbient = !myLightSourceState.LightSources().IsNull()
832 ? myLightSourceState.LightSources()->AmbientColor()
833 : Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 1.0f);
834 myContext->core11->glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbient.GetData());
836 // GL_LIGHTING is managed by drawers to switch between shaded / no lighting output,
837 // therefore managing the state here does not have any effect - do it just for consistency.
838 if (aLightGlId != GL_LIGHT0)
840 ::glEnable (GL_LIGHTING);
844 ::glDisable (GL_LIGHTING);
846 // switch off unused lights
847 for (; aLightGlId <= GL_LIGHT7; ++aLightGlId)
849 ::glDisable (aLightGlId);
855 const Standard_Integer aNbLightsMax = theProgram->NbLightsMax();
856 const GLint anAmbientLoc = theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT);
857 if (aNbLightsMax == 0
858 && anAmbientLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
863 if (myLightTypeArray.Size() < aNbLightsMax)
865 myLightTypeArray .Resize (0, aNbLightsMax - 1, false);
866 myLightParamsArray.Resize (0, aNbLightsMax - 1, false);
868 for (Standard_Integer aLightIt = 0; aLightIt < aNbLightsMax; ++aLightIt)
870 myLightTypeArray.ChangeValue (aLightIt).Type = -1;
873 if (myLightSourceState.LightSources().IsNull()
874 || myLightSourceState.LightSources()->IsEmpty())
876 theProgram->SetUniform (myContext,
877 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
879 theProgram->SetUniform (myContext,
881 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
882 theProgram->SetUniform (myContext,
883 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
884 aNbLightsMax * OpenGl_ShaderLightType::NbOfVec2i(),
885 myLightTypeArray.First().Packed());
889 Standard_Integer aLightsNb = 0;
890 for (Graphic3d_LightSet::Iterator anIter (myLightSourceState.LightSources(), Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
891 anIter.More(); anIter.Next())
893 const Graphic3d_CLight& aLight = *anIter.Value();
894 if (aLightsNb >= aNbLightsMax)
896 if (aNbLightsMax != 0)
898 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
899 TCollection_AsciiString("Warning: light sources limit (") + aNbLightsMax + ") has been exceeded.");
904 OpenGl_ShaderLightType& aLightType = myLightTypeArray.ChangeValue (aLightsNb);
905 OpenGl_ShaderLightParameters& aLightParams = myLightParamsArray.ChangeValue (aLightsNb);
906 if (!aLight.IsEnabled()) // has no affect with Graphic3d_LightSet::IterationFilter_ExcludeDisabled - here just for consistency
908 // 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
909 aLightType.Type = -1; // Graphic3d_TOLS_AMBIENT can be used instead
910 aLightType.IsHeadlight = false;
911 aLightParams.Color = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f);
916 // ignoring OpenGl_Context::ToRenderSRGB() for light colors,
917 // as non-absolute colors for lights are rare and require tuning anyway
918 aLightType.Type = aLight.Type();
919 aLightType.IsHeadlight = aLight.IsHeadlight();
920 aLightParams.Color = aLight.PackedColor();
921 aLightParams.Color.a() = aLight.Intensity(); // used by PBR and ignored by old shading model
922 if (aLight.Type() == Graphic3d_TOLS_DIRECTIONAL)
924 aLightParams.Position = -aLight.PackedDirection();
926 else if (!aLight.IsHeadlight())
928 aLightParams.Position.x() = static_cast<float>(aLight.Position().X() - myLocalOrigin.X());
929 aLightParams.Position.y() = static_cast<float>(aLight.Position().Y() - myLocalOrigin.Y());
930 aLightParams.Position.z() = static_cast<float>(aLight.Position().Z() - myLocalOrigin.Z());
931 aLightParams.Position.w() = 1.0f;
935 aLightParams.Position.x() = static_cast<float>(aLight.Position().X());
936 aLightParams.Position.y() = static_cast<float>(aLight.Position().Y());
937 aLightParams.Position.z() = static_cast<float>(aLight.Position().Z());
938 aLightParams.Position.w() = 1.0f;
941 if (aLight.Type() == Graphic3d_TOLS_SPOT)
943 aLightParams.Direction = aLight.PackedDirection();
945 aLightParams.Parameters = aLight.PackedParams();
949 const Graphic3d_Vec4& anAmbient = myLightSourceState.LightSources()->AmbientColor();
950 theProgram->SetUniform (myContext,
951 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
953 theProgram->SetUniform (myContext,
956 theProgram->SetUniform (myContext,
957 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
958 aNbLightsMax * OpenGl_ShaderLightType::NbOfVec2i(),
959 myLightTypeArray.First().Packed());
962 theProgram->SetUniform (myContext,
963 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
964 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
965 myLightParamsArray.First().Packed());
968 if (const OpenGl_ShaderUniformLocation aLocation = theProgram->GetStateLocation (OpenGl_OCCT_NB_SPEC_IBL_LEVELS))
970 theProgram->SetUniform (myContext, aLocation, myLightSourceState.SpecIBLMapLevels());
974 // =======================================================================
975 // function : pushProjectionState
977 // =======================================================================
978 void OpenGl_ShaderManager::pushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
980 theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
981 if (theProgram == myFfpProgram)
983 #if !defined(GL_ES_VERSION_2_0)
984 if (myContext->core11 != NULL)
986 myContext->core11->glMatrixMode (GL_PROJECTION);
987 myContext->core11->glLoadMatrixf (myProjectionState.ProjectionMatrix());
993 theProgram->SetUniform (myContext,
994 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
995 myProjectionState.ProjectionMatrix());
997 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
998 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
1000 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
1003 theProgram->SetUniform (myContext,
1004 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
1005 myProjectionState.ProjectionMatrix(), true);
1007 aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
1008 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
1010 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
1014 // =======================================================================
1015 // function : pushModelWorldState
1017 // =======================================================================
1018 void OpenGl_ShaderManager::pushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1020 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
1021 if (theProgram == myFfpProgram)
1023 #if !defined(GL_ES_VERSION_2_0)
1024 if (myContext->core11 != NULL)
1026 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
1027 myContext->core11->glMatrixMode (GL_MODELVIEW);
1028 myContext->core11->glLoadMatrixf (aModelView.GetData());
1029 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
1035 theProgram->SetUniform (myContext,
1036 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
1037 myModelWorldState.ModelWorldMatrix());
1039 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
1040 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
1042 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
1045 theProgram->SetUniform (myContext,
1046 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
1047 myModelWorldState.ModelWorldMatrix(), true);
1049 aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
1050 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
1052 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
1056 // =======================================================================
1057 // function : pushWorldViewState
1059 // =======================================================================
1060 void OpenGl_ShaderManager::pushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1062 if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
1067 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
1068 if (theProgram == myFfpProgram)
1070 #if !defined(GL_ES_VERSION_2_0)
1071 if (myContext->core11 != NULL)
1073 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
1074 myContext->core11->glMatrixMode (GL_MODELVIEW);
1075 myContext->core11->glLoadMatrixf (aModelView.GetData());
1076 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
1082 theProgram->SetUniform (myContext,
1083 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
1084 myWorldViewState.WorldViewMatrix());
1086 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
1087 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
1089 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
1092 theProgram->SetUniform (myContext,
1093 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
1094 myWorldViewState.WorldViewMatrix(), true);
1096 aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
1097 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
1099 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
1103 // =======================================================================
1104 // function : UpdateClippingState
1105 // purpose : Updates state of OCCT clipping planes
1106 // =======================================================================
1107 void OpenGl_ShaderManager::UpdateClippingState()
1109 myClippingState.Update();
1112 // =======================================================================
1113 // function : RevertClippingState
1114 // purpose : Reverts state of OCCT clipping planes
1115 // =======================================================================
1116 void OpenGl_ShaderManager::RevertClippingState()
1118 myClippingState.Revert();
1121 // =======================================================================
1122 // function : pushClippingState
1124 // =======================================================================
1125 void OpenGl_ShaderManager::pushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1127 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
1128 if (theProgram == myFfpProgram)
1130 #if !defined(GL_ES_VERSION_2_0)
1131 if (myContext->core11 == NULL)
1136 const Standard_Integer aNbMaxPlanes = myContext->MaxClipPlanes();
1137 if (myClipPlaneArrayFfp.Size() < aNbMaxPlanes)
1139 myClipPlaneArrayFfp.Resize (0, aNbMaxPlanes - 1, false);
1142 Standard_Integer aPlaneId = 0;
1143 Standard_Boolean toRestoreModelView = Standard_False;
1144 const Handle(Graphic3d_ClipPlane)& aCappedChain = myContext->Clipping().CappedChain();
1145 for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
1147 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
1148 if (aPlaneIter.IsDisabled()
1149 || aPlane->IsChain()
1150 || (aPlane == aCappedChain
1151 && myContext->Clipping().IsCappingEnableAllExcept()))
1155 else if (aPlaneId >= aNbMaxPlanes)
1157 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
1158 TCollection_ExtendedString("Warning: clipping planes limit (") + aNbMaxPlanes + ") has been exceeded.");
1162 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
1163 OpenGl_Vec4d& aPlaneEq = myClipPlaneArrayFfp.ChangeValue (aPlaneId);
1164 aPlaneEq.x() = anEquation.x();
1165 aPlaneEq.y() = anEquation.y();
1166 aPlaneEq.z() = anEquation.z();
1167 aPlaneEq.w() = anEquation.w();
1168 if (myHasLocalOrigin)
1170 const gp_XYZ aPos = aPlane->ToPlane().Position().Location().XYZ() - myLocalOrigin;
1171 const Standard_Real aD = -(anEquation.x() * aPos.X() + anEquation.y() * aPos.Y() + anEquation.z() * aPos.Z());
1175 const GLenum anFfpPlaneID = GL_CLIP_PLANE0 + aPlaneId;
1176 if (anFfpPlaneID == GL_CLIP_PLANE0)
1178 // set either identity or pure view matrix
1179 toRestoreModelView = Standard_True;
1180 myContext->core11->glMatrixMode (GL_MODELVIEW);
1181 myContext->core11->glLoadMatrixf (myWorldViewState.WorldViewMatrix().GetData());
1184 ::glEnable (anFfpPlaneID);
1185 myContext->core11->glClipPlane (anFfpPlaneID, aPlaneEq);
1190 // switch off unused lights
1191 for (; aPlaneId < aNbMaxPlanes; ++aPlaneId)
1193 ::glDisable (GL_CLIP_PLANE0 + aPlaneId);
1196 // restore combined model-view matrix
1197 if (toRestoreModelView)
1199 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
1200 myContext->core11->glLoadMatrixf (aModelView.GetData());
1206 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
1207 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION)
1212 const Standard_Integer aNbClipPlanesMax = theProgram->NbClipPlanesMax();
1213 const Standard_Integer aNbPlanes = Min (myContext->Clipping().NbClippingOrCappingOn(), aNbClipPlanesMax);
1216 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), 0);
1220 if (myClipPlaneArray.Size() < aNbClipPlanesMax)
1222 myClipPlaneArray.Resize (0, aNbClipPlanesMax - 1, false);
1223 myClipChainArray.Resize (0, aNbClipPlanesMax - 1, false);
1226 Standard_Integer aPlaneId = 0;
1227 const Handle(Graphic3d_ClipPlane)& aCappedChain = myContext->Clipping().CappedChain();
1228 for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
1230 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
1231 if (aPlaneIter.IsDisabled())
1236 if (myContext->Clipping().IsCappingDisableAllExcept())
1238 // enable only specific (sub) plane
1239 if (aPlane != aCappedChain)
1244 Standard_Integer aSubPlaneIndex = 1;
1245 for (const Graphic3d_ClipPlane* aSubPlaneIter = aCappedChain.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex)
1247 if (aSubPlaneIndex == myContext->Clipping().CappedSubPlane())
1249 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->GetEquation(), 1);
1255 else if (aPlane == aCappedChain) // && myContext->Clipping().IsCappingEnableAllExcept()
1257 // enable sub-planes within processed Chain as reversed and ORed, excluding filtered plane
1258 if (aPlaneId + aPlane->NbChainNextPlanes() - 1 > aNbClipPlanesMax)
1260 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
1261 TCollection_AsciiString("Error: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded.");
1265 Standard_Integer aSubPlaneIndex = 1;
1266 for (const Graphic3d_ClipPlane* aSubPlaneIter = aPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex)
1268 if (aSubPlaneIndex != -myContext->Clipping().CappedSubPlane())
1270 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->ReversedEquation(), 1);
1277 if (aPlaneId + aPlane->NbChainNextPlanes() > aNbClipPlanesMax)
1279 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
1280 TCollection_AsciiString("Error: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded.");
1283 for (const Graphic3d_ClipPlane* aSubPlaneIter = aPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get())
1285 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->GetEquation(), aSubPlaneIter->NbChainNextPlanes());
1290 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), aPlaneId);
1291 theProgram->SetUniform (myContext, aLocEquations, aNbClipPlanesMax, &myClipPlaneArray.First());
1292 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_CHAINS), aNbClipPlanesMax, &myClipChainArray.First());
1295 // =======================================================================
1296 // function : pushMaterialState
1298 // =======================================================================
1299 void OpenGl_ShaderManager::pushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1301 const OpenGl_Material& aFrontMat = myMaterialState.FrontMaterial();
1302 const OpenGl_Material& aBackMat = myMaterialState.BackMaterial();
1303 theProgram->UpdateState (OpenGl_MATERIAL_STATE, myMaterialState.Index());
1304 if (theProgram == myFfpProgram)
1306 #if !defined(GL_ES_VERSION_2_0)
1307 if (myContext->core11 == NULL)
1312 if (myMaterialState.AlphaCutoff() < ShortRealLast())
1314 glAlphaFunc (GL_GEQUAL, myMaterialState.AlphaCutoff());
1315 glEnable (GL_ALPHA_TEST);
1319 glDisable (GL_ALPHA_TEST);
1322 const GLenum aFrontFace = myMaterialState.ToDistinguish() ? GL_FRONT : GL_FRONT_AND_BACK;
1323 myContext->core11->glMaterialfv(aFrontFace, GL_AMBIENT, aFrontMat.Common.Ambient.GetData());
1324 myContext->core11->glMaterialfv(aFrontFace, GL_DIFFUSE, aFrontMat.Common.Diffuse.GetData());
1325 myContext->core11->glMaterialfv(aFrontFace, GL_SPECULAR, aFrontMat.Common.Specular.GetData());
1326 myContext->core11->glMaterialfv(aFrontFace, GL_EMISSION, aFrontMat.Common.Emission.GetData());
1327 myContext->core11->glMaterialf (aFrontFace, GL_SHININESS, aFrontMat.Common.Shine());
1328 if (myMaterialState.ToDistinguish())
1330 myContext->core11->glMaterialfv(GL_BACK, GL_AMBIENT, aBackMat.Common.Ambient.GetData());
1331 myContext->core11->glMaterialfv(GL_BACK, GL_DIFFUSE, aBackMat.Common.Diffuse.GetData());
1332 myContext->core11->glMaterialfv(GL_BACK, GL_SPECULAR, aBackMat.Common.Specular.GetData());
1333 myContext->core11->glMaterialfv(GL_BACK, GL_EMISSION, aBackMat.Common.Emission.GetData());
1334 myContext->core11->glMaterialf (GL_BACK, GL_SHININESS, aBackMat.Common.Shine());
1340 theProgram->SetUniform (myContext,
1341 theProgram->GetStateLocation (OpenGl_OCCT_ALPHA_CUTOFF),
1342 myMaterialState.AlphaCutoff());
1343 theProgram->SetUniform (myContext,
1344 theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
1345 myMaterialState.ToMapTexture() ? 1 : 0);
1346 theProgram->SetUniform (myContext,
1347 theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
1348 myMaterialState.ToDistinguish() ? 1 : 0);
1350 if (const OpenGl_ShaderUniformLocation& aLocPbrFront = theProgram->GetStateLocation (OpenGl_OCCT_PBR_FRONT_MATERIAL))
1352 theProgram->SetUniform (myContext, aLocPbrFront, OpenGl_MaterialPBR::NbOfVec4(),
1353 aFrontMat.Pbr.Packed());
1355 if (const OpenGl_ShaderUniformLocation aLocPbrBack = theProgram->GetStateLocation (OpenGl_OCCT_PBR_BACK_MATERIAL))
1357 theProgram->SetUniform (myContext, aLocPbrBack, OpenGl_MaterialPBR::NbOfVec4(),
1358 aBackMat.Pbr.Packed());
1360 if (const OpenGl_ShaderUniformLocation aLocFront = theProgram->GetStateLocation (OpenGl_OCCT_COMMON_FRONT_MATERIAL))
1362 theProgram->SetUniform (myContext, aLocFront, OpenGl_MaterialCommon::NbOfVec4(),
1363 aFrontMat.Common.Packed());
1365 if (const OpenGl_ShaderUniformLocation aLocBack = theProgram->GetStateLocation (OpenGl_OCCT_COMMON_BACK_MATERIAL))
1367 theProgram->SetUniform (myContext, aLocBack, OpenGl_MaterialCommon::NbOfVec4(),
1368 aBackMat.Common.Packed());
1372 // =======================================================================
1373 // function : pushOitState
1375 // =======================================================================
1376 void OpenGl_ShaderManager::pushOitState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1378 const GLint aLocOutput = theProgram->GetStateLocation (OpenGl_OCCT_OIT_OUTPUT);
1379 if (aLocOutput != OpenGl_ShaderProgram::INVALID_LOCATION)
1381 theProgram->SetUniform (myContext, aLocOutput, myOitState.ToEnableWrite());
1384 const GLint aLocDepthFactor = theProgram->GetStateLocation (OpenGl_OCCT_OIT_DEPTH_FACTOR);
1385 if (aLocDepthFactor != OpenGl_ShaderProgram::INVALID_LOCATION)
1387 theProgram->SetUniform (myContext, aLocDepthFactor, myOitState.DepthFactor());
1391 // =======================================================================
1392 // function : PushInteriorState
1394 // =======================================================================
1395 void OpenGl_ShaderManager::PushInteriorState (const Handle(OpenGl_ShaderProgram)& theProgram,
1396 const Handle(Graphic3d_Aspects)& theAspect) const
1398 if (theProgram.IsNull()
1399 || !theProgram->IsValid())
1404 if (const OpenGl_ShaderUniformLocation aLocLineWidth = theProgram->GetStateLocation (OpenGl_OCCT_LINE_WIDTH))
1406 theProgram->SetUniform (myContext, aLocLineWidth, theAspect->EdgeWidth() * myContext->LineWidthScale());
1407 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCCT_LINE_FEATHER), myContext->LineFeather() * myContext->LineWidthScale());
1409 if (const OpenGl_ShaderUniformLocation aLocWireframeColor = theProgram->GetStateLocation (OpenGl_OCCT_WIREFRAME_COLOR))
1411 if (theAspect->InteriorStyle() == Aspect_IS_HOLLOW)
1413 theProgram->SetUniform (myContext, aLocWireframeColor, OpenGl_Vec4 (-1.0f, -1.0f, -1.0f, -1.0f));
1417 theProgram->SetUniform (myContext, aLocWireframeColor, myContext->Vec4FromQuantityColor (theAspect->EdgeColorRGBA()));
1420 if (const OpenGl_ShaderUniformLocation aLocQuadModeState = theProgram->GetStateLocation (OpenGl_OCCT_QUAD_MODE_STATE))
1422 theProgram->SetUniform (myContext, aLocQuadModeState, theAspect->ToSkipFirstEdge() ? 1 : 0);
1426 // =======================================================================
1427 // function : PushState
1428 // purpose : Pushes state of OCCT graphics parameters to the program
1429 // =======================================================================
1430 void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1432 const Handle(OpenGl_ShaderProgram)& aProgram = !theProgram.IsNull() ? theProgram : myFfpProgram;
1433 PushClippingState (aProgram);
1434 PushWorldViewState (aProgram);
1435 PushModelWorldState (aProgram);
1436 PushProjectionState (aProgram);
1437 PushLightSourceState (aProgram);
1438 PushMaterialState (aProgram);
1439 PushOitState (aProgram);
1441 if (!theProgram.IsNull())
1443 if (const OpenGl_ShaderUniformLocation& aLocViewPort = theProgram->GetStateLocation (OpenGl_OCCT_VIEWPORT))
1445 theProgram->SetUniform (myContext, aLocViewPort, OpenGl_Vec4 ((float )myContext->Viewport()[0], (float )myContext->Viewport()[1],
1446 (float )myContext->Viewport()[2], (float )myContext->Viewport()[3]));
1451 // =======================================================================
1452 // function : prepareStdProgramFont
1454 // =======================================================================
1455 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
1457 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1458 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT));
1459 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1461 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
1464 EOL" TexCoord = occTexCoord.st;"
1465 + THE_VERT_gl_Position
1468 TCollection_AsciiString
1469 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).a; }";
1470 #if !defined(GL_ES_VERSION_2_0)
1471 if (myContext->core11 == NULL)
1473 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).r; }";
1477 TCollection_AsciiString aSrcFrag =
1481 EOL" vec4 aColor = occColor;"
1482 EOL" aColor.a *= getAlpha();"
1483 EOL" if (aColor.a <= 0.285) discard;"
1484 EOL" occSetFragColor (aColor);"
1487 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1488 defaultGlslVersion (aProgramSrc, "font", 0);
1489 aProgramSrc->SetDefaultSampler (false);
1490 aProgramSrc->SetNbLightsMax (0);
1491 aProgramSrc->SetNbClipPlanesMax (0);
1492 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1493 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
1494 TCollection_AsciiString aKey;
1495 if (!Create (aProgramSrc, aKey, myFontProgram))
1497 myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1498 return Standard_False;
1500 return Standard_True;
1503 // =======================================================================
1504 // function : BindFboBlitProgram
1506 // =======================================================================
1507 Standard_Boolean OpenGl_ShaderManager::BindFboBlitProgram (Standard_Integer theNbSamples,
1508 Standard_Boolean theIsFallback_sRGB)
1510 NCollection_Array1<Handle(OpenGl_ShaderProgram)>& aList = myBlitPrograms[theIsFallback_sRGB ? 1 : 0];
1511 Standard_Integer aNbSamples = Max (theNbSamples, 1);
1512 if (aNbSamples > aList.Upper())
1514 aList.Resize (1, aNbSamples, true);
1517 Handle(OpenGl_ShaderProgram)& aProg = aList[aNbSamples];
1520 prepareStdProgramFboBlit (aProg, aNbSamples, theIsFallback_sRGB);
1522 return !aProg.IsNull()
1523 && myContext->BindProgram (aProg);
1526 // =======================================================================
1527 // function : prepareStdProgramFboBlit
1529 // =======================================================================
1530 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit (Handle(OpenGl_ShaderProgram)& theProgram,
1531 Standard_Integer theNbSamples,
1532 Standard_Boolean theIsFallback_sRGB)
1534 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1535 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1537 TCollection_AsciiString aSrcVert =
1540 EOL" TexCoord = occVertex.zw;"
1541 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1544 TCollection_AsciiString aSrcFrag;
1545 if (theNbSamples > 1)
1547 #if defined(GL_ES_VERSION_2_0)
1548 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("highp sampler2DMS uColorSampler", Graphic3d_TOS_FRAGMENT));
1549 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("highp sampler2DMS uDepthSampler", Graphic3d_TOS_FRAGMENT));
1551 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uColorSampler", Graphic3d_TOS_FRAGMENT));
1552 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uDepthSampler", Graphic3d_TOS_FRAGMENT));
1554 aSrcFrag = TCollection_AsciiString()
1555 + EOL"#define THE_NUM_SAMPLES " + theNbSamples
1556 + (theIsFallback_sRGB ? EOL"#define THE_SHIFT_sRGB" : "")
1559 EOL" ivec2 aSize = textureSize (uColorSampler);"
1560 EOL" ivec2 anUV = ivec2 (vec2 (aSize) * TexCoord);"
1561 EOL" gl_FragDepth = texelFetch (uDepthSampler, anUV, THE_NUM_SAMPLES / 2 - 1).r;"
1563 EOL" vec4 aColor = vec4 (0.0);"
1564 EOL" for (int aSample = 0; aSample < THE_NUM_SAMPLES; ++aSample)"
1566 EOL" vec4 aVal = texelFetch (uColorSampler, anUV, aSample);"
1567 EOL" aColor += aVal;"
1569 EOL" aColor /= float(THE_NUM_SAMPLES);"
1570 EOL"#ifdef THE_SHIFT_sRGB"
1571 EOL" aColor.rgb = pow (aColor.rgb, vec3 (1.0 / 2.2));"
1573 EOL" occSetFragColor (aColor);"
1578 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uColorSampler", Graphic3d_TOS_FRAGMENT));
1579 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uDepthSampler", Graphic3d_TOS_FRAGMENT));
1580 aSrcFrag = TCollection_AsciiString()
1581 + (theIsFallback_sRGB ? EOL"#define THE_SHIFT_sRGB" : "")
1584 EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;"
1585 EOL" vec4 aColor = occTexture2D (uColorSampler, TexCoord);"
1586 EOL"#ifdef THE_SHIFT_sRGB"
1587 EOL" aColor.rgb = pow (aColor.rgb, vec3 (1.0 / 2.2));"
1589 EOL" occSetFragColor (aColor);"
1593 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1594 #if defined(GL_ES_VERSION_2_0)
1595 if (myContext->IsGlGreaterEqual (3, 1))
1597 // required for MSAA sampler
1598 aProgramSrc->SetHeader ("#version 310 es");
1600 else if (myContext->IsGlGreaterEqual (3, 0))
1602 aProgramSrc->SetHeader ("#version 300 es");
1604 else if (myContext->extFragDepth)
1606 aProgramSrc->SetHeader ("#extension GL_EXT_frag_depth : enable"
1607 EOL"#define gl_FragDepth gl_FragDepthEXT");
1611 // there is no way to draw into depth buffer
1615 EOL" occSetFragColor (occTexture2D (uColorSampler, TexCoord));"
1619 if (myContext->core32 != NULL)
1621 aProgramSrc->SetHeader ("#version 150");
1624 TCollection_AsciiString anId = "occt_blit";
1625 if (theNbSamples > 1)
1627 anId += TCollection_AsciiString ("_msaa") + theNbSamples;
1629 if (theIsFallback_sRGB)
1633 aProgramSrc->SetId (anId);
1634 aProgramSrc->SetDefaultSampler (false);
1635 aProgramSrc->SetNbLightsMax (0);
1636 aProgramSrc->SetNbClipPlanesMax (0);
1637 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1638 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
1639 TCollection_AsciiString aKey;
1640 if (!Create (aProgramSrc, aKey, theProgram))
1642 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1643 return Standard_False;
1646 myContext->BindProgram (theProgram);
1647 theProgram->SetSampler (myContext, "uColorSampler", Graphic3d_TextureUnit_0);
1648 theProgram->SetSampler (myContext, "uDepthSampler", Graphic3d_TextureUnit_1);
1649 myContext->BindProgram (NULL);
1650 return Standard_True;
1653 // =======================================================================
1654 // function : prepareStdProgramOitCompositing
1656 // =======================================================================
1657 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const Standard_Boolean theMsaa)
1659 Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram[theMsaa ? 1 : 0];
1660 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1661 TCollection_AsciiString aSrcVert, aSrcFrag;
1663 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1664 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1669 EOL" TexCoord = occVertex.zw;"
1670 EOL" gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);"
1675 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uAccumTexture", Graphic3d_TOS_FRAGMENT));
1676 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uWeightTexture", Graphic3d_TOS_FRAGMENT));
1680 EOL" vec4 aAccum = occTexture2D (uAccumTexture, TexCoord);"
1681 EOL" float aWeight = occTexture2D (uWeightTexture, TexCoord).r;"
1682 EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
1684 #if !defined(GL_ES_VERSION_2_0)
1685 if (myContext->IsGlGreaterEqual (3, 2))
1687 aProgramSrc->SetHeader ("#version 150");
1690 if (myContext->IsGlGreaterEqual (3, 0))
1692 aProgramSrc->SetHeader ("#version 300 es");
1698 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uAccumTexture", Graphic3d_TOS_FRAGMENT));
1699 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uWeightTexture", Graphic3d_TOS_FRAGMENT));
1703 EOL" ivec2 aTexel = ivec2 (vec2 (textureSize (uAccumTexture)) * TexCoord);"
1704 EOL" vec4 aAccum = texelFetch (uAccumTexture, aTexel, gl_SampleID);"
1705 EOL" float aWeight = texelFetch (uWeightTexture, aTexel, gl_SampleID).r;"
1706 EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
1708 #if !defined(GL_ES_VERSION_2_0)
1709 if (myContext->IsGlGreaterEqual (4, 0))
1711 aProgramSrc->SetHeader ("#version 400");
1714 if (myContext->IsGlGreaterEqual (3, 2))
1716 aProgramSrc->SetHeader ("#version 320 es");
1718 else if (myContext->IsGlGreaterEqual (3, 0))
1720 aProgramSrc->SetHeader ("#version 300 es"); // with GL_OES_sample_variables extension
1725 aProgramSrc->SetId (theMsaa ? "occt_weight-oit-msaa" : "occt_weight-oit");
1726 aProgramSrc->SetDefaultSampler (false);
1727 aProgramSrc->SetNbLightsMax (0);
1728 aProgramSrc->SetNbClipPlanesMax (0);
1729 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1730 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
1731 TCollection_AsciiString aKey;
1732 if (!Create (aProgramSrc, aKey, aProgram))
1734 aProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1735 return Standard_False;
1738 myContext->BindProgram (aProgram);
1739 aProgram->SetSampler (myContext, "uAccumTexture", Graphic3d_TextureUnit_0);
1740 aProgram->SetSampler (myContext, "uWeightTexture", Graphic3d_TextureUnit_1);
1741 myContext->BindProgram (Handle(OpenGl_ShaderProgram)());
1742 return Standard_True;
1745 // =======================================================================
1746 // function : pointSpriteAlphaSrc
1748 // =======================================================================
1749 TCollection_AsciiString OpenGl_ShaderManager::pointSpriteAlphaSrc (Standard_Integer theBits)
1751 TCollection_AsciiString aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ").a; }";
1752 #if !defined(GL_ES_VERSION_2_0)
1753 if (myContext->core11 == NULL
1754 && (theBits & OpenGl_PO_PointSpriteA) == OpenGl_PO_PointSpriteA)
1756 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ").r; }";
1761 return aSrcGetAlpha;
1764 // =======================================================================
1765 // function : defaultGlslVersion
1767 // =======================================================================
1768 int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram,
1769 const TCollection_AsciiString& theName,
1771 bool theUsesDerivates) const
1773 int aBits = theBits;
1774 const bool toUseDerivates = theUsesDerivates
1775 || (theBits & OpenGl_PO_StippleLine) != 0
1776 || (theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureNormal;
1777 #if !defined(GL_ES_VERSION_2_0)
1778 if (myContext->core32 != NULL)
1780 theProgram->SetHeader ("#version 150");
1784 if ((theBits & OpenGl_PO_StippleLine) != 0
1785 || theProgram->IsPBR())
1787 if (myContext->IsGlGreaterEqual (3, 0))
1789 theProgram->SetHeader ("#version 130");
1791 else if (myContext->CheckExtension ("GL_EXT_gpu_shader4")) // myContext->hasGlslBitwiseOps == OpenGl_FeatureInExtensions
1793 // GL_EXT_gpu_shader4 defines GLSL type "unsigned int", while core GLSL specs define type "uint"
1794 theProgram->SetHeader ("#extension GL_EXT_gpu_shader4 : enable\n"
1795 "#define uint unsigned int");
1799 (void )toUseDerivates;
1802 #if defined(__EMSCRIPTEN__)
1803 if (myContext->IsGlGreaterEqual (3, 0))
1805 // consider this is browser responsibility to provide working WebGL 2.0 implementation
1806 // and black-list broken drivers (there is no OpenGL ES greater than 3.0)
1807 theProgram->SetHeader ("#version 300 es");
1810 // prefer "100 es" on OpenGL ES 3.0- devices (save the features unavailable before "300 es")
1811 // and "300 es" on OpenGL ES 3.1+ devices
1812 if (myContext->IsGlGreaterEqual (3, 1))
1814 if ((theBits & OpenGl_PO_NeedsGeomShader) != 0)
1816 theProgram->SetHeader (myContext->hasGeometryStage != OpenGl_FeatureInExtensions ? "#version 320 es" : "#version 310 es");
1820 theProgram->SetHeader ("#version 300 es");
1825 if (theProgram->IsPBR()
1826 && myContext->IsGlGreaterEqual (3, 0))
1828 theProgram->SetHeader ("#version 300 es");
1830 if ((theBits & OpenGl_PO_WriteOit) != 0
1831 || (theBits & OpenGl_PO_StippleLine) != 0)
1833 if (myContext->IsGlGreaterEqual (3, 0))
1835 theProgram->SetHeader ("#version 300 es");
1839 aBits = aBits & ~OpenGl_PO_WriteOit;
1840 if (!myContext->oesStdDerivatives)
1842 aBits = aBits & ~OpenGl_PO_StippleLine;
1848 if (myContext->IsGlGreaterEqual (3, 0))
1850 theProgram->SetHeader ("#version 300 es");
1852 else if (myContext->oesStdDerivatives)
1854 theProgram->SetHeader ("#extension GL_OES_standard_derivatives : enable");
1860 // should fit OpenGl_PO_NB
1862 Sprintf (aBitsStr, "%04x", aBits);
1863 theProgram->SetId (TCollection_AsciiString ("occt_") + theName + aBitsStr);
1867 // =======================================================================
1868 // function : prepareGeomMainSrc
1870 // =======================================================================
1871 TCollection_AsciiString OpenGl_ShaderManager::prepareGeomMainSrc (OpenGl_ShaderObject::ShaderVariableList& theUnifoms,
1872 OpenGl_ShaderObject::ShaderVariableList& theStageInOuts,
1873 Standard_Integer theBits)
1875 if ((theBits & OpenGl_PO_NeedsGeomShader) == 0)
1877 return TCollection_AsciiString();
1880 TCollection_AsciiString aSrcMainGeom =
1884 if ((theBits & OpenGl_PO_MeshEdges) != 0)
1886 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occViewport", Graphic3d_TOS_GEOMETRY));
1887 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("bool occIsQuadMode", Graphic3d_TOS_GEOMETRY));
1888 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineWidth", Graphic3d_TOS_GEOMETRY));
1889 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineWidth", Graphic3d_TOS_FRAGMENT));
1890 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineFeather", Graphic3d_TOS_FRAGMENT));
1891 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occWireframeColor", Graphic3d_TOS_FRAGMENT));
1892 theStageInOuts.Append(OpenGl_ShaderObject::ShaderVariable ("vec3 EdgeDistance", Graphic3d_TOS_GEOMETRY | Graphic3d_TOS_FRAGMENT));
1894 aSrcMainGeom = TCollection_AsciiString()
1895 + EOL"vec3 ViewPortTransform (vec4 theVec)"
1897 EOL" vec3 aWinCoord = theVec.xyz / theVec.w;"
1898 EOL" aWinCoord = aWinCoord * 0.5 + 0.5;"
1899 EOL" aWinCoord.xy = aWinCoord.xy * occViewport.zw + occViewport.xy;"
1900 EOL" return aWinCoord;"
1903 + EOL" vec3 aSideA = ViewPortTransform (gl_in[2].gl_Position) - ViewPortTransform (gl_in[1].gl_Position);"
1904 EOL" vec3 aSideB = ViewPortTransform (gl_in[2].gl_Position) - ViewPortTransform (gl_in[0].gl_Position);"
1905 EOL" vec3 aSideC = ViewPortTransform (gl_in[1].gl_Position) - ViewPortTransform (gl_in[0].gl_Position);"
1906 EOL" float aQuadArea = abs (aSideB.x * aSideC.y - aSideB.y * aSideC.x);"
1907 EOL" vec3 aLenABC = vec3 (length (aSideA), length (aSideB), length (aSideC));"
1908 EOL" vec3 aHeightABC = vec3 (aQuadArea) / aLenABC;"
1909 EOL" aHeightABC = max (aHeightABC, vec3 (10.0 * occLineWidth));" // avoid shrunk presentation disappearing at distance
1910 EOL" float aQuadModeHeightC = occIsQuadMode ? occLineWidth + 1.0 : 0.0;";
1913 for (Standard_Integer aVertIter = 0; aVertIter < 3; ++aVertIter)
1915 const TCollection_AsciiString aVertIndex (aVertIter);
1916 // pass variables from Vertex shader to Fragment shader through Geometry shader
1917 for (OpenGl_ShaderObject::ShaderVariableList::Iterator aVarListIter (theStageInOuts); aVarListIter.More(); aVarListIter.Next())
1919 if (aVarListIter.Value().Stages == (Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT))
1921 const TCollection_AsciiString aVarName = aVarListIter.Value().Name.Token (" ", 2);
1922 aSrcMainGeom += TCollection_AsciiString()
1923 + EOL" geomOut." + aVarName + " = geomIn[" + aVertIndex + "]." + aVarName + ";";
1927 if ((theBits & OpenGl_PO_MeshEdges) != 0)
1931 case 0: aSrcMainGeom += EOL" EdgeDistance = vec3 (aHeightABC[0], 0.0, aQuadModeHeightC);"; break;
1932 case 1: aSrcMainGeom += EOL" EdgeDistance = vec3 (0.0, aHeightABC[1], aQuadModeHeightC);"; break;
1933 case 2: aSrcMainGeom += EOL" EdgeDistance = vec3 (0.0, 0.0, aHeightABC[2]);"; break;
1936 aSrcMainGeom += TCollection_AsciiString()
1937 + EOL" gl_Position = gl_in[" + aVertIndex + "].gl_Position;"
1938 EOL" EmitVertex();";
1941 EOL" EndPrimitive();"
1944 return aSrcMainGeom;
1947 // =======================================================================
1948 // function : prepareStdProgramUnlit
1950 // =======================================================================
1951 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_ShaderProgram)& theProgram,
1952 Standard_Integer theBits,
1953 Standard_Boolean theIsOutline)
1955 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1956 TCollection_AsciiString aSrcVert, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha, aSrcVertEndMain;
1957 TCollection_AsciiString aSrcFrag, aSrcFragExtraMain;
1958 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
1959 TCollection_AsciiString aSrcFragMainGetColor = EOL" occSetFragColor (getFinalColor());";
1960 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1962 if ((theBits & OpenGl_PO_IsPoint) != 0)
1964 #if defined(GL_ES_VERSION_2_0)
1965 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1968 if ((theBits & OpenGl_PO_PointSprite) != 0)
1970 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT));
1971 if ((theBits & OpenGl_PO_PointSpriteA) != OpenGl_PO_PointSpriteA)
1974 EOL"vec4 getColor(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord "); }";
1976 else if ((theBits & OpenGl_PO_TextureRGB) != 0
1977 && (theBits & OpenGl_PO_VertColor) == 0)
1979 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
1980 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX));
1981 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1982 aSrcVertExtraMain +=
1983 EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);";
1985 EOL"vec4 getColor(void) { return VertColor; }";
1988 aSrcGetAlpha = pointSpriteAlphaSrc (theBits);
1990 #if !defined(GL_ES_VERSION_2_0)
1991 if (myContext->core11 != NULL
1992 && myContext->IsGlGreaterEqual (2, 1))
1994 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
1998 aSrcFragMainGetColor =
1999 EOL" vec4 aColor = getColor();"
2000 EOL" aColor.a = getAlpha();"
2001 EOL" if (aColor.a <= 0.1) discard;"
2002 EOL" occSetFragColor (aColor);";
2006 if ((theBits & OpenGl_PO_TextureRGB) != 0
2007 && (theBits & OpenGl_PO_VertColor) == 0)
2009 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
2010 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX));
2011 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2012 aSrcVertExtraMain +=
2013 EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);";
2015 EOL"vec4 getColor(void) { return VertColor; }";
2018 aSrcFragMainGetColor =
2019 EOL" vec4 aColor = getColor();"
2020 EOL" if (aColor.a <= 0.1) discard;"
2021 EOL" occSetFragColor (aColor);";
2026 if ((theBits & OpenGl_PO_HasTextures) != 0)
2028 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT));
2029 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2031 if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureEnv)
2033 aSrcVertExtraFunc = THE_FUNC_transformNormal_view;
2035 aSrcVertExtraMain +=
2036 EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;"
2037 EOL" vec3 aNormal = transformNormal (occNormal);"
2038 EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);"
2039 EOL" aReflect.z += 1.0;"
2040 EOL" TexCoord = vec4(aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5), 0.0, 1.0);";
2043 EOL"vec4 getColor(void) { return occTexture2D (occSamplerBaseColor, TexCoord.st); }";
2047 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
2048 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
2051 EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w); }";
2055 if ((theBits & OpenGl_PO_VertColor) != 0)
2057 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2058 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
2059 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
2062 int aNbClipPlanes = 0;
2063 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
2065 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2066 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2067 aSrcVertExtraMain +=
2068 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
2069 EOL" Position = occWorldViewMatrix * PositionWorld;";
2071 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
2073 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
2074 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2075 ? THE_FRAG_CLIP_CHAINS_N
2076 : THE_FRAG_CLIP_PLANES_N;
2078 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
2081 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
2083 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
2086 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2087 ? THE_FRAG_CLIP_CHAINS_2
2088 : THE_FRAG_CLIP_PLANES_2;
2091 if ((theBits & OpenGl_PO_WriteOit) != 0)
2093 aProgramSrc->SetNbFragmentOutputs (2);
2094 aProgramSrc->SetWeightOitOutput (true);
2099 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float occOrthoScale", Graphic3d_TOS_VERTEX));
2100 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float occSilhouetteThickness", Graphic3d_TOS_VERTEX));
2101 aSrcVertEndMain = THE_VERT_gl_Position_OUTLINE;
2103 else if ((theBits & OpenGl_PO_StippleLine) != 0)
2105 const Standard_Integer aBits = defaultGlslVersion (aProgramSrc, "unlit", theBits);
2106 if ((aBits & OpenGl_PO_StippleLine) != 0)
2108 if (myContext->hasGlslBitwiseOps != OpenGl_FeatureNotAvailable)
2110 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int occStipplePattern", Graphic3d_TOS_FRAGMENT));
2114 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("bool occStipplePattern[16]", Graphic3d_TOS_FRAGMENT));
2116 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float occStippleFactor", Graphic3d_TOS_FRAGMENT));
2117 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occViewport", Graphic3d_TOS_VERTEX));
2118 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 ScreenSpaceCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2120 EOL" vec2 aPosition = gl_Position.xy / gl_Position.w;"
2121 EOL" aPosition = aPosition * 0.5 + 0.5;"
2122 EOL" ScreenSpaceCoord = aPosition.xy * occViewport.zw + occViewport.xy;";
2123 aSrcFragMainGetColor = TCollection_AsciiString()
2124 + EOL" vec2 anAxis = vec2 (0.0, 1.0);"
2125 EOL" if (abs (dFdx (ScreenSpaceCoord.x)) - abs (dFdy (ScreenSpaceCoord.y)) > 0.001)"
2127 EOL" anAxis = vec2 (1.0, 0.0);"
2129 EOL" float aRotatePoint = dot (gl_FragCoord.xy, anAxis);"
2130 + (myContext->hasGlslBitwiseOps != OpenGl_FeatureNotAvailable
2131 ? EOL" uint aBit = uint (floor (aRotatePoint / occStippleFactor + 0.5)) & 15U;"
2132 EOL" if ((uint (occStipplePattern) & (1U << aBit)) == 0U) discard;"
2133 : EOL" int aBit = int (mod (floor (aRotatePoint / occStippleFactor + 0.5), 16.0));"
2134 EOL" if (!occStipplePattern[aBit]) discard;")
2135 + EOL" vec4 aColor = getFinalColor();"
2136 EOL" if (aColor.a <= 0.1) discard;"
2137 EOL" occSetFragColor (aColor);";
2141 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, "Warning: stipple lines in GLSL will be ignored.");
2150 + THE_VERT_gl_Position
2154 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
2155 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
2156 ? THE_FRAG_WIREFRAME_COLOR
2157 : EOL"#define getFinalColor getColor";
2165 + aSrcFragMainGetColor
2168 defaultGlslVersion (aProgramSrc, theIsOutline ? "outline" : "unlit", theBits);
2169 aProgramSrc->SetDefaultSampler (false);
2170 aProgramSrc->SetNbLightsMax (0);
2171 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
2172 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
2173 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
2174 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2175 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
2176 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2177 TCollection_AsciiString aKey;
2178 if (!Create (aProgramSrc, aKey, theProgram))
2180 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2181 return Standard_False;
2183 return Standard_True;
2186 // =======================================================================
2187 // function : pointSpriteShadingSrc
2189 // =======================================================================
2190 TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TCollection_AsciiString& theBaseColorSrc,
2191 Standard_Integer theBits)
2193 TCollection_AsciiString aSrcFragGetColor;
2194 if ((theBits & OpenGl_PO_PointSpriteA) == OpenGl_PO_PointSpriteA)
2196 aSrcFragGetColor = pointSpriteAlphaSrc (theBits) +
2197 EOL"vec4 getColor(void)"
2199 EOL" vec4 aColor = " + theBaseColorSrc + ";"
2200 EOL" aColor.a = getAlpha();"
2201 EOL" if (aColor.a <= 0.1) discard;"
2202 EOL" return aColor;"
2205 else if ((theBits & OpenGl_PO_PointSprite) == OpenGl_PO_PointSprite)
2207 aSrcFragGetColor = TCollection_AsciiString() +
2208 EOL"vec4 getColor(void)"
2210 EOL" vec4 aColor = " + theBaseColorSrc + ";"
2211 EOL" aColor = occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ") * aColor;"
2212 EOL" if (aColor.a <= 0.1) discard;"
2213 EOL" return aColor;"
2217 return aSrcFragGetColor;
2220 // =======================================================================
2221 // function : stdComputeLighting
2223 // =======================================================================
2224 TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integer& theNbLights,
2225 Standard_Boolean theHasVertColor,
2226 Standard_Boolean theIsPBR,
2227 Standard_Boolean theHasEmissive)
2229 TCollection_AsciiString aLightsFunc, aLightsLoop;
2231 const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources();
2232 if (!aLights.IsNull())
2234 theNbLights = aLights->NbEnabled();
2235 if (theNbLights <= THE_NB_UNROLLED_LIGHTS_MAX)
2237 Standard_Integer anIndex = 0;
2238 for (Graphic3d_LightSet::Iterator aLightIter (aLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
2239 aLightIter.More(); aLightIter.Next(), ++anIndex)
2241 switch (aLightIter.Value()->Type())
2243 case Graphic3d_TOLS_AMBIENT:
2245 break; // skip ambient
2246 case Graphic3d_TOLS_DIRECTIONAL:
2247 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
2249 case Graphic3d_TOLS_POSITIONAL:
2250 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
2252 case Graphic3d_TOLS_SPOT:
2253 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
2260 theNbLights = roundUpMaxLightSources (theNbLights);
2261 bool isFirstInLoop = true;
2262 aLightsLoop = aLightsLoop +
2263 EOL" for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)"
2265 EOL" int aType = occLight_Type (anIndex);";
2266 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0)
2268 isFirstInLoop = false;
2270 EOL" if (aType == OccLightType_Direct)"
2272 EOL" directionalLight (anIndex, theNormal, theView, theIsFront);"
2275 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
2279 aLightsLoop += EOL" else ";
2281 isFirstInLoop = false;
2283 EOL" if (aType == OccLightType_Point)"
2285 EOL" pointLight (anIndex, theNormal, theView, aPoint, theIsFront);"
2288 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0)
2292 aLightsLoop += EOL" else ";
2294 isFirstInLoop = false;
2296 EOL" if (aType == OccLightType_Spot)"
2298 EOL" spotLight (anIndex, theNormal, theView, aPoint, theIsFront);"
2301 aLightsLoop += EOL" }";
2306 aLightsFunc += Shaders_PBRDistribution_glsl;
2307 aLightsFunc += Shaders_PBRGeometry_glsl;
2308 aLightsFunc += Shaders_PBRFresnel_glsl;
2309 aLightsFunc += Shaders_PBRCookTorrance_glsl;
2310 aLightsFunc += Shaders_PBRIllumination_glsl;
2313 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) == 1
2317 // use the version with hard-coded first index
2318 aLightsLoop = EOL" directionalLightFirst(theNormal, theView, theIsFront);";
2319 aLightsFunc += THE_FUNC_directionalLightFirst;
2321 else if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0)
2323 aLightsFunc += theIsPBR ? THE_FUNC_PBR_directionalLight : THE_FUNC_directionalLight;
2325 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
2327 aLightsFunc += theIsPBR ? THE_FUNC_PBR_pointLight : THE_FUNC_pointLight;
2329 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0)
2331 aLightsFunc += theIsPBR ? THE_FUNC_PBR_spotLight : THE_FUNC_spotLight;
2335 TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();";
2336 TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();";
2337 if (theHasVertColor)
2339 aGetMatAmbient = "getVertColor();";
2340 aGetMatDiffuse = "getVertColor();";
2345 return TCollection_AsciiString()
2349 EOL"vec4 computeLighting (in vec3 theNormal,"
2350 EOL" in vec3 theView,"
2351 EOL" in vec4 thePoint,"
2352 EOL" in bool theIsFront)"
2354 EOL" Ambient = occLightAmbient.rgb;"
2355 EOL" Diffuse = vec3 (0.0);"
2356 EOL" Specular = vec3 (0.0);"
2357 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
2359 + EOL" vec4 aMatAmbient = " + aGetMatAmbient
2360 + EOL" vec4 aMatDiffuse = " + aGetMatDiffuse
2361 + EOL" vec4 aMatSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
2362 EOL" vec3 aColor = Ambient * aMatAmbient.rgb + Diffuse * aMatDiffuse.rgb + Specular * aMatSpecular.rgb;"
2363 EOL" occTextureOcclusion(aColor, TexCoord.st);"
2365 ? EOL" vec4 aMatEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
2366 EOL" aColor += aMatEmission.rgb;" : "")
2367 + EOL" return vec4 (aColor, aMatDiffuse.a);"
2372 return TCollection_AsciiString()
2373 + THE_FUNC_PBR_lightDef
2376 EOL"vec4 computeLighting (in vec3 theNormal,"
2377 EOL" in vec3 theView,"
2378 EOL" in vec4 thePoint,"
2379 EOL" in bool theIsFront)"
2381 EOL" DirectLighting = vec3(0.0);"
2382 EOL" BaseColor = " + (theHasVertColor ? "getVertColor();" : "occTextureColor(occPBRMaterial_Color (theIsFront), TexCoord.st);")
2383 + EOL" Emission = occTextureEmissive(occPBRMaterial_Emission (theIsFront), TexCoord.st);"
2384 EOL" Metallic = occTextureMetallic(occPBRMaterial_Metallic (theIsFront), TexCoord.st);"
2385 EOL" NormalizedRoughness = occTextureRoughness(occPBRMaterial_NormalizedRoughness (theIsFront), TexCoord.st);"
2386 EOL" Roughness = occRoughness (NormalizedRoughness);"
2387 EOL" IOR = occPBRMaterial_IOR (theIsFront);"
2388 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
2390 + EOL" vec3 aColor = DirectLighting;"
2391 EOL" vec3 anIndirectLightingSpec = occPBRFresnel (BaseColor.rgb, Metallic, IOR);"
2392 EOL" vec2 aCoeff = occTexture2D (occEnvLUT, vec2(abs(dot(theView, theNormal)), NormalizedRoughness)).xy;"
2393 EOL" anIndirectLightingSpec *= aCoeff.x;"
2394 EOL" anIndirectLightingSpec += aCoeff.y;"
2395 EOL" anIndirectLightingSpec *= occTextureCubeLod (occSpecIBLMap, -reflect (theView, theNormal), NormalizedRoughness * float (occNbSpecIBLLevels - 1)).rgb;"
2396 EOL" vec3 aRefractionCoeff = 1.0 - occPBRFresnel (BaseColor.rgb, Metallic, NormalizedRoughness, IOR, abs(dot(theView, theNormal)));"
2397 EOL" aRefractionCoeff *= (1.0 - Metallic);"
2398 EOL" vec3 anIndirectLightingDiff = aRefractionCoeff * BaseColor.rgb * BaseColor.a;"
2399 EOL" anIndirectLightingDiff *= occDiffIBLMap (theNormal).rgb;"
2400 EOL" aColor += occLightAmbient.rgb * (anIndirectLightingDiff + anIndirectLightingSpec);"
2401 EOL" aColor += Emission;"
2402 EOL" occTextureOcclusion(aColor, TexCoord.st);"
2403 EOL" return vec4 (aColor, mix(1.0, BaseColor.a, aRefractionCoeff.x));"
2408 // =======================================================================
2409 // function : prepareStdProgramGouraud
2411 // =======================================================================
2412 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
2413 const Standard_Integer theBits)
2415 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2416 TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraMain;
2417 TCollection_AsciiString aSrcFrag, aSrcFragExtraMain;
2418 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
2419 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2421 if ((theBits & OpenGl_PO_IsPoint) != 0)
2423 #if defined(GL_ES_VERSION_2_0)
2424 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
2427 if ((theBits & OpenGl_PO_PointSprite) != 0)
2429 #if !defined(GL_ES_VERSION_2_0)
2430 if (myContext->core11 != NULL
2431 && myContext->IsGlGreaterEqual (2, 1))
2433 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
2437 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT));
2438 aSrcFragGetColor = pointSpriteShadingSrc ("gl_FrontFacing ? FrontColor : BackColor", theBits);
2441 if ((theBits & OpenGl_PO_TextureRGB) != 0
2442 && (theBits & OpenGl_PO_VertColor) == 0)
2444 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
2445 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX));
2446 aSrcVertColor = EOL"vec4 getVertColor(void) { return occTexture2D (occSamplerBaseColor, occTexCoord.xy); }";
2451 if ((theBits & OpenGl_PO_TextureRGB) != 0)
2453 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
2454 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT));
2455 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2456 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
2459 EOL"vec4 getColor(void)"
2461 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
2462 EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;"
2467 if ((theBits & OpenGl_PO_VertColor) != 0)
2469 aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
2472 int aNbClipPlanes = 0;
2473 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
2475 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2476 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2477 aSrcVertExtraMain +=
2478 EOL" PositionWorld = aPositionWorld;"
2479 EOL" Position = aPosition;";
2481 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
2483 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
2484 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2485 ? THE_FRAG_CLIP_CHAINS_N
2486 : THE_FRAG_CLIP_PLANES_N;
2488 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
2491 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
2493 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
2496 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2497 ? THE_FRAG_CLIP_CHAINS_2
2498 : THE_FRAG_CLIP_PLANES_2;
2501 if ((theBits & OpenGl_PO_WriteOit) != 0)
2503 aProgramSrc->SetNbFragmentOutputs (2);
2504 aProgramSrc->SetWeightOitOutput (true);
2507 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 FrontColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2508 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 BackColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2510 Standard_Integer aNbLights = 0;
2511 const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcVertColor.IsEmpty(), false, true);
2512 aSrcVert = TCollection_AsciiString()
2513 + THE_FUNC_transformNormal_view
2519 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
2520 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
2521 EOL" vec3 aNormal = transformNormal (occNormal);"
2522 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
2523 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
2524 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
2526 + THE_VERT_gl_Position
2529 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
2530 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
2531 ? THE_FRAG_WIREFRAME_COLOR
2532 : EOL"#define getFinalColor getColor";
2534 aSrcFrag = TCollection_AsciiString()
2539 + EOL" occSetFragColor (getFinalColor());"
2542 const TCollection_AsciiString aProgId = TCollection_AsciiString ("gouraud-") + genLightKey (myLightSourceState.LightSources()) + "-";
2543 defaultGlslVersion (aProgramSrc, aProgId, theBits);
2544 aProgramSrc->SetDefaultSampler (false);
2545 aProgramSrc->SetNbLightsMax (aNbLights);
2546 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
2547 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
2548 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
2549 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2550 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
2551 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2552 TCollection_AsciiString aKey;
2553 if (!Create (aProgramSrc, aKey, theProgram))
2555 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2556 return Standard_False;
2558 return Standard_True;
2561 // =======================================================================
2562 // function : prepareStdProgramPhong
2564 // =======================================================================
2565 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
2566 const Standard_Integer theBits,
2567 const Standard_Boolean theIsFlatNormal,
2568 const Standard_Boolean theIsPBR)
2570 TCollection_AsciiString aPosition = theIsPBR ? "PositionWorld" : "Position";
2571 TCollection_AsciiString aPhongCompLight = TCollection_AsciiString() +
2572 "computeLighting (normalize (Normal), normalize (View), " + aPosition + ", gl_FrontFacing)";
2573 const bool isFlatNormal = theIsFlatNormal
2574 && myContext->hasFlatShading != OpenGl_FeatureNotAvailable;
2575 const char* aDFdxSignReversion = "";
2576 #if defined(GL_ES_VERSION_2_0)
2577 if (isFlatNormal != theIsFlatNormal)
2579 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
2580 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
2581 "Warning: flat shading requires OpenGL ES 3.0+ or GL_OES_standard_derivatives extension.");
2583 else if (isFlatNormal
2584 && myContext->Vendor().Search("qualcomm") != -1)
2586 // workaround Adreno driver bug computing reversed normal using dFdx/dFdy
2587 aDFdxSignReversion = "-";
2588 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
2589 "Warning: applied workaround for flat shading normal computation using dFdx/dFdy on Adreno");
2592 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2593 aProgramSrc->SetPBR (theIsPBR);
2595 TCollection_AsciiString aSrcVert, aSrcVertExtraFunc, aSrcVertExtraMain;
2596 TCollection_AsciiString aSrcFrag, aSrcFragExtraFunc, aSrcFragExtraOut, aSrcFragGetVertColor, aSrcFragExtraMain;
2597 TCollection_AsciiString aSrcFragGetColor = TCollection_AsciiString() + EOL"vec4 getColor(void) { return " + aPhongCompLight + "; }";
2598 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2599 if ((theBits & OpenGl_PO_IsPoint) != 0)
2601 #if defined(GL_ES_VERSION_2_0)
2602 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
2605 if ((theBits & OpenGl_PO_PointSprite) != 0)
2607 #if !defined(GL_ES_VERSION_2_0)
2608 if (myContext->core11 != NULL
2609 && myContext->IsGlGreaterEqual (2, 1))
2611 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
2615 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT));
2616 aSrcFragGetColor = pointSpriteShadingSrc (aPhongCompLight, theBits);
2619 if ((theBits & OpenGl_PO_TextureRGB) != 0
2620 && (theBits & OpenGl_PO_VertColor) == 0)
2622 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
2623 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX));
2624 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2626 aSrcVertExtraMain += EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);";
2627 aSrcFragGetVertColor = EOL"vec4 getVertColor(void) { return VertColor; }";
2632 if ((theBits & OpenGl_PO_TextureRGB) != 0)
2634 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT));
2635 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2636 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
2638 Standard_Integer aTextureBits = Graphic3d_TextureSetBits_BaseColor | Graphic3d_TextureSetBits_Occlusion | Graphic3d_TextureSetBits_Emissive;
2641 aSrcFragGetColor = TCollection_AsciiString() +
2642 EOL"vec4 getColor(void)"
2644 EOL" vec2 aTexUV = TexCoord.st / TexCoord.w;"
2645 EOL" vec4 aColor = " + aPhongCompLight + ";"
2646 EOL" aColor *= occTexture2D(occSamplerBaseColor, aTexUV);"
2647 EOL" vec3 anEmission = occTextureEmissive((gl_FrontFacing ? occFrontMaterial_Emission() : occBackMaterial_Emission()).rgb, aTexUV);"
2648 EOL" aColor.rgb += anEmission;"
2649 EOL" return aColor;"
2654 aTextureBits |= Graphic3d_TextureSetBits_MetallicRoughness;
2656 if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureNormal
2659 if (myContext->hasFlatShading != OpenGl_FeatureNotAvailable)
2661 aTextureBits |= Graphic3d_TextureSetBits_Normal;
2665 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
2666 "Warning: ignoring Normal Map texture due to hardware capabilities");
2669 aProgramSrc->SetTextureSetBits (aTextureBits);
2673 if ((theBits & OpenGl_PO_VertColor) != 0)
2675 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2676 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
2677 aSrcFragGetVertColor = EOL"vec4 getVertColor(void) { return VertColor; }";
2680 int aNbClipPlanes = 0;
2681 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
2683 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
2685 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
2686 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2687 ? THE_FRAG_CLIP_CHAINS_N
2688 : THE_FRAG_CLIP_PLANES_N;
2690 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
2693 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
2695 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
2698 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2699 ? THE_FRAG_CLIP_CHAINS_2
2700 : THE_FRAG_CLIP_PLANES_2;
2703 if ((theBits & OpenGl_PO_WriteOit) != 0)
2705 aProgramSrc->SetNbFragmentOutputs (2);
2706 aProgramSrc->SetWeightOitOutput (true);
2711 aSrcFragExtraOut += EOL"vec3 Normal;";
2712 aSrcFragExtraMain += TCollection_AsciiString()
2713 + EOL" Normal = " + aDFdxSignReversion + "normalize (cross (dFdx (" + aPosition + ".xyz / " + aPosition + ".w), dFdy (" + aPosition + ".xyz / " + aPosition + ".w)));"
2714 EOL" if (!gl_FrontFacing) { Normal = -Normal; }";
2718 aStageInOuts.Append(OpenGl_ShaderObject::ShaderVariable("vec3 vNormal", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2719 aSrcVertExtraFunc += THE_FUNC_transformNormal_world;
2720 aSrcVertExtraMain += EOL" vNormal = transformNormal (occNormal);";
2721 aSrcFragExtraFunc += EOL" vec3 Normal = vNormal;";
2723 if ((theBits & OpenGl_PO_IsPoint) == 0
2724 && (theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureNormal
2725 && myContext->hasFlatShading != OpenGl_FeatureNotAvailable)
2727 // apply normal map texture
2728 aSrcFragExtraMain +=
2729 EOL"#if defined(THE_HAS_TEXTURE_NORMAL)"
2730 EOL" vec4 aMapNormalValue = occTextureNormal(TexCoord.st / TexCoord.w);"
2731 EOL" if (aMapNormalValue.w > 0.5)"
2733 EOL" aMapNormalValue.xyz = normalize (aMapNormalValue.xyz * 2.0 - vec3(1.0));"
2734 EOL" mat2 aDeltaUVMatrix = mat2 (dFdx(TexCoord.st / TexCoord.w), dFdy(TexCoord.st / TexCoord.w));"
2735 EOL" aDeltaUVMatrix = mat2 (aDeltaUVMatrix[1][1], -aDeltaUVMatrix[0][1], -aDeltaUVMatrix[1][0], aDeltaUVMatrix[0][0]);"
2736 EOL" mat2x3 aDeltaVectorMatrix = mat2x3 (dFdx (PositionWorld.xyz), dFdy (PositionWorld.xyz));"
2737 EOL" aDeltaVectorMatrix = aDeltaVectorMatrix * aDeltaUVMatrix;"
2738 EOL" aDeltaVectorMatrix[0] = aDeltaVectorMatrix[0] - dot(Normal, aDeltaVectorMatrix[0]) * Normal;"
2739 EOL" aDeltaVectorMatrix[1] = aDeltaVectorMatrix[1] - dot(Normal, aDeltaVectorMatrix[1]) * Normal;"
2740 EOL" Normal = mat3 (-normalize(aDeltaVectorMatrix[0]), -normalize(aDeltaVectorMatrix[1]), Normal) * aMapNormalValue.xyz;"
2746 aSrcFragExtraMain +=
2747 EOL" Normal = normalize ((occWorldViewMatrixInverseTranspose * vec4 (Normal, 0.0)).xyz);";
2751 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2752 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2753 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 View", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2755 aSrcVert = TCollection_AsciiString()
2759 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
2760 EOL" Position = occWorldViewMatrix * PositionWorld;"
2761 EOL" if (occProjectionMatrix[3][3] == 1.0)"
2763 EOL" View = vec3(0.0, 0.0, 1.0);"
2767 EOL" View = -Position.xyz;"
2769 + (theIsPBR ? EOL" View = (occWorldViewMatrixInverse * vec4(View, 0.0)).xyz;" : "")
2771 + THE_VERT_gl_Position
2774 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
2775 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
2776 ? THE_FRAG_WIREFRAME_COLOR
2777 : EOL"#define getFinalColor getColor";
2779 Standard_Integer aNbLights = 0;
2780 const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcFragGetVertColor.IsEmpty(), theIsPBR,
2781 (theBits & OpenGl_PO_TextureRGB) == 0
2782 || (theBits & OpenGl_PO_IsPoint) != 0);
2783 aSrcFrag = TCollection_AsciiString()
2787 + aSrcFragGetVertColor
2794 + EOL" occSetFragColor (getFinalColor());"
2797 const TCollection_AsciiString aProgId = TCollection_AsciiString (theIsFlatNormal ? "flat-" : "phong-") + (theIsPBR ? "pbr-" : "") + genLightKey (myLightSourceState.LightSources()) + "-";
2798 defaultGlslVersion (aProgramSrc, aProgId, theBits, isFlatNormal);
2799 aProgramSrc->SetDefaultSampler (false);
2800 aProgramSrc->SetNbLightsMax (aNbLights);
2801 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
2802 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
2804 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
2805 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2806 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
2807 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2808 TCollection_AsciiString aKey;
2809 if (!Create (aProgramSrc, aKey, theProgram))
2811 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2812 return Standard_False;
2814 return Standard_True;
2817 // =======================================================================
2818 // function : prepareStdProgramStereo
2820 // =======================================================================
2821 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
2822 const Graphic3d_StereoMode theStereoMode)
2824 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2825 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2827 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2828 TCollection_AsciiString aSrcVert =
2831 EOL" TexCoord = occVertex.zw;"
2832 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
2835 TCollection_AsciiString aSrcFrag;
2836 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uLeftSampler", Graphic3d_TOS_FRAGMENT));
2837 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uRightSampler", Graphic3d_TOS_FRAGMENT));
2838 const char* aName = "stereo";
2839 switch (theStereoMode)
2841 case Graphic3d_StereoMode_Anaglyph:
2844 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 uMultL", Graphic3d_TOS_FRAGMENT));
2845 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 uMultR", Graphic3d_TOS_FRAGMENT));
2846 const TCollection_AsciiString aNormalize = mySRgbState
2847 ? EOL"#define sRgb2linear(theColor) theColor"
2848 EOL"#define linear2sRgb(theColor) theColor"
2849 : EOL"#define sRgb2linear(theColor) pow(theColor, vec4(2.2, 2.2, 2.2, 1.0))"
2850 EOL"#define linear2sRgb(theColor) pow(theColor, 1.0 / vec4(2.2, 2.2, 2.2, 1.0))";
2851 aSrcFrag = aNormalize
2854 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2855 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2856 EOL" aColorL = sRgb2linear (aColorL);"
2857 EOL" aColorR = sRgb2linear (aColorR);"
2858 EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;"
2859 EOL" occSetFragColor (linear2sRgb (aColor));"
2863 case Graphic3d_StereoMode_RowInterlaced:
2865 aName = "row-interlaced";
2869 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2870 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2871 EOL" if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)"
2873 EOL" occSetFragColor (aColorL);"
2877 EOL" occSetFragColor (aColorR);"
2882 case Graphic3d_StereoMode_ColumnInterlaced:
2884 aName = "column-interlaced";
2888 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2889 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2890 EOL" if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)"
2892 EOL" occSetFragColor (aColorL);"
2896 EOL" occSetFragColor (aColorR);"
2901 case Graphic3d_StereoMode_ChessBoard:
2903 aName = "chessboard";
2907 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2908 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2909 EOL" bool isEvenX = int(mod(floor(gl_FragCoord.x - 1023.5), 2.0)) != 1;"
2910 EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y - 1023.5), 2.0)) == 1;"
2911 EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))"
2913 EOL" occSetFragColor (aColorL);"
2917 EOL" occSetFragColor (aColorR);"
2922 case Graphic3d_StereoMode_SideBySide:
2924 aName = "sidebyside";
2928 EOL" vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);"
2929 EOL" if (TexCoord.x > 0.5)"
2931 EOL" aTexCoord.x -= 1.0;"
2933 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
2934 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
2935 EOL" if (TexCoord.x <= 0.5)"
2937 EOL" occSetFragColor (aColorL);"
2941 EOL" occSetFragColor (aColorR);"
2946 case Graphic3d_StereoMode_OverUnder:
2948 aName = "overunder";
2952 EOL" vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);"
2953 EOL" if (TexCoord.y > 0.5)"
2955 EOL" aTexCoord.y -= 1.0;"
2957 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
2958 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
2959 EOL" if (TexCoord.y <= 0.5)"
2961 EOL" occSetFragColor (aColorL);"
2965 EOL" occSetFragColor (aColorR);"
2970 case Graphic3d_StereoMode_QuadBuffer:
2971 case Graphic3d_StereoMode_SoftPageFlip:
2974 /*const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[Graphic3d_StereoMode_QuadBuffer];
2975 if (!aProgram.IsNull())
2977 return aProgram->IsValid();
2982 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2983 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2984 EOL" aColorL.b = 0.0;"
2985 EOL" aColorL.g = 0.0;"
2986 EOL" aColorR.r = 0.0;"
2987 EOL" occSetFragColor (aColorL + aColorR);"
2993 defaultGlslVersion (aProgramSrc, aName, 0);
2994 aProgramSrc->SetDefaultSampler (false);
2995 aProgramSrc->SetNbLightsMax (0);
2996 aProgramSrc->SetNbClipPlanesMax (0);
2997 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
2998 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
2999 TCollection_AsciiString aKey;
3000 if (!Create (aProgramSrc, aKey, theProgram))
3002 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
3003 return Standard_False;
3006 myContext->BindProgram (theProgram);
3007 theProgram->SetSampler (myContext, "uLeftSampler", Graphic3d_TextureUnit_0);
3008 theProgram->SetSampler (myContext, "uRightSampler", Graphic3d_TextureUnit_1);
3009 myContext->BindProgram (NULL);
3010 return Standard_True;
3013 // =======================================================================
3014 // function : prepareStdProgramBoundBox
3016 // =======================================================================
3017 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramBoundBox()
3019 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
3021 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
3022 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 occBBoxCenter", Graphic3d_TOS_VERTEX));
3023 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 occBBoxSize", Graphic3d_TOS_VERTEX));
3025 TCollection_AsciiString aSrcVert =
3028 EOL" vec4 aCenter = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);"
3029 EOL" vec4 aPos = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);"
3030 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * aPos;"
3033 TCollection_AsciiString aSrcFrag =
3036 EOL" occSetFragColor (occColor);"
3039 defaultGlslVersion (aProgramSrc, "bndbox", 0);
3040 aProgramSrc->SetDefaultSampler (false);
3041 aProgramSrc->SetNbLightsMax (0);
3042 aProgramSrc->SetNbClipPlanesMax (0);
3043 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
3044 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
3045 TCollection_AsciiString aKey;
3046 if (!Create (aProgramSrc, aKey, myBoundBoxProgram))
3048 myBoundBoxProgram = new OpenGl_ShaderProgram(); // just mark as invalid
3049 return Standard_False;
3052 const OpenGl_Vec4 aMin (-0.5f, -0.5f, -0.5f, 1.0f);
3053 const OpenGl_Vec4 anAxisShifts[3] =
3055 OpenGl_Vec4 (1.0f, 0.0f, 0.0f, 0.0f),
3056 OpenGl_Vec4 (0.0f, 1.0f, 0.0f, 0.0f),
3057 OpenGl_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)
3060 const OpenGl_Vec4 aLookup1 (0.0f, 1.0f, 0.0f, 1.0f);
3061 const OpenGl_Vec4 aLookup2 (0.0f, 0.0f, 1.0f, 1.0f);
3062 OpenGl_Vec4 aLinesVertices[24];
3063 for (int anAxis = 0, aVertex = 0; anAxis < 3; ++anAxis)
3065 for (int aCompIter = 0; aCompIter < 4; ++aCompIter)
3067 aLinesVertices[aVertex++] = aMin
3068 + anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter]
3069 + anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter];
3071 aLinesVertices[aVertex++] = aMin
3072 + anAxisShifts[anAxis]
3073 + anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter]
3074 + anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter];
3077 if (myContext->ToUseVbo())
3079 myBoundBoxVertBuffer = new OpenGl_VertexBuffer();
3080 if (myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData()))
3082 myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer);
3083 return Standard_True;
3086 myBoundBoxVertBuffer = new OpenGl_VertexBufferCompat();
3087 myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData());
3088 myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer);
3089 return Standard_True;
3092 // =======================================================================
3093 // function : preparePBREnvBakingProgram
3095 // =======================================================================
3096 Standard_Boolean OpenGl_ShaderManager::preparePBREnvBakingProgram()
3098 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
3099 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
3101 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
3102 + THE_FUNC_cubemap_vector_transform
3103 + Shaders_PBREnvBaking_vs;
3105 TCollection_AsciiString aSrcFrag = TCollection_AsciiString()
3106 + THE_FUNC_cubemap_vector_transform
3107 + Shaders_PBRDistribution_glsl
3108 + Shaders_PBREnvBaking_fs;
3110 // constant array definition requires OpenGL 2.1+ or OpenGL ES 3.0+
3111 #if defined(GL_ES_VERSION_2_0)
3112 aProgramSrc->SetHeader ("#version 300 es");
3114 aProgramSrc->SetHeader ("#version 120");
3117 defaultGlslVersion (aProgramSrc, "pbr_env_baking", 0);
3118 aProgramSrc->SetDefaultSampler (false);
3119 aProgramSrc->SetNbLightsMax (0);
3120 aProgramSrc->SetNbClipPlanesMax (0);
3121 aProgramSrc->SetPBR (true);
3122 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
3123 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
3124 TCollection_AsciiString aKey;
3125 if (!Create (aProgramSrc, aKey, myPBREnvBakingProgram))
3127 myPBREnvBakingProgram = new OpenGl_ShaderProgram(); // just mark as invalid
3128 return Standard_False;
3131 return Standard_True;
3134 // =======================================================================
3135 // function : GetBgCubeMapProgram
3137 // =======================================================================
3138 const Handle(Graphic3d_ShaderProgram)& OpenGl_ShaderManager::GetBgCubeMapProgram ()
3140 if (myBgCubeMapProgram.IsNull())
3142 myBgCubeMapProgram = new Graphic3d_ShaderProgram();
3144 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
3145 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable("vec3 ViewDirection", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
3146 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("samplerCube occSampler0", Graphic3d_TOS_FRAGMENT));
3147 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uYCoeff", Graphic3d_TOS_VERTEX));
3148 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uZCoeff", Graphic3d_TOS_VERTEX));
3150 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
3151 + THE_FUNC_cubemap_vector_transform
3154 EOL" vec4 aViewDirection = occProjectionMatrixInverse * vec4(occVertex.xy, 0.0, 1.0);"
3155 EOL" aViewDirection /= aViewDirection.w;"
3156 EOL" aViewDirection.w = 0.0;"
3157 EOL" ViewDirection = normalize((occWorldViewMatrixInverse * aViewDirection).xyz);"
3158 EOL" ViewDirection = cubemapVectorTransform (ViewDirection, uYCoeff, uZCoeff);"
3159 EOL" gl_Position = vec4(occVertex.xy, 0.0, 1.0);"
3162 TCollection_AsciiString aSrcFrag =
3163 EOL"#define occEnvCubemap occSampler0"
3166 EOL" occSetFragColor (vec4(occTextureCube (occEnvCubemap, ViewDirection).rgb, 1.0));"
3169 defaultGlslVersion (myBgCubeMapProgram, "background_cubemap", 0);
3170 myBgCubeMapProgram->SetDefaultSampler (false);
3171 myBgCubeMapProgram->SetNbLightsMax (0);
3172 myBgCubeMapProgram->SetNbClipPlanesMax (0);
3173 myBgCubeMapProgram->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
3174 myBgCubeMapProgram->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
3177 return myBgCubeMapProgram;
3180 // =======================================================================
3181 // function : bindProgramWithState
3183 // =======================================================================
3184 Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram)
3186 const Standard_Boolean isBound = myContext->BindProgram (theProgram);
3188 && !theProgram.IsNull())
3190 theProgram->ApplyVariables (myContext);
3192 PushState (theProgram);
3196 // =======================================================================
3197 // function : BindMarkerProgram
3199 // =======================================================================
3200 Standard_Boolean OpenGl_ShaderManager::BindMarkerProgram (const Handle(OpenGl_TextureSet)& theTextures,
3201 Graphic3d_TypeOfShadingModel theShadingModel,
3202 Graphic3d_AlphaMode theAlphaMode,
3203 Standard_Boolean theHasVertColor,
3204 const Handle(OpenGl_ShaderProgram)& theCustomProgram)
3206 if (!theCustomProgram.IsNull()
3207 || myContext->caps->ffpEnable)
3209 return bindProgramWithState (theCustomProgram);
3212 Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, Aspect_IS_SOLID, theHasVertColor, false, false);
3213 if (!theTextures.IsNull()
3214 && theTextures->HasPointSprite())
3216 aBits |= theTextures->Last()->IsAlpha() ? OpenGl_PO_PointSpriteA : OpenGl_PO_PointSprite;
3220 aBits |= OpenGl_PO_PointSimple;
3222 Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theShadingModel, aBits);
3223 return bindProgramWithState (aProgram);