1 // Created on: 2013-09-19
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.
16 #include <OSD_File.hxx>
17 #include <OSD_Environment.hxx>
19 #include <OpenGl_Context.hxx>
20 #include <OpenGl_ShaderProgram.hxx>
21 #include <OpenGl_ShaderManager.hxx>
22 #include <OpenGl_ArbTexBindless.hxx>
24 #include <OpenGl_GlCore32.hxx>
26 #include "../Shaders/Shaders_DeclarationsImpl_glsl.pxx"
27 #include "../Shaders/Shaders_Declarations_glsl.pxx"
30 #include <malloc.h> // for alloca()
33 IMPLEMENT_STANDARD_RTTIEXT(OpenGl_ShaderProgram, OpenGl_NamedResource)
35 OpenGl_VariableSetterSelector OpenGl_ShaderProgram::mySetterSelector = OpenGl_VariableSetterSelector();
37 // Declare OCCT-specific OpenGL/GLSL shader variables
38 Standard_CString OpenGl_ShaderProgram::PredefinedKeywords[] =
40 "occModelWorldMatrix", // OpenGl_OCC_MODEL_WORLD_MATRIX
41 "occWorldViewMatrix", // OpenGl_OCC_WORLD_VIEW_MATRIX
42 "occProjectionMatrix", // OpenGl_OCC_PROJECTION_MATRIX
43 "occModelWorldMatrixInverse", // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE
44 "occWorldViewMatrixInverse", // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE
45 "occProjectionMatrixInverse", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE
46 "occModelWorldMatrixTranspose", // OpenGl_OCC_MODEL_WORLD_MATRIX_TRANSPOSE
47 "occWorldViewMatrixTranspose", // OpenGl_OCC_WORLD_VIEW_MATRIX_TRANSPOSE
48 "occProjectionMatrixTranspose", // OpenGl_OCC_PROJECTION_MATRIX_TRANSPOSE
49 "occModelWorldMatrixInverseTranspose", // OpenGl_OCC_MODEL_WORLD_MATRIX_INVERSE_TRANSPOSE
50 "occWorldViewMatrixInverseTranspose", // OpenGl_OCC_WORLD_VIEW_MATRIX_INVERSE_TRANSPOSE
51 "occProjectionMatrixInverseTranspose", // OpenGl_OCC_PROJECTION_MATRIX_INVERSE_TRANSPOSE
53 "occClipPlaneEquations", // OpenGl_OCC_CLIP_PLANE_EQUATIONS
54 "occClipPlaneChains", // OpenGl_OCC_CLIP_PLANE_CHAINS
55 "occClipPlaneCount", // OpenGl_OCC_CLIP_PLANE_COUNT
57 "occLightSourcesCount", // OpenGl_OCC_LIGHT_SOURCE_COUNT
58 "occLightSourcesTypes", // OpenGl_OCC_LIGHT_SOURCE_TYPES
59 "occLightSources", // OpenGl_OCC_LIGHT_SOURCE_PARAMS
60 "occLightAmbient", // OpenGl_OCC_LIGHT_AMBIENT
61 "occShadowMapSizeBias", // OpenGl_OCC_LIGHT_SHADOWMAP_SIZE_BIAS
62 "occShadowMapSamplers", // OpenGl_OCC_LIGHT_SHADOWMAP_SAMPLERS,
63 "occShadowMapMatrices", // OpenGl_OCC_LIGHT_SHADOWMAP_MATRICES,
65 "occTextureEnable", // OpenGl_OCCT_TEXTURE_ENABLE
66 "occDistinguishingMode", // OpenGl_OCCT_DISTINGUISH_MODE
67 "occPbrMaterial", // OpenGl_OCCT_PBR_MATERIAL
68 "occCommonMaterial", // OpenGl_OCCT_COMMON_MATERIAL
69 "occAlphaCutoff", // OpenGl_OCCT_ALPHA_CUTOFF
70 "occColor", // OpenGl_OCCT_COLOR
72 "occOitOutput", // OpenGl_OCCT_OIT_OUTPUT
73 "occOitDepthFactor", // OpenGl_OCCT_OIT_DEPTH_FACTOR
75 "occTexTrsf2d", // OpenGl_OCCT_TEXTURE_TRSF2D
76 "occPointSize", // OpenGl_OCCT_POINT_SIZE
78 "occViewport", // OpenGl_OCCT_VIEWPORT
79 "occLineWidth", // OpenGl_OCCT_LINE_WIDTH
80 "occLineFeather", // OpenGl_OCCT_LINE_FEATHER
81 "occStipplePattern", // OpenGl_OCCT_LINE_STIPPLE_PATTERN
82 "occStippleFactor", // OpenGl_OCCT_LINE_STIPPLE_FACTOR
83 "occWireframeColor", // OpenGl_OCCT_WIREFRAME_COLOR
84 "occIsQuadMode", // OpenGl_OCCT_QUAD_MODE_STATE
86 "occOrthoScale", // OpenGl_OCCT_ORTHO_SCALE
87 "occSilhouetteThickness", // OpenGl_OCCT_SILHOUETTE_THICKNESS
89 "occNbSpecIBLLevels" // OpenGl_OCCT_NB_SPEC_IBL_LEVELS
94 //! Convert Graphic3d_TypeOfShaderObject enumeration into OpenGL enumeration.
95 static GLenum shaderTypeToGl (Graphic3d_TypeOfShaderObject theType)
99 case Graphic3d_TOS_VERTEX: return GL_VERTEX_SHADER;
100 case Graphic3d_TOS_FRAGMENT: return GL_FRAGMENT_SHADER;
101 case Graphic3d_TOS_GEOMETRY: return GL_GEOMETRY_SHADER;
102 case Graphic3d_TOS_TESS_CONTROL: return GL_TESS_CONTROL_SHADER;
103 case Graphic3d_TOS_TESS_EVALUATION: return GL_TESS_EVALUATION_SHADER;
104 case Graphic3d_TOS_COMPUTE: return GL_COMPUTE_SHADER;
110 // =======================================================================
111 // function : OpenGl_VariableSetterSelector
112 // purpose : Creates new variable setter selector
113 // =======================================================================
114 OpenGl_VariableSetterSelector::OpenGl_VariableSetterSelector()
116 // Note: Add new variable setters here
117 mySetterList = OpenGl_HashMapInitializer::CreateListOf<size_t, OpenGl_SetterInterface*>
118 (Graphic3d_UniformValueTypeID<int>::ID, new OpenGl_VariableSetter<int>())
119 (Graphic3d_UniformValueTypeID<float>::ID, new OpenGl_VariableSetter<float>())
120 (Graphic3d_UniformValueTypeID<OpenGl_Vec2>::ID, new OpenGl_VariableSetter<OpenGl_Vec2>())
121 (Graphic3d_UniformValueTypeID<OpenGl_Vec3>::ID, new OpenGl_VariableSetter<OpenGl_Vec3>())
122 (Graphic3d_UniformValueTypeID<OpenGl_Vec4>::ID, new OpenGl_VariableSetter<OpenGl_Vec4>())
123 (Graphic3d_UniformValueTypeID<OpenGl_Vec2i>::ID, new OpenGl_VariableSetter<OpenGl_Vec2i>())
124 (Graphic3d_UniformValueTypeID<OpenGl_Vec3i>::ID, new OpenGl_VariableSetter<OpenGl_Vec3i>())
125 (Graphic3d_UniformValueTypeID<OpenGl_Vec4i>::ID, new OpenGl_VariableSetter<OpenGl_Vec4i>());
128 // =======================================================================
129 // function : ~OpenGl_VariableSetterSelector
130 // purpose : Releases memory resources of variable setter selector
131 // =======================================================================
132 OpenGl_VariableSetterSelector::~OpenGl_VariableSetterSelector()
134 for (OpenGl_SetterList::Iterator anIt (mySetterList); anIt.More(); anIt.Next())
139 mySetterList.Clear();
142 // =======================================================================
144 // purpose : Sets generic variable to specified shader program
145 // =======================================================================
146 void OpenGl_VariableSetterSelector::Set (const Handle(OpenGl_Context)& theCtx,
147 const Handle(Graphic3d_ShaderVariable)& theVariable,
148 OpenGl_ShaderProgram* theProgram) const
150 Standard_ASSERT_RETURN (mySetterList.IsBound (theVariable->Value()->TypeID()),
151 "The type of user-defined uniform variable is not supported...", );
153 mySetterList.Find (theVariable->Value()->TypeID())->Set (theCtx, theVariable, theProgram);
156 // =======================================================================
157 // function : OpenGl_ShaderProgram
158 // purpose : Creates uninitialized shader program
159 // =======================================================================
160 OpenGl_ShaderProgram::OpenGl_ShaderProgram (const Handle(Graphic3d_ShaderProgram)& theProxy,
161 const TCollection_AsciiString& theId)
162 : OpenGl_NamedResource (!theProxy.IsNull() ? theProxy->GetId() : theId),
163 myProgramID (NO_PROGRAM),
168 myNbClipPlanesMax (0),
170 myTextureSetBits (Graphic3d_TextureSetBits_NONE),
171 myOitOutput (Graphic3d_RTM_BLEND_UNORDERED),
172 myHasAlphaTest (false),
173 myHasTessShader (false)
175 memset (myCurrentState, 0, sizeof (myCurrentState));
178 // =======================================================================
179 // function : Initialize
180 // purpose : Initializes program object with the list of shader objects
181 // =======================================================================
182 Standard_Boolean OpenGl_ShaderProgram::Initialize (const Handle(OpenGl_Context)& theCtx,
183 const Graphic3d_ShaderObjectList& theShaders)
185 myHasTessShader = false;
186 if (theCtx.IsNull() || !Create (theCtx))
188 return Standard_False;
191 TCollection_AsciiString aHeaderVer = !myProxy.IsNull() ? myProxy->Header() : TCollection_AsciiString();
193 for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders); anIter.More(); anIter.Next())
195 aShaderMask |= anIter.Value()->Type();
197 myHasTessShader = (aShaderMask & (Graphic3d_TOS_TESS_CONTROL | Graphic3d_TOS_TESS_EVALUATION)) != 0;
198 myNbFragOutputs = !myProxy.IsNull() ? myProxy->NbFragmentOutputs() : 1;
199 myTextureSetBits = Graphic3d_TextureSetBits_NONE;
200 myHasAlphaTest = !myProxy.IsNull() && myProxy->HasAlphaTest();
201 myOitOutput = !myProxy.IsNull() ? myProxy->OitOutput() : Graphic3d_RTM_BLEND_UNORDERED;
202 if (myOitOutput == Graphic3d_RTM_BLEND_OIT
203 && myNbFragOutputs < 2)
205 myOitOutput = Graphic3d_RTM_BLEND_UNORDERED;
207 else if (myOitOutput == Graphic3d_RTM_DEPTH_PEELING_OIT
208 && myNbFragOutputs < 3)
210 myOitOutput = Graphic3d_RTM_BLEND_UNORDERED;
213 // detect the minimum GLSL version required for defined Shader Objects
214 if (theCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES)
218 if (!theCtx->IsGlGreaterEqual (3, 2))
220 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
221 "Error! Tessellation shader requires OpenGL ES 3.2+");
224 else if (aHeaderVer.IsEmpty())
226 aHeaderVer = "#version 320 es";
229 else if ((aShaderMask & Graphic3d_TOS_GEOMETRY) != 0)
231 switch (theCtx->hasGeometryStage)
233 case OpenGl_FeatureNotAvailable:
235 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
236 "Error! Geometry shader requires OpenGL ES 3.2+ or GL_EXT_geometry_shader");
239 case OpenGl_FeatureInExtensions:
241 if (aHeaderVer.IsEmpty())
243 aHeaderVer = "#version 310 es";
247 case OpenGl_FeatureInCore:
249 if (aHeaderVer.IsEmpty())
251 aHeaderVer = "#version 320 es";
257 else if ((aShaderMask & Graphic3d_TOS_COMPUTE) != 0)
259 if (!theCtx->IsGlGreaterEqual (3, 1))
261 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
262 "Error! Compute shaders require OpenGL ES 3.1+");
265 else if (aHeaderVer.IsEmpty())
267 aHeaderVer = "#version 310 es";
273 if ((aShaderMask & Graphic3d_TOS_COMPUTE) != 0)
275 if (!theCtx->IsGlGreaterEqual (4, 3))
277 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
278 "Error! Compute shaders require OpenGL 4.3+");
281 else if (aHeaderVer.IsEmpty())
283 aHeaderVer = "#version 430";
286 else if (myHasTessShader)
288 if (!theCtx->IsGlGreaterEqual (4, 0))
290 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
291 "Error! Tessellation shaders require OpenGL 4.0+");
294 else if (aHeaderVer.IsEmpty())
296 aHeaderVer = "#version 400";
299 else if ((aShaderMask & Graphic3d_TOS_GEOMETRY) != 0)
301 if (!theCtx->IsGlGreaterEqual (3, 2))
303 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
304 "Error! Geometry shaders require OpenGL 3.2+");
307 else if (aHeaderVer.IsEmpty())
309 aHeaderVer = "#version 150";
314 for (Graphic3d_ShaderObjectList::Iterator anIter (theShaders); anIter.More(); anIter.Next())
316 if (!anIter.Value()->IsDone())
318 const TCollection_ExtendedString aMsg = "Error! Failed to get shader source";
319 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH, aMsg);
320 return Standard_False;
323 const GLenum aShaderType = shaderTypeToGl (anIter.Value()->Type());
324 if (aShaderType == 0)
326 return Standard_False;
329 Handle(OpenGl_ShaderObject) aShader = new OpenGl_ShaderObject (aShaderType);
330 if (!aShader->Create (theCtx))
332 aShader->Release (theCtx.operator->());
333 return Standard_False;
336 TCollection_AsciiString anExtensions = "// Enable extensions used in OCCT GLSL programs\n";
337 if (myNbFragOutputs > 1)
339 if (theCtx->hasDrawBuffers)
341 anExtensions += "#define OCC_ENABLE_draw_buffers\n";
344 case Graphic3d_RTM_BLEND_UNORDERED:
346 case Graphic3d_RTM_BLEND_OIT:
347 anExtensions += "#define OCC_WRITE_WEIGHT_OIT_COVERAGE\n";
349 case Graphic3d_RTM_DEPTH_PEELING_OIT:
350 anExtensions += "#define OCC_DEPTH_PEEL_OIT\n";
356 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
357 "Error! Multiple draw buffers required by the program, but aren't supported by OpenGL");
358 return Standard_False;
361 if (theCtx->hasDrawBuffers == OpenGl_FeatureInExtensions)
363 if (theCtx->arbDrawBuffers)
365 anExtensions += "#extension GL_ARB_draw_buffers : enable\n";
367 else if (theCtx->extDrawBuffers)
369 anExtensions += "#extension GL_EXT_draw_buffers : enable\n";
375 anExtensions += "#define OCC_ALPHA_TEST\n";
378 if (theCtx->hasSampleVariables == OpenGl_FeatureInExtensions)
380 if (theCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES
381 && theCtx->oesSampleVariables)
383 anExtensions += "#extension GL_OES_sample_variables : enable\n";
385 else if (theCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGL
386 && theCtx->arbSampleShading)
388 anExtensions += "#extension GL_ARB_sample_shading : enable\n";
392 if (theCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES
393 && theCtx->hasGeometryStage == OpenGl_FeatureInExtensions)
395 anExtensions += "#extension GL_EXT_geometry_shader : enable\n"
396 "#extension GL_EXT_shader_io_blocks : enable\n";
399 TCollection_AsciiString aPrecisionHeader;
400 if (anIter.Value()->Type() == Graphic3d_TOS_FRAGMENT
401 && theCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES)
403 aPrecisionHeader = theCtx->hasHighp
404 ? "precision highp float;\n"
405 "precision highp int;\n"
406 : "precision mediump float;\n"
407 "precision mediump int;\n";
410 TCollection_AsciiString aHeaderType;
411 switch (anIter.Value()->Type())
413 case Graphic3d_TOS_COMPUTE: { aHeaderType = "#define COMPUTE_SHADER\n"; break; }
414 case Graphic3d_TOS_VERTEX: { aHeaderType = "#define VERTEX_SHADER\n"; break; }
415 case Graphic3d_TOS_TESS_CONTROL: { aHeaderType = "#define TESS_CONTROL_SHADER\n"; break; }
416 case Graphic3d_TOS_TESS_EVALUATION: { aHeaderType = "#define TESS_EVALUATION_SHADER\n"; break; }
417 case Graphic3d_TOS_GEOMETRY: { aHeaderType = "#define GEOMETRY_SHADER\n"; break; }
418 case Graphic3d_TOS_FRAGMENT: { aHeaderType = "#define FRAGMENT_SHADER\n"; break; }
421 TCollection_AsciiString aHeaderConstants;
422 myNbLightsMax = !myProxy.IsNull() ? myProxy->NbLightsMax() : 0;
423 myNbShadowMaps = !myProxy.IsNull() ? myProxy->NbShadowMaps() : 0;
424 myNbClipPlanesMax = !myProxy.IsNull() ? myProxy->NbClipPlanesMax() : 0;
425 aHeaderConstants += TCollection_AsciiString("#define THE_MAX_LIGHTS ") + myNbLightsMax + "\n";
426 aHeaderConstants += TCollection_AsciiString("#define THE_MAX_CLIP_PLANES ") + myNbClipPlanesMax + "\n";
427 aHeaderConstants += TCollection_AsciiString("#define THE_NB_FRAG_OUTPUTS ") + myNbFragOutputs + "\n";
428 if (myNbShadowMaps > 0)
430 aHeaderConstants += TCollection_AsciiString("#define THE_NB_SHADOWMAPS ") + myNbShadowMaps + "\n";
432 if (theCtx->caps->useZeroToOneDepth
433 && theCtx->arbClipControl)
435 aHeaderConstants += "#define THE_ZERO_TO_ONE_DEPTH\n";
437 if (!myProxy.IsNull()
438 && myProxy->HasDefaultSampler())
440 aHeaderConstants += "#define THE_HAS_DEFAULT_SAMPLER\n";
442 if (!myProxy.IsNull())
444 if (myProxy->IsPBR())
446 aHeaderConstants += "#define THE_IS_PBR\n";
448 if ((myProxy->TextureSetBits() & Graphic3d_TextureSetBits_BaseColor) != 0)
450 aHeaderConstants += "#define THE_HAS_TEXTURE_COLOR\n";
452 if ((myProxy->TextureSetBits() & Graphic3d_TextureSetBits_Emissive) != 0)
454 aHeaderConstants += "#define THE_HAS_TEXTURE_EMISSIVE\n";
456 if ((myProxy->TextureSetBits() & Graphic3d_TextureSetBits_Normal) != 0)
458 aHeaderConstants += "#define THE_HAS_TEXTURE_NORMAL\n";
460 if ((myProxy->TextureSetBits() & Graphic3d_TextureSetBits_Occlusion) != 0)
462 aHeaderConstants += "#define THE_HAS_TEXTURE_OCCLUSION\n";
464 if ((myProxy->TextureSetBits() & Graphic3d_TextureSetBits_MetallicRoughness) != 0)
466 aHeaderConstants += "#define THE_HAS_TEXTURE_METALROUGHNESS\n";
470 const TCollection_AsciiString aSource = aHeaderVer // #version - header defining GLSL version, should be first
471 + (!aHeaderVer.IsEmpty() ? "\n" : "")
472 + anExtensions // #extension - list of enabled extensions, should be second
473 + aPrecisionHeader // precision - default precision qualifiers, should be before any code
474 + aHeaderType // auxiliary macros defining a shader stage (type)
476 + Shaders_Declarations_glsl // common declarations (global constants and Vertex Shader inputs)
477 + Shaders_DeclarationsImpl_glsl
478 + anIter.Value()->Source(); // the source code itself (defining main() function)
479 if (!aShader->LoadAndCompile (theCtx, myResourceId, aSource))
481 aShader->Release (theCtx.operator->());
482 return Standard_False;
485 if (theCtx->caps->glslDumpLevel)
487 TCollection_AsciiString anOutputSource = aSource;
488 if (theCtx->caps->glslDumpLevel == OpenGl_ShaderProgramDumpLevel_Short)
490 anOutputSource = aHeaderVer
491 + (!aHeaderVer.IsEmpty() ? "\n" : "")
496 + anIter.Value()->Source();
498 aShader->DumpSourceCode (theCtx, myResourceId, anOutputSource);
501 if (!AttachShader (theCtx, aShader))
503 aShader->Release (theCtx.operator->());
504 return Standard_False;
508 // bind locations for pre-defined Vertex Attributes
509 SetAttributeName (theCtx, Graphic3d_TOA_POS, "occVertex");
510 SetAttributeName (theCtx, Graphic3d_TOA_NORM, "occNormal");
511 SetAttributeName (theCtx, Graphic3d_TOA_UV, "occTexCoord");
512 SetAttributeName (theCtx, Graphic3d_TOA_COLOR, "occVertColor");
514 // bind custom Vertex Attributes
515 if (!myProxy.IsNull())
517 for (Graphic3d_ShaderAttributeList::Iterator anAttribIter (myProxy->VertexAttributes());
518 anAttribIter.More(); anAttribIter.Next())
520 SetAttributeName (theCtx, anAttribIter.Value()->Location(), anAttribIter.Value()->Name().ToCString());
526 return Standard_False;
529 // set uniform defaults
530 const Handle(OpenGl_ShaderProgram)& anOldProgram = theCtx->ActiveProgram();
531 theCtx->core20fwd->glUseProgram (myProgramID);
532 if (const OpenGl_ShaderUniformLocation aLocTexEnable = GetStateLocation (OpenGl_OCCT_TEXTURE_ENABLE))
534 SetUniform (theCtx, aLocTexEnable, 0); // Off
536 if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occActiveSampler"))
538 SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_0));
540 if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerBaseColor"))
542 myTextureSetBits |= Graphic3d_TextureSetBits_BaseColor;
543 SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_BaseColor));
545 if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerPointSprite"))
547 // Graphic3d_TextureUnit_PointSprite
548 //myTextureSetBits |= Graphic3d_TextureSetBits_PointSprite;
549 SetUniform (theCtx, aLocSampler, GLint(theCtx->SpriteTextureUnit()));
551 if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerMetallicRoughness"))
553 myTextureSetBits |= Graphic3d_TextureSetBits_MetallicRoughness;
554 SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_MetallicRoughness));
556 if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerEmissive"))
558 myTextureSetBits |= Graphic3d_TextureSetBits_Emissive;
559 SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_Emissive));
561 if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerOcclusion"))
563 myTextureSetBits |= Graphic3d_TextureSetBits_Occlusion;
564 SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_Occlusion));
566 if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSamplerNormal"))
568 myTextureSetBits |= Graphic3d_TextureSetBits_Normal;
569 SetUniform (theCtx, aLocSampler, GLint(Graphic3d_TextureUnit_Normal));
571 if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occDiffIBLMapSHCoeffs"))
573 SetUniform (theCtx, aLocSampler, GLint(theCtx->PBRDiffIBLMapSHTexUnit()));
575 if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occSpecIBLMap"))
577 SetUniform (theCtx, aLocSampler, GLint(theCtx->PBRSpecIBLMapTexUnit()));
579 if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occEnvLUT"))
581 SetUniform (theCtx, aLocSampler, GLint(theCtx->PBREnvLUTTexUnit()));
583 if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occShadowMapSamplers"))
585 std::vector<GLint> aShadowSamplers (myNbShadowMaps);
586 const GLint aSamplFrom = GLint(theCtx->ShadowMapTexUnit()) - myNbShadowMaps + 1;
587 for (Standard_Integer aSamplerIter = 0; aSamplerIter < myNbShadowMaps; ++aSamplerIter)
589 aShadowSamplers[aSamplerIter] = aSamplFrom + aSamplerIter;
591 SetUniform (theCtx, aLocSampler, myNbShadowMaps, &aShadowSamplers.front());
594 if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occDepthPeelingDepth"))
596 SetUniform (theCtx, aLocSampler, GLint(theCtx->DepthPeelingDepthTexUnit()));
598 if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, "occDepthPeelingFrontColor"))
600 SetUniform (theCtx, aLocSampler, GLint(theCtx->DepthPeelingFrontColorTexUnit()));
603 const TCollection_AsciiString aSamplerNamePrefix ("occSampler");
604 const Standard_Integer aNbUnitsMax = Max (theCtx->MaxCombinedTextureUnits(), Graphic3d_TextureUnit_NB);
605 for (GLint aUnitIter = 0; aUnitIter < aNbUnitsMax; ++aUnitIter)
607 const TCollection_AsciiString aName = aSamplerNamePrefix + aUnitIter;
608 if (const OpenGl_ShaderUniformLocation aLocSampler = GetUniformLocation (theCtx, aName.ToCString()))
610 SetUniform (theCtx, aLocSampler, aUnitIter);
614 theCtx->core20fwd->glUseProgram (!anOldProgram.IsNull() ? anOldProgram->ProgramId() : OpenGl_ShaderProgram::NO_PROGRAM);
615 return Standard_True;
618 // =======================================================================
619 // function : ~OpenGl_ShaderProgram
620 // purpose : Releases resources of shader program
621 // =======================================================================
622 OpenGl_ShaderProgram::~OpenGl_ShaderProgram()
627 // =======================================================================
628 // function : AttachShader
629 // purpose : Attaches shader object to the program object
630 // =======================================================================
631 Standard_Boolean OpenGl_ShaderProgram::AttachShader (const Handle(OpenGl_Context)& theCtx,
632 const Handle(OpenGl_ShaderObject)& theShader)
634 if (myProgramID == NO_PROGRAM || theShader.IsNull())
636 return Standard_False;
639 for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
641 if (theShader == anIter.Value())
643 return Standard_False;
647 myShaderObjects.Append (theShader);
648 theCtx->core20fwd->glAttachShader (myProgramID, theShader->myShaderID);
649 return Standard_True;
652 // =======================================================================
653 // function : DetachShader
654 // purpose : Detaches shader object to the program object
655 // =======================================================================
656 Standard_Boolean OpenGl_ShaderProgram::DetachShader (const Handle(OpenGl_Context)& theCtx,
657 const Handle(OpenGl_ShaderObject)& theShader)
659 if (myProgramID == NO_PROGRAM
660 || theShader.IsNull())
662 return Standard_False;
665 OpenGl_ShaderList::Iterator anIter (myShaderObjects);
666 while (anIter.More())
668 if (theShader == anIter.Value())
670 myShaderObjects.Remove (anIter);
679 return Standard_False;
682 theCtx->core20fwd->glDetachShader (myProgramID, theShader->myShaderID);
683 return Standard_True;
686 // =======================================================================
688 // purpose : Links the program object
689 // =======================================================================
690 Standard_Boolean OpenGl_ShaderProgram::link (const Handle(OpenGl_Context)& theCtx)
692 if (myProgramID == NO_PROGRAM)
694 return Standard_False;
697 GLint aStatus = GL_FALSE;
698 theCtx->core20fwd->glLinkProgram (myProgramID);
699 theCtx->core20fwd->glGetProgramiv (myProgramID, GL_LINK_STATUS, &aStatus);
700 if (aStatus == GL_FALSE)
702 return Standard_False;
705 memset (myCurrentState, 0, sizeof (myCurrentState));
706 for (GLint aVar = 0; aVar < OpenGl_OCCT_NUMBER_OF_STATE_VARIABLES; ++aVar)
708 myStateLocations[aVar] = GetUniformLocation (theCtx, PredefinedKeywords[aVar]);
710 return Standard_True;
713 // =======================================================================
716 // =======================================================================
717 Standard_Boolean OpenGl_ShaderProgram::Link (const Handle(OpenGl_Context)& theCtx,
722 return link (theCtx);
727 TCollection_AsciiString aLog;
728 FetchInfoLog (theCtx, aLog);
731 aLog = "Linker log is empty.";
733 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_ERROR, 0, GL_DEBUG_SEVERITY_HIGH,
734 TCollection_AsciiString ("Failed to link program object [") + myResourceId + "]! Linker log:\n" + aLog);
737 else if (theCtx->caps->glslWarnings)
739 TCollection_AsciiString aLog;
740 FetchInfoLog (theCtx, aLog);
742 && !aLog.IsEqual ("No errors.\n"))
744 theCtx->PushMessage (GL_DEBUG_SOURCE_APPLICATION, GL_DEBUG_TYPE_PORTABILITY, 0, GL_DEBUG_SEVERITY_LOW,
745 TCollection_AsciiString ("GLSL linker log [") + myResourceId +"]:\n" + aLog);
751 // =======================================================================
752 // function : FetchInfoLog
753 // purpose : Fetches information log of the last link operation
754 // =======================================================================
755 Standard_Boolean OpenGl_ShaderProgram::FetchInfoLog (const Handle(OpenGl_Context)& theCtx,
756 TCollection_AsciiString& theOutput)
758 if (myProgramID == NO_PROGRAM)
760 return Standard_False;
764 theCtx->core20fwd->glGetProgramiv (myProgramID, GL_INFO_LOG_LENGTH, &aLength);
767 GLchar* aLog = (GLchar*) alloca (aLength);
768 memset (aLog, 0, aLength);
769 theCtx->core20fwd->glGetProgramInfoLog (myProgramID, aLength, NULL, aLog);
772 return Standard_True;
775 // =======================================================================
776 // function : ApplyVariables
777 // purpose : Fetches uniform variables from proxy shader program
778 // =======================================================================
779 Standard_Boolean OpenGl_ShaderProgram::ApplyVariables(const Handle(OpenGl_Context)& theCtx)
781 if (myProxy.IsNull() || myProxy->Variables().IsEmpty())
783 return Standard_False;
786 for (Graphic3d_ShaderVariableList::Iterator anIter (myProxy->Variables()); anIter.More(); anIter.Next())
788 mySetterSelector.Set (theCtx, anIter.Value(), this);
791 myProxy->ClearVariables();
792 return Standard_True;
795 // =======================================================================
796 // function : GetUniformLocation
797 // purpose : Returns location (index) of the specific uniform variable
798 // =======================================================================
799 OpenGl_ShaderUniformLocation OpenGl_ShaderProgram::GetUniformLocation (const Handle(OpenGl_Context)& theCtx,
800 const GLchar* theName) const
802 return OpenGl_ShaderUniformLocation (myProgramID != NO_PROGRAM
803 ? theCtx->core20fwd->glGetUniformLocation (myProgramID, theName)
807 // =======================================================================
808 // function : GetAttributeLocation
809 // purpose : Returns location (index) of the generic vertex attribute
810 // =======================================================================
811 GLint OpenGl_ShaderProgram::GetAttributeLocation (const Handle(OpenGl_Context)& theCtx,
812 const GLchar* theName) const
814 return myProgramID != NO_PROGRAM
815 ? theCtx->core20fwd->glGetAttribLocation (myProgramID, theName)
819 // =======================================================================
820 // function : GetUniform
821 // purpose : Returns the value of the integer uniform variable
822 // =======================================================================
823 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
825 OpenGl_Vec4i& theValue) const
827 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
829 return Standard_False;
832 theCtx->core20fwd->glGetUniformiv (myProgramID, theLocation, theValue);
833 return Standard_True;
836 // =======================================================================
837 // function : GetUniform
838 // purpose : Returns the value of the floating-point uniform variable
839 // =======================================================================
840 Standard_Boolean OpenGl_ShaderProgram::GetUniform (const Handle(OpenGl_Context)& theCtx,
842 OpenGl_Vec4& theValue) const
844 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
846 return Standard_False;
849 theCtx->core20fwd->glGetUniformfv (myProgramID, theLocation, theValue);
850 return Standard_True;
853 // =======================================================================
854 // function : GetAttribute
855 // purpose : Returns the integer vertex attribute
856 // =======================================================================
857 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
859 OpenGl_Vec4i& theValue) const
861 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
863 return Standard_False;
866 theCtx->core20fwd->glGetVertexAttribiv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
867 return Standard_True;
870 // =======================================================================
871 // function : GetAttribute
872 // purpose : Returns the floating-point vertex attribute
873 // =======================================================================
874 Standard_Boolean OpenGl_ShaderProgram::GetAttribute (const Handle(OpenGl_Context)& theCtx,
876 OpenGl_Vec4& theValue) const
878 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
880 return Standard_False;
883 theCtx->core20fwd->glGetVertexAttribfv (theIndex, GL_CURRENT_VERTEX_ATTRIB, theValue);
884 return Standard_True;
887 // =======================================================================
888 // function : SetAttributeName
890 // =======================================================================
891 Standard_Boolean OpenGl_ShaderProgram::SetAttributeName (const Handle(OpenGl_Context)& theCtx,
893 const GLchar* theName)
895 theCtx->core20fwd->glBindAttribLocation (myProgramID, theIndex, theName);
896 return Standard_True;
899 // =======================================================================
900 // function : SetAttribute
902 // =======================================================================
903 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
907 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
909 return Standard_False;
912 theCtx->core20fwd->glVertexAttrib1f (theIndex, theValue);
913 return Standard_True;
916 // =======================================================================
917 // function : SetAttribute
919 // =======================================================================
920 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
922 const OpenGl_Vec2& theValue)
924 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
926 return Standard_False;
929 theCtx->core20fwd->glVertexAttrib2fv (theIndex, theValue);
930 return Standard_True;
933 // =======================================================================
934 // function : SetAttribute
936 // =======================================================================
937 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
939 const OpenGl_Vec3& theValue)
941 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
943 return Standard_False;
946 theCtx->core20fwd->glVertexAttrib3fv (theIndex, theValue);
947 return Standard_True;
950 // =======================================================================
951 // function : SetAttribute
953 // =======================================================================
954 Standard_Boolean OpenGl_ShaderProgram::SetAttribute (const Handle(OpenGl_Context)& theCtx,
956 const OpenGl_Vec4& theValue)
958 if (myProgramID == NO_PROGRAM || theIndex == INVALID_LOCATION)
960 return Standard_False;
963 theCtx->core20fwd->glVertexAttrib4fv (theIndex, theValue);
964 return Standard_True;
967 // =======================================================================
968 // function : SetUniform
969 // purpose : Specifies the value of the integer uniform variable
970 // =======================================================================
971 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
975 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
977 return Standard_False;
980 theCtx->core20fwd->glUniform1i (theLocation, theValue);
981 return Standard_True;
984 // =======================================================================
985 // function : SetUniform
987 // =======================================================================
988 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
990 const OpenGl_Vec2u& theValue)
992 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
997 if (theCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES)
999 if (theCtx->core30 != NULL)
1001 theCtx->core30->glUniform2uiv (theLocation, 1, theValue.GetData());
1007 if (theCtx->core32 != NULL)
1009 theCtx->core32->glUniform2uiv (theLocation, 1, theValue.GetData());
1017 // =======================================================================
1018 // function : SetUniform
1020 // =======================================================================
1021 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1022 const GLchar* theName,
1023 const GLsizei theCount,
1024 const OpenGl_Vec2u* theValue)
1026 return SetUniform (theCtx, GetUniformLocation (theCtx, theName), theCount, theValue);
1029 // =======================================================================
1030 // function : SetUniform
1032 // =======================================================================
1033 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1035 const GLsizei theCount,
1036 const OpenGl_Vec2u* theValue)
1038 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1043 if (theCtx->GraphicsLibrary() == Aspect_GraphicsLibrary_OpenGLES)
1045 if (theCtx->core30 != NULL)
1047 theCtx->core30->glUniform2uiv (theLocation, theCount, theValue->GetData());
1053 if (theCtx->core32 != NULL)
1055 theCtx->core32->glUniform2uiv (theLocation, theCount, theValue->GetData());
1062 // =======================================================================
1063 // function : SetUniform
1064 // purpose : Specifies the value of the floating-point uniform variable
1065 // =======================================================================
1066 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1070 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1072 return Standard_False;
1075 theCtx->core20fwd->glUniform1f (theLocation, theValue);
1076 return Standard_True;
1079 // =======================================================================
1080 // function : SetUniform
1081 // purpose : Specifies the value of the integer uniform 2D vector
1082 // =======================================================================
1083 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1085 const OpenGl_Vec2i& theValue)
1087 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1089 return Standard_False;
1092 theCtx->core20fwd->glUniform2iv (theLocation, 1, theValue);
1093 return Standard_True;
1096 // =======================================================================
1097 // function : SetUniform
1098 // purpose : Specifies the value of the integer uniform 3D vector
1099 // =======================================================================
1100 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1102 const OpenGl_Vec3i& theValue)
1104 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1106 return Standard_False;
1109 theCtx->core20fwd->glUniform3iv (theLocation, 1, theValue);
1110 return Standard_True;
1113 // =======================================================================
1114 // function : SetUniform
1115 // purpose : Specifies the value of the integer uniform 4D vector
1116 // =======================================================================
1117 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1119 const OpenGl_Vec4i& theValue)
1121 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1123 return Standard_False;
1126 theCtx->core20fwd->glUniform4iv (theLocation, 1, theValue);
1127 return Standard_True;
1130 // =======================================================================
1131 // function : SetUniform
1132 // purpose : Specifies the value of the floating-point uniform 2D vector
1133 // =======================================================================
1134 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1136 const OpenGl_Vec2& theValue)
1138 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1140 return Standard_False;
1143 theCtx->core20fwd->glUniform2fv (theLocation, 1, theValue);
1144 return Standard_True;
1147 // =======================================================================
1148 // function : SetUniform
1149 // purpose : Specifies the value of the floating-point uniform 3D vector
1150 // =======================================================================
1151 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1153 const OpenGl_Vec3& theValue)
1155 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1157 return Standard_False;
1160 theCtx->core20fwd->glUniform3fv (theLocation, 1, theValue);
1161 return Standard_True;
1164 // =======================================================================
1165 // function : SetUniform
1166 // purpose : Specifies the value of the floating-point uniform 4D vector
1167 // =======================================================================
1168 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1170 const OpenGl_Vec4& theValue)
1172 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1174 return Standard_False;
1177 theCtx->core20fwd->glUniform4fv (theLocation, 1, theValue);
1178 return Standard_True;
1181 // =======================================================================
1182 // function : SetUniform
1184 // =======================================================================
1185 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1188 const NCollection_Mat3<float>* theData)
1190 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1192 return Standard_False;
1195 theCtx->core20fwd->glUniformMatrix3fv (theLocation, theCount, GL_FALSE, theData->GetData());
1196 return Standard_True;
1199 // =======================================================================
1200 // function : SetUniform
1201 // purpose : Specifies the value of the floating-point uniform 4x4 matrix
1202 // =======================================================================
1203 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1205 const OpenGl_Mat4& theValue,
1206 GLboolean theTranspose)
1208 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1210 return Standard_False;
1213 theCtx->core20fwd->glUniformMatrix4fv (theLocation, 1, GL_FALSE, theTranspose ? theValue.Transposed().GetData() : theValue.GetData());
1214 return Standard_True;
1217 // =======================================================================
1218 // function : SetUniform
1220 // =======================================================================
1221 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1224 const OpenGl_Mat4* theData)
1226 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1228 return Standard_False;
1231 theCtx->core20fwd->glUniformMatrix4fv (theLocation, theCount, GL_FALSE, theData->GetData());
1232 return Standard_True;
1235 // =======================================================================
1236 // function : SetUniform
1237 // purpose : Specifies the value of the float uniform array
1238 // =======================================================================
1239 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1242 const Standard_ShortReal* theData)
1244 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1246 return Standard_False;
1249 theCtx->core20fwd->glUniform1fv (theLocation, theCount, theData);
1250 return Standard_True;
1253 // =======================================================================
1254 // function : SetUniform
1255 // purpose : Specifies the value of the float2 uniform array
1256 // =======================================================================
1257 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1260 const OpenGl_Vec2* theData)
1262 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1264 return Standard_False;
1267 theCtx->core20fwd->glUniform2fv (theLocation, theCount, theData[0].GetData());
1268 return Standard_True;
1271 // =======================================================================
1272 // function : SetUniform
1273 // purpose : Specifies the value of the float3 uniform array
1274 // =======================================================================
1275 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1278 const OpenGl_Vec3* theData)
1280 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1282 return Standard_False;
1285 theCtx->core20fwd->glUniform3fv (theLocation, theCount, theData[0].GetData());
1286 return Standard_True;
1289 // =======================================================================
1290 // function : SetUniform
1291 // purpose : Specifies the value of the float4 uniform array
1292 // =======================================================================
1293 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1296 const OpenGl_Vec4* theData)
1298 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1300 return Standard_False;
1303 theCtx->core20fwd->glUniform4fv (theLocation, theCount, theData[0].GetData());
1304 return Standard_True;
1307 // =======================================================================
1308 // function : SetUniform
1309 // purpose : Specifies the value of the integer uniform array
1310 // =======================================================================
1311 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1314 const Standard_Integer* theData)
1316 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1318 return Standard_False;
1321 theCtx->core20fwd->glUniform1iv (theLocation, theCount, theData);
1322 return Standard_True;
1325 // =======================================================================
1326 // function : SetUniform
1327 // purpose : Specifies the value of the int2 uniform array
1328 // =======================================================================
1329 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1332 const OpenGl_Vec2i* theData)
1334 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1336 return Standard_False;
1339 theCtx->core20fwd->glUniform2iv (theLocation, theCount, theData[0].GetData());
1340 return Standard_True;
1343 // =======================================================================
1344 // function : SetUniform
1345 // purpose : Specifies the value of the int3 uniform array
1346 // =======================================================================
1347 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1350 const OpenGl_Vec3i* theData)
1352 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1354 return Standard_False;
1357 theCtx->core20fwd->glUniform3iv (theLocation, theCount, theData[0].GetData());
1358 return Standard_True;
1361 // =======================================================================
1362 // function : SetUniform
1363 // purpose : Specifies the value of the int4 uniform array
1364 // =======================================================================
1365 Standard_Boolean OpenGl_ShaderProgram::SetUniform (const Handle(OpenGl_Context)& theCtx,
1368 const OpenGl_Vec4i* theData)
1370 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1372 return Standard_False;
1375 theCtx->core20fwd->glUniform4iv (theLocation, theCount, theData[0].GetData());
1376 return Standard_True;
1379 // =======================================================================
1380 // function : SetSampler
1381 // purpose : Specifies the value of the sampler uniform variable
1382 // =======================================================================
1383 Standard_Boolean OpenGl_ShaderProgram::SetSampler (const Handle(OpenGl_Context)& theCtx,
1385 const Graphic3d_TextureUnit theTextureUnit)
1387 if (myProgramID == NO_PROGRAM || theLocation == INVALID_LOCATION)
1389 return Standard_False;
1392 theCtx->core20fwd->glUniform1i (theLocation, theTextureUnit);
1393 return Standard_True;
1396 // =======================================================================
1397 // function : Create
1398 // purpose : Creates new empty shader program of specified type
1399 // =======================================================================
1400 Standard_Boolean OpenGl_ShaderProgram::Create (const Handle(OpenGl_Context)& theCtx)
1402 if (myProgramID == NO_PROGRAM
1403 && theCtx->core20fwd != NULL)
1405 myProgramID = theCtx->core20fwd->glCreateProgram();
1408 return myProgramID != NO_PROGRAM;
1411 // =======================================================================
1412 // function : Release
1413 // purpose : Destroys shader program
1414 // =======================================================================
1415 void OpenGl_ShaderProgram::Release (OpenGl_Context* theCtx)
1417 if (myProgramID == NO_PROGRAM)
1422 Standard_ASSERT_RETURN (theCtx != NULL,
1423 "OpenGl_ShaderProgram destroyed without GL context! Possible GPU memory leakage...",);
1425 for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
1427 if (!anIter.Value().IsNull())
1429 anIter.ChangeValue()->Release (theCtx);
1430 anIter.ChangeValue().Nullify();
1434 if (theCtx->core20fwd != NULL
1435 && theCtx->IsValid())
1437 theCtx->core20fwd->glDeleteProgram (myProgramID);
1440 myProgramID = NO_PROGRAM;
1443 // =======================================================================
1444 // function : UpdateDebugDump
1446 // =======================================================================
1447 Standard_Boolean OpenGl_ShaderProgram::UpdateDebugDump (const Handle(OpenGl_Context)& theCtx,
1448 const TCollection_AsciiString& theFolder,
1449 Standard_Boolean theToBeautify,
1450 Standard_Boolean theToReset)
1452 if (myProgramID == NO_PROGRAM)
1454 return Standard_False;
1457 TCollection_AsciiString aFolder = theFolder;
1458 if (aFolder.IsEmpty())
1460 OSD_Environment aShaderVar ("CSF_ShadersDirectoryDump");
1461 aFolder = aShaderVar.Value();
1462 if (aFolder.IsEmpty())
1468 bool hasUpdates = false;
1469 for (OpenGl_ShaderList::Iterator anIter (myShaderObjects); anIter.More(); anIter.Next())
1471 if (!anIter.Value().IsNull())
1473 // desktop OpenGL (but not OpenGL ES) allows multiple shaders of the same stage to be attached,
1474 // but here we expect only single source per stage
1475 hasUpdates = anIter.ChangeValue()->updateDebugDump (theCtx, myResourceId, aFolder, theToBeautify, theToReset) || hasUpdates;
1480 return Link (theCtx);
1482 return Standard_False;