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"
37 #include "../Shaders/Shaders_PointLightAttenuation_glsl.pxx"
38 #include "../Shaders/Shaders_TangentSpaceNormal_glsl.pxx"
40 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderManager,Standard_Transient)
44 //! Number specifying maximum number of light sources to prepare a GLSL program with unrolled loop.
45 const Standard_Integer THE_NB_UNROLLED_LIGHTS_MAX = 32;
47 //! Compute the size of array storing holding light sources definition.
48 static Standard_Integer roundUpMaxLightSources (Standard_Integer theNbLights)
50 Standard_Integer aMaxLimit = THE_NB_UNROLLED_LIGHTS_MAX;
51 for (; aMaxLimit < theNbLights; aMaxLimit *= 2) {}
57 //! Compute TexCoord value in Vertex Shader
58 const char THE_VARY_TexCoord_Trsf[] =
59 EOL" float aRotSin = occTextureTrsf_RotationSin();"
60 EOL" float aRotCos = occTextureTrsf_RotationCos();"
61 EOL" vec2 aTex2 = vec2 (occTexCoord.x * aRotCos - occTexCoord.y * aRotSin,"
62 EOL" occTexCoord.x * aRotSin + occTexCoord.y * aRotCos);"
63 EOL" aTex2 = (aTex2 + occTextureTrsf_Translation()) * occTextureTrsf_Scale();"
64 EOL" TexCoord = vec4(aTex2, occTexCoord.zw);";
66 //! Auxiliary function to flip gl_PointCoord vertically
67 #define THE_VEC2_glPointCoord "vec2 (gl_PointCoord.x, 1.0 - gl_PointCoord.y)"
69 //! Auxiliary function to transform normal from model to view coordinate system.
70 const char THE_FUNC_transformNormal_view[] =
71 EOL"vec3 transformNormal (in vec3 theNormal)"
73 EOL" vec4 aResult = occWorldViewMatrixInverseTranspose"
74 EOL" * occModelWorldMatrixInverseTranspose"
75 EOL" * vec4 (theNormal, 0.0);"
76 EOL" return normalize (aResult.xyz);"
79 //! The same function as THE_FUNC_transformNormal but is used in PBR pipeline.
80 //! The normals are expected to be in world coordinate system in PBR pipeline.
81 const char THE_FUNC_transformNormal_world[] =
82 EOL"vec3 transformNormal (in vec3 theNormal)"
84 EOL" vec4 aResult = occModelWorldMatrixInverseTranspose"
85 EOL" * vec4 (theNormal, 0.0);"
86 EOL" return normalize (aResult.xyz);"
89 //! Global shader variable for color definition with lighting enabled.
90 const char THE_FUNC_lightDef[] =
91 EOL"vec3 Ambient;" //!< Ambient contribution of light sources
92 EOL"vec3 Diffuse;" //!< Diffuse contribution of light sources
93 EOL"vec3 Specular;"; //!< Specular contribution of light sources
95 //! Global shader variable for color definition with lighting enabled.
96 const char THE_FUNC_PBR_lightDef[] =
97 EOL"vec3 DirectLighting;" //!< Accumulator of direct lighting from light sources
98 EOL"vec4 BaseColor;" //!< Base color (albedo) of material for PBR
99 EOL"float Metallic;" //!< Metallic coefficient of material
100 EOL"float NormalizedRoughness;" //!< Normalized roughness coefficient of material
101 EOL"float Roughness;" //!< Roughness coefficient of material
102 EOL"vec3 Emission;" //!< Light intensity emitted by material
103 EOL"float IOR;"; //!< Material's index of refraction
105 //! Function computes contribution of isotropic point light source
106 const char THE_FUNC_pointLight[] =
107 EOL"void pointLight (in int theId,"
108 EOL" in vec3 theNormal,"
109 EOL" in vec3 theView,"
110 EOL" in vec3 thePoint,"
111 EOL" in bool theIsFront)"
113 EOL" vec3 aLight = occLight_Position (theId);"
114 EOL" if (!occLight_IsHeadlight (theId))"
116 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));"
118 EOL" aLight -= thePoint;"
120 EOL" float aDist = length (aLight);"
121 EOL" float aRange = occLight_Range (theId);"
122 EOL" float anAtten = occPointLightAttenuation (aDist, aRange, occLight_LinearAttenuation (theId), occLight_ConstAttenuation (theId));"
123 EOL" if (anAtten <= 0.0) return;"
124 EOL" aLight /= aDist;"
126 EOL" vec3 aHalf = normalize (aLight + theView);"
128 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
129 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
130 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
132 EOL" float aSpecl = 0.0;"
133 EOL" if (aNdotL > 0.0)"
135 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
138 EOL" Diffuse += occLight_Diffuse (theId) * aNdotL * anAtten;"
139 EOL" Specular += occLight_Specular(theId) * aSpecl * anAtten;"
142 //! Function computes contribution of isotropic point light source
143 const char THE_FUNC_PBR_pointLight[] =
144 EOL"void pointLight (in int theId,"
145 EOL" in vec3 theNormal,"
146 EOL" in vec3 theView,"
147 EOL" in vec3 thePoint,"
148 EOL" in bool theIsFront)"
150 EOL" vec3 aLight = occLight_Position (theId);"
151 EOL" if (occLight_IsHeadlight (theId))"
153 EOL" aLight = vec3 (occWorldViewMatrixInverse * vec4 (aLight, 1.0));"
155 EOL" aLight -= thePoint;"
157 EOL" float aDist = length (aLight);"
158 EOL" float aRange = occLight_Range (theId);"
159 EOL" float anAtten = occPointLightAttenuation (aDist, aRange);"
160 EOL" if (anAtten <= 0.0) return;"
161 EOL" aLight /= aDist;"
163 EOL" theNormal = theIsFront ? theNormal : -theNormal;"
164 EOL" DirectLighting += occPBRIllumination (theView, aLight, theNormal,"
165 EOL" BaseColor, Metallic, Roughness, IOR,"
166 EOL" occLight_Specular (theId),"
167 EOL" occLight_Intensity(theId) * anAtten);"
170 //! Function computes contribution of spotlight source
171 const char THE_FUNC_spotLight[] =
172 EOL"void spotLight (in int theId,"
173 EOL" in vec3 theNormal,"
174 EOL" in vec3 theView,"
175 EOL" in vec3 thePoint,"
176 EOL" in bool theIsFront)"
178 EOL" vec3 aLight = occLight_Position (theId);"
179 EOL" vec3 aSpotDir = occLight_SpotDirection (theId);"
180 EOL" if (!occLight_IsHeadlight (theId))"
182 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 1.0));"
183 EOL" aSpotDir = vec3 (occWorldViewMatrix * vec4 (aSpotDir, 0.0));"
185 EOL" aLight -= thePoint;"
187 EOL" float aDist = length (aLight);"
188 EOL" float aRange = occLight_Range (theId);"
189 EOL" float anAtten = occPointLightAttenuation (aDist, aRange, occLight_LinearAttenuation (theId), occLight_ConstAttenuation (theId));"
190 EOL" if (anAtten <= 0.0) return;"
191 EOL" aLight /= 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" if (anExponent > 0.0)"
204 EOL" anAtten *= pow (aCosA, anExponent * 128.0);"
207 EOL" vec3 aHalf = normalize (aLight + theView);"
209 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
210 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
211 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
213 EOL" float aSpecl = 0.0;"
214 EOL" if (aNdotL > 0.0)"
216 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
219 EOL" Diffuse += occLight_Diffuse (theId) * aNdotL * anAtten;"
220 EOL" Specular += occLight_Specular(theId) * aSpecl * anAtten;"
223 //! Function computes contribution of spotlight source
224 const char THE_FUNC_PBR_spotLight[] =
225 EOL"void spotLight (in int theId,"
226 EOL" in vec3 theNormal,"
227 EOL" in vec3 theView,"
228 EOL" in vec3 thePoint,"
229 EOL" in bool theIsFront)"
231 EOL" vec3 aLight = occLight_Position (theId);"
232 EOL" vec3 aSpotDir = occLight_SpotDirection (theId);"
233 EOL" if (occLight_IsHeadlight (theId))"
235 EOL" aLight = vec3 (occWorldViewMatrixInverse * vec4 (aLight, 1.0));"
236 EOL" aSpotDir = vec3 (occWorldViewMatrixInverse * vec4 (aSpotDir, 0.0));"
238 EOL" aLight -= thePoint;"
240 EOL" float aDist = length (aLight);"
241 EOL" float aRange = occLight_Range (theId);"
242 EOL" float anAtten = occPointLightAttenuation (aDist, aRange);"
243 EOL" if (anAtten <= 0.0) return;"
244 EOL" aLight /= aDist;"
246 EOL" aSpotDir = normalize (aSpotDir);"
248 EOL" float aCosA = dot (aSpotDir, -aLight);"
249 EOL" float aRelativeAngle = 2.0 * acos(aCosA) / occLight_SpotCutOff(theId);"
250 EOL" if (aCosA >= 1.0 || aRelativeAngle > 1.0)"
254 EOL" float anExponent = occLight_SpotExponent (theId);"
255 EOL" if ((1.0 - aRelativeAngle) <= anExponent)"
257 EOL" float anAngularAttenuationOffset = cos(0.5 * occLight_SpotCutOff(theId));"
258 EOL" float anAngularAttenuationScale = 1.0 / max(0.001, cos(0.5 * occLight_SpotCutOff(theId) * (1.0 - anExponent)) - anAngularAttenuationOffset);"
259 EOL" anAngularAttenuationOffset *= -anAngularAttenuationScale;"
260 EOL" float anAngularAttenuantion = clamp(aCosA * anAngularAttenuationScale + anAngularAttenuationOffset, 0.0, 1.0);"
261 EOL" anAtten *= anAngularAttenuantion * anAngularAttenuantion;"
263 EOL" theNormal = theIsFront ? theNormal : -theNormal;"
264 EOL" DirectLighting += occPBRIllumination (theView, aLight, theNormal,"
265 EOL" BaseColor, Metallic, Roughness, IOR,"
266 EOL" occLight_Specular(theId),"
267 EOL" occLight_Intensity(theId) * anAtten);"
270 //! Function computes contribution of directional light source
271 const char THE_FUNC_directionalLight[] =
272 EOL"void directionalLight (in int theId,"
273 EOL" in vec3 theNormal,"
274 EOL" in vec3 theView,"
275 EOL" in bool theIsFront)"
277 EOL" vec3 aLight = normalize (occLight_Position (theId));"
278 EOL" if (!occLight_IsHeadlight (theId))"
280 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));"
283 EOL" vec3 aHalf = normalize (aLight + theView);"
285 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
286 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
287 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
289 EOL" float aSpecl = 0.0;"
290 EOL" if (aNdotL > 0.0)"
292 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
295 EOL" Diffuse += occLight_Diffuse (theId) * aNdotL;"
296 EOL" Specular += occLight_Specular (theId) * aSpecl;"
299 //! Function computes contribution of directional light source
300 const char THE_FUNC_PBR_directionalLight[] =
301 EOL"void directionalLight (in int theId,"
302 EOL" in vec3 theNormal,"
303 EOL" in vec3 theView,"
304 EOL" in bool theIsFront)"
306 EOL" vec3 aLight = normalize (occLight_Position (theId));"
307 EOL" if (occLight_IsHeadlight (theId))"
309 EOL" aLight = vec3 (occWorldViewMatrixInverse * vec4 (aLight, 0.0));"
312 EOL" theNormal = theIsFront ? theNormal : -theNormal;"
313 EOL" DirectLighting += occPBRIllumination (theView, aLight, theNormal,"
314 EOL" BaseColor, Metallic, Roughness, IOR,"
315 EOL" occLight_Specular (theId),"
316 EOL" occLight_Intensity(theId));"
319 //! The same as THE_FUNC_directionalLight but for the light with zero index
320 //! (avoids limitations on some mobile devices).
321 const char THE_FUNC_directionalLightFirst[] =
322 EOL"void directionalLightFirst (in vec3 theNormal,"
323 EOL" in vec3 theView,"
324 EOL" in bool theIsFront)"
326 EOL" vec3 aLight = normalize (occLight_Position(0));"
327 EOL" if (!occLight_IsHeadlight (0))"
329 EOL" aLight = vec3 (occWorldViewMatrix * vec4 (aLight, 0.0));"
332 EOL" vec3 aHalf = normalize (aLight + theView);"
334 EOL" vec3 aFaceSideNormal = theIsFront ? theNormal : -theNormal;"
335 EOL" float aNdotL = max (0.0, dot (aFaceSideNormal, aLight));"
336 EOL" float aNdotH = max (0.0, dot (aFaceSideNormal, aHalf ));"
338 EOL" float aSpecl = 0.0;"
339 EOL" if (aNdotL > 0.0)"
341 EOL" aSpecl = pow (aNdotH, theIsFront ? occFrontMaterial_Shininess() : occBackMaterial_Shininess());"
344 EOL" Diffuse += occLight_Diffuse(0) * aNdotL;"
345 EOL" Specular += occLight_Specular(0) * aSpecl;"
348 //! Returns the real cubemap fetching direction considering sides orientation, memory layout and vertical flip.
349 const char THE_FUNC_cubemap_vector_transform[] =
350 EOL"vec3 cubemapVectorTransform (in vec3 theVector,"
351 EOL" in int theYCoeff,"
352 EOL" in int theZCoeff)"
354 EOL" theVector = theVector.yzx;"
355 EOL" theVector.y *= float(theYCoeff);"
356 EOL" theVector.z *= float(theZCoeff);"
357 EOL" return theVector;"
360 //! Process clipping planes in Fragment Shader.
361 //! Should be added at the beginning of the main() function.
362 const char THE_FRAG_CLIP_PLANES_N[] =
363 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount; ++aPlaneIter)"
365 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
366 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)"
372 //! Process chains of clipping planes in Fragment Shader.
373 const char THE_FRAG_CLIP_CHAINS_N[] =
374 EOL" for (int aPlaneIter = 0; aPlaneIter < occClipPlaneCount;)"
376 EOL" vec4 aClipEquation = occClipPlaneEquations[aPlaneIter];"
377 EOL" if (dot (aClipEquation.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation.w < 0.0)"
379 EOL" if (occClipPlaneChains[aPlaneIter] == 1)"
383 EOL" aPlaneIter += 1;"
387 EOL" aPlaneIter += occClipPlaneChains[aPlaneIter];"
391 //! Process 1 clipping plane in Fragment Shader.
392 const char THE_FRAG_CLIP_PLANES_1[] =
393 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
394 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0)"
399 //! Process 2 clipping planes in Fragment Shader.
400 const char THE_FRAG_CLIP_PLANES_2[] =
401 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
402 EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];"
403 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0"
404 EOL" || dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)"
409 //! Process a chain of 2 clipping planes in Fragment Shader (3/4 section).
410 const char THE_FRAG_CLIP_CHAINS_2[] =
411 EOL" vec4 aClipEquation0 = occClipPlaneEquations[0];"
412 EOL" vec4 aClipEquation1 = occClipPlaneEquations[1];"
413 EOL" if (dot (aClipEquation0.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation0.w < 0.0"
414 EOL" && dot (aClipEquation1.xyz, PositionWorld.xyz / PositionWorld.w) + aClipEquation1.w < 0.0)"
419 //! Modify color for Wireframe presentation.
420 const char THE_FRAG_WIREFRAME_COLOR[] =
421 EOL"vec4 getFinalColor(void)"
423 EOL" float aDistance = min (min (EdgeDistance[0], EdgeDistance[1]), EdgeDistance[2]);"
424 EOL" bool isHollow = occWireframeColor.a < 0.0;"
425 EOL" float aMixVal = smoothstep (occLineWidth - occLineFeather * 0.5, occLineWidth + occLineFeather * 0.5, aDistance);"
426 EOL" vec4 aMixColor = isHollow"
427 EOL" ? vec4 (getColor().rgb, 1.0 - aMixVal)" // edges only (of interior color)
428 EOL" : mix (occWireframeColor, getColor(), aMixVal);" // interior + edges
429 EOL" return aMixColor;"
432 //! Compute gl_Position vertex shader output.
433 const char THE_VERT_gl_Position[] =
434 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * occVertex;";
436 //! Displace gl_Position alongside vertex normal for outline rendering.
437 //! This code adds silhouette only for smooth surfaces of closed primitive, and produces visual artifacts on sharp edges.
438 const char THE_VERT_gl_Position_OUTLINE[] =
439 EOL" float anOutlineDisp = occOrthoScale > 0.0 ? occOrthoScale : gl_Position.w;"
440 EOL" vec4 anOutlinePos = occVertex + vec4 (occNormal * (occSilhouetteThickness * anOutlineDisp), 0.0);"
441 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * anOutlinePos;";
443 #if !defined(GL_ES_VERSION_2_0)
445 static const GLfloat THE_DEFAULT_AMBIENT[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
446 static const GLfloat THE_DEFAULT_SPOT_DIR[3] = { 0.0f, 0.0f, -1.0f };
447 static const GLfloat THE_DEFAULT_SPOT_EXPONENT = 0.0f;
448 static const GLfloat THE_DEFAULT_SPOT_CUTOFF = 180.0f;
450 //! Bind FFP light source.
451 static void bindLight (const Graphic3d_CLight& theLight,
452 const GLenum theLightGlId,
453 const OpenGl_Mat4& theModelView,
454 OpenGl_Context* theCtx)
456 // the light is a headlight?
457 if (theLight.IsHeadlight())
459 theCtx->core11->glMatrixMode (GL_MODELVIEW);
460 theCtx->core11->glLoadIdentity();
464 const Graphic3d_Vec4& aLightColor = theLight.PackedColor();
465 switch (theLight.Type())
467 case Graphic3d_TOLS_AMBIENT : break; // handled by separate if-clause at beginning of method
468 case Graphic3d_TOLS_DIRECTIONAL:
470 // if the last parameter of GL_POSITION, is zero, the corresponding light source is a Directional one
471 const OpenGl_Vec4 anInfDir = -theLight.PackedDirectionRange();
473 // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE.
474 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
475 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
476 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
477 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, anInfDir.GetData());
478 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR);
479 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT);
480 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF);
483 case Graphic3d_TOLS_POSITIONAL:
485 // to create a realistic effect, set the GL_SPECULAR parameter to the same value as the GL_DIFFUSE
486 const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position().X()), static_cast<float>(theLight.Position().Y()), static_cast<float>(theLight.Position().Z()), 1.0f);
487 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
488 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
489 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
490 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, aPosition.GetData());
491 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, THE_DEFAULT_SPOT_DIR);
492 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, THE_DEFAULT_SPOT_EXPONENT);
493 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, THE_DEFAULT_SPOT_CUTOFF);
494 theCtx->core11->glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation());
495 theCtx->core11->glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation());
496 theCtx->core11->glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f);
499 case Graphic3d_TOLS_SPOT:
501 const OpenGl_Vec4 aPosition (static_cast<float>(theLight.Position().X()), static_cast<float>(theLight.Position().Y()), static_cast<float>(theLight.Position().Z()), 1.0f);
502 theCtx->core11->glLightfv (theLightGlId, GL_AMBIENT, THE_DEFAULT_AMBIENT);
503 theCtx->core11->glLightfv (theLightGlId, GL_DIFFUSE, aLightColor.GetData());
504 theCtx->core11->glLightfv (theLightGlId, GL_SPECULAR, aLightColor.GetData());
505 theCtx->core11->glLightfv (theLightGlId, GL_POSITION, aPosition.GetData());
506 theCtx->core11->glLightfv (theLightGlId, GL_SPOT_DIRECTION, theLight.PackedDirectionRange().GetData());
507 theCtx->core11->glLightf (theLightGlId, GL_SPOT_EXPONENT, theLight.Concentration() * 128.0f);
508 theCtx->core11->glLightf (theLightGlId, GL_SPOT_CUTOFF, (theLight.Angle() * 180.0f) / GLfloat(M_PI));
509 theCtx->core11->glLightf (theLightGlId, GL_CONSTANT_ATTENUATION, theLight.ConstAttenuation());
510 theCtx->core11->glLightf (theLightGlId, GL_LINEAR_ATTENUATION, theLight.LinearAttenuation());
511 theCtx->core11->glLightf (theLightGlId, GL_QUADRATIC_ATTENUATION, 0.0f);
516 // restore matrix in case of headlight
517 if (theLight.IsHeadlight())
519 theCtx->core11->glLoadMatrixf (theModelView.GetData());
522 glEnable (theLightGlId);
526 //! Generate map key for light sources configuration.
527 static TCollection_AsciiString genLightKey (const Handle(Graphic3d_LightSet)& theLights)
529 if (theLights->NbEnabled() <= THE_NB_UNROLLED_LIGHTS_MAX)
531 return TCollection_AsciiString ("l_") + theLights->KeyEnabledLong();
534 const Standard_Integer aMaxLimit = roundUpMaxLightSources (theLights->NbEnabled());
535 return TCollection_AsciiString ("l_") + theLights->KeyEnabledShort() + aMaxLimit;
539 // =======================================================================
540 // function : OpenGl_ShaderManager
541 // purpose : Creates new empty shader manager
542 // =======================================================================
543 OpenGl_ShaderManager::OpenGl_ShaderManager (OpenGl_Context* theContext)
544 : myFfpProgram (new OpenGl_ShaderProgramFFP()),
545 myShadingModel (Graphic3d_TOSM_VERTEX),
546 myUnlitPrograms (new OpenGl_SetOfPrograms()),
547 myContext (theContext),
548 mySRgbState (theContext->ToRenderSRGB()),
549 myHasLocalOrigin (Standard_False),
555 // =======================================================================
556 // function : ~OpenGl_ShaderManager
557 // purpose : Releases resources of shader manager
558 // =======================================================================
559 OpenGl_ShaderManager::~OpenGl_ShaderManager()
561 myProgramList.Clear();
562 if (!myPBREnvironment.IsNull())
564 myPBREnvironment->Release (myContext);
568 // =======================================================================
571 // =======================================================================
572 void OpenGl_ShaderManager::clear()
574 myProgramList.Clear();
575 myLightPrograms.Nullify();
576 myUnlitPrograms = new OpenGl_SetOfPrograms();
577 myOutlinePrograms.Nullify();
578 myMapOfLightPrograms.Clear();
579 myFontProgram.Nullify();
580 myBlitPrograms[0].Init (Handle(OpenGl_ShaderProgram)());
581 myBlitPrograms[1].Init (Handle(OpenGl_ShaderProgram)());
582 myBoundBoxProgram.Nullify();
583 myBoundBoxVertBuffer.Nullify();
584 for (Standard_Integer aModeIter = 0; aModeIter < Graphic3d_StereoMode_NB; ++aModeIter)
586 myStereoPrograms[aModeIter].Nullify();
588 switchLightPrograms();
591 // =======================================================================
593 // purpose : Creates new shader program
594 // =======================================================================
595 Standard_Boolean OpenGl_ShaderManager::Create (const Handle(Graphic3d_ShaderProgram)& theProxy,
596 TCollection_AsciiString& theShareKey,
597 Handle(OpenGl_ShaderProgram)& theProgram)
599 theProgram.Nullify();
600 if (theProxy.IsNull())
602 return Standard_False;
605 theShareKey = theProxy->GetId();
606 if (myContext->GetResource<Handle(OpenGl_ShaderProgram)> (theShareKey, theProgram))
608 if (theProgram->Share())
610 myProgramList.Append (theProgram);
612 return Standard_True;
615 theProgram = new OpenGl_ShaderProgram (theProxy);
616 if (!theProgram->Initialize (myContext, theProxy->ShaderObjects()))
618 theProgram->Release (myContext);
620 theProgram.Nullify();
621 return Standard_False;
624 myProgramList.Append (theProgram);
625 myContext->ShareResource (theShareKey, theProgram);
626 return Standard_True;
629 // =======================================================================
630 // function : Unregister
631 // purpose : Removes specified shader program from the manager
632 // =======================================================================
633 void OpenGl_ShaderManager::Unregister (TCollection_AsciiString& theShareKey,
634 Handle(OpenGl_ShaderProgram)& theProgram)
636 for (OpenGl_ShaderProgramList::Iterator anIt (myProgramList); anIt.More(); anIt.Next())
638 if (anIt.Value() == theProgram)
640 if (!theProgram->UnShare())
643 theProgram.Nullify();
647 myProgramList.Remove (anIt);
652 const TCollection_AsciiString anID = theProgram->myProxy->GetId();
655 myContext->DelayedRelease (theProgram);
656 theProgram.Nullify();
660 theProgram.Nullify();
661 myContext->ReleaseResource (anID, Standard_True);
665 // =======================================================================
666 // function : ShaderPrograms
667 // purpose : Returns list of registered shader programs
668 // =======================================================================
669 const OpenGl_ShaderProgramList& OpenGl_ShaderManager::ShaderPrograms() const
671 return myProgramList;
674 // =======================================================================
676 // purpose : Returns true if no program objects are attached
677 // =======================================================================
678 Standard_Boolean OpenGl_ShaderManager::IsEmpty() const
680 return myProgramList.IsEmpty();
683 // =======================================================================
684 // function : switchLightPrograms
686 // =======================================================================
687 void OpenGl_ShaderManager::switchLightPrograms()
689 const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources();
690 if (aLights.IsNull())
692 if (!myMapOfLightPrograms.Find ("unlit", myLightPrograms))
694 myLightPrograms = new OpenGl_SetOfShaderPrograms (myUnlitPrograms);
695 myMapOfLightPrograms.Bind ("unlit", myLightPrograms);
700 const TCollection_AsciiString aKey = genLightKey (aLights);
701 if (!myMapOfLightPrograms.Find (aKey, myLightPrograms))
703 myLightPrograms = new OpenGl_SetOfShaderPrograms();
704 myMapOfLightPrograms.Bind (aKey, myLightPrograms);
708 // =======================================================================
709 // function : UpdateSRgbState
711 // =======================================================================
712 void OpenGl_ShaderManager::UpdateSRgbState()
714 if (mySRgbState == myContext->ToRenderSRGB())
719 mySRgbState = myContext->ToRenderSRGB();
721 // special cases - GLSL programs dealing with sRGB/linearRGB internally
722 myStereoPrograms[Graphic3d_StereoMode_Anaglyph].Nullify();
725 // =======================================================================
726 // function : UpdateLightSourceStateTo
727 // purpose : Updates state of OCCT light sources
728 // =======================================================================
729 void OpenGl_ShaderManager::UpdateLightSourceStateTo (const Handle(Graphic3d_LightSet)& theLights,
730 Standard_Integer theSpecIBLMapLevels)
732 myLightSourceState.Set (theLights);
733 myLightSourceState.SetSpecIBLMapLevels (theSpecIBLMapLevels);
734 myLightSourceState.Update();
735 switchLightPrograms();
738 // =======================================================================
739 // function : UpdateLightSourceState
741 // =======================================================================
742 void OpenGl_ShaderManager::UpdateLightSourceState()
744 myLightSourceState.Update();
747 // =======================================================================
748 // function : SetShadingModel
750 // =======================================================================
751 void OpenGl_ShaderManager::SetShadingModel (const Graphic3d_TypeOfShadingModel theModel)
753 if (theModel == Graphic3d_TOSM_DEFAULT)
755 throw Standard_ProgramError ("OpenGl_ShaderManager::SetShadingModel() - attempt to set invalid Shading Model!");
758 myShadingModel = theModel;
759 switchLightPrograms();
762 // =======================================================================
763 // function : SetProjectionState
764 // purpose : Sets new state of OCCT projection transform
765 // =======================================================================
766 void OpenGl_ShaderManager::UpdateProjectionStateTo (const OpenGl_Mat4& theProjectionMatrix)
768 myProjectionState.Set (theProjectionMatrix);
769 myProjectionState.Update();
772 // =======================================================================
773 // function : SetModelWorldState
774 // purpose : Sets new state of OCCT model-world transform
775 // =======================================================================
776 void OpenGl_ShaderManager::UpdateModelWorldStateTo (const OpenGl_Mat4& theModelWorldMatrix)
778 myModelWorldState.Set (theModelWorldMatrix);
779 myModelWorldState.Update();
782 // =======================================================================
783 // function : SetWorldViewState
784 // purpose : Sets new state of OCCT world-view transform
785 // =======================================================================
786 void OpenGl_ShaderManager::UpdateWorldViewStateTo (const OpenGl_Mat4& theWorldViewMatrix)
788 myWorldViewState.Set (theWorldViewMatrix);
789 myWorldViewState.Update();
792 // =======================================================================
793 // function : pushLightSourceState
795 // =======================================================================
796 void OpenGl_ShaderManager::pushLightSourceState (const Handle(OpenGl_ShaderProgram)& theProgram) const
798 theProgram->UpdateState (OpenGl_LIGHT_SOURCES_STATE, myLightSourceState.Index());
799 if (theProgram == myFfpProgram)
801 #if !defined(GL_ES_VERSION_2_0)
802 if (myContext->core11 == NULL)
807 GLenum aLightGlId = GL_LIGHT0;
808 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
809 for (Graphic3d_LightSet::Iterator aLightIt (myLightSourceState.LightSources(), Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
810 aLightIt.More(); aLightIt.Next())
812 if (aLightGlId > GL_LIGHT7) // only 8 lights in FFP...
814 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
815 "Warning: light sources limit (8) has been exceeded within Fixed-function pipeline.");
819 bindLight (*aLightIt.Value(), aLightGlId, aModelView, myContext);
823 // apply accumulated ambient color
824 const Graphic3d_Vec4 anAmbient = !myLightSourceState.LightSources().IsNull()
825 ? myLightSourceState.LightSources()->AmbientColor()
826 : Graphic3d_Vec4 (0.0f, 0.0f, 0.0f, 1.0f);
827 myContext->core11->glLightModelfv (GL_LIGHT_MODEL_AMBIENT, anAmbient.GetData());
829 // GL_LIGHTING is managed by drawers to switch between shaded / no lighting output,
830 // therefore managing the state here does not have any effect - do it just for consistency.
831 if (aLightGlId != GL_LIGHT0)
833 ::glEnable (GL_LIGHTING);
837 ::glDisable (GL_LIGHTING);
839 // switch off unused lights
840 for (; aLightGlId <= GL_LIGHT7; ++aLightGlId)
842 ::glDisable (aLightGlId);
848 const Standard_Integer aNbLightsMax = theProgram->NbLightsMax();
849 const GLint anAmbientLoc = theProgram->GetStateLocation (OpenGl_OCC_LIGHT_AMBIENT);
850 if (aNbLightsMax == 0
851 && anAmbientLoc == OpenGl_ShaderProgram::INVALID_LOCATION)
856 if (myLightTypeArray.Size() < aNbLightsMax)
858 myLightTypeArray .Resize (0, aNbLightsMax - 1, false);
859 myLightParamsArray.Resize (0, aNbLightsMax - 1, false);
861 for (Standard_Integer aLightIt = 0; aLightIt < aNbLightsMax; ++aLightIt)
863 myLightTypeArray.SetValue (aLightIt, -1);
866 if (myLightSourceState.LightSources().IsNull()
867 || myLightSourceState.LightSources()->IsEmpty())
869 theProgram->SetUniform (myContext,
870 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
872 theProgram->SetUniform (myContext,
874 OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f));
875 theProgram->SetUniform (myContext,
876 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
878 &myLightTypeArray.First());
882 Standard_Integer aLightsNb = 0;
883 for (Graphic3d_LightSet::Iterator anIter (myLightSourceState.LightSources(), Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
884 anIter.More(); anIter.Next())
886 const Graphic3d_CLight& aLight = *anIter.Value();
887 if (aLightsNb >= aNbLightsMax)
889 if (aNbLightsMax != 0)
891 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
892 TCollection_AsciiString("Warning: light sources limit (") + aNbLightsMax + ") has been exceeded.");
897 Standard_Integer& aLightType = myLightTypeArray .ChangeValue (aLightsNb);
898 OpenGl_ShaderLightParameters& aLightParams = myLightParamsArray.ChangeValue (aLightsNb);
899 if (!aLight.IsEnabled()) // has no affect with Graphic3d_LightSet::IterationFilter_ExcludeDisabled - here just for consistency
901 // 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
902 aLightType = -1; // Graphic3d_TOLS_AMBIENT can be used instead
903 aLightParams.Color = OpenGl_Vec4 (0.0f, 0.0f, 0.0f, 0.0f);
908 // ignoring OpenGl_Context::ToRenderSRGB() for light colors,
909 // as non-absolute colors for lights are rare and require tuning anyway
910 aLightType = aLight.Type();
911 aLightParams.Color = aLight.PackedColor();
912 aLightParams.Color.a() = aLight.Intensity(); // used by PBR and ignored by old shading model
913 if (aLight.Type() == Graphic3d_TOLS_DIRECTIONAL)
915 aLightParams.Position = -aLight.PackedDirectionRange();
917 else if (!aLight.IsHeadlight())
919 aLightParams.Position.x() = static_cast<float>(aLight.Position().X() - myLocalOrigin.X());
920 aLightParams.Position.y() = static_cast<float>(aLight.Position().Y() - myLocalOrigin.Y());
921 aLightParams.Position.z() = static_cast<float>(aLight.Position().Z() - myLocalOrigin.Z());
925 aLightParams.Position.x() = static_cast<float>(aLight.Position().X());
926 aLightParams.Position.y() = static_cast<float>(aLight.Position().Y());
927 aLightParams.Position.z() = static_cast<float>(aLight.Position().Z());
929 aLightParams.Position.w() = aLight.IsHeadlight() ? 1.0f : 0.0f;
931 if (aLight.Type() == Graphic3d_TOLS_SPOT)
933 aLightParams.Direction = aLight.PackedDirectionRange();
935 if (aLight.Type() == Graphic3d_TOLS_POSITIONAL)
937 aLightParams.Direction.w() = aLight.Range();
939 aLightParams.Parameters = aLight.PackedParams();
943 const Graphic3d_Vec4& anAmbient = myLightSourceState.LightSources()->AmbientColor();
944 theProgram->SetUniform (myContext,
945 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_COUNT),
947 theProgram->SetUniform (myContext,
950 theProgram->SetUniform (myContext,
951 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_TYPES),
953 &myLightTypeArray.First());
956 theProgram->SetUniform (myContext,
957 theProgram->GetStateLocation (OpenGl_OCC_LIGHT_SOURCE_PARAMS),
958 aLightsNb * OpenGl_ShaderLightParameters::NbOfVec4(),
959 myLightParamsArray.First().Packed());
962 if (const OpenGl_ShaderUniformLocation aLocation = theProgram->GetStateLocation (OpenGl_OCCT_NB_SPEC_IBL_LEVELS))
964 theProgram->SetUniform (myContext, aLocation, myLightSourceState.SpecIBLMapLevels());
968 // =======================================================================
969 // function : pushProjectionState
971 // =======================================================================
972 void OpenGl_ShaderManager::pushProjectionState (const Handle(OpenGl_ShaderProgram)& theProgram) const
974 theProgram->UpdateState (OpenGl_PROJECTION_STATE, myProjectionState.Index());
975 if (theProgram == myFfpProgram)
977 #if !defined(GL_ES_VERSION_2_0)
978 if (myContext->core11 != NULL)
980 myContext->core11->glMatrixMode (GL_PROJECTION);
981 myContext->core11->glLoadMatrixf (myProjectionState.ProjectionMatrix());
987 theProgram->SetUniform (myContext,
988 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX),
989 myProjectionState.ProjectionMatrix());
991 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE);
992 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
994 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse());
997 theProgram->SetUniform (myContext,
998 theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE),
999 myProjectionState.ProjectionMatrix(), true);
1001 aLocation = theProgram->GetStateLocation (OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE);
1002 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
1004 theProgram->SetUniform (myContext, aLocation, myProjectionState.ProjectionMatrixInverse(), true);
1008 // =======================================================================
1009 // function : pushModelWorldState
1011 // =======================================================================
1012 void OpenGl_ShaderManager::pushModelWorldState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1014 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
1015 if (theProgram == myFfpProgram)
1017 #if !defined(GL_ES_VERSION_2_0)
1018 if (myContext->core11 != NULL)
1020 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
1021 myContext->core11->glMatrixMode (GL_MODELVIEW);
1022 myContext->core11->glLoadMatrixf (aModelView.GetData());
1023 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
1029 theProgram->SetUniform (myContext,
1030 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX),
1031 myModelWorldState.ModelWorldMatrix());
1033 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE);
1034 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
1036 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse());
1039 theProgram->SetUniform (myContext,
1040 theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE),
1041 myModelWorldState.ModelWorldMatrix(), true);
1043 aLocation = theProgram->GetStateLocation (OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE);
1044 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
1046 theProgram->SetUniform (myContext, aLocation, myModelWorldState.ModelWorldMatrixInverse(), true);
1050 // =======================================================================
1051 // function : pushWorldViewState
1053 // =======================================================================
1054 void OpenGl_ShaderManager::pushWorldViewState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1056 if (myWorldViewState.Index() == theProgram->ActiveState (OpenGl_WORLD_VIEW_STATE))
1061 theProgram->UpdateState (OpenGl_WORLD_VIEW_STATE, myWorldViewState.Index());
1062 if (theProgram == myFfpProgram)
1064 #if !defined(GL_ES_VERSION_2_0)
1065 if (myContext->core11 != NULL)
1067 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
1068 myContext->core11->glMatrixMode (GL_MODELVIEW);
1069 myContext->core11->glLoadMatrixf (aModelView.GetData());
1070 theProgram->UpdateState (OpenGl_MODEL_WORLD_STATE, myModelWorldState.Index());
1076 theProgram->SetUniform (myContext,
1077 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX),
1078 myWorldViewState.WorldViewMatrix());
1080 GLint aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE);
1081 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
1083 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse());
1086 theProgram->SetUniform (myContext,
1087 theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE),
1088 myWorldViewState.WorldViewMatrix(), true);
1090 aLocation = theProgram->GetStateLocation (OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE);
1091 if (aLocation != OpenGl_ShaderProgram::INVALID_LOCATION)
1093 theProgram->SetUniform (myContext, aLocation, myWorldViewState.WorldViewMatrixInverse(), true);
1097 // =======================================================================
1098 // function : UpdateClippingState
1099 // purpose : Updates state of OCCT clipping planes
1100 // =======================================================================
1101 void OpenGl_ShaderManager::UpdateClippingState()
1103 myClippingState.Update();
1106 // =======================================================================
1107 // function : RevertClippingState
1108 // purpose : Reverts state of OCCT clipping planes
1109 // =======================================================================
1110 void OpenGl_ShaderManager::RevertClippingState()
1112 myClippingState.Revert();
1115 // =======================================================================
1116 // function : pushClippingState
1118 // =======================================================================
1119 void OpenGl_ShaderManager::pushClippingState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1121 theProgram->UpdateState (OpenGl_CLIP_PLANES_STATE, myClippingState.Index());
1122 if (theProgram == myFfpProgram)
1124 #if !defined(GL_ES_VERSION_2_0)
1125 if (myContext->core11 == NULL)
1130 const Standard_Integer aNbMaxPlanes = myContext->MaxClipPlanes();
1131 if (myClipPlaneArrayFfp.Size() < aNbMaxPlanes)
1133 myClipPlaneArrayFfp.Resize (0, aNbMaxPlanes - 1, false);
1136 Standard_Integer aPlaneId = 0;
1137 Standard_Boolean toRestoreModelView = Standard_False;
1138 const Handle(Graphic3d_ClipPlane)& aCappedChain = myContext->Clipping().CappedChain();
1139 for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
1141 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
1142 if (aPlaneIter.IsDisabled()
1143 || aPlane->IsChain()
1144 || (aPlane == aCappedChain
1145 && myContext->Clipping().IsCappingEnableAllExcept()))
1149 else if (aPlaneId >= aNbMaxPlanes)
1151 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
1152 TCollection_ExtendedString("Warning: clipping planes limit (") + aNbMaxPlanes + ") has been exceeded.");
1156 const Graphic3d_ClipPlane::Equation& anEquation = aPlane->GetEquation();
1157 OpenGl_Vec4d& aPlaneEq = myClipPlaneArrayFfp.ChangeValue (aPlaneId);
1158 aPlaneEq.x() = anEquation.x();
1159 aPlaneEq.y() = anEquation.y();
1160 aPlaneEq.z() = anEquation.z();
1161 aPlaneEq.w() = anEquation.w();
1162 if (myHasLocalOrigin)
1164 const gp_XYZ aPos = aPlane->ToPlane().Position().Location().XYZ() - myLocalOrigin;
1165 const Standard_Real aD = -(anEquation.x() * aPos.X() + anEquation.y() * aPos.Y() + anEquation.z() * aPos.Z());
1169 const GLenum anFfpPlaneID = GL_CLIP_PLANE0 + aPlaneId;
1170 if (anFfpPlaneID == GL_CLIP_PLANE0)
1172 // set either identity or pure view matrix
1173 toRestoreModelView = Standard_True;
1174 myContext->core11->glMatrixMode (GL_MODELVIEW);
1175 myContext->core11->glLoadMatrixf (myWorldViewState.WorldViewMatrix().GetData());
1178 ::glEnable (anFfpPlaneID);
1179 myContext->core11->glClipPlane (anFfpPlaneID, aPlaneEq);
1184 // switch off unused lights
1185 for (; aPlaneId < aNbMaxPlanes; ++aPlaneId)
1187 ::glDisable (GL_CLIP_PLANE0 + aPlaneId);
1190 // restore combined model-view matrix
1191 if (toRestoreModelView)
1193 const OpenGl_Mat4 aModelView = myWorldViewState.WorldViewMatrix() * myModelWorldState.ModelWorldMatrix();
1194 myContext->core11->glLoadMatrixf (aModelView.GetData());
1200 const GLint aLocEquations = theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_EQUATIONS);
1201 if (aLocEquations == OpenGl_ShaderProgram::INVALID_LOCATION)
1206 const Standard_Integer aNbClipPlanesMax = theProgram->NbClipPlanesMax();
1207 const Standard_Integer aNbPlanes = Min (myContext->Clipping().NbClippingOrCappingOn(), aNbClipPlanesMax);
1210 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), 0);
1214 if (myClipPlaneArray.Size() < aNbClipPlanesMax)
1216 myClipPlaneArray.Resize (0, aNbClipPlanesMax - 1, false);
1217 myClipChainArray.Resize (0, aNbClipPlanesMax - 1, false);
1220 Standard_Integer aPlaneId = 0;
1221 const Handle(Graphic3d_ClipPlane)& aCappedChain = myContext->Clipping().CappedChain();
1222 for (OpenGl_ClippingIterator aPlaneIter (myContext->Clipping()); aPlaneIter.More(); aPlaneIter.Next())
1224 const Handle(Graphic3d_ClipPlane)& aPlane = aPlaneIter.Value();
1225 if (aPlaneIter.IsDisabled())
1230 if (myContext->Clipping().IsCappingDisableAllExcept())
1232 // enable only specific (sub) plane
1233 if (aPlane != aCappedChain)
1238 Standard_Integer aSubPlaneIndex = 1;
1239 for (const Graphic3d_ClipPlane* aSubPlaneIter = aCappedChain.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex)
1241 if (aSubPlaneIndex == myContext->Clipping().CappedSubPlane())
1243 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->GetEquation(), 1);
1249 else if (aPlane == aCappedChain) // && myContext->Clipping().IsCappingEnableAllExcept()
1251 // enable sub-planes within processed Chain as reversed and ORed, excluding filtered plane
1252 if (aPlaneId + aPlane->NbChainNextPlanes() - 1 > aNbClipPlanesMax)
1254 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
1255 TCollection_AsciiString("Error: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded.");
1259 Standard_Integer aSubPlaneIndex = 1;
1260 for (const Graphic3d_ClipPlane* aSubPlaneIter = aPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get(), ++aSubPlaneIndex)
1262 if (aSubPlaneIndex != -myContext->Clipping().CappedSubPlane())
1264 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->ReversedEquation(), 1);
1271 if (aPlaneId + aPlane->NbChainNextPlanes() > aNbClipPlanesMax)
1273 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH,
1274 TCollection_AsciiString("Error: clipping planes limit (") + aNbClipPlanesMax + ") has been exceeded.");
1277 for (const Graphic3d_ClipPlane* aSubPlaneIter = aPlane.get(); aSubPlaneIter != NULL; aSubPlaneIter = aSubPlaneIter->ChainNextPlane().get())
1279 addClippingPlane (aPlaneId, *aSubPlaneIter, aSubPlaneIter->GetEquation(), aSubPlaneIter->NbChainNextPlanes());
1284 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_COUNT), aPlaneId);
1285 theProgram->SetUniform (myContext, aLocEquations, aNbClipPlanesMax, &myClipPlaneArray.First());
1286 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCC_CLIP_PLANE_CHAINS), aNbClipPlanesMax, &myClipChainArray.First());
1289 // =======================================================================
1290 // function : pushMaterialState
1292 // =======================================================================
1293 void OpenGl_ShaderManager::pushMaterialState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1295 const OpenGl_Material& aFrontMat = myMaterialState.FrontMaterial();
1296 const OpenGl_Material& aBackMat = myMaterialState.BackMaterial();
1297 theProgram->UpdateState (OpenGl_MATERIAL_STATE, myMaterialState.Index());
1298 if (theProgram == myFfpProgram)
1300 #if !defined(GL_ES_VERSION_2_0)
1301 if (myContext->core11 == NULL)
1306 if (myMaterialState.AlphaCutoff() < ShortRealLast())
1308 glAlphaFunc (GL_GEQUAL, myMaterialState.AlphaCutoff());
1309 glEnable (GL_ALPHA_TEST);
1313 glDisable (GL_ALPHA_TEST);
1316 const GLenum aFrontFace = myMaterialState.ToDistinguish() ? GL_FRONT : GL_FRONT_AND_BACK;
1317 myContext->core11->glMaterialfv(aFrontFace, GL_AMBIENT, aFrontMat.Common.Ambient.GetData());
1318 myContext->core11->glMaterialfv(aFrontFace, GL_DIFFUSE, aFrontMat.Common.Diffuse.GetData());
1319 myContext->core11->glMaterialfv(aFrontFace, GL_SPECULAR, aFrontMat.Common.Specular.GetData());
1320 myContext->core11->glMaterialfv(aFrontFace, GL_EMISSION, aFrontMat.Common.Emission.GetData());
1321 myContext->core11->glMaterialf (aFrontFace, GL_SHININESS, aFrontMat.Common.Shine());
1322 if (myMaterialState.ToDistinguish())
1324 myContext->core11->glMaterialfv(GL_BACK, GL_AMBIENT, aBackMat.Common.Ambient.GetData());
1325 myContext->core11->glMaterialfv(GL_BACK, GL_DIFFUSE, aBackMat.Common.Diffuse.GetData());
1326 myContext->core11->glMaterialfv(GL_BACK, GL_SPECULAR, aBackMat.Common.Specular.GetData());
1327 myContext->core11->glMaterialfv(GL_BACK, GL_EMISSION, aBackMat.Common.Emission.GetData());
1328 myContext->core11->glMaterialf (GL_BACK, GL_SHININESS, aBackMat.Common.Shine());
1334 theProgram->SetUniform (myContext,
1335 theProgram->GetStateLocation (OpenGl_OCCT_ALPHA_CUTOFF),
1336 myMaterialState.AlphaCutoff());
1337 theProgram->SetUniform (myContext,
1338 theProgram->GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE),
1339 myMaterialState.ToMapTexture() ? 1 : 0);
1340 theProgram->SetUniform (myContext,
1341 theProgram->GetStateLocation (OpenGl_OCCT_DISTINGUISH_MODE),
1342 myMaterialState.ToDistinguish() ? 1 : 0);
1344 if (const OpenGl_ShaderUniformLocation& aLocPbrFront = theProgram->GetStateLocation (OpenGl_OCCT_PBR_FRONT_MATERIAL))
1346 theProgram->SetUniform (myContext, aLocPbrFront, OpenGl_MaterialPBR::NbOfVec4(),
1347 aFrontMat.Pbr.Packed());
1349 if (const OpenGl_ShaderUniformLocation aLocPbrBack = theProgram->GetStateLocation (OpenGl_OCCT_PBR_BACK_MATERIAL))
1351 theProgram->SetUniform (myContext, aLocPbrBack, OpenGl_MaterialPBR::NbOfVec4(),
1352 aBackMat.Pbr.Packed());
1354 if (const OpenGl_ShaderUniformLocation aLocFront = theProgram->GetStateLocation (OpenGl_OCCT_COMMON_FRONT_MATERIAL))
1356 theProgram->SetUniform (myContext, aLocFront, OpenGl_MaterialCommon::NbOfVec4(),
1357 aFrontMat.Common.Packed());
1359 if (const OpenGl_ShaderUniformLocation aLocBack = theProgram->GetStateLocation (OpenGl_OCCT_COMMON_BACK_MATERIAL))
1361 theProgram->SetUniform (myContext, aLocBack, OpenGl_MaterialCommon::NbOfVec4(),
1362 aBackMat.Common.Packed());
1366 // =======================================================================
1367 // function : pushOitState
1369 // =======================================================================
1370 void OpenGl_ShaderManager::pushOitState (const Handle(OpenGl_ShaderProgram)& theProgram) const
1372 const GLint aLocOutput = theProgram->GetStateLocation (OpenGl_OCCT_OIT_OUTPUT);
1373 if (aLocOutput != OpenGl_ShaderProgram::INVALID_LOCATION)
1375 theProgram->SetUniform (myContext, aLocOutput, myOitState.ToEnableWrite());
1378 const GLint aLocDepthFactor = theProgram->GetStateLocation (OpenGl_OCCT_OIT_DEPTH_FACTOR);
1379 if (aLocDepthFactor != OpenGl_ShaderProgram::INVALID_LOCATION)
1381 theProgram->SetUniform (myContext, aLocDepthFactor, myOitState.DepthFactor());
1385 // =======================================================================
1386 // function : PushInteriorState
1388 // =======================================================================
1389 void OpenGl_ShaderManager::PushInteriorState (const Handle(OpenGl_ShaderProgram)& theProgram,
1390 const Handle(Graphic3d_Aspects)& theAspect) const
1392 if (theProgram.IsNull()
1393 || !theProgram->IsValid())
1398 if (const OpenGl_ShaderUniformLocation aLocLineWidth = theProgram->GetStateLocation (OpenGl_OCCT_LINE_WIDTH))
1400 theProgram->SetUniform (myContext, aLocLineWidth, theAspect->EdgeWidth() * myContext->LineWidthScale());
1401 theProgram->SetUniform (myContext, theProgram->GetStateLocation (OpenGl_OCCT_LINE_FEATHER), myContext->LineFeather() * myContext->LineWidthScale());
1403 if (const OpenGl_ShaderUniformLocation aLocWireframeColor = theProgram->GetStateLocation (OpenGl_OCCT_WIREFRAME_COLOR))
1405 if (theAspect->InteriorStyle() == Aspect_IS_HOLLOW)
1407 theProgram->SetUniform (myContext, aLocWireframeColor, OpenGl_Vec4 (-1.0f, -1.0f, -1.0f, -1.0f));
1411 theProgram->SetUniform (myContext, aLocWireframeColor, myContext->Vec4FromQuantityColor (theAspect->EdgeColorRGBA()));
1414 if (const OpenGl_ShaderUniformLocation aLocQuadModeState = theProgram->GetStateLocation (OpenGl_OCCT_QUAD_MODE_STATE))
1416 theProgram->SetUniform (myContext, aLocQuadModeState, theAspect->ToSkipFirstEdge() ? 1 : 0);
1420 // =======================================================================
1421 // function : PushState
1422 // purpose : Pushes state of OCCT graphics parameters to the program
1423 // =======================================================================
1424 void OpenGl_ShaderManager::PushState (const Handle(OpenGl_ShaderProgram)& theProgram,
1425 Graphic3d_TypeOfShadingModel theShadingModel) const
1427 const Handle(OpenGl_ShaderProgram)& aProgram = !theProgram.IsNull() ? theProgram : myFfpProgram;
1428 PushClippingState (aProgram);
1429 PushWorldViewState (aProgram);
1430 PushModelWorldState (aProgram);
1431 PushProjectionState (aProgram);
1432 PushLightSourceState (aProgram);
1433 PushMaterialState (aProgram);
1434 PushOitState (aProgram);
1436 if (!theProgram.IsNull())
1438 if (const OpenGl_ShaderUniformLocation& aLocViewPort = theProgram->GetStateLocation (OpenGl_OCCT_VIEWPORT))
1440 theProgram->SetUniform (myContext, aLocViewPort, OpenGl_Vec4 ((float )myContext->Viewport()[0], (float )myContext->Viewport()[1],
1441 (float )myContext->Viewport()[2], (float )myContext->Viewport()[3]));
1444 #if !defined(GL_ES_VERSION_2_0)
1445 else if (myContext->core11 != NULL)
1447 // manage FFP lighting
1448 myContext->SetShadeModel (theShadingModel);
1449 if (theShadingModel == Graphic3d_TOSM_UNLIT)
1451 glDisable (GL_LIGHTING);
1455 glEnable (GL_LIGHTING);
1459 (void )theShadingModel;
1463 // =======================================================================
1464 // function : prepareStdProgramFont
1466 // =======================================================================
1467 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFont()
1469 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1470 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT));
1471 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1473 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
1476 EOL" TexCoord = occTexCoord.st;"
1477 + THE_VERT_gl_Position
1480 TCollection_AsciiString
1481 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).a; }";
1482 #if !defined(GL_ES_VERSION_2_0)
1483 if (myContext->core11 == NULL)
1485 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st).r; }";
1489 TCollection_AsciiString aSrcFrag =
1493 EOL" vec4 aColor = occColor;"
1494 EOL" aColor.a *= getAlpha();"
1495 EOL" if (aColor.a <= 0.285) discard;"
1496 EOL" occSetFragColor (aColor);"
1499 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1500 defaultGlslVersion (aProgramSrc, "font", 0);
1501 aProgramSrc->SetDefaultSampler (false);
1502 aProgramSrc->SetNbLightsMax (0);
1503 aProgramSrc->SetNbClipPlanesMax (0);
1504 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1505 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
1506 TCollection_AsciiString aKey;
1507 if (!Create (aProgramSrc, aKey, myFontProgram))
1509 myFontProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1510 return Standard_False;
1512 return Standard_True;
1515 // =======================================================================
1516 // function : BindFboBlitProgram
1518 // =======================================================================
1519 Standard_Boolean OpenGl_ShaderManager::BindFboBlitProgram (Standard_Integer theNbSamples,
1520 Standard_Boolean theIsFallback_sRGB)
1522 NCollection_Array1<Handle(OpenGl_ShaderProgram)>& aList = myBlitPrograms[theIsFallback_sRGB ? 1 : 0];
1523 Standard_Integer aNbSamples = Max (theNbSamples, 1);
1524 if (aNbSamples > aList.Upper())
1526 aList.Resize (1, aNbSamples, true);
1529 Handle(OpenGl_ShaderProgram)& aProg = aList[aNbSamples];
1532 prepareStdProgramFboBlit (aProg, aNbSamples, theIsFallback_sRGB);
1534 return !aProg.IsNull()
1535 && myContext->BindProgram (aProg);
1538 // =======================================================================
1539 // function : prepareStdProgramFboBlit
1541 // =======================================================================
1542 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramFboBlit (Handle(OpenGl_ShaderProgram)& theProgram,
1543 Standard_Integer theNbSamples,
1544 Standard_Boolean theIsFallback_sRGB)
1546 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1547 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1549 TCollection_AsciiString aSrcVert =
1552 EOL" TexCoord = occVertex.zw;"
1553 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
1556 TCollection_AsciiString aSrcFrag;
1557 if (theNbSamples > 1)
1559 #if defined(GL_ES_VERSION_2_0)
1560 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("highp sampler2DMS uColorSampler", Graphic3d_TOS_FRAGMENT));
1561 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("highp sampler2DMS uDepthSampler", Graphic3d_TOS_FRAGMENT));
1563 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uColorSampler", Graphic3d_TOS_FRAGMENT));
1564 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uDepthSampler", Graphic3d_TOS_FRAGMENT));
1566 aSrcFrag = TCollection_AsciiString()
1567 + EOL"#define THE_NUM_SAMPLES " + theNbSamples
1568 + (theIsFallback_sRGB ? EOL"#define THE_SHIFT_sRGB" : "")
1571 EOL" ivec2 aSize = textureSize (uColorSampler);"
1572 EOL" ivec2 anUV = ivec2 (vec2 (aSize) * TexCoord);"
1573 EOL" gl_FragDepth = texelFetch (uDepthSampler, anUV, THE_NUM_SAMPLES / 2 - 1).r;"
1575 EOL" vec4 aColor = vec4 (0.0);"
1576 EOL" for (int aSample = 0; aSample < THE_NUM_SAMPLES; ++aSample)"
1578 EOL" vec4 aVal = texelFetch (uColorSampler, anUV, aSample);"
1579 EOL" aColor += aVal;"
1581 EOL" aColor /= float(THE_NUM_SAMPLES);"
1582 EOL"#ifdef THE_SHIFT_sRGB"
1583 EOL" aColor.rgb = pow (aColor.rgb, vec3 (1.0 / 2.2));"
1585 EOL" occSetFragColor (aColor);"
1590 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uColorSampler", Graphic3d_TOS_FRAGMENT));
1591 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uDepthSampler", Graphic3d_TOS_FRAGMENT));
1592 aSrcFrag = TCollection_AsciiString()
1593 + (theIsFallback_sRGB ? EOL"#define THE_SHIFT_sRGB" : "")
1596 EOL" gl_FragDepth = occTexture2D (uDepthSampler, TexCoord).r;"
1597 EOL" vec4 aColor = occTexture2D (uColorSampler, TexCoord);"
1598 EOL"#ifdef THE_SHIFT_sRGB"
1599 EOL" aColor.rgb = pow (aColor.rgb, vec3 (1.0 / 2.2));"
1601 EOL" occSetFragColor (aColor);"
1605 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1606 #if defined(GL_ES_VERSION_2_0)
1607 if (myContext->IsGlGreaterEqual (3, 1))
1609 // required for MSAA sampler
1610 aProgramSrc->SetHeader ("#version 310 es");
1612 else if (myContext->IsGlGreaterEqual (3, 0))
1614 aProgramSrc->SetHeader ("#version 300 es");
1616 else if (myContext->extFragDepth)
1618 aProgramSrc->SetHeader ("#extension GL_EXT_frag_depth : enable"
1619 EOL"#define gl_FragDepth gl_FragDepthEXT");
1623 // there is no way to draw into depth buffer
1627 EOL" occSetFragColor (occTexture2D (uColorSampler, TexCoord));"
1631 if (myContext->core32 != NULL)
1633 aProgramSrc->SetHeader ("#version 150");
1636 TCollection_AsciiString anId = "occt_blit";
1637 if (theNbSamples > 1)
1639 anId += TCollection_AsciiString ("_msaa") + theNbSamples;
1641 if (theIsFallback_sRGB)
1645 aProgramSrc->SetId (anId);
1646 aProgramSrc->SetDefaultSampler (false);
1647 aProgramSrc->SetNbLightsMax (0);
1648 aProgramSrc->SetNbClipPlanesMax (0);
1649 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1650 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
1651 TCollection_AsciiString aKey;
1652 if (!Create (aProgramSrc, aKey, theProgram))
1654 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1655 return Standard_False;
1658 myContext->BindProgram (theProgram);
1659 theProgram->SetSampler (myContext, "uColorSampler", Graphic3d_TextureUnit_0);
1660 theProgram->SetSampler (myContext, "uDepthSampler", Graphic3d_TextureUnit_1);
1661 myContext->BindProgram (NULL);
1662 return Standard_True;
1665 // =======================================================================
1666 // function : prepareStdProgramOitCompositing
1668 // =======================================================================
1669 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramOitCompositing (const Standard_Boolean theMsaa)
1671 Handle(OpenGl_ShaderProgram)& aProgram = myOitCompositingProgram[theMsaa ? 1 : 0];
1672 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1673 TCollection_AsciiString aSrcVert, aSrcFrag;
1675 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1676 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1681 EOL" TexCoord = occVertex.zw;"
1682 EOL" gl_Position = vec4 (occVertex.x, occVertex.y, 0.0, 1.0);"
1687 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uAccumTexture", Graphic3d_TOS_FRAGMENT));
1688 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uWeightTexture", Graphic3d_TOS_FRAGMENT));
1692 EOL" vec4 aAccum = occTexture2D (uAccumTexture, TexCoord);"
1693 EOL" float aWeight = occTexture2D (uWeightTexture, TexCoord).r;"
1694 EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
1696 #if !defined(GL_ES_VERSION_2_0)
1697 if (myContext->IsGlGreaterEqual (3, 2))
1699 aProgramSrc->SetHeader ("#version 150");
1702 if (myContext->IsGlGreaterEqual (3, 0))
1704 aProgramSrc->SetHeader ("#version 300 es");
1710 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uAccumTexture", Graphic3d_TOS_FRAGMENT));
1711 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2DMS uWeightTexture", Graphic3d_TOS_FRAGMENT));
1715 EOL" ivec2 aTexel = ivec2 (vec2 (textureSize (uAccumTexture)) * TexCoord);"
1716 EOL" vec4 aAccum = texelFetch (uAccumTexture, aTexel, gl_SampleID);"
1717 EOL" float aWeight = texelFetch (uWeightTexture, aTexel, gl_SampleID).r;"
1718 EOL" occSetFragColor (vec4 (aAccum.rgb / max (aWeight, 0.00001), aAccum.a));"
1720 #if !defined(GL_ES_VERSION_2_0)
1721 if (myContext->IsGlGreaterEqual (4, 0))
1723 aProgramSrc->SetHeader ("#version 400");
1726 if (myContext->IsGlGreaterEqual (3, 2))
1728 aProgramSrc->SetHeader ("#version 320 es");
1730 else if (myContext->IsGlGreaterEqual (3, 0))
1732 aProgramSrc->SetHeader ("#version 300 es"); // with GL_OES_sample_variables extension
1737 aProgramSrc->SetId (theMsaa ? "occt_weight-oit-msaa" : "occt_weight-oit");
1738 aProgramSrc->SetDefaultSampler (false);
1739 aProgramSrc->SetNbLightsMax (0);
1740 aProgramSrc->SetNbClipPlanesMax (0);
1741 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
1742 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
1743 TCollection_AsciiString aKey;
1744 if (!Create (aProgramSrc, aKey, aProgram))
1746 aProgram = new OpenGl_ShaderProgram(); // just mark as invalid
1747 return Standard_False;
1750 myContext->BindProgram (aProgram);
1751 aProgram->SetSampler (myContext, "uAccumTexture", Graphic3d_TextureUnit_0);
1752 aProgram->SetSampler (myContext, "uWeightTexture", Graphic3d_TextureUnit_1);
1753 myContext->BindProgram (Handle(OpenGl_ShaderProgram)());
1754 return Standard_True;
1757 // =======================================================================
1758 // function : pointSpriteAlphaSrc
1760 // =======================================================================
1761 TCollection_AsciiString OpenGl_ShaderManager::pointSpriteAlphaSrc (Standard_Integer theBits)
1763 TCollection_AsciiString aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ").a; }";
1764 #if !defined(GL_ES_VERSION_2_0)
1765 if (myContext->core11 == NULL
1766 && (theBits & OpenGl_PO_PointSpriteA) == OpenGl_PO_PointSpriteA)
1768 aSrcGetAlpha = EOL"float getAlpha(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ").r; }";
1773 return aSrcGetAlpha;
1776 // =======================================================================
1777 // function : defaultGlslVersion
1779 // =======================================================================
1780 int OpenGl_ShaderManager::defaultGlslVersion (const Handle(Graphic3d_ShaderProgram)& theProgram,
1781 const TCollection_AsciiString& theName,
1783 bool theUsesDerivates) const
1785 int aBits = theBits;
1786 const bool toUseDerivates = theUsesDerivates
1787 || (theBits & OpenGl_PO_StippleLine) != 0
1788 || (theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureNormal;
1789 #if !defined(GL_ES_VERSION_2_0)
1790 if (myContext->core32 != NULL)
1792 theProgram->SetHeader ("#version 150");
1796 if ((theBits & OpenGl_PO_StippleLine) != 0
1797 || theProgram->IsPBR())
1799 if (myContext->IsGlGreaterEqual (3, 0))
1801 theProgram->SetHeader ("#version 130");
1803 else if (myContext->CheckExtension ("GL_EXT_gpu_shader4")) // myContext->hasGlslBitwiseOps == OpenGl_FeatureInExtensions
1805 // GL_EXT_gpu_shader4 defines GLSL type "unsigned int", while core GLSL specs define type "uint"
1806 theProgram->SetHeader ("#extension GL_EXT_gpu_shader4 : enable\n"
1807 "#define uint unsigned int");
1811 (void )toUseDerivates;
1814 #if defined(__EMSCRIPTEN__)
1815 if (myContext->IsGlGreaterEqual (3, 0))
1817 // consider this is browser responsibility to provide working WebGL 2.0 implementation
1818 // and black-list broken drivers (there is no OpenGL ES greater than 3.0)
1819 theProgram->SetHeader ("#version 300 es");
1822 // prefer "100 es" on OpenGL ES 3.0- devices (save the features unavailable before "300 es")
1823 // and "300 es" on OpenGL ES 3.1+ devices
1824 if (myContext->IsGlGreaterEqual (3, 1))
1826 if ((theBits & OpenGl_PO_NeedsGeomShader) != 0)
1828 theProgram->SetHeader (myContext->hasGeometryStage != OpenGl_FeatureInExtensions ? "#version 320 es" : "#version 310 es");
1832 theProgram->SetHeader ("#version 300 es");
1837 if (theProgram->IsPBR()
1838 && myContext->IsGlGreaterEqual (3, 0))
1840 theProgram->SetHeader ("#version 300 es");
1842 if ((theBits & OpenGl_PO_WriteOit) != 0
1843 || (theBits & OpenGl_PO_StippleLine) != 0)
1845 if (myContext->IsGlGreaterEqual (3, 0))
1847 theProgram->SetHeader ("#version 300 es");
1851 aBits = aBits & ~OpenGl_PO_WriteOit;
1852 if (!myContext->oesStdDerivatives)
1854 aBits = aBits & ~OpenGl_PO_StippleLine;
1860 if (myContext->IsGlGreaterEqual (3, 0))
1862 theProgram->SetHeader ("#version 300 es");
1864 else if (myContext->oesStdDerivatives)
1866 theProgram->SetHeader ("#extension GL_OES_standard_derivatives : enable");
1872 // should fit OpenGl_PO_NB
1874 Sprintf (aBitsStr, "%04x", aBits);
1875 theProgram->SetId (TCollection_AsciiString ("occt_") + theName + aBitsStr);
1879 // =======================================================================
1880 // function : prepareGeomMainSrc
1882 // =======================================================================
1883 TCollection_AsciiString OpenGl_ShaderManager::prepareGeomMainSrc (OpenGl_ShaderObject::ShaderVariableList& theUnifoms,
1884 OpenGl_ShaderObject::ShaderVariableList& theStageInOuts,
1885 Standard_Integer theBits)
1887 if ((theBits & OpenGl_PO_NeedsGeomShader) == 0)
1889 return TCollection_AsciiString();
1892 TCollection_AsciiString aSrcMainGeom =
1896 if ((theBits & OpenGl_PO_MeshEdges) != 0)
1898 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occViewport", Graphic3d_TOS_GEOMETRY));
1899 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("bool occIsQuadMode", Graphic3d_TOS_GEOMETRY));
1900 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineWidth", Graphic3d_TOS_GEOMETRY));
1901 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineWidth", Graphic3d_TOS_FRAGMENT));
1902 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("float occLineFeather", Graphic3d_TOS_FRAGMENT));
1903 theUnifoms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occWireframeColor", Graphic3d_TOS_FRAGMENT));
1904 theStageInOuts.Append(OpenGl_ShaderObject::ShaderVariable ("vec3 EdgeDistance", Graphic3d_TOS_GEOMETRY | Graphic3d_TOS_FRAGMENT));
1906 aSrcMainGeom = TCollection_AsciiString()
1907 + EOL"vec3 ViewPortTransform (vec4 theVec)"
1909 EOL" vec3 aWinCoord = theVec.xyz / theVec.w;"
1910 EOL" aWinCoord = aWinCoord * 0.5 + 0.5;"
1911 EOL" aWinCoord.xy = aWinCoord.xy * occViewport.zw + occViewport.xy;"
1912 EOL" return aWinCoord;"
1915 + EOL" vec3 aSideA = ViewPortTransform (gl_in[2].gl_Position) - ViewPortTransform (gl_in[1].gl_Position);"
1916 EOL" vec3 aSideB = ViewPortTransform (gl_in[2].gl_Position) - ViewPortTransform (gl_in[0].gl_Position);"
1917 EOL" vec3 aSideC = ViewPortTransform (gl_in[1].gl_Position) - ViewPortTransform (gl_in[0].gl_Position);"
1918 EOL" float aQuadArea = abs (aSideB.x * aSideC.y - aSideB.y * aSideC.x);"
1919 EOL" vec3 aLenABC = vec3 (length (aSideA), length (aSideB), length (aSideC));"
1920 EOL" vec3 aHeightABC = vec3 (aQuadArea) / aLenABC;"
1921 EOL" aHeightABC = max (aHeightABC, vec3 (10.0 * occLineWidth));" // avoid shrunk presentation disappearing at distance
1922 EOL" float aQuadModeHeightC = occIsQuadMode ? occLineWidth + 1.0 : 0.0;";
1925 for (Standard_Integer aVertIter = 0; aVertIter < 3; ++aVertIter)
1927 const TCollection_AsciiString aVertIndex (aVertIter);
1928 // pass variables from Vertex shader to Fragment shader through Geometry shader
1929 for (OpenGl_ShaderObject::ShaderVariableList::Iterator aVarListIter (theStageInOuts); aVarListIter.More(); aVarListIter.Next())
1931 if (aVarListIter.Value().Stages == (Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT))
1933 const TCollection_AsciiString aVarName = aVarListIter.Value().Name.Token (" ", 2);
1934 aSrcMainGeom += TCollection_AsciiString()
1935 + EOL" geomOut." + aVarName + " = geomIn[" + aVertIndex + "]." + aVarName + ";";
1939 if ((theBits & OpenGl_PO_MeshEdges) != 0)
1943 case 0: aSrcMainGeom += EOL" EdgeDistance = vec3 (aHeightABC[0], 0.0, aQuadModeHeightC);"; break;
1944 case 1: aSrcMainGeom += EOL" EdgeDistance = vec3 (0.0, aHeightABC[1], aQuadModeHeightC);"; break;
1945 case 2: aSrcMainGeom += EOL" EdgeDistance = vec3 (0.0, 0.0, aHeightABC[2]);"; break;
1948 aSrcMainGeom += TCollection_AsciiString()
1949 + EOL" gl_Position = gl_in[" + aVertIndex + "].gl_Position;"
1950 EOL" EmitVertex();";
1953 EOL" EndPrimitive();"
1956 return aSrcMainGeom;
1959 // =======================================================================
1960 // function : prepareStdProgramUnlit
1962 // =======================================================================
1963 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramUnlit (Handle(OpenGl_ShaderProgram)& theProgram,
1964 Standard_Integer theBits,
1965 Standard_Boolean theIsOutline)
1967 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
1968 TCollection_AsciiString aSrcVert, aSrcVertExtraMain, aSrcVertExtraFunc, aSrcGetAlpha, aSrcVertEndMain;
1969 TCollection_AsciiString aSrcFrag, aSrcFragExtraMain;
1970 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return occColor; }";
1971 TCollection_AsciiString aSrcFragMainGetColor = EOL" occSetFragColor (getFinalColor());";
1972 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
1974 if ((theBits & OpenGl_PO_IsPoint) != 0)
1976 #if defined(GL_ES_VERSION_2_0)
1977 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
1980 if ((theBits & OpenGl_PO_PointSprite) != 0)
1982 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT));
1983 if ((theBits & OpenGl_PO_PointSpriteA) != OpenGl_PO_PointSpriteA)
1986 EOL"vec4 getColor(void) { return occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord "); }";
1988 else if ((theBits & OpenGl_PO_TextureRGB) != 0
1989 && (theBits & OpenGl_PO_VertColor) == 0)
1991 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
1992 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX));
1993 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
1994 aSrcVertExtraMain +=
1995 EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);";
1997 EOL"vec4 getColor(void) { return VertColor; }";
2000 aSrcGetAlpha = pointSpriteAlphaSrc (theBits);
2002 #if !defined(GL_ES_VERSION_2_0)
2003 if (myContext->core11 != NULL
2004 && myContext->IsGlGreaterEqual (2, 1))
2006 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
2010 aSrcFragMainGetColor =
2011 EOL" vec4 aColor = getColor();"
2012 EOL" aColor.a = getAlpha();"
2013 EOL" if (aColor.a <= 0.1) discard;"
2014 EOL" occSetFragColor (aColor);";
2018 if ((theBits & OpenGl_PO_TextureRGB) != 0
2019 && (theBits & OpenGl_PO_VertColor) == 0)
2021 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
2022 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX));
2023 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2024 aSrcVertExtraMain +=
2025 EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);";
2027 EOL"vec4 getColor(void) { return VertColor; }";
2030 aSrcFragMainGetColor =
2031 EOL" vec4 aColor = getColor();"
2032 EOL" if (aColor.a <= 0.1) discard;"
2033 EOL" occSetFragColor (aColor);";
2038 if ((theBits & OpenGl_PO_HasTextures) != 0)
2040 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT));
2041 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2043 if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureEnv)
2045 aSrcVertExtraFunc = THE_FUNC_transformNormal_view;
2047 aSrcVertExtraMain +=
2048 EOL" vec4 aPosition = occWorldViewMatrix * occModelWorldMatrix * occVertex;"
2049 EOL" vec3 aNormal = transformNormal (occNormal);"
2050 EOL" vec3 aReflect = reflect (normalize (aPosition.xyz), aNormal);"
2051 EOL" aReflect.z += 1.0;"
2052 EOL" TexCoord = vec4(aReflect.xy * inversesqrt (dot (aReflect, aReflect)) * 0.5 + vec2 (0.5), 0.0, 1.0);";
2055 EOL"vec4 getColor(void) { return occTexture2D (occSamplerBaseColor, TexCoord.st); }";
2059 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
2060 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
2063 EOL"vec4 getColor(void) { return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w); }";
2067 if ((theBits & OpenGl_PO_VertColor) != 0)
2069 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2070 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
2071 aSrcFragGetColor = EOL"vec4 getColor(void) { return VertColor; }";
2074 int aNbClipPlanes = 0;
2075 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
2077 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2078 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2079 aSrcVertExtraMain +=
2080 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
2081 EOL" Position = occWorldViewMatrix * PositionWorld;";
2083 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
2085 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
2086 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2087 ? THE_FRAG_CLIP_CHAINS_N
2088 : THE_FRAG_CLIP_PLANES_N;
2090 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
2093 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
2095 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
2098 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2099 ? THE_FRAG_CLIP_CHAINS_2
2100 : THE_FRAG_CLIP_PLANES_2;
2103 if ((theBits & OpenGl_PO_WriteOit) != 0)
2105 aProgramSrc->SetNbFragmentOutputs (2);
2106 aProgramSrc->SetWeightOitOutput (true);
2111 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float occOrthoScale", Graphic3d_TOS_VERTEX));
2112 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float occSilhouetteThickness", Graphic3d_TOS_VERTEX));
2113 aSrcVertEndMain = THE_VERT_gl_Position_OUTLINE;
2115 else if ((theBits & OpenGl_PO_StippleLine) != 0)
2117 const Standard_Integer aBits = defaultGlslVersion (aProgramSrc, "unlit", theBits);
2118 if ((aBits & OpenGl_PO_StippleLine) != 0)
2120 if (myContext->hasGlslBitwiseOps != OpenGl_FeatureNotAvailable)
2122 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int occStipplePattern", Graphic3d_TOS_FRAGMENT));
2126 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("bool occStipplePattern[16]", Graphic3d_TOS_FRAGMENT));
2128 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("float occStippleFactor", Graphic3d_TOS_FRAGMENT));
2129 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 occViewport", Graphic3d_TOS_VERTEX));
2130 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 ScreenSpaceCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2132 EOL" vec2 aPosition = gl_Position.xy / gl_Position.w;"
2133 EOL" aPosition = aPosition * 0.5 + 0.5;"
2134 EOL" ScreenSpaceCoord = aPosition.xy * occViewport.zw + occViewport.xy;";
2135 aSrcFragMainGetColor = TCollection_AsciiString()
2136 + EOL" vec2 anAxis = vec2 (0.0, 1.0);"
2137 EOL" if (abs (dFdx (ScreenSpaceCoord.x)) - abs (dFdy (ScreenSpaceCoord.y)) > 0.001)"
2139 EOL" anAxis = vec2 (1.0, 0.0);"
2141 EOL" float aRotatePoint = dot (gl_FragCoord.xy, anAxis);"
2142 + (myContext->hasGlslBitwiseOps != OpenGl_FeatureNotAvailable
2143 ? EOL" uint aBit = uint (floor (aRotatePoint / occStippleFactor + 0.5)) & 15U;"
2144 EOL" if ((uint (occStipplePattern) & (1U << aBit)) == 0U) discard;"
2145 : EOL" int aBit = int (mod (floor (aRotatePoint / occStippleFactor + 0.5), 16.0));"
2146 EOL" if (!occStipplePattern[aBit]) discard;")
2147 + EOL" vec4 aColor = getFinalColor();"
2148 EOL" if (aColor.a <= 0.1) discard;"
2149 EOL" occSetFragColor (aColor);";
2153 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_HIGH, "Warning: stipple lines in GLSL will be ignored.");
2162 + THE_VERT_gl_Position
2166 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
2167 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
2168 ? THE_FRAG_WIREFRAME_COLOR
2169 : EOL"#define getFinalColor getColor";
2177 + aSrcFragMainGetColor
2180 defaultGlslVersion (aProgramSrc, theIsOutline ? "outline" : "unlit", theBits);
2181 aProgramSrc->SetDefaultSampler (false);
2182 aProgramSrc->SetNbLightsMax (0);
2183 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
2184 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
2185 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
2186 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2187 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
2188 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2189 TCollection_AsciiString aKey;
2190 if (!Create (aProgramSrc, aKey, theProgram))
2192 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2193 return Standard_False;
2195 return Standard_True;
2198 // =======================================================================
2199 // function : pointSpriteShadingSrc
2201 // =======================================================================
2202 TCollection_AsciiString OpenGl_ShaderManager::pointSpriteShadingSrc (const TCollection_AsciiString& theBaseColorSrc,
2203 Standard_Integer theBits)
2205 TCollection_AsciiString aSrcFragGetColor;
2206 if ((theBits & OpenGl_PO_PointSpriteA) == OpenGl_PO_PointSpriteA)
2208 aSrcFragGetColor = pointSpriteAlphaSrc (theBits) +
2209 EOL"vec4 getColor(void)"
2211 EOL" vec4 aColor = " + theBaseColorSrc + ";"
2212 EOL" aColor.a = getAlpha();"
2213 EOL" if (aColor.a <= 0.1) discard;"
2214 EOL" return aColor;"
2217 else if ((theBits & OpenGl_PO_PointSprite) == OpenGl_PO_PointSprite)
2219 aSrcFragGetColor = TCollection_AsciiString() +
2220 EOL"vec4 getColor(void)"
2222 EOL" vec4 aColor = " + theBaseColorSrc + ";"
2223 EOL" aColor = occTexture2D(occSamplerPointSprite, " THE_VEC2_glPointCoord ") * aColor;"
2224 EOL" if (aColor.a <= 0.1) discard;"
2225 EOL" return aColor;"
2229 return aSrcFragGetColor;
2232 // =======================================================================
2233 // function : stdComputeLighting
2235 // =======================================================================
2236 TCollection_AsciiString OpenGl_ShaderManager::stdComputeLighting (Standard_Integer& theNbLights,
2237 Standard_Boolean theHasVertColor,
2238 Standard_Boolean theIsPBR,
2239 Standard_Boolean theHasEmissive)
2241 TCollection_AsciiString aLightsFunc, aLightsLoop;
2243 const Handle(Graphic3d_LightSet)& aLights = myLightSourceState.LightSources();
2244 if (!aLights.IsNull())
2246 theNbLights = aLights->NbEnabled();
2247 if (theNbLights <= THE_NB_UNROLLED_LIGHTS_MAX)
2249 Standard_Integer anIndex = 0;
2250 for (Graphic3d_LightSet::Iterator aLightIter (aLights, Graphic3d_LightSet::IterationFilter_ExcludeDisabledAndAmbient);
2251 aLightIter.More(); aLightIter.Next(), ++anIndex)
2253 switch (aLightIter.Value()->Type())
2255 case Graphic3d_TOLS_AMBIENT:
2257 break; // skip ambient
2258 case Graphic3d_TOLS_DIRECTIONAL:
2259 aLightsLoop = aLightsLoop + EOL" directionalLight (" + anIndex + ", theNormal, theView, theIsFront);";
2261 case Graphic3d_TOLS_POSITIONAL:
2262 aLightsLoop = aLightsLoop + EOL" pointLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
2264 case Graphic3d_TOLS_SPOT:
2265 aLightsLoop = aLightsLoop + EOL" spotLight (" + anIndex + ", theNormal, theView, aPoint, theIsFront);";
2272 theNbLights = roundUpMaxLightSources (theNbLights);
2273 bool isFirstInLoop = true;
2274 aLightsLoop = aLightsLoop +
2275 EOL" for (int anIndex = 0; anIndex < occLightSourcesCount; ++anIndex)"
2277 EOL" int aType = occLight_Type (anIndex);";
2278 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0)
2280 isFirstInLoop = false;
2282 EOL" if (aType == OccLightType_Direct)"
2284 EOL" directionalLight (anIndex, theNormal, theView, theIsFront);"
2287 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
2291 aLightsLoop += EOL" else ";
2293 isFirstInLoop = false;
2295 EOL" if (aType == OccLightType_Point)"
2297 EOL" pointLight (anIndex, theNormal, theView, aPoint, theIsFront);"
2300 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0)
2304 aLightsLoop += EOL" else ";
2306 isFirstInLoop = false;
2308 EOL" if (aType == OccLightType_Spot)"
2310 EOL" spotLight (anIndex, theNormal, theView, aPoint, theIsFront);"
2313 aLightsLoop += EOL" }";
2318 aLightsFunc += Shaders_PBRDistribution_glsl;
2319 aLightsFunc += Shaders_PBRGeometry_glsl;
2320 aLightsFunc += Shaders_PBRFresnel_glsl;
2321 aLightsFunc += Shaders_PBRCookTorrance_glsl;
2322 aLightsFunc += Shaders_PBRIllumination_glsl;
2325 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) == 1
2329 // use the version with hard-coded first index
2330 aLightsLoop = EOL" directionalLightFirst(theNormal, theView, theIsFront);";
2331 aLightsFunc += THE_FUNC_directionalLightFirst;
2333 else if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_DIRECTIONAL) > 0)
2335 aLightsFunc += theIsPBR ? THE_FUNC_PBR_directionalLight : THE_FUNC_directionalLight;
2337 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_POSITIONAL) > 0)
2339 aLightsFunc += theIsPBR ? THE_FUNC_PBR_pointLight : THE_FUNC_pointLight;
2341 if (aLights->NbEnabledLightsOfType (Graphic3d_TOLS_SPOT) > 0)
2343 aLightsFunc += theIsPBR ? THE_FUNC_PBR_spotLight : THE_FUNC_spotLight;
2347 TCollection_AsciiString aGetMatAmbient = "theIsFront ? occFrontMaterial_Ambient() : occBackMaterial_Ambient();";
2348 TCollection_AsciiString aGetMatDiffuse = "theIsFront ? occFrontMaterial_Diffuse() : occBackMaterial_Diffuse();";
2349 if (theHasVertColor)
2351 aGetMatAmbient = "getVertColor();";
2352 aGetMatDiffuse = "getVertColor();";
2357 return TCollection_AsciiString()
2359 + Shaders_PointLightAttenuation_glsl
2362 EOL"vec4 computeLighting (in vec3 theNormal,"
2363 EOL" in vec3 theView,"
2364 EOL" in vec4 thePoint,"
2365 EOL" in bool theIsFront)"
2367 EOL" Ambient = occLightAmbient.rgb;"
2368 EOL" Diffuse = vec3 (0.0);"
2369 EOL" Specular = vec3 (0.0);"
2370 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
2372 + EOL" vec4 aMatAmbient = " + aGetMatAmbient
2373 + EOL" vec4 aMatDiffuse = " + aGetMatDiffuse
2374 + EOL" vec4 aMatSpecular = theIsFront ? occFrontMaterial_Specular() : occBackMaterial_Specular();"
2375 EOL" vec3 aColor = Ambient * aMatAmbient.rgb + Diffuse * aMatDiffuse.rgb + Specular * aMatSpecular.rgb;"
2376 EOL" occTextureOcclusion(aColor, TexCoord.st);"
2378 ? EOL" vec4 aMatEmission = theIsFront ? occFrontMaterial_Emission() : occBackMaterial_Emission();"
2379 EOL" aColor += aMatEmission.rgb;" : "")
2380 + EOL" return vec4 (aColor, aMatDiffuse.a);"
2385 return TCollection_AsciiString()
2386 + THE_FUNC_PBR_lightDef
2387 + Shaders_PointLightAttenuation_glsl
2390 EOL"vec4 computeLighting (in vec3 theNormal,"
2391 EOL" in vec3 theView,"
2392 EOL" in vec4 thePoint,"
2393 EOL" in bool theIsFront)"
2395 EOL" DirectLighting = vec3(0.0);"
2396 EOL" BaseColor = " + (theHasVertColor ? "getVertColor();" : "occTextureColor(occPBRMaterial_Color (theIsFront), TexCoord.st / TexCoord.w);")
2397 + EOL" Emission = occTextureEmissive(occPBRMaterial_Emission (theIsFront), TexCoord.st / TexCoord.w);"
2398 EOL" Metallic = occTextureMetallic(occPBRMaterial_Metallic (theIsFront), TexCoord.st / TexCoord.w);"
2399 EOL" NormalizedRoughness = occTextureRoughness(occPBRMaterial_NormalizedRoughness (theIsFront), TexCoord.st / TexCoord.w);"
2400 EOL" Roughness = occRoughness (NormalizedRoughness);"
2401 EOL" IOR = occPBRMaterial_IOR (theIsFront);"
2402 EOL" vec3 aPoint = thePoint.xyz / thePoint.w;"
2404 + EOL" vec3 aColor = DirectLighting;"
2405 EOL" vec3 anIndirectLightingSpec = occPBRFresnel (BaseColor.rgb, Metallic, IOR);"
2406 EOL" vec2 aCoeff = occTexture2D (occEnvLUT, vec2(abs(dot(theView, theNormal)), NormalizedRoughness)).xy;"
2407 EOL" anIndirectLightingSpec *= aCoeff.x;"
2408 EOL" anIndirectLightingSpec += aCoeff.y;"
2409 EOL" anIndirectLightingSpec *= occTextureCubeLod (occSpecIBLMap, -reflect (theView, theNormal), NormalizedRoughness * float (occNbSpecIBLLevels - 1)).rgb;"
2410 EOL" vec3 aRefractionCoeff = 1.0 - occPBRFresnel (BaseColor.rgb, Metallic, NormalizedRoughness, IOR, abs(dot(theView, theNormal)));"
2411 EOL" aRefractionCoeff *= (1.0 - Metallic);"
2412 EOL" vec3 anIndirectLightingDiff = aRefractionCoeff * BaseColor.rgb * BaseColor.a;"
2413 EOL" anIndirectLightingDiff *= occDiffIBLMap (theNormal).rgb;"
2414 EOL" aColor += occLightAmbient.rgb * (anIndirectLightingDiff + anIndirectLightingSpec);"
2415 EOL" aColor += Emission;"
2416 EOL" occTextureOcclusion(aColor, TexCoord.st / TexCoord.w);"
2417 EOL" return vec4 (aColor, mix(1.0, BaseColor.a, aRefractionCoeff.x));"
2422 // =======================================================================
2423 // function : prepareStdProgramGouraud
2425 // =======================================================================
2426 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramGouraud (Handle(OpenGl_ShaderProgram)& theProgram,
2427 const Standard_Integer theBits)
2429 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2430 TCollection_AsciiString aSrcVert, aSrcVertColor, aSrcVertExtraMain;
2431 TCollection_AsciiString aSrcFrag, aSrcFragExtraMain;
2432 TCollection_AsciiString aSrcFragGetColor = EOL"vec4 getColor(void) { return gl_FrontFacing ? FrontColor : BackColor; }";
2433 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2435 if ((theBits & OpenGl_PO_IsPoint) != 0)
2437 #if defined(GL_ES_VERSION_2_0)
2438 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
2441 if ((theBits & OpenGl_PO_PointSprite) != 0)
2443 #if !defined(GL_ES_VERSION_2_0)
2444 if (myContext->core11 != NULL
2445 && myContext->IsGlGreaterEqual (2, 1))
2447 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
2451 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT));
2452 aSrcFragGetColor = pointSpriteShadingSrc ("gl_FrontFacing ? FrontColor : BackColor", theBits);
2455 if ((theBits & OpenGl_PO_TextureRGB) != 0
2456 && (theBits & OpenGl_PO_VertColor) == 0)
2458 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
2459 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX));
2460 aSrcVertColor = EOL"vec4 getVertColor(void) { return occTexture2D (occSamplerBaseColor, occTexCoord.xy); }";
2465 if ((theBits & OpenGl_PO_TextureRGB) != 0)
2467 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
2468 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT));
2469 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2470 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
2473 EOL"vec4 getColor(void)"
2475 EOL" vec4 aColor = gl_FrontFacing ? FrontColor : BackColor;"
2476 EOL" return occTexture2D(occSamplerBaseColor, TexCoord.st / TexCoord.w) * aColor;"
2481 if ((theBits & OpenGl_PO_VertColor) != 0)
2483 aSrcVertColor = EOL"vec4 getVertColor(void) { return occVertColor; }";
2486 int aNbClipPlanes = 0;
2487 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
2489 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2490 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2491 aSrcVertExtraMain +=
2492 EOL" PositionWorld = aPositionWorld;"
2493 EOL" Position = aPosition;";
2495 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
2497 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
2498 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2499 ? THE_FRAG_CLIP_CHAINS_N
2500 : THE_FRAG_CLIP_PLANES_N;
2502 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
2505 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
2507 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
2510 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2511 ? THE_FRAG_CLIP_CHAINS_2
2512 : THE_FRAG_CLIP_PLANES_2;
2515 if ((theBits & OpenGl_PO_WriteOit) != 0)
2517 aProgramSrc->SetNbFragmentOutputs (2);
2518 aProgramSrc->SetWeightOitOutput (true);
2521 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 FrontColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2522 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 BackColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2524 Standard_Integer aNbLights = 0;
2525 const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcVertColor.IsEmpty(), false, true);
2526 aSrcVert = TCollection_AsciiString()
2527 + THE_FUNC_transformNormal_view
2533 EOL" vec4 aPositionWorld = occModelWorldMatrix * occVertex;"
2534 EOL" vec4 aPosition = occWorldViewMatrix * aPositionWorld;"
2535 EOL" vec3 aNormal = transformNormal (occNormal);"
2536 EOL" vec3 aView = vec3 (0.0, 0.0, 1.0);"
2537 EOL" FrontColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, true);"
2538 EOL" BackColor = computeLighting (normalize (aNormal), normalize (aView), aPosition, false);"
2540 + THE_VERT_gl_Position
2543 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
2544 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
2545 ? THE_FRAG_WIREFRAME_COLOR
2546 : EOL"#define getFinalColor getColor";
2548 aSrcFrag = TCollection_AsciiString()
2553 + EOL" occSetFragColor (getFinalColor());"
2556 const TCollection_AsciiString aProgId = TCollection_AsciiString ("gouraud-") + genLightKey (myLightSourceState.LightSources()) + "-";
2557 defaultGlslVersion (aProgramSrc, aProgId, theBits);
2558 aProgramSrc->SetDefaultSampler (false);
2559 aProgramSrc->SetNbLightsMax (aNbLights);
2560 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
2561 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
2562 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
2563 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2564 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
2565 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2566 TCollection_AsciiString aKey;
2567 if (!Create (aProgramSrc, aKey, theProgram))
2569 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2570 return Standard_False;
2572 return Standard_True;
2575 // =======================================================================
2576 // function : prepareStdProgramPhong
2578 // =======================================================================
2579 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramPhong (Handle(OpenGl_ShaderProgram)& theProgram,
2580 const Standard_Integer theBits,
2581 const Standard_Boolean theIsFlatNormal,
2582 const Standard_Boolean theIsPBR)
2584 TCollection_AsciiString aPosition = theIsPBR ? "PositionWorld" : "Position";
2585 TCollection_AsciiString aPhongCompLight = TCollection_AsciiString() +
2586 "computeLighting (normalize (Normal), normalize (View), " + aPosition + ", gl_FrontFacing)";
2587 const bool isFlatNormal = theIsFlatNormal
2588 && myContext->hasFlatShading != OpenGl_FeatureNotAvailable;
2589 const char* aDFdxSignReversion = "";
2590 #if defined(GL_ES_VERSION_2_0)
2591 if (isFlatNormal != theIsFlatNormal)
2593 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION,
2594 GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
2595 "Warning: flat shading requires OpenGL ES 3.0+ or GL_OES_standard_derivatives extension.");
2597 else if (isFlatNormal
2598 && myContext->Vendor().Search("qualcomm") != -1)
2600 // workaround Adreno driver bug computing reversed normal using dFdx/dFdy
2601 aDFdxSignReversion = "-";
2602 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
2603 "Warning: applied workaround for flat shading normal computation using dFdx/dFdy on Adreno");
2606 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2607 aProgramSrc->SetPBR (theIsPBR);
2609 TCollection_AsciiString aSrcVert, aSrcVertExtraFunc, aSrcVertExtraMain;
2610 TCollection_AsciiString aSrcFrag, aSrcFragGetVertColor, aSrcFragExtraMain;
2611 TCollection_AsciiString aSrcFragGetColor = TCollection_AsciiString() + EOL"vec4 getColor(void) { return " + aPhongCompLight + "; }";
2612 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2613 if ((theBits & OpenGl_PO_IsPoint) != 0)
2615 #if defined(GL_ES_VERSION_2_0)
2616 aSrcVertExtraMain += EOL" gl_PointSize = occPointSize;";
2619 if ((theBits & OpenGl_PO_PointSprite) != 0)
2621 #if !defined(GL_ES_VERSION_2_0)
2622 if (myContext->core11 != NULL
2623 && myContext->IsGlGreaterEqual (2, 1))
2625 aProgramSrc->SetHeader ("#version 120"); // gl_PointCoord has been added since GLSL 1.2
2629 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerPointSprite", Graphic3d_TOS_FRAGMENT));
2630 aSrcFragGetColor = pointSpriteShadingSrc (aPhongCompLight, theBits);
2633 if ((theBits & OpenGl_PO_TextureRGB) != 0
2634 && (theBits & OpenGl_PO_VertColor) == 0)
2636 aProgramSrc->SetTextureSetBits (Graphic3d_TextureSetBits_BaseColor);
2637 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_VERTEX));
2638 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2640 aSrcVertExtraMain += EOL" VertColor = occTexture2D (occSamplerBaseColor, occTexCoord.xy);";
2641 aSrcFragGetVertColor = EOL"vec4 getVertColor(void) { return VertColor; }";
2646 if ((theBits & OpenGl_PO_TextureRGB) != 0)
2648 aUniforms .Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D occSamplerBaseColor", Graphic3d_TOS_FRAGMENT));
2649 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2650 aSrcVertExtraMain += THE_VARY_TexCoord_Trsf;
2652 Standard_Integer aTextureBits = Graphic3d_TextureSetBits_BaseColor | Graphic3d_TextureSetBits_Occlusion | Graphic3d_TextureSetBits_Emissive;
2655 aSrcFragGetColor = TCollection_AsciiString() +
2656 EOL"vec4 getColor(void)"
2658 EOL" vec2 aTexUV = TexCoord.st / TexCoord.w;"
2659 EOL" vec4 aColor = " + aPhongCompLight + ";"
2660 EOL" aColor *= occTexture2D(occSamplerBaseColor, aTexUV);"
2661 EOL" vec3 anEmission = occTextureEmissive((gl_FrontFacing ? occFrontMaterial_Emission() : occBackMaterial_Emission()).rgb, aTexUV);"
2662 EOL" aColor.rgb += anEmission;"
2663 EOL" return aColor;"
2668 aTextureBits |= Graphic3d_TextureSetBits_MetallicRoughness;
2670 if ((theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureNormal
2673 if (myContext->hasFlatShading != OpenGl_FeatureNotAvailable)
2675 aTextureBits |= Graphic3d_TextureSetBits_Normal;
2679 myContext->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_MEDIUM,
2680 "Warning: ignoring Normal Map texture due to hardware capabilities");
2683 aProgramSrc->SetTextureSetBits (aTextureBits);
2687 if ((theBits & OpenGl_PO_VertColor) != 0)
2689 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 VertColor", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2690 aSrcVertExtraMain += EOL" VertColor = occVertColor;";
2691 aSrcFragGetVertColor = EOL"vec4 getVertColor(void) { return VertColor; }";
2694 int aNbClipPlanes = 0;
2695 if ((theBits & OpenGl_PO_ClipPlanesN) != 0)
2697 if ((theBits & OpenGl_PO_ClipPlanesN) == OpenGl_PO_ClipPlanesN)
2699 aNbClipPlanes = Graphic3d_ShaderProgram::THE_MAX_CLIP_PLANES_DEFAULT;
2700 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2701 ? THE_FRAG_CLIP_CHAINS_N
2702 : THE_FRAG_CLIP_PLANES_N;
2704 else if ((theBits & OpenGl_PO_ClipPlanes1) != 0)
2707 aSrcFragExtraMain += THE_FRAG_CLIP_PLANES_1;
2709 else if ((theBits & OpenGl_PO_ClipPlanes2) != 0)
2712 aSrcFragExtraMain += (theBits & OpenGl_PO_ClipChains) != 0
2713 ? THE_FRAG_CLIP_CHAINS_2
2714 : THE_FRAG_CLIP_PLANES_2;
2717 if ((theBits & OpenGl_PO_WriteOit) != 0)
2719 aProgramSrc->SetNbFragmentOutputs (2);
2720 aProgramSrc->SetWeightOitOutput (true);
2725 aSrcFragExtraMain += TCollection_AsciiString()
2726 + EOL" Normal = " + aDFdxSignReversion + "normalize (cross (dFdx (" + aPosition + ".xyz / " + aPosition + ".w), dFdy (" + aPosition + ".xyz / " + aPosition + ".w)));"
2727 EOL" if (!gl_FrontFacing) { Normal = -Normal; }";
2731 aStageInOuts.Append(OpenGl_ShaderObject::ShaderVariable("vec3 vNormal", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2732 aSrcVertExtraFunc += THE_FUNC_transformNormal_world;
2733 aSrcVertExtraMain += EOL" vNormal = transformNormal (occNormal);";
2734 aSrcFragExtraMain += EOL" Normal = vNormal;";
2736 if ((theBits & OpenGl_PO_IsPoint) == 0
2737 && (theBits & OpenGl_PO_HasTextures) == OpenGl_PO_TextureNormal
2738 && myContext->hasFlatShading != OpenGl_FeatureNotAvailable)
2740 aSrcFrag += Shaders_TangentSpaceNormal_glsl;
2741 // apply normal map texture
2742 aSrcFragExtraMain +=
2743 EOL"#if defined(THE_HAS_TEXTURE_NORMAL)"
2744 EOL" vec2 aTexCoord = TexCoord.st / TexCoord.w;"
2745 EOL" vec4 aMapNormalValue = occTextureNormal(aTexCoord);"
2746 EOL" if (aMapNormalValue.w > 0.5)"
2748 EOL" mat2 aDeltaUVMatrix = mat2 (dFdx(aTexCoord), dFdy(aTexCoord));"
2749 EOL" mat2x3 aDeltaVectorMatrix = mat2x3 (dFdx (PositionWorld.xyz), dFdy (PositionWorld.xyz));"
2750 EOL" Normal = TangentSpaceNormal (aDeltaUVMatrix, aDeltaVectorMatrix, aMapNormalValue.xyz, Normal, !gl_FrontFacing);"
2756 aSrcFragExtraMain +=
2757 EOL" Normal = normalize ((occWorldViewMatrixInverseTranspose * vec4 (Normal, 0.0)).xyz);";
2761 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 PositionWorld", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2762 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec4 Position", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2763 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 View", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2765 aSrcVert = TCollection_AsciiString()
2769 EOL" PositionWorld = occModelWorldMatrix * occVertex;"
2770 EOL" Position = occWorldViewMatrix * PositionWorld;"
2771 EOL" if (occProjectionMatrix[3][3] == 1.0)"
2773 EOL" View = vec3(0.0, 0.0, 1.0);"
2777 EOL" View = -Position.xyz;"
2779 + (theIsPBR ? EOL" View = (occWorldViewMatrixInverse * vec4(View, 0.0)).xyz;" : "")
2781 + THE_VERT_gl_Position
2784 TCollection_AsciiString aSrcGeom = prepareGeomMainSrc (aUniforms, aStageInOuts, theBits);
2785 aSrcFragGetColor += (theBits & OpenGl_PO_MeshEdges) != 0
2786 ? THE_FRAG_WIREFRAME_COLOR
2787 : EOL"#define getFinalColor getColor";
2789 Standard_Integer aNbLights = 0;
2790 const TCollection_AsciiString aLights = stdComputeLighting (aNbLights, !aSrcFragGetVertColor.IsEmpty(), theIsPBR,
2791 (theBits & OpenGl_PO_TextureRGB) == 0
2792 || (theBits & OpenGl_PO_IsPoint) != 0);
2793 aSrcFrag += TCollection_AsciiString()
2795 + aSrcFragGetVertColor
2803 + EOL" occSetFragColor (getFinalColor());"
2806 const TCollection_AsciiString aProgId = TCollection_AsciiString (theIsFlatNormal ? "flat-" : "phong-") + (theIsPBR ? "pbr-" : "") + genLightKey (myLightSourceState.LightSources()) + "-";
2807 defaultGlslVersion (aProgramSrc, aProgId, theBits, isFlatNormal);
2808 aProgramSrc->SetDefaultSampler (false);
2809 aProgramSrc->SetNbLightsMax (aNbLights);
2810 aProgramSrc->SetNbClipPlanesMax (aNbClipPlanes);
2811 aProgramSrc->SetAlphaTest ((theBits & OpenGl_PO_AlphaTest) != 0);
2813 const Standard_Integer aNbGeomInputVerts = !aSrcGeom.IsEmpty() ? 3 : 0;
2814 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2815 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcGeom, Graphic3d_TOS_GEOMETRY, aUniforms, aStageInOuts, "geomIn", "geomOut", aNbGeomInputVerts));
2816 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts, "", "", aNbGeomInputVerts));
2817 TCollection_AsciiString aKey;
2818 if (!Create (aProgramSrc, aKey, theProgram))
2820 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
2821 return Standard_False;
2823 return Standard_True;
2826 // =======================================================================
2827 // function : prepareStdProgramStereo
2829 // =======================================================================
2830 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramStereo (Handle(OpenGl_ShaderProgram)& theProgram,
2831 const Graphic3d_StereoMode theStereoMode)
2833 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
2834 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
2836 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable ("vec2 TexCoord", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
2837 TCollection_AsciiString aSrcVert =
2840 EOL" TexCoord = occVertex.zw;"
2841 EOL" gl_Position = vec4(occVertex.x, occVertex.y, 0.0, 1.0);"
2844 TCollection_AsciiString aSrcFrag;
2845 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uLeftSampler", Graphic3d_TOS_FRAGMENT));
2846 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("sampler2D uRightSampler", Graphic3d_TOS_FRAGMENT));
2847 const char* aName = "stereo";
2848 switch (theStereoMode)
2850 case Graphic3d_StereoMode_Anaglyph:
2853 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 uMultL", Graphic3d_TOS_FRAGMENT));
2854 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("mat4 uMultR", Graphic3d_TOS_FRAGMENT));
2855 const TCollection_AsciiString aNormalize = mySRgbState
2856 ? EOL"#define sRgb2linear(theColor) theColor"
2857 EOL"#define linear2sRgb(theColor) theColor"
2858 : EOL"#define sRgb2linear(theColor) pow(theColor, vec4(2.2, 2.2, 2.2, 1.0))"
2859 EOL"#define linear2sRgb(theColor) pow(theColor, 1.0 / vec4(2.2, 2.2, 2.2, 1.0))";
2860 aSrcFrag = aNormalize
2863 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2864 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2865 EOL" aColorL = sRgb2linear (aColorL);"
2866 EOL" aColorR = sRgb2linear (aColorR);"
2867 EOL" vec4 aColor = uMultR * aColorR + uMultL * aColorL;"
2868 EOL" occSetFragColor (linear2sRgb (aColor));"
2872 case Graphic3d_StereoMode_RowInterlaced:
2874 aName = "row-interlaced";
2878 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2879 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2880 EOL" if (int (mod (gl_FragCoord.y - 1023.5, 2.0)) != 1)"
2882 EOL" occSetFragColor (aColorL);"
2886 EOL" occSetFragColor (aColorR);"
2891 case Graphic3d_StereoMode_ColumnInterlaced:
2893 aName = "column-interlaced";
2897 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2898 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2899 EOL" if (int (mod (gl_FragCoord.x - 1023.5, 2.0)) == 1)"
2901 EOL" occSetFragColor (aColorL);"
2905 EOL" occSetFragColor (aColorR);"
2910 case Graphic3d_StereoMode_ChessBoard:
2912 aName = "chessboard";
2916 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2917 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2918 EOL" bool isEvenX = int(mod(floor(gl_FragCoord.x - 1023.5), 2.0)) != 1;"
2919 EOL" bool isEvenY = int(mod(floor(gl_FragCoord.y - 1023.5), 2.0)) == 1;"
2920 EOL" if ((isEvenX && isEvenY) || (!isEvenX && !isEvenY))"
2922 EOL" occSetFragColor (aColorL);"
2926 EOL" occSetFragColor (aColorR);"
2931 case Graphic3d_StereoMode_SideBySide:
2933 aName = "sidebyside";
2937 EOL" vec2 aTexCoord = vec2 (TexCoord.x * 2.0, TexCoord.y);"
2938 EOL" if (TexCoord.x > 0.5)"
2940 EOL" aTexCoord.x -= 1.0;"
2942 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
2943 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
2944 EOL" if (TexCoord.x <= 0.5)"
2946 EOL" occSetFragColor (aColorL);"
2950 EOL" occSetFragColor (aColorR);"
2955 case Graphic3d_StereoMode_OverUnder:
2957 aName = "overunder";
2961 EOL" vec2 aTexCoord = vec2 (TexCoord.x, TexCoord.y * 2.0);"
2962 EOL" if (TexCoord.y > 0.5)"
2964 EOL" aTexCoord.y -= 1.0;"
2966 EOL" vec4 aColorL = occTexture2D (uLeftSampler, aTexCoord);"
2967 EOL" vec4 aColorR = occTexture2D (uRightSampler, aTexCoord);"
2968 EOL" if (TexCoord.y <= 0.5)"
2970 EOL" occSetFragColor (aColorL);"
2974 EOL" occSetFragColor (aColorR);"
2979 case Graphic3d_StereoMode_QuadBuffer:
2980 case Graphic3d_StereoMode_SoftPageFlip:
2981 case Graphic3d_StereoMode_OpenVR:
2984 /*const Handle(OpenGl_ShaderProgram)& aProgram = myStereoPrograms[Graphic3d_StereoMode_QuadBuffer];
2985 if (!aProgram.IsNull())
2987 return aProgram->IsValid();
2992 EOL" vec4 aColorL = occTexture2D (uLeftSampler, TexCoord);"
2993 EOL" vec4 aColorR = occTexture2D (uRightSampler, TexCoord);"
2994 EOL" aColorL.b = 0.0;"
2995 EOL" aColorL.g = 0.0;"
2996 EOL" aColorR.r = 0.0;"
2997 EOL" occSetFragColor (aColorL + aColorR);"
3003 defaultGlslVersion (aProgramSrc, aName, 0);
3004 aProgramSrc->SetDefaultSampler (false);
3005 aProgramSrc->SetNbLightsMax (0);
3006 aProgramSrc->SetNbClipPlanesMax (0);
3007 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
3008 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
3009 TCollection_AsciiString aKey;
3010 if (!Create (aProgramSrc, aKey, theProgram))
3012 theProgram = new OpenGl_ShaderProgram(); // just mark as invalid
3013 return Standard_False;
3016 myContext->BindProgram (theProgram);
3017 theProgram->SetSampler (myContext, "uLeftSampler", Graphic3d_TextureUnit_0);
3018 theProgram->SetSampler (myContext, "uRightSampler", Graphic3d_TextureUnit_1);
3019 myContext->BindProgram (NULL);
3020 return Standard_True;
3023 // =======================================================================
3024 // function : prepareStdProgramBoundBox
3026 // =======================================================================
3027 Standard_Boolean OpenGl_ShaderManager::prepareStdProgramBoundBox()
3029 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
3031 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
3032 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 occBBoxCenter", Graphic3d_TOS_VERTEX));
3033 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("vec3 occBBoxSize", Graphic3d_TOS_VERTEX));
3035 TCollection_AsciiString aSrcVert =
3038 EOL" vec4 aCenter = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);"
3039 EOL" vec4 aPos = vec4(occVertex.xyz * occBBoxSize + occBBoxCenter, 1.0);"
3040 EOL" gl_Position = occProjectionMatrix * occWorldViewMatrix * occModelWorldMatrix * aPos;"
3043 TCollection_AsciiString aSrcFrag =
3046 EOL" occSetFragColor (occColor);"
3049 defaultGlslVersion (aProgramSrc, "bndbox", 0);
3050 aProgramSrc->SetDefaultSampler (false);
3051 aProgramSrc->SetNbLightsMax (0);
3052 aProgramSrc->SetNbClipPlanesMax (0);
3053 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
3054 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
3055 TCollection_AsciiString aKey;
3056 if (!Create (aProgramSrc, aKey, myBoundBoxProgram))
3058 myBoundBoxProgram = new OpenGl_ShaderProgram(); // just mark as invalid
3059 return Standard_False;
3062 const OpenGl_Vec4 aMin (-0.5f, -0.5f, -0.5f, 1.0f);
3063 const OpenGl_Vec4 anAxisShifts[3] =
3065 OpenGl_Vec4 (1.0f, 0.0f, 0.0f, 0.0f),
3066 OpenGl_Vec4 (0.0f, 1.0f, 0.0f, 0.0f),
3067 OpenGl_Vec4 (0.0f, 0.0f, 1.0f, 0.0f)
3070 const OpenGl_Vec4 aLookup1 (0.0f, 1.0f, 0.0f, 1.0f);
3071 const OpenGl_Vec4 aLookup2 (0.0f, 0.0f, 1.0f, 1.0f);
3072 OpenGl_Vec4 aLinesVertices[24];
3073 for (int anAxis = 0, aVertex = 0; anAxis < 3; ++anAxis)
3075 for (int aCompIter = 0; aCompIter < 4; ++aCompIter)
3077 aLinesVertices[aVertex++] = aMin
3078 + anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter]
3079 + anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter];
3081 aLinesVertices[aVertex++] = aMin
3082 + anAxisShifts[anAxis]
3083 + anAxisShifts[(anAxis + 1) % 3] * aLookup1[aCompIter]
3084 + anAxisShifts[(anAxis + 2) % 3] * aLookup2[aCompIter];
3087 if (myContext->ToUseVbo())
3089 myBoundBoxVertBuffer = new OpenGl_VertexBuffer();
3090 if (myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData()))
3092 myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer);
3093 return Standard_True;
3096 myBoundBoxVertBuffer = new OpenGl_VertexBufferCompat();
3097 myBoundBoxVertBuffer->Init (myContext, 4, 24, aLinesVertices[0].GetData());
3098 myContext->ShareResource ("OpenGl_ShaderManager_BndBoxVbo", myBoundBoxVertBuffer);
3099 return Standard_True;
3102 // =======================================================================
3103 // function : preparePBREnvBakingProgram
3105 // =======================================================================
3106 Standard_Boolean OpenGl_ShaderManager::preparePBREnvBakingProgram()
3108 Handle(Graphic3d_ShaderProgram) aProgramSrc = new Graphic3d_ShaderProgram();
3109 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
3111 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
3112 + THE_FUNC_cubemap_vector_transform
3113 + Shaders_PBREnvBaking_vs;
3115 TCollection_AsciiString aSrcFrag = TCollection_AsciiString()
3116 + THE_FUNC_cubemap_vector_transform
3117 + Shaders_PBRDistribution_glsl
3118 + Shaders_PBREnvBaking_fs;
3120 // constant array definition requires OpenGL 2.1+ or OpenGL ES 3.0+
3121 #if defined(GL_ES_VERSION_2_0)
3122 aProgramSrc->SetHeader ("#version 300 es");
3124 aProgramSrc->SetHeader ("#version 120");
3127 defaultGlslVersion (aProgramSrc, "pbr_env_baking", 0);
3128 aProgramSrc->SetDefaultSampler (false);
3129 aProgramSrc->SetNbLightsMax (0);
3130 aProgramSrc->SetNbClipPlanesMax (0);
3131 aProgramSrc->SetPBR (true);
3132 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
3133 aProgramSrc->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
3134 TCollection_AsciiString aKey;
3135 if (!Create (aProgramSrc, aKey, myPBREnvBakingProgram))
3137 myPBREnvBakingProgram = new OpenGl_ShaderProgram(); // just mark as invalid
3138 return Standard_False;
3141 return Standard_True;
3144 // =======================================================================
3145 // function : GetBgCubeMapProgram
3147 // =======================================================================
3148 const Handle(Graphic3d_ShaderProgram)& OpenGl_ShaderManager::GetBgCubeMapProgram ()
3150 if (myBgCubeMapProgram.IsNull())
3152 myBgCubeMapProgram = new Graphic3d_ShaderProgram();
3154 OpenGl_ShaderObject::ShaderVariableList aUniforms, aStageInOuts;
3155 aStageInOuts.Append (OpenGl_ShaderObject::ShaderVariable("vec3 ViewDirection", Graphic3d_TOS_VERTEX | Graphic3d_TOS_FRAGMENT));
3156 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("samplerCube occSampler0", Graphic3d_TOS_FRAGMENT));
3157 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uYCoeff", Graphic3d_TOS_VERTEX));
3158 aUniforms.Append (OpenGl_ShaderObject::ShaderVariable ("int uZCoeff", Graphic3d_TOS_VERTEX));
3160 TCollection_AsciiString aSrcVert = TCollection_AsciiString()
3161 + THE_FUNC_cubemap_vector_transform
3164 EOL" vec4 aViewDirection = occProjectionMatrixInverse * vec4(occVertex.xy, 0.0, 1.0);"
3165 EOL" aViewDirection /= aViewDirection.w;"
3166 EOL" aViewDirection.w = 0.0;"
3167 EOL" ViewDirection = normalize((occWorldViewMatrixInverse * aViewDirection).xyz);"
3168 EOL" ViewDirection = cubemapVectorTransform (ViewDirection, uYCoeff, uZCoeff);"
3169 EOL" gl_Position = vec4(occVertex.xy, 0.0, 1.0);"
3172 TCollection_AsciiString aSrcFrag =
3173 EOL"#define occEnvCubemap occSampler0"
3176 EOL" occSetFragColor (vec4(occTextureCube (occEnvCubemap, ViewDirection).rgb, 1.0));"
3179 defaultGlslVersion (myBgCubeMapProgram, "background_cubemap", 0);
3180 myBgCubeMapProgram->SetDefaultSampler (false);
3181 myBgCubeMapProgram->SetNbLightsMax (0);
3182 myBgCubeMapProgram->SetNbClipPlanesMax (0);
3183 myBgCubeMapProgram->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcVert, Graphic3d_TOS_VERTEX, aUniforms, aStageInOuts));
3184 myBgCubeMapProgram->AttachShader (OpenGl_ShaderObject::CreateFromSource (aSrcFrag, Graphic3d_TOS_FRAGMENT, aUniforms, aStageInOuts));
3187 return myBgCubeMapProgram;
3190 // =======================================================================
3191 // function : bindProgramWithState
3193 // =======================================================================
3194 Standard_Boolean OpenGl_ShaderManager::bindProgramWithState (const Handle(OpenGl_ShaderProgram)& theProgram,
3195 Graphic3d_TypeOfShadingModel theShadingModel)
3197 const Standard_Boolean isBound = myContext->BindProgram (theProgram);
3199 && !theProgram.IsNull())
3201 theProgram->ApplyVariables (myContext);
3203 PushState (theProgram, theShadingModel);
3207 // =======================================================================
3208 // function : BindMarkerProgram
3210 // =======================================================================
3211 Standard_Boolean OpenGl_ShaderManager::BindMarkerProgram (const Handle(OpenGl_TextureSet)& theTextures,
3212 Graphic3d_TypeOfShadingModel theShadingModel,
3213 Graphic3d_AlphaMode theAlphaMode,
3214 Standard_Boolean theHasVertColor,
3215 const Handle(OpenGl_ShaderProgram)& theCustomProgram)
3217 if (!theCustomProgram.IsNull()
3218 || myContext->caps->ffpEnable)
3220 return bindProgramWithState (theCustomProgram, theShadingModel);
3223 Standard_Integer aBits = getProgramBits (theTextures, theAlphaMode, Aspect_IS_SOLID, theHasVertColor, false, false);
3224 if (!theTextures.IsNull()
3225 && theTextures->HasPointSprite())
3227 aBits |= theTextures->Last()->IsAlpha() ? OpenGl_PO_PointSpriteA : OpenGl_PO_PointSprite;
3231 aBits |= OpenGl_PO_PointSimple;
3233 Handle(OpenGl_ShaderProgram)& aProgram = getStdProgram (theShadingModel, aBits);
3234 return bindProgramWithState (aProgram, theShadingModel);